Merge branch 'stable-2.11' into stable-2.12
[ganeti-github.git] / lib / hypervisor / hv_kvm / __init__.py
1 #
2 #
3
4 # Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 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 shutil
35 import urllib2
36 from bitarray import bitarray
37 try:
38 import affinity # pylint: disable=F0401
39 except ImportError:
40 affinity = None
41 try:
42 import fdsend # pylint: disable=F0401
43 except ImportError:
44 fdsend = None
45
46 from ganeti import utils
47 from ganeti import constants
48 from ganeti import errors
49 from ganeti import serializer
50 from ganeti import objects
51 from ganeti import uidpool
52 from ganeti import ssconf
53 from ganeti import netutils
54 from ganeti import pathutils
55 from ganeti.hypervisor import hv_base
56 from ganeti.utils import wrapper as utils_wrapper
57
58 from ganeti.hypervisor.hv_kvm.monitor import QmpConnection, QmpMessage, \
59 MonitorSocket
60 from ganeti.hypervisor.hv_kvm.netdev import OpenTap
61
62
63 _KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-vif-bridge"
64 _KVM_START_PAUSED_FLAG = "-S"
65
66 #: SPICE parameters which depend on L{constants.HV_KVM_SPICE_BIND}
67 _SPICE_ADDITIONAL_PARAMS = frozenset([
68 constants.HV_KVM_SPICE_IP_VERSION,
69 constants.HV_KVM_SPICE_PASSWORD_FILE,
70 constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
71 constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
72 constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
73 constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
74 constants.HV_KVM_SPICE_USE_TLS,
75 ])
76
77 # Constant bitarray that reflects to a free pci slot
78 # Use it with bitarray.search()
79 _AVAILABLE_PCI_SLOT = bitarray("0")
80
81 # below constants show the format of runtime file
82 # the nics are in second possition, while the disks in 4th (last)
83 # moreover disk entries are stored as a list of in tuples
84 # (L{objects.Disk}, link_name, uri)
85 _KVM_NICS_RUNTIME_INDEX = 1
86 _KVM_DISKS_RUNTIME_INDEX = 3
87 _DEVICE_RUNTIME_INDEX = {
88 constants.HOTPLUG_TARGET_DISK: _KVM_DISKS_RUNTIME_INDEX,
89 constants.HOTPLUG_TARGET_NIC: _KVM_NICS_RUNTIME_INDEX
90 }
91 _FIND_RUNTIME_ENTRY = {
92 constants.HOTPLUG_TARGET_NIC:
93 lambda nic, kvm_nics: [n for n in kvm_nics if n.uuid == nic.uuid],
94 constants.HOTPLUG_TARGET_DISK:
95 lambda disk, kvm_disks: [(d, l, u) for (d, l, u) in kvm_disks
96 if d.uuid == disk.uuid]
97 }
98 _RUNTIME_DEVICE = {
99 constants.HOTPLUG_TARGET_NIC: lambda d: d,
100 constants.HOTPLUG_TARGET_DISK: lambda (d, e, _): d
101 }
102 _RUNTIME_ENTRY = {
103 constants.HOTPLUG_TARGET_NIC: lambda d, e: d,
104 constants.HOTPLUG_TARGET_DISK: lambda d, e: (d, e[0], e[1])
105 }
106
107 _MIGRATION_CAPS_DELIM = ":"
108
109
110 def _GetDriveURI(disk, link, uri):
111 """Helper function to get the drive uri to be used in --drive kvm option
112
113 @type disk: L{objects.Disk}
114 @param disk: A disk configuration object
115 @type link: string
116 @param link: The device link as returned by _SymlinkBlockDev()
117 @type uri: string
118 @param uri: The drive uri as returned by _CalculateDeviceURI()
119
120 """
121 access_mode = disk.params.get(constants.LDP_ACCESS,
122 constants.DISK_KERNELSPACE)
123 if (uri and access_mode == constants.DISK_USERSPACE):
124 drive_uri = uri
125 else:
126 drive_uri = link
127
128 return drive_uri
129
130
131 def _GenerateDeviceKVMId(dev_type, dev):
132 """Helper function to generate a unique device name used by KVM
133
134 QEMU monitor commands use names to identify devices. Here we use their pci
135 slot and a part of their UUID to name them. dev.pci might be None for old
136 devices in the cluster.
137
138 @type dev_type: sting
139 @param dev_type: device type of param dev
140 @type dev: L{objects.Disk} or L{objects.NIC}
141 @param dev: the device object for which we generate a kvm name
142 @raise errors.HotplugError: in case a device has no pci slot (old devices)
143
144 """
145
146 if not dev.pci:
147 raise errors.HotplugError("Hotplug is not supported for %s with UUID %s" %
148 (dev_type, dev.uuid))
149
150 return "%s-%s-pci-%d" % (dev_type.lower(), dev.uuid.split("-")[0], dev.pci)
151
152
153 def _GetFreeSlot(slots, slot=None, reserve=False):
154 """Helper method to get first available slot in a bitarray
155
156 @type slots: bitarray
157 @param slots: the bitarray to operate on
158 @type slot: integer
159 @param slot: if given we check whether the slot is free
160 @type reserve: boolean
161 @param reserve: whether to reserve the first available slot or not
162 @return: the idx of the (first) available slot
163 @raise errors.HotplugError: If all slots in a bitarray are occupied
164 or the given slot is not free.
165
166 """
167 if slot is not None:
168 assert slot < len(slots)
169 if slots[slot]:
170 raise errors.HypervisorError("Slots %d occupied" % slot)
171
172 else:
173 avail = slots.search(_AVAILABLE_PCI_SLOT, 1)
174 if not avail:
175 raise errors.HypervisorError("All slots occupied")
176
177 slot = int(avail[0])
178
179 if reserve:
180 slots[slot] = True
181
182 return slot
183
184
185 def _GetExistingDeviceInfo(dev_type, device, runtime):
186 """Helper function to get an existing device inside the runtime file
187
188 Used when an instance is running. Load kvm runtime file and search
189 for a device based on its type and uuid.
190
191 @type dev_type: sting
192 @param dev_type: device type of param dev
193 @type device: L{objects.Disk} or L{objects.NIC}
194 @param device: the device object for which we generate a kvm name
195 @type runtime: tuple (cmd, nics, hvparams, disks)
196 @param runtime: the runtime data to search for the device
197 @raise errors.HotplugError: in case the requested device does not
198 exist (e.g. device has been added without --hotplug option) or
199 device info has not pci slot (e.g. old devices in the cluster)
200
201 """
202 index = _DEVICE_RUNTIME_INDEX[dev_type]
203 found = _FIND_RUNTIME_ENTRY[dev_type](device, runtime[index])
204 if not found:
205 raise errors.HotplugError("Cannot find runtime info for %s with UUID %s" %
206 (dev_type, device.uuid))
207
208 return found[0]
209
210
211 def _UpgradeSerializedRuntime(serialized_runtime):
212 """Upgrade runtime data
213
214 Remove any deprecated fields or change the format of the data.
215 The runtime files are not upgraded when Ganeti is upgraded, so the required
216 modification have to be performed here.
217
218 @type serialized_runtime: string
219 @param serialized_runtime: raw text data read from actual runtime file
220 @return: (cmd, nic dicts, hvparams, bdev dicts)
221 @rtype: tuple
222
223 """
224 loaded_runtime = serializer.Load(serialized_runtime)
225 kvm_cmd, serialized_nics, hvparams = loaded_runtime[:3]
226 if len(loaded_runtime) >= 4:
227 serialized_disks = loaded_runtime[3]
228 else:
229 serialized_disks = []
230
231 for nic in serialized_nics:
232 # Add a dummy uuid slot if an pre-2.8 NIC is found
233 if "uuid" not in nic:
234 nic["uuid"] = utils.NewUUID()
235
236 return kvm_cmd, serialized_nics, hvparams, serialized_disks
237
238
239 def _AnalyzeSerializedRuntime(serialized_runtime):
240 """Return runtime entries for a serialized runtime file
241
242 @type serialized_runtime: string
243 @param serialized_runtime: raw text data read from actual runtime file
244 @return: (cmd, nics, hvparams, bdevs)
245 @rtype: tuple
246
247 """
248 kvm_cmd, serialized_nics, hvparams, serialized_disks = \
249 _UpgradeSerializedRuntime(serialized_runtime)
250 kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
251 kvm_disks = [(objects.Disk.FromDict(sdisk), link, uri)
252 for sdisk, link, uri in serialized_disks]
253
254 return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
255
256
257 class HeadRequest(urllib2.Request):
258 def get_method(self):
259 return "HEAD"
260
261
262 def _CheckUrl(url):
263 """Check if a given URL exists on the server
264
265 """
266 try:
267 urllib2.urlopen(HeadRequest(url))
268 return True
269 except urllib2.URLError:
270 return False
271
272
273 class KVMHypervisor(hv_base.BaseHypervisor):
274 """KVM hypervisor interface
275
276 """
277 CAN_MIGRATE = True
278
279 _ROOT_DIR = pathutils.RUN_DIR + "/kvm-hypervisor"
280 _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
281 _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
282 _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
283 _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
284 _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
285 _KEYMAP_DIR = _ROOT_DIR + "/keymap" # contains instances keymaps
286 # KVM instances with chroot enabled are started in empty chroot directories.
287 _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
288 # After an instance is stopped, its chroot directory is removed.
289 # If the chroot directory is not empty, it can't be removed.
290 # A non-empty chroot directory indicates a possible security incident.
291 # To support forensics, the non-empty chroot directory is quarantined in
292 # a separate directory, called 'chroot-quarantine'.
293 _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
294 _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
295 _CHROOT_DIR, _CHROOT_QUARANTINE_DIR, _KEYMAP_DIR]
296
297 PARAMETERS = {
298 constants.HV_KVM_PATH: hv_base.REQ_FILE_CHECK,
299 constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
300 constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
301 constants.HV_ROOT_PATH: hv_base.NO_CHECK,
302 constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
303 constants.HV_ACPI: hv_base.NO_CHECK,
304 constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
305 constants.HV_SERIAL_SPEED: hv_base.NO_CHECK,
306 constants.HV_VNC_BIND_ADDRESS: hv_base.NO_CHECK, # will be checked later
307 constants.HV_VNC_TLS: hv_base.NO_CHECK,
308 constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
309 constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
310 constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
311 constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
312 constants.HV_KVM_SPICE_IP_VERSION:
313 (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
314 x in constants.VALID_IP_VERSIONS),
315 "The SPICE IP version should be 4 or 6",
316 None, None),
317 constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
318 constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
319 hv_base.ParamInSet(
320 False, constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
321 constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
322 hv_base.ParamInSet(
323 False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
324 constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
325 hv_base.ParamInSet(
326 False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
327 constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
328 hv_base.ParamInSet(
329 False, constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
330 constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
331 constants.HV_KVM_SPICE_USE_TLS: hv_base.NO_CHECK,
332 constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
333 constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
334 constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
335 constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_OR_URL_CHECK,
336 constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_OR_URL_CHECK,
337 constants.HV_BOOT_ORDER:
338 hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
339 constants.HV_NIC_TYPE:
340 hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
341 constants.HV_DISK_TYPE:
342 hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
343 constants.HV_KVM_CDROM_DISK_TYPE:
344 hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
345 constants.HV_USB_MOUSE:
346 hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
347 constants.HV_KEYMAP: hv_base.NO_CHECK,
348 constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
349 constants.HV_MIGRATION_BANDWIDTH: hv_base.REQ_NONNEGATIVE_INT_CHECK,
350 constants.HV_MIGRATION_DOWNTIME: hv_base.REQ_NONNEGATIVE_INT_CHECK,
351 constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
352 constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
353 constants.HV_DISK_CACHE:
354 hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
355 constants.HV_KVM_DISK_AIO:
356 hv_base.ParamInSet(False, constants.HT_KVM_VALID_AIO_TYPES),
357 constants.HV_SECURITY_MODEL:
358 hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
359 constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
360 constants.HV_KVM_FLAG:
361 hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
362 constants.HV_VHOST_NET: hv_base.NO_CHECK,
363 constants.HV_VIRTIO_NET_QUEUES: hv_base.OPT_VIRTIO_NET_QUEUES_CHECK,
364 constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
365 constants.HV_KVM_USER_SHUTDOWN: hv_base.NO_CHECK,
366 constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
367 constants.HV_REBOOT_BEHAVIOR:
368 hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
369 constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
370 constants.HV_CPU_TYPE: hv_base.NO_CHECK,
371 constants.HV_CPU_CORES: hv_base.OPT_NONNEGATIVE_INT_CHECK,
372 constants.HV_CPU_THREADS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
373 constants.HV_CPU_SOCKETS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
374 constants.HV_SOUNDHW: hv_base.NO_CHECK,
375 constants.HV_USB_DEVICES: hv_base.NO_CHECK,
376 constants.HV_VGA: hv_base.NO_CHECK,
377 constants.HV_KVM_EXTRA: hv_base.NO_CHECK,
378 constants.HV_KVM_MACHINE_VERSION: hv_base.NO_CHECK,
379 constants.HV_KVM_MIGRATION_CAPS: hv_base.NO_CHECK,
380 constants.HV_VNET_HDR: hv_base.NO_CHECK,
381 }
382
383 _VIRTIO = "virtio"
384 _VIRTIO_NET_PCI = "virtio-net-pci"
385 _VIRTIO_BLK_PCI = "virtio-blk-pci"
386
387 _MIGRATION_STATUS_RE = re.compile(r"Migration\s+status:\s+(\w+)",
388 re.M | re.I)
389 _MIGRATION_PROGRESS_RE = \
390 re.compile(r"\s*transferred\s+ram:\s+(?P<transferred>\d+)\s+kbytes\s*\n"
391 r"\s*remaining\s+ram:\s+(?P<remaining>\d+)\s+kbytes\s*\n"
392 r"\s*total\s+ram:\s+(?P<total>\d+)\s+kbytes\s*\n", re.I)
393
394 _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
395 _MIGRATION_INFO_RETRY_DELAY = 2
396
397 _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
398
399 _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
400 _CPU_INFO_CMD = "info cpus"
401 _CONT_CMD = "cont"
402
403 _DEFAULT_MACHINE_VERSION_RE = re.compile(r"^(\S+).*\(default\)", re.M)
404 _CHECK_MACHINE_VERSION_RE = \
405 staticmethod(lambda x: re.compile(r"^(%s)[ ]+.*PC" % x, re.M))
406
407 _QMP_RE = re.compile(r"^-qmp\s", re.M)
408 _SPICE_RE = re.compile(r"^-spice\s", re.M)
409 _VHOST_RE = re.compile(r"^-net\s.*,vhost=on|off", re.M)
410 _VIRTIO_NET_QUEUES_RE = re.compile(r"^-net\s.*,fds=x:y:...:z", re.M)
411 _ENABLE_KVM_RE = re.compile(r"^-enable-kvm\s", re.M)
412 _DISABLE_KVM_RE = re.compile(r"^-disable-kvm\s", re.M)
413 _NETDEV_RE = re.compile(r"^-netdev\s", re.M)
414 _DISPLAY_RE = re.compile(r"^-display\s", re.M)
415 _MACHINE_RE = re.compile(r"^-machine\s", re.M)
416 _VIRTIO_NET_RE = re.compile(r"^name \"%s\"" % _VIRTIO_NET_PCI, re.M)
417 _VIRTIO_BLK_RE = re.compile(r"^name \"%s\"" % _VIRTIO_BLK_PCI, re.M)
418 # match -drive.*boot=on|off on different lines, but in between accept only
419 # dashes not preceeded by a new line (which would mean another option
420 # different than -drive is starting)
421 _BOOT_RE = re.compile(r"^-drive\s([^-]|(?<!^)-)*,boot=on\|off", re.M | re.S)
422 _UUID_RE = re.compile(r"^-uuid\s", re.M)
423
424 _INFO_PCI_RE = re.compile(r'Bus.*device[ ]*(\d+).*')
425 _INFO_PCI_CMD = "info pci"
426 _FIND_PCI_DEVICE_RE = \
427 staticmethod(
428 lambda pci, devid: re.compile(r'Bus.*device[ ]*%d,(.*\n){5,6}.*id "%s"' %
429 (pci, devid), re.M))
430
431 _INFO_VERSION_RE = \
432 re.compile(r'^QEMU (\d+)\.(\d+)(\.(\d+))?.*monitor.*', re.M)
433 _INFO_VERSION_CMD = "info version"
434
435 # Slot 0 for Host bridge, Slot 1 for ISA bridge, Slot 2 for VGA controller
436 _DEFAULT_PCI_RESERVATIONS = "11100000000000000000000000000000"
437 _SOUNDHW_WITH_PCI_SLOT = ["ac97", "es1370", "hda"]
438
439 ANCILLARY_FILES = [
440 _KVM_NETWORK_SCRIPT,
441 ]
442 ANCILLARY_FILES_OPT = [
443 _KVM_NETWORK_SCRIPT,
444 ]
445
446 # Supported kvm options to get output from
447 _KVMOPT_HELP = "help"
448 _KVMOPT_MLIST = "mlist"
449 _KVMOPT_DEVICELIST = "devicelist"
450
451 # Command to execute to get the output from kvm, and whether to
452 # accept the output even on failure.
453 _KVMOPTS_CMDS = {
454 _KVMOPT_HELP: (["--help"], False),
455 _KVMOPT_MLIST: (["-M", "?"], False),
456 _KVMOPT_DEVICELIST: (["-device", "?"], True),
457 }
458
459 def __init__(self):
460 hv_base.BaseHypervisor.__init__(self)
461 # Let's make sure the directories we need exist, even if the RUN_DIR lives
462 # in a tmpfs filesystem or has been otherwise wiped out.
463 dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
464 utils.EnsureDirs(dirs)
465
466 @classmethod
467 def _InstancePidFile(cls, instance_name):
468 """Returns the instance pidfile.
469
470 """
471 return utils.PathJoin(cls._PIDS_DIR, instance_name)
472
473 @classmethod
474 def _InstanceUidFile(cls, instance_name):
475 """Returns the instance uidfile.
476
477 """
478 return utils.PathJoin(cls._UIDS_DIR, instance_name)
479
480 @classmethod
481 def _InstancePidInfo(cls, pid):
482 """Check pid file for instance information.
483
484 Check that a pid file is associated with an instance, and retrieve
485 information from its command line.
486
487 @type pid: string or int
488 @param pid: process id of the instance to check
489 @rtype: tuple
490 @return: (instance_name, memory, vcpus)
491 @raise errors.HypervisorError: when an instance cannot be found
492
493 """
494 alive = utils.IsProcessAlive(pid)
495 if not alive:
496 raise errors.HypervisorError("Cannot get info for pid %s" % pid)
497
498 cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
499 try:
500 cmdline = utils.ReadFile(cmdline_file)
501 except EnvironmentError, err:
502 raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
503 (pid, err))
504
505 instance = None
506 memory = 0
507 vcpus = 0
508
509 arg_list = cmdline.split("\x00")
510 while arg_list:
511 arg = arg_list.pop(0)
512 if arg == "-name":
513 instance = arg_list.pop(0)
514 elif arg == "-m":
515 memory = int(arg_list.pop(0))
516 elif arg == "-smp":
517 vcpus = int(arg_list.pop(0).split(",")[0])
518
519 if instance is None:
520 raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
521 " instance" % pid)
522
523 return (instance, memory, vcpus)
524
525 @classmethod
526 def _InstancePidAlive(cls, instance_name):
527 """Returns the instance pidfile, pid, and liveness.
528
529 @type instance_name: string
530 @param instance_name: instance name
531 @rtype: tuple
532 @return: (pid file name, pid, liveness)
533
534 """
535 pidfile = cls._InstancePidFile(instance_name)
536 pid = utils.ReadPidFile(pidfile)
537
538 alive = False
539 try:
540 cmd_instance = cls._InstancePidInfo(pid)[0]
541 alive = (cmd_instance == instance_name)
542 except errors.HypervisorError:
543 pass
544
545 return (pidfile, pid, alive)
546
547 @classmethod
548 def _CheckDown(cls, instance_name):
549 """Raises an error unless the given instance is down.
550
551 """
552 alive = cls._InstancePidAlive(instance_name)[2]
553 if alive:
554 raise errors.HypervisorError("Failed to start instance %s: %s" %
555 (instance_name, "already running"))
556
557 @classmethod
558 def _InstanceMonitor(cls, instance_name):
559 """Returns the instance monitor socket name
560
561 """
562 return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
563
564 @classmethod
565 def _InstanceSerial(cls, instance_name):
566 """Returns the instance serial socket name
567
568 """
569 return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
570
571 @classmethod
572 def _InstanceQmpMonitor(cls, instance_name):
573 """Returns the instance serial QMP socket name
574
575 """
576 return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
577
578 @classmethod
579 def _InstanceKvmdMonitor(cls, instance_name):
580 """Returns the instance kvm daemon socket name
581
582 """
583 return utils.PathJoin(cls._CTRL_DIR, "%s.kvmd" % instance_name)
584
585 @classmethod
586 def _InstanceShutdownMonitor(cls, instance_name):
587 """Returns the instance QMP output filename
588
589 """
590 return utils.PathJoin(cls._CTRL_DIR, "%s.shutdown" % instance_name)
591
592 @staticmethod
593 def _SocatUnixConsoleParams():
594 """Returns the correct parameters for socat
595
596 If we have a new-enough socat we can use raw mode with an escape character.
597
598 """
599 if constants.SOCAT_USE_ESCAPE:
600 return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
601 else:
602 return "echo=0,icanon=0"
603
604 @classmethod
605 def _InstanceKVMRuntime(cls, instance_name):
606 """Returns the instance KVM runtime filename
607
608 """
609 return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
610
611 @classmethod
612 def _InstanceChrootDir(cls, instance_name):
613 """Returns the name of the KVM chroot dir of the instance
614
615 """
616 return utils.PathJoin(cls._CHROOT_DIR, instance_name)
617
618 @classmethod
619 def _InstanceNICDir(cls, instance_name):
620 """Returns the name of the directory holding the tap device files for a
621 given instance.
622
623 """
624 return utils.PathJoin(cls._NICS_DIR, instance_name)
625
626 @classmethod
627 def _InstanceNICFile(cls, instance_name, seq):
628 """Returns the name of the file containing the tap device for a given NIC
629
630 """
631 return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
632
633 @classmethod
634 def _InstanceKeymapFile(cls, instance_name):
635 """Returns the name of the file containing the keymap for a given instance
636
637 """
638 return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
639
640 @classmethod
641 def _TryReadUidFile(cls, uid_file):
642 """Try to read a uid file
643
644 """
645 if os.path.exists(uid_file):
646 try:
647 uid = int(utils.ReadOneLineFile(uid_file))
648 return uid
649 except EnvironmentError:
650 logging.warning("Can't read uid file", exc_info=True)
651 except (TypeError, ValueError):
652 logging.warning("Can't parse uid file contents", exc_info=True)
653 return None
654
655 @classmethod
656 def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
657 """Removes an instance's rutime sockets/files/dirs.
658
659 """
660 utils.RemoveFile(pidfile)
661 utils.RemoveFile(cls._InstanceMonitor(instance_name))
662 utils.RemoveFile(cls._InstanceSerial(instance_name))
663 utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
664 utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
665 utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
666 uid_file = cls._InstanceUidFile(instance_name)
667 uid = cls._TryReadUidFile(uid_file)
668 utils.RemoveFile(uid_file)
669 if uid is not None:
670 uidpool.ReleaseUid(uid)
671 try:
672 shutil.rmtree(cls._InstanceNICDir(instance_name))
673 except OSError, err:
674 if err.errno != errno.ENOENT:
675 raise
676 try:
677 chroot_dir = cls._InstanceChrootDir(instance_name)
678 utils.RemoveDir(chroot_dir)
679 except OSError, err:
680 if err.errno == errno.ENOTEMPTY:
681 # The chroot directory is expected to be empty, but it isn't.
682 new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
683 prefix="%s-%s-" %
684 (instance_name,
685 utils.TimestampForFilename()))
686 logging.warning("The chroot directory of instance %s can not be"
687 " removed as it is not empty. Moving it to the"
688 " quarantine instead. Please investigate the"
689 " contents (%s) and clean up manually",
690 instance_name, new_chroot_dir)
691 utils.RenameFile(chroot_dir, new_chroot_dir)
692 else:
693 raise
694
695 @staticmethod
696 def _ConfigureNIC(instance, seq, nic, tap):
697 """Run the network configuration script for a specified NIC
698
699 See L{hv_base.ConfigureNIC}.
700
701 @param instance: instance we're acting on
702 @type instance: instance object
703 @param seq: nic sequence number
704 @type seq: int
705 @param nic: nic we're acting on
706 @type nic: nic object
707 @param tap: the host's tap interface this NIC corresponds to
708 @type tap: str
709
710 """
711 hv_base.ConfigureNIC([pathutils.KVM_IFUP, tap], instance, seq, nic, tap)
712
713 @staticmethod
714 def _VerifyAffinityPackage():
715 if affinity is None:
716 raise errors.HypervisorError("affinity Python package not"
717 " found; cannot use CPU pinning under KVM")
718
719 @staticmethod
720 def _BuildAffinityCpuMask(cpu_list):
721 """Create a CPU mask suitable for sched_setaffinity from a list of
722 CPUs.
723
724 See man taskset for more info on sched_setaffinity masks.
725 For example: [ 0, 2, 5, 6 ] will return 101 (0x65, 0..01100101).
726
727 @type cpu_list: list of int
728 @param cpu_list: list of physical CPU numbers to map to vCPUs in order
729 @rtype: int
730 @return: a bit mask of CPU affinities
731
732 """
733 if cpu_list == constants.CPU_PINNING_OFF:
734 return constants.CPU_PINNING_ALL_KVM
735 else:
736 return sum(2 ** cpu for cpu in cpu_list)
737
738 @classmethod
739 def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
740 """Change CPU affinity for running VM according to given CPU mask.
741
742 @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
743 @type cpu_mask: string
744 @param process_id: process ID of KVM process. Used to pin entire VM
745 to physical CPUs.
746 @type process_id: int
747 @param thread_dict: map of virtual CPUs to KVM thread IDs
748 @type thread_dict: dict int:int
749
750 """
751 # Convert the string CPU mask to a list of list of int's
752 cpu_list = utils.ParseMultiCpuMask(cpu_mask)
753
754 if len(cpu_list) == 1:
755 all_cpu_mapping = cpu_list[0]
756 if all_cpu_mapping == constants.CPU_PINNING_OFF:
757 # If CPU pinning has 1 entry that's "all", then do nothing
758 pass
759 else:
760 # If CPU pinning has one non-all entry, map the entire VM to
761 # one set of physical CPUs
762 cls._VerifyAffinityPackage()
763 affinity.set_process_affinity_mask(
764 process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
765 else:
766 # The number of vCPUs mapped should match the number of vCPUs
767 # reported by KVM. This was already verified earlier, so
768 # here only as a sanity check.
769 assert len(thread_dict) == len(cpu_list)
770 cls._VerifyAffinityPackage()
771
772 # For each vCPU, map it to the proper list of physical CPUs
773 for vcpu, i in zip(cpu_list, range(len(cpu_list))):
774 affinity.set_process_affinity_mask(thread_dict[i],
775 cls._BuildAffinityCpuMask(vcpu))
776
777 def _GetVcpuThreadIds(self, instance_name):
778 """Get a mapping of vCPU no. to thread IDs for the instance
779
780 @type instance_name: string
781 @param instance_name: instance in question
782 @rtype: dictionary of int:int
783 @return: a dictionary mapping vCPU numbers to thread IDs
784
785 """
786 result = {}
787 output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
788 for line in output.stdout.splitlines():
789 match = self._CPU_INFO_RE.search(line)
790 if not match:
791 continue
792 grp = map(int, match.groups())
793 result[grp[0]] = grp[1]
794
795 return result
796
797 def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
798 """Complete CPU pinning.
799
800 @type instance_name: string
801 @param instance_name: name of instance
802 @type cpu_mask: string
803 @param cpu_mask: CPU pinning mask as entered by user
804
805 """
806 # Get KVM process ID, to be used if need to pin entire VM
807 _, pid, _ = self._InstancePidAlive(instance_name)
808 # Get vCPU thread IDs, to be used if need to pin vCPUs separately
809 thread_dict = self._GetVcpuThreadIds(instance_name)
810 # Run CPU pinning, based on configured mask
811 self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
812
813 def ListInstances(self, hvparams=None):
814 """Get the list of running instances.
815
816 We can do this by listing our live instances directory and
817 checking whether the associated kvm process is still alive.
818
819 """
820 result = []
821 for name in os.listdir(self._PIDS_DIR):
822 if self._InstancePidAlive(name)[2]:
823 result.append(name)
824 return result
825
826 @classmethod
827 def _IsUserShutdown(cls, instance_name):
828 return os.path.exists(cls._InstanceShutdownMonitor(instance_name))
829
830 @classmethod
831 def _ClearUserShutdown(cls, instance_name):
832 utils.RemoveFile(cls._InstanceShutdownMonitor(instance_name))
833
834 def GetInstanceInfo(self, instance_name, hvparams=None):
835 """Get instance properties.
836
837 @type instance_name: string
838 @param instance_name: the instance name
839 @type hvparams: dict of strings
840 @param hvparams: hypervisor parameters to be used with this instance
841 @rtype: tuple of strings
842 @return: (name, id, memory, vcpus, stat, times)
843
844 """
845 _, pid, alive = self._InstancePidAlive(instance_name)
846 if not alive:
847 if self._IsUserShutdown(instance_name):
848 return (instance_name, -1, 0, 0, hv_base.HvInstanceState.SHUTDOWN, 0)
849 else:
850 return None
851
852 _, memory, vcpus = self._InstancePidInfo(pid)
853 istat = hv_base.HvInstanceState.RUNNING
854 times = 0
855
856 try:
857 qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
858 qmp.connect()
859 vcpus = len(qmp.Execute("query-cpus"))
860 # Will fail if ballooning is not enabled, but we can then just resort to
861 # the value above.
862 mem_bytes = qmp.Execute("query-balloon")[qmp.ACTUAL_KEY]
863 memory = mem_bytes / 1048576
864 except errors.HypervisorError:
865 pass
866
867 return (instance_name, pid, memory, vcpus, istat, times)
868
869 def GetAllInstancesInfo(self, hvparams=None):
870 """Get properties of all instances.
871
872 @type hvparams: dict of strings
873 @param hvparams: hypervisor parameters
874 @return: list of tuples (name, id, memory, vcpus, stat, times)
875
876 """
877 data = []
878 for name in os.listdir(self._PIDS_DIR):
879 try:
880 info = self.GetInstanceInfo(name)
881 except errors.HypervisorError:
882 # Ignore exceptions due to instances being shut down
883 continue
884 if info:
885 data.append(info)
886 return data
887
888 def _GenerateKVMBlockDevicesOptions(self, instance, up_hvp, kvm_disks,
889 kvmhelp, devlist):
890 """Generate KVM options regarding instance's block devices.
891
892 @type instance: L{objects.Instance}
893 @param instance: the instance object
894 @type up_hvp: dict
895 @param up_hvp: the instance's runtime hypervisor parameters
896 @type kvm_disks: list of tuples
897 @param kvm_disks: list of tuples [(disk, link_name, uri)..]
898 @type kvmhelp: string
899 @param kvmhelp: output of kvm --help
900 @type devlist: string
901 @param devlist: output of kvm -device ?
902 @rtype: list
903 @return: list of command line options eventually used by kvm executable
904
905 """
906 kernel_path = up_hvp[constants.HV_KERNEL_PATH]
907 if kernel_path:
908 boot_disk = False
909 else:
910 boot_disk = up_hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
911
912 # whether this is an older KVM version that uses the boot=on flag
913 # on devices
914 needs_boot_flag = self._BOOT_RE.search(kvmhelp)
915
916 dev_opts = []
917 device_driver = None
918 disk_type = up_hvp[constants.HV_DISK_TYPE]
919 if disk_type == constants.HT_DISK_PARAVIRTUAL:
920 if_val = ",if=%s" % self._VIRTIO
921 try:
922 if self._VIRTIO_BLK_RE.search(devlist):
923 if_val = ",if=none"
924 # will be passed in -device option as driver
925 device_driver = self._VIRTIO_BLK_PCI
926 except errors.HypervisorError, _:
927 pass
928 else:
929 if_val = ",if=%s" % disk_type
930 # AIO mode
931 aio_mode = up_hvp[constants.HV_KVM_DISK_AIO]
932 if aio_mode == constants.HT_KVM_AIO_NATIVE:
933 aio_val = ",aio=%s" % aio_mode
934 else:
935 aio_val = ""
936 # Cache mode
937 disk_cache = up_hvp[constants.HV_DISK_CACHE]
938 if instance.disk_template in constants.DTS_EXT_MIRROR:
939 if disk_cache != "none":
940 # TODO: make this a hard error, instead of a silent overwrite
941 logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
942 " to prevent shared storage corruption on migration",
943 disk_cache)
944 cache_val = ",cache=none"
945 elif disk_cache != constants.HT_CACHE_DEFAULT:
946 cache_val = ",cache=%s" % disk_cache
947 else:
948 cache_val = ""
949 for cfdev, link_name, uri in kvm_disks:
950 if cfdev.mode != constants.DISK_RDWR:
951 raise errors.HypervisorError("Instance has read-only disks which"
952 " are not supported by KVM")
953 # TODO: handle FD_LOOP and FD_BLKTAP (?)
954 boot_val = ""
955 if boot_disk:
956 dev_opts.extend(["-boot", "c"])
957 boot_disk = False
958 if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
959 boot_val = ",boot=on"
960
961 drive_uri = _GetDriveURI(cfdev, link_name, uri)
962
963 drive_val = "file=%s,format=raw%s%s%s%s" % \
964 (drive_uri, if_val, boot_val, cache_val, aio_val)
965
966 if device_driver:
967 # kvm_disks are the 4th entry of runtime file that did not exist in
968 # the past. That means that cfdev should always have pci slot and
969 # _GenerateDeviceKVMId() will not raise a exception.
970 kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK, cfdev)
971 drive_val += (",id=%s" % kvm_devid)
972 drive_val += (",bus=0,unit=%d" % cfdev.pci)
973 dev_val = ("%s,drive=%s,id=%s" %
974 (device_driver, kvm_devid, kvm_devid))
975 dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
976 dev_opts.extend(["-device", dev_val])
977
978 dev_opts.extend(["-drive", drive_val])
979
980 return dev_opts
981
982 @staticmethod
983 def _CdromOption(kvm_cmd, cdrom_disk_type, cdrom_image, cdrom_boot,
984 needs_boot_flag):
985 """Extends L{kvm_cmd} with the '-drive' option for a cdrom, and
986 optionally the '-boot' option.
987
988 Example: -drive file=cdrom.iso,media=cdrom,format=raw,if=ide -boot d
989
990 Example: -drive file=cdrom.iso,media=cdrom,format=raw,if=ide,boot=on
991
992 Example: -drive file=http://hostname.com/cdrom.iso,media=cdrom
993
994 @type kvm_cmd: string
995 @param kvm_cmd: KVM command line
996
997 @type cdrom_disk_type:
998 @param cdrom_disk_type:
999
1000 @type cdrom_image:
1001 @param cdrom_image:
1002
1003 @type cdrom_boot:
1004 @param cdrom_boot:
1005
1006 @type needs_boot_flag:
1007 @param needs_boot_flag:
1008
1009 """
1010 # Check that the ISO image is accessible
1011 # See https://bugs.launchpad.net/qemu/+bug/597575
1012 if utils.IsUrl(cdrom_image) and not _CheckUrl(cdrom_image):
1013 raise errors.HypervisorError("Cdrom ISO image '%s' is not accessible" %
1014 cdrom_image)
1015
1016 # set cdrom 'media' and 'format', if needed
1017 if utils.IsUrl(cdrom_image):
1018 options = ",media=cdrom"
1019 else:
1020 options = ",media=cdrom,format=raw"
1021
1022 # set cdrom 'if' type
1023 if cdrom_boot:
1024 if_val = ",if=" + constants.HT_DISK_IDE
1025 elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1026 if_val = ",if=virtio"
1027 else:
1028 if_val = ",if=" + cdrom_disk_type
1029
1030 # set boot flag, if needed
1031 boot_val = ""
1032 if cdrom_boot:
1033 kvm_cmd.extend(["-boot", "d"])
1034
1035 # whether this is an older KVM version that requires the 'boot=on' flag
1036 # on devices
1037 if needs_boot_flag:
1038 boot_val = ",boot=on"
1039
1040 # build '-drive' option
1041 drive_val = "file=%s%s%s%s" % (cdrom_image, options, if_val, boot_val)
1042 kvm_cmd.extend(["-drive", drive_val])
1043
1044 def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1045 kvmhelp):
1046 """Generate KVM information to start an instance.
1047
1048 @type kvmhelp: string
1049 @param kvmhelp: output of kvm --help
1050 @attention: this function must not have any side-effects; for
1051 example, it must not write to the filesystem, or read values
1052 from the current system the are expected to differ between
1053 nodes, since it is only run once at instance startup;
1054 actions/kvm arguments that can vary between systems should be
1055 done in L{_ExecuteKVMRuntime}
1056
1057 """
1058 # pylint: disable=R0912,R0914,R0915
1059 hvp = instance.hvparams
1060 self.ValidateParameters(hvp)
1061
1062 pidfile = self._InstancePidFile(instance.name)
1063 kvm = hvp[constants.HV_KVM_PATH]
1064 kvm_cmd = [kvm]
1065 # used just by the vnc server, if enabled
1066 kvm_cmd.extend(["-name", instance.name])
1067 kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1068
1069 smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1070 if hvp[constants.HV_CPU_CORES]:
1071 smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1072 if hvp[constants.HV_CPU_THREADS]:
1073 smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1074 if hvp[constants.HV_CPU_SOCKETS]:
1075 smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1076
1077 kvm_cmd.extend(["-smp", ",".join(smp_list)])
1078
1079 kvm_cmd.extend(["-pidfile", pidfile])
1080
1081 pci_reservations = bitarray(self._DEFAULT_PCI_RESERVATIONS)
1082
1083 # As requested by music lovers
1084 if hvp[constants.HV_SOUNDHW]:
1085 soundhw = hvp[constants.HV_SOUNDHW]
1086 # For some reason only few sound devices require a PCI slot
1087 # while the Audio controller *must* be in slot 3.
1088 # That's why we bridge this option early in command line
1089 if soundhw in self._SOUNDHW_WITH_PCI_SLOT:
1090 _ = _GetFreeSlot(pci_reservations, reserve=True)
1091 kvm_cmd.extend(["-soundhw", soundhw])
1092
1093 if hvp[constants.HV_DISK_TYPE] == constants.HT_DISK_SCSI:
1094 # The SCSI controller requires another PCI slot.
1095 _ = _GetFreeSlot(pci_reservations, reserve=True)
1096
1097 # Add id to ballon and place to the first available slot (3 or 4)
1098 addr = _GetFreeSlot(pci_reservations, reserve=True)
1099 pci_info = ",bus=pci.0,addr=%s" % hex(addr)
1100 kvm_cmd.extend(["-balloon", "virtio,id=balloon%s" % pci_info])
1101 kvm_cmd.extend(["-daemonize"])
1102 if not instance.hvparams[constants.HV_ACPI]:
1103 kvm_cmd.extend(["-no-acpi"])
1104 if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1105 constants.INSTANCE_REBOOT_EXIT:
1106 kvm_cmd.extend(["-no-reboot"])
1107
1108 mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1109 if not mversion:
1110 mversion = self._GetDefaultMachineVersion(kvm)
1111 if self._MACHINE_RE.search(kvmhelp):
1112 # TODO (2.8): kernel_irqchip and kvm_shadow_mem machine properties, as
1113 # extra hypervisor parameters. We should also investigate whether and how
1114 # shadow_mem should be considered for the resource model.
1115 if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED):
1116 specprop = ",accel=kvm"
1117 else:
1118 specprop = ""
1119 machinespec = "%s%s" % (mversion, specprop)
1120 kvm_cmd.extend(["-machine", machinespec])
1121 else:
1122 kvm_cmd.extend(["-M", mversion])
1123 if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1124 self._ENABLE_KVM_RE.search(kvmhelp)):
1125 kvm_cmd.extend(["-enable-kvm"])
1126 elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1127 self._DISABLE_KVM_RE.search(kvmhelp)):
1128 kvm_cmd.extend(["-disable-kvm"])
1129
1130 kernel_path = hvp[constants.HV_KERNEL_PATH]
1131 if kernel_path:
1132 boot_cdrom = boot_floppy = boot_network = False
1133 else:
1134 boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1135 boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1136 boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1137
1138 if startup_paused:
1139 kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1140
1141 if boot_network:
1142 kvm_cmd.extend(["-boot", "n"])
1143
1144 disk_type = hvp[constants.HV_DISK_TYPE]
1145
1146 # Now we can specify a different device type for CDROM devices.
1147 cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1148 if not cdrom_disk_type:
1149 cdrom_disk_type = disk_type
1150
1151 cdrom_image1 = hvp[constants.HV_CDROM_IMAGE_PATH]
1152 if cdrom_image1:
1153 needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1154 self._CdromOption(kvm_cmd, cdrom_disk_type, cdrom_image1, boot_cdrom,
1155 needs_boot_flag)
1156
1157 cdrom_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1158 if cdrom_image2:
1159 self._CdromOption(kvm_cmd, cdrom_disk_type, cdrom_image2, False, False)
1160
1161 floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1162 if floppy_image:
1163 options = ",format=raw,media=disk"
1164 if boot_floppy:
1165 kvm_cmd.extend(["-boot", "a"])
1166 options = "%s,boot=on" % options
1167 if_val = ",if=floppy"
1168 options = "%s%s" % (options, if_val)
1169 drive_val = "file=%s%s" % (floppy_image, options)
1170 kvm_cmd.extend(["-drive", drive_val])
1171
1172 if kernel_path:
1173 kvm_cmd.extend(["-kernel", kernel_path])
1174 initrd_path = hvp[constants.HV_INITRD_PATH]
1175 if initrd_path:
1176 kvm_cmd.extend(["-initrd", initrd_path])
1177 root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1178 hvp[constants.HV_KERNEL_ARGS]]
1179 if hvp[constants.HV_SERIAL_CONSOLE]:
1180 serial_speed = hvp[constants.HV_SERIAL_SPEED]
1181 root_append.append("console=ttyS0,%s" % serial_speed)
1182 kvm_cmd.extend(["-append", " ".join(root_append)])
1183
1184 mem_path = hvp[constants.HV_MEM_PATH]
1185 if mem_path:
1186 kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1187
1188 monitor_dev = ("unix:%s,server,nowait" %
1189 self._InstanceMonitor(instance.name))
1190 kvm_cmd.extend(["-monitor", monitor_dev])
1191 if hvp[constants.HV_SERIAL_CONSOLE]:
1192 serial_dev = ("unix:%s,server,nowait" %
1193 self._InstanceSerial(instance.name))
1194 kvm_cmd.extend(["-serial", serial_dev])
1195 else:
1196 kvm_cmd.extend(["-serial", "none"])
1197
1198 mouse_type = hvp[constants.HV_USB_MOUSE]
1199 vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1200 spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1201 spice_ip_version = None
1202
1203 kvm_cmd.extend(["-usb"])
1204
1205 if mouse_type:
1206 kvm_cmd.extend(["-usbdevice", mouse_type])
1207 elif vnc_bind_address:
1208 kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1209
1210 if vnc_bind_address:
1211 if netutils.IsValidInterface(vnc_bind_address):
1212 if_addresses = netutils.GetInterfaceIpAddresses(vnc_bind_address)
1213 if_ip4_addresses = if_addresses[constants.IP4_VERSION]
1214 if len(if_ip4_addresses) < 1:
1215 logging.error("Could not determine IPv4 address of interface %s",
1216 vnc_bind_address)
1217 else:
1218 vnc_bind_address = if_ip4_addresses[0]
1219 if netutils.IP4Address.IsValid(vnc_bind_address):
1220 if instance.network_port > constants.VNC_BASE_PORT:
1221 display = instance.network_port - constants.VNC_BASE_PORT
1222 if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1223 vnc_arg = ":%d" % (display)
1224 else:
1225 vnc_arg = "%s:%d" % (vnc_bind_address, display)
1226 else:
1227 logging.error("Network port is not a valid VNC display (%d < %d),"
1228 " not starting VNC",
1229 instance.network_port, constants.VNC_BASE_PORT)
1230 vnc_arg = "none"
1231
1232 # Only allow tls and other option when not binding to a file, for now.
1233 # kvm/qemu gets confused otherwise about the filename to use.
1234 vnc_append = ""
1235 if hvp[constants.HV_VNC_TLS]:
1236 vnc_append = "%s,tls" % vnc_append
1237 if hvp[constants.HV_VNC_X509_VERIFY]:
1238 vnc_append = "%s,x509verify=%s" % (vnc_append,
1239 hvp[constants.HV_VNC_X509])
1240 elif hvp[constants.HV_VNC_X509]:
1241 vnc_append = "%s,x509=%s" % (vnc_append,
1242 hvp[constants.HV_VNC_X509])
1243 if hvp[constants.HV_VNC_PASSWORD_FILE]:
1244 vnc_append = "%s,password" % vnc_append
1245
1246 vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1247
1248 else:
1249 vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1250
1251 kvm_cmd.extend(["-vnc", vnc_arg])
1252 elif spice_bind:
1253 # FIXME: this is wrong here; the iface ip address differs
1254 # between systems, so it should be done in _ExecuteKVMRuntime
1255 if netutils.IsValidInterface(spice_bind):
1256 # The user specified a network interface, we have to figure out the IP
1257 # address.
1258 addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1259 spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1260
1261 # if the user specified an IP version and the interface does not
1262 # have that kind of IP addresses, throw an exception
1263 if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1264 if not addresses[spice_ip_version]:
1265 raise errors.HypervisorError("SPICE: Unable to get an IPv%s address"
1266 " for %s" % (spice_ip_version,
1267 spice_bind))
1268
1269 # the user did not specify an IP version, we have to figure it out
1270 elif (addresses[constants.IP4_VERSION] and
1271 addresses[constants.IP6_VERSION]):
1272 # we have both ipv4 and ipv6, let's use the cluster default IP
1273 # version
1274 cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1275 spice_ip_version = \
1276 netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1277 elif addresses[constants.IP4_VERSION]:
1278 spice_ip_version = constants.IP4_VERSION
1279 elif addresses[constants.IP6_VERSION]:
1280 spice_ip_version = constants.IP6_VERSION
1281 else:
1282 raise errors.HypervisorError("SPICE: Unable to get an IP address"
1283 " for %s" % (spice_bind))
1284
1285 spice_address = addresses[spice_ip_version][0]
1286
1287 else:
1288 # spice_bind is known to be a valid IP address, because
1289 # ValidateParameters checked it.
1290 spice_address = spice_bind
1291
1292 spice_arg = "addr=%s" % spice_address
1293 if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1294 spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1295 (spice_arg, instance.network_port,
1296 pathutils.SPICE_CACERT_FILE))
1297 spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1298 (spice_arg, pathutils.SPICE_CERT_FILE,
1299 pathutils.SPICE_CERT_FILE))
1300 tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1301 if tls_ciphers:
1302 spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1303 else:
1304 spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1305
1306 if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1307 spice_arg = "%s,disable-ticketing" % spice_arg
1308
1309 if spice_ip_version:
1310 spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1311
1312 # Image compression options
1313 img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1314 img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1315 img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1316 if img_lossless:
1317 spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1318 if img_jpeg:
1319 spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1320 if img_zlib_glz:
1321 spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1322
1323 # Video stream detection
1324 video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1325 if video_streaming:
1326 spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1327
1328 # Audio compression, by default in qemu-kvm it is on
1329 if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1330 spice_arg = "%s,playback-compression=off" % spice_arg
1331 if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1332 spice_arg = "%s,agent-mouse=off" % spice_arg
1333 else:
1334 # Enable the spice agent communication channel between the host and the
1335 # agent.
1336 addr = _GetFreeSlot(pci_reservations, reserve=True)
1337 pci_info = ",bus=pci.0,addr=%s" % hex(addr)
1338 kvm_cmd.extend(["-device", "virtio-serial-pci,id=spice%s" % pci_info])
1339 kvm_cmd.extend([
1340 "-device",
1341 "virtserialport,chardev=spicechannel0,name=com.redhat.spice.0",
1342 ])
1343 kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1344
1345 logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1346 kvm_cmd.extend(["-spice", spice_arg])
1347
1348 else:
1349 # From qemu 1.4 -nographic is incompatible with -daemonize. The new way
1350 # also works in earlier versions though (tested with 1.1 and 1.3)
1351 if self._DISPLAY_RE.search(kvmhelp):
1352 kvm_cmd.extend(["-display", "none"])
1353 else:
1354 kvm_cmd.extend(["-nographic"])
1355
1356 if hvp[constants.HV_USE_LOCALTIME]:
1357 kvm_cmd.extend(["-localtime"])
1358
1359 if hvp[constants.HV_KVM_USE_CHROOT]:
1360 kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1361
1362 # Add qemu-KVM -cpu param
1363 if hvp[constants.HV_CPU_TYPE]:
1364 kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1365
1366 # Pass a -vga option if requested, or if spice is used, for backwards
1367 # compatibility.
1368 if hvp[constants.HV_VGA]:
1369 kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1370 elif spice_bind:
1371 kvm_cmd.extend(["-vga", "qxl"])
1372
1373 # Various types of usb devices, comma separated
1374 if hvp[constants.HV_USB_DEVICES]:
1375 for dev in hvp[constants.HV_USB_DEVICES].split(","):
1376 kvm_cmd.extend(["-usbdevice", dev])
1377
1378 # Set system UUID to instance UUID
1379 if self._UUID_RE.search(kvmhelp):
1380 kvm_cmd.extend(["-uuid", instance.uuid])
1381
1382 if hvp[constants.HV_KVM_EXTRA]:
1383 kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
1384
1385 kvm_disks = []
1386 for disk, link_name, uri in block_devices:
1387 disk.pci = _GetFreeSlot(pci_reservations, disk.pci, True)
1388 kvm_disks.append((disk, link_name, uri))
1389
1390 kvm_nics = []
1391 for nic in instance.nics:
1392 nic.pci = _GetFreeSlot(pci_reservations, nic.pci, True)
1393 kvm_nics.append(nic)
1394
1395 hvparams = hvp
1396
1397 return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
1398
1399 def _WriteKVMRuntime(self, instance_name, data):
1400 """Write an instance's KVM runtime
1401
1402 """
1403 try:
1404 utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1405 data=data)
1406 except EnvironmentError, err:
1407 raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1408
1409 def _ReadKVMRuntime(self, instance_name):
1410 """Read an instance's KVM runtime
1411
1412 """
1413 try:
1414 file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1415 except EnvironmentError, err:
1416 raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1417 return file_content
1418
1419 def _SaveKVMRuntime(self, instance, kvm_runtime):
1420 """Save an instance's KVM runtime
1421
1422 """
1423 kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1424
1425 serialized_nics = [nic.ToDict() for nic in kvm_nics]
1426 serialized_disks = [(blk.ToDict(), link, uri)
1427 for blk, link, uri in kvm_disks]
1428 serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1429 serialized_disks))
1430
1431 self._WriteKVMRuntime(instance.name, serialized_form)
1432
1433 def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1434 """Load an instance's KVM runtime
1435
1436 """
1437 if not serialized_runtime:
1438 serialized_runtime = self._ReadKVMRuntime(instance.name)
1439
1440 return _AnalyzeSerializedRuntime(serialized_runtime)
1441
1442 def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1443 """Run the KVM cmd and check for errors
1444
1445 @type name: string
1446 @param name: instance name
1447 @type kvm_cmd: list of strings
1448 @param kvm_cmd: runcmd input for kvm
1449 @type tap_fds: list of int
1450 @param tap_fds: fds of tap devices opened by Ganeti
1451
1452 """
1453 try:
1454 result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1455 finally:
1456 for fd in tap_fds:
1457 utils_wrapper.CloseFdNoError(fd)
1458
1459 if result.failed:
1460 raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1461 (name, result.fail_reason, result.output))
1462 if not self._InstancePidAlive(name)[2]:
1463 raise errors.HypervisorError("Failed to start instance %s" % name)
1464
1465 @staticmethod
1466 def _GenerateKvmTapName(nic):
1467 """Generate a TAP network interface name for a NIC.
1468
1469 See L{hv_base.GenerateTapName}.
1470
1471 For the case of the empty string, see L{OpenTap}
1472
1473 @type nic: ganeti.objects.NIC
1474 @param nic: NIC object for the name should be generated
1475
1476 @rtype: string
1477 @return: TAP network interface name, or the empty string if the
1478 NIC is not used in instance communication
1479
1480 """
1481 if nic.name is None or not \
1482 nic.name.startswith(constants.INSTANCE_COMMUNICATION_NIC_PREFIX):
1483 return ""
1484
1485 return hv_base.GenerateTapName()
1486
1487 def _GetNetworkDeviceFeatures(self, up_hvp, devlist, kvmhelp):
1488 """Get network device options to properly enable supported features.
1489
1490 Return tuple of supported and enabled tap features with nic_model.
1491 This function is called before opening a new tap device.
1492
1493 @return: (nic_model, vnet_hdr, virtio_net_queues, tap_extra, nic_extra)
1494 @rtype: tuple
1495
1496 """
1497 virtio_net_queues = 1
1498 nic_extra = ""
1499 nic_type = up_hvp[constants.HV_NIC_TYPE]
1500 tap_extra = ""
1501 vnet_hdr = False
1502 if nic_type == constants.HT_NIC_PARAVIRTUAL:
1503 nic_model = self._VIRTIO
1504 try:
1505 if self._VIRTIO_NET_RE.search(devlist):
1506 nic_model = self._VIRTIO_NET_PCI
1507 vnet_hdr = up_hvp[constants.HV_VNET_HDR]
1508 except errors.HypervisorError, _:
1509 # Older versions of kvm don't support DEVICE_LIST, but they don't
1510 # have new virtio syntax either.
1511 pass
1512
1513 if up_hvp[constants.HV_VHOST_NET]:
1514 # Check for vhost_net support.
1515 if self._VHOST_RE.search(kvmhelp):
1516 tap_extra = ",vhost=on"
1517 else:
1518 raise errors.HypervisorError("vhost_net is configured"
1519 " but it is not available")
1520 if up_hvp[constants.HV_VIRTIO_NET_QUEUES] > 1:
1521 # Check for multiqueue virtio-net support.
1522 if self._VIRTIO_NET_QUEUES_RE.search(kvmhelp):
1523 virtio_net_queues = up_hvp[constants.HV_VIRTIO_NET_QUEUES]
1524 # As advised at http://www.linux-kvm.org/page/Multiqueue formula
1525 # for calculating vector size is: vectors=2*N+1 where N is the
1526 # number of queues (HV_VIRTIO_NET_QUEUES).
1527 nic_extra = ",mq=on,vectors=%d" % (2 * virtio_net_queues + 1)
1528 else:
1529 raise errors.HypervisorError("virtio_net_queues is configured"
1530 " but it is not available")
1531 else:
1532 nic_model = nic_type
1533
1534 return (nic_model, vnet_hdr, virtio_net_queues, tap_extra, nic_extra)
1535
1536 # too many local variables
1537 # pylint: disable=R0914
1538 def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1539 """Execute a KVM cmd, after completing it with some last minute data.
1540
1541 @type incoming: tuple of strings
1542 @param incoming: (target_host_ip, port)
1543 @type kvmhelp: string
1544 @param kvmhelp: output of kvm --help
1545
1546 """
1547 # Small _ExecuteKVMRuntime hv parameters programming howto:
1548 # - conf_hvp contains the parameters as configured on ganeti. they might
1549 # have changed since the instance started; only use them if the change
1550 # won't affect the inside of the instance (which hasn't been rebooted).
1551 # - up_hvp contains the parameters as they were when the instance was
1552 # started, plus any new parameter which has been added between ganeti
1553 # versions: it is paramount that those default to a value which won't
1554 # affect the inside of the instance as well.
1555 conf_hvp = instance.hvparams
1556 name = instance.name
1557 self._CheckDown(name)
1558
1559 self._ClearUserShutdown(instance.name)
1560 self._StartKvmd(instance.hvparams)
1561
1562 temp_files = []
1563
1564 kvm_cmd, kvm_nics, up_hvp, kvm_disks = kvm_runtime
1565 # the first element of kvm_cmd is always the path to the kvm binary
1566 kvm_path = kvm_cmd[0]
1567 up_hvp = objects.FillDict(conf_hvp, up_hvp)
1568
1569 # We know it's safe to run as a different user upon migration, so we'll use
1570 # the latest conf, from conf_hvp.
1571 security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1572 if security_model == constants.HT_SM_USER:
1573 kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1574
1575 keymap = conf_hvp[constants.HV_KEYMAP]
1576 if keymap:
1577 keymap_path = self._InstanceKeymapFile(name)
1578 # If a keymap file is specified, KVM won't use its internal defaults. By
1579 # first including the "en-us" layout, an error on loading the actual
1580 # layout (e.g. because it can't be found) won't lead to a non-functional
1581 # keyboard. A keyboard with incorrect keys is still better than none.
1582 utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1583 kvm_cmd.extend(["-k", keymap_path])
1584
1585 # We have reasons to believe changing something like the nic driver/type
1586 # upon migration won't exactly fly with the instance kernel, so for nic
1587 # related parameters we'll use up_hvp
1588 tapfds = []
1589 taps = []
1590 devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1591 if not kvm_nics:
1592 kvm_cmd.extend(["-net", "none"])
1593 else:
1594 (nic_model, vnet_hdr,
1595 virtio_net_queues, tap_extra,
1596 nic_extra) = self._GetNetworkDeviceFeatures(up_hvp, devlist, kvmhelp)
1597 kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
1598 for nic_seq, nic in enumerate(kvm_nics):
1599 tapname, nic_tapfds = OpenTap(vnet_hdr=vnet_hdr,
1600 virtio_net_queues=virtio_net_queues,
1601 name=self._GenerateKvmTapName(nic))
1602 tapfds.extend(nic_tapfds)
1603 taps.append(tapname)
1604 tapfd = "%s%s" % ("fds=" if len(nic_tapfds) > 1 else "fd=",
1605 ":".join(str(fd) for fd in nic_tapfds))
1606 if kvm_supports_netdev:
1607 nic_val = "%s,mac=%s" % (nic_model, nic.mac)
1608 try:
1609 # kvm_nics already exist in old runtime files and thus there might
1610 # be some entries without pci slot (therefore try: except:)
1611 kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
1612 netdev = kvm_devid
1613 nic_val += (",id=%s,bus=pci.0,addr=%s" % (kvm_devid, hex(nic.pci)))
1614 except errors.HotplugError:
1615 netdev = "netdev%d" % nic_seq
1616 nic_val += (",netdev=%s%s" % (netdev, nic_extra))
1617 tap_val = ("type=tap,id=%s,%s%s" %
1618 (netdev, tapfd, tap_extra))
1619 kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1620 else:
1621 nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1622 nic.mac, nic_model)
1623 tap_val = "tap,vlan=%s,%s" % (nic_seq, tapfd)
1624 kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1625
1626 if incoming:
1627 target, port = incoming
1628 kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1629
1630 # Changing the vnc password doesn't bother the guest that much. At most it
1631 # will surprise people who connect to it. Whether positively or negatively
1632 # it's debatable.
1633 vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1634 vnc_pwd = None
1635 if vnc_pwd_file:
1636 try:
1637 vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1638 except EnvironmentError, err:
1639 raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1640 % (vnc_pwd_file, err))
1641
1642 if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1643 utils.EnsureDirs([(self._InstanceChrootDir(name),
1644 constants.SECURE_DIR_MODE)])
1645
1646 # Automatically enable QMP if version is >= 0.14
1647 if self._QMP_RE.search(kvmhelp):
1648 logging.debug("Enabling QMP")
1649 kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1650 self._InstanceQmpMonitor(instance.name)])
1651 # Add a second monitor for kvmd
1652 kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1653 self._InstanceKvmdMonitor(instance.name)])
1654
1655 # Configure the network now for starting instances and bridged interfaces,
1656 # during FinalizeMigration for incoming instances' routed interfaces
1657 for nic_seq, nic in enumerate(kvm_nics):
1658 if (incoming and
1659 nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1660 continue
1661 self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1662
1663 bdev_opts = self._GenerateKVMBlockDevicesOptions(instance,
1664 up_hvp,
1665 kvm_disks,
1666 kvmhelp,
1667 devlist)
1668 kvm_cmd.extend(bdev_opts)
1669 # CPU affinity requires kvm to start paused, so we set this flag if the
1670 # instance is not already paused and if we are not going to accept a
1671 # migrating instance. In the latter case, pausing is not needed.
1672 start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1673 if start_kvm_paused:
1674 kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1675
1676 # Note: CPU pinning is using up_hvp since changes take effect
1677 # during instance startup anyway, and to avoid problems when soft
1678 # rebooting the instance.
1679 cpu_pinning = False
1680 if up_hvp.get(constants.HV_CPU_MASK, None):
1681 cpu_pinning = True
1682
1683 if security_model == constants.HT_SM_POOL:
1684 ss = ssconf.SimpleStore()
1685 uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1686 all_uids = set(uidpool.ExpandUidPool(uid_pool))
1687 uid = uidpool.RequestUnusedUid(all_uids)
1688 try:
1689 username = pwd.getpwuid(uid.GetUid()).pw_name
1690 kvm_cmd.extend(["-runas", username])
1691 self._RunKVMCmd(name, kvm_cmd, tapfds)
1692 except:
1693 uidpool.ReleaseUid(uid)
1694 raise
1695 else:
1696 uid.Unlock()
1697 utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1698 else:
1699 self._RunKVMCmd(name, kvm_cmd, tapfds)
1700
1701 utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1702 constants.RUN_DIRS_MODE)])
1703 for nic_seq, tap in enumerate(taps):
1704 utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1705 data=tap)
1706
1707 if vnc_pwd:
1708 change_cmd = "change vnc password %s" % vnc_pwd
1709 self._CallMonitorCommand(instance.name, change_cmd)
1710
1711 # Setting SPICE password. We are not vulnerable to malicious passwordless
1712 # connection attempts because SPICE by default does not allow connections
1713 # if neither a password nor the "disable_ticketing" options are specified.
1714 # As soon as we send the password via QMP, that password is a valid ticket
1715 # for connection.
1716 spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1717 if spice_password_file:
1718 spice_pwd = ""
1719 try:
1720 spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1721 except EnvironmentError, err:
1722 raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1723 % (spice_password_file, err))
1724
1725 qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1726 qmp.connect()
1727 arguments = {
1728 "protocol": "spice",
1729 "password": spice_pwd,
1730 }
1731 qmp.Execute("set_password", arguments)
1732
1733 for filename in temp_files:
1734 utils.RemoveFile(filename)
1735
1736 # If requested, set CPU affinity and resume instance execution
1737 if cpu_pinning:
1738 self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1739
1740 start_memory = self._InstanceStartupMemory(instance)
1741 if start_memory < instance.beparams[constants.BE_MAXMEM]:
1742 self.BalloonInstanceMemory(instance, start_memory)
1743
1744 if start_kvm_paused:
1745 # To control CPU pinning, ballooning, and vnc/spice passwords
1746 # the VM was started in a frozen state. If freezing was not
1747 # explicitly requested resume the vm status.
1748 self._CallMonitorCommand(instance.name, self._CONT_CMD)
1749
1750 @staticmethod
1751 def _StartKvmd(hvparams):
1752 """Ensure that the Kvm daemon is running.
1753
1754 @type hvparams: dict of strings
1755 @param hvparams: hypervisor parameters
1756
1757 """
1758 if hvparams is None \
1759 or not hvparams[constants.HV_KVM_USER_SHUTDOWN] \
1760 or utils.IsDaemonAlive(constants.KVMD):
1761 return
1762
1763 result = utils.RunCmd([pathutils.DAEMON_UTIL, "start", constants.KVMD])
1764
1765 if result.failed:
1766 raise errors.HypervisorError("Failed to start KVM daemon")
1767
1768 def StartInstance(self, instance, block_devices, startup_paused):
1769 """Start an instance.
1770
1771 """
1772 self._CheckDown(instance.name)
1773 kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1774 kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1775 kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1776 startup_paused, kvmhelp)
1777 self._SaveKVMRuntime(instance, kvm_runtime)
1778 self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1779
1780 @classmethod
1781 def _CallMonitorCommand(cls, instance_name, command, timeout=None):
1782 """Invoke a command on the instance monitor.
1783
1784 """
1785 if timeout is not None:
1786 timeout_cmd = "timeout %s" % (timeout, )
1787 else:
1788 timeout_cmd = ""
1789
1790 # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1791 # version. The monitor protocol is designed for human consumption, whereas
1792 # QMP is made for programmatic usage. In the worst case QMP can also
1793 # execute monitor commands. As it is, all calls to socat take at least
1794 # 500ms and likely more: socat can't detect the end of the reply and waits
1795 # for 500ms of no data received before exiting (500 ms is the default for
1796 # the "-t" parameter).
1797 socat = ("echo %s | %s %s STDIO UNIX-CONNECT:%s" %
1798 (utils.ShellQuote(command),
1799 timeout_cmd,
1800 constants.SOCAT_PATH,
1801 utils.ShellQuote(cls._InstanceMonitor(instance_name))))
1802 result = utils.RunCmd(socat)
1803 if result.failed:
1804 msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1805 " output: %s" %
1806 (command, instance_name, result.fail_reason, result.output))
1807 raise errors.HypervisorError(msg)
1808
1809 return result
1810
1811 def _GetFreePCISlot(self, instance, dev):
1812 """Get the first available pci slot of a runnung instance.
1813
1814 """
1815 slots = bitarray(32)
1816 slots.setall(False) # pylint: disable=E1101
1817 output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
1818 for line in output.stdout.splitlines():
1819 match = self._INFO_PCI_RE.search(line)
1820 if match:
1821 slot = int(match.group(1))
1822 slots[slot] = True
1823
1824 dev.pci = _GetFreeSlot(slots)
1825
1826 def VerifyHotplugSupport(self, instance, action, dev_type):
1827 """Verifies that hotplug is supported.
1828
1829 Hotplug is *not* supported in case of:
1830 - security models and chroot (disk hotplug)
1831 - fdsend module is missing (nic hot-add)
1832
1833 @raise errors.HypervisorError: in one of the previous cases
1834
1835 """
1836 if dev_type == constants.HOTPLUG_TARGET_DISK:
1837 hvp = instance.hvparams
1838 security_model = hvp[constants.HV_SECURITY_MODEL]
1839 use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
1840 if use_chroot:
1841 raise errors.HotplugError("Disk hotplug is not supported"
1842 " in case of chroot.")
1843 if security_model != constants.HT_SM_NONE:
1844 raise errors.HotplugError("Disk Hotplug is not supported in case"
1845 " security models are used.")
1846
1847 if (dev_type == constants.HOTPLUG_TARGET_NIC and
1848 action == constants.HOTPLUG_ACTION_ADD and not fdsend):
1849 raise errors.HotplugError("Cannot hot-add NIC."
1850 " fdsend python module is missing.")
1851
1852 def HotplugSupported(self, instance):
1853 """Checks if hotplug is generally supported.
1854
1855 Hotplug is *not* supported in case of:
1856 - qemu versions < 1.0
1857 - for stopped instances
1858
1859 @raise errors.HypervisorError: in one of the previous cases
1860
1861 """
1862 try:
1863 output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
1864 except errors.HypervisorError:
1865 raise errors.HotplugError("Instance is probably down")
1866
1867 # TODO: search for netdev_add, drive_add, device_add.....
1868 match = self._INFO_VERSION_RE.search(output.stdout)
1869 if not match:
1870 raise errors.HotplugError("Cannot parse qemu version via monitor")
1871
1872 v_major, v_min, _, _ = match.groups()
1873 if (int(v_major), int(v_min)) < (1, 0):
1874 raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
1875
1876 def _CallHotplugCommands(self, name, cmds):
1877 for c in cmds:
1878 self._CallMonitorCommand(name, c)
1879 time.sleep(1)
1880
1881 def _VerifyHotplugCommand(self, instance_name, device, dev_type,
1882 should_exist):
1883 """Checks if a previous hotplug command has succeeded.
1884
1885 It issues info pci monitor command and checks depending on should_exist
1886 value if an entry with PCI slot and device ID is found or not.
1887
1888 @raise errors.HypervisorError: if result is not the expected one
1889
1890 """
1891 output = self._CallMonitorCommand(instance_name, self._INFO_PCI_CMD)
1892 kvm_devid = _GenerateDeviceKVMId(dev_type, device)
1893 match = \
1894 self._FIND_PCI_DEVICE_RE(device.pci, kvm_devid).search(output.stdout)
1895 if match and not should_exist:
1896 msg = "Device %s should have been removed but is still there" % kvm_devid
1897 raise errors.HypervisorError(msg)
1898
1899 if not match and should_exist:
1900 msg = "Device %s should have been added but is missing" % kvm_devid
1901 raise errors.HypervisorError(msg)
1902
1903 logging.info("Device %s has been correctly hot-plugged", kvm_devid)
1904
1905 def HotAddDevice(self, instance, dev_type, device, extra, seq):
1906 """ Helper method to hot-add a new device
1907
1908 It gets free pci slot generates the device name and invokes the
1909 device specific method.
1910
1911 """
1912 # in case of hot-mod this is given
1913 if device.pci is None:
1914 self._GetFreePCISlot(instance, device)
1915 kvm_devid = _GenerateDeviceKVMId(dev_type, device)
1916 runtime = self._LoadKVMRuntime(instance)
1917 if dev_type == constants.HOTPLUG_TARGET_DISK:
1918 drive_uri = _GetDriveURI(device, extra[0], extra[1])
1919 cmds = ["drive_add dummy file=%s,if=none,id=%s,format=raw" %
1920 (drive_uri, kvm_devid)]
1921 cmds += ["device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
1922 (hex(device.pci), kvm_devid, kvm_devid)]
1923 elif dev_type == constants.HOTPLUG_TARGET_NIC:
1924 kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1925 kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1926 devlist = self._GetKVMOutput(kvmpath, self._KVMOPT_DEVICELIST)
1927 up_hvp = runtime[2]
1928 (_, vnet_hdr,
1929 virtio_net_queues, tap_extra,
1930 nic_extra) = self._GetNetworkDeviceFeatures(up_hvp, devlist, kvmhelp)
1931 (tap, fds) = OpenTap(vnet_hdr=vnet_hdr,
1932 virtio_net_queues=virtio_net_queues)
1933 # netdev_add don't support "fds=" when multiple fds are
1934 # requested, generate separate "fd=" string for every fd
1935 tapfd = ",".join(["fd=%s" % fd for fd in fds])
1936 self._ConfigureNIC(instance, seq, device, tap)
1937 self._PassTapFd(instance, fds, device)
1938 cmds = ["netdev_add tap,id=%s,%s%s" % (kvm_devid, tapfd, tap_extra)]
1939 args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s%s" % \
1940 (hex(device.pci), device.mac, kvm_devid, kvm_devid, nic_extra)
1941 cmds += ["device_add %s" % args]
1942 utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
1943
1944 self._CallHotplugCommands(instance.name, cmds)
1945 self._VerifyHotplugCommand(instance.name, device, dev_type, True)
1946 # update relevant entries in runtime file
1947 index = _DEVICE_RUNTIME_INDEX[dev_type]
1948 entry = _RUNTIME_ENTRY[dev_type](device, extra)
1949 runtime[index].append(entry)
1950 self._SaveKVMRuntime(instance, runtime)
1951
1952 def HotDelDevice(self, instance, dev_type, device, _, seq):
1953 """ Helper method for hot-del device
1954
1955 It gets device info from runtime file, generates the device name and
1956 invokes the device specific method.
1957
1958 """
1959 runtime = self._LoadKVMRuntime(instance)
1960 entry = _GetExistingDeviceInfo(dev_type, device, runtime)
1961 kvm_device = _RUNTIME_DEVICE[dev_type](entry)
1962 kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
1963 if dev_type == constants.HOTPLUG_TARGET_DISK:
1964 cmds = ["device_del %s" % kvm_devid]
1965 cmds += ["drive_del %s" % kvm_devid]
1966 elif dev_type == constants.HOTPLUG_TARGET_NIC:
1967 cmds = ["device_del %s" % kvm_devid]
1968 cmds += ["netdev_del %s" % kvm_devid]
1969 utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
1970 self._CallHotplugCommands(instance.name, cmds)
1971 self._VerifyHotplugCommand(instance.name, kvm_device, dev_type, False)
1972 index = _DEVICE_RUNTIME_INDEX[dev_type]
1973 runtime[index].remove(entry)
1974 self._SaveKVMRuntime(instance, runtime)
1975
1976 return kvm_device.pci
1977
1978 def HotModDevice(self, instance, dev_type, device, _, seq):
1979 """ Helper method for hot-mod device
1980
1981 It gets device info from runtime file, generates the device name and
1982 invokes the device specific method. Currently only NICs support hot-mod
1983
1984 """
1985 if dev_type == constants.HOTPLUG_TARGET_NIC:
1986 # putting it back in the same pci slot
1987 device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
1988 self.HotAddDevice(instance, dev_type, device, _, seq)
1989
1990 def _PassTapFd(self, instance, fds, nic):
1991 """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
1992
1993 """
1994 # TODO: factor out code related to unix sockets.
1995 # squash common parts between monitor and qmp
1996 kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
1997 command = "getfd %s\n" % kvm_devid
1998 logging.info("%s", fds)
1999 try:
2000 monsock = MonitorSocket(self._InstanceMonitor(instance.name))
2001 monsock.connect()
2002 fdsend.sendfds(monsock.sock, command, fds=fds)
2003 finally:
2004 monsock.close()
2005
2006 @classmethod
2007 def _ParseKVMVersion(cls, text):
2008 """Parse the KVM version from the --help output.
2009
2010 @type text: string
2011 @param text: output of kvm --help
2012 @return: (version, v_maj, v_min, v_rev)
2013 @raise errors.HypervisorError: when the KVM version cannot be retrieved
2014
2015 """
2016 match = cls._VERSION_RE.search(text.splitlines()[0])
2017 if not match:
2018 raise errors.HypervisorError("Unable to get KVM version")
2019
2020 v_all = match.group(0)
2021 v_maj = int(match.group(1))
2022 v_min = int(match.group(2))
2023 if match.group(4):
2024 v_rev = int(match.group(4))
2025 else:
2026 v_rev = 0
2027 return (v_all, v_maj, v_min, v_rev)
2028
2029 @classmethod
2030 def _GetKVMOutput(cls, kvm_path, option):
2031 """Return the output of a kvm invocation
2032
2033 @type kvm_path: string
2034 @param kvm_path: path to the kvm executable
2035 @type option: a key of _KVMOPTS_CMDS
2036 @param option: kvm option to fetch the output from
2037 @return: output a supported kvm invocation
2038 @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2039
2040 """
2041 assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2042
2043 optlist, can_fail = cls._KVMOPTS_CMDS[option]
2044
2045 result = utils.RunCmd([kvm_path] + optlist)
2046 if result.failed and not can_fail:
2047 raise errors.HypervisorError("Unable to get KVM %s output" %
2048 " ".join(optlist))
2049 return result.output
2050
2051 @classmethod
2052 def _GetKVMVersion(cls, kvm_path):
2053 """Return the installed KVM version.
2054
2055 @return: (version, v_maj, v_min, v_rev)
2056 @raise errors.HypervisorError: when the KVM version cannot be retrieved
2057
2058 """
2059 return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2060
2061 @classmethod
2062 def _GetDefaultMachineVersion(cls, kvm_path):
2063 """Return the default hardware revision (e.g. pc-1.1)
2064
2065 """
2066 output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2067 match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2068 if match:
2069 return match.group(1)
2070 else:
2071 return "pc"
2072
2073 @classmethod
2074 def _StopInstance(cls, instance, force=False, name=None, timeout=None):
2075 """Stop an instance.
2076
2077 """
2078 assert(timeout is None or force is not None)
2079
2080 if name is not None and not force:
2081 raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2082 if name is None:
2083 name = instance.name
2084 acpi = instance.hvparams[constants.HV_ACPI]
2085 else:
2086 acpi = False
2087 _, pid, alive = cls._InstancePidAlive(name)
2088 if pid > 0 and alive:
2089 if force or not acpi:
2090 utils.KillProcess(pid)
2091 else:
2092 cls._CallMonitorCommand(name, "system_powerdown", timeout)
2093 cls._ClearUserShutdown(instance.name)
2094
2095 def StopInstance(self, instance, force=False, retry=False, name=None,
2096 timeout=None):
2097 """Stop an instance.
2098
2099 """
2100 self._StopInstance(instance, force, name=name, timeout=timeout)
2101
2102 def CleanupInstance(self, instance_name):
2103 """Cleanup after a stopped instance
2104
2105 """
2106 pidfile, pid, alive = self._InstancePidAlive(instance_name)
2107 if pid > 0 and alive:
2108 raise errors.HypervisorError("Cannot cleanup a live instance")
2109 self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2110 self._ClearUserShutdown(instance_name)
2111
2112 def RebootInstance(self, instance):
2113 """Reboot an instance.
2114
2115 """
2116 # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2117 # socket the instance will stop, but now power up again. So we'll resort
2118 # to shutdown and restart.
2119 _, _, alive = self._InstancePidAlive(instance.name)
2120 if not alive:
2121 raise errors.HypervisorError("Failed to reboot instance %s:"
2122 " not running" % instance.name)
2123 # StopInstance will delete the saved KVM runtime so:
2124 # ...first load it...
2125 kvm_runtime = self._LoadKVMRuntime(instance)
2126 # ...now we can safely call StopInstance...
2127 if not self.StopInstance(instance):
2128 self.StopInstance(instance, force=True)
2129 # ...and finally we can save it again, and execute it...
2130 self._SaveKVMRuntime(instance, kvm_runtime)
2131 kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2132 kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2133 self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2134
2135 def MigrationInfo(self, instance):
2136 """Get instance information to perform a migration.
2137
2138 @type instance: L{objects.Instance}
2139 @param instance: instance to be migrated
2140 @rtype: string
2141 @return: content of the KVM runtime file
2142
2143 """
2144 return self._ReadKVMRuntime(instance.name)
2145
2146 def AcceptInstance(self, instance, info, target):
2147 """Prepare to accept an instance.
2148
2149 @type instance: L{objects.Instance}
2150 @param instance: instance to be accepted
2151 @type info: string
2152 @param info: content of the KVM runtime file on the source node
2153 @type target: string
2154 @param target: target host (usually ip), on this node
2155
2156 """
2157 kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2158 incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2159 kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2160 kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2161 self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2162 incoming=incoming_address)
2163
2164 def FinalizeMigrationDst(self, instance, info, success):
2165 """Finalize the instance migration on the target node.
2166
2167 Stop the incoming mode KVM.
2168
2169 @type instance: L{objects.Instance}
2170 @param instance: instance whose migration is being finalized
2171
2172 """
2173 if success:
2174 kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2175 kvm_nics = kvm_runtime[1]
2176
2177 for nic_seq, nic in enumerate(kvm_nics):
2178 if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2179 # Bridged interfaces have already been configured
2180 continue
2181 try:
2182 tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2183 except EnvironmentError, err:
2184 logging.warning("Failed to find host interface for %s NIC #%d: %s",
2185 instance.name, nic_seq, str(err))
2186 continue
2187 try:
2188 self._ConfigureNIC(instance, nic_seq, nic, tap)
2189 except errors.HypervisorError, err:
2190 logging.warning(str(err))
2191
2192 self._WriteKVMRuntime(instance.name, info)
2193 else:
2194 self.StopInstance(instance, force=True)
2195
2196 def MigrateInstance(self, cluster_name, instance, target, live):
2197 """Migrate an instance to a target node.
2198
2199 The migration will not be attempted if the instance is not
2200 currently running.
2201
2202 @type cluster_name: string
2203 @param cluster_name: name of the cluster
2204 @type instance: L{objects.Instance}
2205 @param instance: the instance to be migrated
2206 @type target: string
2207 @param target: ip address of the target node
2208 @type live: boolean
2209 @param live: perform a live migration
2210
2211 """
2212 instance_name = instance.name
2213 port = instance.hvparams[constants.HV_MIGRATION_PORT]
2214 _, _, alive = self._InstancePidAlive(instance_name)
2215 if not alive:
2216 raise errors.HypervisorError("Instance not running, cannot migrate")
2217
2218 if not live:
2219 self._CallMonitorCommand(instance_name, "stop")
2220
2221 migrate_command = ("migrate_set_speed %dm" %
2222 instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2223 self._CallMonitorCommand(instance_name, migrate_command)
2224
2225 migrate_command = ("migrate_set_downtime %dms" %
2226 instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2227 self._CallMonitorCommand(instance_name, migrate_command)
2228
2229 migration_caps = instance.hvparams[constants.HV_KVM_MIGRATION_CAPS]
2230 if migration_caps:
2231 for c in migration_caps.split(_MIGRATION_CAPS_DELIM):
2232 migrate_command = ("migrate_set_capability %s on" % c)
2233 self._CallMonitorCommand(instance_name, migrate_command)
2234
2235 migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2236 self._CallMonitorCommand(instance_name, migrate_command)
2237
2238 def FinalizeMigrationSource(self, instance, success, live):
2239 """Finalize the instance migration on the source node.
2240
2241 @type instance: L{objects.Instance}
2242 @param instance: the instance that was migrated
2243 @type success: bool
2244 @param success: whether the migration succeeded or not
2245 @type live: bool
2246 @param live: whether the user requested a live migration or not
2247
2248 """
2249 if success:
2250 pidfile, pid, _ = self._InstancePidAlive(instance.name)
2251 utils.KillProcess(pid)
2252 self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2253 elif live:
2254 self._CallMonitorCommand(instance.name, self._CONT_CMD)
2255 self._ClearUserShutdown(instance.name)
2256
2257 def GetMigrationStatus(self, instance):
2258 """Get the migration status
2259
2260 @type instance: L{objects.Instance}
2261 @param instance: the instance that is being migrated
2262 @rtype: L{objects.MigrationStatus}
2263 @return: the status of the current migration (one of
2264 L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2265 progress info that can be retrieved from the hypervisor
2266
2267 """
2268 info_command = "info migrate"
2269 for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2270 result = self._CallMonitorCommand(instance.name, info_command)
2271 match = self._MIGRATION_STATUS_RE.search(result.stdout)
2272 if not match:
2273 if not result.stdout:
2274 logging.info("KVM: empty 'info migrate' result")
2275 else:
2276 logging.warning("KVM: unknown 'info migrate' result: %s",
2277 result.stdout)
2278 else:
2279 status = match.group(1)
2280 if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2281 migration_status = objects.MigrationStatus(status=status)
2282 match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2283 if match:
2284 migration_status.transferred_ram = match.group("transferred")
2285 migration_status.total_ram = match.group("total")
2286
2287 return migration_status
2288
2289 logging.warning("KVM: unknown migration status '%s'", status)
2290
2291 time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2292
2293 return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2294
2295 def BalloonInstanceMemory(self, instance, mem):
2296 """Balloon an instance memory to a certain value.
2297
2298 @type instance: L{objects.Instance}
2299 @param instance: instance to be accepted
2300 @type mem: int
2301 @param mem: actual memory size to use for instance runtime
2302
2303 """
2304 self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2305
2306 def GetNodeInfo(self, hvparams=None):
2307 """Return information about the node.
2308
2309 @type hvparams: dict of strings
2310 @param hvparams: hypervisor parameters, not used in this class
2311
2312 @return: a dict as returned by L{BaseHypervisor.GetLinuxNodeInfo} plus
2313 the following keys:
2314 - hv_version: the hypervisor version in the form (major, minor,
2315 revision)
2316
2317 """
2318 result = self.GetLinuxNodeInfo()
2319 kvmpath = constants.KVM_PATH
2320 if hvparams is not None:
2321 kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2322 _, v_major, v_min, v_rev = self._GetKVMVersion(kvmpath)
2323 result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2324 return result
2325
2326 @classmethod
2327 def GetInstanceConsole(cls, instance, primary_node, node_group,
2328 hvparams, beparams):
2329 """Return a command for connecting to the console of an instance.
2330
2331 """
2332 if hvparams[constants.HV_SERIAL_CONSOLE]:
2333 cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2334 constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2335 utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2336 "STDIO,%s" % cls._SocatUnixConsoleParams(),
2337 "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2338 ndparams = node_group.FillND(primary_node)
2339 return objects.InstanceConsole(instance=instance.name,
2340 kind=constants.CONS_SSH,
2341 host=primary_node.name,
2342 port=ndparams.get(constants.ND_SSH_PORT),
2343 user=constants.SSH_CONSOLE_USER,
2344 command=cmd)
2345
2346 vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2347 if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2348 display = instance.network_port - constants.VNC_BASE_PORT
2349 return objects.InstanceConsole(instance=instance.name,
2350 kind=constants.CONS_VNC,
2351 host=vnc_bind_address,
2352 port=instance.network_port,
2353 display=display)
2354
2355 spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2356 if spice_bind:
2357 return objects.InstanceConsole(instance=instance.name,
2358 kind=constants.CONS_SPICE,
2359 host=spice_bind,
2360 port=instance.network_port)
2361
2362 return objects.InstanceConsole(instance=instance.name,
2363 kind=constants.CONS_MESSAGE,
2364 message=("No serial shell for instance %s" %
2365 instance.name))
2366
2367 def Verify(self, hvparams=None):
2368 """Verify the hypervisor.
2369
2370 Check that the required binaries exist.
2371
2372 @type hvparams: dict of strings
2373 @param hvparams: hypervisor parameters to be verified against, not used here
2374
2375 @return: Problem description if something is wrong, C{None} otherwise
2376
2377 """
2378 msgs = []
2379 kvmpath = constants.KVM_PATH
2380 if hvparams is not None:
2381 kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2382 if not os.path.exists(kvmpath):
2383 msgs.append("The KVM binary ('%s') does not exist" % kvmpath)
2384 if not os.path.exists(constants.SOCAT_PATH):
2385 msgs.append("The socat binary ('%s') does not exist" %
2386 constants.SOCAT_PATH)
2387
2388 return self._FormatVerifyResults(msgs)
2389
2390 @classmethod
2391 def CheckParameterSyntax(cls, hvparams):
2392 """Check the given parameters for validity.
2393
2394 @type hvparams: dict of strings
2395 @param hvparams: hypervisor parameters
2396 @raise errors.HypervisorError: when a parameter is not valid
2397
2398 """
2399 super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2400
2401 kernel_path = hvparams[constants.HV_KERNEL_PATH]
2402 if kernel_path:
2403 if not hvparams[constants.HV_ROOT_PATH]:
2404 raise errors.HypervisorError("Need a root partition for the instance,"
2405 " if a kernel is defined")
2406
2407 if (hvparams[constants.HV_VNC_X509_VERIFY] and
2408 not hvparams[constants.HV_VNC_X509]):
2409 raise errors.HypervisorError("%s must be defined, if %s is" %
2410 (constants.HV_VNC_X509,
2411 constants.HV_VNC_X509_VERIFY))
2412
2413 if hvparams[constants.HV_SERIAL_CONSOLE]:
2414 serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2415 valid_speeds = constants.VALID_SERIAL_SPEEDS
2416 if not serial_speed or serial_speed not in valid_speeds:
2417 raise errors.HypervisorError("Invalid serial console speed, must be"
2418 " one of: %s" %
2419 utils.CommaJoin(valid_speeds))
2420
2421 boot_order = hvparams[constants.HV_BOOT_ORDER]
2422 if (boot_order == constants.HT_BO_CDROM and
2423 not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2424 raise errors.HypervisorError("Cannot boot from cdrom without an"
2425 " ISO path")
2426
2427 security_model = hvparams[constants.HV_SECURITY_MODEL]
2428 if security_model == constants.HT_SM_USER:
2429 if not hvparams[constants.HV_SECURITY_DOMAIN]:
2430 raise errors.HypervisorError("A security domain (user to run kvm as)"
2431 " must be specified")
2432 elif (security_model == constants.HT_SM_NONE or
2433 security_model == constants.HT_SM_POOL):
2434 if hvparams[constants.HV_SECURITY_DOMAIN]:
2435 raise errors.HypervisorError("Cannot have a security domain when the"
2436 " security model is 'none' or 'pool'")
2437
2438 spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2439 spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2440 if spice_bind:
2441 if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2442 # if an IP version is specified, the spice_bind parameter must be an
2443 # IP of that family
2444 if (netutils.IP4Address.IsValid(spice_bind) and
2445 spice_ip_version != constants.IP4_VERSION):
2446 raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2447 " the specified IP version is %s" %
2448 (spice_bind, spice_ip_version))
2449
2450 if (netutils.IP6Address.IsValid(spice_bind) and
2451 spice_ip_version != constants.IP6_VERSION):
2452 raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2453 " the specified IP version is %s" %
2454 (spice_bind, spice_ip_version))
2455 else:
2456 # All the other SPICE parameters depend on spice_bind being set. Raise an
2457 # error if any of them is set without it.
2458 for param in _SPICE_ADDITIONAL_PARAMS:
2459 if hvparams[param]:
2460 raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2461 (param, constants.HV_KVM_SPICE_BIND))
2462
2463 @classmethod
2464 def ValidateParameters(cls, hvparams):
2465 """Check the given parameters for validity.
2466
2467 @type hvparams: dict of strings
2468 @param hvparams: hypervisor parameters
2469 @raise errors.HypervisorError: when a parameter is not valid
2470
2471 """
2472 super(KVMHypervisor, cls).ValidateParameters(hvparams)
2473
2474 kvm_path = hvparams[constants.HV_KVM_PATH]
2475
2476 security_model = hvparams[constants.HV_SECURITY_MODEL]
2477 if security_model == constants.HT_SM_USER:
2478 username = hvparams[constants.HV_SECURITY_DOMAIN]
2479 try:
2480 pwd.getpwnam(username)
2481 except KeyError:
2482 raise errors.HypervisorError("Unknown security domain user %s"
2483 % username)
2484 vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2485 if vnc_bind_address:
2486 bound_to_addr = netutils.IP4Address.IsValid(vnc_bind_address)
2487 is_interface = netutils.IsValidInterface(vnc_bind_address)
2488 is_path = utils.IsNormAbsPath(vnc_bind_address)
2489 if not bound_to_addr and not is_interface and not is_path:
2490 raise errors.HypervisorError("VNC: The %s parameter must be either"
2491 " a valid IP address, an interface name,"
2492 " or an absolute path" %
2493 constants.HV_KVM_SPICE_BIND)
2494
2495 spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2496 if spice_bind:
2497 # only one of VNC and SPICE can be used currently.
2498 if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2499 raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2500 " only one of them can be used at a"
2501 " given time")
2502
2503 # check that KVM supports SPICE
2504 kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2505 if not cls._SPICE_RE.search(kvmhelp):
2506 raise errors.HypervisorError("SPICE is configured, but it is not"
2507 " supported according to 'kvm --help'")
2508
2509 # if spice_bind is not an IP address, it must be a valid interface
2510 bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2511 netutils.IP6Address.IsValid(spice_bind))
2512 if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2513 raise errors.HypervisorError("SPICE: The %s parameter must be either"
2514 " a valid IP address or interface name" %
2515 constants.HV_KVM_SPICE_BIND)
2516
2517 machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2518 if machine_version:
2519 output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2520 if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2521 raise errors.HypervisorError("Unsupported machine version: %s" %
2522 machine_version)
2523
2524 @classmethod
2525 def PowercycleNode(cls, hvparams=None):
2526 """KVM powercycle, just a wrapper over Linux powercycle.
2527
2528 @type hvparams: dict of strings
2529 @param hvparams: hypervisor parameters to be used on this node
2530
2531 """
2532 cls.LinuxPowercycle()