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