virt.init: fix disk target names

Fixes issue #57477.
This commit is contained in:
Cédric Bosdonnat 2020-05-27 18:07:30 +02:00 committed by Daniel Wozniak
parent 694043e38d
commit ad7f60147a
3 changed files with 31 additions and 9 deletions

1
changelog/57477.fixed Normal file
View file

@ -0,0 +1 @@
virt.init fix the disk target names

View file

@ -717,15 +717,17 @@ def _gen_xml(
context["disks"] = []
disk_bus_map = {"virtio": "vd", "xen": "xvd", "fdc": "fd", "ide": "hd"}
targets = []
for i, disk in enumerate(diskp):
prefix = disk_bus_map.get(disk["model"], "sd")
disk_context = {
"device": disk.get("device", "disk"),
"target_dev": "{}{}".format(prefix, string.ascii_lowercase[i]),
"target_dev": _get_disk_target(targets, len(diskp), prefix),
"disk_bus": disk["model"],
"format": disk.get("format", "raw"),
"index": str(i),
}
targets.append(disk_context["target_dev"])
if disk.get("source_file"):
url = urlparse(disk["source_file"])
if not url.scheme or not url.hostname:
@ -2173,6 +2175,21 @@ def _diff_lists(old, new, comparator):
return diff
def _get_disk_target(targets, disks_count, prefix):
"""
Compute the disk target name for a given prefix.
:param targets: the list of already computed targets
:param disks: the number of disks
:param prefix: the prefix of the target name, i.e. "hd"
"""
for i in range(disks_count):
ret = "{}{}".format(prefix, string.ascii_lowercase[i])
if ret not in targets:
return ret
return None
def _diff_disk_lists(old, new):
"""
Compare disk definitions to extract the changes and fix target devices
@ -2189,11 +2206,7 @@ def _diff_disk_lists(old, new):
target_node = disk.find("target")
target = target_node.get("dev")
prefix = [item for item in prefixes if target.startswith(item)][0]
new_target = [
"{}{}".format(prefix, string.ascii_lowercase[i])
for i in range(len(new))
if "{}{}".format(prefix, string.ascii_lowercase[i]) not in targets
][0]
new_target = _get_disk_target(targets, len(new), prefix)
target_node.set("dev", new_target)
targets.append(new_target)

View file

@ -799,7 +799,10 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
self.assertEqual(root.find("vcpu").text, "1")
self.assertEqual(root.find("memory").text, str(512 * 1024))
self.assertEqual(root.find("memory").attrib["unit"], "KiB")
self.assertTrue(len(root.findall(".//disk")) == 2)
disks = root.findall(".//disk")
self.assertTrue(len(disks) == 2)
self.assertEqual(disks[0].find("target").get("dev"), "vda")
self.assertEqual(disks[1].find("target").get("dev"), "vdb")
self.assertTrue(len(root.findall(".//interface")) == 2)
def test_disk_profile_kvm_disk_pool(self):
@ -1143,11 +1146,15 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
"""
Test virt._gen_xml(), generating a cdrom device (different disk type, no source)
"""
self.mock_conn.storagePoolLookupByName.return_value.XMLDesc.return_value = (
"<pool type='dir'/>"
)
diskp = virt._disk_profile(
self.mock_conn,
None,
"kvm",
[
{"name": "system", "pool": "default"},
{
"name": "tested",
"device": "cdrom",
@ -1168,12 +1175,13 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
self.mock_conn, "hello", 1, 512, diskp, nicp, "kvm", "hvm", "x86_64",
)
root = ET.fromstring(xml_data)
disk = root.findall(".//disk")[0]
disk = root.findall(".//disk")[1]
self.assertEqual(disk.get("type"), "file")
self.assertEqual(disk.attrib["device"], "cdrom")
self.assertIsNone(disk.find("source"))
self.assertEqual(disk.find("target").get("dev"), "hda")
disk = root.findall(".//disk")[1]
disk = root.findall(".//disk")[2]
self.assertEqual(disk.get("type"), "network")
self.assertEqual(disk.attrib["device"], "cdrom")
self.assertEqual(