Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 4ab75599

History | View | Annotate | Download (76.3 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
    constants.HV_KVM_MACHINE_VERSION: hv_base.NO_CHECK,
543
    }
544

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

    
552
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
553
  _MIGRATION_INFO_RETRY_DELAY = 2
554

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
645
    return (instance, memory, vcpus)
646

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

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

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

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

    
666
    return (pidfile, pid, alive)
667

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
933
    return result
934

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1026
    pidfile = self._InstancePidFile(instance.name)
1027
    kvm = constants.KVM_PATH
1028
    kvm_cmd = [kvm]
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
    mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1053
    if not mversion:
1054
      mversion = self._GetDefaultMachineVersion()
1055
    kvm_cmd.extend(["-M", mversion])
1056

    
1057
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1058
    if kernel_path:
1059
      boot_disk = boot_cdrom = boot_floppy = boot_network = False
1060
    else:
1061
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1062
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1063
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1064
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1065

    
1066
    self.ValidateParameters(hvp)
1067

    
1068
    if startup_paused:
1069
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1070

    
1071
    if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1072
        self._ENABLE_KVM_RE.search(kvmhelp)):
1073
      kvm_cmd.extend(["-enable-kvm"])
1074
    elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1075
          self._DISABLE_KVM_RE.search(kvmhelp)):
1076
      kvm_cmd.extend(["-disable-kvm"])
1077

    
1078
    if boot_network:
1079
      kvm_cmd.extend(["-boot", "n"])
1080

    
1081
    # whether this is an older KVM version that uses the boot=on flag
1082
    # on devices
1083
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1084

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

    
1115
      drive_val = "file=%s,format=raw%s%s%s" % (dev_path, if_val, boot_val,
1116
                                                cache_val)
1117
      kvm_cmd.extend(["-drive", drive_val])
1118

    
1119
    #Now we can specify a different device type for CDROM devices.
1120
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1121
    if not cdrom_disk_type:
1122
      cdrom_disk_type = disk_type
1123

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

    
1145
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1146
    if iso_image2:
1147
      options = ",format=raw,media=cdrom"
1148
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1149
        if_val = ",if=virtio"
1150
      else:
1151
        if_val = ",if=%s" % cdrom_disk_type
1152
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1153
      kvm_cmd.extend(["-drive", drive_val])
1154

    
1155
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1156
    if floppy_image:
1157
      options = ",format=raw,media=disk"
1158
      if boot_floppy:
1159
        kvm_cmd.extend(["-boot", "a"])
1160
        options = "%s,boot=on" % options
1161
      if_val = ",if=floppy"
1162
      options = "%s%s" % (options, if_val)
1163
      drive_val = "file=%s%s" % (floppy_image, options)
1164
      kvm_cmd.extend(["-drive", drive_val])
1165

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

    
1178
    mem_path = hvp[constants.HV_MEM_PATH]
1179
    if mem_path:
1180
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1181

    
1182
    monitor_dev = ("unix:%s,server,nowait" %
1183
                   self._InstanceMonitor(instance.name))
1184
    kvm_cmd.extend(["-monitor", monitor_dev])
1185
    if hvp[constants.HV_SERIAL_CONSOLE]:
1186
      serial_dev = ("unix:%s,server,nowait" %
1187
                    self._InstanceSerial(instance.name))
1188
      kvm_cmd.extend(["-serial", serial_dev])
1189
    else:
1190
      kvm_cmd.extend(["-serial", "none"])
1191

    
1192
    mouse_type = hvp[constants.HV_USB_MOUSE]
1193
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1194
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1195
    spice_ip_version = None
1196

    
1197
    kvm_cmd.extend(["-usb"])
1198

    
1199
    if mouse_type:
1200
      kvm_cmd.extend(["-usbdevice", mouse_type])
1201
    elif vnc_bind_address:
1202
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1203

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

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

    
1232
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1233

    
1234
      else:
1235
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1236

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

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

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

    
1271
        spice_address = addresses[spice_ip_version][0]
1272

    
1273
      else:
1274
        # spice_bind is known to be a valid IP address, because
