Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 7589346f

History | View | Annotate | Download (76.1 kB)

1
#
2
#
3

    
4
# Copyright (C) 2008, 2009, 2010, 2011, 2012 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

    
22
"""KVM hypervisor
23

24
"""
25

    
26
import errno
27
import os
28
import os.path
29
import re
30
import tempfile
31
import time
32
import logging
33
import pwd
34
import struct
35
import fcntl
36
import shutil
37
import socket
38
import stat
39
import StringIO
40
try:
41
  import affinity   # pylint: disable=F0401
42
except ImportError:
43
  affinity = None
44

    
45
from ganeti import utils
46
from ganeti import constants
47
from ganeti import errors
48
from ganeti import serializer
49
from ganeti import objects
50
from ganeti import uidpool
51
from ganeti import ssconf
52
from ganeti import netutils
53
from ganeti import pathutils
54
from ganeti.hypervisor import hv_base
55
from ganeti.utils import wrapper as utils_wrapper
56

    
57

    
58
_KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-vif-bridge"
59
_KVM_START_PAUSED_FLAG = "-S"
60

    
61
# TUN/TAP driver constants, taken from <linux/if_tun.h>
62
# They are architecture-independent and already hardcoded in qemu-kvm source,
63
# so we can safely include them here.
64
TUNSETIFF = 0x400454ca
65
TUNGETIFF = 0x800454d2
66
TUNGETFEATURES = 0x800454cf
67
IFF_TAP = 0x0002
68
IFF_NO_PI = 0x1000
69
IFF_VNET_HDR = 0x4000
70

    
71
#: SPICE parameters which depend on L{constants.HV_KVM_SPICE_BIND}
72
_SPICE_ADDITIONAL_PARAMS = frozenset([
73
  constants.HV_KVM_SPICE_IP_VERSION,
74
  constants.HV_KVM_SPICE_PASSWORD_FILE,
75
  constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
76
  constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
77
  constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
78
  constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
79
  constants.HV_KVM_SPICE_USE_TLS,
80
  ])
81

    
82

    
83
def _ProbeTapVnetHdr(fd):
84
  """Check whether to enable the IFF_VNET_HDR flag.
85

86
  To do this, _all_ of the following conditions must be met:
87
   1. TUNGETFEATURES ioctl() *must* be implemented
88
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
89
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
90
      drivers/net/tun.c there is no way to test this until after the tap device
91
      has been created using TUNSETIFF, and there is no way to change the
92
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
93
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
94
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
95

96
   @type fd: int
97
   @param fd: the file descriptor of /dev/net/tun
98

99
  """
100
  req = struct.pack("I", 0)
101
  try:
102
    res = fcntl.ioctl(fd, TUNGETFEATURES, req)
103
  except EnvironmentError:
104
    logging.warning("TUNGETFEATURES ioctl() not implemented")
105
    return False
106

    
107
  tunflags = struct.unpack("I", res)[0]
108
  if tunflags & IFF_VNET_HDR:
109
    return True
110
  else:
111
    logging.warning("Host does not support IFF_VNET_HDR, not enabling")
112
    return False
113

    
114

    
115
def _OpenTap(vnet_hdr=True):
116
  """Open a new tap device and return its file descriptor.
117

118
  This is intended to be used by a qemu-type hypervisor together with the -net
119
  tap,fd=<fd> command line parameter.
120

121
  @type vnet_hdr: boolean
122
  @param vnet_hdr: Enable the VNET Header
123
  @return: (ifname, tapfd)
124
  @rtype: tuple
125

126
  """
127
  try:
128
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
129
  except EnvironmentError:
130
    raise errors.HypervisorError("Failed to open /dev/net/tun")
131

    
132
  flags = IFF_TAP | IFF_NO_PI
133

    
134
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
135
    flags |= IFF_VNET_HDR
136

    
137
  # The struct ifreq ioctl request (see netdevice(7))
138
  ifr = struct.pack("16sh", "", flags)
139

    
140
  try:
141
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
142
  except EnvironmentError:
143
    raise errors.HypervisorError("Failed to allocate a new TAP device")
144

    
145
  # Get the interface name from the ioctl
146
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
147
  return (ifname, tapfd)
148

    
149

    
150
def _BuildNetworkEnv(name, network, gateway, network6, gateway6,
151
                     network_type, mac_prefix, tags, env):
152
  """Build environment variables concerning a Network.
153

154
  """
155
  if name:
156
    env["NETWORK_NAME"] = name
157
  if network:
158
    env["NETWORK_SUBNET"] = network
159
  if gateway:
160
    env["NETWORK_GATEWAY"] = gateway
161
  if network6:
162
    env["NETWORK_SUBNET6"] = network6
163
  if gateway6:
164
    env["NETWORK_GATEWAY6"] = gateway6
165
  if mac_prefix:
166
    env["NETWORK_MAC_PREFIX"] = mac_prefix
167
  if network_type:
168
    env["NETWORK_TYPE"] = network_type
169
  if tags:
170
    env["NETWORK_TAGS"] = " ".join(tags)
171

    
172
  return env
173

    
174

    
175
class QmpMessage:
176
  """QEMU Messaging Protocol (QMP) message.
177

178
  """
179
  def __init__(self, data):
180
    """Creates a new QMP message based on the passed data.
181

182
    """
183
    if not isinstance(data, dict):
184
      raise TypeError("QmpMessage must be initialized with a dict")
185

    
186
    self.data = data
187

    
188
  def __getitem__(self, field_name):
189
    """Get the value of the required field if present, or None.
190

191
    Overrides the [] operator to provide access to the message data,
192
    returning None if the required item is not in the message
193
    @return: the value of the field_name field, or None if field_name
194
             is not contained in the message
195

196
    """
197
    return self.data.get(field_name, None)
198

    
199
  def __setitem__(self, field_name, field_value):
200
    """Set the value of the required field_name to field_value.
201

202
    """
203
    self.data[field_name] = field_value
204

    
205
  @staticmethod
206
  def BuildFromJsonString(json_string):
207
    """Build a QmpMessage from a JSON encoded string.
208

209
    @type json_string: str
210
    @param json_string: JSON string representing the message
211
    @rtype: L{QmpMessage}
212
    @return: a L{QmpMessage} built from json_string
213

214
    """
215
    # Parse the string
216
    data = serializer.LoadJson(json_string)
217
    return QmpMessage(data)
218

    
219
  def __str__(self):
220
    # The protocol expects the JSON object to be sent as a single line.
221
    return serializer.DumpJson(self.data)
222

    
223
  def __eq__(self, other):
224
    # When comparing two QmpMessages, we are interested in comparing
225
    # their internal representation of the message data
226
    return self.data == other.data
227

    
228

    
229
class QmpConnection:
230
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
231

232
  """
233
  _FIRST_MESSAGE_KEY = "QMP"
234
  _EVENT_KEY = "event"
235
  _ERROR_KEY = "error"
236
  _RETURN_KEY = RETURN_KEY = "return"
237
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
238
  _ERROR_CLASS_KEY = "class"
239
  _ERROR_DATA_KEY = "data"
240
  _ERROR_DESC_KEY = "desc"
241
  _EXECUTE_KEY = "execute"
242
  _ARGUMENTS_KEY = "arguments"
243
  _CAPABILITIES_COMMAND = "qmp_capabilities"
244
  _MESSAGE_END_TOKEN = "\r\n"
245
  _SOCKET_TIMEOUT = 5
246

    
247
  def __init__(self, monitor_filename):
248
    """Instantiates the QmpConnection object.
249

250
    @type monitor_filename: string
251
    @param monitor_filename: the filename of the UNIX raw socket on which the
252
                             QMP monitor is listening
253

254
    """
255
    self.monitor_filename = monitor_filename
256
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
257
    # We want to fail if the server doesn't send a complete message
258
    # in a reasonable amount of time
259
    self.sock.settimeout(self._SOCKET_TIMEOUT)
260
    self._connected = False
261
    self._buf = ""
262

    
263
  def _check_socket(self):
264
    sock_stat = None
265
    try:
266
      sock_stat = os.stat(self.monitor_filename)
267
    except EnvironmentError, err:
268
      if err.errno == errno.ENOENT:
269
        raise errors.HypervisorError("No qmp socket found")
270
      else:
271
        raise errors.HypervisorError("Error checking qmp socket: %s",
272
                                     utils.ErrnoOrStr(err))
273
    if not stat.S_ISSOCK(sock_stat.st_mode):
274
      raise errors.HypervisorError("Qmp socket is not a socket")
275

    
276
  def _check_connection(self):
277
    """Make sure that the connection is established.
278

279
    """
280
    if not self._connected:
281
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
282
                                   " invoke connect() on it")
283

    
284
  def connect(self):
285
    """Connects to the QMP monitor.
286

287
    Connects to the UNIX socket and makes sure that we can actually send and
288
    receive data to the kvm instance via QMP.
289

290
    @raise errors.HypervisorError: when there are communication errors
