diff options
author | Balazs Gibizer <gibi@redhat.com> | 2022-07-15 12:43:58 +0200 |
---|---|---|
committer | Balazs Gibizer <gibi@redhat.com> | 2022-09-08 09:15:43 +0200 |
commit | f8c91eb75fc5504a37fc3b4be1d65d33dbc9b511 (patch) | |
tree | aa1a5e52385306c9447d70deeb6e88bc4319b627 | |
parent | df366cab7cb72bf60490d056cfd7b8da34b648e9 (diff) | |
download | nova-f8c91eb75fc5504a37fc3b4be1d65d33dbc9b511.tar.gz |
Reproduce bug 1981813 in func env
Related-Bug: #1981813
Change-Id: I9367b7ed475917bdb05eb3f209ce1a4e646534e2
-rw-r--r-- | nova/tests/fixtures/libvirt.py | 9 | ||||
-rw-r--r-- | nova/tests/functional/libvirt/test_pci_sriov_servers.py | 72 |
2 files changed, 78 insertions, 3 deletions
diff --git a/nova/tests/fixtures/libvirt.py b/nova/tests/fixtures/libvirt.py index b20ce17b5f..5d20e7d54f 100644 --- a/nova/tests/fixtures/libvirt.py +++ b/nova/tests/fixtures/libvirt.py @@ -2234,9 +2234,12 @@ class LibvirtFixture(fixtures.Fixture): # libvirt driver needs to call out to the filesystem to get the # parent_ifname for the SRIOV VFs. - self.useFixture(fixtures.MockPatch( - 'nova.pci.utils.get_ifname_by_pci_address', - return_value='fake_pf_interface_name')) + self.mock_get_ifname_by_pci_address = self.useFixture( + fixtures.MockPatch( + "nova.pci.utils.get_ifname_by_pci_address", + return_value="fake_pf_interface_name", + ) + ).mock self.useFixture(fixtures.MockPatch( 'nova.pci.utils.get_mac_by_pci_address', diff --git a/nova/tests/functional/libvirt/test_pci_sriov_servers.py b/nova/tests/functional/libvirt/test_pci_sriov_servers.py index c45621efd8..3364aeec42 100644 --- a/nova/tests/functional/libvirt/test_pci_sriov_servers.py +++ b/nova/tests/functional/libvirt/test_pci_sriov_servers.py @@ -28,6 +28,7 @@ from oslo_utils import units import nova from nova import context +from nova import exception from nova.network import constants from nova import objects from nova.objects import fields @@ -1042,6 +1043,77 @@ class SRIOVServersTest(_PCIServersWithMigrationTestBase): ], ) + def test_change_bound_port_vnic_type_kills_compute_at_restart(self): + """Create a server with a direct port and change the vnic_type of the + bound port to macvtap. Then restart the compute service. + + As the vnic_type is changed on the port but the vif_type is hwveb + instead of macvtap the vif plug logic will try to look up the netdev + of the parent VF. Howvere that VF consumed by the instance so the + netdev does not exists. This causes that the compute service will fail + with an exception during startup + """ + pci_info = fakelibvirt.HostPCIDevicesInfo(num_pfs=1, num_vfs=2) + self.start_compute(pci_info=pci_info) + + # create a direct port + port = self.neutron.network_4_port_1 + self.neutron.create_port({'port': port}) + + # create a server using the VF via neutron + server = self._create_server(networks=[{'port': port['id']}]) + + # update the vnic_type of the port in neutron + port = copy.deepcopy(port) + port['binding:vnic_type'] = 'macvtap' + self.neutron.update_port(port['id'], {"port": port}) + + compute = self.computes['compute1'] + + # Force an update on the instance info cache to ensure nova gets the + # information about the updated port + with context.target_cell( + context.get_admin_context(), + self.host_mappings['compute1'].cell_mapping + ) as cctxt: + compute.manager._heal_instance_info_cache(cctxt) + + def fake_get_ifname_by_pci_address(pci_addr: str, pf_interface=False): + # we want to fail the netdev lookup only if the pci_address is + # already consumed by our instance. So we look into the instance + # definition to see if the device is attached to the instance as VF + conn = compute.manager.driver._host.get_connection() + dom = conn.lookupByUUIDString(server['id']) + dev = dom._def['devices']['nics'][0] + lookup_addr = pci_addr.replace(':', '_').replace('.', '_') + if ( + dev['type'] == 'hostdev' and + dev['source'] == 'pci_' + lookup_addr + ): + # nova tried to look up the netdev of an already consumed VF. + # So we have to fail + raise exception.PciDeviceNotFoundById(id=pci_addr) + + # We need to simulate the actual failure manually as in our functional + # environment all the PCI lookup is mocked. In reality nova tries to + # look up the netdev of the pci device on the host used by the port as + # the parent of the macvtap. However, as the originally direct port is + # bound to the instance, the VF pci device is already consumed by the + # instance and therefore there is no netdev for the VF. + self.libvirt.mock_get_ifname_by_pci_address.side_effect = ( + fake_get_ifname_by_pci_address + ) + # This is bug 1981813 as the compute service fails to start with an + # exception. + # Nova cannot prevent the vnic_type change on a bound port. Neutron + # should prevent that instead. But the nova-compute should still + # be able to start up and only log an ERROR for this instance in + # inconsistent state. + self.assertRaises( + exception.PciDeviceNotFoundById, + self.restart_compute_service, 'compute1' + ) + class SRIOVAttachDetachTest(_PCIServersTestBase): # no need for aliases as these test will request SRIOV via neutron |