1275
        # ValidateParameters checked it.
1276
        spice_address = spice_bind
1277

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

    
1292
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1293
        spice_arg = "%s,disable-ticketing" % spice_arg
1294

    
1295
      if spice_ip_version:
1296
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1297

    
1298
      # Image compression options
1299
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1300
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1301
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1302
      if img_lossless:
1303
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1304
      if img_jpeg:
1305
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1306
      if img_zlib_glz:
1307
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1308

    
1309
      # Video stream detection
1310
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1311
      if video_streaming:
1312
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1313

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

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

    
1330
    else:
1331
      kvm_cmd.extend(["-nographic"])
1332

    
1333
    if hvp[constants.HV_USE_LOCALTIME]:
1334
      kvm_cmd.extend(["-localtime"])
1335

    
1336
    if hvp[constants.HV_KVM_USE_CHROOT]:
1337
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1338

    
1339
    # Add qemu-KVM -cpu param
1340
    if hvp[constants.HV_CPU_TYPE]:
1341
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1342

    
1343
    # As requested by music lovers
1344
    if hvp[constants.HV_SOUNDHW]:
1345
      kvm_cmd.extend(["-soundhw", hvp[constants.HV_SOUNDHW]])
1346

    
1347
    # Pass a -vga option if requested, or if spice is used, for backwards
1348
    # compatibility.
1349
    if hvp[constants.HV_VGA]:
1350
      kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1351
    elif spice_bind:
1352
      kvm_cmd.extend(["-vga", "qxl"])
1353

    
1354
    # Various types of usb devices, comma separated
1355
    if hvp[constants.HV_USB_DEVICES]:
1356
      for dev in hvp[constants.HV_USB_DEVICES].split(","):
1357
        kvm_cmd.extend(["-usbdevice", dev])
1358

    
1359
    if hvp[constants.HV_KVM_EXTRA]:
1360
      kvm_cmd.extend([hvp[constants.HV_KVM_EXTRA]])
1361

    
1362
    # Save the current instance nics, but defer their expansion as parameters,
1363
    # as we'll need to generate executable temp files for them.
1364
    kvm_nics = instance.nics
1365
    hvparams = hvp
1366

    
1367
    return (kvm_cmd, kvm_nics, hvparams)
1368

    
1369
  def _WriteKVMRuntime(self, instance_name, data):
1370
    """Write an instance's KVM runtime
1371

1372
    """
1373
    try:
1374
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1375
                      data=data)
1376
    except EnvironmentError, err:
1377
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1378

    
1379
  def _ReadKVMRuntime(self, instance_name):
1380
    """Read an instance's KVM runtime
1381

1382
    """
1383
    try:
1384
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1385
    except EnvironmentError, err:
1386
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1387
    return file_content
1388

    
1389
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1390
    """Save an instance's KVM runtime
1391

1392
    """
1393
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1394
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1395
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1396
    self._WriteKVMRuntime(instance.name, serialized_form)
1397

    
1398
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1399
    """Load an instance's KVM runtime
1400

1401
    """
1402
    if not serialized_runtime:
1403
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1404
    loaded_runtime = serializer.Load(serialized_runtime)
1405
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1406
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1407
    return (kvm_cmd, kvm_nics, hvparams)
1408

    
1409
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1410
    """Run the KVM cmd and check for errors
1411

1412
    @type name: string
1413
    @param name: instance name
1414
    @type kvm_cmd: list of strings
1415
    @param kvm_cmd: runcmd input for kvm
1416
    @type tap_fds: list of int
1417
    @param tap_fds: fds of tap devices opened by Ganeti
1418

1419
    """
1420
    try:
1421
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1422
    finally:
1423
      for fd in tap_fds:
1424
        utils_wrapper.CloseFdNoError(fd)
1425

    
1426
    if result.failed:
1427
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1428
                                   (name, result.fail_reason, result.output))
1429
    if not self._InstancePidAlive(name)[2]:
1430
      raise errors.HypervisorError("Failed to start instance %s" % name)
1431

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

1435
    @type incoming: tuple of strings
