Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ b8168679

History | View | Annotate | Download (81.7 kB)

1
#
2
#
3

    
4
# Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 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_ONE_QUEUE = 0x2000
70
IFF_VNET_HDR = 0x4000
71

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

    
83

    
84
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
85
  """Retrieves supported TUN features from file descriptor.
86

87
  @see: L{_ProbeTapVnetHdr}
88

89
  """
90
  req = struct.pack("I", 0)
91
  try:
92
    buf = _ioctl(fd, TUNGETFEATURES, req)
93
  except EnvironmentError, err:
94
    logging.warning("ioctl(TUNGETFEATURES) failed: %s", err)
95
    return None
96
  else:
97
    (flags, ) = struct.unpack("I", buf)
98
    return flags
99

    
100

    
101
def _ProbeTapVnetHdr(fd, _features_fn=_GetTunFeatures):
102
  """Check whether to enable the IFF_VNET_HDR flag.
103

104
  To do this, _all_ of the following conditions must be met:
105
   1. TUNGETFEATURES ioctl() *must* be implemented
106
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
107
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
108
      drivers/net/tun.c there is no way to test this until after the tap device
109
      has been created using TUNSETIFF, and there is no way to change the
110
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
111
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
112
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
113

114
   @type fd: int
115
   @param fd: the file descriptor of /dev/net/tun
116

117
  """
118
  flags = _features_fn(fd)
119

    
120
  if flags is None:
121
    # Not supported
122
    return False
123

    
124
  result = bool(flags & IFF_VNET_HDR)
125

    
126
  if not result:
127
    logging.warning("Kernel does not support IFF_VNET_HDR, not enabling")
128

    
129
  return result
130

    
131

    
132
def _OpenTap(vnet_hdr=True):
133
  """Open a new tap device and return its file descriptor.
134

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

138
  @type vnet_hdr: boolean
139
  @param vnet_hdr: Enable the VNET Header
140
  @return: (ifname, tapfd)
141
  @rtype: tuple
142

143
  """
144
  try:
145
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
146
  except EnvironmentError:
147
    raise errors.HypervisorError("Failed to open /dev/net/tun")
148

    
149
  flags = IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE
150

    
151
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
152
    flags |= IFF_VNET_HDR
153

    
154
  # The struct ifreq ioctl request (see netdevice(7))
155
  ifr = struct.pack("16sh", "", flags)
156

    
157
  try:
158
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
159
  except EnvironmentError, err:
160
    raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
161
                                 err)
162

    
163
  # Get the interface name from the ioctl
164
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
165
  return (ifname, tapfd)
166

    
167

    
168
class QmpMessage:
169
  """QEMU Messaging Protocol (QMP) message.
170

171
  """
172
  def __init__(self, data):
173
    """Creates a new QMP message based on the passed data.
174

175
    """
176
    if not isinstance(data, dict):
177
      raise TypeError("QmpMessage must be initialized with a dict")
178

    
179
    self.data = data
180

    
181
  def __getitem__(self, field_name):
182
    """Get the value of the required field if present, or None.
183

184
    Overrides the [] operator to provide access to the message data,
185
    returning None if the required item is not in the message
186
    @return: the value of the field_name field, or None if field_name
187
             is not contained in the message
188

189
    """
190
    return self.data.get(field_name, None)
191

    
192
  def __setitem__(self, field_name, field_value):
193
    """Set the value of the required field_name to field_value.
194

195
    """
196
    self.data[field_name] = field_value
197

    
198
  def __len__(self):
199
    """Return the number of fields stored in this QmpMessage.
200

201
    """
202
    return len(self.data)
203

    
204
  def __delitem__(self, key):
205
    """Delete the specified element from the QmpMessage.
206

207
    """
208
    del(self.data[key])
209

    
210
  @staticmethod
211
  def BuildFromJsonString(json_string):
212
    """Build a QmpMessage from a JSON encoded string.
213

214
    @type json_string: str
215
    @param json_string: JSON string representing the message
216
    @rtype: L{QmpMessage}
217
    @return: a L{QmpMessage} built from json_string
218

219
    """
220
    # Parse the string
221
    data = serializer.LoadJson(json_string)
222
    return QmpMessage(data)
223

    
224
  def __str__(self):
225
    # The protocol expects the JSON object to be sent as a single line.
226
    return serializer.DumpJson(self.data)
227

    
228
  def __eq__(self, other):
229
    # When comparing two QmpMessages, we are interested in comparing
230
    # their internal representation of the message data
231
    return self.data == other.data
232

    
233

    
234
class QmpConnection:
235
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
236

237
  """
238
  _FIRST_MESSAGE_KEY = "QMP"
239
  _EVENT_KEY = "event"
240
  _ERROR_KEY = "error"
241
  _RETURN_KEY = RETURN_KEY = "return"
242
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
243
  _ERROR_CLASS_KEY = "class"
244
  _ERROR_DESC_KEY = "desc"
245
  _EXECUTE_KEY = "execute"
246
  _ARGUMENTS_KEY = "arguments"
247
  _CAPABILITIES_COMMAND = "qmp_capabilities"
248
  _MESSAGE_END_TOKEN = "\r\n"
249
  _SOCKET_TIMEOUT = 5
250

    
251
  def __init__(self, monitor_filename):
252
    """Instantiates the QmpConnection object.
253

254
    @type monitor_filename: string
255
    @param monitor_filename: the filename of the UNIX raw socket on which the
256
                             QMP monitor is listening
257

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

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

    
280
  def _check_connection(self):
281
    """Make sure that the connection is established.
282

283
    """
284
    if not self._connected:
285
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
286
                                   " invoke connect() on it")
287

    
288
  def connect(self):
289
    """Connects to the QMP monitor.
290

291
    Connects to the UNIX socket and makes sure that we can actually send and
292
    receive data to the kvm instance via QMP.
293

294
    @raise errors.HypervisorError: when there are communication errors
295
    @raise errors.ProgrammerError: when there are data serialization errors
296

297
    """
298
    if self._connected:
299
      raise errors.ProgrammerError("Cannot connect twice")
300

    
301
    self._check_socket()
302

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

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

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

    
323
  def _ParseMessage(self, buf):
324
    """Extract and parse a QMP message from the given buffer.
325

326
    Seeks for a QMP message in the given buf. If found, it parses it and
327
    returns it together with the rest of the characters in the buf.
328
    If no message is found, returns None and the whole buffer.
329

330
    @raise errors.ProgrammerError: when there are data serialization errors
331

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

    
344
    return (message, buf)
345

    
346
  def _Recv(self):
347
    """Receives a message from QMP and decodes the received JSON object.
348

349
    @rtype: QmpMessage
350
    @return: the received message
351
    @raise errors.HypervisorError: when there are communication errors
352
    @raise errors.ProgrammerError: when there are data serialization errors
353

354
    """
355
    self._check_connection()
356

    
357
    # Check if there is already a message in the buffer
358
    (message, self._buf) = self._ParseMessage(self._buf)
359
    if message:
360
      return message
361

    
362
    recv_buffer = StringIO.StringIO(self._buf)
363
    recv_buffer.seek(len(self._buf))
364
    try:
365
      while True:
366
        data = self.sock.recv(4096)
367
        if not data:
368
          break
369
        recv_buffer.write(data)
370

    
371
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
372
        if message:
373
          return message
374

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

    
382
  def _Send(self, message):
383
    """Encodes and sends a message to KVM using QMP.
384

385
    @type message: QmpMessage
386
    @param message: message to send to KVM
387
    @raise errors.HypervisorError: when there are communication errors
388
    @raise errors.ProgrammerError: when there are data serialization errors
389

390
    """
391
    self._check_connection()
392
    try:
393
      message_str = str(message)
394
    except Exception, err:
395
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
396

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

    
406
  def Execute(self, command, arguments=None):
407
    """Executes a QMP command and returns the response of the server.
408

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

418
    """
419
    self._check_connection()
420
    message = QmpMessage({self._EXECUTE_KEY: command})
421
    if arguments:
422
      message[self._ARGUMENTS_KEY] = arguments
423
    self._Send(message)
424

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

    
437
      elif not response[self._EVENT_KEY]:
438
        return response
439

    
440

    
441
class KVMHypervisor(hv_base.BaseHypervisor):
442
  """KVM hypervisor interface
443

