Revision 58502c9e lib/hypervisor/hv_kvm.py
b/lib/hypervisor/hv_kvm.py | ||
---|---|---|
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. |
Also available in: Unified diff