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