444
  """
445
  CAN_MIGRATE = True
446

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

    
465
  PARAMETERS = {
466
    constants.HV_KVM_PATH: hv_base.REQ_FILE_CHECK,
467
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
468
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
469
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
470
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
471
    constants.HV_ACPI: hv_base.NO_CHECK,
472
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
473
    constants.HV_SERIAL_SPEED: hv_base.NO_CHECK,
474
    constants.HV_VNC_BIND_ADDRESS: hv_base.NO_CHECK, # will be checked later
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
    constants.HV_VNET_HDR: hv_base.NO_CHECK,
544
    }
545

    
546
  _VIRTIO = "virtio"
547
  _VIRTIO_NET_PCI = "virtio-net-pci"
548

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

    
556
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
557
  _MIGRATION_INFO_RETRY_DELAY = 2
558

    
559
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
560

    
561
  _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
562
  _CPU_INFO_CMD = "info cpus"
563
  _CONT_CMD = "cont"
564

    
565
  _DEFAULT_MACHINE_VERSION_RE = re.compile(r"^(\S+).*\(default\)", re.M)
566
  _CHECK_MACHINE_VERSION_RE = \
567
    staticmethod(lambda x: re.compile(r"^(%s)[ ]+.*PC" % x, re.M))
568

    
569
  _QMP_RE = re.compile(r"^-qmp\s", re.M)
570
  _SPICE_RE = re.compile(r"^-spice\s", re.M)
571
  _VHOST_RE = re.compile(r"^-net\s.*,vhost=on|off", re.M)
572
  _ENABLE_KVM_RE = re.compile(r"^-enable-kvm\s", re.M)
573
  _DISABLE_KVM_RE = re.compile(r"^-disable-kvm\s", re.M)
574
  _NETDEV_RE = re.compile(r"^-netdev\s", re.M)
575
  _DISPLAY_RE = re.compile(r"^-display\s", re.M)
576
  _MACHINE_RE = re.compile(r"^-machine\s", re.M)
577
  _NEW_VIRTIO_RE = re.compile(r"^name \"%s\"" % _VIRTIO_NET_PCI, re.M)
578
  # match  -drive.*boot=on|off on different lines, but in between accept only
579
  # dashes not preceeded by a new line (which would mean another option
580
  # different than -drive is starting)
581
  _BOOT_RE = re.compile(r"^-drive\s([^-]|(?<!^)-)*,boot=on\|off", re.M | re.S)
582
  _UUID_RE = re.compile(r"^-uuid\s", re.M)
583

    
584
  ANCILLARY_FILES = [
585
    _KVM_NETWORK_SCRIPT,
586
    ]
587
  ANCILLARY_FILES_OPT = [
588
    _KVM_NETWORK_SCRIPT,
589
    ]
590

    
591
  # Supported kvm options to get output from
592
  _KVMOPT_HELP = "help"
593
  _KVMOPT_MLIST = "mlist"
594
  _KVMOPT_DEVICELIST = "devicelist"
595

    
596
  # Command to execute to get the output from kvm, and whether to
597
  # accept the output even on failure.
598
  _KVMOPTS_CMDS = {
599
    _KVMOPT_HELP: (["--help"], False),
600
    _KVMOPT_MLIST: (["-M", "?"], False),
601
    _KVMOPT_DEVICELIST: (["-device", "?"], True),
602
  }
603

    
604
  def __init__(self):
605
    hv_base.BaseHypervisor.__init__(self)
606
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
607
    # in a tmpfs filesystem or has been otherwise wiped out.
608
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
609
    utils.EnsureDirs(dirs)
610

    
611
  @classmethod
612
  def _InstancePidFile(cls, instance_name):
613
    """Returns the instance pidfile.
614

615
    """
616
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
617

    
618
  @classmethod
619
  def _InstanceUidFile(cls, instance_name):
620
    """Returns the instance uidfile.
621

622
    """
623
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
624

    
625
  @classmethod
626
  def _InstancePidInfo(cls, pid):
627
    """Check pid file for instance information.
628

629
    Check that a pid file is associated with an instance, and retrieve
630
    information from its command line.
631

632
    @type pid: string or int
633
    @param pid: process id of the instance to check
634
    @rtype: tuple
635
    @return: (instance_name, memory, vcpus)
636
    @raise errors.HypervisorError: when an instance cannot be found
637

638
    """
639
    alive = utils.IsProcessAlive(pid)
640
    if not alive:
641
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
642

    
643
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
644
    try:
645
      cmdline = utils.ReadFile(cmdline_file)
646
    except EnvironmentError, err:
647
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
648
                                   (pid, err))
649

    
650
    instance = None
651
    memory = 0
652
    vcpus = 0
653

    
654
    arg_list = cmdline.split("\x00")
655
    while arg_list:
656
      arg = arg_list.pop(0)
657
      if arg == "-name":
658
        instance = arg_list.pop(0)
659
      elif arg == "-m":
660
        memory = int(arg_list.pop(0))
661
      elif arg == "-smp":
662
        vcpus = int(arg_list.pop(0).split(",")[0])
663

    
664
    if instance is None:
665
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
666
                                   " instance" % pid)
667

    
668
    return (instance, memory, vcpus)
669

    
670
  def _InstancePidAlive(self, instance_name):
671
    """Returns the instance pidfile, pid, and liveness.
672

673
    @type instance_name: string
674
    @param instance_name: instance name
675
    @rtype: tuple
676
    @return: (pid file name, pid, liveness)
677

678
    """
679
    pidfile = self._InstancePidFile(instance_name)
680
    pid = utils.ReadPidFile(pidfile)
681

    
682
    alive = False
683
    try:
684
      cmd_instance = self._InstancePidInfo(pid)[0]
685
      alive = (cmd_instance == instance_name)
686
    except errors.HypervisorError:
687
      pass
688

    
689
    return (pidfile, pid, alive)
690

    
691
  def _CheckDown(self, instance_name):
692
    """Raises an error unless the given instance is down.
693

694
    """
695
    alive = self._InstancePidAlive(instance_name)[2]
696
    if alive:
697
      raise errors.HypervisorError("Failed to start instance %s: %s" %
698
                                   (instance_name, "already running"))
699

    
700
  @classmethod
701
  def _InstanceMonitor(cls, instance_name):
702
    """Returns the instance monitor socket name
703

704
    """
705
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
706

    
707
  @classmethod
708
  def _InstanceSerial(cls, instance_name):
709
    """Returns the instance serial socket name
710

711
    """
712
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
713

    
714
  @classmethod
715
  def _InstanceQmpMonitor(cls, instance_name):
716
    """Returns the instance serial QMP socket name
717

718
    """
719
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
720

    
721
  @staticmethod
722
  def _SocatUnixConsoleParams():
723
    """Returns the correct parameters for socat
724

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

727
    """
728
    if constants.SOCAT_USE_ESCAPE:
729
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
730
    else:
731
      return "echo=0,icanon=0"
732

    
733
  @classmethod
734
  def _InstanceKVMRuntime(cls, instance_name):
735
    """Returns the instance KVM runtime filename
736

737
    """
738
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
739

    
740
  @classmethod
741
  def _InstanceChrootDir(cls, instance_name):
742
    """Returns the name of the KVM chroot dir of the instance
743

744
    """
745
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
746

    
747
  @classmethod
748
  def _InstanceNICDir(cls, instance_name):
749
    """Returns the name of the directory holding the tap device files for a
750
    given instance.
751

752
    """
753
    return utils.PathJoin(cls._NICS_DIR, instance_name)
754

    
755
  @classmethod
756
  def _InstanceNICFile(cls, instance_name, seq):
757
    """Returns the name of the file containing the tap device for a given NIC
758

759
    """
760
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
761

    
762
  @classmethod
763
  def _InstanceKeymapFile(cls, instance_name):
764
    """Returns the name of the file containing the keymap for a given instance
765

766
    """
767
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
768

    
769
  @classmethod
770
  def _TryReadUidFile(cls, uid_file):
771
    """Try to read a uid file
772

773
    """
774
    if os.path.exists(uid_file):
775
      try:
776
        uid = int(utils.ReadOneLineFile(uid_file))
777
        return uid
778
      except EnvironmentError:
779
        logging.warning("Can't read uid file", exc_info=True)
780
      except (TypeError, ValueError):
781
        logging.warning("Can't parse uid file contents", exc_info=True)
782
    return None
783

    
784
  @classmethod
785
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
786
    """Removes an instance's rutime sockets/files/dirs.
787

