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