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 psutil # pylint: disable=F0401
39 except ImportError:
40 psutil = 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 @classmethod
714 def _SetProcessAffinity(cls, process_id, cpus):
715 """Sets the affinity of a process to the given CPUs.
716
717 @type process_id: int
718 @type cpus: list of int
719 @param cpus: The list of CPUs the process ID may use.
720
721 """
722 if psutil is None:
723 raise errors.HypervisorError("psutil Python package not"
724 " found; cannot use CPU pinning under KVM")
725
726 target_process = psutil.Process(process_id)
727 if cpus == constants.CPU_PINNING_OFF:
728 target_process.set_cpu_affinity(range(psutil.NUM_CPUS))
729 else:
730 target_process.set_cpu_affinity(cpus)
731
732 @classmethod
733 def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
734 """Change CPU affinity for running VM according to given CPU mask.
735
736 @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
737 @type cpu_mask: string
738 @param process_id: process ID of KVM process. Used to pin entire VM
739 to physical CPUs.
740 @type process_id: int
741 @param thread_dict: map of virtual CPUs to KVM thread IDs
742 @type thread_dict: dict int:int
743
744 """
745 # Convert the string CPU mask to a list of list of int's
746 cpu_list = utils.ParseMultiCpuMask(cpu_mask)
747
748 if len(cpu_list) == 1:
749 all_cpu_mapping = cpu_list[0]
750 if all_cpu_mapping == constants.CPU_PINNING_OFF:
751 # If CPU pinning has 1 entry that's "all", then do nothing
752 pass
753 else:
754 # If CPU pinning has one non-all entry, map the entire VM to
755 # one set of physical CPUs
756 cls._SetProcessAffinity(process_id, all_cpu_mapping)
757 else:
758 # The number of vCPUs mapped should match the number of vCPUs
759 # reported by KVM. This was already verified earlier, so
760 # here only as a sanity check.
761 assert len(thread_dict) == len(cpu_list)
762
763 # For each vCPU, map it to the proper list of physical CPUs
764 for i, vcpu in enumerate(cpu_list):
765 cls._SetProcessAffinity(thread_dict[i], vcpu)
766
767 def _GetVcpuThreadIds(self, instance_name):
768 """Get a mapping of vCPU no. to thread IDs for the instance
769
770 @type instance_name: string
771 @param instance_name: instance in question
772 @rtype: dictionary of int:int
773 @return: a dictionary mapping vCPU numbers to thread IDs
774
775 """
776 result = {}
777 output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
778 for line in output.stdout.splitlines():
779 match = self._CPU_INFO_RE.search(line)
780 if not match:
781 continue
782 grp = map(int, match.groups())
783 result[grp[0]] = grp[1]
784
785 return result
786
787 def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
788 """Complete CPU pinning.
789
790 @type instance_name: string
791 @param instance_name: name of instance
792 @type cpu_mask: string
793 @param cpu_mask: CPU pinning mask as entered by user
794
795 """
796 # Get KVM process ID, to be used if need to pin entire VM
797 _, pid, _ = self._InstancePidAlive(instance_name)
798 # Get vCPU thread IDs, to be used if need to pin vCPUs separately
799 thread_dict = self._GetVcpuThreadIds(instance_name)
800 # Run CPU pinning, based on configured mask
801 self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
802
803 def ListInstances(self, hvparams=None):
804 """Get the list of running instances.
805
806 We can do this by listing our live instances directory and
807 checking whether the associated kvm process is still alive.
808
809 """
810 result = []
811 for name in os.listdir(self._PIDS_DIR):
812 if self._InstancePidAlive(name)[2]:
813 result.append(name)
814 return result
815
816 @classmethod
817 def _IsUserShutdown(cls, instance_name):
818 return os.path.exists(cls._InstanceShutdownMonitor(instance_name))
819
820 @classmethod
821 def _ClearUserShutdown(cls, instance_name):
822 utils.RemoveFile(cls._InstanceShutdownMonitor(instance_name))
823
824 def GetInstanceInfo(self, instance_name, hvparams=None):
825 """Get instance properties.
826
827 @type instance_name: string
828 @param instance_name: the instance name
829 @type hvparams: dict of strings
830 @param hvparams: hypervisor parameters to be used with this instance
831 @rtype: tuple of strings
832 @return: (name, id, memory, vcpus, stat, times)
833
834 """
835 _, pid, alive = self._InstancePidAlive(instance_name)
836 if not alive:
837 if self._IsUserShutdown(instance_name):
838 return (instance_name, -1, 0, 0, hv_base.HvInstanceState.SHUTDOWN, 0)
839 else:
840 return None
841
842 _, memory, vcpus = self._InstancePidInfo(pid)
843 istat = hv_base.HvInstanceState.RUNNING
844 times = 0
845
846 try:
847 qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
848 qmp.connect()
849 vcpus = len(qmp.Execute("query-cpus"))
850 # Will fail if ballooning is not enabled, but we can then just resort to
851 # the value above.
852 mem_bytes = qmp.Execute("query-balloon")[qmp.ACTUAL_KEY]
853 memory = mem_bytes / 1048576
854 except errors.HypervisorError:
855 pass
856
857 return (instance_name, pid, memory, vcpus, istat, times)
858
859 def GetAllInstancesInfo(self, hvparams=None):
860 """Get properties of all instances.
861
862 @type hvparams: dict of strings
863 @param hvparams: hypervisor parameters
864 @return: list of tuples (name, id, memory, vcpus, stat, times)
865
866 """
867 data = []
868 for name in os.listdir(self._PIDS_DIR):
869 try:
870 info = self.GetInstanceInfo(name)
871 except errors.HypervisorError:
872 # Ignore exceptions due to instances being shut down
873 continue
874 if info:
875 data.append(info)
876 return data
877
878 def _GenerateKVMBlockDevicesOptions(self, instance, up_hvp, kvm_disks,
879 kvmhelp, devlist):
880 """Generate KVM options regarding instance's block devices.
881
882 @type instance: L{objects.Instance}
883 @param instance: the instance object
884 @type up_hvp: dict
885 @param up_hvp: the instance's runtime hypervisor parameters
886 @type kvm_disks: list of tuples
887 @param kvm_disks: list of tuples [(disk, link_name, uri)..]
888 @type kvmhelp: string
889 @param kvmhelp: output of kvm --help
890 @type devlist: string
891 @param devlist: output of kvm -device ?
892 @rtype: list
893 @return: list of command line options eventually used by kvm executable
894
895 """
896 kernel_path = up_hvp[constants.HV_KERNEL_PATH]
897 if kernel_path:
898 boot_disk = False
899 else:
900 boot_disk = up_hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
901
902 # whether this is an older KVM version that uses the boot=on flag
903 # on devices
904 needs_boot_flag = self._BOOT_RE.search(kvmhelp)
905
906 dev_opts = []
907 device_driver = None
908 disk_type = up_hvp[constants.HV_DISK_TYPE]
909 if disk_type == constants.HT_DISK_PARAVIRTUAL:
910 if_val = ",if=%s" % self._VIRTIO
911 try:
912 if self._VIRTIO_BLK_RE.search(devlist):
913 if_val = ",if=none"
914 # will be passed in -device option as driver
915 device_driver = self._VIRTIO_BLK_PCI
916 except errors.HypervisorError, _:
917 pass
918 else:
919 if_val = ",if=%s" % disk_type
920 # AIO mode
921 aio_mode = up_hvp[constants.HV_KVM_DISK_AIO]
922 if aio_mode == constants.HT_KVM_AIO_NATIVE:
923 aio_val = ",aio=%s" % aio_mode
924 else:
925 aio_val = ""
926 # Cache mode
927 disk_cache = up_hvp[constants.HV_DISK_CACHE]
928 if instance.disk_template in constants.DTS_EXT_MIRROR:
929 if disk_cache != "none":
930 # TODO: make this a hard error, instead of a silent overwrite
931 logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
932 " to prevent shared storage corruption on migration",
933 disk_cache)
934 cache_val = ",cache=none"
935 elif disk_cache != constants.HT_CACHE_DEFAULT:
936 cache_val = ",cache=%s" % disk_cache
937 else:
938 cache_val = ""
939 for cfdev, link_name, uri in kvm_disks:
940 if cfdev.mode != constants.DISK_RDWR:
941 raise errors.HypervisorError("Instance has read-only disks which"
942 " are not supported by KVM")
943 # TODO: handle FD_LOOP and FD_BLKTAP (?)
944 boot_val = ""
945 if boot_disk:
946 dev_opts.extend(["-boot", "c"])
947 boot_disk = False
948 if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
949 boot_val = ",boot=on"
950
951 drive_uri = _GetDriveURI(cfdev, link_name, uri)
952
953 drive_val = "file=%s,format=raw%s%s%s%s" % \
954 (drive_uri, if_val, boot_val, cache_val, aio_val)
955
956 if device_driver:
957 # kvm_disks are the 4th entry of runtime file that did not exist in
958 # the past. That means that cfdev should always have pci slot and
959 # _GenerateDeviceKVMId() will not raise a exception.
960 kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK, cfdev)
961 drive_val += (",id=%s" % kvm_devid)
962 drive_val += (",bus=0,unit=%d" % cfdev.pci)
963 dev_val = ("%s,drive=%s,id=%s" %
964 (device_driver, kvm_devid, kvm_devid))
965 dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
966 dev_opts.extend(["-device", dev_val])
967
968 dev_opts.extend(["-drive", drive_val])
969
970 return dev_opts
971
972 @staticmethod
973 def _CdromOption(kvm_cmd, cdrom_disk_type, cdrom_image, cdrom_boot,
974 needs_boot_flag):
975 """Extends L{kvm_cmd} with the '-drive' option for a cdrom, and
976 optionally the '-boot' option.
977
978 Example: -drive file=cdrom.iso,media=cdrom,format=raw,if=ide -boot d
979
980 Example: -drive file=cdrom.iso,media=cdrom,format=raw,if=ide,boot=on
981
982 Example: -drive file=http://hostname.com/cdrom.iso,media=cdrom
983
984 @type kvm_cmd: string
985 @param kvm_cmd: KVM command line
986
987 @type cdrom_disk_type:
988 @param cdrom_disk_type:
989
990 @type cdrom_image:
991 @param cdrom_image:
992
993 @type cdrom_boot:
994 @param cdrom_boot:
995
996 @type needs_boot_flag:
997 @param needs_boot_flag:
998
999 """
1000 # Check that the ISO image is accessible
1001 # See https://bugs.launchpad.net/qemu/+bug/597575
1002 if utils.IsUrl(cdrom_image) and not _CheckUrl(cdrom_image):
1003 raise errors.HypervisorError("Cdrom ISO image '%s' is not accessible" %
1004 cdrom_image)
1005
1006 # set cdrom 'media' and 'format', if needed
1007 if utils.IsUrl(cdrom_image):
1008 options = ",media=cdrom"
1009 else:
1010 options = ",media=cdrom,format=raw"
1011
1012 # set cdrom 'if' type
1013 if cdrom_boot:
1014 if_val = ",if=" + constants.HT_DISK_IDE
1015 elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1016 if_val = ",if=virtio"
1017 else:
1018 if_val = ",if=" + cdrom_disk_type
1019
1020 # set boot flag, if needed
1021 boot_val = ""
1022 if cdrom_boot:
1023 kvm_cmd.extend(["-boot", "d"])
1024
1025 # whether this is an older KVM version that requires the 'boot=on' flag
1026 # on devices
1027 if needs_boot_flag:
1028 boot_val = ",boot=on"
1029
1030 # build '-drive' option
1031 drive_val = "file=%s%s%s%s" % (cdrom_image, options, if_val, boot_val)
1032 kvm_cmd.extend(["-drive", drive_val])
1033
1034 def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1035 kvmhelp):
1036 """Generate KVM information to start an instance.
1037
1038 @type kvmhelp: string
1039 @param kvmhelp: output of kvm --help
1040 @attention: this function must not have any side-effects; for
1041 example, it must not write to the filesystem, or read values
1042 from the current system the are expected to differ between
1043 nodes, since it is only run once at instance startup;
1044 actions/kvm arguments that can vary between systems should be
1045 done in L{_ExecuteKVMRuntime}
1046
1047 """
1048 # pylint: disable=R0912,R0914,R0915
1049 hvp = instance.hvparams
1050 self.ValidateParameters(hvp)
1051
1052 pidfile = self._InstancePidFile(instance.name)
1053 kvm = hvp[constants.HV_KVM_PATH]
1054 kvm_cmd = [kvm]
1055 # used just by the vnc server, if enabled
1056 kvm_cmd.extend(["-name", instance.name])
1057 kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1058
1059 smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1060 if hvp[constants.HV_CPU_CORES]:
1061 smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1062 if hvp[constants.HV_CPU_THREADS]:
1063 smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1064 if hvp[constants.HV_CPU_SOCKETS]:
1065 smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1066
1067 kvm_cmd.extend(["-smp", ",".join(smp_list)])
1068
1069 kvm_cmd.extend(["-pidfile", pidfile])
1070
1071 pci_reservations = bitarray(self._DEFAULT_PCI_RESERVATIONS)
1072
1073 # As requested by music lovers
1074 if hvp[constants.HV_SOUNDHW]:
1075 soundhw = hvp[constants.HV_SOUNDHW]
1076 # For some reason only few sound devices require a PCI slot
1077 # while the Audio controller *must* be in slot 3.
1078 # That's why we bridge this option early in command line
1079 if soundhw in self._SOUNDHW_WITH_PCI_SLOT:
1080 _ = _GetFreeSlot(pci_reservations, reserve=True)
1081 kvm_cmd.extend(["-soundhw", soundhw])
1082
1083 if hvp[constants.HV_DISK_TYPE] == constants.HT_DISK_SCSI:
1084 # The SCSI controller requires another PCI slot.
1085 _ = _GetFreeSlot(pci_reservations, reserve=True)
1086
1087 # Add id to ballon and place to the first available slot (3 or 4)
1088 addr = _GetFreeSlot(pci_reservations, reserve=True)
1089 pci_info = ",bus=pci.0,addr=%s" % hex(addr)
1090 kvm_cmd.extend(["-balloon", "virtio,id=balloon%s" % pci_info])
1091 kvm_cmd.extend(["-daemonize"])
1092 if not instance.hvparams[constants.HV_ACPI]:
1093 kvm_cmd.extend(["-no-acpi"])
1094 if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1095 constants.INSTANCE_REBOOT_EXIT:
1096 kvm_cmd.extend(["-no-reboot"])
1097
1098 mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1099 if not mversion:
1100 mversion = self._GetDefaultMachineVersion(kvm)
1101 if self._MACHINE_RE.search(kvmhelp):
1102 # TODO (2.8): kernel_irqchip and kvm_shadow_mem machine properties, as
1103 # extra hypervisor parameters. We should also investigate whether and how
1104 # shadow_mem should be considered for the resource model.
1105 if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED):
1106 specprop = ",accel=kvm"
1107 else:
1108 specprop = ""
1109 machinespec = "%s%s" % (mversion, specprop)
1110 kvm_cmd.extend(["-machine", machinespec])
1111 else:
1112 kvm_cmd.extend(["-M", mversion])
1113 if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1114 self._ENABLE_KVM_RE.search(kvmhelp)):
1115 kvm_cmd.extend(["-enable-kvm"])
1116 elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1117 self._DISABLE_KVM_RE.search(kvmhelp)):
1118 kvm_cmd.extend(["-disable-kvm"])
1119
1120 kernel_path = hvp[constants.HV_KERNEL_PATH]
1121 if kernel_path:
1122 boot_cdrom = boot_floppy = boot_network = False
1123 else:
1124 boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1125 boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1126 boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1127
1128 if startup_paused:
1129 kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1130
1131 if boot_network:
1132 kvm_cmd.extend(["-boot", "n"])
1133
1134 disk_type = hvp[constants.HV_DISK_TYPE]
1135
1136 # Now we can specify a different device type for CDROM devices.
1137 cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1138 if not cdrom_disk_type:
1139 cdrom_disk_type = disk_type
1140
1141 cdrom_image1 = hvp[constants.HV_CDROM_IMAGE_PATH]
1142 if cdrom_image1:
1143 needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1144 self._CdromOption(kvm_cmd, cdrom_disk_type, cdrom_image1, boot_cdrom,
1145 needs_boot_flag)
1146
1147 cdrom_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1148 if cdrom_image2:
1149 self._CdromOption(kvm_cmd, cdrom_disk_type, cdrom_image2, False, False)
1150
1151 floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1152 if floppy_image:
1153 options = ",format=raw,media=disk"
1154 if boot_floppy:
1155 kvm_cmd.extend(["-boot", "a"])
1156 options = "%s,boot=on" % options
1157 if_val = ",if=floppy"
1158 options = "%s%s" % (options, if_val)
1159 drive_val = "file=%s%s" % (floppy_image, options)
1160 kvm_cmd.extend(["-drive", drive_val])
1161
1162 if kernel_path:
1163 kvm_cmd.extend(["-kernel", kernel_path])
1164 initrd_path = hvp[constants.HV_INITRD_PATH]
1165 if initrd_path:
1166 kvm_cmd.extend(["-initrd", initrd_path])
1167 root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1168 hvp[constants.HV_KERNEL_ARGS]]
1169 if hvp[constants.HV_SERIAL_CONSOLE]:
1170 serial_speed = hvp[constants.HV_SERIAL_SPEED]
1171 root_append.append("console=ttyS0,%s" % serial_speed)
1172 kvm_cmd.extend(["-append", " ".join(root_append)])
1173
1174 mem_path = hvp[constants.HV_MEM_PATH]
1175 if mem_path:
1176 kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1177
1178 monitor_dev = ("unix:%s,server,nowait" %
1179 self._InstanceMonitor(instance.name))
1180 kvm_cmd.extend(["-monitor", monitor_dev])
1181 if hvp[constants.HV_SERIAL_CONSOLE]:
1182 serial_dev = ("unix:%s,server,nowait" %
1183 self._InstanceSerial(instance.name))
1184 kvm_cmd.extend(["-serial", serial_dev])
1185 else:
1186 kvm_cmd.extend(["-serial", "none"])
1187
1188 mouse_type = hvp[constants.HV_USB_MOUSE]
1189 vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1190 spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1191 spice_ip_version = None
1192
1193 kvm_cmd.extend(["-usb"])
1194
1195 if mouse_type:
1196 kvm_cmd.extend(["-usbdevice", mouse_type])
1197 elif vnc_bind_address:
1198 kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1199
1200 if vnc_bind_address:
1201 if netutils.IsValidInterface(vnc_bind_address):
1202 if_addresses = netutils.GetInterfaceIpAddresses(vnc_bind_address)
1203 if_ip4_addresses = if_addresses[constants.IP4_VERSION]
1204 if len(if_ip4_addresses) < 1:
1205 logging.error("Could not determine IPv4 address of interface %s",
1206 vnc_bind_address)
1207 else:
1208 vnc_bind_address = if_ip4_addresses[0]
1209 if netutils.IP4Address.IsValid(vnc_bind_address):
1210 if instance.network_port > constants.VNC_BASE_PORT:
1211 display = instance.network_port - constants.VNC_BASE_PORT
1212 if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1213 vnc_arg = ":%d" % (display)
1214 else:
1215 vnc_arg = "%s:%d" % (vnc_bind_address, display)
1216 else:
1217 logging.error("Network port is not a valid VNC display (%d < %d),"
1218 " not starting VNC",
1219 instance.network_port, constants.VNC_BASE_PORT)
1220 vnc_arg = "none"
1221
1222 # Only allow tls and other option when not binding to a file, for now.
1223 # kvm/qemu gets confused otherwise about the filename to use.
1224 vnc_append = ""
1225 if hvp[constants.HV_VNC_TLS]:
1226 vnc_append = "%s,tls" % vnc_append
1227 if hvp[constants.HV_VNC_X509_VERIFY]:
1228 vnc_append = "%s,x509verify=%s" % (vnc_append,
1229 hvp[constants.HV_VNC_X509])
1230 elif hvp[constants.HV_VNC_X509]:
1231 vnc_append = "%s,x509=%s" % (vnc_append,
1232 hvp[constants.HV_VNC_X509])
1233 if hvp[constants.HV_VNC_PASSWORD_FILE]:
1234 vnc_append = "%s,password" % vnc_append
1235
1236 vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1237
1238 else:
1239 vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1240
1241 kvm_cmd.extend(["-vnc", vnc_arg])
1242 elif spice_bind:
1243 # FIXME: this is wrong here; the iface ip address differs
1244 # between systems, so it should be done in _ExecuteKVMRuntime
1245 if netutils.IsValidInterface(spice_bind):
1246 # The user specified a network interface, we have to figure out the IP
1247 # address.
1248 addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1249 spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1250
1251 # if the user specified an IP version and the interface does not
1252 # have that kind of IP addresses, throw an exception
1253 if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1254 if not addresses[spice_ip_version]:
1255 raise errors.HypervisorError("SPICE: Unable to get an IPv%s address"
1256 " for %s" % (spice_ip_version,
1257 spice_bind))
1258
1259 # the user did not specify an IP version, we have to figure it out
1260 elif (addresses[constants.IP4_VERSION] and
1261 addresses[constants.IP6_VERSION]):
1262 # we have both ipv4 and ipv6, let's use the cluster default IP
1263 # version
1264 cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1265 spice_ip_version = \
1266 netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1267 elif addresses[constants.IP4_VERSION]:
1268 spice_ip_version = constants.IP4_VERSION
1269 elif addresses[constants.IP6_VERSION]:
1270 spice_ip_version = constants.IP6_VERSION
1271 else:
1272 raise errors.HypervisorError("SPICE: Unable to get an IP address"
1273 " for %s" % (spice_bind))
1274
1275 spice_address = addresses[spice_ip_version][0]
1276
1277 else:
1278 # spice_bind is known to be a valid IP address, because
1279 # ValidateParameters checked it.
1280 spice_address = spice_bind
1281
1282 spice_arg = "addr=%s" % spice_address
1283 if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1284 spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1285 (spice_arg, instance.network_port,
1286 pathutils.SPICE_CACERT_FILE))
1287 spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1288 (spice_arg, pathutils.SPICE_CERT_FILE,
1289 pathutils.SPICE_CERT_FILE))
1290 tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1291 if tls_ciphers:
1292 spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1293 else:
1294 spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1295
1296 if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1297 spice_arg = "%s,disable-ticketing" % spice_arg
1298
1299 if spice_ip_version:
1300 spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1301
1302 # Image compression options
1303 img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1304 img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1305 img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1306 if img_lossless:
1307 spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1308 if img_jpeg:
1309 spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1310 if img_zlib_glz:
1311 spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1312
1313 # Video stream detection
1314 video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1315 if video_streaming:
1316 spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1317
1318 # Audio compression, by default in qemu-kvm it is on
1319 if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1320 spice_arg = "%s,playback-compression=off" % spice_arg
1321 if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1322 spice_arg = "%s,agent-mouse=off" % spice_arg
1323 else:
1324 # Enable the spice agent communication channel between the host and the
1325 # agent.
1326 addr = _GetFreeSlot(pci_reservations, reserve=True)
1327 pci_info = ",bus=pci.0,addr=%s" % hex(addr)
1328 kvm_cmd.extend(["-device", "virtio-serial-pci,id=spice%s" % pci_info])
1329 kvm_cmd.extend([
1330 "-device",
1331 "virtserialport,chardev=spicechannel0,name=com.redhat.spice.0",
1332 ])
1333 kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1334
1335 logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1336 kvm_cmd.extend(["-spice", spice_arg])
1337
1338 else:
1339 # From qemu 1.4 -nographic is incompatible with -daemonize. The new way
1340 # also works in earlier versions though (tested with 1.1 and 1.3)
1341 if self._DISPLAY_RE.search(kvmhelp):
1342 kvm_cmd.extend(["-display", "none"])
1343 else:
1344 kvm_cmd.extend(["-nographic"])
1345
1346 if hvp[constants.HV_USE_LOCALTIME]:
1347 kvm_cmd.extend(["-localtime"])
1348
1349 if hvp[constants.HV_KVM_USE_CHROOT]:
1350 kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1351
1352 # Add qemu-KVM -cpu param
1353 if hvp[constants.HV_CPU_TYPE]:
1354 kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1355
1356 # Pass a -vga option if requested, or if spice is used, for backwards
1357 # compatibility.
1358 if hvp[constants.HV_VGA]:
1359 kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1360 elif spice_bind:
1361 kvm_cmd.extend(["-vga", "qxl"])
1362
1363 # Various types of usb devices, comma separated
1364 if hvp[constants.HV_USB_DEVICES]:
1365 for dev in hvp[constants.HV_USB_DEVICES].split(","):
1366 kvm_cmd.extend(["-usbdevice", dev])
1367
1368 # Set system UUID to instance UUID
1369 if self._UUID_RE.search(kvmhelp):
1370 kvm_cmd.extend(["-uuid", instance.uuid])
1371
1372 if hvp[constants.HV_KVM_EXTRA]:
1373 kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
1374
1375 kvm_disks = []
1376 for disk, link_name, uri in block_devices:
1377 disk.pci = _GetFreeSlot(pci_reservations, disk.pci, True)
1378 kvm_disks.append((disk, link_name, uri))
1379
1380 kvm_nics = []
1381 for nic in instance.nics:
1382 nic.pci = _GetFreeSlot(pci_reservations, nic.pci, True)
1383 kvm_nics.append(nic)
1384
1385 hvparams = hvp
1386
1387 return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
1388
1389 def _WriteKVMRuntime(self, instance_name, data):
1390 """Write an instance's KVM runtime
1391
1392 """
1393 try:
1394 utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1395 data=data)
1396 except EnvironmentError, err:
1397 raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1398
1399 def _ReadKVMRuntime(self, instance_name):
1400 """Read an instance's KVM runtime
1401
1402 """
1403 try:
1404 file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1405 except EnvironmentError, err:
1406 raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1407 return file_content
1408
1409 def _SaveKVMRuntime(self, instance, kvm_runtime):
1410 """Save an instance's KVM runtime
1411
1412 """
1413 kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1414
1415 serialized_nics = [nic.ToDict() for nic in kvm_nics]
1416 serialized_disks = [(blk.ToDict(), link, uri)
1417 for blk, link, uri in kvm_disks]
1418 serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1419 serialized_disks))
1420
1421 self._WriteKVMRuntime(instance.name, serialized_form)
1422
1423 def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1424 """Load an instance's KVM runtime
1425
1426 """
1427 if not serialized_runtime:
1428 serialized_runtime = self._ReadKVMRuntime(instance.name)
1429
1430 return _AnalyzeSerializedRuntime(serialized_runtime)
1431
1432 def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1433 """Run the KVM cmd and check for errors
1434
1435 @type name: string
1436 @param name: instance name
1437 @type kvm_cmd: list of strings
1438 @param kvm_cmd: runcmd input for kvm
1439 @type tap_fds: list of int
1440 @param tap_fds: fds of tap devices opened by Ganeti
1441
1442 """
1443 try:
1444 result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1445 finally:
1446 for fd in tap_fds:
1447 utils_wrapper.CloseFdNoError(fd)
1448
1449 if result.failed:
1450 raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1451 (name, result.fail_reason, result.output))
1452 if not self._InstancePidAlive(name)[2]:
1453 raise errors.HypervisorError("Failed to start instance %s" % name)
1454
1455 @staticmethod
1456 def _GenerateKvmTapName(nic):
1457 """Generate a TAP network interface name for a NIC.
1458
1459 See L{hv_base.GenerateTapName}.
1460
1461 For the case of the empty string, see L{OpenTap}
1462
1463 @type nic: ganeti.objects.NIC
1464 @param nic: NIC object for the name should be generated
1465
1466 @rtype: string
1467 @return: TAP network interface name, or the empty string if the
1468 NIC is not used in instance communication
1469
1470 """
1471 if nic.name is None or not \
1472 nic.name.startswith(constants.INSTANCE_COMMUNICATION_NIC_PREFIX):
1473 return ""
1474
1475 return hv_base.GenerateTapName()
1476
1477 def _GetNetworkDeviceFeatures(self, up_hvp, devlist, kvmhelp):
1478 """Get network device options to properly enable supported features.
1479
1480 Return tuple of supported and enabled tap features with nic_model.
1481 This function is called before opening a new tap device.
1482
1483 @return: (nic_model, vnet_hdr, virtio_net_queues, tap_extra, nic_extra)
1484 @rtype: tuple
1485
1486 """
1487 virtio_net_queues = 1
1488 nic_extra = ""
1489 nic_type = up_hvp[constants.HV_NIC_TYPE]
1490 tap_extra = ""
1491 vnet_hdr = False
1492 if nic_type == constants.HT_NIC_PARAVIRTUAL:
1493 nic_model = self._VIRTIO
1494 try:
1495 if self._VIRTIO_NET_RE.search(devlist):
1496 nic_model = self._VIRTIO_NET_PCI
1497 vnet_hdr = up_hvp[constants.HV_VNET_HDR]
1498 except errors.HypervisorError, _:
1499 # Older versions of kvm don't support DEVICE_LIST, but they don't
1500 # have new virtio syntax either.
1501 pass
1502
1503 if up_hvp[constants.HV_VHOST_NET]:
1504 # Check for vhost_net support.
1505 if self._VHOST_RE.search(kvmhelp):
1506 tap_extra = ",vhost=on"
1507 else:
1508 raise errors.HypervisorError("vhost_net is configured"
1509 " but it is not available")
1510 if up_hvp[constants.HV_VIRTIO_NET_QUEUES] > 1:
1511 # Check for multiqueue virtio-net support.
1512 if self._VIRTIO_NET_QUEUES_RE.search(kvmhelp):
1513 virtio_net_queues = up_hvp[constants.HV_VIRTIO_NET_QUEUES]
1514 # As advised at http://www.linux-kvm.org/page/Multiqueue formula
1515 # for calculating vector size is: vectors=2*N+1 where N is the
1516 # number of queues (HV_VIRTIO_NET_QUEUES).
1517 nic_extra = ",mq=on,vectors=%d" % (2 * virtio_net_queues + 1)
1518 else:
1519 raise errors.HypervisorError("virtio_net_queues is configured"
1520 " but it is not available")
1521 else:
1522 nic_model = nic_type
1523
1524 return (nic_model, vnet_hdr, virtio_net_queues, tap_extra, nic_extra)
1525
1526 # too many local variables
1527 # pylint: disable=R0914
1528 def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1529 """Execute a KVM cmd, after completing it with some last minute data.
1530
1531 @type incoming: tuple of strings
1532 @param incoming: (target_host_ip, port)
1533 @type kvmhelp: string
1534 @param kvmhelp: output of kvm --help
1535
1536 """
1537 # Small _ExecuteKVMRuntime hv parameters programming howto:
1538 # - conf_hvp contains the parameters as configured on ganeti. they might
1539 # have changed since the instance started; only use them if the change
1540 # won't affect the inside of the instance (which hasn't been rebooted).
1541 # - up_hvp contains the parameters as they were when the instance was
1542 # started, plus any new parameter which has been added between ganeti
1543 # versions: it is paramount that those default to a value which won't
1544 # affect the inside of the instance as well.
1545 conf_hvp = instance.hvparams
1546 name = instance.name
1547 self._CheckDown(name)
1548
1549 self._ClearUserShutdown(instance.name)
1550 self._StartKvmd(instance.hvparams)
1551
1552 temp_files = []
1553
1554 kvm_cmd, kvm_nics, up_hvp, kvm_disks = kvm_runtime
1555 # the first element of kvm_cmd is always the path to the kvm binary
1556 kvm_path = kvm_cmd[0]
1557 up_hvp = objects.FillDict(conf_hvp, up_hvp)
1558
1559 # We know it's safe to run as a different user upon migration, so we'll use
1560 # the latest conf, from conf_hvp.
1561 security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1562 if security_model == constants.HT_SM_USER:
1563 kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1564
1565 keymap = conf_hvp[constants.HV_KEYMAP]
1566 if keymap:
1567 keymap_path = self._InstanceKeymapFile(name)
1568 # If a keymap file is specified, KVM won't use its internal defaults. By
1569 # first including the "en-us" layout, an error on loading the actual
1570 # layout (e.g. because it can't be found) won't lead to a non-functional
1571 # keyboard. A keyboard with incorrect keys is still better than none.
1572 utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1573 kvm_cmd.extend(["-k", keymap_path])
1574
1575 # We have reasons to believe changing something like the nic driver/type
1576 # upon migration won't exactly fly with the instance kernel, so for nic
1577 # related parameters we'll use up_hvp
1578 tapfds = []
1579 taps = []
1580 devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1581 if not kvm_nics:
1582 kvm_cmd.extend(["-net", "none"])
1583 else:
1584 (nic_model, vnet_hdr,
1585 virtio_net_queues, tap_extra,
1586 nic_extra) = self._GetNetworkDeviceFeatures(up_hvp, devlist, kvmhelp)
1587 kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
1588 for nic_seq, nic in enumerate(kvm_nics):
1589 tapname, nic_tapfds = OpenTap(vnet_hdr=vnet_hdr,
1590 virtio_net_queues=virtio_net_queues,
1591 name=self._GenerateKvmTapName(nic))
1592 tapfds.extend(nic_tapfds)
1593 taps.append(tapname)
1594 tapfd = "%s%s" % ("fds=" if len(nic_tapfds) > 1 else "fd=",
1595 ":".join(str(fd) for fd in nic_tapfds))
1596 if kvm_supports_netdev:
1597 nic_val = "%s,mac=%s" % (nic_model, nic.mac)
1598 try:
1599 # kvm_nics already exist in old runtime files and thus there might
1600 # be some entries without pci slot (therefore try: except:)
1601 kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
1602 netdev = kvm_devid
1603 nic_val += (",id=%s,bus=pci.0,addr=%s" % (kvm_devid, hex(nic.pci)))
1604 except errors.HotplugError:
1605 netdev = "netdev%d" % nic_seq
1606 nic_val += (",netdev=%s%s" % (netdev, nic_extra))
1607 tap_val = ("type=tap,id=%s,%s%s" %
1608 (netdev, tapfd, tap_extra))
1609 kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1610 else:
1611 nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1612 nic.mac, nic_model)
1613 tap_val = "tap,vlan=%s,%s" % (nic_seq, tapfd)
1614 kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1615
1616 if incoming:
1617 target, port = incoming
1618 kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1619
1620 # Changing the vnc password doesn't bother the guest that much. At most it
1621 # will surprise people who connect to it. Whether positively or negatively
1622 # it's debatable.
1623 vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1624 vnc_pwd = None
1625 if vnc_pwd_file:
1626 try:
1627 vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1628 except EnvironmentError, err:
1629 raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1630 % (vnc_pwd_file, err))
1631
1632 if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1633 utils.EnsureDirs([(self._InstanceChrootDir(name),
1634 constants.SECURE_DIR_MODE)])
1635
1636 # Automatically enable QMP if version is >= 0.14
1637 if self._QMP_RE.search(kvmhelp):
1638 logging.debug("Enabling QMP")
1639 kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1640 self._InstanceQmpMonitor(instance.name)])
1641 # Add a second monitor for kvmd
1642 kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1643 self._InstanceKvmdMonitor(instance.name)])
1644
1645 # Configure the network now for starting instances and bridged interfaces,
1646 # during FinalizeMigration for incoming instances' routed interfaces
1647 for nic_seq, nic in enumerate(kvm_nics):
1648 if (incoming and
1649 nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1650 continue
1651 self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1652
1653 bdev_opts = self._GenerateKVMBlockDevicesOptions(instance,
1654 up_hvp,
1655 kvm_disks,
1656 kvmhelp,
1657 devlist)
1658 kvm_cmd.extend(bdev_opts)
1659 # CPU affinity requires kvm to start paused, so we set this flag if the
1660 # instance is not already paused and if we are not going to accept a
1661 # migrating instance. In the latter case, pausing is not needed.
1662 start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1663 if start_kvm_paused:
1664 kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1665
1666 # Note: CPU pinning is using up_hvp since changes take effect
1667 # during instance startup anyway, and to avoid problems when soft
1668 # rebooting the instance.
1669 cpu_pinning = False
1670 if up_hvp.get(constants.HV_CPU_MASK, None):
1671 cpu_pinning = True
1672
1673 if security_model == constants.HT_SM_POOL:
1674 ss = ssconf.SimpleStore()
1675 uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1676 all_uids = set(uidpool.ExpandUidPool(uid_pool))
1677 uid = uidpool.RequestUnusedUid(all_uids)
1678 try:
1679 username = pwd.getpwuid(uid.GetUid()).pw_name
1680 kvm_cmd.extend(["-runas", username])
1681 self._RunKVMCmd(name, kvm_cmd, tapfds)
1682 except:
1683 uidpool.ReleaseUid(uid)
1684 raise
1685 else:
1686 uid.Unlock()
1687 utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1688 else:
1689 self._RunKVMCmd(name, kvm_cmd, tapfds)
1690
1691 utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1692 constants.RUN_DIRS_MODE)])
1693 for nic_seq, tap in enumerate(taps):
1694 utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1695 data=tap)
1696
1697 if vnc_pwd:
1698 change_cmd = "change vnc password %s" % vnc_pwd
1699 self._CallMonitorCommand(instance.name, change_cmd)
1700
1701 # Setting SPICE password. We are not vulnerable to malicious passwordless
1702 # connection attempts because SPICE by default does not allow connections
1703 # if neither a password nor the "disable_ticketing" options are specified.
1704 # As soon as we send the password via QMP, that password is a valid ticket
1705 # for connection.
1706 spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1707 if spice_password_file:
1708 spice_pwd = ""
1709 try:
1710 spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1711 except EnvironmentError, err:
1712 raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1713 % (spice_password_file, err))
1714
1715 qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1716 qmp.connect()
1717 arguments = {
1718 "protocol": "spice",
1719 "password": spice_pwd,
1720 }
1721 qmp.Execute("set_password", arguments)
1722
1723 for filename in temp_files:
1724 utils.RemoveFile(filename)
1725
1726 # If requested, set CPU affinity and resume instance execution
1727 if cpu_pinning:
1728 self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1729
1730 start_memory = self._InstanceStartupMemory(instance)
1731 if start_memory < instance.beparams[constants.BE_MAXMEM]:
1732 self.BalloonInstanceMemory(instance, start_memory)
1733
1734 if start_kvm_paused:
1735 # To control CPU pinning, ballooning, and vnc/spice passwords
1736 # the VM was started in a frozen state. If freezing was not
1737 # explicitly requested resume the vm status.
1738 self._CallMonitorCommand(instance.name, self._CONT_CMD)
1739
1740 @staticmethod
1741 def _StartKvmd(hvparams):
1742 """Ensure that the Kvm daemon is running.
1743
1744 @type hvparams: dict of strings
1745 @param hvparams: hypervisor parameters
1746
1747 """
1748 if hvparams is None \
1749 or not hvparams[constants.HV_KVM_USER_SHUTDOWN] \
1750 or utils.IsDaemonAlive(constants.KVMD):
1751 return
1752
1753 result = utils.RunCmd([pathutils.DAEMON_UTIL, "start", constants.KVMD])
1754
1755 if result.failed:
1756 raise errors.HypervisorError("Failed to start KVM daemon")
1757
1758 def StartInstance(self, instance, block_devices, startup_paused):
1759 """Start an instance.
1760
1761 """
1762 self._CheckDown(instance.name)
1763 kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1764 kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1765 kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1766 startup_paused, kvmhelp)
1767 self._SaveKVMRuntime(instance, kvm_runtime)
1768 self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1769
1770 @classmethod
1771 def _CallMonitorCommand(cls, instance_name, command, timeout=None):
1772 """Invoke a command on the instance monitor.
1773
1774 """
1775 if timeout is not None:
1776 timeout_cmd = "timeout %s" % (timeout, )
1777 else:
1778 timeout_cmd = ""
1779
1780 # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1781 # version. The monitor protocol is designed for human consumption, whereas
1782 # QMP is made for programmatic usage. In the worst case QMP can also
1783 # execute monitor commands. As it is, all calls to socat take at least
1784 # 500ms and likely more: socat can't detect the end of the reply and waits
1785 # for 500ms of no data received before exiting (500 ms is the default for
1786 # the "-t" parameter).
1787 socat = ("echo %s | %s %s STDIO UNIX-CONNECT:%s" %
1788 (utils.ShellQuote(command),
1789 timeout_cmd,
1790 constants.SOCAT_PATH,
1791 utils.ShellQuote(cls._InstanceMonitor(instance_name))))
1792 result = utils.RunCmd(socat)
1793 if result.failed:
1794 msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1795 " output: %s" %
1796 (command, instance_name, result.fail_reason, result.output))
1797 raise errors.HypervisorError(msg)
1798
1799 return result
1800
1801 def _GetFreePCISlot(self, instance, dev):
1802 """Get the first available pci slot of a runnung instance.
1803
1804 """
1805 slots = bitarray(32)
1806 slots.setall(False) # pylint: disable=E1101
1807 output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
1808 for line in output.stdout.splitlines():
1809 match = self._INFO_PCI_RE.search(line)
1810 if match:
1811 slot = int(match.group(1))
1812 slots[slot] = True
1813
1814 dev.pci = _GetFreeSlot(slots)
1815
1816 def VerifyHotplugSupport(self, instance, action, dev_type):
1817 """Verifies that hotplug is supported.
1818
1819 Hotplug is *not* supported in case of:
1820 - security models and chroot (disk hotplug)
1821 - fdsend module is missing (nic hot-add)
1822
1823 @raise errors.HypervisorError: in one of the previous cases
1824
1825 """
1826 if dev_type == constants.HOTPLUG_TARGET_DISK:
1827 hvp = instance.hvparams
1828 security_model = hvp[constants.HV_SECURITY_MODEL]
1829 use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
1830 if action == constants.HOTPLUG_ACTION_ADD:
1831 if use_chroot:
1832 raise errors.HotplugError("Disk hotplug is not supported"
1833 " in case of chroot.")
1834 if security_model != constants.HT_SM_NONE:
1835 raise errors.HotplugError("Disk Hotplug is not supported in case"
1836 " security models are used.")
1837
1838 if (dev_type == constants.HOTPLUG_TARGET_NIC and
1839 action == constants.HOTPLUG_ACTION_ADD and not fdsend):
1840 raise errors.HotplugError("Cannot hot-add NIC."
1841 " fdsend python module is missing.")
1842
1843 def HotplugSupported(self, instance):
1844 """Checks if hotplug is generally supported.
1845
1846 Hotplug is *not* supported in case of:
1847 - qemu versions < 1.0
1848 - for stopped instances
1849
1850 @raise errors.HypervisorError: in one of the previous cases
1851
1852 """
1853 try:
1854 output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
1855 except errors.HypervisorError:
1856 raise errors.HotplugError("Instance is probably down")
1857
1858 # TODO: search for netdev_add, drive_add, device_add.....
1859 match = self._INFO_VERSION_RE.search(output.stdout)
1860 if not match:
1861 raise errors.HotplugError("Cannot parse qemu version via monitor")
1862
1863 v_major, v_min, _, _ = match.groups()
1864 if (int(v_major), int(v_min)) < (1, 0):
1865 raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
1866
1867 def _CallHotplugCommands(self, name, cmds):
1868 for c in cmds:
1869 self._CallMonitorCommand(name, c)
1870 time.sleep(1)
1871
1872 def _VerifyHotplugCommand(self, instance_name, device, dev_type,
1873 should_exist):
1874 """Checks if a previous hotplug command has succeeded.
1875
1876 It issues info pci monitor command and checks depending on should_exist
1877 value if an entry with PCI slot and device ID is found or not.
1878
1879 @raise errors.HypervisorError: if result is not the expected one
1880
1881 """
1882 output = self._CallMonitorCommand(instance_name, self._INFO_PCI_CMD)
1883 kvm_devid = _GenerateDeviceKVMId(dev_type, device)
1884 match = \
1885 self._FIND_PCI_DEVICE_RE(device.pci, kvm_devid).search(output.stdout)
1886 if match and not should_exist:
1887 msg = "Device %s should have been removed but is still there" % kvm_devid
1888 raise errors.HypervisorError(msg)
1889
1890 if not match and should_exist:
1891 msg = "Device %s should have been added but is missing" % kvm_devid
1892 raise errors.HypervisorError(msg)
1893
1894 logging.info("Device %s has been correctly hot-plugged", kvm_devid)
1895
1896 def HotAddDevice(self, instance, dev_type, device, extra, seq):
1897 """ Helper method to hot-add a new device
1898
1899 It gets free pci slot generates the device name and invokes the
1900 device specific method.
1901
1902 """
1903 # in case of hot-mod this is given
1904 if device.pci is None:
1905 self._GetFreePCISlot(instance, device)
1906 kvm_devid = _GenerateDeviceKVMId(dev_type, device)
1907 runtime = self._LoadKVMRuntime(instance)
1908 if dev_type == constants.HOTPLUG_TARGET_DISK:
1909 drive_uri = _GetDriveURI(device, extra[0], extra[1])
1910 cmds = ["drive_add dummy file=%s,if=none,id=%s,format=raw" %
1911 (drive_uri, kvm_devid)]
1912 cmds += ["device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
1913 (hex(device.pci), kvm_devid, kvm_devid)]
1914 elif dev_type == constants.HOTPLUG_TARGET_NIC:
1915 kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1916 kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1917 devlist = self._GetKVMOutput(kvmpath, self._KVMOPT_DEVICELIST)
1918 up_hvp = runtime[2]
1919 (_, vnet_hdr,
1920 virtio_net_queues, tap_extra,
1921 nic_extra) = self._GetNetworkDeviceFeatures(up_hvp, devlist, kvmhelp)
1922 (tap, fds) = OpenTap(vnet_hdr=vnet_hdr,
1923 virtio_net_queues=virtio_net_queues)
1924 # netdev_add don't support "fds=" when multiple fds are
1925 # requested, generate separate "fd=" string for every fd
1926 tapfd = ",".join(["fd=%s" % fd for fd in fds])
1927 self._ConfigureNIC(instance, seq, device, tap)
1928 self._PassTapFd(instance, fds, device)
1929 cmds = ["netdev_add tap,id=%s,%s%s" % (kvm_devid, tapfd, tap_extra)]
1930 args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s%s" % \
1931 (hex(device.pci), device.mac, kvm_devid, kvm_devid, nic_extra)
1932 cmds += ["device_add %s" % args]
1933 utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
1934
1935 self._CallHotplugCommands(instance.name, cmds)
1936 self._VerifyHotplugCommand(instance.name, device, dev_type, True)
1937 # update relevant entries in runtime file
1938 index = _DEVICE_RUNTIME_INDEX[dev_type]
1939 entry = _RUNTIME_ENTRY[dev_type](device, extra)
1940 runtime[index].append(entry)
1941 self._SaveKVMRuntime(instance, runtime)
1942
1943 def HotDelDevice(self, instance, dev_type, device, _, seq):
1944 """ Helper method for hot-del device
1945
1946 It gets device info from runtime file, generates the device name and
1947 invokes the device specific method.
1948
1949 """
1950 runtime = self._LoadKVMRuntime(instance)
1951 entry = _GetExistingDeviceInfo(dev_type, device, runtime)
1952 kvm_device = _RUNTIME_DEVICE[dev_type](entry)
1953 kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
1954 if dev_type == constants.HOTPLUG_TARGET_DISK:
1955 cmds = ["device_del %s" % kvm_devid]
1956 cmds += ["drive_del %s" % kvm_devid]
1957 elif dev_type == constants.HOTPLUG_TARGET_NIC:
1958 cmds = ["device_del %s" % kvm_devid]
1959 cmds += ["netdev_del %s" % kvm_devid]
1960 utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
1961 self._CallHotplugCommands(instance.name, cmds)
1962 self._VerifyHotplugCommand(instance.name, kvm_device, dev_type, False)
1963 index = _DEVICE_RUNTIME_INDEX[dev_type]
1964 runtime[index].remove(entry)
1965 self._SaveKVMRuntime(instance, runtime)
1966
1967 return kvm_device.pci
1968
1969 def HotModDevice(self, instance, dev_type, device, _, seq):
1970 """ Helper method for hot-mod device
1971
1972 It gets device info from runtime file, generates the device name and
1973 invokes the device specific method. Currently only NICs support hot-mod
1974
1975 """
1976 if dev_type == constants.HOTPLUG_TARGET_NIC:
1977 # putting it back in the same pci slot
1978 device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
1979 self.HotAddDevice(instance, dev_type, device, _, seq)
1980
1981 def _PassTapFd(self, instance, fds, nic):
1982 """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
1983
1984 """
1985 # TODO: factor out code related to unix sockets.
1986 # squash common parts between monitor and qmp
1987 kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
1988 command = "getfd %s\n" % kvm_devid
1989 logging.info("%s", fds)
1990 try:
1991 monsock = MonitorSocket(self._InstanceMonitor(instance.name))
1992 monsock.connect()
1993 fdsend.sendfds(monsock.sock, command, fds=fds)
1994 finally:
1995 monsock.close()
1996
1997 @classmethod
1998 def _ParseKVMVersion(cls, text):
1999 """Parse the KVM version from the --help output.
2000
2001 @type text: string
2002 @param text: output of kvm --help
2003 @return: (version, v_maj, v_min, v_rev)
2004 @raise errors.HypervisorError: when the KVM version cannot be retrieved
2005
2006 """
2007 match = cls._VERSION_RE.search(text.splitlines()[0])
2008 if not match:
2009 raise errors.HypervisorError("Unable to get KVM version")
2010
2011 v_all = match.group(0)
2012 v_maj = int(match.group(1))
2013 v_min = int(match.group(2))
2014 if match.group(4):
2015 v_rev = int(match.group(4))
2016 else:
2017 v_rev = 0
2018 return (v_all, v_maj, v_min, v_rev)
2019
2020 @classmethod
2021 def _GetKVMOutput(cls, kvm_path, option):
2022 """Return the output of a kvm invocation
2023
2024 @type kvm_path: string
2025 @param kvm_path: path to the kvm executable
2026 @type option: a key of _KVMOPTS_CMDS
2027 @param option: kvm option to fetch the output from
2028 @return: output a supported kvm invocation
2029 @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2030
2031 """
2032 assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2033
2034 optlist, can_fail = cls._KVMOPTS_CMDS[option]
2035
2036 result = utils.RunCmd([kvm_path] + optlist)
2037 if result.failed and not can_fail:
2038 raise errors.HypervisorError("Unable to get KVM %s output" %
2039 " ".join(optlist))
2040 return result.output
2041
2042 @classmethod
2043 def _GetKVMVersion(cls, kvm_path):
2044 """Return the installed KVM version.
2045
2046 @return: (version, v_maj, v_min, v_rev)
2047 @raise errors.HypervisorError: when the KVM version cannot be retrieved
2048
2049 """
2050 return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2051
2052 @classmethod
2053 def _GetDefaultMachineVersion(cls, kvm_path):
2054 """Return the default hardware revision (e.g. pc-1.1)
2055
2056 """
2057 output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2058 match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2059 if match:
2060 return match.group(1)
2061 else:
2062 return "pc"
2063
2064 @classmethod
2065 def _StopInstance(cls, instance, force=False, name=None, timeout=None):
2066 """Stop an instance.
2067
2068 """
2069 assert(timeout is None or force is not None)
2070
2071 if name is not None and not force:
2072 raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2073 if name is None:
2074 name = instance.name
2075 acpi = instance.hvparams[constants.HV_ACPI]
2076 else:
2077 acpi = False
2078 _, pid, alive = cls._InstancePidAlive(name)
2079 if pid > 0 and alive:
2080 if force or not acpi:
2081 utils.KillProcess(pid)
2082 else:
2083 cls._CallMonitorCommand(name, "system_powerdown", timeout)
2084 cls._ClearUserShutdown(instance.name)
2085
2086 def StopInstance(self, instance, force=False, retry=False, name=None,
2087 timeout=None):
2088 """Stop an instance.
2089
2090 """
2091 self._StopInstance(instance, force, name=name, timeout=timeout)
2092
2093 def CleanupInstance(self, instance_name):
2094 """Cleanup after a stopped instance
2095
2096 """
2097 pidfile, pid, alive = self._InstancePidAlive(instance_name)
2098 if pid > 0 and alive:
2099 raise errors.HypervisorError("Cannot cleanup a live instance")
2100 self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2101 self._ClearUserShutdown(instance_name)
2102
2103 def RebootInstance(self, instance):
2104 """Reboot an instance.
2105
2106 """
2107 # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2108 # socket the instance will stop, but now power up again. So we'll resort
2109 # to shutdown and restart.
2110 _, _, alive = self._InstancePidAlive(instance.name)
2111 if not alive:
2112 raise errors.HypervisorError("Failed to reboot instance %s:"
2113 " not running" % instance.name)
2114 # StopInstance will delete the saved KVM runtime so:
2115 # ...first load it...
2116 kvm_runtime = self._LoadKVMRuntime(instance)
2117 # ...now we can safely call StopInstance...
2118 if not self.StopInstance(instance):
2119 self.StopInstance(instance, force=True)
2120 # ...and finally we can save it again, and execute it...
2121 self._SaveKVMRuntime(instance, kvm_runtime)
2122 kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2123 kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2124 self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2125
2126 def MigrationInfo(self, instance):
2127 """Get instance information to perform a migration.
2128
2129 @type instance: L{objects.Instance}
2130 @param instance: instance to be migrated
2131 @rtype: string
2132 @return: content of the KVM runtime file
2133
2134 """
2135 return self._ReadKVMRuntime(instance.name)
2136
2137 def AcceptInstance(self, instance, info, target):
2138 """Prepare to accept an instance.
2139
2140 @type instance: L{objects.Instance}
2141 @param instance: instance to be accepted
2142 @type info: string
2143 @param info: content of the KVM runtime file on the source node
2144 @type target: string
2145 @param target: target host (usually ip), on this node
2146
2147 """
2148 kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2149 incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2150 kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2151 kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2152 self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2153 incoming=incoming_address)
2154
2155 def FinalizeMigrationDst(self, instance, info, success):
2156 """Finalize the instance migration on the target node.
2157
2158 Stop the incoming mode KVM.
2159
2160 @type instance: L{objects.Instance}
2161 @param instance: instance whose migration is being finalized
2162
2163 """
2164 if success:
2165 kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2166 kvm_nics = kvm_runtime[1]
2167
2168 for nic_seq, nic in enumerate(kvm_nics):
2169 if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2170 # Bridged interfaces have already been configured
2171 continue
2172 try:
2173 tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2174 except EnvironmentError, err:
2175 logging.warning("Failed to find host interface for %s NIC #%d: %s",
2176 instance.name, nic_seq, str(err))
2177 continue
2178 try:
2179 self._ConfigureNIC(instance, nic_seq, nic, tap)
2180 except errors.HypervisorError, err:
2181 logging.warning(str(err))
2182
2183 self._WriteKVMRuntime(instance.name, info)
2184 else:
2185 self.StopInstance(instance, force=True)
2186
2187 def MigrateInstance(self, cluster_name, instance, target, live):
2188 """Migrate an instance to a target node.
2189
2190 The migration will not be attempted if the instance is not
2191 currently running.
2192
2193 @type cluster_name: string
2194 @param cluster_name: name of the cluster
2195 @type instance: L{objects.Instance}
2196 @param instance: the instance to be migrated
2197 @type target: string
2198 @param target: ip address of the target node
2199 @type live: boolean
2200 @param live: perform a live migration
2201
2202 """
2203 instance_name = instance.name
2204 port = instance.hvparams[constants.HV_MIGRATION_PORT]
2205 _, _, alive = self._InstancePidAlive(instance_name)
2206 if not alive:
2207 raise errors.HypervisorError("Instance not running, cannot migrate")
2208
2209 if not live:
2210 self._CallMonitorCommand(instance_name, "stop")
2211
2212 migrate_command = ("migrate_set_speed %dm" %
2213 instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2214 self._CallMonitorCommand(instance_name, migrate_command)
2215
2216 migrate_command = ("migrate_set_downtime %dms" %
2217 instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2218 self._CallMonitorCommand(instance_name, migrate_command)
2219
2220 migration_caps = instance.hvparams[constants.HV_KVM_MIGRATION_CAPS]
2221 if migration_caps:
2222 for c in migration_caps.split(_MIGRATION_CAPS_DELIM):
2223 migrate_command = ("migrate_set_capability %s on" % c)
2224 self._CallMonitorCommand(instance_name, migrate_command)
2225
2226 migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2227 self._CallMonitorCommand(instance_name, migrate_command)
2228
2229 def FinalizeMigrationSource(self, instance, success, live):
2230 """Finalize the instance migration on the source node.
2231
2232 @type instance: L{objects.Instance}
2233 @param instance: the instance that was migrated
2234 @type success: bool
2235 @param success: whether the migration succeeded or not
2236 @type live: bool
2237 @param live: whether the user requested a live migration or not
2238
2239 """
2240 if success:
2241 pidfile, pid, _ = self._InstancePidAlive(instance.name)
2242 utils.KillProcess(pid)
2243 self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2244 elif live:
2245 self._CallMonitorCommand(instance.name, self._CONT_CMD)
2246 self._ClearUserShutdown(instance.name)
2247
2248 def GetMigrationStatus(self, instance):
2249 """Get the migration status
2250
2251 @type instance: L{objects.Instance}
2252 @param instance: the instance that is being migrated
2253 @rtype: L{objects.MigrationStatus}
2254 @return: the status of the current migration (one of
2255 L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2256 progress info that can be retrieved from the hypervisor
2257
2258 """
2259 info_command = "info migrate"
2260 for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2261 result = self._CallMonitorCommand(instance.name, info_command)
2262 match = self._MIGRATION_STATUS_RE.search(result.stdout)
2263 if not match:
2264 if not result.stdout:
2265 logging.info("KVM: empty 'info migrate' result")
2266 else:
2267 logging.warning("KVM: unknown 'info migrate' result: %s",
2268 result.stdout)
2269 else:
2270 status = match.group(1)
2271 if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2272 migration_status = objects.MigrationStatus(status=status)
2273 match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2274 if match:
2275 migration_status.transferred_ram = match.group("transferred")
2276 migration_status.total_ram = match.group("total")
2277
2278 return migration_status
2279
2280 logging.warning("KVM: unknown migration status '%s'", status)
2281
2282 time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2283
2284 return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2285
2286 def BalloonInstanceMemory(self, instance, mem):
2287 """Balloon an instance memory to a certain value.
2288
2289 @type instance: L{objects.Instance}
2290 @param instance: instance to be accepted
2291 @type mem: int
2292 @param mem: actual memory size to use for instance runtime
2293
2294 """
2295 self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2296
2297 def GetNodeInfo(self, hvparams=None):
2298 """Return information about the node.
2299
2300 @type hvparams: dict of strings
2301 @param hvparams: hypervisor parameters, not used in this class
2302
2303 @return: a dict as returned by L{BaseHypervisor.GetLinuxNodeInfo} plus
2304 the following keys:
2305 - hv_version: the hypervisor version in the form (major, minor,
2306 revision)
2307
2308 """
2309 result = self.GetLinuxNodeInfo()
2310 kvmpath = constants.KVM_PATH
2311 if hvparams is not None:
2312 kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2313 _, v_major, v_min, v_rev = self._GetKVMVersion(kvmpath)
2314 result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2315 return result
2316
2317 @classmethod
2318 def GetInstanceConsole(cls, instance, primary_node, node_group,
2319 hvparams, beparams):
2320 """Return a command for connecting to the console of an instance.
2321
2322 """
2323 if hvparams[constants.HV_SERIAL_CONSOLE]:
2324 cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2325 constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2326 utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2327 "STDIO,%s" % cls._SocatUnixConsoleParams(),
2328 "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2329 ndparams = node_group.FillND(primary_node)
2330 return objects.InstanceConsole(instance=instance.name,
2331 kind=constants.CONS_SSH,
2332 host=primary_node.name,
2333 port=ndparams.get(constants.ND_SSH_PORT),
2334 user=constants.SSH_CONSOLE_USER,
2335 command=cmd)
2336
2337 vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2338 if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2339 display = instance.network_port - constants.VNC_BASE_PORT
2340 return objects.InstanceConsole(instance=instance.name,
2341 kind=constants.CONS_VNC,
2342 host=vnc_bind_address,
2343 port=instance.network_port,
2344 display=display)
2345
2346 spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2347 if spice_bind:
2348 return objects.InstanceConsole(instance=instance.name,
2349 kind=constants.CONS_SPICE,
2350 host=spice_bind,
2351 port=instance.network_port)
2352
2353 return objects.InstanceConsole(instance=instance.name,
2354 kind=constants.CONS_MESSAGE,
2355 message=("No serial shell for instance %s" %
2356 instance.name))
2357
2358 def Verify(self, hvparams=None):
2359 """Verify the hypervisor.
2360
2361 Check that the required binaries exist.
2362
2363 @type hvparams: dict of strings
2364 @param hvparams: hypervisor parameters to be verified against, not used here
2365
2366 @return: Problem description if something is wrong, C{None} otherwise
2367
2368 """
2369 msgs = []
2370 kvmpath = constants.KVM_PATH
2371 if hvparams is not None:
2372 kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2373 if not os.path.exists(kvmpath):
2374 msgs.append("The KVM binary ('%s') does not exist" % kvmpath)
2375 if not os.path.exists(constants.SOCAT_PATH):
2376 msgs.append("The socat binary ('%s') does not exist" %
2377 constants.SOCAT_PATH)
2378
2379 return self._FormatVerifyResults(msgs)
2380
2381 @classmethod
2382 def CheckParameterSyntax(cls, hvparams):
2383 """Check the given parameters for validity.
2384
2385 @type hvparams: dict of strings
2386 @param hvparams: hypervisor parameters
2387 @raise errors.HypervisorError: when a parameter is not valid
2388
2389 """
2390 super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2391
2392 kernel_path = hvparams[constants.HV_KERNEL_PATH]
2393 if kernel_path:
2394 if not hvparams[constants.HV_ROOT_PATH]:
2395 raise errors.HypervisorError("Need a root partition for the instance,"
2396 " if a kernel is defined")
2397
2398 if (hvparams[constants.HV_VNC_X509_VERIFY] and
2399 not hvparams[constants.HV_VNC_X509]):
2400 raise errors.HypervisorError("%s must be defined, if %s is" %
2401 (constants.HV_VNC_X509,
2402 constants.HV_VNC_X509_VERIFY))
2403
2404 if hvparams[constants.HV_SERIAL_CONSOLE]:
2405 serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2406 valid_speeds = constants.VALID_SERIAL_SPEEDS
2407 if not serial_speed or serial_speed not in valid_speeds:
2408 raise errors.HypervisorError("Invalid serial console speed, must be"
2409 " one of: %s" %
2410 utils.CommaJoin(valid_speeds))
2411
2412 boot_order = hvparams[constants.HV_BOOT_ORDER]
2413 if (boot_order == constants.HT_BO_CDROM and
2414 not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2415 raise errors.HypervisorError("Cannot boot from cdrom without an"
2416 " ISO path")
2417
2418 security_model = hvparams[constants.HV_SECURITY_MODEL]
2419 if security_model == constants.HT_SM_USER:
2420 if not hvparams[constants.HV_SECURITY_DOMAIN]:
2421 raise errors.HypervisorError("A security domain (user to run kvm as)"
2422 " must be specified")
2423 elif (security_model == constants.HT_SM_NONE or
2424 security_model == constants.HT_SM_POOL):
2425 if hvparams[constants.HV_SECURITY_DOMAIN]:
2426 raise errors.HypervisorError("Cannot have a security domain when the"
2427 " security model is 'none' or 'pool'")
2428
2429 spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2430 spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2431 if spice_bind:
2432 if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2433 # if an IP version is specified, the spice_bind parameter must be an
2434 # IP of that family
2435 if (netutils.IP4Address.IsValid(spice_bind) and
2436 spice_ip_version != constants.IP4_VERSION):
2437 raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2438 " the specified IP version is %s" %
2439 (spice_bind, spice_ip_version))
2440
2441 if (netutils.IP6Address.IsValid(spice_bind) and
2442 spice_ip_version != constants.IP6_VERSION):
2443 raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2444 " the specified IP version is %s" %
2445 (spice_bind, spice_ip_version))
2446 else:
2447 # All the other SPICE parameters depend on spice_bind being set. Raise an
2448 # error if any of them is set without it.
2449 for param in _SPICE_ADDITIONAL_PARAMS:
2450 if hvparams[param]:
2451 raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2452 (param, constants.HV_KVM_SPICE_BIND))
2453
2454 @classmethod
2455 def ValidateParameters(cls, hvparams):
2456 """Check the given parameters for validity.
2457
2458 @type hvparams: dict of strings
2459 @param hvparams: hypervisor parameters
2460 @raise errors.HypervisorError: when a parameter is not valid
2461
2462 """
2463 super(KVMHypervisor, cls).ValidateParameters(hvparams)
2464
2465 kvm_path = hvparams[constants.HV_KVM_PATH]
2466
2467 security_model = hvparams[constants.HV_SECURITY_MODEL]
2468 if security_model == constants.HT_SM_USER:
2469 username = hvparams[constants.HV_SECURITY_DOMAIN]
2470 try:
2471 pwd.getpwnam(username)
2472 except KeyError:
2473 raise errors.HypervisorError("Unknown security domain user %s"
2474 % username)
2475 vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2476 if vnc_bind_address:
2477 bound_to_addr = netutils.IP4Address.IsValid(vnc_bind_address)
2478 is_interface = netutils.IsValidInterface(vnc_bind_address)
2479 is_path = utils.IsNormAbsPath(vnc_bind_address)
2480 if not bound_to_addr and not is_interface and not is_path:
2481 raise errors.HypervisorError("VNC: The %s parameter must be either"
2482 " a valid IP address, an interface name,"
2483 " or an absolute path" %
2484 constants.HV_KVM_SPICE_BIND)
2485
2486 spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2487 if spice_bind:
2488 # only one of VNC and SPICE can be used currently.
2489 if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2490 raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2491 " only one of them can be used at a"
2492 " given time")
2493
2494 # check that KVM supports SPICE
2495 kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2496 if not cls._SPICE_RE.search(kvmhelp):
2497 raise errors.HypervisorError("SPICE is configured, but it is not"
2498 " supported according to 'kvm --help'")
2499
2500 # if spice_bind is not an IP address, it must be a valid interface
2501 bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2502 netutils.IP6Address.IsValid(spice_bind))
2503 if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2504 raise errors.HypervisorError("SPICE: The %s parameter must be either"
2505 " a valid IP address or interface name" %
2506 constants.HV_KVM_SPICE_BIND)
2507
2508 machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2509 if machine_version:
2510 output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2511 if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2512 raise errors.HypervisorError("Unsupported machine version: %s" %
2513 machine_version)
2514
2515 @classmethod
2516 def PowercycleNode(cls, hvparams=None):
2517 """KVM powercycle, just a wrapper over Linux powercycle.
2518
2519 @type hvparams: dict of strings
2520 @param hvparams: hypervisor parameters to be used on this node
2521
2522 """
2523 cls.LinuxPowercycle()