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