788
    """
789
    utils.RemoveFile(pidfile)
790
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
791
    utils.RemoveFile(cls._InstanceSerial(instance_name))
792
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
793
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
794
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
795
    uid_file = cls._InstanceUidFile(instance_name)
796
    uid = cls._TryReadUidFile(uid_file)
797
    utils.RemoveFile(uid_file)
798
    if uid is not None:
799
      uidpool.ReleaseUid(uid)
800
    try:
801
      shutil.rmtree(cls._InstanceNICDir(instance_name))
802
    except OSError, err:
803
      if err.errno != errno.ENOENT:
804
        raise
805
    try:
806
      chroot_dir = cls._InstanceChrootDir(instance_name)
807
      utils.RemoveDir(chroot_dir)
808
    except OSError, err:
809
      if err.errno == errno.ENOTEMPTY:
810
        # The chroot directory is expected to be empty, but it isn't.
811
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
812
                                          prefix="%s-%s-" %
813
                                          (instance_name,
814
                                           utils.TimestampForFilename()))
815
        logging.warning("The chroot directory of instance %s can not be"
816
                        " removed as it is not empty. Moving it to the"
817
                        " quarantine instead. Please investigate the"
818
                        " contents (%s) and clean up manually",
819
                        instance_name, new_chroot_dir)
820
        utils.RenameFile(chroot_dir, new_chroot_dir)
821
      else:
822
        raise
823

    
824
  @staticmethod
825
  def _ConfigureNIC(instance, seq, nic, tap):
826
    """Run the network configuration script for a specified NIC
827

828
    @param instance: instance we're acting on
829
    @type instance: instance object
830
    @param seq: nic sequence number
831
    @type seq: int
832
    @param nic: nic we're acting on
833
    @type nic: nic object
834
    @param tap: the host's tap interface this NIC corresponds to
835
    @type tap: str
836

837
    """
838
    if instance.tags:
839
      tags = " ".join(instance.tags)
840
    else:
841
      tags = ""
842

    
843
    env = {
844
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
845
      "INSTANCE": instance.name,
846
      "MAC": nic.mac,
847
      "MODE": nic.nicparams[constants.NIC_MODE],
848
      "INTERFACE": tap,
849
      "INTERFACE_INDEX": str(seq),
850
      "TAGS": tags,
851
    }
852

    
853
    if nic.ip:
854
      env["IP"] = nic.ip
855

    
856
    if nic.nicparams[constants.NIC_LINK]:
857
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
858

    
859
    if nic.network:
860
      n = objects.Network.FromDict(nic.netinfo)
861
      env.update(n.HooksDict())
862

    
863
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
864
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
865

    
866
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
867
    if result.failed:
868
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
869
                                   " network configuration script output: %s" %
870
                                   (tap, result.fail_reason, result.output))
871

    
872
  @staticmethod
873
  def _VerifyAffinityPackage():
874
    if affinity is None:
875
      raise errors.HypervisorError("affinity Python package not"
876
                                   " found; cannot use CPU pinning under KVM")
877

    
878
  @staticmethod
879
  def _BuildAffinityCpuMask(cpu_list):
880
    """Create a CPU mask suitable for sched_setaffinity from a list of
881
    CPUs.
882

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

886
    @type cpu_list: list of int
887
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
888
    @rtype: int
889
    @return: a bit mask of CPU affinities
890

891
    """
892
    if cpu_list == constants.CPU_PINNING_OFF:
893
      return constants.CPU_PINNING_ALL_KVM
894
    else:
895
      return sum(2 ** cpu for cpu in cpu_list)
896

    
897
  @classmethod
898
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
899
    """Change CPU affinity for running VM according to given CPU mask.
900

901
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
902
    @type cpu_mask: string
903
    @param process_id: process ID of KVM process. Used to pin entire VM
904
                       to physical CPUs.
905
    @type process_id: int
906
    @param thread_dict: map of virtual CPUs to KVM thread IDs
907
    @type thread_dict: dict int:int
908

909
    """
910
    # Convert the string CPU mask to a list of list of int's
911
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
912

    
913
    if len(cpu_list) == 1:
914
      all_cpu_mapping = cpu_list[0]
915
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
916
        # If CPU pinning has 1 entry that's "all", then do nothing
917
        pass
918
      else:
919
        # If CPU pinning has one non-all entry, map the entire VM to
920
        # one set of physical CPUs
921
        cls._VerifyAffinityPackage()
922
        affinity.set_process_affinity_mask(
923
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
924
    else:
925
      # The number of vCPUs mapped should match the number of vCPUs
926
      # reported by KVM. This was already verified earlier, so
927
      # here only as a sanity check.
928
      assert len(thread_dict) == len(cpu_list)
929
      cls._VerifyAffinityPackage()
930

    
931
      # For each vCPU, map it to the proper list of physical CPUs
932
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
933
        affinity.set_process_affinity_mask(thread_dict[i],
934
                                           cls._BuildAffinityCpuMask(vcpu))
935

    
936
  def _GetVcpuThreadIds(self, instance_name):
937
    """Get a mapping of vCPU no. to thread IDs for the instance
938

939
    @type instance_name: string
940
    @param instance_name: instance in question
941
    @rtype: dictionary of int:int
942
    @return: a dictionary mapping vCPU numbers to thread IDs
943

944
    """
945
    result = {}
946
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
947
    for line in output.stdout.splitlines():
948
      match = self._CPU_INFO_RE.search(line)
949
      if not match:
950
        continue
951
      grp = map(int, match.groups())
952
      result[grp[0]] = grp[1]
953

    
954
    return result
955

    
956
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
957
    """Complete CPU pinning.
958

959
    @type instance_name: string
960
    @param instance_name: name of instance
961
    @type cpu_mask: string
962
    @param cpu_mask: CPU pinning mask as entered by user
963

964
    """
965
    # Get KVM process ID, to be used if need to pin entire VM
966
    _, pid, _ = self._InstancePidAlive(instance_name)
967
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
968
    thread_dict = self._GetVcpuThreadIds(instance_name)
969
    # Run CPU pinning, based on configured mask
970
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
971

    
972
  def ListInstances(self, hvparams=None):
973
    """Get the list of running instances.
974

975
    We can do this by listing our live instances directory and
976
    checking whether the associated kvm process is still alive.
977

978
    """
979
    result = []
980
    for name in os.listdir(self._PIDS_DIR):
981
      if self._InstancePidAlive(name)[2]:
982
        result.append(name)
983
    return result
984

    
985
  def GetInstanceInfo(self, instance_name, hvparams=None):
986
    """Get instance properties.
987

988
    @type instance_name: string
989
    @param instance_name: the instance name
990
    @type hvparams: dict of strings
991
    @param hvparams: hvparams to be used with this instance
992
    @rtype: tuple of strings
993
    @return: (name, id, memory, vcpus, stat, times)
994

995
    """
996
    _, pid, alive = self._InstancePidAlive(instance_name)
997
    if not alive:
998
      return None
999

    
1000
    _, memory, vcpus = self._InstancePidInfo(pid)
1001
    istat = "---b-"
1002
    times = "0"
1003

    
1004
    try:
1005
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1006
      qmp.connect()
1007
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1008
      # Will fail if ballooning is not enabled, but we can then just resort to
1009
      # the value above.
1010
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1011
      memory = mem_bytes / 1048576
1012
    except errors.HypervisorError:
1013
      pass
1014

    
1015
    return (instance_name, pid, memory, vcpus, istat, times)
1016

    
1017
  def GetAllInstancesInfo(self, hvparams=None):
1018
    """Get properties of all instances.
1019

1020
    @type hvparams: dict of strings
1021
    @param hvparams: hypervisor parameter
1022
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1023

1024
    """
1025
    data = []
1026
    for name in os.listdir(self._PIDS_DIR):
1027
      try:
1028
        info = self.GetInstanceInfo(name)
1029
      except errors.HypervisorError:
1030
        # Ignore exceptions due to instances being shut down
1031
        continue
1032
      if info:
1033
        data.append(info)
1034
    return data
1035

    
1036
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1037
                          kvmhelp):
1038
    """Generate KVM information to start an instance.
1039

1040
    @type kvmhelp: string
1041
    @param kvmhelp: output of kvm --help
1042
    @attention: this function must not have any side-effects; for
1043
        example, it must not write to the filesystem, or read values
1044
        from the current system the are expected to differ between
1045
        nodes, since it is only run once at instance startup;
1046
        actions/kvm arguments that can vary between systems should be
1047
        done in L{_ExecuteKVMRuntime}
1048

