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