diff --git a/nova/tests/fixtures/libvirt.py b/nova/tests/fixtures/libvirt.py index 65513e295d..41885f3245 100644 --- a/nova/tests/fixtures/libvirt.py +++ b/nova/tests/fixtures/libvirt.py @@ -917,6 +917,10 @@ def _parse_disk_info(element): disk_info['target_dev'] = target.get('dev') disk_info['target_bus'] = target.get('bus') + alias = element.find('./alias') + if alias is not None: + disk_info['alias'] = alias.get('name') + return disk_info @@ -962,6 +966,10 @@ def _parse_nic_info(element): if target is not None: nic_info['target_dev'] = target.get('dev') + alias = element.find('./alias') + if alias is not None: + nic_info['alias'] = alias.get('name') + return nic_info @@ -979,6 +987,10 @@ def _parse_hostdev_info(element): hostdev_info['slot'] = address.get('slot') hostdev_info['function'] = address.get('function') + alias = element.find('./alias') + if alias is not None: + hostdev_info['alias'] = alias.get('name') + return hostdev_info @@ -1222,8 +1234,16 @@ class Domain(object): if device_nodes is not None: disks_info = [] disks = device_nodes.findall('./disk') - for disk in disks: - disks_info += [_parse_disk_info(disk)] + for idx, disk in enumerate(disks): + disk_info = _parse_disk_info(disk) + + alias = disk.find('./alias') + if alias is not None: + disk_info['alias'] = alias.get('name') + else: + disk_info['alias'] = f'disk{idx}' + + disks_info.append(disk_info) devices['disks'] = disks_info # Manage shares @@ -1235,7 +1255,7 @@ class Domain(object): nics_info = [] nics = device_nodes.findall('./interface') - for nic in nics: + for idx, nic in enumerate(nics): nic_info = {} nic_info['type'] = nic.get('type') @@ -1243,6 +1263,12 @@ class Domain(object): if mac is not None: nic_info['mac'] = mac.get('address') + alias = nic.find('./alias') + if alias is not None: + nic_info['alias'] = alias.get('name') + else: + nic_info['alias'] = f'net{idx}' + source = nic.find('./source') if source is not None: if nic_info['type'] == 'network': @@ -1409,16 +1435,25 @@ class Domain(object): if xml.startswith(" + +
@@ -1563,6 +1601,7 @@ class Domain(object): # this branch covers hardware offloaded ovs with vdpa nics += ''' +
@@ -1572,6 +1611,7 @@ class Domain(object): elif 'source' in nic: nics += ''' +
+
diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 4ef3055be8..0e12e1c3e5 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -10726,17 +10726,22 @@ class LibvirtConnTestCase(test.NoDBTestCase, drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) instance = objects.Instance(**self.test_instance) volume_id = uuids.volume - alias_xml = '' % vconfig.make_libvirt_device_alias( - volume_id) + if use_alias: + alias = vconfig.make_libvirt_device_alias(volume_id) + else: + # if we haven't created our own alias, libvirt will generate one + # for us + alias = 'virtio-disk0' + mock_xml_with_disk = """ - %(alias)s + -""" % {'alias': use_alias and alias_xml or ''} +""" % {'alias': alias} mock_xml_without_disk = """ @@ -10781,10 +10786,10 @@ class LibvirtConnTestCase(test.NoDBTestCase, mock_get_domain.assert_called_with(instance) xml = """ - %(alias)s + - """ % {'alias': use_alias and alias_xml or ''} + """ % {'alias': alias} # we expect two separate detach calls self.assertEqual(2, mock_dom.detachDeviceFlags.call_count) # one for the persistent domain @@ -26094,6 +26099,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin): + @@ -26109,6 +26115,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin): expected_cfg.parse_str(""" + @@ -26250,6 +26257,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin): + @@ -26258,6 +26266,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin): + @@ -26272,6 +26281,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin): expected.parse_str(""" + diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index b5adcd3c89..b0a143ac83 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -2673,6 +2673,12 @@ class LibvirtDriver(driver.ComputeDriver): synchronously. :raises DeviceDetachFailed: if libvirt sent DeviceRemovalFailedEvent """ + if dev.alias is None: + # our event handler needs a device alias, and we should never get + # here without one + msg = 'Device %s has no alias. This should not happen.' + raise exception.InternalError(msg % dev) + # So we will issue an detach to libvirt and we will wait for an # event from libvirt about the result. We need to set up the event # handling before the detach to avoid missing the event if libvirt