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