Skip to content

Commit 4954f99

Browse files
committed
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 f8c91eb)
1 parent a45cf40 commit 4954f99

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

nova/tests/fixtures/libvirt.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2225,9 +2225,12 @@ def setUp(self):
22252225

22262226
# libvirt driver needs to call out to the filesystem to get the
22272227
# parent_ifname for the SRIOV VFs.
2228-
self.useFixture(fixtures.MockPatch(
2229-
'nova.pci.utils.get_ifname_by_pci_address',
2230-
return_value='fake_pf_interface_name'))
2228+
self.mock_get_ifname_by_pci_address = self.useFixture(
2229+
fixtures.MockPatch(
2230+
"nova.pci.utils.get_ifname_by_pci_address",
2231+
return_value="fake_pf_interface_name",
2232+
)
2233+
).mock
22312234

22322235
self.useFixture(fixtures.MockPatch(
22332236
'nova.pci.utils.get_mac_by_pci_address',

nova/tests/functional/libvirt/test_pci_sriov_servers.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import nova
3030
from nova import context
31+
from nova import exception
3132
from nova.network import constants
3233
from nova import objects
3334
from nova.objects import fields
@@ -951,6 +952,79 @@ def test_create_server_after_change_in_nonsriov_pf_to_sriov_pf(self):
951952
],
952953
)
953954

955+
def test_change_bound_port_vnic_type_kills_compute_at_restart(self):
956+
"""Create a server with a direct port and change the vnic_type of the
957+
bound port to macvtap. Then restart the compute service.
958+
959+
As the vnic_type is changed on the port but the vif_type is hwveb
960+
instead of macvtap the vif plug logic will try to look up the netdev
961+
of the parent VF. Howvere that VF consumed by the instance so the
962+
netdev does not exists. This causes that the compute service will fail
963+
with an exception during startup
964+
"""
965+
pci_info = fakelibvirt.HostPCIDevicesInfo(num_pfs=1, num_vfs=2)
966+
self.start_compute(pci_info=pci_info)
967+
968+
# create a direct port
969+
port = self.neutron.network_4_port_1
970+
self.neutron.create_port({'port': port})
971+
972+
# create a server using the VF via neutron
973+
server = self._create_server(networks=[{'port': port['id']}])
974+
975+
# update the vnic_type of the port in neutron
976+
port = copy.deepcopy(port)
977+
port['binding:vnic_type'] = 'macvtap'
978+
self.neutron.update_port(port['id'], {"port": port})
979+
980+
compute = self.computes['compute1']
981+
982+
# Force an update on the instance info cache to ensure nova gets the
983+
# information about the updated port
984+
with context.target_cell(
985+
context.get_admin_context(),
986+
self.host_mappings['compute1'].cell_mapping
987+
) as cctxt:
988+
compute.manager._heal_instance_info_cache(cctxt)
989+
990+
def fake_get_ifname_by_pci_address(pci_addr: str, pf_interface=False):
991+
# we want to fail the netdev lookup only if the pci_address is
992+
# already consumed by our instance. So we look into the instance
993+
# definition to see if the device is attached to the instance as VF
994+
conn = compute.manager.driver._host.get_connection()
995+
dom = conn.lookupByUUIDString(server['id'])
996+
dev = dom._def['devices']['nics'][0]
997+
lookup_addr = pci_addr.replace(':', '_').replace('.', '_')
998+
if (
999+
dev['type'] == 'hostdev' and
1000+
dev['source'] == 'pci_' + lookup_addr
1001+
):
1002+
# nova tried to look up the netdev of an already consumed VF.
1003+
# So we have to fail
1004+
raise exception.PciDeviceNotFoundById(id=pci_addr)
1005+
1006+
# We need to simulate the actual failure manually as in our functional
1007+
# environment all the PCI lookup is mocked. In reality nova tries to
1008+
# look up the netdev of the pci device on the host used by the port as
1009+
# the parent of the macvtap. However, as the originally direct port is
1010+
# bound to the instance, the VF pci device is already consumed by the
1011+
# instance and therefore there is no netdev for the VF.
1012+
with mock.patch(
1013+
'nova.pci.utils.get_ifname_by_pci_address',
1014+
side_effect=fake_get_ifname_by_pci_address,
1015+
):
1016+
# This is bug 1981813 as the compute service fails to start with an
1017+
# exception.
1018+
# Nova cannot prevent the vnic_type change on a bound port. Neutron
1019+
# should prevent that instead. But the nova-compute should still
1020+
# be able to start up and only log an ERROR for this instance in
1021+
# inconsistent state.
1022+
self.assertRaises(
1023+
exception.PciDeviceNotFoundById,
1024+
self.restart_compute_service,
1025+
'compute1',
1026+
)
1027+
9541028

9551029
class SRIOVAttachDetachTest(_PCIServersTestBase):
9561030
# no need for aliases as these test will request SRIOV via neutron

0 commit comments

Comments
 (0)