291
    @raise errors.ProgrammerError: when there are data serialization errors
292

293
    """
294
    if self._connected:
295
      raise errors.ProgrammerError("Cannot connect twice")
296

    
297
    self._check_socket()
298

    
299
    # Check file existance/stuff
300
    try:
301
      self.sock.connect(self.monitor_filename)
302
    except EnvironmentError:
303
      raise errors.HypervisorError("Can't connect to qmp socket")
304
    self._connected = True
305

    
306
    # Check if we receive a correct greeting message from the server
307
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
308
    greeting = self._Recv()
309
    if not greeting[self._FIRST_MESSAGE_KEY]:
310
      self._connected = False
311
      raise errors.HypervisorError("kvm: qmp communication error (wrong"
312
                                   " server greeting")
313

    
314
    # Let's put the monitor in command mode using the qmp_capabilities
315
    # command, or else no command will be executable.
316
    # (As per the QEMU Protocol Specification 0.1 - section 4)
317
    self.Execute(self._CAPABILITIES_COMMAND)
318

    
319
  def _ParseMessage(self, buf):
320
    """Extract and parse a QMP message from the given buffer.
321

322
    Seeks for a QMP message in the given buf. If found, it parses it and
323
    returns it together with the rest of the characters in the buf.
324
    If no message is found, returns None and the whole buffer.
325

326
    @raise errors.ProgrammerError: when there are data serialization errors
327

328
    """
329
    message = None
330
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
331
    # Specification 0.1 - Section 2.1.1)
332
    pos = buf.find(self._MESSAGE_END_TOKEN)
333
    if pos >= 0:
334
      try:
335
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
336
      except Exception, err:
337
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
338
      buf = buf[pos + 1:]
339

    
340
    return (message, buf)
341

    
342
  def _Recv(self):
343
    """Receives a message from QMP and decodes the received JSON object.
344

345
    @rtype: QmpMessage
346
    @return: the received message
347
    @raise errors.HypervisorError: when there are communication errors
348
    @raise errors.ProgrammerError: when there are data serialization errors
349

350
    """
351
    self._check_connection()
352

    
353
    # Check if there is already a message in the buffer
354
    (message, self._buf) = self._ParseMessage(self._buf)
355
    if message:
356
      return message
357

    
358
    recv_buffer = StringIO.StringIO(self._buf)
359
    recv_buffer.seek(len(self._buf))
360
    try:
361
      while True:
362
        data = self.sock.recv(4096)
363
        if not data:
364
          break
365
        recv_buffer.write(data)
366

    
367
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
368
        if message:
369
          return message
370

    
371
    except socket.timeout, err:
372
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
373
                                   "%s" % (err))
374
    except socket.error, err:
375
      raise errors.HypervisorError("Unable to receive data from KVM using the"
376
                                   " QMP protocol: %s" % err)
377

    
378
  def _Send(self, message):
379
    """Encodes and sends a message to KVM using QMP.
380

381
    @type message: QmpMessage
382
    @param message: message to send to KVM
383
    @raise errors.HypervisorError: when there are communication errors
384
    @raise errors.ProgrammerError: when there are data serialization errors
385

386
    """
387
    self._check_connection()
388
    try:
389
      message_str = str(message)
390
    except Exception, err:
391
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
392

    
393
    try:
394
      self.sock.sendall(message_str)
395
    except socket.timeout, err:
396
      raise errors.HypervisorError("Timeout while sending a QMP message: "
397
                                   "%s (%s)" % (err.string, err.errno))
398
    except socket.error, err:
399
      raise errors.HypervisorError("Unable to send data from KVM using the"
400
                                   " QMP protocol: %s" % err)
401

    
402
  def Execute(self, command, arguments=None):
403
    """Executes a QMP command and returns the response of the server.
404

405
    @type command: str
406
    @param command: the command to execute
407
    @type arguments: dict
408
    @param arguments: dictionary of arguments to be passed to the command
409
    @rtype: dict
410
    @return: dictionary representing the received JSON object
411
    @raise errors.HypervisorError: when there are communication errors
412
    @raise errors.ProgrammerError: when there are data serialization errors
413

414
    """
415
    self._check_connection()
416
    message = QmpMessage({self._EXECUTE_KEY: command})
417
    if arguments:
418
      message[self._ARGUMENTS_KEY] = arguments
419
    self._Send(message)
420

    
421
    # Events can occur between the sending of the command and the reception
422
    # of the response, so we need to filter out messages with the event key.
423
    while True:
424
      response = self._Recv()
425
      err = response[self._ERROR_KEY]
426
      if err:
427
        raise errors.HypervisorError("kvm: error executing the %s"
428
                                     " command: %s (%s, %s):" %
429
                                     (command,
430
                                      err[self._ERROR_DESC_KEY],
431
                                      err[self._ERROR_CLASS_KEY],
432
                                      err[self._ERROR_DATA_KEY]))
433

    
434
      elif not response[self._EVENT_KEY]:
435
        return response
436

    
437

    
438
class KVMHypervisor(hv_base.BaseHypervisor):
439
  """KVM hypervisor interface
440

441
  """
442
  CAN_MIGRATE = True
443

    
444
  _ROOT_DIR = pathutils.RUN_DIR + "/kvm-hypervisor"
445
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
446
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
447
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
448
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
449
  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
450
  _KEYMAP_DIR = _ROOT_DIR + "/keymap" # contains instances keymaps
451
  # KVM instances with chroot enabled are started in empty chroot directories.
452
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
453
  # After an instance is stopped, its chroot directory is removed.
454
  # If the chroot directory is not empty, it can't be removed.
455
  # A non-empty chroot directory indicates a possible security incident.
456
  # To support forensics, the non-empty chroot directory is quarantined in
457
  # a separate directory, called 'chroot-quarantine'.
458
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
459
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
460
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR, _KEYMAP_DIR]
461

    
462
  PARAMETERS = {
463
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
464
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
465
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
466
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
467
    constants.HV_ACPI: hv_base.NO_CHECK,
468
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
469
    constants.HV_SERIAL_SPEED: hv_base.NO_CHECK,
470
    constants.HV_VNC_BIND_ADDRESS:
471
      (False, lambda x: (netutils.IP4Address.IsValid(x) or
472
                         utils.IsNormAbsPath(x)),
473
       "the VNC bind address must be either a valid IP address or an absolute"
474
       " pathname", None, None),
475
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
476
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
477
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
478
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
479
    constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
480
    constants.HV_KVM_SPICE_IP_VERSION:
481
      (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
482
                         x in constants.VALID_IP_VERSIONS),
483
       "the SPICE IP version should be 4 or 6",
484
       None, None),
485
    constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
486
    constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
487
      hv_base.ParamInSet(
488
        False, constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
489
    constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
490
      hv_base.ParamInSet(
491
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
492
    constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
493
      hv_base.ParamInSet(
494
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
495
    constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
496
      hv_base.ParamInSet(
497
        False, constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
498
    constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
499
    constants.HV_KVM_SPICE_USE_TLS: hv_base.NO_CHECK,
500
    constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
501
    constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
502
    constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
503
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
504
    constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
505
    constants.HV_BOOT_ORDER:
506
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
507
    constants.HV_NIC_TYPE:
508
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
509
    constants.HV_DISK_TYPE:
510
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
511
    constants.HV_KVM_CDROM_DISK_TYPE:
512
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
513
    constants.HV_USB_MOUSE:
514
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
515
    constants.HV_KEYMAP: hv_base.NO_CHECK,
516
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
517
    constants.HV_MIGRATION_BANDWIDTH: hv_base.REQ_NONNEGATIVE_INT_CHECK,
518
    constants.HV_MIGRATION_DOWNTIME: hv_base.REQ_NONNEGATIVE_INT_CHECK,
519
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
520
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
521
    constants.HV_DISK_CACHE:
522
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
523
    constants.HV_SECURITY_MODEL:
524
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
525
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
526
    constants.HV_KVM_FLAG:
527
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
528
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
529
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
530
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
531
    constants.HV_REBOOT_BEHAVIOR:
532
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
533
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
534
    constants.HV_CPU_TYPE: hv_base.NO_CHECK,
535
    constants.HV_CPU_CORES: hv_base.OPT_NONNEGATIVE_INT_CHECK,
536
    constants.HV_CPU_THREADS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
537
    constants.HV_CPU_SOCKETS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
538
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
539
    constants.HV_USB_DEVICES: hv_base.NO_CHECK,
540
    constants.HV_VGA: hv_base.NO_CHECK,
541
    constants.HV_KVM_EXTRA: hv_base.NO_CHECK,
542
    }
543

    
544
  _MIGRATION_STATUS_RE = re.compile("Migration\s+status:\s+(\w+)",
545
                                    re.M | re.I)
546
  _MIGRATION_PROGRESS_RE = \
547
    re.compile(r"\s*transferred\s+ram:\s+(?P<transferred>\d+)\s+kbytes\s*\n"
548
               r"\s*remaining\s+ram:\s+(?P<remaining>\d+)\s+kbytes\s*\n"
549
               r"\s*total\s+ram:\s+(?P<total>\d+)\s+kbytes\s*\n", re.I)
550

    
551
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
552
  _MIGRATION_INFO_RETRY_DELAY = 2
553

    
554
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
555

    
556
  _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
557
  _CPU_INFO_CMD = "info cpus"
558
  _CONT_CMD = "cont"
559

    
560
  _DEFAULT_MACHINE_VERSION_RE = re.compile(r"^(\S+).*\(default\)", re.M)
561

    
562
  _QMP_RE = re.compile(r"^-qmp\s", re.M)
563
  _SPICE_RE = re.compile(r"^-spice\s", re.M)
564
  _VHOST_RE = re.compile(r"^-net\s.*,vhost=on|off", re.M)
565
  _ENABLE_KVM_RE = re.compile(r"^-enable-kvm\s", re.M)
566
  _DISABLE_KVM_RE = re.compile(r"^-disable-kvm\s", re.M)
567
  _NETDEV_RE = re.compile(r"^-netdev\s", re.M)
568
  # match  -drive.*boot=on|off on different lines, but in between accept only
569
  # dashes not preceeded by a new line (which would mean another option
570
  # different than -drive is starting)
571
  _BOOT_RE = re.compile(r"^-drive\s([^-]|(?<!^)-)*,boot=on\|off", re.M | re.S)
572

    
573
  ANCILLARY_FILES = [
574
    _KVM_NETWORK_SCRIPT,
575
    ]
576
  ANCILLARY_FILES_OPT = [
577
    _KVM_NETWORK_SCRIPT,
578
    ]
579

    
580
  def __init__(self):
581
    hv_base.BaseHypervisor.__init__(self)
582
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
583
    # in a tmpfs filesystem or has been otherwise wiped out.
584
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
585
    utils.EnsureDirs(dirs)
586

    
587
  @classmethod
588
  def _InstancePidFile(cls, instance_name):
589
    """Returns the instance pidfile.
