Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 1a73ae30

History | View | Annotate | Download (90.9 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
from bitarray import bitarray
41
try:
42
  import affinity   # pylint: disable=F0401
43
except ImportError:
44
  affinity = None
45
try:
46
  import fdsend   # pylint: disable=F0401
47
except ImportError:
48
  fdsend = None
49

    
50
from ganeti import utils
51
from ganeti import constants
52
from ganeti import errors
53
from ganeti import serializer
54
from ganeti import objects
55
from ganeti import uidpool
56
from ganeti import ssconf
57
from ganeti import netutils
58
from ganeti import pathutils
59
from ganeti.hypervisor import hv_base
60
from ganeti.utils import wrapper as utils_wrapper
61

    
62

    
63
_KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-vif-bridge"
64
_KVM_START_PAUSED_FLAG = "-S"
65

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

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

    
87
# Constant bitarray that reflects to a free pci slot
88
# Use it with bitarray.search()
89
_AVAILABLE_PCI_SLOT = bitarray("0")
90

    
91
# below constants show the format of runtime file
92
# the nics are in second possition, while the disks in 4th (last)
93
# moreover disk entries are stored in tupples of L{objects.Disk}, dev_path
94
_KVM_NICS_RUNTIME_INDEX = 1
95
_KVM_DISKS_RUNTIME_INDEX = 3
96
_DEVICE_RUNTIME_INDEX = {
97
  constants.HOTPLUG_TARGET_DISK: _KVM_DISKS_RUNTIME_INDEX,
98
  constants.HOTPLUG_TARGET_NIC: _KVM_NICS_RUNTIME_INDEX
99
  }
100
_FIND_RUNTIME_ENTRY = {
101
  constants.HOTPLUG_TARGET_NIC:
102
    lambda nic, kvm_nics: [n for n in kvm_nics if n.uuid == nic.uuid],
103
  constants.HOTPLUG_TARGET_DISK:
104
    lambda disk, kvm_disks: [(d, l) for (d, l) in kvm_disks
105
                             if d.uuid == disk.uuid]
106
  }
107
_RUNTIME_DEVICE = {
108
  constants.HOTPLUG_TARGET_NIC: lambda d: d,
109
  constants.HOTPLUG_TARGET_DISK: lambda (d, e): d
110
  }
111
_RUNTIME_ENTRY = {
112
  constants.HOTPLUG_TARGET_NIC: lambda d, e: d,
113
  constants.HOTPLUG_TARGET_DISK: lambda d, e: (d, e)
114
  }
115

    
116

    
117
def _GenerateDeviceKVMId(dev_type, dev):
118
  """Helper function to generate a unique device name used by KVM
119

120
  QEMU monitor commands use names to identify devices. Here we use their pci
121
  slot and a part of their UUID to name them. dev.pci might be None for old
122
  devices in the cluster.
123

124
  @type dev_type: sting
125
  @param dev_type: device type of param dev
126
  @type dev: L{objects.Disk} or L{objects.NIC}
127
  @param dev: the device object for which we generate a kvm name
128
  @raise errors.HotplugError: in case a device has no pci slot (old devices)
129

130
  """
131

    
132
  if not dev.pci:
133
    raise errors.HotplugError("Hotplug is not supported for %s with UUID %s" %
134
                              (dev_type, dev.uuid))
135

    
136
  return "%s-%s-pci-%d" % (dev_type.lower(), dev.uuid.split("-")[0], dev.pci)
137

    
138

    
139
def _UpdatePCISlots(dev, pci_reservations):
140
  """Update pci configuration for a stopped instance
141

142
  If dev has a pci slot the reserve it, else find first available
143
  in pci_reservations bitarray. It acts on the same objects passed
144
  as params so there is no need to return anything.
145

146
  @type dev: L{objects.Disk} or L{objects.NIC}
147
  @param dev: the device object for which we update its pci slot
148
  @type pci_reservations: bitarray
149
  @param pci_reservations: existing pci reservations for an instance
150
  @raise errors.HotplugError: in case an instance has all its slot occupied
151

152
  """
153
  if dev.pci:
154
    free = dev.pci
155
  else: # pylint: disable=E1103
156
    [free] = pci_reservations.search(_AVAILABLE_PCI_SLOT, 1)
157
    if not free:
158
      raise errors.HypervisorError("All PCI slots occupied")
159
    dev.pci = int(free)
160

    
161
  pci_reservations[free] = True
162

    
163

    
164
def _GetExistingDeviceInfo(dev_type, device, runtime):
165
  """Helper function to get an existing device inside the runtime file
166

167
  Used when an instance is running. Load kvm runtime file and search
168
  for a device based on its type and uuid.
169

170
  @type dev_type: sting
171
  @param dev_type: device type of param dev
172
  @type device: L{objects.Disk} or L{objects.NIC}
173
  @param device: the device object for which we generate a kvm name
174
  @type runtime: tuple (cmd, nics, hvparams, disks)
175
  @param runtime: the runtime data to search for the device
176
  @raise errors.HotplugError: in case the requested device does not
177
    exist (e.g. device has been added without --hotplug option) or
178
    device info has not pci slot (e.g. old devices in the cluster)
179

180
  """
181
  index = _DEVICE_RUNTIME_INDEX[dev_type]
182
  found = _FIND_RUNTIME_ENTRY[dev_type](device, runtime[index])
183
  if not found:
184
    raise errors.HotplugError("Cannot find runtime info for %s with UUID %s" %
185
                              (dev_type, device.uuid))
186

    
187
  return found[0]
188

    
189

    
190
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
191
  """Retrieves supported TUN features from file descriptor.
192

193
  @see: L{_ProbeTapVnetHdr}
194

195
  """
196
  req = struct.pack("I", 0)
197
  try:
198
    buf = _ioctl(fd, TUNGETFEATURES, req)
199
  except EnvironmentError, err:
200
    logging.warning("ioctl(TUNGETFEATURES) failed: %s", err)
201
    return None
202
  else:
203
    (flags, ) = struct.unpack("I", buf)
204
    return flags
205

    
206

    
207
def _ProbeTapVnetHdr(fd, _features_fn=_GetTunFeatures):
208
  """Check whether to enable the IFF_VNET_HDR flag.
209

210
  To do this, _all_ of the following conditions must be met:
211
   1. TUNGETFEATURES ioctl() *must* be implemented
212
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
213
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
214
      drivers/net/tun.c there is no way to test this until after the tap device
215
      has been created using TUNSETIFF, and there is no way to change the
216
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
217
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
218
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
219

220
   @type fd: int
221
   @param fd: the file descriptor of /dev/net/tun
222

223
  """
224
  flags = _features_fn(fd)
225

    
226
  if flags is None:
227
    # Not supported
228
    return False
229

    
230
  result = bool(flags & IFF_VNET_HDR)
231

    
232
  if not result:
233
    logging.warning("Kernel does not support IFF_VNET_HDR, not enabling")
234

    
235
  return result
236

    
237

    
238
def _OpenTap(vnet_hdr=True):
239
  """Open a new tap device and return its file descriptor.
240

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

244
  @type vnet_hdr: boolean
245
  @param vnet_hdr: Enable the VNET Header
246
  @return: (ifname, tapfd)
247
  @rtype: tuple
248

249
  """
250
  try:
251
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
252
  except EnvironmentError:
253
    raise errors.HypervisorError("Failed to open /dev/net/tun")
254

    
255
  flags = IFF_TAP | IFF_NO_PI
256

    
257
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
258
    flags |= IFF_VNET_HDR
259

    
260
  # The struct ifreq ioctl request (see netdevice(7))
261
  ifr = struct.pack("16sh", "", flags)
262

    
263
  try:
264
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
265
  except EnvironmentError, err:
266
    raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
267
                                 err)
268

    
269
  # Get the interface name from the ioctl
270
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
271
  return (ifname, tapfd)
272

    
273

    
274
class QmpMessage:
275
  """QEMU Messaging Protocol (QMP) message.
276

277
  """
278
  def __init__(self, data):
279
    """Creates a new QMP message based on the passed data.
280

281
    """
282
    if not isinstance(data, dict):
283
      raise TypeError("QmpMessage must be initialized with a dict")
284

    
285
    self.data = data
286

    
287
  def __getitem__(self, field_name):
288
    """Get the value of the required field if present, or None.
289

290
    Overrides the [] operator to provide access to the message data,
291
    returning None if the required item is not in the message
292
    @return: the value of the field_name field, or None if field_name
293
             is not contained in the message
294

295
    """
296
    return self.data.get(field_name, None)
297

    
298
  def __setitem__(self, field_name, field_value):
299
    """Set the value of the required field_name to field_value.
300

301
    """
302
    self.data[field_name] = field_value
303

    
304
  @staticmethod
305
  def BuildFromJsonString(json_string):
306
    """Build a QmpMessage from a JSON encoded string.
307

308
    @type json_string: str
309
    @param json_string: JSON string representing the message
310
    @rtype: L{QmpMessage}
311
    @return: a L{QmpMessage} built from json_string
312

313
    """
314
    # Parse the string
315
    data = serializer.LoadJson(json_string)
316
    return QmpMessage(data)
317

    
318
  def __str__(self):
319
    # The protocol expects the JSON object to be sent as a single line.
320
    return serializer.DumpJson(self.data)
321

    
322
  def __eq__(self, other):
323
    # When comparing two QmpMessages, we are interested in comparing
324
    # their internal representation of the message data
325
    return self.data == other.data
326

    
327

    
328
class MonitorSocket(object):
329
  _SOCKET_TIMEOUT = 5
330

    
331
  def __init__(self, monitor_filename):
332
    """Instantiates the MonitorSocket object.
333

334
    @type monitor_filename: string
335
    @param monitor_filename: the filename of the UNIX raw socket on which the
336
                             monitor (QMP or simple one) is listening
337

338
    """
339
    self.monitor_filename = monitor_filename
340
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
341
    # We want to fail if the server doesn't send a complete message
342
    # in a reasonable amount of time
343
    self.sock.settimeout(self._SOCKET_TIMEOUT)
344
    self._connected = False
345

    
346
  def _check_socket(self):
347
    sock_stat = None
348
    try:
349
      sock_stat = os.stat(self.monitor_filename)
350
    except EnvironmentError, err:
351
      if err.errno == errno.ENOENT:
352
        raise errors.HypervisorError("No monitor socket found")
353
      else:
354
        raise errors.HypervisorError("Error checking monitor socket: %s",
355
                                     utils.ErrnoOrStr(err))
356
    if not stat.S_ISSOCK(sock_stat.st_mode):
357
      raise errors.HypervisorError("Monitor socket is not a socket")
358

    
359
  def _check_connection(self):
360
    """Make sure that the connection is established.
361

362
    """
363
    if not self._connected:
364
      raise errors.ProgrammerError("To use a MonitorSocket you need to first"
365
                                   " invoke connect() on it")
366

    
367
  def connect(self):
368
    """Connects to the monitor.
369

370
    Connects to the UNIX socket
371

372
    @raise errors.HypervisorError: when there are communication errors
373

374
    """
375
    if self._connected:
376
      raise errors.ProgrammerError("Cannot connect twice")
377

    
378
    self._check_socket()
379

    
380
    # Check file existance/stuff
381
    try:
382
      self.sock.connect(self.monitor_filename)
383
    except EnvironmentError:
384
      raise errors.HypervisorError("Can't connect to qmp socket")
385
    self._connected = True
386

    
387
  def close(self):
388
    """Closes the socket
389

390
    It cannot be used after this call.
391

392
    """
393
    self.sock.close()
394

    
395

    
396
class QmpConnection(MonitorSocket):
397
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
398

399
  """
400
  _FIRST_MESSAGE_KEY = "QMP"
401
  _EVENT_KEY = "event"
402
  _ERROR_KEY = "error"
403
  _RETURN_KEY = RETURN_KEY = "return"
404
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
405
  _ERROR_CLASS_KEY = "class"
406
  _ERROR_DATA_KEY = "data"
407
  _ERROR_DESC_KEY = "desc"
408
  _EXECUTE_KEY = "execute"
409
  _ARGUMENTS_KEY = "arguments"
410
  _CAPABILITIES_COMMAND = "qmp_capabilities"
411
  _MESSAGE_END_TOKEN = "\r\n"
412

    
413
  def __init__(self, monitor_filename):
414
    super(QmpConnection, self).__init__(monitor_filename)
415
    self._buf = ""
416

    
417
  def connect(self):
418
    """Connects to the QMP monitor.
419

420
    Connects to the UNIX socket and makes sure that we can actually send and
421
    receive data to the kvm instance via QMP.
422

423
    @raise errors.HypervisorError: when there are communication errors
424
    @raise errors.ProgrammerError: when there are data serialization errors
425

426
    """
427
    super(QmpConnection, self).connect()
428
    # Check if we receive a correct greeting message from the server
429
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
430
    greeting = self._Recv()
431
    if not greeting[self._FIRST_MESSAGE_KEY]:
432
      self._connected = False
433
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
434
                                   " server greeting")
435

    
436
    # Let's put the monitor in command mode using the qmp_capabilities
437
    # command, or else no command will be executable.
438
    # (As per the QEMU Protocol Specification 0.1 - section 4)
439
    self.Execute(self._CAPABILITIES_COMMAND)
440

    
441
  def _ParseMessage(self, buf):
442
    """Extract and parse a QMP message from the given buffer.
443

444
    Seeks for a QMP message in the given buf. If found, it parses it and
445
    returns it together with the rest of the characters in the buf.
446
    If no message is found, returns None and the whole buffer.
447

448
    @raise errors.ProgrammerError: when there are data serialization errors
449

450
    """
451
    message = None
452
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
453
    # Specification 0.1 - Section 2.1.1)
454
    pos = buf.find(self._MESSAGE_END_TOKEN)
455
    if pos >= 0:
456
      try:
457
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
458
      except Exception, err:
459
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
460
      buf = buf[pos + 1:]
461

    
462
    return (message, buf)
463

    
464
  def _Recv(self):
465
    """Receives a message from QMP and decodes the received JSON object.
466

467
    @rtype: QmpMessage
468
    @return: the received message
469
    @raise errors.HypervisorError: when there are communication errors
470
    @raise errors.ProgrammerError: when there are data serialization errors
471

472
    """
473
    self._check_connection()
474

    
475
    # Check if there is already a message in the buffer
476
    (message, self._buf) = self._ParseMessage(self._buf)
477
    if message:
478
      return message
479

    
480
    recv_buffer = StringIO.StringIO(self._buf)
481
    recv_buffer.seek(len(self._buf))
482
    try:
483
      while True:
484
        data = self.sock.recv(4096)
485
        if not data:
486
          break
487
        recv_buffer.write(data)
488

    
489
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
490
        if message:
491
          return message
492

    
493
    except socket.timeout, err:
494
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
495
                                   "%s" % (err))
496
    except socket.error, err:
497
      raise errors.HypervisorError("Unable to receive data from KVM using the"
498
                                   " QMP protocol: %s" % err)
499

    
500
  def _Send(self, message):
501
    """Encodes and sends a message to KVM using QMP.
502

503
    @type message: QmpMessage
504
    @param message: message to send to KVM
505
    @raise errors.HypervisorError: when there are communication errors
506
    @raise errors.ProgrammerError: when there are data serialization errors
507

508
    """
509
    self._check_connection()
510
    try:
511
      message_str = str(message)
512
    except Exception, err:
513
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
514

    
515
    try:
516
      self.sock.sendall(message_str)
517
    except socket.timeout, err:
518
      raise errors.HypervisorError("Timeout while sending a QMP message: "
519
                                   "%s (%s)" % (err.string, err.errno))
520
    except socket.error, err:
521
      raise errors.HypervisorError("Unable to send data from KVM using the"
522
                                   " QMP protocol: %s" % err)
523

    
524
  def Execute(self, command, arguments=None):
525
    """Executes a QMP command and returns the response of the server.
526

527
    @type command: str
528
    @param command: the command to execute
529
    @type arguments: dict
530
    @param arguments: dictionary of arguments to be passed to the command
531
    @rtype: dict
532
    @return: dictionary representing the received JSON object
533
    @raise errors.HypervisorError: when there are communication errors
534
    @raise errors.ProgrammerError: when there are data serialization errors
535

536
    """
537
    self._check_connection()
538
    message = QmpMessage({self._EXECUTE_KEY: command})
539
    if arguments:
540
      message[self._ARGUMENTS_KEY] = arguments
541
    self._Send(message)
542

    
543
    # Events can occur between the sending of the command and the reception
544
    # of the response, so we need to filter out messages with the event key.
545
    while True:
546
      response = self._Recv()
547
      err = response[self._ERROR_KEY]
548
      if err:
549
        raise errors.HypervisorError("kvm: error executing the %s"
550
                                     " command: %s (%s, %s):" %
551
                                     (command,
552
                                      err[self._ERROR_DESC_KEY],
553
                                      err[self._ERROR_CLASS_KEY],
554
                                      err[self._ERROR_DATA_KEY]))
555

    
556
      elif not response[self._EVENT_KEY]:
557
        return response
558

    
559

    
560
class KVMHypervisor(hv_base.BaseHypervisor):
561
  """KVM hypervisor interface
562

563
  """
564
  CAN_MIGRATE = True
565

    
566
  _ROOT_DIR = pathutils.RUN_DIR + "/kvm-hypervisor"
567
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
568
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
569
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
570
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
571
  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
572
  _KEYMAP_DIR = _ROOT_DIR + "/keymap" # contains instances keymaps
573
  # KVM instances with chroot enabled are started in empty chroot directories.
574
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
575
  # After an instance is stopped, its chroot directory is removed.
576
  # If the chroot directory is not empty, it can't be removed.
577
  # A non-empty chroot directory indicates a possible security incident.
578
  # To support forensics, the non-empty chroot directory is quarantined in
579
  # a separate directory, called 'chroot-quarantine'.
580
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
581
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
582
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR, _KEYMAP_DIR]
583

    
584
  PARAMETERS = {
585
    constants.HV_KVM_PATH: hv_base.REQ_FILE_CHECK,
586
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
587
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
588
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
589
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
590
    constants.HV_ACPI: hv_base.NO_CHECK,
591
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
592
    constants.HV_SERIAL_SPEED: hv_base.NO_CHECK,
593
    constants.HV_VNC_BIND_ADDRESS: hv_base.NO_CHECK, # will be checked later
594
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
595
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
596
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
597
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
598
    constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
599
    constants.HV_KVM_SPICE_IP_VERSION:
600
      (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
601
                         x in constants.VALID_IP_VERSIONS),
602
       "The SPICE IP version should be 4 or 6",
603
       None, None),
604
    constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
605
    constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
606
      hv_base.ParamInSet(
607
        False, constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
608
    constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
609
      hv_base.ParamInSet(
610
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
611
    constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
612
      hv_base.ParamInSet(
613
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
614
    constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
615
      hv_base.ParamInSet(
616
        False, constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
617
    constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
618
    constants.HV_KVM_SPICE_USE_TLS: hv_base.NO_CHECK,
619
    constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
620
    constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
621
    constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
622
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
623
    constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
624
    constants.HV_BOOT_ORDER:
625
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
626
    constants.HV_NIC_TYPE:
627
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
628
    constants.HV_DISK_TYPE:
629
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
630
    constants.HV_KVM_CDROM_DISK_TYPE:
631
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
632
    constants.HV_USB_MOUSE:
633
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
634
    constants.HV_KEYMAP: hv_base.NO_CHECK,
635
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
636
    constants.HV_MIGRATION_BANDWIDTH: hv_base.REQ_NONNEGATIVE_INT_CHECK,
637
    constants.HV_MIGRATION_DOWNTIME: hv_base.REQ_NONNEGATIVE_INT_CHECK,
638
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
639
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
640
    constants.HV_DISK_CACHE:
641
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
642
    constants.HV_SECURITY_MODEL:
643
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
644
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
645
    constants.HV_KVM_FLAG:
646
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
647
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
648
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
649
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
650
    constants.HV_REBOOT_BEHAVIOR:
651
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
652
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
653
    constants.HV_CPU_TYPE: hv_base.NO_CHECK,
654
    constants.HV_CPU_CORES: hv_base.OPT_NONNEGATIVE_INT_CHECK,
655
    constants.HV_CPU_THREADS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
656
    constants.HV_CPU_SOCKETS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
657
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
658
    constants.HV_USB_DEVICES: hv_base.NO_CHECK,
659
    constants.HV_VGA: hv_base.NO_CHECK,
660
    constants.HV_KVM_EXTRA: hv_base.NO_CHECK,
661
    constants.HV_KVM_MACHINE_VERSION: hv_base.NO_CHECK,
662
    constants.HV_VNET_HDR: hv_base.NO_CHECK,
663
    }
664

    
665
  _VIRTIO = "virtio"
666
  _VIRTIO_NET_PCI = "virtio-net-pci"
667
  _VIRTIO_BLK_PCI = "virtio-blk-pci"
668

    
669
  _MIGRATION_STATUS_RE = re.compile("Migration\s+status:\s+(\w+)",
670
                                    re.M | re.I)
671
  _MIGRATION_PROGRESS_RE = \
672
    re.compile(r"\s*transferred\s+ram:\s+(?P<transferred>\d+)\s+kbytes\s*\n"
673
               r"\s*remaining\s+ram:\s+(?P<remaining>\d+)\s+kbytes\s*\n"
674
               r"\s*total\s+ram:\s+(?P<total>\d+)\s+kbytes\s*\n", re.I)
675

    
676
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
677
  _MIGRATION_INFO_RETRY_DELAY = 2
678

    
679
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
680

    
681
  _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
682
  _CPU_INFO_CMD = "info cpus"
683
  _CONT_CMD = "cont"
684

    
685
  _DEFAULT_MACHINE_VERSION_RE = re.compile(r"^(\S+).*\(default\)", re.M)
686
  _CHECK_MACHINE_VERSION_RE = \
687
    staticmethod(lambda x: re.compile(r"^(%s)[ ]+.*PC" % x, re.M))
688

    
689
  _QMP_RE = re.compile(r"^-qmp\s", re.M)
690
  _SPICE_RE = re.compile(r"^-spice\s", re.M)
691
  _VHOST_RE = re.compile(r"^-net\s.*,vhost=on|off", re.M)
692
  _ENABLE_KVM_RE = re.compile(r"^-enable-kvm\s", re.M)
693
  _DISABLE_KVM_RE = re.compile(r"^-disable-kvm\s", re.M)
694
  _NETDEV_RE = re.compile(r"^-netdev\s", re.M)
695
  _DISPLAY_RE = re.compile(r"^-display\s", re.M)
696
  _MACHINE_RE = re.compile(r"^-machine\s", re.M)
697
  _VIRTIO_NET_RE = re.compile(r"^name \"%s\"" % _VIRTIO_NET_PCI, re.M)
698
  _VIRTIO_BLK_RE = re.compile(r"^name \"%s\"" % _VIRTIO_BLK_PCI, re.M)
699
  # match  -drive.*boot=on|off on different lines, but in between accept only
700
  # dashes not preceeded by a new line (which would mean another option
701
  # different than -drive is starting)
702
  _BOOT_RE = re.compile(r"^-drive\s([^-]|(?<!^)-)*,boot=on\|off", re.M | re.S)
703
  _UUID_RE = re.compile(r"^-uuid\s", re.M)
704

    
705
  _INFO_PCI_RE = re.compile(r'Bus.*device[ ]*(\d+).*')
706
  _INFO_PCI_CMD = "info pci"
707
  _INFO_VERSION_RE = \
708
    re.compile(r'^QEMU (\d+)\.(\d+)(\.(\d+))?.*monitor.*', re.M)
709
  _INFO_VERSION_CMD = "info version"
710

    
711
  _DEFAULT_PCI_RESERVATIONS = "11110000000000000000000000000000"
712

    
713
  ANCILLARY_FILES = [
714
    _KVM_NETWORK_SCRIPT,
715
    ]
716
  ANCILLARY_FILES_OPT = [
717
    _KVM_NETWORK_SCRIPT,
718
    ]
719

    
720
  # Supported kvm options to get output from
721
  _KVMOPT_HELP = "help"
722
  _KVMOPT_MLIST = "mlist"
723
  _KVMOPT_DEVICELIST = "devicelist"
724

    
725
  # Command to execute to get the output from kvm, and whether to
726
  # accept the output even on failure.
727
  _KVMOPTS_CMDS = {
728
    _KVMOPT_HELP: (["--help"], False),
729
    _KVMOPT_MLIST: (["-M", "?"], False),
730
    _KVMOPT_DEVICELIST: (["-device", "?"], True),
731
  }
732

    
733
  def __init__(self):
734
    hv_base.BaseHypervisor.__init__(self)
735
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
736
    # in a tmpfs filesystem or has been otherwise wiped out.
737
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
738
    utils.EnsureDirs(dirs)
739

    
740
  @classmethod
741
  def _InstancePidFile(cls, instance_name):
742
    """Returns the instance pidfile.
