summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBalazs Gibizer <gibi@redhat.com>2022-07-15 12:43:58 +0200
committerBalazs Gibizer <gibi@redhat.com>2023-01-11 12:32:07 +0100
commit4954f993680c75fd9d3d507f2dcd00300c9b3d44 (patch)
tree3d19a68c11d0032ac3d9a54eedce7a25ad8734dc
parenta45cf404bf71eac32641d88350a32cf92ae0eb53 (diff)
downloadnova-4954f993680c75fd9d3d507f2dcd00300c9b3d44.tar.gz
Reproduce bug 1981813 in func env
There stable/yoga only change in test_pci_sriov_servers.py due to unittest.mock switch[1] only happened in zed. [1] https://review.opendev.org/q/topic:unittest.mock+status:merged+project:openstack/nova Related-Bug: #1981813 Change-Id: I9367b7ed475917bdb05eb3f209ce1a4e646534e2 (cherry picked from commit f8c91eb75fc5504a37fc3b4be1d65d33dbc9b511)
-rw-r--r--nova/tests/fixtures/libvirt.py9
-rw-r--r--nova/tests/functional/libvirt/test_pci_sriov_servers.py74
2 files changed, 80 insertions, 3 deletions
diff --git a/nova/tests/fixtures/libvirt.py b/nova/tests/fixtures/libvirt.py
index 0684bae7dd..5ccf01e40f 100644
--- a/nova/tests/fixtures/libvirt.py
+++ b/nova/tests/fixtures/libvirt.py
@@ -2225,9 +2225,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 c228fb04cf..c1618751a9 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
@@ -951,6 +952,79 @@ 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.
+ with mock.patch(
+ 'nova.pci.utils.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