1436
    @param incoming: (target_host_ip, port)
1437

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

    
1451
    temp_files = []
1452

    
1453
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1454
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1455

    
1456
    kvmhelp = self._GetKVMHelpOutput()
1457
    _, v_major, v_min, _ = self._ParseKVMVersion(kvmhelp)
1458

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

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

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

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

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

    
1518
    if incoming:
1519
      target, port = incoming
1520
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1521

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

    
1534
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1535
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1536
                         constants.SECURE_DIR_MODE)])
1537

    
1538
    # Automatically enable QMP if version is >= 0.14
1539
    if self._QMP_RE.search(kvmhelp):
1540
      logging.debug("Enabling QMP")
1541
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1542
                      self._InstanceQmpMonitor(instance.name)])
1543

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

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

    
1559
    # Note: CPU pinning is using up_hvp since changes take effect
1560
    # during instance startup anyway, and to avoid problems when soft
1561
    # rebooting the instance.
1562
    cpu_pinning = False
1563
    if up_hvp.get(constants.HV_CPU_MASK, None):
1564
      cpu_pinning = True
1565

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

    
1584
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1585
                     constants.RUN_DIRS_MODE)])
1586
    for nic_seq, tap in enumerate(taps):
1587
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1588
                      data=tap)
1589

    
1590
    if vnc_pwd:
1591
      change_cmd = "change vnc password %s" % vnc_pwd
1592
      self._CallMonitorCommand(instance.name, change_cmd)
1593

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

    
1608
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1609
      qmp.connect()
1610
      arguments = {
1611
          "protocol": "spice",
1612
          "password": spice_pwd,
1613
      }
1614
      qmp.Execute("set_password", arguments)
1615

    
1616
    for filename in temp_files:
1617
      utils.RemoveFile(filename)
1618

    
1619
    # If requested, set CPU affinity and resume instance execution
1620
    if cpu_pinning:
1621
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1622

    
1623
    start_memory = self._InstanceStartupMemory(instance)
1624
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1625
      self.BalloonInstanceMemory(instance, start_memory)
1626

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

    
1633
  def StartInstance(self, instance, block_devices, startup_paused):
1634
    """Start an instance.
1635

1636
    """
1637
    self._CheckDown(instance.name)
1638
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1639
                                           startup_paused)
1640
    self._SaveKVMRuntime(instance, kvm_runtime)
1641
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1642

    
1643
  def _CallMonitorCommand(self, instance_name, command):
1644
    """Invoke a command on the instance monitor.
1645

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

    
1659
    return result
1660

    
1661
  @classmethod
1662
  def _ParseKVMVersion(cls, text):
1663
    """Parse the KVM version from the --help output.
1664

1665
    @type text: string
1666
    @param text: output of kvm --help
1667
    @return: (version, v_maj, v_min, v_rev)
1668
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1669

1670
    """
1671
    match = cls._VERSION_RE.search(text.splitlines()[0])
1672
    if not match:
1673
      raise errors.HypervisorError("Unable to get KVM version")
1674

    
1675
    v_all = match.group(0)
1676
    v_maj = int(match.group(1))
1677
    v_min = int(match.group(2))
1678
    if match.group(4):
1679
      v_rev = int(match.group(4))
1680
    else:
1681
      v_rev = 0
1682
    return (v_all, v_maj, v_min, v_rev)
1683

    
1684
  @classmethod
1685
  def _GetKVMHelpOutput(cls):
1686
    """Return the KVM help output.
1687

1688
    @return: output of kvm --help
1689
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1690

1691
    """
1692
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
1693
    if result.failed:
1694
      raise errors.HypervisorError("Unable to get KVM help output")
1695
    return result.output
1696

    
1697
  @classmethod
1698
  def _GetKVMVersion(cls):
1699
    """Return the installed KVM version.
1700

1701
    @return: (version, v_maj, v_min, v_rev)
1702
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1703

1704
    """
1705
    return cls._ParseKVMVersion(cls._GetKVMHelpOutput())
1706

    
1707
  def StopInstance(self, instance, force=False, retry=False, name=None):
1708
    """Stop an instance.