743

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

    
747
  @classmethod
748
  def _InstanceUidFile(cls, instance_name):
749
    """Returns the instance uidfile.
750

751
    """
752
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
753

    
754
  @classmethod
755
  def _InstancePidInfo(cls, pid):
756
    """Check pid file for instance information.
757

758
    Check that a pid file is associated with an instance, and retrieve
759
    information from its command line.
760

761
    @type pid: string or int
762
    @param pid: process id of the instance to check
763
    @rtype: tuple
764
    @return: (instance_name, memory, vcpus)
765
    @raise errors.HypervisorError: when an instance cannot be found
766

767
    """
768
    alive = utils.IsProcessAlive(pid)
769
    if not alive:
770
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
771

    
772
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
773
    try:
774
      cmdline = utils.ReadFile(cmdline_file)
775
    except EnvironmentError, err:
776
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
777
                                   (pid, err))
778

    
779
    instance = None
780
    memory = 0
781
    vcpus = 0
782

    
783
    arg_list = cmdline.split("\x00")
784
    while arg_list:
785
      arg = arg_list.pop(0)
786
      if arg == "-name":
787
        instance = arg_list.pop(0)
788
      elif arg == "-m":
789
        memory = int(arg_list.pop(0))
790
      elif arg == "-smp":
791
        vcpus = int(arg_list.pop(0).split(",")[0])
792

    
793
    if instance is None:
794
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
795
                                   " instance" % pid)
796

    
797
    return (instance, memory, vcpus)
798

    
799
  def _InstancePidAlive(self, instance_name):
800
    """Returns the instance pidfile, pid, and liveness.
801

802
    @type instance_name: string
803
    @param instance_name: instance name
804
    @rtype: tuple
805
    @return: (pid file name, pid, liveness)
806

807
    """
808
    pidfile = self._InstancePidFile(instance_name)
809
    pid = utils.ReadPidFile(pidfile)
810

    
811
    alive = False
812
    try:
813
      cmd_instance = self._InstancePidInfo(pid)[0]
814
      alive = (cmd_instance == instance_name)
815
    except errors.HypervisorError:
816
      pass
817

    
818
    return (pidfile, pid, alive)
819

    
820
  def _CheckDown(self, instance_name):
821
    """Raises an error unless the given instance is down.
822

823
    """
824
    alive = self._InstancePidAlive(instance_name)[2]
825
    if alive:
826
      raise errors.HypervisorError("Failed to start instance %s: %s" %
827
                                   (instance_name, "already running"))
828

    
829
  @classmethod
830
  def _InstanceMonitor(cls, instance_name):
831
    """Returns the instance monitor socket name
832

833
    """
834
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
835

    
836
  @classmethod
837
  def _InstanceSerial(cls, instance_name):
838
    """Returns the instance serial socket name
839

840
    """
841
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
842

    
843
  @classmethod
844
  def _InstanceQmpMonitor(cls, instance_name):
845
    """Returns the instance serial QMP socket name
846

847
    """
848
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
849

    
850
  @staticmethod
851
  def _SocatUnixConsoleParams():
852
    """Returns the correct parameters for socat
853

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

856
    """
857
    if constants.SOCAT_USE_ESCAPE:
858
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
859
    else:
860
      return "echo=0,icanon=0"
861

    
862
  @classmethod
863
  def _InstanceKVMRuntime(cls, instance_name):
864
    """Returns the instance KVM runtime filename
865

866
    """
867
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
868

    
869
  @classmethod
870
  def _InstanceChrootDir(cls, instance_name):
871
    """Returns the name of the KVM chroot dir of the instance
872

873
    """
874
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
875

    
876
  @classmethod
877
  def _InstanceNICDir(cls, instance_name):
878
    """Returns the name of the directory holding the tap device files for a
879
    given instance.
880

881
    """
882
    return utils.PathJoin(cls._NICS_DIR, instance_name)
883

    
884
  @classmethod
885
  def _InstanceNICFile(cls, instance_name, seq):
886
    """Returns the name of the file containing the tap device for a given NIC
887

888
    """
889
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
890

    
891
  @classmethod
892
  def _InstanceKeymapFile(cls, instance_name):
893
    """Returns the name of the file containing the keymap for a given instance
894

895
    """
896
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
897

    
898
  @classmethod
899
  def _TryReadUidFile(cls, uid_file):
900
    """Try to read a uid file
901

902
    """
903
    if os.path.exists(uid_file):
904
      try:
905
        uid = int(utils.ReadOneLineFile(uid_file))
906
        return uid
907
      except EnvironmentError:
908
        logging.warning("Can't read uid file", exc_info=True)
909
      except (TypeError, ValueError):
910
        logging.warning("Can't parse uid file contents", exc_info=True)
911
    return None
912

    
913
  @classmethod
914
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
915
    """Removes an instance's rutime sockets/files/dirs.
916

917
    """
918
    utils.RemoveFile(pidfile)
919
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
920
    utils.RemoveFile(cls._InstanceSerial(instance_name))
921
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
922
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
923
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
924
    uid_file = cls._InstanceUidFile(instance_name)
925
    uid = cls._TryReadUidFile(uid_file)
926
    utils.RemoveFile(uid_file)
927
    if uid is not None:
928
      uidpool.ReleaseUid(uid)
929
    try:
930
      shutil.rmtree(cls._InstanceNICDir(instance_name))
931
    except OSError, err:
932
      if err.errno != errno.ENOENT:
933
        raise
934
    try:
935
      chroot_dir = cls._InstanceChrootDir(instance_name)
936
      utils.RemoveDir(chroot_dir)
937
    except OSError, err:
938
      if err.errno == errno.ENOTEMPTY:
939
        # The chroot directory is expected to be empty, but it isn't.
940
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
941
                                          prefix="%s-%s-" %
942
                                          (instance_name,
943
                                           utils.TimestampForFilename()))
944
        logging.warning("The chroot directory of instance %s can not be"
945
                        " removed as it is not empty. Moving it to the"
946
                        " quarantine instead. Please investigate the"
947
                        " contents (%s) and clean up manually",
948
                        instance_name, new_chroot_dir)
949
        utils.RenameFile(chroot_dir, new_chroot_dir)
950
      else:
951
        raise
952

    
953
  @staticmethod
954
  def _ConfigureNIC(instance, seq, nic, tap):
955
    """Run the network configuration script for a specified NIC
956

957
    @param instance: instance we're acting on
958
    @type instance: instance object
959
    @param seq: nic sequence number
960
    @type seq: int
961
    @param nic: nic we're acting on
962
    @type nic: nic object
963
    @param tap: the host's tap interface this NIC corresponds to
964
    @type tap: str
965

966
    """
967
    if instance.tags:
968
      tags = " ".join(instance.tags)
969
    else:
970
      tags = ""
971

    
972
    env = {
973
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
974
      "INSTANCE": instance.name,
975
      "MAC": nic.mac,
976
      "MODE": nic.nicparams[constants.NIC_MODE],
977
      "INTERFACE": tap,
978
      "INTERFACE_INDEX": str(seq),
979
      "TAGS": tags,
980
    }
981

    
982
    if nic.ip:
983
      env["IP"] = nic.ip