1049
    """
1050
    # pylint: disable=R0912,R0914,R0915
1051
    hvp = instance.hvparams
1052
    self.ValidateParameters(hvp)
1053

    
1054
    pidfile = self._InstancePidFile(instance.name)
1055
    kvm = hvp[constants.HV_KVM_PATH]
1056
    kvm_cmd = [kvm]
1057
    # used just by the vnc server, if enabled
1058
    kvm_cmd.extend(["-name", instance.name])
1059
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1060

    
1061
    smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1062
    if hvp[constants.HV_CPU_CORES]:
1063
      smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1064
    if hvp[constants.HV_CPU_THREADS]:
1065
      smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1066
    if hvp[constants.HV_CPU_SOCKETS]:
1067
      smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1068

    
1069
    kvm_cmd.extend(["-smp", ",".join(smp_list)])
1070

    
1071
    kvm_cmd.extend(["-pidfile", pidfile])
1072
    kvm_cmd.extend(["-balloon", "virtio"])
1073
    kvm_cmd.extend(["-daemonize"])
1074
    if not instance.hvparams[constants.HV_ACPI]:
1075
      kvm_cmd.extend(["-no-acpi"])
1076
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1077
        constants.INSTANCE_REBOOT_EXIT:
1078
      kvm_cmd.extend(["-no-reboot"])
1079

    
1080
    mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1081
    if not mversion:
1082
      mversion = self._GetDefaultMachineVersion(kvm)
1083
    if self._MACHINE_RE.search(kvmhelp):
1084
      # TODO (2.8): kernel_irqchip and kvm_shadow_mem machine properties, as
1085
      # extra hypervisor parameters. We should also investigate whether and how
1086
      # shadow_mem should be considered for the resource model.
1087
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED):
1088
        specprop = ",accel=kvm"
1089
      else:
1090
        specprop = ""
1091
      machinespec = "%s%s" % (mversion, specprop)
1092
      kvm_cmd.extend(["-machine", machinespec])
1093
    else:
1094
      kvm_cmd.extend(["-M", mversion])
1095
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1096
          self._ENABLE_KVM_RE.search(kvmhelp)):
1097
        kvm_cmd.extend(["-enable-kvm"])
1098
      elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1099
            self._DISABLE_KVM_RE.search(kvmhelp)):
1100
        kvm_cmd.extend(["-disable-kvm"])
1101

    
1102
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1103
    if kernel_path:
1104
      boot_disk = boot_cdrom = boot_floppy = boot_network = False
1105
    else:
1106
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1107
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1108
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1109
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1110

    
1111
    if startup_paused:
1112
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1113

    
1114
    if boot_network:
1115
      kvm_cmd.extend(["-boot", "n"])
1116

    
1117
    # whether this is an older KVM version that uses the boot=on flag
1118
    # on devices
1119
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1120

    
1121
    disk_type = hvp[constants.HV_DISK_TYPE]
1122
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1123
      if_val = ",if=virtio"
1124
    else:
1125
      if_val = ",if=%s" % disk_type
1126
    # Cache mode
1127
    disk_cache = hvp[constants.HV_DISK_CACHE]
1128
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1129
      if disk_cache != "none":
1130
        # TODO: make this a hard error, instead of a silent overwrite
1131
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1132
                        " to prevent shared storage corruption on migration",
1133
                        disk_cache)
1134
      cache_val = ",cache=none"
1135
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1136
      cache_val = ",cache=%s" % disk_cache
1137
    else:
1138
      cache_val = ""
1139
    for cfdev, dev_path in block_devices:
1140
      if cfdev.mode != constants.DISK_RDWR:
1141
        raise errors.HypervisorError("Instance has read-only disks which"
1142
                                     " are not supported by KVM")
1143
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1144
      boot_val = ""
1145
      if boot_disk:
1146
        kvm_cmd.extend(["-boot", "c"])
1147
        boot_disk = False
1148
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1149
          boot_val = ",boot=on"
1150

    
1151
      drive_val = "file=%s,format=raw%s%s%s" % (dev_path, if_val, boot_val,
1152
                                                cache_val)
1153
      kvm_cmd.extend(["-drive", drive_val])
1154

    
1155
    #Now we can specify a different device type for CDROM devices.
1156
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1157
    if not cdrom_disk_type:
1158
      cdrom_disk_type = disk_type
1159

    
1160
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1161
    if iso_image:
1162
      options = ",format=raw,media=cdrom"
1163
      # set cdrom 'if' type
1164
      if boot_cdrom:
1165
        actual_cdrom_type = constants.HT_DISK_IDE
1166
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1167
        actual_cdrom_type = "virtio"
1168
      else:
1169
        actual_cdrom_type = cdrom_disk_type
1170
      if_val = ",if=%s" % actual_cdrom_type
1171
      # set boot flag, if needed
1172
      boot_val = ""
1173
      if boot_cdrom:
1174
        kvm_cmd.extend(["-boot", "d"])
1175
        if needs_boot_flag:
1176
          boot_val = ",boot=on"
1177
      # and finally build the entire '-drive' value
1178
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1179
      kvm_cmd.extend(["-drive", drive_val])
1180

    
1181
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1182
    if iso_image2:
1183
      options = ",format=raw,media=cdrom"
1184
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1185
        if_val = ",if=virtio"
1186
      else:
1187
        if_val = ",if=%s" % cdrom_disk_type
1188
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1189
      kvm_cmd.extend(["-drive", drive_val])
1190

    
1191
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1192
    if floppy_image:
1193
      options = ",format=raw,media=disk"
1194
      if boot_floppy:
1195
        kvm_cmd.extend(["-boot", "a"])
1196
        options = "%s,boot=on" % options
1197
      if_val = ",if=floppy"
1198
      options = "%s%s" % (options, if_val)
1199
      drive_val = "file=%s%s" % (floppy_image, options)
1200
      kvm_cmd.extend(["-drive", drive_val])
1201

    
1202
    if kernel_path:
1203
      kvm_cmd.extend(["-kernel", kernel_path])
1204
      initrd_path = hvp[constants.HV_INITRD_PATH]
1205
      if initrd_path:
1206
        kvm_cmd.extend(["-initrd", initrd_path])
1207
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1208
                     hvp[constants.HV_KERNEL_ARGS]]
1209
      if hvp[constants.HV_SERIAL_CONSOLE]:
1210
        serial_speed = hvp[constants.HV_SERIAL_SPEED]
1211
        root_append.append("console=ttyS0,%s" % serial_speed)
1212
      kvm_cmd.extend(["-append", " ".join(root_append)])
1213

    
1214
    mem_path = hvp[constants.HV_MEM_PATH]
1215
    if mem_path:
1216
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1217

    
1218
    monitor_dev = ("unix:%s,server,nowait" %
1219
                   self._InstanceMonitor(instance.name))
1220
    kvm_cmd.extend(["-monitor", monitor_dev])
1221
    if hvp[constants.HV_SERIAL_CONSOLE]:
1222
      serial_dev = ("unix:%s,server,nowait" %
1223
                    self._InstanceSerial(instance.name))
1224
      kvm_cmd.extend(["-serial", serial_dev])
1225
    else:
1226
      kvm_cmd.extend(["-serial", "none"])
1227

    
1228
    mouse_type = hvp[constants.HV_USB_MOUSE]
1229
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1230
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1231
    spice_ip_version = None
1232

    
1233
    kvm_cmd.extend(["-usb"])
1234

    
1235
    if mouse_type:
1236
      kvm_cmd.extend(["-usbdevice", mouse_type])
1237
    elif vnc_bind_address:
1238
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1239

    
1240
    if vnc_bind_address:
1241
      if netutils.IsValidInterface(vnc_bind_address):
1242
        if_addresses = netutils.GetInterfaceIpAddresses(vnc_bind_address)
1243
        if_ip4_addresses = if_addresses[constants.IP4_VERSION]
1244
        if len(if_ip4_addresses) < 1:
1245
          logging.error("Could not determine IPv4 address of interface %s",
1246
                        vnc_bind_address)
1247
        else:
1248
          vnc_bind_address = if_ip4_addresses[0]
1249
      if netutils.IP4Address.IsValid(vnc_bind_address):
1250
        if instance.network_port > constants.VNC_BASE_PORT:
1251
          display = instance.network_port - constants.VNC_BASE_PORT
1252
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1253
            vnc_arg = ":%d" % (display)
1254
          else:
1255
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1256
        else:
1257
          logging.error("Network port is not a valid VNC display (%d < %d),"
1258
                        " not starting VNC",
1259
                        instance.network_port, constants.VNC_BASE_PORT)
1260
          vnc_arg = "none"
1261

    
1262
        # Only allow tls and other option when not binding to a file, for now.
1263
        # kvm/qemu gets confused otherwise about the filename to use.
1264
        vnc_append = ""
1265
        if hvp[constants.HV_VNC_TLS]:
1266
          vnc_append = "%s,tls" % vnc_append
1267
          if hvp[constants.HV_VNC_X509_VERIFY]:
1268
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1269
                                               hvp[constants.HV_VNC_X509])
1270
          elif hvp[constants.HV_VNC_X509]:
1271
            vnc_append = "%s,x509=%s" % (vnc_append,
1272
                                         hvp[constants.HV_VNC_X509])
1273
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1274
          vnc_append = "%s,password" % vnc_append
1275

    
1276
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1277

    
1278
      else:
1279
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1280

    
1281
      kvm_cmd.extend(["-vnc", vnc_arg])
1282
    elif spice_bind:
1283
      # FIXME: this is wrong here; the iface ip address differs
1284
      # between systems, so it should be done in _ExecuteKVMRuntime
1285
      if netutils.IsValidInterface(spice_bind):
1286
        # The user specified a network interface, we have to figure out the IP
1287
        # address.
1288
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1289
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1290

    
1291
        # if the user specified an IP version and the interface does not
1292
        # have that kind of IP addresses, throw an exception
1293
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1294
          if not addresses[spice_ip_version]:
1295
            raise errors.HypervisorError("SPICE: Unable to get an IPv%s address"
1296
                                         " for %s" % (spice_ip_version,
1297
                                                      spice_bind))
1298

    
1299
        # the user did not specify an IP version, we have to figure it out
1300
        elif (addresses[constants.IP4_VERSION] and
1301
              addresses[constants.IP6_VERSION]):
1302
          # we have both ipv4 and ipv6, let's use the cluster default IP
1303
          # version
1304
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1305
          spice_ip_version = \
1306
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1307
        elif addresses[constants.IP4_VERSION]:
1308
          spice_ip_version = constants.IP4_VERSION
1309
        elif addresses[constants.IP6_VERSION]:
1310
          spice_ip_version = constants.IP6_VERSION
1311
        else:
1312
          raise errors.HypervisorError("SPICE: Unable to get an IP address"
1313
                                       " for %s" % (spice_bind))
1314

    
1315
        spice_address = addresses[spice_ip_version][0]
1316

    
1317
      else:
1318
        # spice_bind is known to be a valid IP address, because
1319
        # ValidateParameters checked it.
1320
        spice_address = spice_bind
1321

    
1322
      spice_arg = "addr=%s" % spice_address
1323
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1324
        spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1325
                     (spice_arg, instance.network_port,
1326
                      pathutils.SPICE_CACERT_FILE))
1327
        spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1328
                     (spice_arg, pathutils.SPICE_CERT_FILE,
1329
                      pathutils.SPICE_CERT_FILE))
1330
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1331
        if tls_ciphers:
1332
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1333
      else:
1334
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1335

    
1336
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1337
        spice_arg = "%s,disable-ticketing" % spice_arg
1338

    
1339
      if spice_ip_version:
1340
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1341

    
1342
      # Image compression options
1343
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1344
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1345
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1346
      if img_lossless:
1347
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1348
      if img_jpeg:
1349
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1350
      if img_zlib_glz:
1351
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1352

    
1353
      # Video stream detection
1354
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1355
      if video_streaming:
1356
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1357

    
1358
      # Audio compression, by default in qemu-kvm it is on
1359
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1360
        spice_arg = "%s,playback-compression=off" % spice_arg
1361
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1362
        spice_arg = "%s,agent-mouse=off" % spice_arg
1363
      else:
1364
        # Enable the spice agent communication channel between the host and the
1365
        # agent.
1366
        kvm_cmd.extend(["-device", "virtio-serial-pci"])
1367
        kvm_cmd.extend([
1368
          "-device",
1369
          "virtserialport,chardev=spicechannel0,name=com.redhat.spice.0",
1370
          ])
1371
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1372

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

    
1376
    else:
1377
      # From qemu 1.4 -nographic is incompatible with -daemonize. The new way
1378
      # also works in earlier versions though (tested with 1.1 and 1.3)
1379
      if self._DISPLAY_RE.search(kvmhelp):
1380
        kvm_cmd.extend(["-display", "none"])
1381
      else:
1382
        kvm_cmd.extend(["-nographic"])
1383

    
1384
    if hvp[constants.HV_USE_LOCALTIME]:
1385
      kvm_cmd.extend(["-localtime"])
1386

    
1387
    if hvp[constants.HV_KVM_USE_CHROOT]:
1388
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1389

    
1390
    # Add qemu-KVM -cpu param
1391
    if hvp[constants.HV_CPU_TYPE]:
1392
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1393

    
1394
    # As requested by music lovers
1395
    if hvp[constants.HV_SOUNDHW]:
1396
      kvm_cmd.extend(["-soundhw", hvp[constants.HV_SOUNDHW]])
1397

    
1398
    # Pass a -vga option if requested, or if spice is used, for backwards
1399
    # compatibility.
1400
    if hvp[constants.HV_VGA]:
1401
      kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1402
    elif spice_bind:
1403
      kvm_cmd.extend(["-vga", "qxl"])
1404

    
1405
    # Various types of usb devices, comma separated
1406
    if hvp[constants.HV_USB_DEVICES]:
1407
      for dev in hvp[constants.HV_USB_DEVICES].split(","):
1408
        kvm_cmd.extend(["-usbdevice", dev])
1409

    
1410
    # Set system UUID to instance UUID
1411
    if self._UUID_RE.search(kvmhelp):
1412
      kvm_cmd.extend(["-uuid", instance.uuid])
1413

    
1414
    if hvp[constants.HV_KVM_EXTRA]:
1415
      kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
1416

    
1417
    # Save the current instance nics, but defer their expansion as parameters,
1418
    # as we'll need to generate executable temp files for them.
1419
    kvm_nics = instance.nics
1420
    hvparams = hvp
1421

    
1422
    return (kvm_cmd, kvm_nics, hvparams)
1423

    
1424
  def _WriteKVMRuntime(self, instance_name, data):
1425
    """Write an instance's KVM runtime