590

591
    """
592
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
593

    
594
  @classmethod
595
  def _InstanceUidFile(cls, instance_name):
596
    """Returns the instance uidfile.
597

598
    """
599
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
600

    
601
  @classmethod
602
  def _InstancePidInfo(cls, pid):
603
    """Check pid file for instance information.
604

605
    Check that a pid file is associated with an instance, and retrieve
606
    information from its command line.
607

608
    @type pid: string or int
609
    @param pid: process id of the instance to check
610
    @rtype: tuple
611
    @return: (instance_name, memory, vcpus)
612
    @raise errors.HypervisorError: when an instance cannot be found
613

614
    """
615
    alive = utils.IsProcessAlive(pid)
616
    if not alive:
617
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
618

    
619
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
620
    try:
621
      cmdline = utils.ReadFile(cmdline_file)
622
    except EnvironmentError, err:
623
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
624
                                   (pid, err))
625

    
626
    instance = None
627
    memory = 0
628
    vcpus = 0
629

    
630
    arg_list = cmdline.split("\x00")
631
    while arg_list:
632
      arg = arg_list.pop(0)
633
      if arg == "-name":
634
        instance = arg_list.pop(0)
635
      elif arg == "-m":
636
        memory = int(arg_list.pop(0))
637
      elif arg == "-smp":
638
        vcpus = int(arg_list.pop(0).split(",")[0])
639

    
640
    if instance is None:
641
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
642
                                   " instance" % pid)
643

    
644
    return (instance, memory, vcpus)
645

    
646
  def _InstancePidAlive(self, instance_name):
647
    """Returns the instance pidfile, pid, and liveness.
648

649
    @type instance_name: string
650
    @param instance_name: instance name
651
    @rtype: tuple
652
    @return: (pid file name, pid, liveness)
653

654
    """
655
    pidfile = self._InstancePidFile(instance_name)
656
    pid = utils.ReadPidFile(pidfile)
657

    
658
    alive = False
659
    try:
660
      cmd_instance = self._InstancePidInfo(pid)[0]
661
      alive = (cmd_instance == instance_name)
662
    except errors.HypervisorError:
663
      pass
664

    
665
    return (pidfile, pid, alive)
666

    
667
  def _CheckDown(self, instance_name):
668
    """Raises an error unless the given instance is down.
669

670
    """
671
    alive = self._InstancePidAlive(instance_name)[2]
672
    if alive:
673
      raise errors.HypervisorError("Failed to start instance %s: %s" %
674
                                   (instance_name, "already running"))
675

    
676
  @classmethod
677
  def _InstanceMonitor(cls, instance_name):
678
    """Returns the instance monitor socket name
679

680
    """
681
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
682

    
683
  @classmethod
684
  def _InstanceSerial(cls, instance_name):
685
    """Returns the instance serial socket name
686

687
    """
688
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
689

    
690
  @classmethod
691
  def _InstanceQmpMonitor(cls, instance_name):
692
    """Returns the instance serial QMP socket name
693

694
    """
695
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
696

    
697
  @staticmethod
698
  def _SocatUnixConsoleParams():
699
    """Returns the correct parameters for socat
700

701
    If we have a new-enough socat we can use raw mode with an escape character.
702

703
    """
704
    if constants.SOCAT_USE_ESCAPE:
705
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
706
    else:
707
      return "echo=0,icanon=0"
708

    
709
  @classmethod
710
  def _InstanceKVMRuntime(cls, instance_name):
711
    """Returns the instance KVM runtime filename
712

713
    """
714
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
715

    
716
  @classmethod
717
  def _InstanceChrootDir(cls, instance_name):
718
    """Returns the name of the KVM chroot dir of the instance
719

720
    """
721
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
722

    
723
  @classmethod
724
  def _InstanceNICDir(cls, instance_name):
725
    """Returns the name of the directory holding the tap device files for a
726
    given instance.
727

728
    """
729
    return utils.PathJoin(cls._NICS_DIR, instance_name)
730

    
731
  @classmethod
732
  def _InstanceNICFile(cls, instance_name, seq):
733
    """Returns the name of the file containing the tap device for a given NIC
734

735
    """
736
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
737

    
738
  @classmethod
739
  def _InstanceKeymapFile(cls, instance_name):
740
    """Returns the name of the file containing the keymap for a given instance
741

742
    """
743
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
744

    
745
  @classmethod
746
  def _TryReadUidFile(cls, uid_file):
747
    """Try to read a uid file
748

749
    """
750
    if os.path.exists(uid_file):
751
      try:
752
        uid = int(utils.ReadOneLineFile(uid_file))
753
        return uid
754
      except EnvironmentError:
755
        logging.warning("Can't read uid file", exc_info=True)
756
      except (TypeError, ValueError):
757
        logging.warning("Can't parse uid file contents", exc_info=True)
758
    return None
759

    
760
  @classmethod
761
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
762
    """Removes an instance's rutime sockets/files/dirs.
763

764
    """
765
    utils.RemoveFile(pidfile)
766
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
767
    utils.RemoveFile(cls._InstanceSerial(instance_name))
768
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
769
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
770
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
771
    uid_file = cls._InstanceUidFile(instance_name)
772
    uid = cls._TryReadUidFile(uid_file)
773
    utils.RemoveFile(uid_file)
774
    if uid is not None:
775
      uidpool.ReleaseUid(uid)
776
    try:
777
      shutil.rmtree(cls._InstanceNICDir(instance_name))
778
    except OSError, err:
779
      if err.errno != errno.ENOENT:
780
        raise
781
    try:
782
      chroot_dir = cls._InstanceChrootDir(instance_name)
783
      utils.RemoveDir(chroot_dir)
784
    except OSError, err:
785
      if err.errno == errno.ENOTEMPTY:
786
        # The chroot directory is expected to be empty, but it isn't.
787
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
788
                                          prefix="%s-%s-" %
789
                                          (instance_name,
790
                                           utils.TimestampForFilename()))
791
        logging.warning("The chroot directory of instance %s can not be"
792
                        " removed as it is not empty. Moving it to the"
793
                        " quarantine instead. Please investigate the"
794
                        " contents (%s) and clean up manually",
795
                        instance_name, new_chroot_dir)
796
        utils.RenameFile(chroot_dir, new_chroot_dir)
797
      else:
798
        raise
799

    
800
  @staticmethod
801
  def _ConfigureNIC(instance, seq, nic, tap):
802
    """Run the network configuration script for a specified NIC
803

804
    @param instance: instance we're acting on
805
    @type instance: instance object
806
    @param seq: nic sequence number
807
    @type seq: int
808
    @param nic: nic we're acting on
809
    @type nic: nic object
810
    @param tap: the host's tap interface this NIC corresponds to
811
    @type tap: str
812