984

    
985
    if nic.nicparams[constants.NIC_LINK]:
986
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
987

    
988
    if nic.network:
989
      n = objects.Network.FromDict(nic.netinfo)
990
      env.update(n.HooksDict())
991

    
992
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
993
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
994

    
995
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
996
    if result.failed:
997
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
998
                                   " network configuration script output: %s" %
999
                                   (tap, result.fail_reason, result.output))
1000

    
1001
  @staticmethod
1002
  def _VerifyAffinityPackage():
1003
    if affinity is None:
1004
      raise errors.HypervisorError("affinity Python package not"
1005
                                   " found; cannot use CPU pinning under KVM")
1006

    
1007
  @staticmethod
1008
  def _BuildAffinityCpuMask(cpu_list):
1009
    """Create a CPU mask suitable for sched_setaffinity from a list of
1010
    CPUs.
1011

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

1015
    @type cpu_list: list of int
1016
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1017
    @rtype: int
1018
    @return: a bit mask of CPU affinities
1019

1020
    """
1021
    if cpu_list == constants.CPU_PINNING_OFF:
1022
      return constants.CPU_PINNING_ALL_KVM
1023
    else:
1024
      return sum(2 ** cpu for cpu in cpu_list)
1025

    
1026
  @classmethod
1027
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1028
    """Change CPU affinity for running VM according to given CPU mask.
1029

1030
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1031
    @type cpu_mask: string
1032
    @param process_id: process ID of KVM process. Used to pin entire VM
1033
                       to physical CPUs.
1034
    @type process_id: int
1035
    @param thread_dict: map of virtual CPUs to KVM thread IDs
1036
    @type thread_dict: dict int:int
1037

1038
    """
1039
    # Convert the string CPU mask to a list of list of int's
1040
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
1041

    
1042
    if len(cpu_list) == 1:
1043
      all_cpu_mapping = cpu_list[0]
1044
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
1045
        # If CPU pinning has 1 entry that's "all", then do nothing
1046
        pass
1047
      else:
1048
        # If CPU pinning has one non-all entry, map the entire VM to
1049
        # one set of physical CPUs
1050
        cls._VerifyAffinityPackage()
1051
        affinity.set_process_affinity_mask(
1052
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
1053
    else:
1054
      # The number of vCPUs mapped should match the number of vCPUs
1055
      # reported by KVM. This was already verified earlier, so
1056
      # here only as a sanity check.
1057
      assert len(thread_dict) == len(cpu_list)
1058
      cls._VerifyAffinityPackage()
1059

    
1060
      # For each vCPU, map it to the proper list of physical CPUs
1061
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
1062
        affinity.set_process_affinity_mask(thread_dict[i],
1063
                                           cls._BuildAffinityCpuMask(vcpu))
1064

    
1065
  def _GetVcpuThreadIds(self, instance_name):
1066
    """Get a mapping of vCPU no. to thread IDs for the instance
1067

1068
    @type instance_name: string
1069
    @param instance_name: instance in question
1070
    @rtype: dictionary of int:int
1071
    @return: a dictionary mapping vCPU numbers to thread IDs
1072

1073
    """
1074
    result = {}
1075
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1076
    for line in output.stdout.splitlines():
1077
      match = self._CPU_INFO_RE.search(line)
1078
      if not match:
1079
        continue
1080
      grp = map(int, match.groups())
1081
      result[grp[0]] = grp[1]
1082

    
1083
    return result
1084

    
1085
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1086
    """Complete CPU pinning.
1087

1088
    @type instance_name: string
1089
    @param instance_name: name of instance
1090
    @type cpu_mask: string
1091
    @param cpu_mask: CPU pinning mask as entered by user
1092

1093
    """
1094
    # Get KVM process ID, to be used if need to pin entire VM
1095
    _, pid, _ = self._InstancePidAlive(instance_name)
1096
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1097
    thread_dict = self._GetVcpuThreadIds(instance_name)
1098
    # Run CPU pinning, based on configured mask
1099
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1100

    
1101
  def ListInstances(self, hvparams=None):
1102
    """Get the list of running instances.
1103

1104
    We can do this by listing our live instances directory and
1105
    checking whether the associated kvm process is still alive.
1106

1107
    """
1108
    result = []
1109
    for name in os.listdir(self._PIDS_DIR):
1110
      if self._InstancePidAlive(name)[2]:
1111
        result.append(name)
1112
    return result
1113

    
1114
  def GetInstanceInfo(self, instance_name, hvparams=None):
1115
    """Get instance properties.
1116

1117
    @type instance_name: string
1118
    @param instance_name: the instance name
1119
    @type hvparams: dict of strings
1120
    @param hvparams: hvparams to be used with this instance
1121
    @rtype: tuple of strings
1122
    @return: (name, id, memory, vcpus, stat, times)
1123

1124
    """
1125
    _, pid, alive = self._InstancePidAlive(instance_name)
1126
    if not alive:
1127
      return None
1128

    
1129
    _, memory, vcpus = self._InstancePidInfo(pid)
1130
    istat = "---b-"
1131
    times = "0"
1132

    
1133
    try:
1134
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1135
      qmp.connect()
1136
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1137
      # Will fail if ballooning is not enabled, but we can then just resort to
1138
      # the value above.
1139
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1140
      memory = mem_bytes / 1048576
1141
    except errors.HypervisorError:
1142
      pass
1143

    
1144
    return (instance_name, pid, memory, vcpus, istat, times)
1145

    
1146
  def GetAllInstancesInfo(self, hvparams=None):
1147
    """Get properties of all instances.
1148

1149
    @type hvparams: dict of strings
1150
    @param hvparams: hypervisor parameter
1151
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1152

1153
    """
1154
    data = []
1155
    for name in os.listdir(self._PIDS_DIR):
1156
      try:
1157
        info = self.GetInstanceInfo(name)
1158
      except errors.HypervisorError:
1159
        # Ignore exceptions due to instances being shut down
1160
        continue
1161
      if info:
1162
        data.append(info)
1163
    return data
1164

    
1165
  def _GenerateKVMBlockDevicesOptions(self, instance, block_devices, kvmhelp):
1166

    
1167
    hvp = instance.hvparams
1168
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1169
    kvm_path = hvp[constants.HV_KVM_PATH]
1170

    
1171
    # whether this is an older KVM version that uses the boot=on flag
1172
    # on devices
1173
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1174

    
1175
    dev_opts = []
1176
    device_driver = None
1177
    disk_type = hvp[constants.HV_DISK_TYPE]
1178
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1179
      if_val = ",if=%s" % self._VIRTIO
1180
      try:
1181
        devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1182
        if self._VIRTIO_BLK_RE.search(devlist):
1183
          if_val = ",if=none"
1184
          # will be passed in -device option as driver
1185
          device_driver = self._VIRTIO_BLK_PCI
1186
      except errors.HypervisorError, _:
1187
        pass
1188
    else:
1189
      if_val = ",if=%s" % disk_type
1190
    # Cache mode
1191
    disk_cache = hvp[constants.HV_DISK_CACHE]
1192
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1193
      if disk_cache != "none":
1194
        # TODO: make this a hard error, instead of a silent overwrite
1195
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1196
                        " to prevent shared storage corruption on migration",
1197
                        disk_cache)
1198
      cache_val = ",cache=none"
1199
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1200
      cache_val = ",cache=%s" % disk_cache
1201
    else:
1202
      cache_val = ""
1203
    for cfdev, dev_path in block_devices:
1204
      if cfdev.mode != constants.DISK_RDWR:
1205
        raise errors.HypervisorError("Instance has read-only disks which"
1206
                                     " are not supported by KVM")
1207
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1208
      boot_val = ""
1209
      if boot_disk:
1210
        dev_opts.extend(["-boot", "c"])
1211
        boot_disk = False
1212
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1213
          boot_val = ",boot=on"
1214
      drive_val = "file=%s,format=raw%s%s%s" % \
1215
                  (dev_path, if_val, boot_val, cache_val)
1216

    
1217
      if device_driver:
1218
        # block_devices are the 4th entry of runtime file that did not exist in
1219
        # the past. That means that cfdev should always have pci slot and
1220
        # _GenerateDeviceKVMId() will not raise a exception.
1221
        kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK, cfdev)
1222
        drive_val += (",id=%s" % kvm_devid)
1223
        drive_val += (",bus=0,unit=%d" % cfdev.pci)
1224
        dev_val = ("%s,drive=%s,id=%s" %
1225
                   (device_driver, kvm_devid, kvm_devid))
1226
        dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1227
        dev_opts.extend(["-device", dev_val])
1228

    
1229
      dev_opts.extend(["-drive", drive_val])
1230

    
1231
    return dev_opts
1232

    
1233
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1234
                          kvmhelp):
1235
    """Generate KVM information to start an instance.
1236

1237
    @type kvmhelp: string
1238
    @param kvmhelp: output of kvm --help
1239
    @attention: this function must not have any side-effects; for
1240
        example, it must not write to the filesystem, or read values
1241
        from the current system the are expected to differ between
1242
        nodes, since it is only run once at instance startup;
1243
        actions/kvm arguments that can vary between systems should be
1244
        done in L{_ExecuteKVMRuntime}
1245

1246
    """
1247
    # pylint: disable=R0912,R0914,R0915
1248
    hvp = instance.hvparams
1249
    self.ValidateParameters(hvp)
1250

    
1251
    pidfile = self._InstancePidFile(instance.name)
1252
    kvm = hvp[constants.HV_KVM_PATH]
1253
    kvm_cmd = [kvm]
1254
    # used just by the vnc server, if enabled
1255
    kvm_cmd.extend(["-name", instance.name])
1256
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1257

    
1258
    smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1259
    if hvp[constants.HV_CPU_CORES]:
1260
      smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1261
    if hvp[constants.HV_CPU_THREADS]:
1262
      smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1263
    if hvp[constants.HV_CPU_SOCKETS]:
1264
      smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1265

    
1266
    kvm_cmd.extend(["-smp", ",".join(smp_list)])
1267

    
1268
    kvm_cmd.extend(["-pidfile", pidfile])
1269
    kvm_cmd.extend(["-balloon", "virtio"])
1270
    kvm_cmd.extend(["-daemonize"])
1271
    if not instance.hvparams[constants.HV_ACPI]:
1272
      kvm_cmd.extend(["-no-acpi"])
1273
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1274
        constants.INSTANCE_REBOOT_EXIT:
1275
      kvm_cmd.extend(["-no-reboot"])
1276

    
1277
    mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1278
    if not mversion:
1279
      mversion = self._GetDefaultMachineVersion(kvm)
1280
    if self._MACHINE_RE.search(kvmhelp):
1281
      # TODO (2.8): kernel_irqchip and kvm_shadow_mem machine properties, as
1282
      # extra hypervisor parameters. We should also investigate whether and how