1426

1427
    """
1428
    try:
1429
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1430
                      data=data)
1431
    except EnvironmentError, err:
1432
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1433

    
1434
  def _ReadKVMRuntime(self, instance_name):
1435
    """Read an instance's KVM runtime
1436

1437
    """
1438
    try:
1439
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1440
    except EnvironmentError, err:
1441
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1442
    return file_content
1443

    
1444
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1445
    """Save an instance's KVM runtime
1446

1447
    """
1448
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1449
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1450
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1451
    self._WriteKVMRuntime(instance.name, serialized_form)
1452

    
1453
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1454
    """Load an instance's KVM runtime
1455

1456
    """
1457
    if not serialized_runtime:
1458
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1459
    loaded_runtime = serializer.Load(serialized_runtime)
1460
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1461
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1462
    return (kvm_cmd, kvm_nics, hvparams)
1463

    
1464
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1465
    """Run the KVM cmd and check for errors
1466

1467
    @type name: string
1468
    @param name: instance name
1469
    @type kvm_cmd: list of strings
1470
    @param kvm_cmd: runcmd input for kvm
1471
    @type tap_fds: list of int
1472
    @param tap_fds: fds of tap devices opened by Ganeti
1473

1474
    """
1475
    try:
1476
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1477
    finally:
1478
      for fd in tap_fds:
1479
        utils_wrapper.CloseFdNoError(fd)
1480

    
1481
    if result.failed:
1482
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1483
                                   (name, result.fail_reason, result.output))
1484
    if not self._InstancePidAlive(name)[2]:
1485
      raise errors.HypervisorError("Failed to start instance %s" % name)
1486

    
1487
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1488
    """Execute a KVM cmd, after completing it with some last minute data.
1489

1490
    @type incoming: tuple of strings
1491
    @param incoming: (target_host_ip, port)
1492
    @type kvmhelp: string
1493
    @param kvmhelp: output of kvm --help
1494