813
    """
814
    if instance.tags:
815
      tags = " ".join(instance.tags)
816
    else:
817
      tags = ""
818

    
819
    env = {
820
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
821
      "INSTANCE": instance.name,
822
      "MAC": nic.mac,
823
      "MODE": nic.nicparams[constants.NIC_MODE],
824
      "INTERFACE": tap,
825
      "INTERFACE_INDEX": str(seq),
826
      "TAGS": tags,
827
    }
828

    
829
    if nic.ip:
830
      env["IP"] = nic.ip
831

    
832
    if nic.nicparams[constants.NIC_LINK]:
833
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
834

    
835
    if nic.network:
836
      n = objects.Network.FromDict(nic.netinfo)
837
      _BuildNetworkEnv(nic.network, n.network, n.gateway,
838
                       n.network6, n.gateway6, n.network_type,
839
                       n.mac_prefix, n.tags, env)
840

    
841
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
842
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
843

    
844
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
845
    if result.failed:
846
      raise errors.HypervisorError("Failed to configure interface %s: %s."
847
                                   " Network configuration script output: %s" %
848
                                   (tap, result.fail_reason, result.output))
849

    
850
  @staticmethod
851
  def _VerifyAffinityPackage():
852
    if affinity is None:
853
      raise errors.HypervisorError("affinity Python package not"
854
                                   " found; cannot use CPU pinning under KVM")
855

    
856
  @staticmethod
857
  def _BuildAffinityCpuMask(cpu_list):
858
    """Create a CPU mask suitable for sched_setaffinity from a list of
859
    CPUs.
860

861
    See man taskset for more info on sched_setaffinity masks.
862
    For example: [ 0, 2, 5, 6 ] will return 101 (0x65, 0..01100101).
863

864
    @type cpu_list: list of int
865
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
866
    @rtype: int
867
    @return: a bit mask of CPU affinities
868

869
    """
870
    if cpu_list == constants.CPU_PINNING_OFF:
871
      return constants.CPU_PINNING_ALL_KVM
872
    else:
873
      return sum(2 ** cpu for cpu in cpu_list)
874

    
875
  @classmethod
876
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
877
    """Change CPU affinity for running VM according to given CPU mask.
878

879
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
880
    @type cpu_mask: string
881
    @param process_id: process ID of KVM process. Used to pin entire VM
882
                       to physical CPUs.
883
    @type process_id: int
884
    @param thread_dict: map of virtual CPUs to KVM thread IDs
885
    @type thread_dict: dict int:int
886

887
    """
888
    # Convert the string CPU mask to a list of list of int's
889
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
890

    
891
    if len(cpu_list) == 1:
892
      all_cpu_mapping = cpu_list[0]
893
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
894
        # If CPU pinning has 1 entry that's "all", then do nothing
895
        pass
896
      else:
897
        # If CPU pinning has one non-all entry, map the entire VM to
898
        # one set of physical CPUs
899
        cls._VerifyAffinityPackage()
900
        affinity.set_process_affinity_mask(
901
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
902
    else:
903
      # The number of vCPUs mapped should match the number of vCPUs
904
      # reported by KVM. This was already verified earlier, so
905
      # here only as a sanity check.
906
      assert len(thread_dict) == len(cpu_list)
907
      cls._VerifyAffinityPackage()
908

    
909
      # For each vCPU, map it to the proper list of physical CPUs
910
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
911
        affinity.set_process_affinity_mask(thread_dict[i],
912
                                           cls._BuildAffinityCpuMask(vcpu))
913

    
914
  def _GetVcpuThreadIds(self, instance_name):
915
    """Get a mapping of vCPU no. to thread IDs for the instance
916

917
    @type instance_name: string
918
    @param instance_name: instance in question
919
    @rtype: dictionary of int:int
920
    @return: a dictionary mapping vCPU numbers to thread IDs
921

922
    """
923
    result = {}
924
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
925
    for line in output.stdout.splitlines():
926
      match = self._CPU_INFO_RE.search(line)
927
      if not match:
928
        continue
929
      grp = map(int, match.groups())
930
      result[grp[0]] = grp[1]
931

    
932
    return result
933

    
934
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
935
    """Complete CPU pinning.
936

937
    @type instance_name: string
938
    @param instance_name: name of instance
939
    @type cpu_mask: string
940
    @param cpu_mask: CPU pinning mask as entered by user
941

942
    """
943
    # Get KVM process ID, to be used if need to pin entire VM
944
    _, pid, _ = self._InstancePidAlive(instance_name)
945
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
946
    thread_dict = self._GetVcpuThreadIds(instance_name)
947
    # Run CPU pinning, based on configured mask
948
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
949

    
950
  def ListInstances(self):
951
    """Get the list of running instances.
952

953
    We can do this by listing our live instances directory and
954
    checking whether the associated kvm process is still alive.
955

956
    """
957
    result = []
958
    for name in os.listdir(self._PIDS_DIR):
959
      if self._InstancePidAlive(name)[2]:
960
        result.append(name)
961
    return result
962

    
963
  def GetInstanceInfo(self, instance_name):
964
    """Get instance properties.
965

966
    @type instance_name: string
967
    @param instance_name: the instance name
968
    @rtype: tuple of strings
969
    @return: (name, id, memory, vcpus, stat, times)
970

971
    """
972
    _, pid, alive = self._InstancePidAlive(instance_name)
973
    if not alive:
974
      return None
975

    
976
    _, memory, vcpus = self._InstancePidInfo(pid)
977
    istat = "---b-"
978
    times = "0"
979

    
980
    try:
981
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
982
      qmp.connect()
983
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
984
      # Will fail if ballooning is not enabled, but we can then just resort to
985
      # the value above.
986
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
987
      memory = mem_bytes / 1048576
988
    except errors.HypervisorError:
989
      pass
990

    
991
    return (instance_name, pid, memory, vcpus, istat, times)
992

    
993
  def GetAllInstancesInfo(self):
994
    """Get properties of all instances.
995

996
    @return: list of tuples (name, id, memory, vcpus, stat, times)
997

998
    """
999
    data = []
1000
    for name in os.listdir(self._PIDS_DIR):
1001
      try:
1002
        info = self.GetInstanceInfo(name)
1003
      except errors.HypervisorError:
1004
        # Ignore exceptions due to instances being shut down
1005
        continue
1006
      if info:
1007
        data.append(info)
1008
    return data
1009

    
1010
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused):
1011
    """Generate KVM information to start an instance.
1012

1013
    @attention: this function must not have any side-effects; for
1014
        example, it must not write to the filesystem, or read values
1015
        from the current system the are expected to differ between
1016
        nodes, since it is only run once at instance startup;
1017
        actions/kvm arguments that can vary between systems should be
1018
        done in L{_ExecuteKVMRuntime}
1019

