(2.10) KVM: use running HVPs to calc blockdev options
[ganeti-local] / lib / hypervisor / hv_kvm.py
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-ifup-custom"
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 as a list of in tuples
94 # (L{objects.Disk}, link_name)
95 _KVM_NICS_RUNTIME_INDEX = 1
96 _KVM_DISKS_RUNTIME_INDEX = 3
97 _DEVICE_RUNTIME_INDEX = {
98   constants.HOTPLUG_TARGET_DISK: _KVM_DISKS_RUNTIME_INDEX,
99   constants.HOTPLUG_TARGET_NIC: _KVM_NICS_RUNTIME_INDEX
100   }
101 _FIND_RUNTIME_ENTRY = {
102   constants.HOTPLUG_TARGET_NIC:
103     lambda nic, kvm_nics: [n for n in kvm_nics if n.uuid == nic.uuid],
104   constants.HOTPLUG_TARGET_DISK:
105     lambda disk, kvm_disks: [(d, l) for (d, l) in kvm_disks
106                              if d.uuid == disk.uuid]
107   }
108 _RUNTIME_DEVICE = {
109   constants.HOTPLUG_TARGET_NIC: lambda d: d,
110   constants.HOTPLUG_TARGET_DISK: lambda (d, e): d
111   }
112 _RUNTIME_ENTRY = {
113   constants.HOTPLUG_TARGET_NIC: lambda d, e: d,
114   constants.HOTPLUG_TARGET_DISK: lambda d, e: (d, e)
115   }
116
117 _MIGRATION_CAPS_DELIM = ":"
118
119
120 def _GenerateDeviceKVMId(dev_type, dev, idx=None):
121   """Helper function to generate a unique device name used by KVM
122
123   QEMU monitor commands use names to identify devices. Here we use their pci
124   slot and a part of their UUID to name them. dev.pci might be None for old
125   devices in the cluster.
126
127   @type dev_type: sting
128   @param dev_type: device type of param dev
129   @type dev: L{objects.Disk} or L{objects.NIC}
130   @param dev: the device object for which we generate a kvm name
131   @raise errors.HotplugError: in case a device has no pci slot (old devices)
132
133   """
134
135   # proper device id - available in latest Ganeti versions
136   if dev.pci and dev.uuid:
137     return "%s-%s-pci-%d" % (dev_type.lower(), dev.uuid.split("-")[0], dev.pci)
138
139   # dummy device id - returned only to _GenerateKVMBlockDevicesOptions
140   # This enables -device option for paravirtual disk_type
141   if idx is not None:
142     return "%s-%d" % (dev_type.lower(), idx)
143
144   raise errors.HotplugError("Hotplug is not supported for devices"
145                             " without UUID or PCI info")
146
147
148 def _GetFreeSlot(slots, slot=None, reserve=False):
149   """Helper method to get first available slot in a bitarray
150
151   @type slots: bitarray
152   @param slots: the bitarray to operate on
153   @type slot: integer
154   @param slot: if given we check whether the slot is free
155   @type reserve: boolean
156   @param reserve: whether to reserve the first available slot or not
157   @return: the idx of the (first) available slot
158   @raise errors.HotplugError: If all slots in a bitarray are occupied
159     or the given slot is not free.
160
161   """
162   if slot is not None:
163     assert slot < len(slots)
164     if slots[slot]:
165       raise errors.HypervisorError("Slots %d occupied" % slot)
166
167   else:
168     avail = slots.search(_AVAILABLE_PCI_SLOT, 1)
169     if not avail:
170       raise errors.HypervisorError("All slots occupied")
171
172     slot = int(avail[0])
173
174   if reserve:
175     slots[slot] = True
176
177   return slot
178
179
180 def _GetExistingDeviceInfo(dev_type, device, runtime):
181   """Helper function to get an existing device inside the runtime file
182
183   Used when an instance is running. Load kvm runtime file and search
184   for a device based on its type and uuid.
185
186   @type dev_type: sting
187   @param dev_type: device type of param dev
188   @type device: L{objects.Disk} or L{objects.NIC}
189   @param device: the device object for which we generate a kvm name
190   @type runtime: tuple (cmd, nics, hvparams, disks)
191   @param runtime: the runtime data to search for the device
192   @raise errors.HotplugError: in case the requested device does not
193     exist (e.g. device has been added without --hotplug option) or
194     device info has not pci slot (e.g. old devices in the cluster)
195
196   """
197   index = _DEVICE_RUNTIME_INDEX[dev_type]
198   found = _FIND_RUNTIME_ENTRY[dev_type](device, runtime[index])
199   if not found:
200     raise errors.HotplugError("Cannot find runtime info for %s with UUID %s" %
201                               (dev_type, device.uuid))
202
203   return found[0]
204
205
206 def _UpgradeSerializedRuntime(serialized_runtime):
207   """Upgrade runtime data
208
209   Remove any deprecated fields or change the format of the data.
210   The runtime files are not upgraded when Ganeti is upgraded, so the required
211   modification have to be performed here.
212
213   @type serialized_runtime: string
214   @param serialized_runtime: raw text data read from actual runtime file
215   @return: (cmd, nic dicts, hvparams, bdev dicts)
216   @rtype: tuple
217
218   """
219   loaded_runtime = serializer.Load(serialized_runtime)
220   kvm_cmd, serialized_nics, hvparams = loaded_runtime[:3]
221   if len(loaded_runtime) >= 4:
222     serialized_disks = loaded_runtime[3]
223   else:
224     serialized_disks = []
225
226   for nic in serialized_nics:
227     # Add a dummy uuid slot if an pre-2.8 NIC is found
228     if "uuid" not in nic:
229       nic["uuid"] = utils.NewUUID()
230
231   return kvm_cmd, serialized_nics, hvparams, serialized_disks
232
233
234 def _AnalyzeSerializedRuntime(serialized_runtime):
235   """Return runtime entries for a serialized runtime file
236
237   @type serialized_runtime: string
238   @param serialized_runtime: raw text data read from actual runtime file
239   @return: (cmd, nics, hvparams, bdevs)
240   @rtype: tuple
241
242   """
243   kvm_cmd, serialized_nics, hvparams, serialized_disks = \
244     _UpgradeSerializedRuntime(serialized_runtime)
245   kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
246   kvm_disks = [(objects.Disk.FromDict(sdisk), link)
247                for sdisk, link in serialized_disks]
248
249   return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
250
251
252 def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
253   """Retrieves supported TUN features from file descriptor.
254
255   @see: L{_ProbeTapVnetHdr}
256
257   """
258   req = struct.pack("I", 0)
259   try:
260     buf = _ioctl(fd, TUNGETFEATURES, req)
261   except EnvironmentError, err:
262     logging.warning("ioctl(TUNGETFEATURES) failed: %s", err)
263     return None
264   else:
265     (flags, ) = struct.unpack("I", buf)
266     return flags
267
268
269 def _ProbeTapVnetHdr(fd, _features_fn=_GetTunFeatures):
270   """Check whether to enable the IFF_VNET_HDR flag.
271
272   To do this, _all_ of the following conditions must be met:
273    1. TUNGETFEATURES ioctl() *must* be implemented
274    2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
275    3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
276       drivers/net/tun.c there is no way to test this until after the tap device
277       has been created using TUNSETIFF, and there is no way to change the
278       IFF_VNET_HDR flag after creating the interface, catch-22! However both
279       TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
280       thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
281
282    @type fd: int
283    @param fd: the file descriptor of /dev/net/tun
284
285   """
286   flags = _features_fn(fd)
287
288   if flags is None:
289     # Not supported
290     return False
291
292   result = bool(flags & IFF_VNET_HDR)
293
294   if not result:
295     logging.warning("Kernel does not support IFF_VNET_HDR, not enabling")
296
297   return result
298
299
300 def _OpenTap(vnet_hdr=True):
301   """Open a new tap device and return its file descriptor.
302
303   This is intended to be used by a qemu-type hypervisor together with the -net
304   tap,fd=<fd> command line parameter.
305
306   @type vnet_hdr: boolean
307   @param vnet_hdr: Enable the VNET Header
308   @return: (ifname, tapfd)
309   @rtype: tuple
310
311   """
312   try:
313     tapfd = os.open("/dev/net/tun", os.O_RDWR)
314   except EnvironmentError:
315     raise errors.HypervisorError("Failed to open /dev/net/tun")
316
317   flags = IFF_TAP | IFF_NO_PI
318
319   if vnet_hdr and _ProbeTapVnetHdr(tapfd):
320     flags |= IFF_VNET_HDR
321
322   # The struct ifreq ioctl request (see netdevice(7))
323   ifr = struct.pack("16sh", "", flags)
324
325   try:
326     res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
327   except EnvironmentError, err:
328     raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
329                                  err)
330
331   # Get the interface name from the ioctl
332   ifname = struct.unpack("16sh", res)[0].strip("\x00")
333   return (ifname, tapfd)
334
335
336 class QmpMessage:
337   """QEMU Messaging Protocol (QMP) message.
338
339   """
340   def __init__(self, data):
341     """Creates a new QMP message based on the passed data.
342
343     """
344     if not isinstance(data, dict):
345       raise TypeError("QmpMessage must be initialized with a dict")
346
347     self.data = data
348
349   def __getitem__(self, field_name):
350     """Get the value of the required field if present, or None.
351
352     Overrides the [] operator to provide access to the message data,
353     returning None if the required item is not in the message
354     @return: the value of the field_name field, or None if field_name
355              is not contained in the message
356
357     """
358     return self.data.get(field_name, None)
359
360   def __setitem__(self, field_name, field_value):
361     """Set the value of the required field_name to field_value.
362
363     """
364     self.data[field_name] = field_value
365
366   @staticmethod
367   def BuildFromJsonString(json_string):
368     """Build a QmpMessage from a JSON encoded string.
369
370     @type json_string: str
371     @param json_string: JSON string representing the message
372     @rtype: L{QmpMessage}
373     @return: a L{QmpMessage} built from json_string
374
375     """
376     # Parse the string
377     data = serializer.LoadJson(json_string)
378     return QmpMessage(data)
379
380   def __str__(self):
381     # The protocol expects the JSON object to be sent as a single line.
382     return serializer.DumpJson(self.data)
383
384   def __eq__(self, other):
385     # When comparing two QmpMessages, we are interested in comparing
386     # their internal representation of the message data
387     return self.data == other.data
388
389
390 class MonitorSocket(object):
391   _SOCKET_TIMEOUT = 5
392
393   def __init__(self, monitor_filename):
394     """Instantiates the MonitorSocket object.
395
396     @type monitor_filename: string
397     @param monitor_filename: the filename of the UNIX raw socket on which the
398                              monitor (QMP or simple one) is listening
399
400     """
401     self.monitor_filename = monitor_filename
402     self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
403     # We want to fail if the server doesn't send a complete message
404     # in a reasonable amount of time
405     self.sock.settimeout(self._SOCKET_TIMEOUT)
406     self._connected = False
407
408   def _check_socket(self):
409     sock_stat = None
410     try:
411       sock_stat = os.stat(self.monitor_filename)
412     except EnvironmentError, err:
413       if err.errno == errno.ENOENT:
414         raise errors.HypervisorError("No monitor socket found")
415       else:
416         raise errors.HypervisorError("Error checking monitor socket: %s",
417                                      utils.ErrnoOrStr(err))
418     if not stat.S_ISSOCK(sock_stat.st_mode):
419       raise errors.HypervisorError("Monitor socket is not a socket")
420
421   def _check_connection(self):
422     """Make sure that the connection is established.
423
424     """
425     if not self._connected:
426       raise errors.ProgrammerError("To use a MonitorSocket you need to first"
427                                    " invoke connect() on it")
428
429   def connect(self):
430     """Connects to the monitor.
431
432     Connects to the UNIX socket
433
434     @raise errors.HypervisorError: when there are communication errors
435
436     """
437     if self._connected:
438       raise errors.ProgrammerError("Cannot connect twice")
439
440     self._check_socket()
441
442     # Check file existance/stuff
443     try:
444       self.sock.connect(self.monitor_filename)
445     except EnvironmentError:
446       raise errors.HypervisorError("Can't connect to qmp socket")
447     self._connected = True
448
449   def close(self):
450     """Closes the socket
451
452     It cannot be used after this call.
453
454     """
455     self.sock.close()
456
457
458 class QmpConnection(MonitorSocket):
459   """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
460
461   """
462   _FIRST_MESSAGE_KEY = "QMP"
463   _EVENT_KEY = "event"
464   _ERROR_KEY = "error"
465   _RETURN_KEY = RETURN_KEY = "return"
466   _ACTUAL_KEY = ACTUAL_KEY = "actual"
467   _ERROR_CLASS_KEY = "class"
468   _ERROR_DESC_KEY = "desc"
469   _EXECUTE_KEY = "execute"
470   _ARGUMENTS_KEY = "arguments"
471   _CAPABILITIES_COMMAND = "qmp_capabilities"
472   _MESSAGE_END_TOKEN = "\r\n"
473
474   def __init__(self, monitor_filename):
475     super(QmpConnection, self).__init__(monitor_filename)
476     self._buf = ""
477
478   def connect(self):
479     """Connects to the QMP monitor.
480
481     Connects to the UNIX socket and makes sure that we can actually send and
482     receive data to the kvm instance via QMP.
483
484     @raise errors.HypervisorError: when there are communication errors
485     @raise errors.ProgrammerError: when there are data serialization errors
486
487     """
488     super(QmpConnection, self).connect()
489     # Check if we receive a correct greeting message from the server
490     # (As per the QEMU Protocol Specification 0.1 - section 2.2)
491     greeting = self._Recv()
492     if not greeting[self._FIRST_MESSAGE_KEY]:
493       self._connected = False
494       raise errors.HypervisorError("kvm: QMP communication error (wrong"
495                                    " server greeting")
496
497     # This is needed because QMP can return more than one greetings
498     # see https://groups.google.com/d/msg/ganeti-devel/gZYcvHKDooU/SnukC8dgS5AJ
499     self._buf = ""
500
501     # Let's put the monitor in command mode using the qmp_capabilities
502     # command, or else no command will be executable.
503     # (As per the QEMU Protocol Specification 0.1 - section 4)
504     self.Execute(self._CAPABILITIES_COMMAND)
505
506   def _ParseMessage(self, buf):
507     """Extract and parse a QMP message from the given buffer.
508
509     Seeks for a QMP message in the given buf. If found, it parses it and
510     returns it together with the rest of the characters in the buf.
511     If no message is found, returns None and the whole buffer.
512
513     @raise errors.ProgrammerError: when there are data serialization errors
514
515     """
516     message = None
517     # Check if we got the message end token (CRLF, as per the QEMU Protocol
518     # Specification 0.1 - Section 2.1.1)
519     pos = buf.find(self._MESSAGE_END_TOKEN)
520     if pos >= 0:
521       try:
522         message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
523       except Exception, err:
524         raise errors.ProgrammerError("QMP data serialization error: %s" % err)
525       buf = buf[pos + 1:]
526
527     return (message, buf)
528
529   def _Recv(self):
530     """Receives a message from QMP and decodes the received JSON object.
531
532     @rtype: QmpMessage
533     @return: the received message
534     @raise errors.HypervisorError: when there are communication errors
535     @raise errors.ProgrammerError: when there are data serialization errors
536
537     """
538     self._check_connection()
539
540     # Check if there is already a message in the buffer
541     (message, self._buf) = self._ParseMessage(self._buf)
542     if message:
543       return message
544
545     recv_buffer = StringIO.StringIO(self._buf)
546     recv_buffer.seek(len(self._buf))
547     try:
548       while True:
549         data = self.sock.recv(4096)
550         if not data:
551           break
552         recv_buffer.write(data)
553
554         (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
555         if message:
556           return message
557
558     except socket.timeout, err:
559       raise errors.HypervisorError("Timeout while receiving a QMP message: "
560                                    "%s" % (err))
561     except socket.error, err:
562       raise errors.HypervisorError("Unable to receive data from KVM using the"
563                                    " QMP protocol: %s" % err)
564
565   def _Send(self, message):
566     """Encodes and sends a message to KVM using QMP.
567
568     @type message: QmpMessage
569     @param message: message to send to KVM
570     @raise errors.HypervisorError: when there are communication errors
571     @raise errors.ProgrammerError: when there are data serialization errors
572
573     """
574     self._check_connection()
575     try:
576       message_str = str(message)
577     except Exception, err:
578       raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
579
580     try:
581       self.sock.sendall(message_str)
582     except socket.timeout, err:
583       raise errors.HypervisorError("Timeout while sending a QMP message: "
584                                    "%s (%s)" % (err.string, err.errno))
585     except socket.error, err:
586       raise errors.HypervisorError("Unable to send data from KVM using the"
587                                    " QMP protocol: %s" % err)
588
589   def Execute(self, command, arguments=None):
590     """Executes a QMP command and returns the response of the server.
591
592     @type command: str
593     @param command: the command to execute
594     @type arguments: dict
595     @param arguments: dictionary of arguments to be passed to the command
596     @rtype: dict
597     @return: dictionary representing the received JSON object
598     @raise errors.HypervisorError: when there are communication errors
599     @raise errors.ProgrammerError: when there are data serialization errors
600
601     """
602     self._check_connection()
603     message = QmpMessage({self._EXECUTE_KEY: command})
604     if arguments:
605       message[self._ARGUMENTS_KEY] = arguments
606     self._Send(message)
607
608     # Events can occur between the sending of the command and the reception
609     # of the response, so we need to filter out messages with the event key.
610     while True:
611       response = self._Recv()
612       err = response[self._ERROR_KEY]
613       if err:
614         raise errors.HypervisorError("kvm: error executing the %s"
615                                      " command: %s (%s):" %
616                                      (command,
617                                       err[self._ERROR_DESC_KEY],
618                                       err[self._ERROR_CLASS_KEY]))
619
620       elif not response[self._EVENT_KEY]:
621         return response
622
623
624 class KVMHypervisor(hv_base.BaseHypervisor):
625   """KVM hypervisor interface
626
627   """
628   CAN_MIGRATE = True
629
630   _ROOT_DIR = pathutils.RUN_DIR + "/kvm-hypervisor"
631   _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
632   _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
633   _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
634   _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
635   _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
636   _KEYMAP_DIR = _ROOT_DIR + "/keymap" # contains instances keymaps
637   # KVM instances with chroot enabled are started in empty chroot directories.
638   _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
639   # After an instance is stopped, its chroot directory is removed.
640   # If the chroot directory is not empty, it can't be removed.
641   # A non-empty chroot directory indicates a possible security incident.
642   # To support forensics, the non-empty chroot directory is quarantined in
643   # a separate directory, called 'chroot-quarantine'.
644   _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
645   _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
646            _CHROOT_DIR, _CHROOT_QUARANTINE_DIR, _KEYMAP_DIR]
647
648   PARAMETERS = {
649     constants.HV_KVM_PATH: hv_base.REQ_FILE_CHECK,
650     constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
651     constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
652     constants.HV_ROOT_PATH: hv_base.NO_CHECK,
653     constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
654     constants.HV_ACPI: hv_base.NO_CHECK,
655     constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
656     constants.HV_SERIAL_SPEED: hv_base.NO_CHECK,
657     constants.HV_VNC_BIND_ADDRESS:
658       (False, lambda x: (netutils.IP4Address.IsValid(x) or
659                          utils.IsNormAbsPath(x)),
660        "The VNC bind address must be either a valid IP address or an absolute"
661        " pathname", None, None),
662     constants.HV_VNC_TLS: hv_base.NO_CHECK,
663     constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
664     constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
665     constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
666     constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
667     constants.HV_KVM_SPICE_IP_VERSION:
668       (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
669                          x in constants.VALID_IP_VERSIONS),
670        "The SPICE IP version should be 4 or 6",
671        None, None),
672     constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
673     constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
674       hv_base.ParamInSet(
675         False, constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
676     constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
677       hv_base.ParamInSet(
678         False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
679     constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
680       hv_base.ParamInSet(
681         False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
682     constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
683       hv_base.ParamInSet(
684         False, constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
685     constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
686     constants.HV_KVM_SPICE_USE_TLS: hv_base.NO_CHECK,
687     constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
688     constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
689     constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
690     constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
691     constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
692     constants.HV_BOOT_ORDER:
693       hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
694     constants.HV_NIC_TYPE:
695       hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
696     constants.HV_DISK_TYPE:
697       hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
698     constants.HV_KVM_CDROM_DISK_TYPE:
699       hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
700     constants.HV_USB_MOUSE:
701       hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
702     constants.HV_KEYMAP: hv_base.NO_CHECK,
703     constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
704     constants.HV_MIGRATION_BANDWIDTH: hv_base.REQ_NONNEGATIVE_INT_CHECK,
705     constants.HV_MIGRATION_DOWNTIME: hv_base.REQ_NONNEGATIVE_INT_CHECK,
706     constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
707     constants.HV_KVM_MIGRATION_CAPS: hv_base.NO_CHECK,
708     constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
709     constants.HV_DISK_CACHE:
710       hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
711     constants.HV_SECURITY_MODEL:
712       hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
713     constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
714     constants.HV_KVM_FLAG:
715       hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
716     constants.HV_VHOST_NET: hv_base.NO_CHECK,
717     constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
718     constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
719     constants.HV_REBOOT_BEHAVIOR:
720       hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
721     constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
722     constants.HV_CPU_TYPE: hv_base.NO_CHECK,
723     constants.HV_CPU_CORES: hv_base.OPT_NONNEGATIVE_INT_CHECK,
724     constants.HV_CPU_THREADS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
725     constants.HV_CPU_SOCKETS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
726     constants.HV_SOUNDHW: hv_base.NO_CHECK,
727     constants.HV_USB_DEVICES: hv_base.NO_CHECK,
728     constants.HV_VGA: hv_base.NO_CHECK,
729     constants.HV_KVM_EXTRA: hv_base.NO_CHECK,
730     constants.HV_KVM_MACHINE_VERSION: hv_base.NO_CHECK,
731     constants.HV_VNET_HDR: hv_base.NO_CHECK,
732     }
733
734   _VIRTIO = "virtio"
735   _VIRTIO_NET_PCI = "virtio-net-pci"
736   _VIRTIO_BLK_PCI = "virtio-blk-pci"
737
738   _MIGRATION_STATUS_RE = re.compile("Migration\s+status:\s+(\w+)",
739                                     re.M | re.I)
740   _MIGRATION_PROGRESS_RE = \
741     re.compile(r"\s*transferred\s+ram:\s+(?P<transferred>\d+)\s+kbytes\s*\n"
742                r"\s*remaining\s+ram:\s+(?P<remaining>\d+)\s+kbytes\s*\n"
743                r"\s*total\s+ram:\s+(?P<total>\d+)\s+kbytes\s*\n", re.I)
744
745   _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
746   _MIGRATION_INFO_RETRY_DELAY = 2
747
748   _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
749
750   _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
751   _CPU_INFO_CMD = "info cpus"
752   _CONT_CMD = "cont"
753
754   _DEFAULT_MACHINE_VERSION_RE = re.compile(r"^(\S+).*\(default\)", re.M)
755   _CHECK_MACHINE_VERSION_RE = \
756     staticmethod(lambda x: re.compile(r"^(%s)[ ]+.*PC" % x, re.M))
757
758   _QMP_RE = re.compile(r"^-qmp\s", re.M)
759   _SPICE_RE = re.compile(r"^-spice\s", re.M)
760   _VHOST_RE = re.compile(r"^-net\s.*,vhost=on|off", re.M)
761   _ENABLE_KVM_RE = re.compile(r"^-enable-kvm\s", re.M)
762   _DISABLE_KVM_RE = re.compile(r"^-disable-kvm\s", re.M)
763   _NETDEV_RE = re.compile(r"^-netdev\s", re.M)
764   _DISPLAY_RE = re.compile(r"^-display\s", re.M)
765   _MACHINE_RE = re.compile(r"^-machine\s", re.M)
766   _VIRTIO_NET_RE = re.compile(r"^name \"%s\"" % _VIRTIO_NET_PCI, re.M)
767   _VIRTIO_BLK_RE = re.compile(r"^name \"%s\"" % _VIRTIO_BLK_PCI, re.M)
768   # match  -drive.*boot=on|off on different lines, but in between accept only
769   # dashes not preceeded by a new line (which would mean another option
770   # different than -drive is starting)
771   _BOOT_RE = re.compile(r"^-drive\s([^-]|(?<!^)-)*,boot=on\|off", re.M | re.S)
772
773   _INFO_PCI_RE = re.compile(r'Bus.*device[ ]*(\d+).*')
774   _INFO_PCI_CMD = "info pci"
775   _FIND_PCI_DEVICE_RE = \
776     staticmethod(lambda pci, devid:
777       re.compile(r'Bus.*device[ ]*%d,(.*\n){5,6}.*id "%s"' % (pci, devid),
778                  re.M))
779
780   _INFO_VERSION_RE = \
781     re.compile(r'^QEMU (\d+)\.(\d+)(\.(\d+))?.*monitor.*', re.M)
782   _INFO_VERSION_CMD = "info version"
783
784   # Slot 0 for Host bridge, Slot 1 for ISA bridge, Slot 2 for VGA controller
785   _DEFAULT_PCI_RESERVATIONS = "11100000000000000000000000000000"
786   _SOUNDHW_WITH_PCI_SLOT = ["ac97", "es1370", "hda"]
787
788   ANCILLARY_FILES = [
789     _KVM_NETWORK_SCRIPT,
790     ]
791   ANCILLARY_FILES_OPT = [
792     _KVM_NETWORK_SCRIPT,
793     ]
794
795   # Supported kvm options to get output from
796   _KVMOPT_HELP = "help"
797   _KVMOPT_MLIST = "mlist"
798   _KVMOPT_DEVICELIST = "devicelist"
799
800   # Command to execute to get the output from kvm, and whether to
801   # accept the output even on failure.
802   _KVMOPTS_CMDS = {
803     _KVMOPT_HELP: (["--help"], False),
804     _KVMOPT_MLIST: (["-M", "?"], False),
805     _KVMOPT_DEVICELIST: (["-device", "?"], True),
806   }
807
808   def __init__(self):
809     hv_base.BaseHypervisor.__init__(self)
810     # Let's make sure the directories we need exist, even if the RUN_DIR lives
811     # in a tmpfs filesystem or has been otherwise wiped out.
812     dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
813     utils.EnsureDirs(dirs)
814
815   @classmethod
816   def _InstancePidFile(cls, instance_name):
817     """Returns the instance pidfile.
818
819     """
820     return utils.PathJoin(cls._PIDS_DIR, instance_name)
821
822   @classmethod
823   def _InstanceUidFile(cls, instance_name):
824     """Returns the instance uidfile.
825
826     """
827     return utils.PathJoin(cls._UIDS_DIR, instance_name)
828
829   @classmethod
830   def _InstancePidInfo(cls, pid):
831     """Check pid file for instance information.
832
833     Check that a pid file is associated with an instance, and retrieve
834     information from its command line.
835
836     @type pid: string or int
837     @param pid: process id of the instance to check
838     @rtype: tuple
839     @return: (instance_name, memory, vcpus)
840     @raise errors.HypervisorError: when an instance cannot be found
841
842     """
843     alive = utils.IsProcessAlive(pid)
844     if not alive:
845       raise errors.HypervisorError("Cannot get info for pid %s" % pid)
846
847     cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
848     try:
849       cmdline = utils.ReadFile(cmdline_file)
850     except EnvironmentError, err:
851       raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
852                                    (pid, err))
853
854     instance = None
855     memory = 0
856     vcpus = 0
857
858     arg_list = cmdline.split("\x00")
859     while arg_list:
860       arg = arg_list.pop(0)
861       if arg == "-name":
862         instance = arg_list.pop(0)
863       elif arg == "-m":
864         memory = int(arg_list.pop(0))
865       elif arg == "-smp":
866         vcpus = int(arg_list.pop(0).split(",")[0])
867
868     if instance is None:
869       raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
870                                    " instance" % pid)
871
872     return (instance, memory, vcpus)
873
874   def _InstancePidAlive(self, instance_name):
875     """Returns the instance pidfile, pid, and liveness.
876
877     @type instance_name: string
878     @param instance_name: instance name
879     @rtype: tuple
880     @return: (pid file name, pid, liveness)
881
882     """
883     pidfile = self._InstancePidFile(instance_name)
884     pid = utils.ReadPidFile(pidfile)
885
886     alive = False
887     try:
888       cmd_instance = self._InstancePidInfo(pid)[0]
889       alive = (cmd_instance == instance_name)
890     except errors.HypervisorError:
891       pass
892
893     return (pidfile, pid, alive)
894
895   def _CheckDown(self, instance_name):
896     """Raises an error unless the given instance is down.
897
898     """
899     alive = self._InstancePidAlive(instance_name)[2]
900     if alive:
901       raise errors.HypervisorError("Failed to start instance %s: %s" %
902                                    (instance_name, "already running"))
903
904   @classmethod
905   def _InstanceMonitor(cls, instance_name):
906     """Returns the instance monitor socket name
907
908     """
909     return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
910
911   @classmethod
912   def _InstanceSerial(cls, instance_name):
913     """Returns the instance serial socket name
914
915     """
916     return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
917
918   @classmethod
919   def _InstanceQmpMonitor(cls, instance_name):
920     """Returns the instance serial QMP socket name
921
922     """
923     return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
924
925   @staticmethod
926   def _SocatUnixConsoleParams():
927     """Returns the correct parameters for socat
928
929     If we have a new-enough socat we can use raw mode with an escape character.
930
931     """
932     if constants.SOCAT_USE_ESCAPE:
933       return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
934     else:
935       return "echo=0,icanon=0"
936
937   @classmethod
938   def _InstanceKVMRuntime(cls, instance_name):
939     """Returns the instance KVM runtime filename
940
941     """
942     return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
943
944   @classmethod
945   def _InstanceChrootDir(cls, instance_name):
946     """Returns the name of the KVM chroot dir of the instance
947
948     """
949     return utils.PathJoin(cls._CHROOT_DIR, instance_name)
950
951   @classmethod
952   def _InstanceNICDir(cls, instance_name):
953     """Returns the name of the directory holding the tap device files for a
954     given instance.
955
956     """
957     return utils.PathJoin(cls._NICS_DIR, instance_name)
958
959   @classmethod
960   def _InstanceNICFile(cls, instance_name, seq_or_uuid):
961     """Returns the name of the file containing the tap device for a given NIC
962
963     """
964     return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq_or_uuid))
965
966   @classmethod
967   def _GetInstanceNICTap(cls, instance_name, nic):
968     """Returns the tap for the corresponding nic
969
970     Search for tap file named after NIC's uuid.
971     For old instances without uuid indexed tap files returns nothing.
972
973     """
974     try:
975       return utils.ReadFile(cls._InstanceNICFile(instance_name, nic.uuid))
976     except EnvironmentError:
977       pass
978
979   @classmethod
980   def _WriteInstanceNICFiles(cls, instance_name, seq, nic, tap):
981     """Write tap name to both instance NIC files
982
983     """
984     for ident in [seq, nic.uuid]:
985       utils.WriteFile(cls._InstanceNICFile(instance_name, ident), data=tap)
986
987   @classmethod
988   def _RemoveInstanceNICFiles(cls, instance_name, seq, nic):
989     """Write tap name to both instance NIC files
990
991     """
992     for ident in [seq, nic.uuid]:
993       utils.RemoveFile(cls._InstanceNICFile(instance_name, ident))
994
995   @classmethod
996   def _InstanceKeymapFile(cls, instance_name):
997     """Returns the name of the file containing the keymap for a given instance
998
999     """
1000     return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
1001
1002   @classmethod
1003   def _TryReadUidFile(cls, uid_file):
1004     """Try to read a uid file
1005
1006     """
1007     if os.path.exists(uid_file):
1008       try:
1009         uid = int(utils.ReadOneLineFile(uid_file))
1010         return uid
1011       except EnvironmentError:
1012         logging.warning("Can't read uid file", exc_info=True)
1013       except (TypeError, ValueError):
1014         logging.warning("Can't parse uid file contents", exc_info=True)
1015     return None
1016
1017   @classmethod
1018   def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
1019     """Removes an instance's rutime sockets/files/dirs.
1020
1021     """
1022     # This takes info from NICDir and RuntimeFile
1023     cls._UnconfigureInstanceNICs(instance_name)
1024     utils.RemoveFile(pidfile)
1025     utils.RemoveFile(cls._InstanceMonitor(instance_name))
1026     utils.RemoveFile(cls._InstanceSerial(instance_name))
1027     utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
1028     utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
1029     utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
1030     uid_file = cls._InstanceUidFile(instance_name)
1031     uid = cls._TryReadUidFile(uid_file)
1032     utils.RemoveFile(uid_file)
1033     if uid is not None:
1034       uidpool.ReleaseUid(uid)
1035     try:
1036       shutil.rmtree(cls._InstanceNICDir(instance_name))
1037     except OSError, err:
1038       if err.errno != errno.ENOENT:
1039         raise
1040     try:
1041       chroot_dir = cls._InstanceChrootDir(instance_name)
1042       utils.RemoveDir(chroot_dir)
1043     except OSError, err:
1044       if err.errno == errno.ENOTEMPTY:
1045         # The chroot directory is expected to be empty, but it isn't.
1046         new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
1047                                           prefix="%s-%s-" %
1048                                           (instance_name,
1049                                            utils.TimestampForFilename()))
1050         logging.warning("The chroot directory of instance %s can not be"
1051                         " removed as it is not empty. Moving it to the"
1052                         " quarantine instead. Please investigate the"
1053                         " contents (%s) and clean up manually",
1054                         instance_name, new_chroot_dir)
1055         utils.RenameFile(chroot_dir, new_chroot_dir)
1056       else:
1057         raise
1058
1059   @staticmethod
1060   def _CreateNICEnv(instance_name, nic, tap, seq=None, instance_tags=None):
1061     """Create environment variables for a specific NIC
1062
1063     This is needed during NIC ifup/ifdown scripts.
1064     Since instance tags may change during NIC creation and removal
1065     and because during cleanup instance object is not available we
1066     pass them only upon NIC creation (instance startup/NIC hot-plugging).
1067
1068     """
1069     env = {
1070       "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
1071       "INSTANCE": instance_name,
1072       "MAC": nic.mac,
1073       "MODE": nic.nicparams[constants.NIC_MODE],
1074       "INTERFACE_UUID": nic.uuid,
1075     }
1076
1077     if instance_tags:
1078       env["TAGS"] = " ".join(instance_tags)
1079
1080     # This should always be available except for old instances in the
1081     # cluster without uuid indexed tap files.
1082     if tap:
1083       env["INTERFACE"] = tap
1084
1085     if seq:
1086       env["INTERFACE_INDEX"] = str(seq)
1087
1088     if nic.ip:
1089       env["IP"] = nic.ip
1090
1091     if nic.name:
1092       env["INTERFACE_NAME"] = nic.name
1093
1094     if nic.nicparams[constants.NIC_LINK]:
1095       env["LINK"] = nic.nicparams[constants.NIC_LINK]
1096
1097     if nic.network:
1098       n = objects.Network.FromDict(nic.netinfo)
1099       env.update(n.HooksDict())
1100
1101     if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1102       env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
1103
1104     return env
1105
1106   @classmethod
1107   def _ConfigureNIC(cls, instance, seq, nic, tap):
1108     """Run the network configuration script for a specified NIC
1109
1110     @param instance: instance we're acting on
1111     @type instance: instance object
1112     @param seq: nic sequence number
1113     @type seq: int
1114     @param nic: nic we're acting on
1115     @type nic: nic object
1116     @param tap: the host's tap interface this NIC corresponds to
1117     @type tap: str
1118
1119     """
1120     env = cls._CreateNICEnv(instance.name, nic, tap, seq, instance.GetTags())
1121     result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
1122     if result.failed:
1123       raise errors.HypervisorError("Failed to configure interface %s: %s;"
1124                                    " network configuration script output: %s" %
1125                                    (tap, result.fail_reason, result.output))
1126
1127   @classmethod
1128   def _UnconfigureNic(cls, instance_name, nic, only_local=True):
1129     """Run ifdown script for a specific NIC
1130
1131     This is executed during instance cleanup and NIC hot-unplug
1132
1133     @param instance: instance we're acting on
1134     @type instance: instance object
1135     @param nic: nic we're acting on
1136     @type nic: nic object
1137     @param localy: whether ifdown script should reset global conf (dns) or not
1138     @type localy: boolean
1139
1140     """
1141     tap = cls._GetInstanceNICTap(instance_name, nic)
1142     env = cls._CreateNICEnv(instance_name, nic, tap)
1143     arg2 = str(only_local).lower()
1144     result = utils.RunCmd([pathutils.KVM_IFDOWN, tap, arg2], env=env)
1145     if result.failed:
1146       raise errors.HypervisorError("Failed to unconfigure interface %s: %s;"
1147                                    " network configuration script output: %s" %
1148                                    (tap, result.fail_reason, result.output))
1149
1150   @staticmethod
1151   def _VerifyAffinityPackage():
1152     if affinity is None:
1153       raise errors.HypervisorError("affinity Python package not"
1154                                    " found; cannot use CPU pinning under KVM")
1155
1156   @staticmethod
1157   def _BuildAffinityCpuMask(cpu_list):
1158     """Create a CPU mask suitable for sched_setaffinity from a list of
1159     CPUs.
1160
1161     See man taskset for more info on sched_setaffinity masks.
1162     For example: [ 0, 2, 5, 6 ] will return 101 (0x65, 0..01100101).
1163
1164     @type cpu_list: list of int
1165     @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1166     @rtype: int
1167     @return: a bit mask of CPU affinities
1168
1169     """
1170     if cpu_list == constants.CPU_PINNING_OFF:
1171       return constants.CPU_PINNING_ALL_KVM
1172     else:
1173       return sum(2 ** cpu for cpu in cpu_list)
1174
1175   @classmethod
1176   def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1177     """Change CPU affinity for running VM according to given CPU mask.
1178
1179     @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1180     @type cpu_mask: string
1181     @param process_id: process ID of KVM process. Used to pin entire VM
1182                        to physical CPUs.
1183     @type process_id: int
1184     @param thread_dict: map of virtual CPUs to KVM thread IDs
1185     @type thread_dict: dict int:int
1186
1187     """
1188     # Convert the string CPU mask to a list of list of int's
1189     cpu_list = utils.ParseMultiCpuMask(cpu_mask)
1190
1191     if len(cpu_list) == 1:
1192       all_cpu_mapping = cpu_list[0]
1193       if all_cpu_mapping == constants.CPU_PINNING_OFF:
1194         # If CPU pinning has 1 entry that's "all", then do nothing
1195         pass
1196       else:
1197         # If CPU pinning has one non-all entry, map the entire VM to
1198         # one set of physical CPUs
1199         cls._VerifyAffinityPackage()
1200         affinity.set_process_affinity_mask(
1201           process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
1202     else:
1203       # The number of vCPUs mapped should match the number of vCPUs
1204       # reported by KVM. This was already verified earlier, so
1205       # here only as a sanity check.
1206       assert len(thread_dict) == len(cpu_list)
1207       cls._VerifyAffinityPackage()
1208
1209       # For each vCPU, map it to the proper list of physical CPUs
1210       for vcpu, i in zip(cpu_list, range(len(cpu_list))):
1211         affinity.set_process_affinity_mask(thread_dict[i],
1212                                            cls._BuildAffinityCpuMask(vcpu))
1213
1214   def _GetVcpuThreadIds(self, instance_name):
1215     """Get a mapping of vCPU no. to thread IDs for the instance
1216
1217     @type instance_name: string
1218     @param instance_name: instance in question
1219     @rtype: dictionary of int:int
1220     @return: a dictionary mapping vCPU numbers to thread IDs
1221
1222     """
1223     result = {}
1224     output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1225     for line in output.stdout.splitlines():
1226       match = self._CPU_INFO_RE.search(line)
1227       if not match:
1228         continue
1229       grp = map(int, match.groups())
1230       result[grp[0]] = grp[1]
1231
1232     return result
1233
1234   def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1235     """Complete CPU pinning.
1236
1237     @type instance_name: string
1238     @param instance_name: name of instance
1239     @type cpu_mask: string
1240     @param cpu_mask: CPU pinning mask as entered by user
1241
1242     """
1243     # Get KVM process ID, to be used if need to pin entire VM
1244     _, pid, _ = self._InstancePidAlive(instance_name)
1245     # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1246     thread_dict = self._GetVcpuThreadIds(instance_name)
1247     # Run CPU pinning, based on configured mask
1248     self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1249
1250   def ListInstances(self):
1251     """Get the list of running instances.
1252
1253     We can do this by listing our live instances directory and
1254     checking whether the associated kvm process is still alive.
1255
1256     """
1257     result = []
1258     for name in os.listdir(self._PIDS_DIR):
1259       if self._InstancePidAlive(name)[2]:
1260         result.append(name)
1261     return result
1262
1263   def GetInstanceInfo(self, instance_name):
1264     """Get instance properties.
1265
1266     @type instance_name: string
1267     @param instance_name: the instance name
1268     @rtype: tuple of strings
1269     @return: (name, id, memory, vcpus, stat, times)
1270
1271     """
1272     _, pid, alive = self._InstancePidAlive(instance_name)
1273     if not alive:
1274       return None
1275
1276     _, memory, vcpus = self._InstancePidInfo(pid)
1277     istat = "---b-"
1278     times = "0"
1279
1280     try:
1281       qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1282       qmp.connect()
1283       vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1284       # Will fail if ballooning is not enabled, but we can then just resort to
1285       # the value above.
1286       mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1287       memory = mem_bytes / 1048576
1288     except errors.HypervisorError:
1289       pass
1290
1291     return (instance_name, pid, memory, vcpus, istat, times)
1292
1293   def GetAllInstancesInfo(self):
1294     """Get properties of all instances.
1295
1296     @return: list of tuples (name, id, memory, vcpus, stat, times)
1297
1298     """
1299     data = []
1300     for name in os.listdir(self._PIDS_DIR):
1301       try:
1302         info = self.GetInstanceInfo(name)
1303       except errors.HypervisorError:
1304         # Ignore exceptions due to instances being shut down
1305         continue
1306       if info:
1307         data.append(info)
1308     return data
1309
1310   def _GenerateKVMBlockDevicesOptions(self, instance, up_hvp, kvm_disks,
1311                                       kvmhelp, devlist):
1312     """Generate KVM options regarding instance's block devices.
1313
1314     @type instance: L{objects.Instance}
1315     @param instance: the instance object
1316     @type up_hvp: dict
1317     @param up_hvp: the instance's runtime hypervisor parameters
1318     @type kvm_disks: list of tuples
1319     @param kvm_disks: list of tuples [(disk, link_name)..]
1320     @type kvmhelp: string
1321     @param kvmhelp: output of kvm --help
1322     @type devlist: string
1323     @param devlist: output of kvm -device ?
1324     @rtype: list
1325     @return: list of command line options eventually used by kvm executable
1326
1327     """
1328     kernel_path = up_hvp[constants.HV_KERNEL_PATH]
1329     if kernel_path:
1330       boot_disk = False
1331     else:
1332       boot_disk = up_hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1333
1334     # whether this is an older KVM version that uses the boot=on flag
1335     # on devices
1336     needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1337
1338     dev_opts = []
1339     device_driver = None
1340     disk_type = up_hvp[constants.HV_DISK_TYPE]
1341     if disk_type == constants.HT_DISK_PARAVIRTUAL:
1342       if_val = ",if=%s" % self._VIRTIO
1343       try:
1344         if self._VIRTIO_BLK_RE.search(devlist):
1345           if_val = ",if=none"
1346           # will be passed in -device option as driver
1347           device_driver = self._VIRTIO_BLK_PCI
1348       except errors.HypervisorError, _:
1349         pass
1350     else:
1351       if_val = ",if=%s" % disk_type
1352     # Cache mode
1353     disk_cache = up_hvp[constants.HV_DISK_CACHE]
1354     if instance.disk_template in constants.DTS_EXT_MIRROR:
1355       if disk_cache != "none":
1356         # TODO: make this a hard error, instead of a silent overwrite
1357         logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1358                         " to prevent shared storage corruption on migration",
1359                         disk_cache)
1360       cache_val = ",cache=none"
1361     elif disk_cache != constants.HT_CACHE_DEFAULT:
1362       cache_val = ",cache=%s" % disk_cache
1363     else:
1364       cache_val = ""
1365     for idx, (cfdev, link_name) in enumerate(kvm_disks):
1366       if cfdev.mode != constants.DISK_RDWR:
1367         raise errors.HypervisorError("Instance has read-only disks which"
1368                                      " are not supported by KVM")
1369       # TODO: handle FD_LOOP and FD_BLKTAP (?)
1370       boot_val = ""
1371       if boot_disk:
1372         dev_opts.extend(["-boot", "c"])
1373         boot_disk = False
1374         if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1375           boot_val = ",boot=on"
1376
1377       # For ext we allow overriding disk_cache hypervisor params per disk
1378       disk_cache = cfdev.params.get("cache", None)
1379       if disk_cache:
1380         cache_val = ",cache=%s" % disk_cache
1381       drive_val = "file=%s,format=raw%s%s%s" % \
1382                   (link_name, if_val, boot_val, cache_val)
1383
1384       if device_driver:
1385         # kvm_disks are the 4th entry of runtime file that did not exist in
1386         # the past. That means that cfdev should always have pci slot and
1387         # _GenerateDeviceKVMId() will not raise a exception.
1388         kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK,
1389                                          cfdev, idx)
1390         drive_val += (",id=%s" % kvm_devid)
1391         if cfdev.pci:
1392           drive_val += (",bus=0,unit=%d" % cfdev.pci)
1393         dev_val = ("%s,drive=%s,id=%s" %
1394                    (device_driver, kvm_devid, kvm_devid))
1395         if cfdev.pci:
1396           dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1397         dev_opts.extend(["-device", dev_val])
1398
1399       # TODO: export disk geometry in IDISK_PARAMS
1400       heads = cfdev.params.get('heads', None)
1401       secs = cfdev.params.get('secs', None)
1402       if heads and secs:
1403         nr_sectors = cfdev.size * 1024 * 1024 / 512
1404         cyls = nr_sectors / (int(heads) * int(secs))
1405         if cyls > 16383:
1406           cyls = 16383
1407         elif cyls < 2:
1408           cyls = 2
1409         if cyls and heads and secs:
1410           drive_val += (",cyls=%d,heads=%d,secs=%d" %
1411                         (cyls, int(heads), int(secs)))
1412
1413       dev_opts.extend(["-drive", drive_val])
1414
1415     return dev_opts
1416
1417   def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1418                           kvmhelp):
1419     """Generate KVM information to start an instance.
1420
1421     @type kvmhelp: string
1422     @param kvmhelp: output of kvm --help
1423     @attention: this function must not have any side-effects; for
1424         example, it must not write to the filesystem, or read values
1425         from the current system the are expected to differ between
1426         nodes, since it is only run once at instance startup;
1427         actions/kvm arguments that can vary between systems should be
1428         done in L{_ExecuteKVMRuntime}
1429
1430     """
1431     # pylint: disable=R0912,R0914,R0915
1432     hvp = instance.hvparams
1433     self.ValidateParameters(hvp)
1434
1435     pidfile = self._InstancePidFile(instance.name)
1436     kvm = hvp[constants.HV_KVM_PATH]
1437     kvm_cmd = [kvm]
1438     # used just by the vnc server, if enabled
1439     kvm_cmd.extend(["-name", instance.name])
1440     kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1441
1442     smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1443     if hvp[constants.HV_CPU_CORES]:
1444       smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1445     if hvp[constants.HV_CPU_THREADS]:
1446       smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1447     if hvp[constants.HV_CPU_SOCKETS]:
1448       smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1449
1450     kvm_cmd.extend(["-smp", ",".join(smp_list)])
1451
1452     kvm_cmd.extend(["-pidfile", pidfile])
1453
1454     pci_reservations = bitarray(self._DEFAULT_PCI_RESERVATIONS)
1455
1456     # As requested by music lovers
1457     if hvp[constants.HV_SOUNDHW]:
1458       soundhw = hvp[constants.HV_SOUNDHW]
1459       # For some reason only few sound devices require a PCI slot
1460       # while the Audio controller *must* be in slot 3.
1461       # That's why we bridge this option early in command line
1462       if soundhw in self._SOUNDHW_WITH_PCI_SLOT:
1463         _ = _GetFreeSlot(pci_reservations, reserve=True)
1464       kvm_cmd.extend(["-soundhw", soundhw])
1465
1466     if hvp[constants.HV_DISK_TYPE] == constants.HT_DISK_SCSI:
1467       # The SCSI controller requires another PCI slot.
1468       _ = _GetFreeSlot(pci_reservations, reserve=True)
1469
1470     # Add id to ballon and place to the first available slot (3 or 4)
1471     addr = _GetFreeSlot(pci_reservations, reserve=True)
1472     pci_info = ",bus=pci.0,addr=%s" % hex(addr)
1473     kvm_cmd.extend(["-balloon", "virtio,id=balloon%s" % pci_info])
1474     kvm_cmd.extend(["-daemonize"])
1475     if not instance.hvparams[constants.HV_ACPI]:
1476       kvm_cmd.extend(["-no-acpi"])
1477     if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1478         constants.INSTANCE_REBOOT_EXIT:
1479       kvm_cmd.extend(["-no-reboot"])
1480
1481     mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1482     if not mversion:
1483       mversion = self._GetDefaultMachineVersion(kvm)
1484     if self._MACHINE_RE.search(kvmhelp):
1485       # TODO (2.8): kernel_irqchip and kvm_shadow_mem machine properties, as
1486       # extra hypervisor parameters. We should also investigate whether and how
1487       # shadow_mem should be considered for the resource model.
1488       if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED):
1489         specprop = ",accel=kvm"
1490       else:
1491         specprop = ""
1492       machinespec = "%s%s" % (mversion, specprop)
1493       kvm_cmd.extend(["-machine", machinespec])
1494     else:
1495       kvm_cmd.extend(["-M", mversion])
1496       if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1497           self._ENABLE_KVM_RE.search(kvmhelp)):
1498         kvm_cmd.extend(["-enable-kvm"])
1499       elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1500             self._DISABLE_KVM_RE.search(kvmhelp)):
1501         kvm_cmd.extend(["-disable-kvm"])
1502
1503     kernel_path = hvp[constants.HV_KERNEL_PATH]
1504     if kernel_path:
1505       boot_cdrom = boot_floppy = boot_network = False
1506     else:
1507       boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1508       boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1509       boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1510
1511     if startup_paused:
1512       kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1513
1514     if boot_network:
1515       kvm_cmd.extend(["-boot", "n"])
1516
1517     # whether this is an older KVM version that uses the boot=on flag
1518     # on devices
1519     needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1520
1521     disk_type = hvp[constants.HV_DISK_TYPE]
1522
1523     #Now we can specify a different device type for CDROM devices.
1524     cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1525     if not cdrom_disk_type:
1526       cdrom_disk_type = disk_type
1527
1528     iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1529     if iso_image:
1530       options = ",format=raw,media=cdrom"
1531       # set cdrom 'if' type
1532       if boot_cdrom:
1533         actual_cdrom_type = constants.HT_DISK_IDE
1534       elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1535         actual_cdrom_type = "virtio"
1536       else:
1537         actual_cdrom_type = cdrom_disk_type
1538       if_val = ",if=%s" % actual_cdrom_type
1539       # set boot flag, if needed
1540       boot_val = ""
1541       if boot_cdrom:
1542         kvm_cmd.extend(["-boot", "d"])
1543         if needs_boot_flag:
1544           boot_val = ",boot=on"
1545       # and finally build the entire '-drive' value
1546       drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1547       kvm_cmd.extend(["-drive", drive_val])
1548
1549     iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1550     if iso_image2:
1551       options = ",format=raw,media=cdrom"
1552       if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1553         if_val = ",if=virtio"
1554       else:
1555         if_val = ",if=%s" % cdrom_disk_type
1556       drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1557       kvm_cmd.extend(["-drive", drive_val])
1558
1559     floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1560     if floppy_image:
1561       options = ",format=raw,media=disk"
1562       if boot_floppy:
1563         kvm_cmd.extend(["-boot", "a"])
1564         options = "%s,boot=on" % options
1565       if_val = ",if=floppy"
1566       options = "%s%s" % (options, if_val)
1567       drive_val = "file=%s%s" % (floppy_image, options)
1568       kvm_cmd.extend(["-drive", drive_val])
1569
1570     if kernel_path:
1571       kvm_cmd.extend(["-kernel", kernel_path])
1572       initrd_path = hvp[constants.HV_INITRD_PATH]
1573       if initrd_path:
1574         kvm_cmd.extend(["-initrd", initrd_path])
1575       root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1576                      hvp[constants.HV_KERNEL_ARGS]]
1577       if hvp[constants.HV_SERIAL_CONSOLE]:
1578         serial_speed = hvp[constants.HV_SERIAL_SPEED]
1579         root_append.append("console=ttyS0,%s" % serial_speed)
1580       kvm_cmd.extend(["-append", " ".join(root_append)])
1581
1582     mem_path = hvp[constants.HV_MEM_PATH]
1583     if mem_path:
1584       kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1585
1586     monitor_dev = ("unix:%s,server,nowait" %
1587                    self._InstanceMonitor(instance.name))
1588     kvm_cmd.extend(["-monitor", monitor_dev])
1589     if hvp[constants.HV_SERIAL_CONSOLE]:
1590       serial_dev = ("unix:%s,server,nowait" %
1591                     self._InstanceSerial(instance.name))
1592       kvm_cmd.extend(["-serial", serial_dev])
1593     else:
1594       kvm_cmd.extend(["-serial", "none"])
1595
1596     mouse_type = hvp[constants.HV_USB_MOUSE]
1597     vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1598     spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1599     spice_ip_version = None
1600
1601     kvm_cmd.extend(["-usb"])
1602
1603     if mouse_type:
1604       kvm_cmd.extend(["-usbdevice", mouse_type])
1605     elif vnc_bind_address:
1606       kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1607
1608     if vnc_bind_address:
1609       if netutils.IP4Address.IsValid(vnc_bind_address):
1610         if instance.network_port > constants.VNC_BASE_PORT:
1611           display = instance.network_port - constants.VNC_BASE_PORT
1612           if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1613             vnc_arg = ":%d" % (display)
1614           else:
1615             vnc_arg = "%s:%d" % (vnc_bind_address, display)
1616         else:
1617           logging.error("Network port is not a valid VNC display (%d < %d),"
1618                         " not starting VNC",
1619                         instance.network_port, constants.VNC_BASE_PORT)
1620           vnc_arg = "none"
1621
1622         # Only allow tls and other option when not binding to a file, for now.
1623         # kvm/qemu gets confused otherwise about the filename to use.
1624         vnc_append = ""
1625         if hvp[constants.HV_VNC_TLS]:
1626           vnc_append = "%s,tls" % vnc_append
1627           if hvp[constants.HV_VNC_X509_VERIFY]:
1628             vnc_append = "%s,x509verify=%s" % (vnc_append,
1629                                                hvp[constants.HV_VNC_X509])
1630           elif hvp[constants.HV_VNC_X509]:
1631             vnc_append = "%s,x509=%s" % (vnc_append,
1632                                          hvp[constants.HV_VNC_X509])
1633         if hvp[constants.HV_VNC_PASSWORD_FILE]:
1634           vnc_append = "%s,password" % vnc_append
1635
1636         vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1637
1638       else:
1639         vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1640
1641       kvm_cmd.extend(["-vnc", vnc_arg])
1642     elif spice_bind:
1643       # FIXME: this is wrong here; the iface ip address differs
1644       # between systems, so it should be done in _ExecuteKVMRuntime
1645       if netutils.IsValidInterface(spice_bind):
1646         # The user specified a network interface, we have to figure out the IP
1647         # address.
1648         addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1649         spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1650
1651         # if the user specified an IP version and the interface does not
1652         # have that kind of IP addresses, throw an exception
1653         if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1654           if not addresses[spice_ip_version]:
1655             raise errors.HypervisorError("SPICE: Unable to get an IPv%s address"
1656                                          " for %s" % (spice_ip_version,
1657                                                       spice_bind))
1658
1659         # the user did not specify an IP version, we have to figure it out
1660         elif (addresses[constants.IP4_VERSION] and
1661               addresses[constants.IP6_VERSION]):
1662           # we have both ipv4 and ipv6, let's use the cluster default IP
1663           # version
1664           cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1665           spice_ip_version = \
1666             netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1667         elif addresses[constants.IP4_VERSION]:
1668           spice_ip_version = constants.IP4_VERSION
1669         elif addresses[constants.IP6_VERSION]:
1670           spice_ip_version = constants.IP6_VERSION
1671         else:
1672           raise errors.HypervisorError("SPICE: Unable to get an IP address"
1673                                        " for %s" % (spice_bind))
1674
1675         spice_address = addresses[spice_ip_version][0]
1676
1677       else:
1678         # spice_bind is known to be a valid IP address, because
1679         # ValidateParameters checked it.
1680         spice_address = spice_bind
1681
1682       spice_arg = "addr=%s" % spice_address
1683       if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1684         spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1685                      (spice_arg, instance.network_port,
1686                       pathutils.SPICE_CACERT_FILE))
1687         spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1688                      (spice_arg, pathutils.SPICE_CERT_FILE,
1689                       pathutils.SPICE_CERT_FILE))
1690         tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1691         if tls_ciphers:
1692           spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1693       else:
1694         spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1695
1696       if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1697         spice_arg = "%s,disable-ticketing" % spice_arg
1698
1699       if spice_ip_version:
1700         spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1701
1702       # Image compression options
1703       img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1704       img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1705       img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1706       if img_lossless:
1707         spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1708       if img_jpeg:
1709         spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1710       if img_zlib_glz:
1711         spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1712
1713       # Video stream detection
1714       video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1715       if video_streaming:
1716         spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1717
1718       # Audio compression, by default in qemu-kvm it is on
1719       if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1720         spice_arg = "%s,playback-compression=off" % spice_arg
1721       if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1722         spice_arg = "%s,agent-mouse=off" % spice_arg
1723       else:
1724         # Enable the spice agent communication channel between the host and the
1725         # agent.
1726         addr = _GetFreeSlot(pci_reservations, reserve=True)
1727         pci_info = ",bus=pci.0,addr=%s" % hex(addr)
1728         kvm_cmd.extend(["-device", "virtio-serial-pci,id=spice%s" % pci_info])
1729         kvm_cmd.extend([
1730           "-device",
1731           "virtserialport,chardev=spicechannel0,name=com.redhat.spice.0",
1732           ])
1733         kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1734
1735       logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1736       kvm_cmd.extend(["-spice", spice_arg])
1737
1738     else:
1739       # From qemu 1.4 -nographic is incompatible with -daemonize. The new way
1740       # also works in earlier versions though (tested with 1.1 and 1.3)
1741       if self._DISPLAY_RE.search(kvmhelp):
1742         kvm_cmd.extend(["-display", "none"])
1743       else:
1744         kvm_cmd.extend(["-nographic"])
1745
1746     if hvp[constants.HV_USE_LOCALTIME]:
1747       kvm_cmd.extend(["-localtime"])
1748
1749     if hvp[constants.HV_KVM_USE_CHROOT]:
1750       kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1751
1752     # Add qemu-KVM -cpu param
1753     if hvp[constants.HV_CPU_TYPE]:
1754       kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1755
1756     # Pass a -vga option if requested, or if spice is used, for backwards
1757     # compatibility.
1758     if hvp[constants.HV_VGA]:
1759       kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1760     elif spice_bind:
1761       kvm_cmd.extend(["-vga", "qxl"])
1762
1763     # Various types of usb devices, comma separated
1764     if hvp[constants.HV_USB_DEVICES]:
1765       for dev in hvp[constants.HV_USB_DEVICES].split(","):
1766         kvm_cmd.extend(["-usbdevice", dev])
1767
1768     if hvp[constants.HV_KVM_EXTRA]:
1769       kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
1770
1771     kvm_disks = []
1772     for disk, link_name in block_devices:
1773       disk.pci = _GetFreeSlot(pci_reservations, disk.pci, True)
1774       kvm_disks.append((disk, link_name))
1775
1776     kvm_nics = []
1777     for nic in instance.nics:
1778       nic.pci = _GetFreeSlot(pci_reservations, nic.pci, True)
1779       kvm_nics.append(nic)
1780
1781     hvparams = hvp
1782
1783     return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
1784
1785   def _WriteKVMRuntime(self, instance_name, data):
1786     """Write an instance's KVM runtime
1787
1788     """
1789     try:
1790       utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1791                       data=data)
1792     except EnvironmentError, err:
1793       raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1794
1795   @classmethod
1796   def _ReadKVMRuntime(cls, instance_name):
1797     """Read an instance's KVM runtime
1798
1799     """
1800     try:
1801       file_content = utils.ReadFile(cls._InstanceKVMRuntime(instance_name))
1802     except EnvironmentError, err:
1803       raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1804     return file_content
1805
1806   def _SaveKVMRuntime(self, instance, kvm_runtime):
1807     """Save an instance's KVM runtime
1808
1809     """
1810     kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1811
1812     serialized_nics = [nic.ToDict() for nic in kvm_nics]
1813     serialized_disks = [(blk.ToDict(), link)
1814                             for blk, link in kvm_disks]
1815     serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1816                                       serialized_disks))
1817
1818     self._WriteKVMRuntime(instance.name, serialized_form)
1819
1820   @classmethod
1821   def _LoadKVMRuntime(cls, instance_name, serialized_runtime=None):
1822     """Load an instance's KVM runtime
1823
1824     """
1825     if not serialized_runtime:
1826       serialized_runtime = cls._ReadKVMRuntime(instance_name)
1827
1828     return _AnalyzeSerializedRuntime(serialized_runtime)
1829
1830   def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1831     """Run the KVM cmd and check for errors
1832
1833     @type name: string
1834     @param name: instance name
1835     @type kvm_cmd: list of strings
1836     @param kvm_cmd: runcmd input for kvm
1837     @type tap_fds: list of int
1838     @param tap_fds: fds of tap devices opened by Ganeti
1839
1840     """
1841     try:
1842       result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1843     finally:
1844       for fd in tap_fds:
1845         utils_wrapper.CloseFdNoError(fd)
1846
1847     if result.failed:
1848       raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1849                                    (name, result.fail_reason, result.output))
1850     if not self._InstancePidAlive(name)[2]:
1851       raise errors.HypervisorError("Failed to start instance %s" % name)
1852
1853   # too many local variables
1854   # pylint: disable=R0914
1855   def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1856     """Execute a KVM cmd, after completing it with some last minute data.
1857
1858     @type incoming: tuple of strings
1859     @param incoming: (target_host_ip, port)
1860     @type kvmhelp: string
1861     @param kvmhelp: output of kvm --help
1862
1863     """
1864     # Small _ExecuteKVMRuntime hv parameters programming howto:
1865     #  - conf_hvp contains the parameters as configured on ganeti. they might
1866     #    have changed since the instance started; only use them if the change
1867     #    won't affect the inside of the instance (which hasn't been rebooted).
1868     #  - up_hvp contains the parameters as they were when the instance was
1869     #    started, plus any new parameter which has been added between ganeti
1870     #    versions: it is paramount that those default to a value which won't
1871     #    affect the inside of the instance as well.
1872     conf_hvp = instance.hvparams
1873     name = instance.name
1874     self._CheckDown(name)
1875
1876     temp_files = []
1877
1878     kvm_cmd, kvm_nics, up_hvp, kvm_disks = kvm_runtime
1879     # the first element of kvm_cmd is always the path to the kvm binary
1880     kvm_path = kvm_cmd[0]
1881     up_hvp = objects.FillDict(conf_hvp, up_hvp)
1882
1883     # We know it's safe to run as a different user upon migration, so we'll use
1884     # the latest conf, from conf_hvp.
1885     security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1886     if security_model == constants.HT_SM_USER:
1887       kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1888
1889     keymap = conf_hvp[constants.HV_KEYMAP]
1890     if keymap:
1891       keymap_path = self._InstanceKeymapFile(name)
1892       # If a keymap file is specified, KVM won't use its internal defaults. By
1893       # first including the "en-us" layout, an error on loading the actual
1894       # layout (e.g. because it can't be found) won't lead to a non-functional
1895       # keyboard. A keyboard with incorrect keys is still better than none.
1896       utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1897       kvm_cmd.extend(["-k", keymap_path])
1898
1899     # We have reasons to believe changing something like the nic driver/type
1900     # upon migration won't exactly fly with the instance kernel, so for nic
1901     # related parameters we'll use up_hvp
1902     tapfds = []
1903     taps = []
1904     devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1905
1906     bdev_opts = self._GenerateKVMBlockDevicesOptions(instance,
1907                                                      up_hvp,
1908                                                      kvm_disks,
1909                                                      kvmhelp,
1910                                                      devlist)
1911     kvm_cmd.extend(bdev_opts)
1912
1913     if not kvm_nics:
1914       kvm_cmd.extend(["-net", "none"])
1915     else:
1916       vnet_hdr = False
1917       tap_extra = ""
1918       nic_type = up_hvp[constants.HV_NIC_TYPE]
1919       if nic_type == constants.HT_NIC_PARAVIRTUAL:
1920         nic_model = self._VIRTIO
1921         try:
1922           if self._VIRTIO_NET_RE.search(devlist):
1923             nic_model = self._VIRTIO_NET_PCI
1924             vnet_hdr = up_hvp[constants.HV_VNET_HDR]
1925         except errors.HypervisorError, _:
1926           # Older versions of kvm don't support DEVICE_LIST, but they don't
1927           # have new virtio syntax either.
1928           pass
1929
1930         if up_hvp[constants.HV_VHOST_NET]:
1931           # check for vhost_net support
1932           if self._VHOST_RE.search(kvmhelp):
1933             tap_extra = ",vhost=on"
1934           else:
1935             raise errors.HypervisorError("vhost_net is configured"
1936                                          " but it is not available")
1937       else:
1938         nic_model = nic_type
1939
1940       kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
1941
1942       for nic_seq, nic in enumerate(kvm_nics):
1943         tapname, tapfd = _OpenTap(vnet_hdr=vnet_hdr)
1944         tapfds.append(tapfd)
1945         taps.append(tapname)
1946         if kvm_supports_netdev:
1947           nic_val = "%s,mac=%s" % (nic_model, nic.mac)
1948           try:
1949             # kvm_nics already exist in old runtime files and thus there might
1950             # be some entries without pci slot (therefore try: except:)
1951             kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
1952             netdev = kvm_devid
1953             nic_val += (",id=%s,bus=pci.0,addr=%s" % (kvm_devid, hex(nic.pci)))
1954           except errors.HotplugError:
1955             netdev = "netdev%d" % nic_seq
1956           nic_val += (",netdev=%s" % netdev)
1957           tap_val = ("type=tap,id=%s,fd=%d%s" %
1958                      (netdev, tapfd, tap_extra))
1959           kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1960         else:
1961           nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1962                                                          nic.mac, nic_model)
1963           tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1964           kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1965
1966     if incoming:
1967       target, port = incoming
1968       kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1969
1970     # Changing the vnc password doesn't bother the guest that much. At most it
1971     # will surprise people who connect to it. Whether positively or negatively
1972     # it's debatable.
1973     vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1974     vnc_pwd = None
1975     if vnc_pwd_file:
1976       try:
1977         vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1978       except EnvironmentError, err:
1979         raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1980                                      % (vnc_pwd_file, err))
1981
1982     if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1983       utils.EnsureDirs([(self._InstanceChrootDir(name),
1984                          constants.SECURE_DIR_MODE)])
1985
1986     # Automatically enable QMP if version is >= 0.14
1987     if self._QMP_RE.search(kvmhelp):
1988       logging.debug("Enabling QMP")
1989       kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1990                       self._InstanceQmpMonitor(instance.name)])
1991
1992     # Configure the network now for starting instances and bridged interfaces,
1993     # during FinalizeMigration for incoming instances' routed interfaces
1994     for nic_seq, nic in enumerate(kvm_nics):
1995       if (incoming and
1996           nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1997         continue
1998       self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1999
2000     # CPU affinity requires kvm to start paused, so we set this flag if the
2001     # instance is not already paused and if we are not going to accept a
2002     # migrating instance. In the latter case, pausing is not needed.
2003     start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
2004     if start_kvm_paused:
2005       kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
2006
2007     # Note: CPU pinning is using up_hvp since changes take effect
2008     # during instance startup anyway, and to avoid problems when soft
2009     # rebooting the instance.
2010     cpu_pinning = False
2011     if up_hvp.get(constants.HV_CPU_MASK, None):
2012       cpu_pinning = True
2013
2014     if security_model == constants.HT_SM_POOL:
2015       ss = ssconf.SimpleStore()
2016       uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
2017       all_uids = set(uidpool.ExpandUidPool(uid_pool))
2018       uid = uidpool.RequestUnusedUid(all_uids)
2019       try:
2020         username = pwd.getpwuid(uid.GetUid()).pw_name
2021         kvm_cmd.extend(["-runas", username])
2022         self._RunKVMCmd(name, kvm_cmd, tapfds)
2023       except:
2024         uidpool.ReleaseUid(uid)
2025         raise
2026       else:
2027         uid.Unlock()
2028         utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
2029     else:
2030       self._RunKVMCmd(name, kvm_cmd, tapfds)
2031
2032     utils.EnsureDirs([(self._InstanceNICDir(instance.name),
2033                      constants.RUN_DIRS_MODE)])
2034     for nic_seq, tap in enumerate(taps):
2035       nic = kvm_nics[nic_seq]
2036       self._WriteInstanceNICFiles(instance.name, nic_seq, nic, tap)
2037
2038     if vnc_pwd:
2039       change_cmd = "change vnc password %s" % vnc_pwd
2040       self._CallMonitorCommand(instance.name, change_cmd)
2041
2042     # Setting SPICE password. We are not vulnerable to malicious passwordless
2043     # connection attempts because SPICE by default does not allow connections
2044     # if neither a password nor the "disable_ticketing" options are specified.
2045     # As soon as we send the password via QMP, that password is a valid ticket
2046     # for connection.
2047     spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
2048     if spice_password_file:
2049       spice_pwd = ""
2050       try:
2051         spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
2052       except EnvironmentError, err:
2053         raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
2054                                      % (spice_password_file, err))
2055
2056       qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
2057       qmp.connect()
2058       arguments = {
2059           "protocol": "spice",
2060           "password": spice_pwd,
2061       }
2062       qmp.Execute("set_password", arguments)
2063
2064     for filename in temp_files:
2065       utils.RemoveFile(filename)
2066
2067     # If requested, set CPU affinity and resume instance execution
2068     if cpu_pinning:
2069       self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
2070
2071     start_memory = self._InstanceStartupMemory(instance)
2072     if start_memory < instance.beparams[constants.BE_MAXMEM]:
2073       self.BalloonInstanceMemory(instance, start_memory)
2074
2075     if start_kvm_paused:
2076       # To control CPU pinning, ballooning, and vnc/spice passwords
2077       # the VM was started in a frozen state. If freezing was not
2078       # explicitly requested resume the vm status.
2079       self._CallMonitorCommand(instance.name, self._CONT_CMD)
2080
2081   def StartInstance(self, instance, block_devices, startup_paused):
2082     """Start an instance.
2083
2084     """
2085     self._CheckDown(instance.name)
2086     kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2087     kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2088     kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
2089                                            startup_paused, kvmhelp)
2090     self._SaveKVMRuntime(instance, kvm_runtime)
2091     self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2092
2093   def _CallMonitorCommand(self, instance_name, command, timeout=None):
2094     """Invoke a command on the instance monitor.
2095
2096     """
2097     if timeout is not None:
2098       timeout_cmd = "timeout %s" % (timeout, )
2099     else:
2100       timeout_cmd = ""
2101
2102     # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
2103     # version. The monitor protocol is designed for human consumption, whereas
2104     # QMP is made for programmatic usage. In the worst case QMP can also
2105     # execute monitor commands. As it is, all calls to socat take at least
2106     # 500ms and likely more: socat can't detect the end of the reply and waits
2107     # for 500ms of no data received before exiting (500 ms is the default for
2108     # the "-t" parameter).
2109     socat = ("echo %s | %s %s STDIO UNIX-CONNECT:%s" %
2110              (utils.ShellQuote(command),
2111               timeout_cmd,
2112               constants.SOCAT_PATH,
2113               utils.ShellQuote(self._InstanceMonitor(instance_name))))
2114
2115     result = utils.RunCmd(socat)
2116     if result.failed:
2117       msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
2118              " output: %s" %
2119              (command, instance_name, result.fail_reason, result.output))
2120       raise errors.HypervisorError(msg)
2121
2122     return result
2123
2124   def _GetFreePCISlot(self, instance, dev):
2125     """Get the first available pci slot of a runnung instance.
2126
2127     """
2128     slots = bitarray(32)
2129     slots.setall(False) # pylint: disable=E1101
2130     output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
2131     for line in output.stdout.splitlines():
2132       match = self._INFO_PCI_RE.search(line)
2133       if match:
2134         slot = int(match.group(1))
2135         slots[slot] = True
2136
2137     dev.pci = _GetFreeSlot(slots)
2138
2139   def VerifyHotplugSupport(self, instance, action, dev_type):
2140     """Verifies that hotplug is supported.
2141
2142     Hotplug is *not* supported in case of:
2143      - security models and chroot (disk hotplug)
2144      - fdsend module is missing (nic hot-add)
2145
2146     @raise errors.HypervisorError: in one of the previous cases
2147
2148     """
2149     if dev_type == constants.HOTPLUG_TARGET_DISK:
2150       hvp = instance.hvparams
2151       security_model = hvp[constants.HV_SECURITY_MODEL]
2152       use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
2153       if use_chroot:
2154         raise errors.HotplugError("Disk hotplug is not supported"
2155                                   " in case of chroot.")
2156       if security_model != constants.HT_SM_NONE:
2157         raise errors.HotplugError("Disk Hotplug is not supported in case"
2158                                   " security models are used.")
2159
2160     if (dev_type == constants.HOTPLUG_TARGET_NIC and
2161         action == constants.HOTPLUG_ACTION_ADD and not fdsend):
2162       raise errors.HotplugError("Cannot hot-add NIC."
2163                                 " fdsend python module is missing.")
2164
2165   def HotplugSupported(self, instance):
2166     """Checks if hotplug is generally supported.
2167
2168     Hotplug is *not* supported in case of:
2169      - qemu versions < 1.0
2170      - for stopped instances
2171
2172     @raise errors.HypervisorError: in one of the previous cases
2173
2174     """
2175     try:
2176       output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
2177     except errors.HypervisorError:
2178       raise errors.HotplugError("Instance is probably down")
2179
2180     # TODO: search for netdev_add, drive_add, device_add.....
2181     match = self._INFO_VERSION_RE.search(output.stdout)
2182     if not match:
2183       raise errors.HotplugError("Cannot parse qemu version via monitor")
2184
2185     v_major, v_min, _, _ = match.groups()
2186     if (int(v_major), int(v_min)) < (1, 0):
2187       raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
2188
2189   def _CallHotplugCommands(self, name, cmds):
2190     for c in cmds:
2191       self._CallMonitorCommand(name, c)
2192       time.sleep(1)
2193
2194   def _VerifyHotplugCommand(self, instance_name, device, dev_type,
2195                             should_exist):
2196     """Checks if a previous hotplug command has succeeded.
2197
2198     It issues info pci monitor command and checks depending on should_exist
2199     value if an entry with PCI slot and device ID is found or not.
2200
2201     @raise errors.HypervisorError: if result is not the expected one
2202
2203     """
2204     output = self._CallMonitorCommand(instance_name, self._INFO_PCI_CMD)
2205     kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2206     match = \
2207       self._FIND_PCI_DEVICE_RE(device.pci, kvm_devid).search(output.stdout)
2208     if match and not should_exist:
2209       msg = "Device %s should have been removed but is still there" % kvm_devid
2210       raise errors.HypervisorError(msg)
2211
2212     if not match and should_exist:
2213       msg = "Device %s should have been added but is missing" % kvm_devid
2214       raise errors.HypervisorError(msg)
2215
2216     logging.info("Device %s has been correctly hot-plugged", kvm_devid)
2217
2218   def HotAddDevice(self, instance, dev_type, device, extra, seq):
2219     """ Helper method to hot-add a new device
2220
2221     It gets free pci slot generates the device name and invokes the
2222     device specific method.
2223
2224     """
2225     # in case of hot-mod this is given
2226     if device.pci is None:
2227       self._GetFreePCISlot(instance, device)
2228     kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2229     runtime = self._LoadKVMRuntime(instance.name)
2230     if dev_type == constants.HOTPLUG_TARGET_DISK:
2231       cmds = ["drive_add dummy file=%s,if=none,id=%s,format=raw" %
2232                 (extra, kvm_devid)]
2233       cmds += ["device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
2234                 (hex(device.pci), kvm_devid, kvm_devid)]
2235     elif dev_type == constants.HOTPLUG_TARGET_NIC:
2236       (tap, fd) = _OpenTap()
2237       self._ConfigureNIC(instance, seq, device, tap)
2238       self._PassTapFd(instance, fd, device)
2239       cmds = ["netdev_add tap,id=%s,fd=%s" % (kvm_devid, kvm_devid)]
2240       args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s" % \
2241                (hex(device.pci), device.mac, kvm_devid, kvm_devid)
2242       cmds += ["device_add %s" % args]
2243       self._WriteInstanceNICFiles(instance.name, seq, device, tap)
2244
2245     self._CallHotplugCommands(instance.name, cmds)
2246     self._VerifyHotplugCommand(instance.name, device, dev_type, True)
2247     # update relevant entries in runtime file
2248     index = _DEVICE_RUNTIME_INDEX[dev_type]
2249     entry = _RUNTIME_ENTRY[dev_type](device, extra)
2250     runtime[index].append(entry)
2251     self._SaveKVMRuntime(instance, runtime)
2252
2253   def HotDelDevice(self, instance, dev_type, device, _, seq):
2254     """ Helper method for hot-del device
2255
2256     It gets device info from runtime file, generates the device name and
2257     invokes the device specific method.
2258
2259     """
2260     runtime = self._LoadKVMRuntime(instance.name)
2261     entry = _GetExistingDeviceInfo(dev_type, device, runtime)
2262     kvm_device = _RUNTIME_DEVICE[dev_type](entry)
2263     kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
2264     if dev_type == constants.HOTPLUG_TARGET_DISK:
2265       cmds = ["device_del %s" % kvm_devid]
2266       cmds += ["drive_del %s" % kvm_devid]
2267     elif dev_type == constants.HOTPLUG_TARGET_NIC:
2268       cmds = ["device_del %s" % kvm_devid]
2269       cmds += ["netdev_del %s" % kvm_devid]
2270       self._UnconfigureNic(instance.name, kvm_device, False)
2271       self._RemoveInstanceNICFiles(instance.name, seq, device)
2272     self._CallHotplugCommands(instance.name, cmds)
2273     self._VerifyHotplugCommand(instance.name, kvm_device, dev_type, False)
2274     index = _DEVICE_RUNTIME_INDEX[dev_type]
2275     runtime[index].remove(entry)
2276     self._SaveKVMRuntime(instance, runtime)
2277
2278     return kvm_device.pci
2279
2280   def HotModDevice(self, instance, dev_type, device, _, seq):
2281     """ Helper method for hot-mod device
2282
2283     It gets device info from runtime file, generates the device name and
2284     invokes the device specific method. Currently only NICs support hot-mod
2285
2286     """
2287     if dev_type == constants.HOTPLUG_TARGET_NIC:
2288       # putting it back in the same pci slot
2289       device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2290       # TODO: remove sleep when socat gets removed
2291       self.HotAddDevice(instance, dev_type, device, _, seq)
2292
2293   def _PassTapFd(self, instance, fd, nic):
2294     """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2295
2296     """
2297     # TODO: factor out code related to unix sockets.
2298     #       squash common parts between monitor and qmp
2299     kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
2300     command = "getfd %s\n" % kvm_devid
2301     fds = [fd]
2302     logging.info("%s", fds)
2303     try:
2304       monsock = MonitorSocket(self._InstanceMonitor(instance.name))
2305       monsock.connect()
2306       fdsend.sendfds(monsock.sock, command, fds=fds)
2307     finally:
2308       monsock.close()
2309
2310   @classmethod
2311   def _ParseKVMVersion(cls, text):
2312     """Parse the KVM version from the --help output.
2313
2314     @type text: string
2315     @param text: output of kvm --help
2316     @return: (version, v_maj, v_min, v_rev)
2317     @raise errors.HypervisorError: when the KVM version cannot be retrieved
2318
2319     """
2320     match = cls._VERSION_RE.search(text.splitlines()[0])
2321     if not match:
2322       raise errors.HypervisorError("Unable to get KVM version")
2323
2324     v_all = match.group(0)
2325     v_maj = int(match.group(1))
2326     v_min = int(match.group(2))
2327     if match.group(4):
2328       v_rev = int(match.group(4))
2329     else:
2330       v_rev = 0
2331     return (v_all, v_maj, v_min, v_rev)
2332
2333   @classmethod
2334   def _GetKVMOutput(cls, kvm_path, option):
2335     """Return the output of a kvm invocation
2336
2337     @type kvm_path: string
2338     @param kvm_path: path to the kvm executable
2339     @type option: a key of _KVMOPTS_CMDS
2340     @param option: kvm option to fetch the output from
2341     @return: output a supported kvm invocation
2342     @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2343
2344     """
2345     assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2346
2347     optlist, can_fail = cls._KVMOPTS_CMDS[option]
2348
2349     result = utils.RunCmd([kvm_path] + optlist)
2350     if result.failed and not can_fail:
2351       raise errors.HypervisorError("Unable to get KVM %s output" %
2352                                     " ".join(optlist))
2353     return result.output
2354
2355   @classmethod
2356   def _GetKVMVersion(cls, kvm_path):
2357     """Return the installed KVM version.
2358
2359     @return: (version, v_maj, v_min, v_rev)
2360     @raise errors.HypervisorError: when the KVM version cannot be retrieved
2361
2362     """
2363     return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2364
2365   @classmethod
2366   def _GetDefaultMachineVersion(cls, kvm_path):
2367     """Return the default hardware revision (e.g. pc-1.1)
2368
2369     """
2370     output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2371     match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2372     if match:
2373       return match.group(1)
2374     else:
2375       return "pc"
2376
2377   def StopInstance(self, instance, force=False, retry=False, name=None,
2378                    timeout=None):
2379     """Stop an instance.
2380
2381     """
2382     assert(timeout is None or force is not None)
2383
2384     if name is not None and not force:
2385       raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2386     if name is None:
2387       name = instance.name
2388       acpi = instance.hvparams[constants.HV_ACPI]
2389     else:
2390       acpi = False
2391     _, pid, alive = self._InstancePidAlive(name)
2392     if pid > 0 and alive:
2393       if force or not acpi:
2394         utils.KillProcess(pid)
2395       else:
2396         self._CallMonitorCommand(name, "system_powerdown", timeout)
2397
2398   @classmethod
2399   def _UnconfigureInstanceNICs(cls, instance_name, info=None):
2400     """Get runtime NICs of an instance and unconfigure them
2401
2402     """
2403     _, kvm_nics, __, ___ = cls._LoadKVMRuntime(instance_name, info)
2404     for nic in kvm_nics:
2405       cls._UnconfigureNic(instance_name, nic)
2406
2407   def CleanupInstance(self, instance_name):
2408     """Cleanup after a stopped instance
2409
2410     """
2411     pidfile, pid, alive = self._InstancePidAlive(instance_name)
2412     if pid > 0 and alive:
2413       raise errors.HypervisorError("Cannot cleanup a live instance")
2414     self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2415
2416   def RebootInstance(self, instance):
2417     """Reboot an instance.
2418
2419     """
2420     # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2421     # socket the instance will stop, but now power up again. So we'll resort
2422     # to shutdown and restart.
2423     _, _, alive = self._InstancePidAlive(instance.name)
2424     if not alive:
2425       raise errors.HypervisorError("Failed to reboot instance %s:"
2426                                    " not running" % instance.name)
2427     # StopInstance will delete the saved KVM runtime so:
2428     # ...first load it...
2429     kvm_runtime = self._LoadKVMRuntime(instance.name)
2430     # ...now we can safely call StopInstance...
2431     if not self.StopInstance(instance):
2432       self.StopInstance(instance, force=True)
2433     # ...and finally we can save it again, and execute it...
2434     self._SaveKVMRuntime(instance, kvm_runtime)
2435     kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2436     kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2437     self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2438
2439   def MigrationInfo(self, instance):
2440     """Get instance information to perform a migration.
2441
2442     @type instance: L{objects.Instance}
2443     @param instance: instance to be migrated
2444     @rtype: string
2445     @return: content of the KVM runtime file
2446
2447     """
2448     return self._ReadKVMRuntime(instance.name)
2449
2450   def AcceptInstance(self, instance, info, target):
2451     """Prepare to accept an instance.
2452
2453     @type instance: L{objects.Instance}
2454     @param instance: instance to be accepted
2455     @type info: string
2456     @param info: content of the KVM runtime file on the source node
2457     @type target: string
2458     @param target: target host (usually ip), on this node
2459
2460     """
2461     kvm_runtime = self._LoadKVMRuntime(instance.name, serialized_runtime=info)
2462     incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2463     kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2464     kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2465     self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2466                             incoming=incoming_address)
2467
2468   def FinalizeMigrationDst(self, instance, info, success):
2469     """Finalize the instance migration on the target node.
2470
2471     Stop the incoming mode KVM.
2472
2473     @type instance: L{objects.Instance}
2474     @param instance: instance whose migration is being finalized
2475
2476     """
2477     if success:
2478       kvm_runtime = self._LoadKVMRuntime(instance.name, serialized_runtime=info)
2479       kvm_nics = kvm_runtime[1]
2480
2481       for nic_seq, nic in enumerate(kvm_nics):
2482         if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2483           # Bridged interfaces have already been configured
2484           continue
2485         try:
2486           tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2487         except EnvironmentError, err:
2488           logging.warning("Failed to find host interface for %s NIC #%d: %s",
2489                           instance.name, nic_seq, str(err))
2490           continue
2491         try:
2492           self._ConfigureNIC(instance, nic_seq, nic, tap)
2493         except errors.HypervisorError, err:
2494           logging.warning(str(err))
2495
2496       self._WriteKVMRuntime(instance.name, info)
2497     else:
2498       self._UnconfigureInstanceNICs(instance.name, info)
2499       self.StopInstance(instance, force=True)
2500
2501   def MigrateInstance(self, instance, target, live):
2502     """Migrate an instance to a target node.
2503
2504     The migration will not be attempted if the instance is not
2505     currently running.
2506
2507     @type instance: L{objects.Instance}
2508     @param instance: the instance to be migrated
2509     @type target: string
2510     @param target: ip address of the target node
2511     @type live: boolean
2512     @param live: perform a live migration
2513
2514     """
2515     instance_name = instance.name
2516     port = instance.hvparams[constants.HV_MIGRATION_PORT]
2517     _, _, alive = self._InstancePidAlive(instance_name)
2518     if not alive:
2519       raise errors.HypervisorError("Instance not running, cannot migrate")
2520
2521     if not live:
2522       self._CallMonitorCommand(instance_name, "stop")
2523
2524     migrate_command = ("migrate_set_speed %dm" %
2525                        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2526     self._CallMonitorCommand(instance_name, migrate_command)
2527
2528     migrate_command = ("migrate_set_downtime %dms" %
2529                        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2530     self._CallMonitorCommand(instance_name, migrate_command)
2531
2532     # These commands are supported in latest qemu versions.
2533     # Since _CallMonitorCommand does not catch monitor errors
2534     # this does not raise an exception in case command is not supported
2535     # TODO: either parse output of command or see if the command supported
2536     # via info help (see hotplug)
2537     migration_caps = instance.hvparams[constants.HV_KVM_MIGRATION_CAPS]
2538     if migration_caps:
2539       for c in migration_caps.split(_MIGRATION_CAPS_DELIM):
2540         migrate_command = ("migrate_set_capability %s on" % c)
2541         self._CallMonitorCommand(instance_name, migrate_command)
2542
2543     migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2544     self._CallMonitorCommand(instance_name, migrate_command)
2545
2546   def FinalizeMigrationSource(self, instance, success, live):
2547     """Finalize the instance migration on the source node.
2548
2549     @type instance: L{objects.Instance}
2550     @param instance: the instance that was migrated
2551     @type success: bool
2552     @param success: whether the migration succeeded or not
2553     @type live: bool
2554     @param live: whether the user requested a live migration or not
2555
2556     """
2557     if success:
2558       pidfile, pid, _ = self._InstancePidAlive(instance.name)
2559       utils.KillProcess(pid)
2560       self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2561     elif live:
2562       self._CallMonitorCommand(instance.name, self._CONT_CMD)
2563
2564   def GetMigrationStatus(self, instance):
2565     """Get the migration status
2566
2567     @type instance: L{objects.Instance}
2568     @param instance: the instance that is being migrated
2569     @rtype: L{objects.MigrationStatus}
2570     @return: the status of the current migration (one of
2571              L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2572              progress info that can be retrieved from the hypervisor
2573
2574     """
2575     info_command = "info migrate"
2576     for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2577       result = self._CallMonitorCommand(instance.name, info_command)
2578       match = self._MIGRATION_STATUS_RE.search(result.stdout)
2579       if not match:
2580         if not result.stdout:
2581           logging.info("KVM: empty 'info migrate' result")
2582         else:
2583           logging.warning("KVM: unknown 'info migrate' result: %s",
2584                           result.stdout)
2585       else:
2586         status = match.group(1)
2587         if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2588           migration_status = objects.MigrationStatus(status=status)
2589           match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2590           if match:
2591             migration_status.transferred_ram = match.group("transferred")
2592             migration_status.total_ram = match.group("total")
2593
2594           return migration_status
2595
2596         logging.warning("KVM: unknown migration status '%s'", status)
2597
2598       time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2599
2600     return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2601
2602   def BalloonInstanceMemory(self, instance, mem):
2603     """Balloon an instance memory to a certain value.
2604
2605     @type instance: L{objects.Instance}
2606     @param instance: instance to be accepted
2607     @type mem: int
2608     @param mem: actual memory size to use for instance runtime
2609
2610     """
2611     self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2612
2613   def GetNodeInfo(self):
2614     """Return information about the node.
2615
2616     @return: a dict with the following keys (values in MiB):
2617           - memory_total: the total memory size on the node
2618           - memory_free: the available memory on the node for instances
2619           - memory_dom0: the memory used by the node itself, if available
2620           - hv_version: the hypervisor version in the form (major, minor,
2621                         revision)
2622
2623     """
2624     result = self.GetLinuxNodeInfo()
2625     # FIXME: this is the global kvm version, but the actual version can be
2626     # customized as an hv parameter. we should use the nodegroup's default kvm
2627     # path parameter here.
2628     _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2629     result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2630     return result
2631
2632   @classmethod
2633   def GetInstanceConsole(cls, instance, hvparams, beparams):
2634     """Return a command for connecting to the console of an instance.
2635
2636     """
2637     if hvparams[constants.HV_SERIAL_CONSOLE]:
2638       cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2639              constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2640              utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2641              "STDIO,%s" % cls._SocatUnixConsoleParams(),
2642              "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2643       return objects.InstanceConsole(instance=instance.name,
2644                                      kind=constants.CONS_SSH,
2645                                      host=instance.primary_node,
2646                                      user=constants.SSH_CONSOLE_USER,
2647                                      command=cmd)
2648
2649     vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2650     if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2651       display = instance.network_port - constants.VNC_BASE_PORT
2652       return objects.InstanceConsole(instance=instance.name,
2653                                      kind=constants.CONS_VNC,
2654                                      host=vnc_bind_address,
2655                                      port=instance.network_port,
2656                                      display=display)
2657
2658     spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2659     if spice_bind:
2660       return objects.InstanceConsole(instance=instance.name,
2661                                      kind=constants.CONS_SPICE,
2662                                      host=spice_bind,
2663                                      port=instance.network_port)
2664
2665     return objects.InstanceConsole(instance=instance.name,
2666                                    kind=constants.CONS_MESSAGE,
2667                                    message=("No serial shell for instance %s" %
2668                                             instance.name))
2669
2670   def Verify(self):
2671     """Verify the hypervisor.
2672
2673     Check that the required binaries exist.
2674
2675     @return: Problem description if something is wrong, C{None} otherwise
2676
2677     """
2678     msgs = []
2679     # FIXME: this is the global kvm binary, but the actual path can be
2680     # customized as an hv parameter; we should use the nodegroup's
2681     # default kvm path parameter here.
2682     if not os.path.exists(constants.KVM_PATH):
2683       msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2684     if not os.path.exists(constants.SOCAT_PATH):
2685       msgs.append("The socat binary ('%s') does not exist" %
2686                   constants.SOCAT_PATH)
2687
2688     return self._FormatVerifyResults(msgs)
2689
2690   @classmethod
2691   def CheckParameterSyntax(cls, hvparams):
2692     """Check the given parameters for validity.
2693
2694     @type hvparams:  dict
2695     @param hvparams: dictionary with parameter names/value
2696     @raise errors.HypervisorError: when a parameter is not valid
2697
2698     """
2699     super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2700
2701     kernel_path = hvparams[constants.HV_KERNEL_PATH]
2702     if kernel_path:
2703       if not hvparams[constants.HV_ROOT_PATH]:
2704         raise errors.HypervisorError("Need a root partition for the instance,"
2705                                      " if a kernel is defined")
2706
2707     if (hvparams[constants.HV_VNC_X509_VERIFY] and
2708         not hvparams[constants.HV_VNC_X509]):
2709       raise errors.HypervisorError("%s must be defined, if %s is" %
2710                                    (constants.HV_VNC_X509,
2711                                     constants.HV_VNC_X509_VERIFY))
2712
2713     if hvparams[constants.HV_SERIAL_CONSOLE]:
2714       serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2715       valid_speeds = constants.VALID_SERIAL_SPEEDS
2716       if not serial_speed or serial_speed not in valid_speeds:
2717         raise errors.HypervisorError("Invalid serial console speed, must be"
2718                                      " one of: %s" %
2719                                      utils.CommaJoin(valid_speeds))
2720
2721     boot_order = hvparams[constants.HV_BOOT_ORDER]
2722     if (boot_order == constants.HT_BO_CDROM and
2723         not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2724       raise errors.HypervisorError("Cannot boot from cdrom without an"
2725                                    " ISO path")
2726
2727     security_model = hvparams[constants.HV_SECURITY_MODEL]
2728     if security_model == constants.HT_SM_USER:
2729       if not hvparams[constants.HV_SECURITY_DOMAIN]:
2730         raise errors.HypervisorError("A security domain (user to run kvm as)"
2731                                      " must be specified")
2732     elif (security_model == constants.HT_SM_NONE or
2733           security_model == constants.HT_SM_POOL):
2734       if hvparams[constants.HV_SECURITY_DOMAIN]:
2735         raise errors.HypervisorError("Cannot have a security domain when the"
2736                                      " security model is 'none' or 'pool'")
2737
2738     spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2739     spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2740     if spice_bind:
2741       if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2742         # if an IP version is specified, the spice_bind parameter must be an
2743         # IP of that family
2744         if (netutils.IP4Address.IsValid(spice_bind) and
2745             spice_ip_version != constants.IP4_VERSION):
2746           raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2747                                        " the specified IP version is %s" %
2748                                        (spice_bind, spice_ip_version))
2749
2750         if (netutils.IP6Address.IsValid(spice_bind) and
2751             spice_ip_version != constants.IP6_VERSION):
2752           raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2753                                        " the specified IP version is %s" %
2754                                        (spice_bind, spice_ip_version))
2755     else:
2756       # All the other SPICE parameters depend on spice_bind being set. Raise an
2757       # error if any of them is set without it.
2758       for param in _SPICE_ADDITIONAL_PARAMS:
2759         if hvparams[param]:
2760           raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2761                                        (param, constants.HV_KVM_SPICE_BIND))
2762
2763   @classmethod
2764   def ValidateParameters(cls, hvparams):
2765     """Check the given parameters for validity.
2766
2767     @type hvparams:  dict
2768     @param hvparams: dictionary with parameter names/value
2769     @raise errors.HypervisorError: when a parameter is not valid
2770
2771     """
2772     super(KVMHypervisor, cls).ValidateParameters(hvparams)
2773
2774     kvm_path = hvparams[constants.HV_KVM_PATH]
2775
2776     security_model = hvparams[constants.HV_SECURITY_MODEL]
2777     if security_model == constants.HT_SM_USER:
2778       username = hvparams[constants.HV_SECURITY_DOMAIN]
2779       try:
2780         pwd.getpwnam(username)
2781       except KeyError:
2782         raise errors.HypervisorError("Unknown security domain user %s"
2783                                      % username)
2784
2785     spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2786     if spice_bind:
2787       # only one of VNC and SPICE can be used currently.
2788       if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2789         raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2790                                      " only one of them can be used at a"
2791                                      " given time")
2792
2793       # check that KVM supports SPICE
2794       kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2795       if not cls._SPICE_RE.search(kvmhelp):
2796         raise errors.HypervisorError("SPICE is configured, but it is not"
2797                                      " supported according to 'kvm --help'")
2798
2799       # if spice_bind is not an IP address, it must be a valid interface
2800       bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2801                        netutils.IP6Address.IsValid(spice_bind))
2802       if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2803         raise errors.HypervisorError("SPICE: The %s parameter must be either"
2804                                      " a valid IP address or interface name" %
2805                                      constants.HV_KVM_SPICE_BIND)
2806
2807     machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2808     if machine_version:
2809       output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2810       if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2811         raise errors.HypervisorError("Unsupported machine version: %s" %
2812                                      machine_version)
2813
2814   @classmethod
2815   def PowercycleNode(cls):
2816     """KVM powercycle, just a wrapper over Linux powercycle.
2817
2818     """
2819     cls.LinuxPowercycle()