1495
    """
1496
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1497
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1498
    #    have changed since the instance started; only use them if the change
1499
    #    won't affect the inside of the instance (which hasn't been rebooted).
1500
    #  - up_hvp contains the parameters as they were when the instance was
1501
    #    started, plus any new parameter which has been added between ganeti
1502
    #    versions: it is paramount that those default to a value which won't
1503
    #    affect the inside of the instance as well.
1504
    conf_hvp = instance.hvparams
1505
    name = instance.name
1506
    self._CheckDown(name)
1507

    
1508
    temp_files = []
1509

    
1510
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1511
    # the first element of kvm_cmd is always the path to the kvm binary
1512
    kvm_path = kvm_cmd[0]
1513
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1514

    
1515
    # We know it's safe to run as a different user upon migration, so we'll use
1516
    # the latest conf, from conf_hvp.
1517
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1518
    if security_model == constants.HT_SM_USER:
1519
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1520

    
1521
    keymap = conf_hvp[constants.HV_KEYMAP]
1522
    if keymap:
1523
      keymap_path = self._InstanceKeymapFile(name)
1524
      # If a keymap file is specified, KVM won't use its internal defaults. By
1525
      # first including the "en-us" layout, an error on loading the actual
1526
      # layout (e.g. because it can't be found) won't lead to a non-functional
1527
      # keyboard. A keyboard with incorrect keys is still better than none.
1528
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1529
      kvm_cmd.extend(["-k", keymap_path])
1530

    
1531
    # We have reasons to believe changing something like the nic driver/type
1532
    # upon migration won't exactly fly with the instance kernel, so for nic
1533
    # related parameters we'll use up_hvp
1534
    tapfds = []
1535
    taps = []
1536
    if not kvm_nics:
1537
      kvm_cmd.extend(["-net", "none"])
1538
    else:
1539
      vnet_hdr = False
1540
      tap_extra = ""
1541
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1542
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1543
        nic_model = self._VIRTIO
1544
        try:
1545
          devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1546
          if self._NEW_VIRTIO_RE.search(devlist):
1547
            nic_model = self._VIRTIO_NET_PCI
1548
            vnet_hdr = up_hvp[constants.HV_VNET_HDR]
1549
        except errors.HypervisorError, _:
1550
          # Older versions of kvm don't support DEVICE_LIST, but they don't
1551
          # have new virtio syntax either.
1552
          pass
1553

    
1554
        if up_hvp[constants.HV_VHOST_NET]:
1555
          # check for vhost_net support
1556
          if self._VHOST_RE.search(kvmhelp):
1557
            tap_extra = ",vhost=on"
1558
          else:
1559
            raise errors.HypervisorError("vhost_net is configured"
1560
                                         " but it is not available")
1561
      else:
1562
        nic_model = nic_type
1563

    
1564
      kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
1565

    
1566
      for nic_seq, nic in enumerate(kvm_nics):
1567
        tapname, tapfd = _OpenTap(vnet_hdr=vnet_hdr)
1568
        tapfds.append(tapfd)
1569
        taps.append(tapname)
1570
        if kvm_supports_netdev:
1571
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
1572
          tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
1573
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1574
        else:
1575
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1576
                                                         nic.mac, nic_model)
1577
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1578
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1579

    
1580
    if incoming:
1581
      target, port = incoming
1582
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1583

    
1584
    # Changing the vnc password doesn't bother the guest that much. At most it
1585
    # will surprise people who connect to it. Whether positively or negatively
1586
    # it's debatable.
1587
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1588
    vnc_pwd = None
1589
    if vnc_pwd_file:
1590
      try:
1591
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1592
      except EnvironmentError, err:
1593
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1594
                                     % (vnc_pwd_file, err))
1595

    
1596
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1597
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1598
                         constants.SECURE_DIR_MODE)])
1599

    
1600
    # Automatically enable QMP if version is >= 0.14
1601
    if self._QMP_RE.search(kvmhelp):
1602
      logging.debug("Enabling QMP")
1603
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1604
                      self._InstanceQmpMonitor(instance.name)])
1605

    
1606
    # Configure the network now for starting instances and bridged interfaces,
1607
    # during FinalizeMigration for incoming instances' routed interfaces
1608
    for nic_seq, nic in enumerate(kvm_nics):
1609
      if (incoming and
1610
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1611
        continue
1612
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1613

    
1614
    # CPU affinity requires kvm to start paused, so we set this flag if the
1615
    # instance is not already paused and if we are not going to accept a
1616
    # migrating instance. In the latter case, pausing is not needed.
1617
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1618
    if start_kvm_paused:
1619
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1620

    
1621
    # Note: CPU pinning is using up_hvp since changes take effect
1622
    # during instance startup anyway, and to avoid problems when soft
1623
    # rebooting the instance.
1624
    cpu_pinning = False
1625
    if up_hvp.get(constants.HV_CPU_MASK, None):
1626
      cpu_pinning = True
1627

    
1628
    if security_model == constants.HT_SM_POOL:
1629
      ss = ssconf.SimpleStore()
1630
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1631
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1632
      uid = uidpool.RequestUnusedUid(all_uids)
1633
      try:
1634
        username = pwd.getpwuid(uid.GetUid()).pw_name
1635
        kvm_cmd.extend(["-runas", username])
1636
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1637
      except:
1638
        uidpool.ReleaseUid(uid)
1639
        raise
1640
      else:
1641
        uid.Unlock()
1642
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1643
    else:
1644
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1645

    
1646
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1647
                     constants.RUN_DIRS_MODE)])
1648
    for nic_seq, tap in enumerate(taps):
1649
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1650
                      data=tap)
1651

    
1652
    if vnc_pwd:
1653
      change_cmd = "change vnc password %s" % vnc_pwd
1654
      self._CallMonitorCommand(instance.name, change_cmd)
1655

    
1656
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1657
    # connection attempts because SPICE by default does not allow connections
1658
    # if neither a password nor the "disable_ticketing" options are specified.
1659
    # As soon as we send the password via QMP, that password is a valid ticket
1660
    # for connection.
1661
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1662
    if spice_password_file:
1663
      spice_pwd = ""
1664
      try:
1665
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1666
      except EnvironmentError, err:
1667
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1668
                                     % (spice_password_file, err))
1669

    
1670
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1671
      qmp.connect()
1672
      arguments = {
1673
          "protocol": "spice",
1674
          "password": spice_pwd,
1675
      }
1676
      qmp.Execute("set_password", arguments)
1677

    
1678
    for filename in temp_files:
1679
      utils.RemoveFile(filename)
1680

    
1681
    # If requested, set CPU affinity and resume instance execution
1682
    if cpu_pinning:
1683
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1684

    
1685
    start_memory = self._InstanceStartupMemory(instance)
1686
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1687
      self.BalloonInstanceMemory(instance, start_memory)
1688

    
1689
    if start_kvm_paused:
1690
      # To control CPU pinning, ballooning, and vnc/spice passwords
1691
      # the VM was started in a frozen state. If freezing was not
1692
      # explicitly requested resume the vm status.
1693
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1694

    
1695
  def StartInstance(self, instance, block_devices, startup_paused):
1696
    """Start an instance.
1697

1698
    """
1699
    self._CheckDown(instance.name)
1700
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1701
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1702
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1703
                                           startup_paused, kvmhelp)
1704
    self._SaveKVMRuntime(instance, kvm_runtime)
1705
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1706

    
1707
  def _CallMonitorCommand(self, instance_name, command, timeout=None):
1708
    """Invoke a command on the instance monitor.
1709

1710
    """
1711
    if timeout is not None:
1712
      timeout_cmd = "timeout %s" % (timeout, )
1713
    else:
1714
      timeout_cmd = ""
1715

    
1716
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1717
    # version. The monitor protocol is designed for human consumption, whereas
1718
    # QMP is made for programmatic usage. In the worst case QMP can also
1719
    # execute monitor commands. As it is, all calls to socat take at least
1720
    # 500ms and likely more: socat can't detect the end of the reply and waits
1721
    # for 500ms of no data received before exiting (500 ms is the default for
1722
    # the "-t" parameter).
1723
    socat = ("echo %s | %s %s STDIO UNIX-CONNECT:%s" %
1724
             (utils.ShellQuote(command),
1725
              timeout_cmd,
1726
              constants.SOCAT_PATH,
1727
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1728

    
1729
    result = utils.RunCmd(socat)
1730
    if result.failed:
1731
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1732
             " output: %s" %
1733
             (command, instance_name, result.fail_reason, result.output))
1734
      raise errors.HypervisorError(msg)
1735

    
1736
    return result
1737

    
1738
  @classmethod
1739
  def _ParseKVMVersion(cls, text):
1740
    """Parse the KVM version from the --help output.