1020
    """
1021
    # pylint: disable=R0912,R0914,R0915
1022
    kvmhelp = self._GetKVMHelpOutput()
1023
    hvp = instance.hvparams
1024

    
1025
    pidfile = self._InstancePidFile(instance.name)
1026
    kvm = constants.KVM_PATH
1027
    kvm_cmd = [kvm]
1028
    kvm_cmd.extend(["-M", self._GetDefaultMachineVersion()])
1029
    # used just by the vnc server, if enabled
1030
    kvm_cmd.extend(["-name", instance.name])
1031
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1032

    
1033
    smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1034
    if hvp[constants.HV_CPU_CORES]:
1035
      smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1036
    if hvp[constants.HV_CPU_THREADS]:
1037
      smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1038
    if hvp[constants.HV_CPU_SOCKETS]:
1039
      smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1040

    
1041
    kvm_cmd.extend(["-smp", ",".join(smp_list)])
1042

    
1043
    kvm_cmd.extend(["-pidfile", pidfile])
1044
    kvm_cmd.extend(["-balloon", "virtio"])
1045
    kvm_cmd.extend(["-daemonize"])
1046
    if not instance.hvparams[constants.HV_ACPI]:
1047
      kvm_cmd.extend(["-no-acpi"])
1048
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1049
        constants.INSTANCE_REBOOT_EXIT:
1050
      kvm_cmd.extend(["-no-reboot"])
1051

    
1052
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1053
    if kernel_path:
1054
      boot_disk = boot_cdrom = boot_floppy = boot_network = False
1055
    else:
1056
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1057
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1058
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1059
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1060

    
1061
    self.ValidateParameters(hvp)
1062

    
1063
    if startup_paused:
1064
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1065

    
1066
    if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1067
        self._ENABLE_KVM_RE.search(kvmhelp)):
1068
      kvm_cmd.extend(["-enable-kvm"])
1069
    elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1070
          self._DISABLE_KVM_RE.search(kvmhelp)):
1071
      kvm_cmd.extend(["-disable-kvm"])
1072

    
1073
    if boot_network:
1074
      kvm_cmd.extend(["-boot", "n"])
1075

    
1076
    # whether this is an older KVM version that uses the boot=on flag
1077
    # on devices
1078
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1079

    
1080
    disk_type = hvp[constants.HV_DISK_TYPE]
1081
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1082
      if_val = ",if=virtio"
1083
    else:
1084
      if_val = ",if=%s" % disk_type
1085
    # Cache mode
1086
    disk_cache = hvp[constants.HV_DISK_CACHE]
1087
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1088
      if disk_cache != "none":
1089
        # TODO: make this a hard error, instead of a silent overwrite
1090
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1091
                        " to prevent shared storage corruption on migration",
1092
                        disk_cache)
1093
      cache_val = ",cache=none"
1094
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1095
      cache_val = ",cache=%s" % disk_cache
1096
    else:
1097
      cache_val = ""
1098
    for cfdev, dev_path in block_devices:
1099
      if cfdev.mode != constants.DISK_RDWR:
1100
        raise errors.HypervisorError("Instance has read-only disks which"
1101
                                     " are not supported by KVM")
1102
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1103
      boot_val = ""
1104
      if boot_disk:
1105
        kvm_cmd.extend(["-boot", "c"])
1106
        boot_disk = False
1107
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1108
          boot_val = ",boot=on"
1109

    
1110
      drive_val = "file=%s,format=raw%s%s%s" % (dev_path, if_val, boot_val,
1111
                                                cache_val)
1112
      kvm_cmd.extend(["-drive", drive_val])
1113

    
1114
    #Now we can specify a different device type for CDROM devices.
1115
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1116
    if not cdrom_disk_type:
1117
      cdrom_disk_type = disk_type
1118

    
1119
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1120
    if iso_image:
1121
      options = ",format=raw,media=cdrom"
1122
      # set cdrom 'if' type
1123
      if boot_cdrom:
1124
        actual_cdrom_type = constants.HT_DISK_IDE
1125
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1126
        actual_cdrom_type = "virtio"
1127
      else:
1128
        actual_cdrom_type = cdrom_disk_type
1129
      if_val = ",if=%s" % actual_cdrom_type
1130
      # set boot flag, if needed
1131
      boot_val = ""
1132
      if boot_cdrom:
1133
        kvm_cmd.extend(["-boot", "d"])
1134
        if needs_boot_flag:
1135
          boot_val = ",boot=on"
1136
      # and finally build the entire '-drive' value
1137
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1138
      kvm_cmd.extend(["-drive", drive_val])
1139

    
1140
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1141
    if iso_image2:
1142
      options = ",format=raw,media=cdrom"
1143
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1144
        if_val = ",if=virtio"
1145
      else:
1146
        if_val = ",if=%s" % cdrom_disk_type
1147
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1148
      kvm_cmd.extend(["-drive", drive_val])
1149

    
1150
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1151
    if floppy_image:
1152
      options = ",format=raw,media=disk"
1153
      if boot_floppy:
1154
        kvm_cmd.extend(["-boot", "a"])
1155
        options = "%s,boot=on" % options
1156
      if_val = ",if=floppy"
1157
      options = "%s%s" % (options, if_val)
1158
      drive_val = "file=%s%s" % (floppy_image, options)
1159
      kvm_cmd.extend(["-drive", drive_val])
1160

    
1161
    if kernel_path:
1162
      kvm_cmd.extend(["-kernel", kernel_path])
1163
      initrd_path = hvp[constants.HV_INITRD_PATH]
1164
      if initrd_path:
1165
        kvm_cmd.extend(["-initrd", initrd_path])
1166
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1167
                     hvp[constants.HV_KERNEL_ARGS]]
1168
      if hvp[constants.HV_SERIAL_CONSOLE]:
1169
        serial_speed = hvp[constants.HV_SERIAL_SPEED]
1170
        root_append.append("console=ttyS0,%s" % serial_speed)
1171
      kvm_cmd.extend(["-append", " ".join(root_append)])
1172

    
1173
    mem_path = hvp[constants.HV_MEM_PATH]
1174
    if mem_path:
1175
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1176

    
1177
    monitor_dev = ("unix:%s,server,nowait" %
1178
                   self._InstanceMonitor(instance.name))
1179
    kvm_cmd.extend(["-monitor", monitor_dev])
1180
    if hvp[constants.HV_SERIAL_CONSOLE]:
1181
      serial_dev = ("unix:%s,server,nowait" %
1182
                    self._InstanceSerial(instance.name))
1183
      kvm_cmd.extend(["-serial", serial_dev])
1184
    else:
1185
      kvm_cmd.extend(["-serial", "none"])
1186

    
1187
    mouse_type = hvp[constants.HV_USB_MOUSE]
1188
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1189
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1190
    spice_ip_version = None
1191

    
1192
    kvm_cmd.extend(["-usb"])
1193

    
1194
    if mouse_type:
1195
      kvm_cmd.extend(["-usbdevice", mouse_type])
1196
    elif vnc_bind_address:
1197
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1198

    
1199
    if vnc_bind_address:
1200
      if netutils.IP4Address.IsValid(vnc_bind_address):
1201
        if instance.network_port > constants.VNC_BASE_PORT:
1202
          display = instance.network_port - constants.VNC_BASE_PORT
1203
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1204
            vnc_arg = ":%d" % (display)
1205
          else:
1206
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1207
        else:
1208
          logging.error("Network port is not a valid VNC display (%d < %d)."
1209
                        " Not starting VNC", instance.network_port,
1210
                        constants.VNC_BASE_PORT)
1211
          vnc_arg = "none"
1212

    
1213
        # Only allow tls and other option when not binding to a file, for now.
1214
        # kvm/qemu gets confused otherwise about the filename to use.
1215
        vnc_append = ""
1216
        if hvp[constants.HV_VNC_TLS]:
1217
          vnc_append = "%s,tls" % vnc_append
1218
          if hvp[constants.HV_VNC_X509_VERIFY]:
1219
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1220
                                               hvp[constants.HV_VNC_X509])
1221
          elif hvp[constants.HV_VNC_X509]:
1222
            vnc_append = "%s,x509=%s" % (vnc_append,
1223
                                         hvp[constants.HV_VNC_X509])
1224
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1225
          vnc_append = "%s,password" % vnc_append
1226

    
1227
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1228

    
1229
      else:
1230
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1231

    
1232
      kvm_cmd.extend(["-vnc", vnc_arg])
1233
    elif spice_bind:
1234
      # FIXME: this is wrong here; the iface ip address differs
1235
      # between systems, so it should be done in _ExecuteKVMRuntime
1236
      if netutils.IsValidInterface(spice_bind):
1237
        # The user specified a network interface, we have to figure out the IP
1238
        # address.
1239
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1240
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1241

    
1242
        # if the user specified an IP version and the interface does not
1243
        # have that kind of IP addresses, throw an exception
1244
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1245
          if not addresses[spice_ip_version]:
1246
            raise errors.HypervisorError("spice: unable to get an IPv%s address"
1247
                                         " for %s" % (spice_ip_version,
1248
                                                      spice_bind))
1249

    
1250
        # the user did not specify an IP version, we have to figure it out
1251
        elif (addresses[constants.IP4_VERSION] and
1252
              addresses[constants.IP6_VERSION]):
1253
          # we have both ipv4 and ipv6, let's use the cluster default IP
1254
          # version
1255
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1256
          spice_ip_version = \
1257
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1258
        elif addresses[constants.IP4_VERSION]:
1259
          spice_ip_version = constants.IP4_VERSION
1260
        elif addresses[constants.IP6_VERSION]:
1261
          spice_ip_version = constants.IP6_VERSION
1262
        else:
1263
          raise errors.HypervisorError("spice: unable to get an IP address"
1264
                                       " for %s" % (spice_bind))
1265

    
1266
        spice_address = addresses[spice_ip_version][0]
1267

    
1268
      else:
1269
        # spice_bind is known to be a valid IP address, because
1270
        # ValidateParameters checked it.
1271
        spice_address = spice_bind
1272

    
1273
      spice_arg = "addr=%s" % spice_address
1274
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1275
        spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1276
                     (spice_arg, instance.network_port,
1277
                      pathutils.SPICE_CACERT_FILE))
1278
        spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1279
                     (spice_arg, pathutils.SPICE_CERT_FILE,
1280
                      pathutils.SPICE_CERT_FILE))
1281
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1282
        if tls_ciphers:
1283
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1284
      else:
1285
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1286

    
1287
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1288
        spice_arg = "%s,disable-ticketing" % spice_arg
1289

    
1290
      if spice_ip_version:
1291
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1292

    
1293
      # Image compression options
1294
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1295
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1296
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1297
      if img_lossless:
1298
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1299
      if img_jpeg:
1300
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1301
      if img_zlib_glz:
1302
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1303

    
1304
      # Video stream detection
1305
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1306
      if video_streaming:
1307
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1308

    
1309
      # Audio compression, by default in qemu-kvm it is on
1310
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1311
        spice_arg = "%s,playback-compression=off" % spice_arg
1312
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1313
        spice_arg = "%s,agent-mouse=off" % spice_arg
1314
      else:
1315
        # Enable the spice agent communication channel between the host and the
1316
        # agent.
1317
        kvm_cmd.extend(["-device", "virtio-serial-pci"])
1318
        kvm_cmd.extend(["-device", "virtserialport,chardev=spicechannel0,"
1319
                                                   "name=com.redhat.spice.0"])
1320
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1321

    
1322
      logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1323
      kvm_cmd.extend(["-spice", spice_arg])
1324

    
1325
    else:
1326
      kvm_cmd.extend(["-nographic"])
1327

    
1328
    if hvp[constants.HV_USE_LOCALTIME]:
1329
      kvm_cmd.extend(["-localtime"])
1330

    
1331
    if hvp[constants.HV_KVM_USE_CHROOT]:
1332
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1333

    
1334
    # Add qemu-KVM -cpu param
1335
    if hvp[constants.HV_CPU_TYPE]:
1336
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1337

    
1338
    # As requested by music lovers
1339
    if hvp[constants.HV_SOUNDHW]:
1340
      kvm_cmd.extend(["-soundhw", hvp[constants.HV_SOUNDHW]])
1341

    
1342
    # Pass a -vga option if requested, or if spice is used, for backwards
1343
    # compatibility.
1344
    if hvp[constants.HV_VGA]:
1345
      kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1346
    elif spice_bind:
1347
      kvm_cmd.extend(["-vga", "qxl"])
1348

    
1349
    # Various types of usb devices, comma separated
1350
    if hvp[constants.HV_USB_DEVICES]:
1351
      for dev in hvp[constants.HV_USB_DEVICES].split(","):
1352
        kvm_cmd.extend(["-usbdevice", dev])
1353

    
1354
    if hvp[constants.HV_KVM_EXTRA]:
1355
      kvm_cmd.extend([hvp[constants.HV_KVM_EXTRA]])
1356

    
1357
    # Save the current instance nics, but defer their expansion as parameters,
1358
    # as we'll need to generate executable temp files for them.
1359
    kvm_nics = instance.nics
1360
    hvparams = hvp
1361

    
1362
    return (kvm_cmd, kvm_nics, hvparams)
1363

    
1364
  def _WriteKVMRuntime(self, instance_name, data):
1365
    """Write an instance's KVM runtime