1709

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

    
1725
  @classmethod
1726
  def _GetDefaultMachineVersion(cls):
1727
    """Return the default hardware revision (e.g. pc-1.1)
1728

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

    
1739
  def CleanupInstance(self, instance_name):
1740
    """Cleanup after a stopped instance
1741

1742
    """
1743
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1744
    if pid > 0 and alive:
1745
      raise errors.HypervisorError("Cannot cleanup a live instance")
1746
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1747

    
1748
  def RebootInstance(self, instance):
1749
    """Reboot an instance.
1750

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

    
1769
  def MigrationInfo(self, instance):
1770
    """Get instance information to perform a migration.
1771

1772
    @type instance: L{objects.Instance}
1773
    @param instance: instance to be migrated
1774
    @rtype: string
1775
    @return: content of the KVM runtime file
1776

1777
    """
1778
    return self._ReadKVMRuntime(instance.name)
1779

    
1780
  def AcceptInstance(self, instance, info, target):
1781
    """Prepare to accept an instance.
1782

1783
    @type instance: L{objects.Instance}
1784
    @param instance: instance to be accepted
1785
    @type info: string
1786
    @param info: content of the KVM runtime file on the source node
1787
    @type target: string
1788
    @param target: target host (usually ip), on this node
1789

1790
    """
1791
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1792
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1793
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1794

    
1795
  def FinalizeMigrationDst(self, instance, info, success):
1796
    """Finalize the instance migration on the target node.
1797

1798
    Stop the incoming mode KVM.
1799

1800
    @type instance: L{objects.Instance}
1801
    @param instance: instance whose migration is being finalized
1802

1803
    """
1804
    if success:
1805
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1806
      kvm_nics = kvm_runtime[1]
1807

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

    
1823
      self._WriteKVMRuntime(instance.name, info)
1824
    else:
1825
      self.StopInstance(instance, force=True)
1826

    
1827
  def MigrateInstance(self, instance, target, live):
1828
    """Migrate an instance to a target node.
1829

1830
    The migration will not be attempted if the instance is not
1831
    currently running.
1832

1833
    @type instance: L{objects.Instance}
1834
    @param instance: the instance to be migrated
1835
    @type target: string
1836
    @param target: ip address of the target node
1837
    @type live: boolean
1838
    @param live: perform a live migration
1839

1840
    """
1841
    instance_name = instance.name
1842
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1843
    _, _, alive = self._InstancePidAlive(instance_name)
1844
    if not alive:
1845
      raise errors.HypervisorError("Instance not running, cannot migrate")
1846

    
1847
    if not live:
1848
      self._CallMonitorCommand(instance_name, "stop")