1283
      # shadow_mem should be considered for the resource model.
1284
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED):
1285
        specprop = ",accel=kvm"
1286
      else:
1287
        specprop = ""
1288
      machinespec = "%s%s" % (mversion, specprop)
1289
      kvm_cmd.extend(["-machine", machinespec])
1290
    else:
1291
      kvm_cmd.extend(["-M", mversion])
1292
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1293
          self._ENABLE_KVM_RE.search(kvmhelp)):
1294
        kvm_cmd.extend(["-enable-kvm"])
1295
      elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1296
            self._DISABLE_KVM_RE.search(kvmhelp)):
1297
        kvm_cmd.extend(["-disable-kvm"])
1298

    
1299
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1300
    if kernel_path:
1301
      boot_cdrom = boot_floppy = boot_network = False
1302
    else:
1303
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1304
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1305
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1306

    
1307
    if startup_paused:
1308
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1309

    
1310
    if boot_network:
1311
      kvm_cmd.extend(["-boot", "n"])
1312

    
1313
    # whether this is an older KVM version that uses the boot=on flag
1314
    # on devices
1315
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1316

    
1317
    disk_type = hvp[constants.HV_DISK_TYPE]
1318

    
1319
    #Now we can specify a different device type for CDROM devices.
1320
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1321
    if not cdrom_disk_type:
1322
      cdrom_disk_type = disk_type
1323

    
1324
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1325
    if iso_image:
1326
      options = ",format=raw,media=cdrom"
1327
      # set cdrom 'if' type
1328
      if boot_cdrom:
1329
        actual_cdrom_type = constants.HT_DISK_IDE
1330
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1331
        actual_cdrom_type = "virtio"
1332
      else:
1333
        actual_cdrom_type = cdrom_disk_type
1334
      if_val = ",if=%s" % actual_cdrom_type
1335
      # set boot flag, if needed
1336
      boot_val = ""
1337
      if boot_cdrom:
1338
        kvm_cmd.extend(["-boot", "d"])
1339
        if needs_boot_flag:
1340
          boot_val = ",boot=on"
1341
      # and finally build the entire '-drive' value
1342
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1343
      kvm_cmd.extend(["-drive", drive_val])
1344

    
1345
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1346
    if iso_image2:
1347
      options = ",format=raw,media=cdrom"
1348
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1349
        if_val = ",if=virtio"
1350
      else:
1351
        if_val = ",if=%s" % cdrom_disk_type
1352
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1353
      kvm_cmd.extend(["-drive", drive_val])
1354

    
1355
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1356
    if floppy_image:
1357
      options = ",format=raw,media=disk"
1358
      if boot_floppy:
1359
        kvm_cmd.extend(["-boot", "a"])
1360
        options = "%s,boot=on" % options
1361
      if_val = ",if=floppy"
1362
      options = "%s%s" % (options, if_val)
1363
      drive_val = "file=%s%s" % (floppy_image, options)
1364
      kvm_cmd.extend(["-drive", drive_val])
1365

    
1366
    if kernel_path:
1367
      kvm_cmd.extend(["-kernel", kernel_path])
1368
      initrd_path = hvp[constants.HV_INITRD_PATH]
1369
      if initrd_path:
1370
        kvm_cmd.extend(["-initrd", initrd_path])
1371
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1372
                     hvp[constants.HV_KERNEL_ARGS]]
1373
      if hvp[constants.HV_SERIAL_CONSOLE]:
1374
        serial_speed = hvp[constants.HV_SERIAL_SPEED]
1375
        root_append.append("console=ttyS0,%s" % serial_speed)
1376
      kvm_cmd.extend(["-append", " ".join(root_append)])
1377

    
1378
    mem_path = hvp[constants.HV_MEM_PATH]
1379
    if mem_path:
1380
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1381

    
1382
    monitor_dev = ("unix:%s,server,nowait" %
1383
                   self._InstanceMonitor(instance.name))
1384
    kvm_cmd.extend(["-monitor", monitor_dev])
1385
    if hvp[constants.HV_SERIAL_CONSOLE]:
1386
      serial_dev = ("unix:%s,server,nowait" %
1387
                    self._InstanceSerial(instance.name))
1388
      kvm_cmd.extend(["-serial", serial_dev])
1389
    else:
1390
      kvm_cmd.extend(["-serial", "none"])
1391

    
1392
    mouse_type = hvp[constants.HV_USB_MOUSE]
1393
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1394
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1395
    spice_ip_version = None
1396

    
1397
    kvm_cmd.extend(["-usb"])
1398

    
1399
    if mouse_type:
1400
      kvm_cmd.extend(["-usbdevice", mouse_type])
1401
    elif vnc_bind_address:
1402
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1403

    
1404
    if vnc_bind_address:
1405
      if netutils.IsValidInterface(vnc_bind_address):
1406
        if_addresses = netutils.GetInterfaceIpAddresses(vnc_bind_address)
1407
        if_ip4_addresses = if_addresses[constants.IP4_VERSION]
1408
        if len(if_ip4_addresses) < 1:
1409
          logging.error("Could not determine IPv4 address of interface %s",
1410
                        vnc_bind_address)
1411
        else:
1412
          vnc_bind_address = if_ip4_addresses[0]
1413
      if netutils.IP4Address.IsValid(vnc_bind_address):
1414
        if instance.network_port > constants.VNC_BASE_PORT:
1415
          display = instance.network_port - constants.VNC_BASE_PORT
1416
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1417
            vnc_arg = ":%d" % (display)
1418
          else:
1419
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1420
        else:
1421
          logging.error("Network port is not a valid VNC display (%d < %d),"
1422
                        " not starting VNC",
1423
                        instance.network_port, constants.VNC_BASE_PORT)
1424
          vnc_arg = "none"
1425

    
1426
        # Only allow tls and other option when not binding to a file, for now.
1427
        # kvm/qemu gets confused otherwise about the filename to use.
1428
        vnc_append = ""
1429
        if hvp[constants.HV_VNC_TLS]:
1430
          vnc_append = "%s,tls" % vnc_append
1431
          if hvp[constants.HV_VNC_X509_VERIFY]:
1432
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1433
                                               hvp[constants.HV_VNC_X509])
1434
          elif hvp[constants.HV_VNC_X509]:
1435
            vnc_append = "%s,x509=%s" % (vnc_append,
1436
                                         hvp[constants.HV_VNC_X509])
1437
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1438
          vnc_append = "%s,password" % vnc_append
1439

    
1440
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1441

    
1442
      else:
1443
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1444

    
1445
      kvm_cmd.extend(["-vnc", vnc_arg])
1446
    elif spice_bind:
1447
      # FIXME: this is wrong here; the iface ip address differs
1448
      # between systems, so it should be done in _ExecuteKVMRuntime
1449
      if netutils.IsValidInterface(spice_bind):
1450
        # The user specified a network interface, we have to figure out the IP
1451
        # address.
1452
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1453
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1454

    
1455
        # if the user specified an IP version and the interface does not
1456
        # have that kind of IP addresses, throw an exception
1457
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1458
          if not addresses[spice_ip_version]:
1459
            raise errors.HypervisorError("SPICE: Unable to get an IPv%s address"
1460
                                         " for %s" % (spice_ip_version,
1461
                                                      spice_bind))
1462

    
1463
        # the user did not specify an IP version, we have to figure it out
1464
        elif (addresses[constants.IP4_VERSION] and
1465
              addresses[constants.IP6_VERSION]):
1466
          # we have both ipv4 and ipv6, let's use the cluster default IP
1467
          # version
1468
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1469
          spice_ip_version = \
1470
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1471
        elif addresses[constants.IP4_VERSION]:
1472
          spice_ip_version = constants.IP4_VERSION
1473
        elif addresses[constants.IP6_VERSION]:
1474
          spice_ip_version = constants.IP6_VERSION
1475
        else:
1476
          raise errors.HypervisorError("SPICE: Unable to get an IP address"
1477
                                       " for %s" % (spice_bind))
1478

    
1479
        spice_address = addresses[spice_ip_version][0]
1480

    
1481
      else:
1482
        # spice_bind is known to be a valid IP address, because
1483
        # ValidateParameters checked it.
1484
        spice_address = spice_bind
1485

    
1486
      spice_arg = "addr=%s" % spice_address
1487
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1488
        spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1489
                     (spice_arg, instance.network_port,
1490
                      pathutils.SPICE_CACERT_FILE))
1491
        spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1492
                     (spice_arg, pathutils.SPICE_CERT_FILE,
1493
                      pathutils.SPICE_CERT_FILE))
1494
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1495
        if tls_ciphers:
1496
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1497
      else:
1498
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1499

    
1500
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1501
        spice_arg = "%s,disable-ticketing" % spice_arg
1502

    
1503
      if spice_ip_version:
1504
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1505

    
1506
      # Image compression options
1507
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1508
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1509
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1510
      if img_lossless:
1511
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1512
      if img_jpeg:
1513
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1514
      if img_zlib_glz:
1515
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1516

    
1517
      # Video stream detection
1518
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1519
      if video_streaming:
1520
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1521

    
1522
      # Audio compression, by default in qemu-kvm it is on
1523
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1524
        spice_arg = "%s,playback-compression=off" % spice_arg
1525
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1526
        spice_arg = "%s,agent-mouse=off" % spice_arg
1527
      else:
1528
        # Enable the spice agent communication channel between the host and the
1529
        # agent.
1530
        kvm_cmd.extend(["-device", "virtio-serial-pci"])
1531
        kvm_cmd.extend([
1532
          "-device",
1533
          "virtserialport,chardev=spicechannel0,name=com.redhat.spice.0",
1534
          ])
1535
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1536

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

    
1540
    else:
1541
      # From qemu 1.4 -nographic is incompatible with -daemonize. The new way
1542
      # also works in earlier versions though (tested with 1.1 and 1.3)
1543
      if self._DISPLAY_RE.search(kvmhelp):
1544
        kvm_cmd.extend(["-display", "none"])
1545
      else:
1546
        kvm_cmd.extend(["-nographic"])
1547

    
1548
    if hvp[constants.HV_USE_LOCALTIME]:
1549
      kvm_cmd.extend(["-localtime"])
1550

    
1551
    if hvp[constants.HV_KVM_USE_CHROOT]:
1552
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1553

    
1554
    # Add qemu-KVM -cpu param
1555
    if hvp[constants.HV_CPU_TYPE]:
1556
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1557

    
1558
    # As requested by music lovers
1559
    if hvp[constants.HV_SOUNDHW]:
1560
      kvm_cmd.extend(["-soundhw", hvp[constants.HV_SOUNDHW]])
1561

    
1562
    # Pass a -vga option if requested, or if spice is used, for backwards
1563
    # compatibility.
1564
    if hvp[constants.HV_VGA]:
1565
      kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1566
    elif spice_bind:
1567
      kvm_cmd.extend(["-vga", "qxl"])
1568

    
1569
    # Various types of usb devices, comma separated
1570
    if hvp[constants.HV_USB_DEVICES]:
1571
      for dev in hvp[constants.HV_USB_DEVICES].split(","):
1572
        kvm_cmd.extend(["-usbdevice", dev])
1573

    
1574
    # Set system UUID to instance UUID
1575
    if self._UUID_RE.search(kvmhelp):
1576
      kvm_cmd.extend(["-uuid", instance.uuid])
1577

    
1578
    if hvp[constants.HV_KVM_EXTRA]:
1579
      kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
1580

    
1581
    pci_reservations = bitarray(self._DEFAULT_PCI_RESERVATIONS)
1582
    kvm_disks = []
1583
    for disk, dev_path in block_devices:
1584
      _UpdatePCISlots(disk, pci_reservations)
1585
      kvm_disks.append((disk, dev_path))
1586

    
1587
    kvm_nics = []
1588
    for nic in instance.nics:
1589
      _UpdatePCISlots(nic, pci_reservations)
1590
      kvm_nics.append(nic)
1591

    
1592
    hvparams = hvp
1593

    
1594
    return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
1595

    
1596
  def _WriteKVMRuntime(self, instance_name, data):
1597
    """Write an instance's KVM runtime
1598

1599
    """
1600
    try:
1601
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1602
                      data=data)
1603
    except EnvironmentError, err:
1604
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1605

    
1606
  def _ReadKVMRuntime(self, instance_name):
1607
    """Read an instance's KVM runtime
1608

1609
    """
1610
    try:
1611
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1612
    except EnvironmentError, err:
1613
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1614
    return file_content
1615

    
1616
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1617
    """Save an instance's KVM runtime
1618

1619
    """
1620
    kvm_cmd, kvm_nics, hvparams, block_devices = kvm_runtime
1621

    
1622
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1623
    serialized_blockdevs = [(blk.ToDict(), link) for blk, link in block_devices]
1624
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1625
                                      serialized_blockdevs))
1626

    
1627
    self._WriteKVMRuntime(instance.name, serialized_form)
1628

    
1629
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1630
    """Load an instance's KVM runtime
1631

1632
    """
1633
    if not serialized_runtime:
1634
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1635

    
1636
    loaded_runtime = serializer.Load(serialized_runtime)
1637
    if len(loaded_runtime) == 3:
1638
      serialized_blockdevs = []
1639
      kvm_cmd, serialized_nics, hvparams = loaded_runtime
1640
    else:
1641
      kvm_cmd, serialized_nics, hvparams, serialized_blockdevs = loaded_runtime
1642

    
1643
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1644
    block_devices = [(objects.Disk.FromDict(sdisk), link)
1645
                     for sdisk, link in serialized_blockdevs]
1646

    
1647
    return (kvm_cmd, kvm_nics, hvparams, block_devices)
1648

    
1649
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1650
    """Run the KVM cmd and check for errors
1651

1652
    @type name: string
1653
    @param name: instance name
1654
    @type kvm_cmd: list of strings
1655
    @param kvm_cmd: runcmd input for kvm
1656
    @type tap_fds: list of int
1657
    @param tap_fds: fds of tap devices opened by Ganeti
1658

1659
    """
1660
    try:
1661
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1662
    finally:
1663
      for fd in tap_fds:
1664
        utils_wrapper.CloseFdNoError(fd)
1665

    
1666
    if result.failed:
1667
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1668
                                   (name, result.fail_reason, result.output))
1669
    if not self._InstancePidAlive(name)[2]:
1670
      raise errors.HypervisorError("Failed to start instance %s" % name)
1671

    
1672
  # 52/50 local variables
1673
  # pylint: disable=R0914
1674
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1675
    """Execute a KVM cmd, after completing it with some last minute data.
1676

1677
    @type incoming: tuple of strings
1678
    @param incoming: (target_host_ip, port)
1679
    @type kvmhelp: string
1680
    @param kvmhelp: output of kvm --help
1681

1682
    """
1683
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1684
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1685
    #    have changed since the instance started; only use them if the change
1686
    #    won't affect the inside of the instance (which hasn't been rebooted).
1687
    #  - up_hvp contains the parameters as they were when the instance was
1688
    #    started, plus any new parameter which has been added between ganeti
1689
    #    versions: it is paramount that those default to a value which won't
1690
    #    affect the inside of the instance as well.
1691
    conf_hvp = instance.hvparams
1692
    name = instance.name
1693
    self._CheckDown(name)
1694

    
1695
    temp_files = []
1696

    
1697
    kvm_cmd, kvm_nics, up_hvp, block_devices = kvm_runtime
1698
    # the first element of kvm_cmd is always the path to the kvm binary
1699
    kvm_path = kvm_cmd[0]
1700
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1701

    
1702
    # We know it's safe to run as a different user upon migration, so we'll use
1703
    # the latest conf, from conf_hvp.
1704
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1705
    if security_model == constants.HT_SM_USER:
1706
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1707

    
1708
    keymap = conf_hvp[constants.HV_KEYMAP]
1709
    if keymap:
1710
      keymap_path = self._InstanceKeymapFile(name)
1711
      # If a keymap file is specified, KVM won't use its internal defaults. By
1712
      # first including the "en-us" layout, an error on loading the actual
1713
      # layout (e.g. because it can't be found) won't lead to a non-functional
1714
      # keyboard. A keyboard with incorrect keys is still better than none.
1715
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1716
      kvm_cmd.extend(["-k", keymap_path])
1717

    
1718
    # We have reasons to believe changing something like the nic driver/type
1719
    # upon migration won't exactly fly with the instance kernel, so for nic
1720
    # related parameters we'll use up_hvp
1721
    tapfds = []
1722
    taps = []
1723
    if not kvm_nics:
1724
      kvm_cmd.extend(["-net", "none"])
1725
    else:
1726
      vnet_hdr = False
1727
      tap_extra = ""
1728
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1729
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1730
        nic_model = self._VIRTIO
1731
        try:
1732
          devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1733
          if self._VIRTIO_NET_RE.search(devlist):
1734
            nic_model = self._VIRTIO_NET_PCI
1735
            vnet_hdr = up_hvp[constants.HV_VNET_HDR]
1736
        except errors.HypervisorError, _:
1737
          # Older versions of kvm don't support DEVICE_LIST, but they don't
1738
          # have new virtio syntax either.
1739
          pass
1740

    
1741
        if up_hvp[constants.HV_VHOST_NET]:
1742
          # check for vhost_net support
1743
          if self._VHOST_RE.search(kvmhelp):
1744
            tap_extra = ",vhost=on"
1745
          else:
1746
            raise errors.HypervisorError("vhost_net is configured"
1747
                                         " but it is not available")
1748
      else:
1749
        nic_model = nic_type
1750

    
1751
      kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
1752

    
1753
      for nic_seq, nic in enumerate(kvm_nics):
1754
        tapname, tapfd = _OpenTap(vnet_hdr=vnet_hdr)
1755
        tapfds.append(tapfd)
1756
        taps.append(tapname)
1757
        if kvm_supports_netdev:
1758
          nic_val = "%s,mac=%s" % (nic_model, nic.mac)
1759
          try:
1760
            # kvm_nics already exist in old runtime files and thus there might
1761
            # be some entries without pci slot (therefore try: except:)
1762
            kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
1763
            netdev = kvm_devid
1764
            nic_val += (",id=%s,bus=pci.0,addr=%s" % (kvm_devid, hex(nic.pci)))
1765
          except errors.HotplugError:
1766
            netdev = "netdev%d" % nic_seq
1767
          nic_val += (",netdev=%s" % netdev)
1768
          tap_val = ("type=tap,id=%s,fd=%d%s" %
1769
                     (netdev, tapfd, tap_extra))
1770
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1771
        else:
1772
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1773
                                                         nic.mac, nic_model)
1774
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1775
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1776

    
1777
    if incoming:
1778
      target, port = incoming
1779
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1780

    
1781
    # Changing the vnc password doesn't bother the guest that much. At most it
1782
    # will surprise people who connect to it. Whether positively or negatively
1783
    # it's debatable.
1784
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1785
    vnc_pwd = None
1786
    if vnc_pwd_file:
1787
      try:
1788
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1789
      except EnvironmentError, err:
1790
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1791
                                     % (vnc_pwd_file, err))
1792

    
1793
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1794
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1795
                         constants.SECURE_DIR_MODE)])
1796

    
1797
    # Automatically enable QMP if version is >= 0.14
1798
    if self._QMP_RE.search(kvmhelp):
1799
      logging.debug("Enabling QMP")
1800
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1801
                      self._InstanceQmpMonitor(instance.name)])
1802

    
1803
    # Configure the network now for starting instances and bridged interfaces,
1804
    # during FinalizeMigration for incoming instances' routed interfaces
1805
    for nic_seq, nic in enumerate(kvm_nics):
1806
      if (incoming and
1807
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1808
        continue
1809
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1810

    
1811
    bdev_opts = self._GenerateKVMBlockDevicesOptions(instance,
1812
                                                     block_devices,
1813
                                                     kvmhelp)
1814
    kvm_cmd.extend(bdev_opts)
1815
    # CPU affinity requires kvm to start paused, so we set this flag if the
1816
    # instance is not already paused and if we are not going to accept a
1817
    # migrating instance. In the latter case, pausing is not needed.
1818
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1819
    if start_kvm_paused:
1820
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1821

    
1822
    # Note: CPU pinning is using up_hvp since changes take effect
1823
    # during instance startup anyway, and to avoid problems when soft
1824
    # rebooting the instance.
1825
    cpu_pinning = False
1826
    if up_hvp.get(constants.HV_CPU_MASK, None):
1827
      cpu_pinning = True
1828

    
1829
    if security_model == constants.HT_SM_POOL:
1830
      ss = ssconf.SimpleStore()
1831
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1832
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1833
      uid = uidpool.RequestUnusedUid(all_uids)
1834
      try:
1835
        username = pwd.getpwuid(uid.GetUid()).pw_name
1836
        kvm_cmd.extend(["-runas", username])
1837
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1838
      except:
1839
        uidpool.ReleaseUid(uid)
1840
        raise
1841
      else:
1842
        uid.Unlock()
1843
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1844
    else:
1845
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1846

    
1847
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1848
                     constants.RUN_DIRS_MODE)])
1849
    for nic_seq, tap in enumerate(taps):
1850
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1851
                      data=tap)
1852

    
1853
    if vnc_pwd:
1854
      change_cmd = "change vnc password %s" % vnc_pwd
1855
      self._CallMonitorCommand(instance.name, change_cmd)
1856

    
1857
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1858
    # connection attempts because SPICE by default does not allow connections
1859
    # if neither a password nor the "disable_ticketing" options are specified.