1366

1367
    """
1368
    try:
1369
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1370
                      data=data)
1371
    except EnvironmentError, err:
1372
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1373

    
1374
  def _ReadKVMRuntime(self, instance_name):
1375
    """Read an instance's KVM runtime
1376

1377
    """
1378
    try:
1379
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1380
    except EnvironmentError, err:
1381
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1382
    return file_content
1383

    
1384
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1385
    """Save an instance's KVM runtime
1386

1387
    """
1388
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1389
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1390
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1391
    self._WriteKVMRuntime(instance.name, serialized_form)
1392

    
1393
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1394
    """Load an instance's KVM runtime
1395

1396
    """
1397
    if not serialized_runtime:
1398
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1399
    loaded_runtime = serializer.Load(serialized_runtime)
1400
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1401
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1402
    return (kvm_cmd, kvm_nics, hvparams)
1403

    
1404
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1405
    """Run the KVM cmd and check for errors
1406

1407
    @type name: string
1408
    @param name: instance name
1409
    @type kvm_cmd: list of strings
1410
    @param kvm_cmd: runcmd input for kvm
1411
    @type tap_fds: list of int
1412
    @param tap_fds: fds of tap devices opened by Ganeti
1413

1414
    """
1415
    try:
1416
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1417
    finally:
1418
      for fd in tap_fds:
1419
        utils_wrapper.CloseFdNoError(fd)
1420

    
1421
    if result.failed:
1422
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1423
                                   (name, result.fail_reason, result.output))
1424
    if not self._InstancePidAlive(name)[2]:
1425
      raise errors.HypervisorError("Failed to start instance %s" % name)
1426

    
1427
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
1428
    """Execute a KVM cmd, after completing it with some last minute data.
1429

1430
    @type incoming: tuple of strings
1431
    @param incoming: (target_host_ip, port)
1432

1433
    """
1434
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1435
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1436
    #    have changed since the instance started; only use them if the change
1437
    #    won't affect the inside of the instance (which hasn't been rebooted).
1438
    #  - up_hvp contains the parameters as they were when the instance was
1439
    #    started, plus any new parameter which has been added between ganeti
1440
    #    versions: it is paramount that those default to a value which won't
1441
    #    affect the inside of the instance as well.
1442
    conf_hvp = instance.hvparams
1443
    name = instance.name
1444
    self._CheckDown(name)
1445

    
1446
    temp_files = []
1447

    
1448
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1449
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1450

    
1451
    kvmhelp = self._GetKVMHelpOutput()
1452
    _, v_major, v_min, _ = self._ParseKVMVersion(kvmhelp)
1453

    
1454
    # We know it's safe to run as a different user upon migration, so we'll use
1455
    # the latest conf, from conf_hvp.
1456
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1457
    if security_model == constants.HT_SM_USER:
1458
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1459

    
1460
    keymap = conf_hvp[constants.HV_KEYMAP]
1461
    if keymap:
1462
      keymap_path = self._InstanceKeymapFile(name)
1463
      # If a keymap file is specified, KVM won't use its internal defaults. By
1464
      # first including the "en-us" layout, an error on loading the actual
1465
      # layout (e.g. because it can't be found) won't lead to a non-functional
1466
      # keyboard. A keyboard with incorrect keys is still better than none.
1467
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1468
      kvm_cmd.extend(["-k", keymap_path])
1469

    
1470
    # We have reasons to believe changing something like the nic driver/type
1471
    # upon migration won't exactly fly with the instance kernel, so for nic
1472
    # related parameters we'll use up_hvp
1473
    tapfds = []
1474
    taps = []
1475
    if not kvm_nics:
1476
      kvm_cmd.extend(["-net", "none"])
1477
    else:
1478
      vnet_hdr = False
1479
      tap_extra = ""
1480
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1481
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1482
        # From version 0.12.0, kvm uses a new sintax for network configuration.
1483
        if (v_major, v_min) >= (0, 12):
1484
          nic_model = "virtio-net-pci"
1485
          vnet_hdr = True
1486
        else:
1487
          nic_model = "virtio"
1488

    
1489
        if up_hvp[constants.HV_VHOST_NET]:
1490
          # vhost_net is only available from version 0.13.0 or newer
1491
          if self._VHOST_RE.search(kvmhelp):
1492
            tap_extra = ",vhost=on"
1493
          else:
1494
            raise errors.HypervisorError("vhost_net is configured"
1495
                                         " but it is not available")
1496
      else:
1497
        nic_model = nic_type
1498

    
1499
      for nic_seq, nic in enumerate(kvm_nics):
1500
        tapname, tapfd = _OpenTap(vnet_hdr)
1501
        tapfds.append(tapfd)
1502
        taps.append(tapname)
1503
        if self._NETDEV_RE.search(kvmhelp):
1504
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
1505
          tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
1506
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1507
        else:
1508
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1509
                                                         nic.mac, nic_model)
1510
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1511
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1512

    
1513
    if incoming:
1514
      target, port = incoming
1515
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1516

    
1517
    # Changing the vnc password doesn't bother the guest that much. At most it
1518
    # will surprise people who connect to it. Whether positively or negatively
1519
    # it's debatable.
1520
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1521
    vnc_pwd = None
1522
    if vnc_pwd_file:
1523
      try:
1524
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1525
      except EnvironmentError, err:
1526
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1527
                                     % (vnc_pwd_file, err))
1528

    
1529
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1530
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1531
                         constants.SECURE_DIR_MODE)])
1532

    
1533
    # Automatically enable QMP if version is >= 0.14
1534
    if self._QMP_RE.search(kvmhelp):
1535
      logging.debug("Enabling QMP")
1536
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1537
                      self._InstanceQmpMonitor(instance.name)])
1538

    
1539
    # Configure the network now for starting instances and bridged interfaces,
1540
    # during FinalizeMigration for incoming instances' routed interfaces
1541
    for nic_seq, nic in enumerate(kvm_nics):
1542
      if (incoming and
1543
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1544
        continue
1545
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1546

    
1547
    # CPU affinity requires kvm to start paused, so we set this flag if the
1548
    # instance is not already paused and if we are not going to accept a
1549
    # migrating instance. In the latter case, pausing is not needed.
1550
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1551
    if start_kvm_paused:
1552
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1553

    
1554
    # Note: CPU pinning is using up_hvp since changes take effect
1555
    # during instance startup anyway, and to avoid problems when soft
1556
    # rebooting the instance.
1557
    cpu_pinning = False
1558
    if up_hvp.get(constants.HV_CPU_MASK, None):
1559
      cpu_pinning = True
1560

    
1561
    if security_model == constants.HT_SM_POOL:
1562
      ss = ssconf.SimpleStore()
1563
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1564
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1565
      uid = uidpool.RequestUnusedUid(all_uids)
1566
      try:
1567
        username = pwd.getpwuid(uid.GetUid()).pw_name
1568
        kvm_cmd.extend(["-runas", username])
1569
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1570
      except:
1571
        uidpool.ReleaseUid(uid)
1572
        raise
1573
      else:
1574
        uid.Unlock()
1575
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1576
    else:
1577
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1578

    
1579
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1580
                     constants.RUN_DIRS_MODE)])
1581
    for nic_seq, tap in enumerate(taps):
1582
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1583
                      data=tap)
1584

    
1585
    if vnc_pwd:
1586
      change_cmd = "change vnc password %s" % vnc_pwd
1587
      self._CallMonitorCommand(instance.name, change_cmd)
1588

    
1589
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1590
    # connection attempts because SPICE by default does not allow connections
1591
    # if neither a password nor the "disable_ticketing" options are specified.
1592
    # As soon as we send the password via QMP, that password is a valid ticket
1593
    # for connection.
1594
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1595
    if spice_password_file:
1596
      spice_pwd = ""
1597
      try:
1598
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1599
      except EnvironmentError, err:
1600
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1601
                                     % (spice_password_file, err))
1602

    
1603
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1604
      qmp.connect()
1605
      arguments = {
1606
          "protocol": "spice",
1607
          "password": spice_pwd,
1608
      }
1609
      qmp.Execute("set_password", arguments)
1610

    
1611
    for filename in temp_files:
1612
      utils.RemoveFile(filename)
1613

    
1614
    # If requested, set CPU affinity and resume instance execution
1615
    if cpu_pinning:
1616
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1617

    
1618
    start_memory = self._InstanceStartupMemory(instance)
1619
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1620
      self.BalloonInstanceMemory(instance, start_memory)
1621

    
1622
    if start_kvm_paused:
1623
      # To control CPU pinning, ballooning, and vnc/spice passwords
1624
      # the VM was started in a frozen state. If freezing was not
1625
      # explicitly requested resume the vm status.
1626
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1627

    
1628
  def StartInstance(self, instance, block_devices, startup_paused):
1629
    """Start an instance.
