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