1849

    
1850
    migrate_command = ("migrate_set_speed %dm" %
1851
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1852
    self._CallMonitorCommand(instance_name, migrate_command)
1853

    
1854
    migrate_command = ("migrate_set_downtime %dms" %
1855
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1856
    self._CallMonitorCommand(instance_name, migrate_command)
1857

    
1858
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1859
    self._CallMonitorCommand(instance_name, migrate_command)
1860

    
1861
  def FinalizeMigrationSource(self, instance, success, live):
1862
    """Finalize the instance migration on the source node.
1863

1864
    @type instance: L{objects.Instance}
1865
    @param instance: the instance that was migrated
1866
    @type success: bool
1867
    @param success: whether the migration succeeded or not
1868
    @type live: bool
1869
    @param live: whether the user requested a live migration or not
1870

1871
    """
1872
    if success:
1873
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1874
      utils.KillProcess(pid)
1875
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1876
    elif live:
1877
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1878

    
1879
  def GetMigrationStatus(self, instance):
1880
    """Get the migration status
1881

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

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

    
1909
          return migration_status
1910

    
1911
        logging.warning("KVM: unknown migration status '%s'", status)
1912

    
1913
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1914

    
1915
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1916

    
1917
  def BalloonInstanceMemory(self, instance, mem):
1918
    """Balloon an instance memory to a certain value.
1919

1920
    @type instance: L{objects.Instance}
1921
    @param instance: instance to be accepted
1922
    @type mem: int
1923
    @param mem: actual memory size to use for instance runtime
1924

1925
    """
1926
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1927

    
1928
  def GetNodeInfo(self):
1929
    """Return information about the node.
1930

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

1938
    """
1939
    result = self.GetLinuxNodeInfo()
1940
    _, v_major, v_min, v_rev = self._GetKVMVersion()
1941
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1942
    return result
1943

    
1944
  @classmethod
1945
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1946
    """Return a command for connecting to the console of an instance.
1947

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

    
1961
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1962
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1963
      display = instance.network_port - constants.VNC_BASE_PORT
1964
      return objects.InstanceConsole(instance=instance.name,
1965
                                     kind=constants.CONS_VNC,
1966
                                     host=vnc_bind_address,
1967
                                     port=instance.network_port,
1968
                                     display=display)
1969

    
1970
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1971
    if spice_bind:
1972
      return objects.InstanceConsole(instance=instance.name,
1973
                                     kind=constants.CONS_SPICE,
1974
                                     host=spice_bind,
1975
                                     port=instance.network_port)
1976

    
1977
    return objects.InstanceConsole(instance=instance.name,
1978
                                   kind=constants.CONS_MESSAGE,
1979
                                   message=("No serial shell for instance %s" %
1980
                                            instance.name))
1981

    
1982
  def Verify(self):
1983
    """Verify the hypervisor.
1984

1985
    Check that the binary exists.
1986

1987
    """
1988
    if not os.path.exists(constants.KVM_PATH):
1989
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1990
    if not os.path.exists(constants.SOCAT_PATH):
1991
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1992

    
1993
  @classmethod
1994
  def CheckParameterSyntax(cls, hvparams):
1995
    """Check the given parameters for validity.
1996

1997
    @type hvparams:  dict
1998
    @param hvparams: dictionary with parameter names/value
1999
    @raise errors.HypervisorError: when a parameter is not valid
2000

2001
    """
2002
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2003

    
2004
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2005
    if kernel_path:
2006
      if not hvparams[constants.HV_ROOT_PATH]:
2007
        raise errors.HypervisorError("Need a root partition for the instance,"
2008
                                     " if a kernel is defined")
2009

    
2010
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2011
        not hvparams[constants.HV_VNC_X509]):
2012
      raise errors.HypervisorError("%s must be defined, if %s is" %
2013
                                   (constants.HV_VNC_X509,
2014
                                    constants.HV_VNC_X509_VERIFY))
2015

    
2016
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2017
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2018
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2019
      if not serial_speed or serial_speed not in valid_speeds:
2020
        raise errors.HypervisorError("Invalid serial console speed, must be"
2021
                                     " one of: %s" %
2022
                                     utils.CommaJoin(valid_speeds))
2023

    
2024
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2025
    if (boot_order == constants.HT_BO_CDROM and
2026
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2027
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2028
                                   " ISO path")
2029

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

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

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

    
2066
  @classmethod
2067
  def ValidateParameters(cls, hvparams):
2068
    """Check the given parameters for validity.
2069

2070
    @type hvparams:  dict
2071
    @param hvparams: dictionary with parameter names/value
2072
    @raise errors.HypervisorError: when a parameter is not valid
2073

2074
    """
2075
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2076

    
2077
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2078
    if security_model == constants.HT_SM_USER:
2079
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2080
      try:
2081
        pwd.getpwnam(username)
2082
      except KeyError:
2083
        raise errors.HypervisorError("Unknown security domain user %s"
2084
                                     % username)
2085

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

    
2094
      # KVM version should be >= 0.14.0
2095
      kvmhelp = cls._GetKVMHelpOutput()
2096
      if not cls._SPICE_RE.search(kvmhelp):
2097
        raise errors.HypervisorError("spice is configured, but it is not"
2098
                                     " supported according to kvm --help")
2099

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

    
2108
  @classmethod
2109
  def PowercycleNode(cls):
2110
    """KVM powercycle, just a wrapper over Linux powercycle.
2111

2112
    """
2113
    cls.LinuxPowercycle()