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