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