79 |
79 |
constants.HV_KVM_SPICE_USE_TLS,
|
80 |
80 |
])
|
81 |
81 |
|
|
82 |
# below constants show the format of runtime file
|
|
83 |
# the nics are in second possition, while the disks in 4th (last)
|
|
84 |
# moreover disk entries are stored in tupples of L{objects.Disk}, dev_path
|
|
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, None)
|
|
105 |
}
|
|
106 |
|
|
107 |
|
|
108 |
def _GetExistingDeviceInfo(dev_type, device, runtime):
|
|
109 |
"""Helper function to get an existing device inside the runtime file
|
|
110 |
|
|
111 |
Used when an instance is running. Load kvm runtime file and search
|
|
112 |
for a device based on its type and uuid.
|
|
113 |
|
|
114 |
@type dev_type: sting
|
|
115 |
@param dev_type: device type of param dev
|
|
116 |
@type device: L{objects.Disk} or L{objects.NIC}
|
|
117 |
@param device: the device object for which we generate a kvm name
|
|
118 |
@type runtime: tuple (cmd, nics, hvparams, disks)
|
|
119 |
@param runtime: the runtime data to search for the device
|
|
120 |
@raise errors.HotplugError: in case the requested device does not
|
|
121 |
exist (e.g. device has been added without --hotplug option) or
|
|
122 |
device info has not pci slot (e.g. old devices in the cluster)
|
|
123 |
|
|
124 |
"""
|
|
125 |
index = _DEVICE_RUNTIME_INDEX[dev_type]
|
|
126 |
found = _FIND_RUNTIME_ENTRY[dev_type](device, runtime[index])
|
|
127 |
if not found:
|
|
128 |
raise errors.HotplugError("Cannot find runtime info for %s with UUID %s" %
|
|
129 |
(dev_type, device.uuid))
|
|
130 |
|
|
131 |
return found[0]
|
|
132 |
|
|
133 |
|
|
134 |
def _AnalyzeSerializedRuntime(serialized_runtime):
|
|
135 |
"""Return runtime entries for a serialized runtime file
|
|
136 |
|
|
137 |
@type serialized_runtime: string
|
|
138 |
@param serialized_runtime: raw text data read from actual runtime file
|
|
139 |
@return: (cmd, nics, hvparams, bdevs)
|
|
140 |
@rtype: list
|
|
141 |
|
|
142 |
"""
|
|
143 |
loaded_runtime = serializer.Load(serialized_runtime)
|
|
144 |
if len(loaded_runtime) == 3:
|
|
145 |
serialized_blockdevs = []
|
|
146 |
kvm_cmd, serialized_nics, hvparams = loaded_runtime
|
|
147 |
else:
|
|
148 |
kvm_cmd, serialized_nics, hvparams, serialized_blockdevs = loaded_runtime
|
|
149 |
|
|
150 |
kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
|
|
151 |
block_devices = [(objects.Disk.FromDict(sdisk), link, uri)
|
|
152 |
for sdisk, link, uri in serialized_blockdevs]
|
|
153 |
|
|
154 |
return (kvm_cmd, kvm_nics, hvparams, block_devices)
|
|
155 |
|
82 |
156 |
|
83 |
157 |
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
|
84 |
158 |
"""Retrieves supported TUN features from file descriptor.
|
... | ... | |
1418 |
1492 |
if hvp[constants.HV_KVM_EXTRA]:
|
1419 |
1493 |
kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
|
1420 |
1494 |
|
1421 |
|
bdev_opts = self._GenerateKVMBlockDevicesOptions(instance,
|
1422 |
|
block_devices,
|
1423 |
|
kvmhelp)
|
1424 |
|
kvm_cmd.extend(bdev_opts)
|
1425 |
|
# Save the current instance nics, but defer their expansion as parameters,
|
1426 |
|
# as we'll need to generate executable temp files for them.
|
1427 |
|
kvm_nics = instance.nics
|
|
1495 |
kvm_disks = []
|
|
1496 |
for disk, dev_path in block_devices:
|
|
1497 |
kvm_disks.append((disk, dev_path))
|
|
1498 |
|
|
1499 |
kvm_nics = []
|
|
1500 |
for nic in instance.nics:
|
|
1501 |
kvm_nics.append(nic)
|
|
1502 |
|
1428 |
1503 |
hvparams = hvp
|
1429 |
1504 |
|
1430 |
|
return (kvm_cmd, kvm_nics, hvparams)
|
|
1505 |
return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
|
1431 |
1506 |
|
1432 |
1507 |
def _WriteKVMRuntime(self, instance_name, data):
|
1433 |
1508 |
"""Write an instance's KVM runtime
|
... | ... | |
1453 |
1528 |
"""Save an instance's KVM runtime
|
1454 |
1529 |
|
1455 |
1530 |
"""
|
1456 |
|
kvm_cmd, kvm_nics, hvparams = kvm_runtime
|
|
1531 |
kvm_cmd, kvm_nics, hvparams, block_devices = kvm_runtime
|
|
1532 |
|
1457 |
1533 |
serialized_nics = [nic.ToDict() for nic in kvm_nics]
|
1458 |
|
serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
|
|
1534 |
serialized_blockdevs = [(blk.ToDict(), link, uri)
|
|
1535 |
for blk, link, uri in block_devices]
|
|
1536 |
serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
|
|
1537 |
serialized_blockdevs))
|
|
1538 |
|
1459 |
1539 |
self._WriteKVMRuntime(instance.name, serialized_form)
|
1460 |
1540 |
|
1461 |
1541 |
def _LoadKVMRuntime(self, instance, serialized_runtime=None):
|
... | ... | |
1464 |
1544 |
"""
|
1465 |
1545 |
if not serialized_runtime:
|
1466 |
1546 |
serialized_runtime = self._ReadKVMRuntime(instance.name)
|
1467 |
|
loaded_runtime = serializer.Load(serialized_runtime)
|
1468 |
|
kvm_cmd, serialized_nics, hvparams = loaded_runtime
|
1469 |
|
kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
|
1470 |
|
return (kvm_cmd, kvm_nics, hvparams)
|
|
1547 |
|
|
1548 |
return _AnalyzeSerializedRuntime(serialized_runtime)
|
1471 |
1549 |
|
1472 |
1550 |
def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
|
1473 |
1551 |
"""Run the KVM cmd and check for errors
|
... | ... | |
1492 |
1570 |
if not self._InstancePidAlive(name)[2]:
|
1493 |
1571 |
raise errors.HypervisorError("Failed to start instance %s" % name)
|
1494 |
1572 |
|
|
1573 |
# 52/50 local variables
|
|
1574 |
# pylint: disable=R0914
|
1495 |
1575 |
def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
|
1496 |
1576 |
"""Execute a KVM cmd, after completing it with some last minute data.
|
1497 |
1577 |
|
... | ... | |
1515 |
1595 |
|
1516 |
1596 |
temp_files = []
|
1517 |
1597 |
|
1518 |
|
kvm_cmd, kvm_nics, up_hvp = kvm_runtime
|
|
1598 |
kvm_cmd, kvm_nics, up_hvp, block_devices = kvm_runtime
|
1519 |
1599 |
# the first element of kvm_cmd is always the path to the kvm binary
|
1520 |
1600 |
kvm_path = kvm_cmd[0]
|
1521 |
1601 |
up_hvp = objects.FillDict(conf_hvp, up_hvp)
|
... | ... | |
1619 |
1699 |
continue
|
1620 |
1700 |
self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
|
1621 |
1701 |
|
|
1702 |
bdev_opts = self._GenerateKVMBlockDevicesOptions(instance,
|
|
1703 |
block_devices,
|
|
1704 |
kvmhelp)
|
|
1705 |
kvm_cmd.extend(bdev_opts)
|
1622 |
1706 |
# CPU affinity requires kvm to start paused, so we set this flag if the
|
1623 |
1707 |
# instance is not already paused and if we are not going to accept a
|
1624 |
1708 |
# migrating instance. In the latter case, pausing is not needed.
|