1741

1742
    @type text: string
1743
    @param text: output of kvm --help
1744
    @return: (version, v_maj, v_min, v_rev)
1745
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1746

1747
    """
1748
    match = cls._VERSION_RE.search(text.splitlines()[0])
1749
    if not match:
1750
      raise errors.HypervisorError("Unable to get KVM version")
1751

    
1752
    v_all = match.group(0)
1753
    v_maj = int(match.group(1))
1754
    v_min = int(match.group(2))
1755
    if match.group(4):
1756
      v_rev = int(match.group(4))
1757
    else:
1758
      v_rev = 0
1759
    return (v_all, v_maj, v_min, v_rev)
1760

    
1761
  @classmethod
1762
  def _GetKVMOutput(cls, kvm_path, option):
1763
    """Return the output of a kvm invocation
1764

1765
    @type kvm_path: string
1766
    @param kvm_path: path to the kvm executable
1767
    @type option: a key of _KVMOPTS_CMDS
1768
    @param option: kvm option to fetch the output from
1769
    @return: output a supported kvm invocation
1770
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1771

1772
    """
1773
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
1774

    
1775
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
1776

    
1777
    result = utils.RunCmd([kvm_path] + optlist)
1778
    if result.failed and not can_fail:
1779
      raise errors.HypervisorError("Unable to get KVM %s output" %
1780
                                    " ".join(optlist))
1781
    return result.output
1782

    
1783
  @classmethod
1784
  def _GetKVMVersion(cls, kvm_path):
1785
    """Return the installed KVM version.
1786

1787
    @return: (version, v_maj, v_min, v_rev)
1788
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1789

1790
    """
1791
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
1792

    
1793
  @classmethod
1794
  def _GetDefaultMachineVersion(cls, kvm_path):
1795
    """Return the default hardware revision (e.g. pc-1.1)
1796

1797
    """
1798
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
1799
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
1800
    if match:
1801
      return match.group(1)
1802
    else:
1803
      return "pc"
1804

    
1805
  def StopInstance(self, instance, force=False, retry=False, name=None,
1806
                   timeout=None):
1807
    """Stop an instance.
1808

1809
    """
1810
    assert(timeout is None or force is not None)
1811

    
1812
    if name is not None and not force:
1813
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1814
    if name is None:
1815
      name = instance.name
1816
      acpi = instance.hvparams[constants.HV_ACPI]
1817
    else:
1818
      acpi = False
1819
    _, pid, alive = self._InstancePidAlive(name)
1820
    if pid > 0 and alive:
1821
      if force or not acpi:
1822
        utils.KillProcess(pid)
1823
      else:
1824
        self._CallMonitorCommand(name, "system_powerdown", timeout)
1825

    
1826
  def CleanupInstance(self, instance_name):
1827
    """Cleanup after a stopped instance
1828

1829
    """
1830
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1831
    if pid > 0 and alive:
1832
      raise errors.HypervisorError("Cannot cleanup a live instance")
1833
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1834

    
1835
  def RebootInstance(self, instance):
1836
    """Reboot an instance.
1837

1838
    """
1839
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1840
    # socket the instance will stop, but now power up again. So we'll resort
1841
    # to shutdown and restart.
1842
    _, _, alive = self._InstancePidAlive(instance.name)
1843
    if not alive:
1844
      raise errors.HypervisorError("Failed to reboot instance %s:"
1845
                                   " not running" % instance.name)
1846
    # StopInstance will delete the saved KVM runtime so:
1847
    # ...first load it...
1848
    kvm_runtime = self._LoadKVMRuntime(instance)
1849
    # ...now we can safely call StopInstance...
1850
    if not self.StopInstance(instance):
1851
      self.StopInstance(instance, force=True)
1852
    # ...and finally we can save it again, and execute it...
1853
    self._SaveKVMRuntime(instance, kvm_runtime)
1854
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1855
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1856
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1857

    
1858
  def MigrationInfo(self, instance):
1859
    """Get instance information to perform a migration.
1860

1861
    @type instance: L{objects.Instance}
1862
    @param instance: instance to be migrated
1863
    @rtype: string
1864
    @return: content of the KVM runtime file
1865

1866
    """
1867
    return self._ReadKVMRuntime(instance.name)
1868

    
1869
  def AcceptInstance(self, instance, info, target):
1870
    """Prepare to accept an instance.
1871

1872
    @type instance: L{objects.Instance}
1873
    @param instance: instance to be accepted
1874
    @type info: string
1875
    @param info: content of the KVM runtime file on the source node
1876
    @type target: string
1877
    @param target: target host (usually ip), on this node
1878

1879
    """
1880
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1881
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1882
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1883
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1884
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
1885
                            incoming=incoming_address)
1886

    
1887
  def FinalizeMigrationDst(self, instance, info, success):
1888
    """Finalize the instance migration on the target node.
1889

1890
    Stop the incoming mode KVM.
1891

1892
    @type instance: L{objects.Instance}
1893
    @param instance: instance whose migration is being finalized
1894

1895
    """
1896
    if success:
1897
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1898
      kvm_nics = kvm_runtime[1]
1899

    
1900
      for nic_seq, nic in enumerate(kvm_nics):
1901
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1902
          # Bridged interfaces have already been configured
1903
          continue
1904
        try:
1905
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1906
        except EnvironmentError, err:
1907
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1908
                          instance.name, nic_seq, str(err))
1909
          continue
1910
        try:
1911
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1912
        except errors.HypervisorError, err:
1913
          logging.warning(str(err))
1914

    
1915
      self._WriteKVMRuntime(instance.name, info)
1916
    else:
1917
      self.StopInstance(instance, force=True)
1918

    
1919
  def MigrateInstance(self, cluster_name, instance, target, live):
1920
    """Migrate an instance to a target node.
1921

1922
    The migration will not be attempted if the instance is not
1923
    currently running.
1924

1925
    @type cluster_name: string
1926
    @param cluster_name: name of the cluster
1927
    @type instance: L{objects.Instance}
1928
    @param instance: the instance to be migrated
1929
    @type target: string
1930
    @param target: ip address of the target node
1931
    @type live: boolean
1932
    @param live: perform a live migration
1933

1934
    """
1935
    instance_name = instance.name
1936
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1937
    _, _, alive = self._InstancePidAlive(instance_name)
1938
    if not alive:
1939
      raise errors.HypervisorError("Instance not running, cannot migrate")
1940

    
1941
    if not live:
1942
      self._CallMonitorCommand(instance_name, "stop")
1943

    
1944
    migrate_command = ("migrate_set_speed %dm" %
1945
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1946
    self._CallMonitorCommand(instance_name, migrate_command)
1947

    
1948
    migrate_command = ("migrate_set_downtime %dms" %
1949
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1950
    self._CallMonitorCommand(instance_name, migrate_command)
1951

    
1952
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1953
    self._CallMonitorCommand(instance_name, migrate_command)
1954

    
1955
  def FinalizeMigrationSource(self, instance, success, live):
1956
    """Finalize the instance migration on the source node.
1957

1958
    @type instance: L{objects.Instance}
1959
    @param instance: the instance that was migrated
1960
    @type success: bool
1961
    @param success: whether the migration succeeded or not
1962
    @type live: bool
1963
    @param live: whether the user requested a live migration or not
1964

1965
    """
1966
    if success:
1967
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1968
      utils.KillProcess(pid)
1969
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1970
    elif live:
1971
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1972

    
1973
  def GetMigrationStatus(self, instance):
1974
    """Get the migration status
1975

1976
    @type instance: L{objects.Instance}
1977
    @param instance: the instance that is being migrated
1978
    @rtype: L{objects.MigrationStatus}