1630

1631
    """
1632
    self._CheckDown(instance.name)
1633
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1634
                                           startup_paused)
1635
    self._SaveKVMRuntime(instance, kvm_runtime)
1636
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1637

    
1638
  def _CallMonitorCommand(self, instance_name, command):
1639
    """Invoke a command on the instance monitor.
1640

1641
    """
1642
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1643
             (utils.ShellQuote(command),
1644
              constants.SOCAT_PATH,
1645
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1646
    result = utils.RunCmd(socat)
1647
    if result.failed:
1648
      msg = ("Failed to send command '%s' to instance %s."
1649
             " output: %s, error: %s, fail_reason: %s" %
1650
             (command, instance_name,
1651
              result.stdout, result.stderr, result.fail_reason))
1652
      raise errors.HypervisorError(msg)
1653

    
1654
    return result
1655

    
1656
  @classmethod
1657
  def _ParseKVMVersion(cls, text):
1658
    """Parse the KVM version from the --help output.
1659

1660
    @type text: string
1661
    @param text: output of kvm --help
1662
    @return: (version, v_maj, v_min, v_rev)
1663
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1664

1665
    """
1666
    match = cls._VERSION_RE.search(text.splitlines()[0])
1667
    if not match:
1668
      raise errors.HypervisorError("Unable to get KVM version")
1669

    
1670
    v_all = match.group(0)
1671
    v_maj = int(match.group(1))
1672
    v_min = int(match.group(2))
1673
    if match.group(4):
1674
      v_rev = int(match.group(4))
1675
    else:
1676
      v_rev = 0
1677
    return (v_all, v_maj, v_min, v_rev)
1678

    
1679
  @classmethod
1680
  def _GetKVMHelpOutput(cls):
1681
    """Return the KVM help output.
1682

1683
    @return: output of kvm --help
1684
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1685

1686
    """
1687
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
1688
    if result.failed:
1689
      raise errors.HypervisorError("Unable to get KVM help output")
1690
    return result.output
1691

    
1692
  @classmethod
1693
  def _GetKVMVersion(cls):
1694
    """Return the installed KVM version.
1695

1696
    @return: (version, v_maj, v_min, v_rev)
1697
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1698

1699
    """
1700
    return cls._ParseKVMVersion(cls._GetKVMHelpOutput())
1701

    
1702
  def StopInstance(self, instance, force=False, retry=False, name=None):
1703
    """Stop an instance.
1704

1705
    """
1706
    if name is not None and not force:
1707
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1708
    if name is None:
1709
      name = instance.name
1710
      acpi = instance.hvparams[constants.HV_ACPI]
1711
    else:
1712
      acpi = False
1713
    _, pid, alive = self._InstancePidAlive(name)
1714
    if pid > 0 and alive:
1715
      if force or not acpi:
1716
        utils.KillProcess(pid)
1717
      else:
1718
        self._CallMonitorCommand(name, "system_powerdown")
1719

    
1720
  @classmethod
1721
  def _GetDefaultMachineVersion(cls):
1722
    """Return the default hardware revision (e.g. pc-1.1)
1723

1724
    """
1725
    result = utils.RunCmd([constants.KVM_PATH, "-M", "?"])
1726
    if result.failed:
1727
      raise errors.HypervisorError("Unable to get default hardware revision")
1728
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(result.output)
1729
    if match:
1730
      return match.group(1)
1731
    else:
1732
      return "pc"
1733

    
1734
  def CleanupInstance(self, instance_name):
1735
    """Cleanup after a stopped instance
1736

1737
    """
1738
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1739
    if pid > 0 and alive:
1740
      raise errors.HypervisorError("Cannot cleanup a live instance")
1741
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1742

    
1743
  def RebootInstance(self, instance):
1744
    """Reboot an instance.
1745

1746
    """
1747
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1748
    # socket the instance will stop, but now power up again. So we'll resort
1749
    # to shutdown and restart.
1750
    _, _, alive = self._InstancePidAlive(instance.name)
1751
    if not alive:
1752
      raise errors.HypervisorError("Failed to reboot instance %s:"
1753
                                   " not running" % instance.name)
1754
    # StopInstance will delete the saved KVM runtime so:
1755
    # ...first load it...
1756
    kvm_runtime = self._LoadKVMRuntime(instance)
1757
    # ...now we can safely call StopInstance...
1758
    if not self.StopInstance(instance):
1759
      self.StopInstance(instance, force=True)
1760
    # ...and finally we can save it again, and execute it...
1761
    self._SaveKVMRuntime(instance, kvm_runtime)
1762
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1763

    
1764
  def MigrationInfo(self, instance):
1765
    """Get instance information to perform a migration.
1766

1767
    @type instance: L{objects.Instance}
1768
    @param instance: instance to be migrated
1769
    @rtype: string
1770
    @return: content of the KVM runtime file
1771

1772
    """
1773
    return self._ReadKVMRuntime(instance.name)
1774

    
1775
  def AcceptInstance(self, instance, info, target):
1776
    """Prepare to accept an instance.
1777

1778
    @type instance: L{objects.Instance}
1779
    @param instance: instance to be accepted
1780
    @type info: string
1781
    @param info: content of the KVM runtime file on the source node
1782
    @type target: string
1783
    @param target: target host (usually ip), on this node
1784

1785
    """
1786
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1787
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1788
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1789

    
1790
  def FinalizeMigrationDst(self, instance, info, success):
1791
    """Finalize the instance migration on the target node.
1792

1793
    Stop the incoming mode KVM.
1794

1795
    @type instance: L{objects.Instance}
1796
    @param instance: instance whose migration is being finalized
1797

1798
    """
1799
    if success:
1800
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1801
      kvm_nics = kvm_runtime[1]
1802

    
1803
      for nic_seq, nic in enumerate(kvm_nics):
1804
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1805
          # Bridged interfaces have already been configured
1806
          continue
1807
        try:
1808
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1809
        except EnvironmentError, err:
1810
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1811
                          instance.name, nic_seq, str(err))
1812
          continue
1813
        try:
1814
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1815
        except errors.HypervisorError, err:
1816
          logging.warning(str(err))
1817

    
1818
      self._WriteKVMRuntime(instance.name, info)
1819
    else:
1820
      self.StopInstance(instance, force=True)
1821

    
1822
  def MigrateInstance(self, instance, target, live):
1823
    """Migrate an instance to a target node.
1824

1825
    The migration will not be attempted if the instance is not
1826
    currently running.
1827

1828
    @type instance: L{objects.Instance}
1829
    @param instance: the instance to be migrated
1830
    @type target: string
1831
    @param target: ip address of the target node
1832
    @type live: boolean
1833
    @param live: perform a live migration
1834

