Add cluster name to instance migration RPC
[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: hv_base.NO_CHECK, # will be checked later
464     constants.HV_VNC_TLS: hv_base.NO_CHECK,
465     constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
466     constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
467     constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
468     constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
469     constants.HV_KVM_SPICE_IP_VERSION:
470       (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
471                          x in constants.VALID_IP_VERSIONS),
472        "The SPICE IP version should be 4 or 6",
473        None, None),
474     constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
475     constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
476       hv_base.ParamInSet(
477         False, constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
478     constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
479       hv_base.ParamInSet(
480         False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
481     constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
482       hv_base.ParamInSet(
483         False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
484     constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
485       hv_base.ParamInSet(
486         False, constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
487     constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
488     constants.HV_KVM_SPICE_USE_TLS: hv_base.NO_CHECK,
489     constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
490     constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
491     constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
492     constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
493     constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
494     constants.HV_BOOT_ORDER:
495       hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
496     constants.HV_NIC_TYPE:
497       hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
498     constants.HV_DISK_TYPE:
499       hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
500     constants.HV_KVM_CDROM_DISK_TYPE:
501       hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
502     constants.HV_USB_MOUSE:
503       hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
504     constants.HV_KEYMAP: hv_base.NO_CHECK,
505     constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
506     constants.HV_MIGRATION_BANDWIDTH: hv_base.REQ_NONNEGATIVE_INT_CHECK,
507     constants.HV_MIGRATION_DOWNTIME: hv_base.REQ_NONNEGATIVE_INT_CHECK,
508     constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
509     constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
510     constants.HV_DISK_CACHE:
511       hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
512     constants.HV_SECURITY_MODEL:
513       hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
514     constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
515     constants.HV_KVM_FLAG:
516       hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
517     constants.HV_VHOST_NET: hv_base.NO_CHECK,
518     constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
519     constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
520     constants.HV_REBOOT_BEHAVIOR:
521       hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
522     constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
523     constants.HV_CPU_TYPE: hv_base.NO_CHECK,
524     constants.HV_CPU_CORES: hv_base.OPT_NONNEGATIVE_INT_CHECK,
525     constants.HV_CPU_THREADS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
526     constants.HV_CPU_SOCKETS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
527     constants.HV_SOUNDHW: hv_base.NO_CHECK,
528     constants.HV_USB_DEVICES: hv_base.NO_CHECK,
529     constants.HV_VGA: hv_base.NO_CHECK,
530     constants.HV_KVM_EXTRA: hv_base.NO_CHECK,
531     constants.HV_KVM_MACHINE_VERSION: hv_base.NO_CHECK,
532     }
533
534   _VIRTIO = "virtio"
535   _VIRTIO_NET_PCI = "virtio-net-pci"
536
537   _MIGRATION_STATUS_RE = re.compile("Migration\s+status:\s+(\w+)",
538                                     re.M | re.I)
539   _MIGRATION_PROGRESS_RE = \
540     re.compile(r"\s*transferred\s+ram:\s+(?P<transferred>\d+)\s+kbytes\s*\n"
541                r"\s*remaining\s+ram:\s+(?P<remaining>\d+)\s+kbytes\s*\n"
542                r"\s*total\s+ram:\s+(?P<total>\d+)\s+kbytes\s*\n", re.I)
543
544   _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
545   _MIGRATION_INFO_RETRY_DELAY = 2
546
547   _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
548
549   _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
550   _CPU_INFO_CMD = "info cpus"
551   _CONT_CMD = "cont"
552
553   _DEFAULT_MACHINE_VERSION_RE = re.compile(r"^(\S+).*\(default\)", re.M)
554   _CHECK_MACHINE_VERSION_RE = \
555     staticmethod(lambda x: re.compile(r"^(%s)[ ]+.*PC" % x, re.M))
556
557   _QMP_RE = re.compile(r"^-qmp\s", re.M)
558   _SPICE_RE = re.compile(r"^-spice\s", re.M)
559   _VHOST_RE = re.compile(r"^-net\s.*,vhost=on|off", re.M)
560   _ENABLE_KVM_RE = re.compile(r"^-enable-kvm\s", re.M)
561   _DISABLE_KVM_RE = re.compile(r"^-disable-kvm\s", re.M)
562   _NETDEV_RE = re.compile(r"^-netdev\s", re.M)
563   _DISPLAY_RE = re.compile(r"^-display\s", re.M)
564   _MACHINE_RE = re.compile(r"^-machine\s", re.M)
565   _NEW_VIRTIO_RE = re.compile(r"^name \"%s\"" % _VIRTIO_NET_PCI, re.M)
566   # match  -drive.*boot=on|off on different lines, but in between accept only
567   # dashes not preceeded by a new line (which would mean another option
568   # different than -drive is starting)
569   _BOOT_RE = re.compile(r"^-drive\s([^-]|(?<!^)-)*,boot=on\|off", re.M | re.S)
570   _UUID_RE = re.compile(r"^-uuid\s", re.M)
571
572   ANCILLARY_FILES = [
573     _KVM_NETWORK_SCRIPT,
574     ]
575   ANCILLARY_FILES_OPT = [
576     _KVM_NETWORK_SCRIPT,
577     ]
578
579   # Supported kvm options to get output from
580   _KVMOPT_HELP = "help"
581   _KVMOPT_MLIST = "mlist"
582   _KVMOPT_DEVICELIST = "devicelist"
583
584   # Command to execute to get the output from kvm, and whether to
585   # accept the output even on failure.
586   _KVMOPTS_CMDS = {
587     _KVMOPT_HELP: (["--help"], False),
588     _KVMOPT_MLIST: (["-M", "?"], False),
589     _KVMOPT_DEVICELIST: (["-device", "?"], True),
590   }
591
592   def __init__(self):
593     hv_base.BaseHypervisor.__init__(self)
594     # Let's make sure the directories we need exist, even if the RUN_DIR lives
595     # in a tmpfs filesystem or has been otherwise wiped out.
596     dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
597     utils.EnsureDirs(dirs)
598
599   @classmethod
600   def _InstancePidFile(cls, instance_name):
601     """Returns the instance pidfile.
602
603     """
604     return utils.PathJoin(cls._PIDS_DIR, instance_name)
605
606   @classmethod
607   def _InstanceUidFile(cls, instance_name):
608     """Returns the instance uidfile.
609
610     """
611     return utils.PathJoin(cls._UIDS_DIR, instance_name)
612
613   @classmethod
614   def _InstancePidInfo(cls, pid):
615     """Check pid file for instance information.
616
617     Check that a pid file is associated with an instance, and retrieve
618     information from its command line.
619
620     @type pid: string or int
621     @param pid: process id of the instance to check
622     @rtype: tuple
623     @return: (instance_name, memory, vcpus)
624     @raise errors.HypervisorError: when an instance cannot be found
625
626     """
627     alive = utils.IsProcessAlive(pid)
628     if not alive:
629       raise errors.HypervisorError("Cannot get info for pid %s" % pid)
630
631     cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
632     try:
633       cmdline = utils.ReadFile(cmdline_file)
634     except EnvironmentError, err:
635       raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
636                                    (pid, err))
637
638     instance = None
639     memory = 0
640     vcpus = 0
641
642     arg_list = cmdline.split("\x00")
643     while arg_list:
644       arg = arg_list.pop(0)
645       if arg == "-name":
646         instance = arg_list.pop(0)
647       elif arg == "-m":
648         memory = int(arg_list.pop(0))
649       elif arg == "-smp":
650         vcpus = int(arg_list.pop(0).split(",")[0])
651
652     if instance is None:
653       raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
654                                    " instance" % pid)
655
656     return (instance, memory, vcpus)
657
658   def _InstancePidAlive(self, instance_name):
659     """Returns the instance pidfile, pid, and liveness.
660
661     @type instance_name: string
662     @param instance_name: instance name
663     @rtype: tuple
664     @return: (pid file name, pid, liveness)
665
666     """
667     pidfile = self._InstancePidFile(instance_name)
668     pid = utils.ReadPidFile(pidfile)
669
670     alive = False
671     try:
672       cmd_instance = self._InstancePidInfo(pid)[0]
673       alive = (cmd_instance == instance_name)
674     except errors.HypervisorError:
675       pass
676
677     return (pidfile, pid, alive)
678
679   def _CheckDown(self, instance_name):
680     """Raises an error unless the given instance is down.
681
682     """
683     alive = self._InstancePidAlive(instance_name)[2]
684     if alive:
685       raise errors.HypervisorError("Failed to start instance %s: %s" %
686                                    (instance_name, "already running"))
687
688   @classmethod
689   def _InstanceMonitor(cls, instance_name):
690     """Returns the instance monitor socket name
691
692     """
693     return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
694
695   @classmethod
696   def _InstanceSerial(cls, instance_name):
697     """Returns the instance serial socket name
698
699     """
700     return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
701
702   @classmethod
703   def _InstanceQmpMonitor(cls, instance_name):
704     """Returns the instance serial QMP socket name
705
706     """
707     return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
708
709   @staticmethod
710   def _SocatUnixConsoleParams():
711     """Returns the correct parameters for socat
712
713     If we have a new-enough socat we can use raw mode with an escape character.
714
715     """
716     if constants.SOCAT_USE_ESCAPE:
717       return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
718     else:
719       return "echo=0,icanon=0"
720
721   @classmethod
722   def _InstanceKVMRuntime(cls, instance_name):
723     """Returns the instance KVM runtime filename
724
725     """
726     return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
727
728   @classmethod
729   def _InstanceChrootDir(cls, instance_name):
730     """Returns the name of the KVM chroot dir of the instance
731
732     """
733     return utils.PathJoin(cls._CHROOT_DIR, instance_name)
734
735   @classmethod
736   def _InstanceNICDir(cls, instance_name):
737     """Returns the name of the directory holding the tap device files for a
738     given instance.
739
740     """
741     return utils.PathJoin(cls._NICS_DIR, instance_name)
742
743   @classmethod
744   def _InstanceNICFile(cls, instance_name, seq):
745     """Returns the name of the file containing the tap device for a given NIC
746
747     """
748     return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
749
750   @classmethod
751   def _InstanceKeymapFile(cls, instance_name):
752     """Returns the name of the file containing the keymap for a given instance
753
754     """
755     return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
756
757   @classmethod
758   def _TryReadUidFile(cls, uid_file):
759     """Try to read a uid file
760
761     """
762     if os.path.exists(uid_file):
763       try:
764         uid = int(utils.ReadOneLineFile(uid_file))
765         return uid
766       except EnvironmentError:
767         logging.warning("Can't read uid file", exc_info=True)
768       except (TypeError, ValueError):
769         logging.warning("Can't parse uid file contents", exc_info=True)
770     return None
771
772   @classmethod
773   def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
774     """Removes an instance's rutime sockets/files/dirs.
775
776     """
777     utils.RemoveFile(pidfile)
778     utils.RemoveFile(cls._InstanceMonitor(instance_name))
779     utils.RemoveFile(cls._InstanceSerial(instance_name))
780     utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
781     utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
782     utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
783     uid_file = cls._InstanceUidFile(instance_name)
784     uid = cls._TryReadUidFile(uid_file)
785     utils.RemoveFile(uid_file)
786     if uid is not None:
787       uidpool.ReleaseUid(uid)
788     try:
789       shutil.rmtree(cls._InstanceNICDir(instance_name))
790     except OSError, err:
791       if err.errno != errno.ENOENT:
792         raise
793     try:
794       chroot_dir = cls._InstanceChrootDir(instance_name)
795       utils.RemoveDir(chroot_dir)
796     except OSError, err:
797       if err.errno == errno.ENOTEMPTY:
798         # The chroot directory is expected to be empty, but it isn't.
799         new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
800                                           prefix="%s-%s-" %
801                                           (instance_name,
802                                            utils.TimestampForFilename()))
803         logging.warning("The chroot directory of instance %s can not be"
804                         " removed as it is not empty. Moving it to the"
805                         " quarantine instead. Please investigate the"
806                         " contents (%s) and clean up manually",
807                         instance_name, new_chroot_dir)
808         utils.RenameFile(chroot_dir, new_chroot_dir)
809       else:
810         raise
811
812   @staticmethod
813   def _ConfigureNIC(instance, seq, nic, tap):
814     """Run the network configuration script for a specified NIC
815
816     @param instance: instance we're acting on
817     @type instance: instance object
818     @param seq: nic sequence number
819     @type seq: int
820     @param nic: nic we're acting on
821     @type nic: nic object
822     @param tap: the host's tap interface this NIC corresponds to
823     @type tap: str
824
825     """
826     if instance.tags:
827       tags = " ".join(instance.tags)
828     else:
829       tags = ""
830
831     env = {
832       "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
833       "INSTANCE": instance.name,
834       "MAC": nic.mac,
835       "MODE": nic.nicparams[constants.NIC_MODE],
836       "INTERFACE": tap,
837       "INTERFACE_INDEX": str(seq),
838       "TAGS": tags,
839     }
840
841     if nic.ip:
842       env["IP"] = nic.ip
843
844     if nic.nicparams[constants.NIC_LINK]:
845       env["LINK"] = nic.nicparams[constants.NIC_LINK]
846
847     if nic.network:
848       n = objects.Network.FromDict(nic.netinfo)
849       env.update(n.HooksDict())
850
851     if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
852       env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
853
854     result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
855     if result.failed:
856       raise errors.HypervisorError("Failed to configure interface %s: %s;"
857                                    " network configuration script output: %s" %
858                                    (tap, result.fail_reason, result.output))
859
860   @staticmethod
861   def _VerifyAffinityPackage():
862     if affinity is None:
863       raise errors.HypervisorError("affinity Python package not"
864                                    " found; cannot use CPU pinning under KVM")
865
866   @staticmethod
867   def _BuildAffinityCpuMask(cpu_list):
868     """Create a CPU mask suitable for sched_setaffinity from a list of
869     CPUs.
870
871     See man taskset for more info on sched_setaffinity masks.
872     For example: [ 0, 2, 5, 6 ] will return 101 (0x65, 0..01100101).
873
874     @type cpu_list: list of int
875     @param cpu_list: list of physical CPU numbers to map to vCPUs in order
876     @rtype: int
877     @return: a bit mask of CPU affinities
878
879     """
880     if cpu_list == constants.CPU_PINNING_OFF:
881       return constants.CPU_PINNING_ALL_KVM
882     else:
883       return sum(2 ** cpu for cpu in cpu_list)
884
885   @classmethod
886   def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
887     """Change CPU affinity for running VM according to given CPU mask.
888
889     @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
890     @type cpu_mask: string
891     @param process_id: process ID of KVM process. Used to pin entire VM
892                        to physical CPUs.
893     @type process_id: int
894     @param thread_dict: map of virtual CPUs to KVM thread IDs
895     @type thread_dict: dict int:int
896
897     """
898     # Convert the string CPU mask to a list of list of int's
899     cpu_list = utils.ParseMultiCpuMask(cpu_mask)
900
901     if len(cpu_list) == 1:
902       all_cpu_mapping = cpu_list[0]
903       if all_cpu_mapping == constants.CPU_PINNING_OFF:
904         # If CPU pinning has 1 entry that's "all", then do nothing
905         pass
906       else:
907         # If CPU pinning has one non-all entry, map the entire VM to
908         # one set of physical CPUs
909         cls._VerifyAffinityPackage()
910         affinity.set_process_affinity_mask(
911           process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
912     else:
913       # The number of vCPUs mapped should match the number of vCPUs
914       # reported by KVM. This was already verified earlier, so
915       # here only as a sanity check.
916       assert len(thread_dict) == len(cpu_list)
917       cls._VerifyAffinityPackage()
918
919       # For each vCPU, map it to the proper list of physical CPUs
920       for vcpu, i in zip(cpu_list, range(len(cpu_list))):
921         affinity.set_process_affinity_mask(thread_dict[i],
922                                            cls._BuildAffinityCpuMask(vcpu))
923
924   def _GetVcpuThreadIds(self, instance_name):
925     """Get a mapping of vCPU no. to thread IDs for the instance
926
927     @type instance_name: string
928     @param instance_name: instance in question
929     @rtype: dictionary of int:int
930     @return: a dictionary mapping vCPU numbers to thread IDs
931
932     """
933     result = {}
934     output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
935     for line in output.stdout.splitlines():
936       match = self._CPU_INFO_RE.search(line)
937       if not match:
938         continue
939       grp = map(int, match.groups())
940       result[grp[0]] = grp[1]
941
942     return result
943
944   def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
945     """Complete CPU pinning.
946
947     @type instance_name: string
948     @param instance_name: name of instance
949     @type cpu_mask: string
950     @param cpu_mask: CPU pinning mask as entered by user
951
952     """
953     # Get KVM process ID, to be used if need to pin entire VM
954     _, pid, _ = self._InstancePidAlive(instance_name)
955     # Get vCPU thread IDs, to be used if need to pin vCPUs separately
956     thread_dict = self._GetVcpuThreadIds(instance_name)
957     # Run CPU pinning, based on configured mask
958     self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
959
960   def ListInstances(self, hvparams=None):
961     """Get the list of running instances.
962
963     We can do this by listing our live instances directory and
964     checking whether the associated kvm process is still alive.
965
966     """
967     result = []
968     for name in os.listdir(self._PIDS_DIR):
969       if self._InstancePidAlive(name)[2]:
970         result.append(name)
971     return result
972
973   def GetInstanceInfo(self, instance_name, hvparams=None):
974     """Get instance properties.
975
976     @type instance_name: string
977     @param instance_name: the instance name
978     @type hvparams: dict of strings
979     @param hvparams: hvparams to be used with this instance
980     @rtype: tuple of strings
981     @return: (name, id, memory, vcpus, stat, times)
982
983     """
984     _, pid, alive = self._InstancePidAlive(instance_name)
985     if not alive:
986       return None
987
988     _, memory, vcpus = self._InstancePidInfo(pid)
989     istat = "---b-"
990     times = "0"
991
992     try:
993       qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
994       qmp.connect()
995       vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
996       # Will fail if ballooning is not enabled, but we can then just resort to
997       # the value above.
998       mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
999       memory = mem_bytes / 1048576
1000     except errors.HypervisorError:
1001       pass
1002
1003     return (instance_name, pid, memory, vcpus, istat, times)
1004
1005   def GetAllInstancesInfo(self, hvparams=None):
1006     """Get properties of all instances.
1007
1008     @type hvparams: dict of strings
1009     @param hvparams: hypervisor parameter
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.IsValidInterface(vnc_bind_address):
1230         if_addresses = netutils.GetInterfaceIpAddresses(vnc_bind_address)
1231         if_ip4_addresses = if_addresses[constants.IP4_VERSION]
1232         if len(if_ip4_addresses) < 1:
1233           logging.error("Could not determine IPv4 address of interface %s",
1234                         vnc_bind_address)
1235         else:
1236           vnc_bind_address = if_ip4_addresses[0]
1237       if netutils.IP4Address.IsValid(vnc_bind_address):
1238         if instance.network_port > constants.VNC_BASE_PORT:
1239           display = instance.network_port - constants.VNC_BASE_PORT
1240           if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1241             vnc_arg = ":%d" % (display)
1242           else:
1243             vnc_arg = "%s:%d" % (vnc_bind_address, display)
1244         else:
1245           logging.error("Network port is not a valid VNC display (%d < %d),"
1246                         " not starting VNC",
1247                         instance.network_port, constants.VNC_BASE_PORT)
1248           vnc_arg = "none"
1249
1250         # Only allow tls and other option when not binding to a file, for now.
1251         # kvm/qemu gets confused otherwise about the filename to use.
1252         vnc_append = ""
1253         if hvp[constants.HV_VNC_TLS]:
1254           vnc_append = "%s,tls" % vnc_append
1255           if hvp[constants.HV_VNC_X509_VERIFY]:
1256             vnc_append = "%s,x509verify=%s" % (vnc_append,
1257                                                hvp[constants.HV_VNC_X509])
1258           elif hvp[constants.HV_VNC_X509]:
1259             vnc_append = "%s,x509=%s" % (vnc_append,
1260                                          hvp[constants.HV_VNC_X509])
1261         if hvp[constants.HV_VNC_PASSWORD_FILE]:
1262           vnc_append = "%s,password" % vnc_append
1263
1264         vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1265
1266       else:
1267         vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1268
1269       kvm_cmd.extend(["-vnc", vnc_arg])
1270     elif spice_bind:
1271       # FIXME: this is wrong here; the iface ip address differs
1272       # between systems, so it should be done in _ExecuteKVMRuntime
1273       if netutils.IsValidInterface(spice_bind):
1274         # The user specified a network interface, we have to figure out the IP
1275         # address.
1276         addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1277         spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1278
1279         # if the user specified an IP version and the interface does not
1280         # have that kind of IP addresses, throw an exception
1281         if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1282           if not addresses[spice_ip_version]:
1283             raise errors.HypervisorError("SPICE: Unable to get an IPv%s address"
1284                                          " for %s" % (spice_ip_version,
1285                                                       spice_bind))
1286
1287         # the user did not specify an IP version, we have to figure it out
1288         elif (addresses[constants.IP4_VERSION] and
1289               addresses[constants.IP6_VERSION]):
1290           # we have both ipv4 and ipv6, let's use the cluster default IP
1291           # version
1292           cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1293           spice_ip_version = \
1294             netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1295         elif addresses[constants.IP4_VERSION]:
1296           spice_ip_version = constants.IP4_VERSION
1297         elif addresses[constants.IP6_VERSION]:
1298           spice_ip_version = constants.IP6_VERSION
1299         else:
1300           raise errors.HypervisorError("SPICE: Unable to get an IP address"
1301                                        " for %s" % (spice_bind))
1302
1303         spice_address = addresses[spice_ip_version][0]
1304
1305       else:
1306         # spice_bind is known to be a valid IP address, because
1307         # ValidateParameters checked it.
1308         spice_address = spice_bind
1309
1310       spice_arg = "addr=%s" % spice_address
1311       if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1312         spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1313                      (spice_arg, instance.network_port,
1314                       pathutils.SPICE_CACERT_FILE))
1315         spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1316                      (spice_arg, pathutils.SPICE_CERT_FILE,
1317                       pathutils.SPICE_CERT_FILE))
1318         tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1319         if tls_ciphers:
1320           spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1321       else:
1322         spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1323
1324       if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1325         spice_arg = "%s,disable-ticketing" % spice_arg
1326
1327       if spice_ip_version:
1328         spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1329
1330       # Image compression options
1331       img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1332       img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1333       img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1334       if img_lossless:
1335         spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1336       if img_jpeg:
1337         spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1338       if img_zlib_glz:
1339         spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1340
1341       # Video stream detection
1342       video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1343       if video_streaming:
1344         spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1345
1346       # Audio compression, by default in qemu-kvm it is on
1347       if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1348         spice_arg = "%s,playback-compression=off" % spice_arg
1349       if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1350         spice_arg = "%s,agent-mouse=off" % spice_arg
1351       else:
1352         # Enable the spice agent communication channel between the host and the
1353         # agent.
1354         kvm_cmd.extend(["-device", "virtio-serial-pci"])
1355         kvm_cmd.extend([
1356           "-device",
1357           "virtserialport,chardev=spicechannel0,name=com.redhat.spice.0",
1358           ])
1359         kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1360
1361       logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1362       kvm_cmd.extend(["-spice", spice_arg])
1363
1364     else:
1365       # From qemu 1.4 -nographic is incompatible with -daemonize. The new way
1366       # also works in earlier versions though (tested with 1.1 and 1.3)
1367       if self._DISPLAY_RE.search(kvmhelp):
1368         kvm_cmd.extend(["-display", "none"])
1369       else:
1370         kvm_cmd.extend(["-nographic"])
1371
1372     if hvp[constants.HV_USE_LOCALTIME]:
1373       kvm_cmd.extend(["-localtime"])
1374
1375     if hvp[constants.HV_KVM_USE_CHROOT]:
1376       kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1377
1378     # Add qemu-KVM -cpu param
1379     if hvp[constants.HV_CPU_TYPE]:
1380       kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1381
1382     # As requested by music lovers
1383     if hvp[constants.HV_SOUNDHW]:
1384       kvm_cmd.extend(["-soundhw", hvp[constants.HV_SOUNDHW]])
1385
1386     # Pass a -vga option if requested, or if spice is used, for backwards
1387     # compatibility.
1388     if hvp[constants.HV_VGA]:
1389       kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1390     elif spice_bind:
1391       kvm_cmd.extend(["-vga", "qxl"])
1392
1393     # Various types of usb devices, comma separated
1394     if hvp[constants.HV_USB_DEVICES]:
1395       for dev in hvp[constants.HV_USB_DEVICES].split(","):
1396         kvm_cmd.extend(["-usbdevice", dev])
1397
1398     # Set system UUID to instance UUID
1399     if self._UUID_RE.search(kvmhelp):
1400       kvm_cmd.extend(["-uuid", instance.uuid])
1401
1402     if hvp[constants.HV_KVM_EXTRA]:
1403       kvm_cmd.extend([hvp[constants.HV_KVM_EXTRA]])
1404
1405     # Save the current instance nics, but defer their expansion as parameters,
1406     # as we'll need to generate executable temp files for them.
1407     kvm_nics = instance.nics
1408     hvparams = hvp
1409
1410     return (kvm_cmd, kvm_nics, hvparams)
1411
1412   def _WriteKVMRuntime(self, instance_name, data):
1413     """Write an instance's KVM runtime
1414
1415     """
1416     try:
1417       utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1418                       data=data)
1419     except EnvironmentError, err:
1420       raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1421
1422   def _ReadKVMRuntime(self, instance_name):
1423     """Read an instance's KVM runtime
1424
1425     """
1426     try:
1427       file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1428     except EnvironmentError, err:
1429       raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1430     return file_content
1431
1432   def _SaveKVMRuntime(self, instance, kvm_runtime):
1433     """Save an instance's KVM runtime
1434
1435     """
1436     kvm_cmd, kvm_nics, hvparams = kvm_runtime
1437     serialized_nics = [nic.ToDict() for nic in kvm_nics]
1438     serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1439     self._WriteKVMRuntime(instance.name, serialized_form)
1440
1441   def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1442     """Load an instance's KVM runtime
1443
1444     """
1445     if not serialized_runtime:
1446       serialized_runtime = self._ReadKVMRuntime(instance.name)
1447     loaded_runtime = serializer.Load(serialized_runtime)
1448     kvm_cmd, serialized_nics, hvparams = loaded_runtime
1449     kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1450     return (kvm_cmd, kvm_nics, hvparams)
1451
1452   def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1453     """Run the KVM cmd and check for errors
1454
1455     @type name: string
1456     @param name: instance name
1457     @type kvm_cmd: list of strings
1458     @param kvm_cmd: runcmd input for kvm
1459     @type tap_fds: list of int
1460     @param tap_fds: fds of tap devices opened by Ganeti
1461
1462     """
1463     try:
1464       result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1465     finally:
1466       for fd in tap_fds:
1467         utils_wrapper.CloseFdNoError(fd)
1468
1469     if result.failed:
1470       raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1471                                    (name, result.fail_reason, result.output))
1472     if not self._InstancePidAlive(name)[2]:
1473       raise errors.HypervisorError("Failed to start instance %s" % name)
1474
1475   def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1476     """Execute a KVM cmd, after completing it with some last minute data.
1477
1478     @type incoming: tuple of strings
1479     @param incoming: (target_host_ip, port)
1480     @type kvmhelp: string
1481     @param kvmhelp: output of kvm --help
1482
1483     """
1484     # Small _ExecuteKVMRuntime hv parameters programming howto:
1485     #  - conf_hvp contains the parameters as configured on ganeti. they might
1486     #    have changed since the instance started; only use them if the change
1487     #    won't affect the inside of the instance (which hasn't been rebooted).
1488     #  - up_hvp contains the parameters as they were when the instance was
1489     #    started, plus any new parameter which has been added between ganeti
1490     #    versions: it is paramount that those default to a value which won't
1491     #    affect the inside of the instance as well.
1492     conf_hvp = instance.hvparams
1493     name = instance.name
1494     self._CheckDown(name)
1495
1496     temp_files = []
1497
1498     kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1499     # the first element of kvm_cmd is always the path to the kvm binary
1500     kvm_path = kvm_cmd[0]
1501     up_hvp = objects.FillDict(conf_hvp, up_hvp)
1502
1503     # We know it's safe to run as a different user upon migration, so we'll use
1504     # the latest conf, from conf_hvp.
1505     security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1506     if security_model == constants.HT_SM_USER:
1507       kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1508
1509     keymap = conf_hvp[constants.HV_KEYMAP]
1510     if keymap:
1511       keymap_path = self._InstanceKeymapFile(name)
1512       # If a keymap file is specified, KVM won't use its internal defaults. By
1513       # first including the "en-us" layout, an error on loading the actual
1514       # layout (e.g. because it can't be found) won't lead to a non-functional
1515       # keyboard. A keyboard with incorrect keys is still better than none.
1516       utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1517       kvm_cmd.extend(["-k", keymap_path])
1518
1519     # We have reasons to believe changing something like the nic driver/type
1520     # upon migration won't exactly fly with the instance kernel, so for nic
1521     # related parameters we'll use up_hvp
1522     tapfds = []
1523     taps = []
1524     if not kvm_nics:
1525       kvm_cmd.extend(["-net", "none"])
1526     else:
1527       vnet_hdr = False
1528       tap_extra = ""
1529       nic_type = up_hvp[constants.HV_NIC_TYPE]
1530       if nic_type == constants.HT_NIC_PARAVIRTUAL:
1531         nic_model = self._VIRTIO
1532         try:
1533           devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1534           if self._NEW_VIRTIO_RE.search(devlist):
1535             nic_model = self._VIRTIO_NET_PCI
1536             vnet_hdr = True
1537         except errors.HypervisorError, _:
1538           # Older versions of kvm don't support DEVICE_LIST, but they don't
1539           # have new virtio syntax either.
1540           pass
1541
1542         if up_hvp[constants.HV_VHOST_NET]:
1543           # check for vhost_net support
1544           if self._VHOST_RE.search(kvmhelp):
1545             tap_extra = ",vhost=on"
1546           else:
1547             raise errors.HypervisorError("vhost_net is configured"
1548                                          " but it is not available")
1549       else:
1550         nic_model = nic_type
1551
1552       kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
1553
1554       for nic_seq, nic in enumerate(kvm_nics):
1555         tapname, tapfd = _OpenTap(vnet_hdr=vnet_hdr)
1556         tapfds.append(tapfd)
1557         taps.append(tapname)
1558         if kvm_supports_netdev:
1559           nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
1560           tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
1561           kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1562         else:
1563           nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1564                                                          nic.mac, nic_model)
1565           tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1566           kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1567
1568     if incoming:
1569       target, port = incoming
1570       kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1571
1572     # Changing the vnc password doesn't bother the guest that much. At most it
1573     # will surprise people who connect to it. Whether positively or negatively
1574     # it's debatable.
1575     vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1576     vnc_pwd = None
1577     if vnc_pwd_file:
1578       try:
1579         vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1580       except EnvironmentError, err:
1581         raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1582                                      % (vnc_pwd_file, err))
1583
1584     if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1585       utils.EnsureDirs([(self._InstanceChrootDir(name),
1586                          constants.SECURE_DIR_MODE)])
1587
1588     # Automatically enable QMP if version is >= 0.14
1589     if self._QMP_RE.search(kvmhelp):
1590       logging.debug("Enabling QMP")
1591       kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1592                       self._InstanceQmpMonitor(instance.name)])
1593
1594     # Configure the network now for starting instances and bridged interfaces,
1595     # during FinalizeMigration for incoming instances' routed interfaces
1596     for nic_seq, nic in enumerate(kvm_nics):
1597       if (incoming and
1598           nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1599         continue
1600       self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1601
1602     # CPU affinity requires kvm to start paused, so we set this flag if the
1603     # instance is not already paused and if we are not going to accept a
1604     # migrating instance. In the latter case, pausing is not needed.
1605     start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1606     if start_kvm_paused:
1607       kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1608
1609     # Note: CPU pinning is using up_hvp since changes take effect
1610     # during instance startup anyway, and to avoid problems when soft
1611     # rebooting the instance.
1612     cpu_pinning = False
1613     if up_hvp.get(constants.HV_CPU_MASK, None):
1614       cpu_pinning = True
1615
1616     if security_model == constants.HT_SM_POOL:
1617       ss = ssconf.SimpleStore()
1618       uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1619       all_uids = set(uidpool.ExpandUidPool(uid_pool))
1620       uid = uidpool.RequestUnusedUid(all_uids)
1621       try:
1622         username = pwd.getpwuid(uid.GetUid()).pw_name
1623         kvm_cmd.extend(["-runas", username])
1624         self._RunKVMCmd(name, kvm_cmd, tapfds)
1625       except:
1626         uidpool.ReleaseUid(uid)
1627         raise
1628       else:
1629         uid.Unlock()
1630         utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1631     else:
1632       self._RunKVMCmd(name, kvm_cmd, tapfds)
1633
1634     utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1635                      constants.RUN_DIRS_MODE)])
1636     for nic_seq, tap in enumerate(taps):
1637       utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1638                       data=tap)
1639
1640     if vnc_pwd:
1641       change_cmd = "change vnc password %s" % vnc_pwd
1642       self._CallMonitorCommand(instance.name, change_cmd)
1643
1644     # Setting SPICE password. We are not vulnerable to malicious passwordless
1645     # connection attempts because SPICE by default does not allow connections
1646     # if neither a password nor the "disable_ticketing" options are specified.
1647     # As soon as we send the password via QMP, that password is a valid ticket
1648     # for connection.
1649     spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1650     if spice_password_file:
1651       spice_pwd = ""
1652       try:
1653         spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1654       except EnvironmentError, err:
1655         raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1656                                      % (spice_password_file, err))
1657
1658       qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1659       qmp.connect()
1660       arguments = {
1661           "protocol": "spice",
1662           "password": spice_pwd,
1663       }
1664       qmp.Execute("set_password", arguments)
1665
1666     for filename in temp_files:
1667       utils.RemoveFile(filename)
1668
1669     # If requested, set CPU affinity and resume instance execution
1670     if cpu_pinning:
1671       self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1672
1673     start_memory = self._InstanceStartupMemory(instance)
1674     if start_memory < instance.beparams[constants.BE_MAXMEM]:
1675       self.BalloonInstanceMemory(instance, start_memory)
1676
1677     if start_kvm_paused:
1678       # To control CPU pinning, ballooning, and vnc/spice passwords
1679       # the VM was started in a frozen state. If freezing was not
1680       # explicitly requested resume the vm status.
1681       self._CallMonitorCommand(instance.name, self._CONT_CMD)
1682
1683   def StartInstance(self, instance, block_devices, startup_paused):
1684     """Start an instance.
1685
1686     """
1687     self._CheckDown(instance.name)
1688     kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1689     kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1690     kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1691                                            startup_paused, kvmhelp)
1692     self._SaveKVMRuntime(instance, kvm_runtime)
1693     self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1694
1695   def _CallMonitorCommand(self, instance_name, command):
1696     """Invoke a command on the instance monitor.
1697
1698     """
1699     # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1700     # version. The monitor protocol is designed for human consumption, whereas
1701     # QMP is made for programmatic usage. In the worst case QMP can also
1702     # execute monitor commands. As it is, all calls to socat take at least
1703     # 500ms and likely more: socat can't detect the end of the reply and waits
1704     # for 500ms of no data received before exiting (500 ms is the default for
1705     # the "-t" parameter).
1706     socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1707              (utils.ShellQuote(command),
1708               constants.SOCAT_PATH,
1709               utils.ShellQuote(self._InstanceMonitor(instance_name))))
1710     result = utils.RunCmd(socat)
1711     if result.failed:
1712       msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1713              " output: %s" %
1714              (command, instance_name, result.fail_reason, result.output))
1715       raise errors.HypervisorError(msg)
1716
1717     return result
1718
1719   @classmethod
1720   def _ParseKVMVersion(cls, text):
1721     """Parse the KVM version from the --help output.
1722
1723     @type text: string
1724     @param text: output of kvm --help
1725     @return: (version, v_maj, v_min, v_rev)
1726     @raise errors.HypervisorError: when the KVM version cannot be retrieved
1727
1728     """
1729     match = cls._VERSION_RE.search(text.splitlines()[0])
1730     if not match:
1731       raise errors.HypervisorError("Unable to get KVM version")
1732
1733     v_all = match.group(0)
1734     v_maj = int(match.group(1))
1735     v_min = int(match.group(2))
1736     if match.group(4):
1737       v_rev = int(match.group(4))
1738     else:
1739       v_rev = 0
1740     return (v_all, v_maj, v_min, v_rev)
1741
1742   @classmethod
1743   def _GetKVMOutput(cls, kvm_path, option):
1744     """Return the output of a kvm invocation
1745
1746     @type kvm_path: string
1747     @param kvm_path: path to the kvm executable
1748     @type option: a key of _KVMOPTS_CMDS
1749     @param option: kvm option to fetch the output from
1750     @return: output a supported kvm invocation
1751     @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1752
1753     """
1754     assert option in cls._KVMOPTS_CMDS, "Invalid output option"
1755
1756     optlist, can_fail = cls._KVMOPTS_CMDS[option]
1757
1758     result = utils.RunCmd([kvm_path] + optlist)
1759     if result.failed and not can_fail:
1760       raise errors.HypervisorError("Unable to get KVM %s output" %
1761                                     " ".join(cls._KVMOPTS_CMDS[option]))
1762     return result.output
1763
1764   @classmethod
1765   def _GetKVMVersion(cls, kvm_path):
1766     """Return the installed KVM version.
1767
1768     @return: (version, v_maj, v_min, v_rev)
1769     @raise errors.HypervisorError: when the KVM version cannot be retrieved
1770
1771     """
1772     return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
1773
1774   @classmethod
1775   def _GetDefaultMachineVersion(cls, kvm_path):
1776     """Return the default hardware revision (e.g. pc-1.1)
1777
1778     """
1779     output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
1780     match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
1781     if match:
1782       return match.group(1)
1783     else:
1784       return "pc"
1785
1786   def StopInstance(self, instance, force=False, retry=False, name=None):
1787     """Stop an instance.
1788
1789     """
1790     if name is not None and not force:
1791       raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1792     if name is None:
1793       name = instance.name
1794       acpi = instance.hvparams[constants.HV_ACPI]
1795     else:
1796       acpi = False
1797     _, pid, alive = self._InstancePidAlive(name)
1798     if pid > 0 and alive:
1799       if force or not acpi:
1800         utils.KillProcess(pid)
1801       else:
1802         self._CallMonitorCommand(name, "system_powerdown")
1803
1804   def CleanupInstance(self, instance_name):
1805     """Cleanup after a stopped instance
1806
1807     """
1808     pidfile, pid, alive = self._InstancePidAlive(instance_name)
1809     if pid > 0 and alive:
1810       raise errors.HypervisorError("Cannot cleanup a live instance")
1811     self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1812
1813   def RebootInstance(self, instance):
1814     """Reboot an instance.
1815
1816     """
1817     # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1818     # socket the instance will stop, but now power up again. So we'll resort
1819     # to shutdown and restart.
1820     _, _, alive = self._InstancePidAlive(instance.name)
1821     if not alive:
1822       raise errors.HypervisorError("Failed to reboot instance %s:"
1823                                    " not running" % instance.name)
1824     # StopInstance will delete the saved KVM runtime so:
1825     # ...first load it...
1826     kvm_runtime = self._LoadKVMRuntime(instance)
1827     # ...now we can safely call StopInstance...
1828     if not self.StopInstance(instance):
1829       self.StopInstance(instance, force=True)
1830     # ...and finally we can save it again, and execute it...
1831     self._SaveKVMRuntime(instance, kvm_runtime)
1832     kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1833     kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1834     self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1835
1836   def MigrationInfo(self, instance):
1837     """Get instance information to perform a migration.
1838
1839     @type instance: L{objects.Instance}
1840     @param instance: instance to be migrated
1841     @rtype: string
1842     @return: content of the KVM runtime file
1843
1844     """
1845     return self._ReadKVMRuntime(instance.name)
1846
1847   def AcceptInstance(self, instance, info, target):
1848     """Prepare to accept an instance.
1849
1850     @type instance: L{objects.Instance}
1851     @param instance: instance to be accepted
1852     @type info: string
1853     @param info: content of the KVM runtime file on the source node
1854     @type target: string
1855     @param target: target host (usually ip), on this node
1856
1857     """
1858     kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1859     incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1860     kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1861     kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1862     self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
1863                             incoming=incoming_address)
1864
1865   def FinalizeMigrationDst(self, instance, info, success):
1866     """Finalize the instance migration on the target node.
1867
1868     Stop the incoming mode KVM.
1869
1870     @type instance: L{objects.Instance}
1871     @param instance: instance whose migration is being finalized
1872
1873     """
1874     if success:
1875       kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1876       kvm_nics = kvm_runtime[1]
1877
1878       for nic_seq, nic in enumerate(kvm_nics):
1879         if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1880           # Bridged interfaces have already been configured
1881           continue
1882         try:
1883           tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1884         except EnvironmentError, err:
1885           logging.warning("Failed to find host interface for %s NIC #%d: %s",
1886                           instance.name, nic_seq, str(err))
1887           continue
1888         try:
1889           self._ConfigureNIC(instance, nic_seq, nic, tap)
1890         except errors.HypervisorError, err:
1891           logging.warning(str(err))
1892
1893       self._WriteKVMRuntime(instance.name, info)
1894     else:
1895       self.StopInstance(instance, force=True)
1896
1897   def MigrateInstance(self, cluster_name, instance, target, live):
1898     """Migrate an instance to a target node.
1899
1900     The migration will not be attempted if the instance is not
1901     currently running.
1902
1903     @type cluster_name: string
1904     @param cluster_name: name of the cluster
1905     @type instance: L{objects.Instance}
1906     @param instance: the instance to be migrated
1907     @type target: string
1908     @param target: ip address of the target node
1909     @type live: boolean
1910     @param live: perform a live migration
1911
1912     """
1913     instance_name = instance.name
1914     port = instance.hvparams[constants.HV_MIGRATION_PORT]
1915     _, _, alive = self._InstancePidAlive(instance_name)
1916     if not alive:
1917       raise errors.HypervisorError("Instance not running, cannot migrate")
1918
1919     if not live:
1920       self._CallMonitorCommand(instance_name, "stop")
1921
1922     migrate_command = ("migrate_set_speed %dm" %
1923                        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1924     self._CallMonitorCommand(instance_name, migrate_command)
1925
1926     migrate_command = ("migrate_set_downtime %dms" %
1927                        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1928     self._CallMonitorCommand(instance_name, migrate_command)
1929
1930     migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1931     self._CallMonitorCommand(instance_name, migrate_command)
1932
1933   def FinalizeMigrationSource(self, instance, success, live):
1934     """Finalize the instance migration on the source node.
1935
1936     @type instance: L{objects.Instance}
1937     @param instance: the instance that was migrated
1938     @type success: bool
1939     @param success: whether the migration succeeded or not
1940     @type live: bool
1941     @param live: whether the user requested a live migration or not
1942
1943     """
1944     if success:
1945       pidfile, pid, _ = self._InstancePidAlive(instance.name)
1946       utils.KillProcess(pid)
1947       self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1948     elif live:
1949       self._CallMonitorCommand(instance.name, self._CONT_CMD)
1950
1951   def GetMigrationStatus(self, instance):
1952     """Get the migration status
1953
1954     @type instance: L{objects.Instance}
1955     @param instance: the instance that is being migrated
1956     @rtype: L{objects.MigrationStatus}
1957     @return: the status of the current migration (one of
1958              L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1959              progress info that can be retrieved from the hypervisor
1960
1961     """
1962     info_command = "info migrate"
1963     for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1964       result = self._CallMonitorCommand(instance.name, info_command)
1965       match = self._MIGRATION_STATUS_RE.search(result.stdout)
1966       if not match:
1967         if not result.stdout:
1968           logging.info("KVM: empty 'info migrate' result")
1969         else:
1970           logging.warning("KVM: unknown 'info migrate' result: %s",
1971                           result.stdout)
1972       else:
1973         status = match.group(1)
1974         if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1975           migration_status = objects.MigrationStatus(status=status)
1976           match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1977           if match:
1978             migration_status.transferred_ram = match.group("transferred")
1979             migration_status.total_ram = match.group("total")
1980
1981           return migration_status
1982
1983         logging.warning("KVM: unknown migration status '%s'", status)
1984
1985       time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1986
1987     return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1988
1989   def BalloonInstanceMemory(self, instance, mem):
1990     """Balloon an instance memory to a certain value.
1991
1992     @type instance: L{objects.Instance}
1993     @param instance: instance to be accepted
1994     @type mem: int
1995     @param mem: actual memory size to use for instance runtime
1996
1997     """
1998     self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1999
2000   def GetNodeInfo(self, hvparams=None):
2001     """Return information about the node.
2002
2003     @type hvparams: dict of strings
2004     @param hvparams: hypervisor parameters, not used in this class
2005
2006     @return: a dict with the following keys (values in MiB):
2007           - memory_total: the total memory size on the node
2008           - memory_free: the available memory on the node for instances
2009           - memory_dom0: the memory used by the node itself, if available
2010           - hv_version: the hypervisor version in the form (major, minor,
2011                         revision)
2012
2013     """
2014     result = self.GetLinuxNodeInfo()
2015     # FIXME: this is the global kvm version, but the actual version can be
2016     # customized as an hv parameter. we should use the nodegroup's default kvm
2017     # path parameter here.
2018     _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2019     result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2020     return result
2021
2022   @classmethod
2023   def GetInstanceConsole(cls, instance, hvparams, beparams):
2024     """Return a command for connecting to the console of an instance.
2025
2026     """
2027     if hvparams[constants.HV_SERIAL_CONSOLE]:
2028       cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2029              constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2030              utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2031              "STDIO,%s" % cls._SocatUnixConsoleParams(),
2032              "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2033       return objects.InstanceConsole(instance=instance.name,
2034                                      kind=constants.CONS_SSH,
2035                                      host=instance.primary_node,
2036                                      user=constants.SSH_CONSOLE_USER,
2037                                      command=cmd)
2038
2039     vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2040     if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2041       display = instance.network_port - constants.VNC_BASE_PORT
2042       return objects.InstanceConsole(instance=instance.name,
2043                                      kind=constants.CONS_VNC,
2044                                      host=vnc_bind_address,
2045                                      port=instance.network_port,
2046                                      display=display)
2047
2048     spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2049     if spice_bind:
2050       return objects.InstanceConsole(instance=instance.name,
2051                                      kind=constants.CONS_SPICE,
2052                                      host=spice_bind,
2053                                      port=instance.network_port)
2054
2055     return objects.InstanceConsole(instance=instance.name,
2056                                    kind=constants.CONS_MESSAGE,
2057                                    message=("No serial shell for instance %s" %
2058                                             instance.name))
2059
2060   def Verify(self, hvparams=None):
2061     """Verify the hypervisor.
2062
2063     Check that the required binaries exist.
2064
2065     @type hvparams: dict of strings
2066     @param hvparams: hypervisor parameters to be verified against, not used here
2067
2068     @return: Problem description if something is wrong, C{None} otherwise
2069
2070     """
2071     msgs = []
2072     # FIXME: this is the global kvm binary, but the actual path can be
2073     # customized as an hv parameter; we should use the nodegroup's
2074     # default kvm path parameter here.
2075     if not os.path.exists(constants.KVM_PATH):
2076       msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2077     if not os.path.exists(constants.SOCAT_PATH):
2078       msgs.append("The socat binary ('%s') does not exist" %
2079                   constants.SOCAT_PATH)
2080
2081     return self._FormatVerifyResults(msgs)
2082
2083   @classmethod
2084   def CheckParameterSyntax(cls, hvparams):
2085     """Check the given parameters for validity.
2086
2087     @type hvparams:  dict
2088     @param hvparams: dictionary with parameter names/value
2089     @raise errors.HypervisorError: when a parameter is not valid
2090
2091     """
2092     super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2093
2094     kernel_path = hvparams[constants.HV_KERNEL_PATH]
2095     if kernel_path:
2096       if not hvparams[constants.HV_ROOT_PATH]:
2097         raise errors.HypervisorError("Need a root partition for the instance,"
2098                                      " if a kernel is defined")
2099
2100     if (hvparams[constants.HV_VNC_X509_VERIFY] and
2101         not hvparams[constants.HV_VNC_X509]):
2102       raise errors.HypervisorError("%s must be defined, if %s is" %
2103                                    (constants.HV_VNC_X509,
2104                                     constants.HV_VNC_X509_VERIFY))
2105
2106     if hvparams[constants.HV_SERIAL_CONSOLE]:
2107       serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2108       valid_speeds = constants.VALID_SERIAL_SPEEDS
2109       if not serial_speed or serial_speed not in valid_speeds:
2110         raise errors.HypervisorError("Invalid serial console speed, must be"
2111                                      " one of: %s" %
2112                                      utils.CommaJoin(valid_speeds))
2113
2114     boot_order = hvparams[constants.HV_BOOT_ORDER]
2115     if (boot_order == constants.HT_BO_CDROM and
2116         not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2117       raise errors.HypervisorError("Cannot boot from cdrom without an"
2118                                    " ISO path")
2119
2120     security_model = hvparams[constants.HV_SECURITY_MODEL]
2121     if security_model == constants.HT_SM_USER:
2122       if not hvparams[constants.HV_SECURITY_DOMAIN]:
2123         raise errors.HypervisorError("A security domain (user to run kvm as)"
2124                                      " must be specified")
2125     elif (security_model == constants.HT_SM_NONE or
2126           security_model == constants.HT_SM_POOL):
2127       if hvparams[constants.HV_SECURITY_DOMAIN]:
2128         raise errors.HypervisorError("Cannot have a security domain when the"
2129                                      " security model is 'none' or 'pool'")
2130
2131     spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2132     spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2133     if spice_bind:
2134       if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2135         # if an IP version is specified, the spice_bind parameter must be an
2136         # IP of that family
2137         if (netutils.IP4Address.IsValid(spice_bind) and
2138             spice_ip_version != constants.IP4_VERSION):
2139           raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2140                                        " the specified IP version is %s" %
2141                                        (spice_bind, spice_ip_version))
2142
2143         if (netutils.IP6Address.IsValid(spice_bind) and
2144             spice_ip_version != constants.IP6_VERSION):
2145           raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2146                                        " the specified IP version is %s" %
2147                                        (spice_bind, spice_ip_version))
2148     else:
2149       # All the other SPICE parameters depend on spice_bind being set. Raise an
2150       # error if any of them is set without it.
2151       for param in _SPICE_ADDITIONAL_PARAMS:
2152         if hvparams[param]:
2153           raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2154                                        (param, constants.HV_KVM_SPICE_BIND))
2155
2156   @classmethod
2157   def ValidateParameters(cls, hvparams):
2158     """Check the given parameters for validity.
2159
2160     @type hvparams:  dict
2161     @param hvparams: dictionary with parameter names/value
2162     @raise errors.HypervisorError: when a parameter is not valid
2163
2164     """
2165     super(KVMHypervisor, cls).ValidateParameters(hvparams)
2166
2167     kvm_path = hvparams[constants.HV_KVM_PATH]
2168
2169     security_model = hvparams[constants.HV_SECURITY_MODEL]
2170     if security_model == constants.HT_SM_USER:
2171       username = hvparams[constants.HV_SECURITY_DOMAIN]
2172       try:
2173         pwd.getpwnam(username)
2174       except KeyError:
2175         raise errors.HypervisorError("Unknown security domain user %s"
2176                                      % username)
2177     vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2178     if vnc_bind_address:
2179       bound_to_addr = netutils.IP4Address.IsValid(vnc_bind_address)
2180       is_interface = netutils.IsValidInterface(vnc_bind_address)
2181       is_path = utils.IsNormAbsPath(vnc_bind_address)
2182       if not bound_to_addr and not is_interface and not is_path:
2183         raise errors.HypervisorError("VNC: The %s parameter must be either"
2184                                      " a valid IP address, an interface name,"
2185                                      " or an absolute path" %
2186                                      constants.HV_KVM_SPICE_BIND)
2187
2188     spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2189     if spice_bind:
2190       # only one of VNC and SPICE can be used currently.
2191       if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2192         raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2193                                      " only one of them can be used at a"
2194                                      " given time")
2195
2196       # check that KVM supports SPICE
2197       kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2198       if not cls._SPICE_RE.search(kvmhelp):
2199         raise errors.HypervisorError("SPICE is configured, but it is not"
2200                                      " supported according to 'kvm --help'")
2201
2202       # if spice_bind is not an IP address, it must be a valid interface
2203       bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2204                        netutils.IP6Address.IsValid(spice_bind))
2205       if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2206         raise errors.HypervisorError("SPICE: The %s parameter must be either"
2207                                      " a valid IP address or interface name" %
2208                                      constants.HV_KVM_SPICE_BIND)
2209
2210     machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2211     if machine_version:
2212       output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2213       if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2214         raise errors.HypervisorError("Unsupported machine version: %s" %
2215                                      machine_version)
2216
2217   @classmethod
2218   def PowercycleNode(cls, hvparams=None):
2219     """KVM powercycle, just a wrapper over Linux powercycle.
2220
2221     @type hvparams: dict of strings
2222     @param hvparams: hypervisor params to be used on this node
2223
2224     """
2225     cls.LinuxPowercycle()