1979
    @return: the status of the current migration (one of
1980
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1981
             progress info that can be retrieved from the hypervisor
1982

1983
    """
1984
    info_command = "info migrate"
1985
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1986
      result = self._CallMonitorCommand(instance.name, info_command)
1987
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1988
      if not match:
1989
        if not result.stdout:
1990
          logging.info("KVM: empty 'info migrate' result")
1991
        else:
1992
          logging.warning("KVM: unknown 'info migrate' result: %s",
1993
                          result.stdout)
1994
      else:
1995
        status = match.group(1)
1996
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1997
          migration_status = objects.MigrationStatus(status=status)
1998
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1999
          if match:
2000
            migration_status.transferred_ram = match.group("transferred")
2001
            migration_status.total_ram = match.group("total")
2002

    
2003
          return migration_status
2004

    
2005
        logging.warning("KVM: unknown migration status '%s'", status)
2006

    
2007
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2008

    
2009
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2010

    
2011
  def BalloonInstanceMemory(self, instance, mem):
2012
    """Balloon an instance memory to a certain value.
2013

2014
    @type instance: L{objects.Instance}
2015
    @param instance: instance to be accepted
2016
    @type mem: int
2017
    @param mem: actual memory size to use for instance runtime
2018

2019
    """
2020
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2021

    
2022
  def GetNodeInfo(self, hvparams=None):
2023
    """Return information about the node.
2024

2025
    @type hvparams: dict of strings
2026
    @param hvparams: hypervisor parameters, not used in this class
2027

2028
    @return: a dict as returned by L{BaseHypervisor.GetLinuxNodeInfo} plus
2029
        the following keys:
2030
          - hv_version: the hypervisor version in the form (major, minor,
2031
                        revision)
2032

2033
    """
2034
    result = self.GetLinuxNodeInfo()
2035
    kvmpath = constants.KVM_PATH
2036
    if hvparams is not None:
2037
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2038
    _, v_major, v_min, v_rev = self._GetKVMVersion(kvmpath)
2039
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2040
    return result
2041

    
2042
  @classmethod
2043
  def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
2044
    """Return a command for connecting to the console of an instance.
2045

2046
    """
2047
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2048
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2049
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2050
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2051
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2052
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2053
      return objects.InstanceConsole(instance=instance.name,
2054
                                     kind=constants.CONS_SSH,
2055
                                     host=primary_node.name,
2056
                                     user=constants.SSH_CONSOLE_USER,
2057
                                     command=cmd)
2058

    
2059
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2060
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2061
      display = instance.network_port - constants.VNC_BASE_PORT
2062
      return objects.InstanceConsole(instance=instance.name,
2063
                                     kind=constants.CONS_VNC,
2064
                                     host=vnc_bind_address,
2065
                                     port=instance.network_port,
2066
                                     display=display)
2067

    
2068
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2069
    if spice_bind:
2070
      return objects.InstanceConsole(instance=instance.name,
2071
                                     kind=constants.CONS_SPICE,
2072
                                     host=spice_bind,
2073
                                     port=instance.network_port)
2074

    
2075
    return objects.InstanceConsole(instance=instance.name,
2076
                                   kind=constants.CONS_MESSAGE,
2077
                                   message=("No serial shell for instance %s" %
2078
                                            instance.name))
2079

    
2080
  def Verify(self, hvparams=None):
2081
    """Verify the hypervisor.
2082

2083
    Check that the required binaries exist.
2084

2085
    @type hvparams: dict of strings
2086
    @param hvparams: hypervisor parameters to be verified against, not used here
2087

2088
    @return: Problem description if something is wrong, C{None} otherwise
2089

2090
    """
2091
    msgs = []
2092
    kvmpath = constants.KVM_PATH
2093
    if hvparams is not None:
2094
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2095
    if not os.path.exists(kvmpath):
2096
      msgs.append("The KVM binary ('%s') does not exist" % kvmpath)
2097
    if not os.path.exists(constants.SOCAT_PATH):
2098
      msgs.append("The socat binary ('%s') does not exist" %
2099
                  constants.SOCAT_PATH)
2100

    
2101
    return self._FormatVerifyResults(msgs)
2102

    
2103
  @classmethod
2104
  def CheckParameterSyntax(cls, hvparams):
2105
    """Check the given parameters for validity.
2106

2107
    @type hvparams:  dict
2108
    @param hvparams: dictionary with parameter names/value
2109
    @raise errors.HypervisorError: when a parameter is not valid
2110

2111
    """
2112
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2113

    
2114
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2115
    if kernel_path:
2116
      if not hvparams[constants.HV_ROOT_PATH]:
2117
        raise errors.HypervisorError("Need a root partition for the instance,"
2118
                                     " if a kernel is defined")
2119

    
2120
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2121
        not hvparams[constants.HV_VNC_X509]):
2122
      raise errors.HypervisorError("%s must be defined, if %s is" %
2123
                                   (constants.HV_VNC_X509,
2124
                                    constants.HV_VNC_X509_VERIFY))
2125

    
2126
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2127
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2128
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2129
      if not serial_speed or serial_speed not in valid_speeds:
2130
        raise errors.HypervisorError("Invalid serial console speed, must be"
2131
                                     " one of: %s" %
2132
                                     utils.CommaJoin(valid_speeds))
2133

    
2134
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2135
    if (boot_order == constants.HT_BO_CDROM and
2136
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2137
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2138
                                   " ISO path")
2139

    
2140
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2141
    if security_model == constants.HT_SM_USER:
2142
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2143
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2144
                                     " must be specified")
2145
    elif (security_model == constants.HT_SM_NONE or
2146
          security_model == constants.HT_SM_POOL):
2147
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2148
        raise errors.HypervisorError("Cannot have a security domain when the"
2149
                                     " security model is 'none' or 'pool'")
2150

    
2151
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2152
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2153
    if spice_bind:
2154
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2155
        # if an IP version is specified, the spice_bind parameter must be an
2156
        # IP of that family
2157
        if (netutils.IP4Address.IsValid(spice_bind) and
2158
            spice_ip_version != constants.IP4_VERSION):
2159
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2160
                                       " the specified IP version is %s" %
2161
                                       (spice_bind, spice_ip_version))
2162

    
2163
        if (netutils.IP6Address.IsValid(spice_bind) and
2164
            spice_ip_version != constants.IP6_VERSION):
2165
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2166
                                       " the specified IP version is %s" %
2167
                                       (spice_bind, spice_ip_version))
2168
    else:
2169
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2170
      # error if any of them is set without it.
2171
      for param in _SPICE_ADDITIONAL_PARAMS:
2172
        if hvparams[param]:
2173
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2174
                                       (param, constants.HV_KVM_SPICE_BIND))
2175

    
2176
  @classmethod
2177
  def ValidateParameters(cls, hvparams):
2178
    """Check the given parameters for validity.
2179

2180
    @type hvparams:  dict
2181
    @param hvparams: dictionary with parameter names/value
2182
    @raise errors.HypervisorError: when a parameter is not valid
2183

2184
    """
2185
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2186

    
2187
    kvm_path = hvparams[constants.HV_KVM_PATH]
2188

    
2189
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2190
    if security_model == constants.HT_SM_USER:
2191
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2192
      try:
2193
        pwd.getpwnam(username)
2194
      except KeyError:
2195
        raise errors.HypervisorError("Unknown security domain user %s"
2196
                                     % username)
2197
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2198
    if vnc_bind_address:
2199
      bound_to_addr = netutils.IP4Address.IsValid(vnc_bind_address)
2200
      is_interface = netutils.IsValidInterface(vnc_bind_address)
2201
      is_path = utils.IsNormAbsPath(vnc_bind_address)
2202
      if not bound_to_addr and not is_interface and not is_path:
2203
        raise errors.HypervisorError("VNC: The %s parameter must be either"
2204
                                     " a valid IP address, an interface name,"
2205
                                     " or an absolute path" %
2206
                                     constants.HV_KVM_SPICE_BIND)
2207

    
2208
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2209
    if spice_bind:
2210
      # only one of VNC and SPICE can be used currently.
2211
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2212
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2213
                                     " only one of them can be used at a"
2214
                                     " given time")
2215

    
2216
      # check that KVM supports SPICE
2217
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2218
      if not cls._SPICE_RE.search(kvmhelp):
2219
        raise errors.HypervisorError("SPICE is configured, but it is not"
2220
                                     " supported according to 'kvm --help'")
2221

    
2222
      # if spice_bind is not an IP address, it must be a valid interface
2223
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2224
                       netutils.IP6Address.IsValid(spice_bind))
2225
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2226
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2227
                                     " a valid IP address or interface name" %
2228
                                     constants.HV_KVM_SPICE_BIND)
2229

    
2230
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2231
    if machine_version:
2232
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2233
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2234
        raise errors.HypervisorError("Unsupported machine version: %s" %
2235
                                     machine_version)
2236

    
2237
  @classmethod
2238
  def PowercycleNode(cls, hvparams=None):
2239
    """KVM powercycle, just a wrapper over Linux powercycle.
2240

2241
    @type hvparams: dict of strings
2242
    @param hvparams: hypervisor params to be used on this node
2243

2244
    """
2245
    cls.LinuxPowercycle()