Merge "Store pf_mac_address and vf_num in extra_info"
This commit is contained in:
commit
17755cc438
|
@ -84,7 +84,6 @@ from nova.objects import fields
|
|||
from nova.objects import instance as obj_instance
|
||||
from nova.objects import migrate_data as migrate_data_obj
|
||||
from nova.pci import request as pci_req_module
|
||||
from nova.pci import utils as pci_utils
|
||||
from nova.pci import whitelist
|
||||
from nova import safe_utils
|
||||
from nova.scheduler.client import query
|
||||
|
@ -10926,11 +10925,9 @@ class ComputeManager(manager.Manager):
|
|||
# tagged as remote-managed have a serial in PCI VPD.
|
||||
profile['card_serial_number'] = pci_dev.card_serial_number
|
||||
if profile.get('pf_mac_address'):
|
||||
profile['pf_mac_address'] = pci_utils.get_mac_by_pci_address(
|
||||
pci_dev.parent_addr)
|
||||
profile['pf_mac_address'] = pci_dev.sriov_cap['pf_mac_address']
|
||||
if profile.get('vf_num'):
|
||||
profile['vf_num'] = pci_utils.get_vf_num_by_pci_address(
|
||||
pci_dev.address)
|
||||
profile['vf_num'] = pci_dev.sriov_cap['vf_num']
|
||||
|
||||
mig_vif.profile = profile
|
||||
LOG.debug("Updating migrate VIF profile for port %(port_id)s:"
|
||||
|
|
|
@ -1571,40 +1571,16 @@ class API:
|
|||
forwarding.
|
||||
"""
|
||||
vf_profile: ty.Dict[str, ty.Union[str, int]] = {}
|
||||
try:
|
||||
pf_mac = pci_utils.get_mac_by_pci_address(pci_dev.parent_addr)
|
||||
except (exception.PciDeviceNotFoundById) as e:
|
||||
LOG.debug(
|
||||
"Could not determine PF MAC address for a VF with"
|
||||
" addr %(addr)s, error: %(e)s",
|
||||
{"addr": pci_dev.address, "e": e})
|
||||
# NOTE(dmitriis): we do not raise here since not all PFs will
|
||||
# have netdevs even when VFs are netdevs (see LP: #1915255). The
|
||||
# rest of the fields (VF number and card serial) are not enough
|
||||
# to fully identify the VF so they are not populated either.
|
||||
return vf_profile
|
||||
try:
|
||||
vf_num = pci_utils.get_vf_num_by_pci_address(
|
||||
pci_dev.address)
|
||||
except exception.PciDeviceNotFoundById as e:
|
||||
# This is unlikely to happen because the kernel has a common SR-IOV
|
||||
# code that creates physfn symlinks, however, it would be better
|
||||
# to avoid raising an exception here and simply warn an operator
|
||||
# that things did not go as planned.
|
||||
LOG.warning(
|
||||
"Could not determine a VF logical number for a VF"
|
||||
" with addr %(addr)s, error: %(e)s", {
|
||||
"addr": pci_dev.address, "e": e})
|
||||
return vf_profile
|
||||
|
||||
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 card_serial_number:
|
||||
if all((pf_mac, vf_num, card_serial_number)):
|
||||
vf_profile.update({
|
||||
'card_serial_number': card_serial_number
|
||||
'card_serial_number': card_serial_number,
|
||||
'pf_mac_address': pf_mac,
|
||||
'vf_num': vf_num,
|
||||
})
|
||||
vf_profile.update({
|
||||
'pf_mac_address': pf_mac,
|
||||
'vf_num': vf_num,
|
||||
})
|
||||
return vf_profile
|
||||
|
||||
def _get_pci_device_profile(self, pci_dev):
|
||||
|
|
|
@ -517,6 +517,12 @@ class PciDevice(base.NovaPersistentObject, base.NovaObject):
|
|||
caps = jsonutils.loads(caps_json)
|
||||
return caps.get('vpd', {}).get('card_serial_number')
|
||||
|
||||
@property
|
||||
def sriov_cap(self):
|
||||
caps_json = self.extra_info.get('capabilities', '{}')
|
||||
caps = jsonutils.loads(caps_json)
|
||||
return caps.get('sriov', {})
|
||||
|
||||
|
||||
@base.NovaObjectRegistry.register
|
||||
class PciDeviceList(base.ObjectListBase, base.NovaObject):
|
||||
|
|
|
@ -2185,6 +2185,27 @@ _fake_NodeDevXml = {
|
|||
<capability type='80203'/>
|
||||
</capability>
|
||||
</device>""", # noqa:E501
|
||||
"net_enp130s0f0v0_36_33_10_a3_94_65": """
|
||||
<device>
|
||||
<name>net_enp130s0f0v0_36_33_10_a3_94_64</name>
|
||||
<path>/sys/devices/pci0002:80/0002:80:03.0/0002:82:00.3/net/enp130s0f0v0</path>
|
||||
<parent>pci_0002_82_00_3</parent>
|
||||
<capability type='net'>
|
||||
<interface>enp130s0f0v0</interface>
|
||||
<address>36:33:10:a3:94:65</address>
|
||||
<link state='down'/>
|
||||
<feature name='rx'/>
|
||||
<feature name='tx'/>
|
||||
<feature name='sg'/>
|
||||
<feature name='tso'/>
|
||||
<feature name='gso'/>
|
||||
<feature name='gro'/>
|
||||
<feature name='rxvlan'/>
|
||||
<feature name='txvlan'/>
|
||||
<feature name='rxhash'/>
|
||||
<capability type='80203'/>
|
||||
</capability>
|
||||
</device>""", # noqa:E501
|
||||
}
|
||||
|
||||
_fake_NodeDevXml_parents = {
|
||||
|
|
|
@ -294,8 +294,6 @@ 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'],
|
||||
)
|
||||
|
@ -538,8 +536,6 @@ class SRIOVServersTest(_PCIServersWithMigrationTestBase):
|
|||
# matching one)
|
||||
'pci_slot': '0000:81:01.4',
|
||||
'physical_network': 'physnet4',
|
||||
'pf_mac_address': '52:54:00:1e:59:c6',
|
||||
'vf_num': 1,
|
||||
},
|
||||
port['binding:profile'],
|
||||
)
|
||||
|
@ -572,8 +568,6 @@ 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'],
|
||||
)
|
||||
|
|
|
@ -7697,78 +7697,22 @@ class TestAPIPortbinding(TestAPIBase):
|
|||
'address': '0000:0a:00.1',
|
||||
'parent_addr': '0000:0a:00.0',
|
||||
'card_serial_number': 'MT2113X00000',
|
||||
'sriov_cap': {
|
||||
'pf_mac_address': '52:54:00:1e:59:c6',
|
||||
'vf_num': 1,
|
||||
},
|
||||
'dev_type': obj_fields.PciDeviceType.SRIOV_VF,
|
||||
}
|
||||
PciDevice = collections.namedtuple('PciDevice',
|
||||
['vendor_id', 'product_id', 'address',
|
||||
'card_serial_number', 'dev_type',
|
||||
'parent_addr'])
|
||||
'card_serial_number', 'sriov_cap',
|
||||
'dev_type', 'parent_addr'])
|
||||
mydev = PciDevice(**pci_dev)
|
||||
self.assertEqual(self.api._get_vf_pci_device_profile(mydev),
|
||||
{'pf_mac_address': '52:54:00:1e:59:c6',
|
||||
'vf_num': 1,
|
||||
'card_serial_number': 'MT2113X00000'})
|
||||
|
||||
@mock.patch.object(
|
||||
pci_utils, 'get_mac_by_pci_address',
|
||||
new=mock.MagicMock(
|
||||
side_effect=exception.PciDeviceNotFoundById(id='0000:0a:00.1'))
|
||||
)
|
||||
def test__get_vf_pci_device_profile_invalid_pf_address(self):
|
||||
pci_dev = {'vendor_id': 'a2d6',
|
||||
'product_id': '15b3',
|
||||
'address': '0000:0a:00.1',
|
||||
'parent_addr': '0000:0a:00.0',
|
||||
'card_serial_number': 'MT2113X00000',
|
||||
'dev_type': obj_fields.PciDeviceType.SRIOV_VF,
|
||||
}
|
||||
PciDevice = collections.namedtuple('PciDevice',
|
||||
['vendor_id', 'product_id', 'address',
|
||||
'card_serial_number', 'dev_type',
|
||||
'parent_addr'])
|
||||
mydev = PciDevice(**pci_dev)
|
||||
self.assertEqual(self.api._get_vf_pci_device_profile(mydev), {})
|
||||
|
||||
@mock.patch.object(
|
||||
pci_utils, 'get_vf_num_by_pci_address',
|
||||
new=mock.MagicMock(
|
||||
side_effect=exception.PciDeviceNotFoundById(id='0000:0a:00.0'))
|
||||
)
|
||||
@mock.patch.object(
|
||||
pci_utils, 'get_mac_by_pci_address',
|
||||
new=mock.MagicMock(side_effect=(lambda vf_a: {
|
||||
'0000:0a:00.0': '52:54:00:1e:59:c6'}.get(vf_a))))
|
||||
def test__get_vf_pci_device_profile_invalid_vf_address(self):
|
||||
pci_dev = {'vendor_id': 'a2d6',
|
||||
'product_id': '15b3',
|
||||
'address': '0000:0a:00.1',
|
||||
'parent_addr': '0000:0a:00.0',
|
||||
'card_serial_number': 'MT2113X00000',
|
||||
'dev_type': obj_fields.PciDeviceType.SRIOV_VF,
|
||||
}
|
||||
PciDevice = collections.namedtuple('PciDevice',
|
||||
['vendor_id', 'product_id', 'address',
|
||||
'card_serial_number', 'dev_type',
|
||||
'parent_addr'])
|
||||
mydev = PciDevice(**pci_dev)
|
||||
vf_profile = self.api._get_vf_pci_device_profile(mydev)
|
||||
self.assertEqual(vf_profile, {})
|
||||
|
||||
def test__get_vf_pci_device_profile_not_vf_address(self):
|
||||
pci_dev = {'vendor_id': 'a2d6',
|
||||
'product_id': '15b3',
|
||||
'address': '0000:0a:00.1',
|
||||
'parent_addr': None,
|
||||
'card_serial_number': 'MT2113X00000',
|
||||
'dev_type': obj_fields.PciDeviceType.SRIOV_VF,
|
||||
}
|
||||
PciDevice = collections.namedtuple('PciDevice',
|
||||
['vendor_id', 'product_id', 'address',
|
||||
'card_serial_number', 'dev_type',
|
||||
'parent_addr'])
|
||||
mydev = PciDevice(**pci_dev)
|
||||
self.assertEqual(self.api._get_vf_pci_device_profile(mydev), {})
|
||||
|
||||
@mock.patch.object(
|
||||
neutronapi.API, '_get_vf_pci_device_profile',
|
||||
new=mock.MagicMock(side_effect=(
|
||||
|
|
|
@ -1113,6 +1113,10 @@ Active: 8381604 kB
|
|||
expect_vf = ["rx", "tx", "sg", "tso", "gso", "gro", "rxvlan", "txvlan"]
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
|
||||
@mock.patch.object(pci_utils, 'get_mac_by_pci_address',
|
||||
new=mock.MagicMock(
|
||||
side_effect=exception.PciDeviceNotFoundById(
|
||||
'0000:04:00.3')))
|
||||
@mock.patch.object(pci_utils, 'get_ifname_by_pci_address')
|
||||
def test_get_pcidev_info_non_nic(self, mock_get_ifname):
|
||||
dev_name = "pci_0000_04_11_7"
|
||||
|
@ -1184,7 +1188,9 @@ Active: 8381604 kB
|
|||
"parent_ifname": "ens1",
|
||||
"capabilities": {
|
||||
"network": ["rx", "tx", "sg", "tso", "gso", "gro",
|
||||
"rxvlan", "txvlan"]},
|
||||
"rxvlan", "txvlan"],
|
||||
"sriov": {"pf_mac_address": "52:54:00:1e:59:c6",
|
||||
"vf_num": 1}},
|
||||
}
|
||||
self.assertEqual(expect_vf, actual_vf)
|
||||
|
||||
|
@ -1202,7 +1208,9 @@ Active: 8381604 kB
|
|||
"parent_addr": '0000:04:00.3',
|
||||
"capabilities": {
|
||||
"network": ["rx", "tx", "sg", "tso", "gso", "gro",
|
||||
"rxvlan", "txvlan"]},
|
||||
"rxvlan", "txvlan"],
|
||||
"sriov": {"pf_mac_address": "52:54:00:1e:59:c6",
|
||||
"vf_num": 1}},
|
||||
"parent_ifname": "ens1",
|
||||
}
|
||||
self.assertEqual(expect_vf, actual_vf)
|
||||
|
@ -1284,6 +1292,8 @@ Active: 8381604 kB
|
|||
"capabilities": {
|
||||
"network": ["rx", "tx", "sg", "tso", "gso", "gro", "rxvlan",
|
||||
"txvlan", "rxhash"],
|
||||
"sriov": {"pf_mac_address": "52:54:00:1e:59:c6",
|
||||
"vf_num": 1},
|
||||
# Should be obtained from the parent PF in this case.
|
||||
"vpd": {"card_serial_number": "MT2113X00000"}},
|
||||
}
|
||||
|
@ -1323,6 +1333,12 @@ Active: 8381604 kB
|
|||
"vendor_id": "15b3",
|
||||
"label": "label_15b3_101e",
|
||||
"dev_type": obj_fields.PciDeviceType.SRIOV_VF,
|
||||
'parent_ifname': 'ens1',
|
||||
"capabilities": {
|
||||
"network": ["rx", "tx", "sg", "tso", "gso", "gro",
|
||||
"rxvlan", "txvlan", "rxhash"],
|
||||
"sriov": {"pf_mac_address": "52:54:00:1e:59:c6",
|
||||
"vf_num": 1}},
|
||||
}
|
||||
|
||||
self.assertEqual(expect_vf, actual_vf)
|
||||
|
|
|
@ -1380,6 +1380,37 @@ class Host(object):
|
|||
vpd_info = {'card_serial_number': card_serial_number}
|
||||
return vpd_info
|
||||
|
||||
def _get_sriov_netdev_details(
|
||||
device_dict: dict,
|
||||
device: 'libvirt.virNodeDevice',
|
||||
) -> ty.Dict[str, ty.Dict[str, ty.Any]]:
|
||||
"""Get SR-IOV related information"""
|
||||
sriov_info: ty.Dict[str, ty.Any] = {}
|
||||
|
||||
if device_dict.get('dev_type') != fields.PciDeviceType.SRIOV_VF:
|
||||
return sriov_info
|
||||
|
||||
pf_addr = device_dict['parent_addr']
|
||||
|
||||
# A netdev VF may be associated with a PF which does not have a
|
||||
# netdev as described in LP #1915255.
|
||||
try:
|
||||
sriov_info.update({
|
||||
'pf_mac_address': pci_utils.get_mac_by_pci_address(pf_addr)
|
||||
})
|
||||
except exception.PciDeviceNotFoundById:
|
||||
LOG.debug(f'Could not get a PF mac for {pf_addr}')
|
||||
# For the purposes Nova uses this information currently,
|
||||
# having both a PF MAC and a VF number is needed so we return
|
||||
# an empty dict if a PF MAC is not available.
|
||||
return {}
|
||||
|
||||
vf_num = pci_utils.get_vf_num_by_pci_address(
|
||||
device_dict['address'])
|
||||
|
||||
sriov_info.update({'vf_num': vf_num})
|
||||
return sriov_info
|
||||
|
||||
def _get_device_capabilities(
|
||||
device_dict: dict,
|
||||
device: 'libvirt.virNodeDevice',
|
||||
|
@ -1398,6 +1429,11 @@ class Host(object):
|
|||
pcinet_info = self._get_pcinet_info(device, net_devs)
|
||||
if pcinet_info:
|
||||
caps['network'] = pcinet_info
|
||||
# Only attempt to get SR-IOV details if a VF is a netdev
|
||||
# because there are no use cases for other dev types yet.
|
||||
sriov_caps = _get_sriov_netdev_details(device_dict, dev)
|
||||
if sriov_caps:
|
||||
caps['sriov'] = sriov_caps
|
||||
|
||||
vpd_info = _get_vpd_details(device_dict, device, pci_devs)
|
||||
if vpd_info:
|
||||
|
|
Loading…
Reference in New Issue