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