1835
    """
1836
    instance_name = instance.name
1837
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1838
    _, _, alive = self._InstancePidAlive(instance_name)
1839
    if not alive:
1840
      raise errors.HypervisorError("Instance not running, cannot migrate")
1841

    
1842
    if not live:
1843
      self._CallMonitorCommand(instance_name, "stop")
1844

    
1845
    migrate_command = ("migrate_set_speed %dm" %
1846
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1847
    self._CallMonitorCommand(instance_name, migrate_command)
1848

    
1849
    migrate_command = ("migrate_set_downtime %dms" %
1850
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1851
    self._CallMonitorCommand(instance_name, migrate_command)
1852

    
1853
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1854
    self._CallMonitorCommand(instance_name, migrate_command)
1855

    
1856
  def FinalizeMigrationSource(self, instance, success, live):
1857
    """Finalize the instance migration on the source node.
1858

1859
    @type instance: L{objects.Instance}
1860
    @param instance: the instance that was migrated
1861
    @type success: bool
1862
    @param success: whether the migration succeeded or not
1863
    @type live: bool
1864
    @param live: whether the user requested a live migration or not
1865

1866
    """
1867
    if success:
1868
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1869
      utils.KillProcess(pid)
1870
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1871
    elif live:
1872
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1873

    
1874
  def GetMigrationStatus(self, instance):
1875
    """Get the migration status
1876

1877
    @type instance: L{objects.Instance}
1878
    @param instance: the instance that is being migrated
1879
    @rtype: L{objects.MigrationStatus}
1880
    @return: the status of the current migration (one of
1881
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1882
             progress info that can be retrieved from the hypervisor
1883

1884
    """
1885
    info_command = "info migrate"
1886
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1887
      result = self._CallMonitorCommand(instance.name, info_command)
1888
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1889
      if not match:
1890
        if not result.stdout:
1891
          logging.info("KVM: empty 'info migrate' result")
1892
        else:
1893
          logging.warning("KVM: unknown 'info migrate' result: %s",
1894
                          result.stdout)
1895
      else:
1896
        status = match.group(1)
1897
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1898
          migration_status = objects.MigrationStatus(status=status)
1899
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1900
          if match:
1901
            migration_status.transferred_ram = match.group("transferred")
1902
            migration_status.total_ram = match.group("total")
1903

    
1904
          return migration_status
1905

    
1906
        logging.warning("KVM: unknown migration status '%s'", status)
1907

    
1908
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1909

    
1910
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1911

    
1912
  def BalloonInstanceMemory(self, instance, mem):
1913
    """Balloon an instance memory to a certain value.
1914

1915
    @type instance: L{objects.Instance}
1916
    @param instance: instance to be accepted
1917
    @type mem: int
1918
    @param mem: actual memory size to use for instance runtime
1919

1920
    """
1921
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1922

    
1923
  def GetNodeInfo(self):
1924
    """Return information about the node.
1925

1926
    @return: a dict with the following keys (values in MiB):
1927
          - memory_total: the total memory size on the node
1928
          - memory_free: the available memory on the node for instances
1929
          - memory_dom0: the memory used by the node itself, if available
1930
          - hv_version: the hypervisor version in the form (major, minor,
1931
                        revision)
1932

1933
    """
1934
    result = self.GetLinuxNodeInfo()
1935
    _, v_major, v_min, v_rev = self._GetKVMVersion()
1936
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1937
    return result
1938

    
1939
  @classmethod
1940
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1941
    """Return a command for connecting to the console of an instance.
1942

1943
    """
1944
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1945
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
1946
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
1947
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
1948
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1949
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1950
      return objects.InstanceConsole(instance=instance.name,
1951
                                     kind=constants.CONS_SSH,
1952
                                     host=instance.primary_node,
1953
                                     user=constants.SSH_CONSOLE_USER,
1954
                                     command=cmd)
1955

    
1956
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1957
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1958
      display = instance.network_port - constants.VNC_BASE_PORT
1959
      return objects.InstanceConsole(instance=instance.name,
1960
                                     kind=constants.CONS_VNC,
1961
                                     host=vnc_bind_address,
1962
                                     port=instance.network_port,
1963
                                     display=display)
1964

    
1965
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1966
    if spice_bind:
1967
      return objects.InstanceConsole(instance=instance.name,
1968
                                     kind=constants.CONS_SPICE,
1969
                                     host=spice_bind,
1970
                                     port=instance.network_port)
1971

    
1972
    return objects.InstanceConsole(instance=instance.name,
1973
                                   kind=constants.CONS_MESSAGE,
1974
                                   message=("No serial shell for instance %s" %
1975
                                            instance.name))
1976

    
1977
  def Verify(self):
1978
    """Verify the hypervisor.
1979

1980
    Check that the binary exists.
1981

1982
    """
1983
    if not os.path.exists(constants.KVM_PATH):
1984
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1985
    if not os.path.exists(constants.SOCAT_PATH):
1986
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1987

    
1988
  @classmethod
1989
  def CheckParameterSyntax(cls, hvparams):
1990
    """Check the given parameters for validity.
1991

1992
    @type hvparams:  dict
1993
    @param hvparams: dictionary with parameter names/value
1994
    @raise errors.HypervisorError: when a parameter is not valid
1995

1996
    """
1997
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1998

    
1999
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2000
    if kernel_path:
2001
      if not hvparams[constants.HV_ROOT_PATH]:
2002
        raise errors.HypervisorError("Need a root partition for the instance,"
2003
                                     " if a kernel is defined")
2004

    
2005
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2006
        not hvparams[constants.HV_VNC_X509]):
2007
      raise errors.HypervisorError("%s must be defined, if %s is" %
2008
                                   (constants.HV_VNC_X509,
2009
                                    constants.HV_VNC_X509_VERIFY))
2010

    
2011
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2012
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2013
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2014
      if not serial_speed or serial_speed not in valid_speeds:
2015
        raise errors.HypervisorError("Invalid serial console speed, must be"
2016
                                     " one of: %s" %
2017
                                     utils.CommaJoin(valid_speeds))
2018

    
2019
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2020
    if (boot_order == constants.HT_BO_CDROM and
2021
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2022
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2023
                                   " ISO path")
2024

    
2025
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2026
    if security_model == constants.HT_SM_USER:
2027
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2028
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2029
                                     " must be specified")
2030
    elif (security_model == constants.HT_SM_NONE or
2031
          security_model == constants.HT_SM_POOL):
2032
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2033
        raise errors.HypervisorError("Cannot have a security domain when the"
2034
                                     " security model is 'none' or 'pool'")
2035

    
2036
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2037
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2038
    if spice_bind:
2039
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2040
        # if an IP version is specified, the spice_bind parameter must be an
2041
        # IP of that family
2042
        if (netutils.IP4Address.IsValid(spice_bind) and
2043
            spice_ip_version != constants.IP4_VERSION):
2044
          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
2045
                                       " the specified IP version is %s" %
2046
                                       (spice_bind, spice_ip_version))
2047

    
2048
        if (netutils.IP6Address.IsValid(spice_bind) and
2049
            spice_ip_version != constants.IP6_VERSION):
2050
          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
2051
                                       " the specified IP version is %s" %
2052
                                       (spice_bind, spice_ip_version))
2053
    else:
2054
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2055
      # error if any of them is set without it.
2056
      for param in _SPICE_ADDITIONAL_PARAMS:
2057
        if hvparams[param]:
2058
          raise errors.HypervisorError("spice: %s requires %s to be set" %
2059
                                       (param, constants.HV_KVM_SPICE_BIND))
2060

    
2061
  @classmethod
2062
  def ValidateParameters(cls, hvparams):
2063
    """Check the given parameters for validity.
2064

2065
    @type hvparams:  dict
2066
    @param hvparams: dictionary with parameter names/value
2067
    @raise errors.HypervisorError: when a parameter is not valid
2068

2069
    """
2070
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2071

    
2072
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2073
    if security_model == constants.HT_SM_USER:
2074
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2075
      try:
2076
        pwd.getpwnam(username)
2077
      except KeyError:
2078
        raise errors.HypervisorError("Unknown security domain user %s"
2079
                                     % username)
2080

    
2081
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2082
    if spice_bind:
2083
      # only one of VNC and SPICE can be used currently.
2084
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2085
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
2086
                                     " only one of them can be used at a"
2087
                                     " given time.")
2088

    
2089
      # KVM version should be >= 0.14.0
2090
      kvmhelp = cls._GetKVMHelpOutput()
2091
      if not cls._SPICE_RE.search(kvmhelp):
2092
        raise errors.HypervisorError("spice is configured, but it is not"
2093
                                     " supported according to kvm --help")
2094

    
2095
      # if spice_bind is not an IP address, it must be a valid interface
2096
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
2097
                       or netutils.IP6Address.IsValid(spice_bind))
2098
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2099
        raise errors.HypervisorError("spice: the %s parameter must be either"
2100
                                     " a valid IP address or interface name" %
2101
                                     constants.HV_KVM_SPICE_BIND)
2102

    
2103
  @classmethod
2104
  def PowercycleNode(cls):
2105
    """KVM powercycle, just a wrapper over Linux powercycle.
2106

2107
    """
2108
    cls.LinuxPowercycle()