1860
    # As soon as we send the password via QMP, that password is a valid ticket
1861
    # for connection.
1862
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1863
    if spice_password_file:
1864
      spice_pwd = ""
1865
      try:
1866
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1867
      except EnvironmentError, err:
1868
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1869
                                     % (spice_password_file, err))
1870

    
1871
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1872
      qmp.connect()
1873
      arguments = {
1874
          "protocol": "spice",
1875
          "password": spice_pwd,
1876
      }
1877
      qmp.Execute("set_password", arguments)
1878

    
1879
    for filename in temp_files:
1880
      utils.RemoveFile(filename)
1881

    
1882
    # If requested, set CPU affinity and resume instance execution
1883
    if cpu_pinning:
1884
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1885

    
1886
    start_memory = self._InstanceStartupMemory(instance)
1887
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1888
      self.BalloonInstanceMemory(instance, start_memory)
1889

    
1890
    if start_kvm_paused:
1891
      # To control CPU pinning, ballooning, and vnc/spice passwords
1892
      # the VM was started in a frozen state. If freezing was not
1893
      # explicitly requested resume the vm status.
1894
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1895

    
1896
  def StartInstance(self, instance, block_devices, startup_paused):
1897
    """Start an instance.
1898

1899
    """
1900
    self._CheckDown(instance.name)
1901
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1902
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1903
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1904
                                           startup_paused, kvmhelp)
1905
    self._SaveKVMRuntime(instance, kvm_runtime)
1906
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1907

    
1908
  def _CallMonitorCommand(self, instance_name, command):
1909
    """Invoke a command on the instance monitor.
1910

1911
    """
1912
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1913
    # version. The monitor protocol is designed for human consumption, whereas
1914
    # QMP is made for programmatic usage. In the worst case QMP can also
1915
    # execute monitor commands. As it is, all calls to socat take at least
1916
    # 500ms and likely more: socat can't detect the end of the reply and waits
1917
    # for 500ms of no data received before exiting (500 ms is the default for
1918
    # the "-t" parameter).
1919
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1920
             (utils.ShellQuote(command),
1921
              constants.SOCAT_PATH,
1922
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1923
    result = utils.RunCmd(socat)
1924
    if result.failed:
1925
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1926
             " output: %s" %
1927
             (command, instance_name, result.fail_reason, result.output))
1928
      raise errors.HypervisorError(msg)
1929

    
1930
    return result
1931

    
1932
  def _GetFreePCISlot(self, instance, dev):
1933
    """Get the first available pci slot of a runnung instance.
1934

1935
    """
1936
    slots = bitarray(32)
1937
    slots.setall(False) # pylint: disable=E1101
1938
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
1939
    for line in output.stdout.splitlines():
1940
      match = self._INFO_PCI_RE.search(line)
1941
      if match:
1942
        slot = int(match.group(1))
1943
        slots[slot] = True
1944

    
1945
    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
1946
    if not free:
1947
      raise errors.HypervisorError("All PCI slots occupied")
1948

    
1949
    dev.pci = int(free)
1950

    
1951
  def HotplugSupported(self, instance, action, dev_type):
1952
    """Check if hotplug is supported.
1953

1954
    Hotplug is *not* supported in case of:
1955
     - qemu versions < 1.0
1956
     - security models and chroot (disk hotplug)
1957
     - fdsend module is missing (nic hot-add)
1958

1959
    @raise errors.HypervisorError: in previous cases
1960

1961
    """
1962
    output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
1963
    # TODO: search for netdev_add, drive_add, device_add.....
1964
    match = self._INFO_VERSION_RE.search(output.stdout)
1965
    if not match:
1966
      raise errors.HotplugError("Try hotplug only in running instances.")
1967
    v_major, v_min, _, _ = match.groups()
1968
    if (v_major, v_min) <= (1, 0):
1969
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
1970

    
1971
    if dev_type == constants.HOTPLUG_TARGET_DISK:
1972
      hvp = instance.hvparams
1973
      security_model = hvp[constants.HV_SECURITY_MODEL]
1974
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
1975
      if use_chroot:
1976
        raise errors.HotplugError("Disk hotplug is not supported"
1977
                                  " in case of chroot.")
1978
      if security_model != constants.HT_SM_NONE:
1979
        raise errors.HotplugError("Disk Hotplug is not supported in case"
1980
                                  " security models are used.")
1981

    
1982
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
1983
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
1984
      raise errors.HotplugError("Cannot hot-add NIC."
1985
                                " fdsend python module is missing.")
1986
    return True
1987

    
1988
  def _CallHotplugCommand(self, name, cmd):
1989
    output = self._CallMonitorCommand(name, cmd)
1990
    # TODO: parse output and check if succeeded
1991
    for line in output.stdout.splitlines():
1992
      logging.info("%s", line)
1993

    
1994
  @classmethod
1995
  def _ParseKVMVersion(cls, text):
1996
    """Parse the KVM version from the --help output.
1997

1998
    @type text: string
1999
    @param text: output of kvm --help
2000
    @return: (version, v_maj, v_min, v_rev)
2001
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2002

2003
    """
2004
    match = cls._VERSION_RE.search(text.splitlines()[0])
2005
    if not match:
2006
      raise errors.HypervisorError("Unable to get KVM version")
2007

    
2008
    v_all = match.group(0)
2009
    v_maj = int(match.group(1))
2010
    v_min = int(match.group(2))
2011
    if match.group(4):
2012
      v_rev = int(match.group(4))
2013
    else:
2014
      v_rev = 0
2015
    return (v_all, v_maj, v_min, v_rev)
2016

    
2017
  @classmethod
2018
  def _GetKVMOutput(cls, kvm_path, option):
2019
    """Return the output of a kvm invocation
2020

2021
    @type kvm_path: string
2022
    @param kvm_path: path to the kvm executable
2023
    @type option: a key of _KVMOPTS_CMDS
2024
    @param option: kvm option to fetch the output from
2025
    @return: output a supported kvm invocation
2026
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2027

2028
    """
2029
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2030

    
2031
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2032

    
2033
    result = utils.RunCmd([kvm_path] + optlist)
2034
    if result.failed and not can_fail:
2035
      raise errors.HypervisorError("Unable to get KVM %s output" %
2036
                                    " ".join(cls._KVMOPTS_CMDS[option]))
2037
    return result.output
2038

    
2039
  @classmethod
2040
  def _GetKVMVersion(cls, kvm_path):
2041
    """Return the installed KVM version.
2042

2043
    @return: (version, v_maj, v_min, v_rev)
2044
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2045

2046
    """
2047
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2048

    
2049
  @classmethod
2050
  def _GetDefaultMachineVersion(cls, kvm_path):
2051
    """Return the default hardware revision (e.g. pc-1.1)
2052

2053
    """
2054
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2055
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2056
    if match:
2057
      return match.group(1)
2058
    else:
2059
      return "pc"
2060

    
2061
  def StopInstance(self, instance, force=False, retry=False, name=None):
2062
    """Stop an instance.
2063

2064
    """
2065
    if name is not None and not force:
2066
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2067
    if name is None:
2068
      name = instance.name
2069
      acpi = instance.hvparams[constants.HV_ACPI]
2070
    else:
2071
      acpi = False
2072
    _, pid, alive = self._InstancePidAlive(name)
2073
    if pid > 0 and alive:
2074
      if force or not acpi:
2075
        utils.KillProcess(pid)
2076
      else:
2077
        self._CallMonitorCommand(name, "system_powerdown")
2078

    
2079
  def CleanupInstance(self, instance_name):
2080
    """Cleanup after a stopped instance
2081

2082
    """
2083
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2084
    if pid > 0 and alive:
2085
      raise errors.HypervisorError("Cannot cleanup a live instance")
2086
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2087

    
2088
  def RebootInstance(self, instance):
2089
    """Reboot an instance.
2090

2091
    """
2092
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2093
    # socket the instance will stop, but now power up again. So we'll resort
2094
    # to shutdown and restart.
2095
    _, _, alive = self._InstancePidAlive(instance.name)
2096
    if not alive:
2097
      raise errors.HypervisorError("Failed to reboot instance %s:"
2098
                                   " not running" % instance.name)
2099
    # StopInstance will delete the saved KVM runtime so:
2100
    # ...first load it...
2101
    kvm_runtime = self._LoadKVMRuntime(instance)
2102
    # ...now we can safely call StopInstance...
2103
    if not self.StopInstance(instance):
2104
      self.StopInstance(instance, force=True)
2105
    # ...and finally we can save it again, and execute it...
2106
    self._SaveKVMRuntime(instance, kvm_runtime)
2107
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2108
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2109
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2110

    
2111
  def MigrationInfo(self, instance):
2112
    """Get instance information to perform a migration.
2113

2114
    @type instance: L{objects.Instance}
2115
    @param instance: instance to be migrated
2116
    @rtype: string
2117
    @return: content of the KVM runtime file
2118

2119
    """
2120
    return self._ReadKVMRuntime(instance.name)
2121

    
2122
  def AcceptInstance(self, instance, info, target):
2123
    """Prepare to accept an instance.
2124

2125
    @type instance: L{objects.Instance}
2126
    @param instance: instance to be accepted
2127
    @type info: string
2128
    @param info: content of the KVM runtime file on the source node
2129
    @type target: string
2130
    @param target: target host (usually ip), on this node
2131

2132
    """
2133
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2134
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2135
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2136
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2137
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2138
                            incoming=incoming_address)
2139

    
2140
  def FinalizeMigrationDst(self, instance, info, success):
2141
    """Finalize the instance migration on the target node.
2142

2143
    Stop the incoming mode KVM.
2144

2145
    @type instance: L{objects.Instance}
2146
    @param instance: instance whose migration is being finalized
2147

2148
    """
2149
    if success:
2150
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2151
      kvm_nics = kvm_runtime[1]
2152

    
2153
      for nic_seq, nic in enumerate(kvm_nics):
2154
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2155
          # Bridged interfaces have already been configured
2156
          continue
2157
        try:
2158
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2159
        except EnvironmentError, err:
2160
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2161
                          instance.name, nic_seq, str(err))
2162
          continue
2163
        try:
2164
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2165
        except errors.HypervisorError, err:
2166
          logging.warning(str(err))
2167

    
2168
      self._WriteKVMRuntime(instance.name, info)
2169
    else:
2170
      self.StopInstance(instance, force=True)
2171

    
2172
  def MigrateInstance(self, cluster_name, instance, target, live):
2173
    """Migrate an instance to a target node.
2174

2175
    The migration will not be attempted if the instance is not
2176
    currently running.
2177

2178
    @type cluster_name: string
2179
    @param cluster_name: name of the cluster
2180
    @type instance: L{objects.Instance}
2181
    @param instance: the instance to be migrated
2182
    @type target: string
2183
    @param target: ip address of the target node
2184
    @type live: boolean
2185
    @param live: perform a live migration
2186

2187
    """
