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