diff --git a/nova/network/neutron.py b/nova/network/neutron.py index 7eee8cd79dac..9ce3ab6191f2 100644 --- a/nova/network/neutron.py +++ b/nova/network/neutron.py @@ -1595,12 +1595,13 @@ class API: pf_mac = pci_dev.sriov_cap.get('pf_mac_address') vf_num = pci_dev.sriov_cap.get('vf_num') card_serial_number = pci_dev.card_serial_number - if all((pf_mac, vf_num, card_serial_number)): - vf_profile.update({ - 'card_serial_number': card_serial_number, - 'pf_mac_address': pf_mac, - 'vf_num': vf_num, - }) + + if card_serial_number is not None: + vf_profile['card_serial_number'] = card_serial_number + if pf_mac is not None: + vf_profile['pf_mac_address'] = pf_mac + if vf_num is not None: + vf_profile['vf_num'] = vf_num # Update port binding capabilities using PCI device's network # capabilities if they exist. diff --git a/nova/tests/functional/libvirt/test_pci_sriov_servers.py b/nova/tests/functional/libvirt/test_pci_sriov_servers.py index f5a97df5b918..d1a32771ebd1 100644 --- a/nova/tests/functional/libvirt/test_pci_sriov_servers.py +++ b/nova/tests/functional/libvirt/test_pci_sriov_servers.py @@ -521,6 +521,8 @@ class SRIOVServersTest(_PCIServersWithMigrationTestBase): 'pci_vendor_info': '8086:1515', 'pci_slot': '0000:81:00.2', 'physical_network': 'physnet4', + 'pf_mac_address': '52:54:00:1e:59:c6', + 'vf_num': 1 }, port['binding:profile'], ) @@ -1017,6 +1019,8 @@ class SRIOVServersTest(_PCIServersWithMigrationTestBase): # matching one) 'pci_slot': '0000:81:00.4', 'physical_network': 'physnet4', + 'pf_mac_address': '52:54:00:1e:59:c6', + 'vf_num': 1 }, port['binding:profile'], ) @@ -1062,6 +1066,8 @@ class SRIOVServersTest(_PCIServersWithMigrationTestBase): 'pci_vendor_info': '8086:1515', 'pci_slot': '0000:81:00.2', 'physical_network': 'physnet4', + 'pf_mac_address': '52:54:00:1e:59:c6', + 'vf_num': 1, }, port['binding:profile'], ) diff --git a/nova/tests/unit/network/test_neutron.py b/nova/tests/unit/network/test_neutron.py index a9aa501a1346..767f83363999 100644 --- a/nova/tests/unit/network/test_neutron.py +++ b/nova/tests/unit/network/test_neutron.py @@ -8627,6 +8627,73 @@ class TestAPIPortbinding(TestAPIBase): self.assertEqual(call_args['port']['binding:profile'], {'key': 'val'}) + def test__get_vf_pci_device_profile_without_serial_num(self): + mydev = objects.PciDevice( + address='foo', + compute_node_id='123', + extra_info={ + 'capabilities': jsonutils.dumps({ + 'sriov': { + 'pf_mac_address': '52:54:00:1e:59:c6', + 'vf_num': 1, + }, + 'network': ['gso', 'sg', 'tso', 'tx'], + }), + }, + ) + self.assertEqual(self.api._get_vf_pci_device_profile(mydev), + {'pf_mac_address': '52:54:00:1e:59:c6', + 'vf_num': 1, + 'capabilities': ['gso', 'sg', 'tso', 'tx']}) + + def test__get_vf_pci_device_profile_without_pf_mac_addr(self): + mydev = objects.PciDevice( + address='foo', + compute_node_id='123', + extra_info={ + 'capabilities': jsonutils.dumps({ + 'vpd': {'card_serial_number': 'MT2113X00000'}, + 'sriov': {'vf_num': 1}, + 'network': ['gso', 'sg', 'tso', 'tx'], + }), + }, + ) + self.assertEqual(self.api._get_vf_pci_device_profile(mydev), + {'card_serial_number': 'MT2113X00000', + 'vf_num': 1, + 'capabilities': ['gso', 'sg', 'tso', 'tx']}) + + def test__get_vf_pci_device_profile_without_vf_num(self): + mydev = objects.PciDevice( + address='foo', + compute_node_id='123', + extra_info={ + 'capabilities': jsonutils.dumps({ + 'vpd': {'card_serial_number': 'MT2113X00000'}, + 'sriov': {'pf_mac_address': '52:54:00:1e:59:c6'}, + 'network': ['gso', 'sg', 'tso', 'tx'], + }), + }, + ) + self.assertEqual(self.api._get_vf_pci_device_profile(mydev), + {'card_serial_number': 'MT2113X00000', + 'pf_mac_address': '52:54:00:1e:59:c6', + 'capabilities': ['gso', 'sg', 'tso', 'tx']}) + + def test__get_vf_pci_device_profile_with_dev_capabilities(self): + mydev = objects.PciDevice( + address='foo', + compute_node_id='123', + extra_info={ + 'capabilities': jsonutils.dumps({ + 'sriov': {}, + 'network': ['gso', 'sg', 'tso', 'tx'], + }), + }, + ) + self.assertEqual(self.api._get_vf_pci_device_profile(mydev), + {'capabilities': ['gso', 'sg', 'tso', 'tx']}) + class TestAllocateForInstance(test.NoDBTestCase): def setUp(self):