2188
    instance_name = instance.name
2189
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2190
    _, _, alive = self._InstancePidAlive(instance_name)
2191
    if not alive:
2192
      raise errors.HypervisorError("Instance not running, cannot migrate")
2193

    
2194
    if not live:
2195
      self._CallMonitorCommand(instance_name, "stop")
2196

    
2197
    migrate_command = ("migrate_set_speed %dm" %
2198
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2199
    self._CallMonitorCommand(instance_name, migrate_command)
2200

    
2201
    migrate_command = ("migrate_set_downtime %dms" %
2202
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2203
    self._CallMonitorCommand(instance_name, migrate_command)
2204

    
2205
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2206
    self._CallMonitorCommand(instance_name, migrate_command)
2207

    
2208
  def FinalizeMigrationSource(self, instance, success, live):
2209
    """Finalize the instance migration on the source node.
2210

2211
    @type instance: L{objects.Instance}
2212
    @param instance: the instance that was migrated
2213
    @type success: bool
2214
    @param success: whether the migration succeeded or not
2215
    @type live: bool
2216
    @param live: whether the user requested a live migration or not
2217

2218
    """
2219
    if success:
2220
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2221
      utils.KillProcess(pid)
2222
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2223
    elif live:
2224
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2225

    
2226
  def GetMigrationStatus(self, instance):
2227
    """Get the migration status
2228

2229
    @type instance: L{objects.Instance}
2230
    @param instance: the instance that is being migrated
2231
    @rtype: L{objects.MigrationStatus}
2232
    @return: the status of the current migration (one of
2233
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2234
             progress info that can be retrieved from the hypervisor
2235

2236
    """
2237
    info_command = "info migrate"
2238
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2239
      result = self._CallMonitorCommand(instance.name, info_command)
2240
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2241
      if not match:
2242
        if not result.stdout:
2243
          logging.info("KVM: empty 'info migrate' result")
2244
        else:
2245
          logging.warning("KVM: unknown 'info migrate' result: %s",
2246
                          result.stdout)
2247
      else:
2248
        status = match.group(1)
2249
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2250
          migration_status = objects.MigrationStatus(status=status)
2251
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2252
          if match:
2253
            migration_status.transferred_ram = match.group("transferred")
2254
            migration_status.total_ram = match.group("total")
2255

    
2256
          return migration_status
2257

    
2258
        logging.warning("KVM: unknown migration status '%s'", status)
2259

    
2260
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2261

    
2262
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2263

    
2264
  def BalloonInstanceMemory(self, instance, mem):
2265
    """Balloon an instance memory to a certain value.
2266

2267
    @type instance: L{objects.Instance}
2268
    @param instance: instance to be accepted
2269
    @type mem: int
2270
    @param mem: actual memory size to use for instance runtime
2271

2272
    """
2273
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2274

    
2275
  def GetNodeInfo(self, hvparams=None):
2276
    """Return information about the node.
2277

2278
    @type hvparams: dict of strings
2279
    @param hvparams: hypervisor parameters, not used in this class
2280

2281
    @return: a dict as returned by L{BaseHypervisor.GetLinuxNodeInfo} plus
2282
        the following keys:
2283
          - hv_version: the hypervisor version in the form (major, minor,
2284
                        revision)
2285

2286
    """
2287
    result = self.GetLinuxNodeInfo()
2288
    # FIXME: this is the global kvm version, but the actual version can be
2289
    # customized as an hv parameter. we should use the nodegroup's default kvm
2290
    # path parameter here.
2291
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2292
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2293
    return result
2294

    
2295
  @classmethod
2296
  def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
2297
    """Return a command for connecting to the console of an instance.
2298

2299
    """
2300
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2301
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2302
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2303
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2304
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2305
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2306
      return objects.InstanceConsole(instance=instance.name,
2307
                                     kind=constants.CONS_SSH,
2308
                                     host=primary_node.name,
2309
                                     user=constants.SSH_CONSOLE_USER,
2310
                                     command=cmd)
2311

    
2312
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2313
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2314
      display = instance.network_port - constants.VNC_BASE_PORT
2315
      return objects.InstanceConsole(instance=instance.name,
2316
                                     kind=constants.CONS_VNC,
2317
                                     host=vnc_bind_address,
2318
                                     port=instance.network_port,
2319
                                     display=display)
2320

    
2321
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2322
    if spice_bind:
2323
      return objects.InstanceConsole(instance=instance.name,
2324
                                     kind=constants.CONS_SPICE,
2325
                                     host=spice_bind,
2326
                                     port=instance.network_port)
2327

    
2328
    return objects.InstanceConsole(instance=instance.name,
2329
                                   kind=constants.CONS_MESSAGE,
2330
                                   message=("No serial shell for instance %s" %
2331
                                            instance.name))
2332

    
2333
  def Verify(self, hvparams=None):
2334
    """Verify the hypervisor.
2335

2336
    Check that the required binaries exist.
2337

2338
    @type hvparams: dict of strings
2339
    @param hvparams: hypervisor parameters to be verified against, not used here
2340

2341
    @return: Problem description if something is wrong, C{None} otherwise
2342

2343
    """
2344
    msgs = []
2345
    # FIXME: this is the global kvm binary, but the actual path can be
2346
    # customized as an hv parameter; we should use the nodegroup's
2347
    # default kvm path parameter here.
2348
    if not os.path.exists(constants.KVM_PATH):
2349
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2350
    if not os.path.exists(constants.SOCAT_PATH):
2351
      msgs.append("The socat binary ('%s') does not exist" %
2352
                  constants.SOCAT_PATH)
2353

    
2354
    return self._FormatVerifyResults(msgs)
2355

    
2356
  @classmethod
2357
  def CheckParameterSyntax(cls, hvparams):
2358
    """Check the given parameters for validity.
2359

2360
    @type hvparams:  dict
2361
    @param hvparams: dictionary with parameter names/value
2362
    @raise errors.HypervisorError: when a parameter is not valid
2363

2364
    """
2365
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2366

    
2367
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2368
    if kernel_path:
2369
      if not hvparams[constants.HV_ROOT_PATH]:
2370
        raise errors.HypervisorError("Need a root partition for the instance,"
2371
                                     " if a kernel is defined")
2372

    
2373
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2374
        not hvparams[constants.HV_VNC_X509]):
2375
      raise errors.HypervisorError("%s must be defined, if %s is" %
2376
                                   (constants.HV_VNC_X509,
2377
                                    constants.HV_VNC_X509_VERIFY))
2378

    
2379
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2380
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2381
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2382
      if not serial_speed or serial_speed not in valid_speeds:
2383
        raise errors.HypervisorError("Invalid serial console speed, must be"
2384
                                     " one of: %s" %
2385
                                     utils.CommaJoin(valid_speeds))
2386

    
2387
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2388
    if (boot_order == constants.HT_BO_CDROM and
2389
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2390
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2391
                                   " ISO path")
2392

    
2393
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2394
    if security_model == constants.HT_SM_USER:
2395
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2396
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2397
                                     " must be specified")
2398
    elif (security_model == constants.HT_SM_NONE or
2399
          security_model == constants.HT_SM_POOL):
2400
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2401
        raise errors.HypervisorError("Cannot have a security domain when the"
2402
                                     " security model is 'none' or 'pool'")
2403

    
2404
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2405
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2406
    if spice_bind:
2407
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2408
        # if an IP version is specified, the spice_bind parameter must be an
2409
        # IP of that family
2410
        if (netutils.IP4Address.IsValid(spice_bind) and
2411
            spice_ip_version != constants.IP4_VERSION):
2412
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2413
                                       " the specified IP version is %s" %
2414
                                       (spice_bind, spice_ip_version))
2415

    
2416
        if (netutils.IP6Address.IsValid(spice_bind) and
2417
            spice_ip_version != constants.IP6_VERSION):
2418
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2419
                                       " the specified IP version is %s" %
2420
                                       (spice_bind, spice_ip_version))
2421
    else:
2422
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2423
      # error if any of them is set without it.
2424
      for param in _SPICE_ADDITIONAL_PARAMS:
2425
        if hvparams[param]:
2426
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2427
                                       (param, constants.HV_KVM_SPICE_BIND))
2428

    
2429
  @classmethod
2430
  def ValidateParameters(cls, hvparams):
2431
    """Check the given parameters for validity.
2432

2433
    @type hvparams:  dict
2434
    @param hvparams: dictionary with parameter names/value
2435
    @raise errors.HypervisorError: when a parameter is not valid
2436

2437
    """
2438
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2439

    
2440
    kvm_path = hvparams[constants.HV_KVM_PATH]
2441

    
2442
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2443
    if security_model == constants.HT_SM_USER:
2444
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2445
      try:
2446
        pwd.getpwnam(username)
2447
      except KeyError:
2448
        raise errors.HypervisorError("Unknown security domain user %s"
2449
                                     % username)
2450
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2451
    if vnc_bind_address:
2452
      bound_to_addr = netutils.IP4Address.IsValid(vnc_bind_address)
2453
      is_interface = netutils.IsValidInterface(vnc_bind_address)
2454
      is_path = utils.IsNormAbsPath(vnc_bind_address)
2455
      if not bound_to_addr and not is_interface and not is_path:
2456
        raise errors.HypervisorError("VNC: The %s parameter must be either"
2457
                                     " a valid IP address, an interface name,"
2458
                                     " or an absolute path" %
2459
                                     constants.HV_KVM_SPICE_BIND)
2460

    
2461
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2462
    if spice_bind:
2463
      # only one of VNC and SPICE can be used currently.
2464
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2465
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2466
                                     " only one of them can be used at a"
2467
                                     " given time")
2468

    
2469
      # check that KVM supports SPICE
2470
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2471
      if not cls._SPICE_RE.search(kvmhelp):
2472
        raise errors.HypervisorError("SPICE is configured, but it is not"
2473
                                     " supported according to 'kvm --help'")
2474

    
2475
      # if spice_bind is not an IP address, it must be a valid interface
2476
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2477
                       netutils.IP6Address.IsValid(spice_bind))
2478
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2479
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2480
                                     " a valid IP address or interface name" %
2481
                                     constants.HV_KVM_SPICE_BIND)
2482

    
2483
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2484
    if machine_version:
2485
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2486
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2487
        raise errors.HypervisorError("Unsupported machine version: %s" %
2488
                                     machine_version)
2489

    
2490
  @classmethod
2491
  def PowercycleNode(cls, hvparams=None):
2492
    """KVM powercycle, just a wrapper over Linux powercycle.
2493

2494
    @type hvparams: dict of strings
2495
    @param hvparams: hypervisor params to be used on this node
2496

2497
    """
2498
    cls.LinuxPowercycle()