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