Merge "pci: Add vDPA vnic to PCI request mapping and filtering"
This commit is contained in:
commit
b7334b5089
|
@ -354,7 +354,9 @@ class PciDevice(base.NovaPersistentObject, base.NovaObject):
|
||||||
self._bulk_update_status(vfs_list,
|
self._bulk_update_status(vfs_list,
|
||||||
fields.PciDeviceStatus.UNCLAIMABLE)
|
fields.PciDeviceStatus.UNCLAIMABLE)
|
||||||
|
|
||||||
elif self.dev_type == fields.PciDeviceType.SRIOV_VF:
|
elif self.dev_type in (
|
||||||
|
fields.PciDeviceType.SRIOV_VF, fields.PciDeviceType.VDPA
|
||||||
|
):
|
||||||
# Update VF status to CLAIMED if it's parent has not been
|
# Update VF status to CLAIMED if it's parent has not been
|
||||||
# previously allocated or claimed
|
# previously allocated or claimed
|
||||||
# When claiming/allocating a VF, it's parent PF becomes
|
# When claiming/allocating a VF, it's parent PF becomes
|
||||||
|
@ -414,7 +416,9 @@ class PciDevice(base.NovaPersistentObject, base.NovaObject):
|
||||||
self._bulk_update_status(vfs_list,
|
self._bulk_update_status(vfs_list,
|
||||||
fields.PciDeviceStatus.UNAVAILABLE)
|
fields.PciDeviceStatus.UNAVAILABLE)
|
||||||
|
|
||||||
elif (self.dev_type == fields.PciDeviceType.SRIOV_VF):
|
elif self.dev_type in (
|
||||||
|
fields.PciDeviceType.SRIOV_VF, fields.PciDeviceType.VDPA
|
||||||
|
):
|
||||||
parent = self.parent_device
|
parent = self.parent_device
|
||||||
if parent:
|
if parent:
|
||||||
if parent.status not in parent_ok_statuses:
|
if parent.status not in parent_ok_statuses:
|
||||||
|
@ -473,7 +477,9 @@ class PciDevice(base.NovaPersistentObject, base.NovaObject):
|
||||||
self._bulk_update_status(vfs_list,
|
self._bulk_update_status(vfs_list,
|
||||||
fields.PciDeviceStatus.AVAILABLE)
|
fields.PciDeviceStatus.AVAILABLE)
|
||||||
free_devs.extend(vfs_list)
|
free_devs.extend(vfs_list)
|
||||||
if self.dev_type == fields.PciDeviceType.SRIOV_VF:
|
if self.dev_type in (
|
||||||
|
fields.PciDeviceType.SRIOV_VF, fields.PciDeviceType.VDPA
|
||||||
|
):
|
||||||
# Set PF status to AVAILABLE if all of it's VFs are free
|
# Set PF status to AVAILABLE if all of it's VFs are free
|
||||||
parent = self.parent_device
|
parent = self.parent_device
|
||||||
if not parent:
|
if not parent:
|
||||||
|
|
|
@ -189,7 +189,9 @@ class PciDevTracker(object):
|
||||||
if dev.dev_type == fields.PciDeviceType.SRIOV_PF:
|
if dev.dev_type == fields.PciDeviceType.SRIOV_PF:
|
||||||
dev.child_devices = []
|
dev.child_devices = []
|
||||||
parents[dev.address] = dev
|
parents[dev.address] = dev
|
||||||
elif dev.dev_type == fields.PciDeviceType.SRIOV_VF:
|
elif dev.dev_type in (
|
||||||
|
fields.PciDeviceType.SRIOV_VF, fields.PciDeviceType.VDPA
|
||||||
|
):
|
||||||
dev.parent_device = parents.get(dev.parent_addr)
|
dev.parent_device = parents.get(dev.parent_addr)
|
||||||
if dev.parent_device:
|
if dev.parent_device:
|
||||||
parents[dev.parent_addr].child_devices.append(dev)
|
parents[dev.parent_addr].child_devices.append(dev)
|
||||||
|
|
|
@ -56,7 +56,8 @@ PCI_TRUSTED_TAG = 'trusted'
|
||||||
PCI_DEVICE_TYPE_TAG = 'dev_type'
|
PCI_DEVICE_TYPE_TAG = 'dev_type'
|
||||||
|
|
||||||
DEVICE_TYPE_FOR_VNIC_TYPE = {
|
DEVICE_TYPE_FOR_VNIC_TYPE = {
|
||||||
network_model.VNIC_TYPE_DIRECT_PHYSICAL: obj_fields.PciDeviceType.SRIOV_PF
|
network_model.VNIC_TYPE_DIRECT_PHYSICAL: obj_fields.PciDeviceType.SRIOV_PF,
|
||||||
|
network_model.VNIC_TYPE_VDPA: obj_fields.PciDeviceType.VDPA,
|
||||||
}
|
}
|
||||||
|
|
||||||
CONF = nova.conf.CONF
|
CONF = nova.conf.CONF
|
||||||
|
|
|
@ -217,15 +217,18 @@ class PciDeviceStats(object):
|
||||||
|
|
||||||
In case the device is a PF, all of it's dependent VFs should
|
In case the device is a PF, all of it's dependent VFs should
|
||||||
be removed from pools count, if these are present.
|
be removed from pools count, if these are present.
|
||||||
When the device is a VF, it's parent PF pool count should be
|
When the device is a VF, or a VDPA device, it's parent PF
|
||||||
decreased, unless it is no longer in a pool.
|
pool count should be decreased, unless it is no longer in a pool.
|
||||||
"""
|
"""
|
||||||
if pci_dev.dev_type == fields.PciDeviceType.SRIOV_PF:
|
if pci_dev.dev_type == fields.PciDeviceType.SRIOV_PF:
|
||||||
vfs_list = pci_dev.child_devices
|
vfs_list = pci_dev.child_devices
|
||||||
if vfs_list:
|
if vfs_list:
|
||||||
for vf in vfs_list:
|
for vf in vfs_list:
|
||||||
self.remove_device(vf)
|
self.remove_device(vf)
|
||||||
elif pci_dev.dev_type == fields.PciDeviceType.SRIOV_VF:
|
elif pci_dev.dev_type in (
|
||||||
|
fields.PciDeviceType.SRIOV_VF,
|
||||||
|
fields.PciDeviceType.VDPA,
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
parent = pci_dev.parent_device
|
parent = pci_dev.parent_device
|
||||||
# Make sure not to decrease PF pool count if this parent has
|
# Make sure not to decrease PF pool count if this parent has
|
||||||
|
@ -387,6 +390,28 @@ class PciDeviceStats(object):
|
||||||
]
|
]
|
||||||
return pools
|
return pools
|
||||||
|
|
||||||
|
def _filter_pools_for_unrequested_vdpa_devices(self, pools, request):
|
||||||
|
"""Filter out pools with VDPA devices, unless these are required.
|
||||||
|
|
||||||
|
This is necessary as vdpa devices require special handling and
|
||||||
|
should not be allocated to generic pci device requests.
|
||||||
|
|
||||||
|
:param pools: A list of PCI device pool dicts
|
||||||
|
:param request: An InstancePCIRequest object describing the type,
|
||||||
|
quantity and required NUMA affinity of device(s) we want.
|
||||||
|
:returns: A list of pools that can be used to support the request if
|
||||||
|
this is possible.
|
||||||
|
"""
|
||||||
|
if all(
|
||||||
|
spec.get('dev_type') != fields.PciDeviceType.VDPA
|
||||||
|
for spec in request.spec
|
||||||
|
):
|
||||||
|
pools = [
|
||||||
|
pool for pool in pools
|
||||||
|
if not pool.get('dev_type') == fields.PciDeviceType.VDPA
|
||||||
|
]
|
||||||
|
return pools
|
||||||
|
|
||||||
def _filter_pools(self, pools, request, numa_cells):
|
def _filter_pools(self, pools, request, numa_cells):
|
||||||
"""Determine if an individual PCI request can be met.
|
"""Determine if an individual PCI request can be met.
|
||||||
|
|
||||||
|
@ -421,7 +446,7 @@ class PciDeviceStats(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
if after_count < request.count:
|
if after_count < request.count:
|
||||||
LOG.debug('Not enough PCI devices left to satify request')
|
LOG.debug('Not enough PCI devices left to satisfy request')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Next, let's exclude all devices that aren't on the correct NUMA node
|
# Next, let's exclude all devices that aren't on the correct NUMA node
|
||||||
|
@ -438,10 +463,10 @@ class PciDeviceStats(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
if after_count < request.count:
|
if after_count < request.count:
|
||||||
LOG.debug('Not enough PCI devices left to satify request')
|
LOG.debug('Not enough PCI devices left to satisfy request')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Finally, if we're not requesting PFs then we should not use these.
|
# If we're not requesting PFs then we should not use these.
|
||||||
# Exclude them.
|
# Exclude them.
|
||||||
before_count = after_count
|
before_count = after_count
|
||||||
pools = self._filter_pools_for_unrequested_pfs(pools, request)
|
pools = self._filter_pools_for_unrequested_pfs(pools, request)
|
||||||
|
@ -455,7 +480,24 @@ class PciDeviceStats(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
if after_count < request.count:
|
if after_count < request.count:
|
||||||
LOG.debug('Not enough PCI devices left to satify request')
|
LOG.debug('Not enough PCI devices left to satisfy request')
|
||||||
|
return None
|
||||||
|
|
||||||
|
# If we're not requesting VDPA devices then we should not use these
|
||||||
|
# either. Exclude them.
|
||||||
|
before_count = after_count
|
||||||
|
pools = self._filter_pools_for_unrequested_vdpa_devices(pools, request)
|
||||||
|
after_count = sum([pool['count'] for pool in pools])
|
||||||
|
|
||||||
|
if after_count < before_count:
|
||||||
|
LOG.debug(
|
||||||
|
'Dropped %d devices as they are VDPA devices which we have '
|
||||||
|
'not requested',
|
||||||
|
before_count - after_count
|
||||||
|
)
|
||||||
|
|
||||||
|
if after_count < request.count:
|
||||||
|
LOG.debug('Not enough PCI devices left to satisfy request')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return pools
|
return pools
|
||||||
|
|
|
@ -5772,7 +5772,8 @@ class TestAPI(TestAPIBase):
|
||||||
objects.NetworkRequest(port_id=uuids.portid_3),
|
objects.NetworkRequest(port_id=uuids.portid_3),
|
||||||
objects.NetworkRequest(port_id=uuids.portid_4),
|
objects.NetworkRequest(port_id=uuids.portid_4),
|
||||||
objects.NetworkRequest(port_id=uuids.portid_5),
|
objects.NetworkRequest(port_id=uuids.portid_5),
|
||||||
objects.NetworkRequest(port_id=uuids.trusted_port)])
|
objects.NetworkRequest(port_id=uuids.trusted_port),
|
||||||
|
objects.NetworkRequest(port_id=uuids.portid_vdpa)])
|
||||||
pci_requests = objects.InstancePCIRequests(requests=[])
|
pci_requests = objects.InstancePCIRequests(requests=[])
|
||||||
# _get_port_vnic_info should be called for every NetworkRequest with a
|
# _get_port_vnic_info should be called for every NetworkRequest with a
|
||||||
# port_id attribute (so six times)
|
# port_id attribute (so six times)
|
||||||
|
@ -5785,13 +5786,14 @@ class TestAPI(TestAPIBase):
|
||||||
(model.VNIC_TYPE_DIRECT_PHYSICAL, None, 'netN', None, None),
|
(model.VNIC_TYPE_DIRECT_PHYSICAL, None, 'netN', None, None),
|
||||||
(model.VNIC_TYPE_DIRECT, True, 'netN',
|
(model.VNIC_TYPE_DIRECT, True, 'netN',
|
||||||
mock.sentinel.resource_request2, None),
|
mock.sentinel.resource_request2, None),
|
||||||
|
(model.VNIC_TYPE_VDPA, None, 'netN', None, None),
|
||||||
]
|
]
|
||||||
# _get_physnet_tunneled_info should be called for every NetworkRequest
|
# _get_physnet_tunneled_info should be called for every NetworkRequest
|
||||||
# (so seven times)
|
# (so seven times)
|
||||||
mock_get_physnet_tunneled_info.side_effect = [
|
mock_get_physnet_tunneled_info.side_effect = [
|
||||||
('physnet1', False), ('physnet1', False), ('', True),
|
('physnet1', False), ('physnet1', False), ('', True),
|
||||||
('physnet1', False), ('physnet2', False), ('physnet3', False),
|
('physnet1', False), ('physnet2', False), ('physnet3', False),
|
||||||
('physnet4', False),
|
('physnet4', False), ('physnet1', False)
|
||||||
]
|
]
|
||||||
api = neutronapi.API()
|
api = neutronapi.API()
|
||||||
|
|
||||||
|
@ -5808,12 +5810,13 @@ class TestAPI(TestAPIBase):
|
||||||
mock.sentinel.request_group1,
|
mock.sentinel.request_group1,
|
||||||
mock.sentinel.request_group2],
|
mock.sentinel.request_group2],
|
||||||
port_resource_requests)
|
port_resource_requests)
|
||||||
self.assertEqual(5, len(pci_requests.requests))
|
self.assertEqual(6, len(pci_requests.requests))
|
||||||
has_pci_request_id = [net.pci_request_id is not None for net in
|
has_pci_request_id = [net.pci_request_id is not None for net in
|
||||||
requested_networks.objects]
|
requested_networks.objects]
|
||||||
self.assertEqual(pci_requests.requests[3].spec[0]["dev_type"],
|
self.assertEqual(pci_requests.requests[3].spec[0]["dev_type"],
|
||||||
"type-PF")
|
"type-PF")
|
||||||
expected_results = [True, False, False, True, True, True, True]
|
self.assertEqual(pci_requests.requests[5].spec[0]["dev_type"], "vdpa")
|
||||||
|
expected_results = [True, False, False, True, True, True, True, True]
|
||||||
self.assertEqual(expected_results, has_pci_request_id)
|
self.assertEqual(expected_results, has_pci_request_id)
|
||||||
# Make sure only the trusted VF has the 'trusted' tag set in the spec.
|
# Make sure only the trusted VF has the 'trusted' tag set in the spec.
|
||||||
for pci_req in pci_requests.requests:
|
for pci_req in pci_requests.requests:
|
||||||
|
@ -5827,7 +5830,7 @@ class TestAPI(TestAPIBase):
|
||||||
|
|
||||||
# Only the port with a resource_request will have pci_req.requester_id.
|
# Only the port with a resource_request will have pci_req.requester_id.
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[None, None, None, None, uuids.trusted_port],
|
[None, None, None, None, uuids.trusted_port, None],
|
||||||
[pci_req.requester_id for pci_req in pci_requests.requests])
|
[pci_req.requester_id for pci_req in pci_requests.requests])
|
||||||
|
|
||||||
self.assertCountEqual(
|
self.assertCountEqual(
|
||||||
|
|
|
@ -523,18 +523,20 @@ class TestPciDeviceListObjectRemote(test_objects._RemoteTest,
|
||||||
|
|
||||||
class _TestSRIOVPciDeviceObject(object):
|
class _TestSRIOVPciDeviceObject(object):
|
||||||
def _create_pci_devices(self, vf_product_id=1515, pf_product_id=1528,
|
def _create_pci_devices(self, vf_product_id=1515, pf_product_id=1528,
|
||||||
num_pfs=2, num_vfs=8):
|
num_pfs=2, num_vfs=8, num_vdpa=0):
|
||||||
self.sriov_pf_devices = []
|
self.sriov_pf_devices = []
|
||||||
for dev in range(num_pfs):
|
for dev in range(num_pfs):
|
||||||
pci_dev = {'compute_node_id': 1,
|
pci_dev = {
|
||||||
'address': '0000:81:00.%d' % dev,
|
'compute_node_id': 1,
|
||||||
'vendor_id': '8086',
|
'address': '0000:81:00.%d' % dev,
|
||||||
'product_id': '%d' % pf_product_id,
|
'vendor_id': '8086',
|
||||||
'status': 'available',
|
'product_id': '%d' % pf_product_id,
|
||||||
'request_id': None,
|
'status': 'available',
|
||||||
'dev_type': fields.PciDeviceType.SRIOV_PF,
|
'request_id': None,
|
||||||
'parent_addr': None,
|
'dev_type': fields.PciDeviceType.SRIOV_PF,
|
||||||
'numa_node': 0}
|
'parent_addr': None,
|
||||||
|
'numa_node': 0
|
||||||
|
}
|
||||||
pci_dev_obj = objects.PciDevice.create(None, pci_dev)
|
pci_dev_obj = objects.PciDevice.create(None, pci_dev)
|
||||||
pci_dev_obj.id = dev + 81
|
pci_dev_obj.id = dev + 81
|
||||||
pci_dev_obj.child_devices = []
|
pci_dev_obj.child_devices = []
|
||||||
|
@ -542,21 +544,42 @@ class _TestSRIOVPciDeviceObject(object):
|
||||||
|
|
||||||
self.sriov_vf_devices = []
|
self.sriov_vf_devices = []
|
||||||
for dev in range(num_vfs):
|
for dev in range(num_vfs):
|
||||||
pci_dev = {'compute_node_id': 1,
|
pci_dev = {
|
||||||
'address': '0000:81:10.%d' % dev,
|
'compute_node_id': 1,
|
||||||
'vendor_id': '8086',
|
'address': '0000:81:10.%d' % dev,
|
||||||
'product_id': '%d' % vf_product_id,
|
'vendor_id': '8086',
|
||||||
'status': 'available',
|
'product_id': '%d' % vf_product_id,
|
||||||
'request_id': None,
|
'status': 'available',
|
||||||
'dev_type': fields.PciDeviceType.SRIOV_VF,
|
'request_id': None,
|
||||||
'parent_addr': '0000:81:00.%d' % int(dev / 4),
|
'dev_type': fields.PciDeviceType.SRIOV_VF,
|
||||||
'numa_node': 0}
|
'parent_addr': '0000:81:00.%d' % int(dev / 4),
|
||||||
|
'numa_node': 0
|
||||||
|
}
|
||||||
pci_dev_obj = objects.PciDevice.create(None, pci_dev)
|
pci_dev_obj = objects.PciDevice.create(None, pci_dev)
|
||||||
pci_dev_obj.id = dev + 1
|
pci_dev_obj.id = dev + 1
|
||||||
pci_dev_obj.parent_device = self.sriov_pf_devices[int(dev / 4)]
|
pci_dev_obj.parent_device = self.sriov_pf_devices[int(dev / 4)]
|
||||||
pci_dev_obj.parent_device.child_devices.append(pci_dev_obj)
|
pci_dev_obj.parent_device.child_devices.append(pci_dev_obj)
|
||||||
self.sriov_vf_devices.append(pci_dev_obj)
|
self.sriov_vf_devices.append(pci_dev_obj)
|
||||||
|
|
||||||
|
self.sriov_vdpa_devices = []
|
||||||
|
for dev in range(num_vdpa):
|
||||||
|
pci_dev = {
|
||||||
|
'compute_node_id': 1,
|
||||||
|
'address': '0000:81:11.%d' % dev,
|
||||||
|
'vendor_id': '8086',
|
||||||
|
'product_id': '%d' % vf_product_id,
|
||||||
|
'status': 'available',
|
||||||
|
'request_id': None,
|
||||||
|
'dev_type': fields.PciDeviceType.VDPA,
|
||||||
|
'parent_addr': '0000:81:00.%d' % (dev % num_pfs),
|
||||||
|
'numa_node': 0
|
||||||
|
}
|
||||||
|
pci_dev_obj = objects.PciDevice.create(None, pci_dev)
|
||||||
|
pci_dev_obj.id = dev + 1
|
||||||
|
pci_dev_obj.parent_device = self.sriov_pf_devices[dev % num_pfs]
|
||||||
|
pci_dev_obj.parent_device.child_devices.append(pci_dev_obj)
|
||||||
|
self.sriov_vdpa_devices.append(pci_dev_obj)
|
||||||
|
|
||||||
def _create_fake_instance(self):
|
def _create_fake_instance(self):
|
||||||
self.inst = instance.Instance()
|
self.inst = instance.Instance()
|
||||||
self.inst.uuid = uuids.instance
|
self.inst.uuid = uuids.instance
|
||||||
|
@ -587,26 +610,35 @@ class _TestSRIOVPciDeviceObject(object):
|
||||||
self._create_pci_devices()
|
self._create_pci_devices()
|
||||||
devobj = self.sriov_pf_devices[0]
|
devobj = self.sriov_pf_devices[0]
|
||||||
devobj.claim(self.inst.uuid)
|
devobj.claim(self.inst.uuid)
|
||||||
self.assertEqual(devobj.status,
|
self.assertEqual(devobj.status, fields.PciDeviceStatus.CLAIMED)
|
||||||
fields.PciDeviceStatus.CLAIMED)
|
self.assertEqual(devobj.instance_uuid, self.inst.uuid)
|
||||||
self.assertEqual(devobj.instance_uuid,
|
|
||||||
self.inst.uuid)
|
|
||||||
self.assertEqual(len(self.inst.pci_devices), 0)
|
self.assertEqual(len(self.inst.pci_devices), 0)
|
||||||
# check if the all the dependants are UNCLAIMABLE
|
# check if the all the dependants are UNCLAIMABLE
|
||||||
self.assertTrue(all(
|
self.assertTrue(all(
|
||||||
[dev.status == fields.PciDeviceStatus.UNCLAIMABLE for
|
[dev.status == fields.PciDeviceStatus.UNCLAIMABLE for
|
||||||
dev in self._get_children_by_parent_address(
|
dev in self._get_children_by_parent_address(
|
||||||
self.sriov_pf_devices[0].address)]))
|
self.sriov_pf_devices[0].address)]))
|
||||||
|
|
||||||
def test_claim_VF(self):
|
def test_claim_VF(self):
|
||||||
self._create_fake_instance()
|
self._create_fake_instance()
|
||||||
self._create_pci_devices()
|
self._create_pci_devices()
|
||||||
devobj = self.sriov_vf_devices[0]
|
devobj = self.sriov_vf_devices[0]
|
||||||
devobj.claim(self.inst.uuid)
|
devobj.claim(self.inst.uuid)
|
||||||
self.assertEqual(devobj.status,
|
self.assertEqual(devobj.status, fields.PciDeviceStatus.CLAIMED)
|
||||||
fields.PciDeviceStatus.CLAIMED)
|
self.assertEqual(devobj.instance_uuid, self.inst.uuid)
|
||||||
self.assertEqual(devobj.instance_uuid,
|
self.assertEqual(len(self.inst.pci_devices), 0)
|
||||||
self.inst.uuid)
|
|
||||||
|
# check if parent device status has been changed to UNCLAIMABLE
|
||||||
|
parent = self._get_parent_by_address(devobj.parent_addr)
|
||||||
|
self.assertEqual(fields.PciDeviceStatus.UNCLAIMABLE, parent.status)
|
||||||
|
|
||||||
|
def test_claim_VDPA(self):
|
||||||
|
self._create_fake_instance()
|
||||||
|
self._create_pci_devices(num_pfs=1, num_vfs=0, num_vdpa=2)
|
||||||
|
devobj = self.sriov_vdpa_devices[0]
|
||||||
|
devobj.claim(self.inst.uuid)
|
||||||
|
self.assertEqual(devobj.status, fields.PciDeviceStatus.CLAIMED)
|
||||||
|
self.assertEqual(devobj.instance_uuid, self.inst.uuid)
|
||||||
self.assertEqual(len(self.inst.pci_devices), 0)
|
self.assertEqual(len(self.inst.pci_devices), 0)
|
||||||
|
|
||||||
# check if parent device status has been changed to UNCLAIMABLE
|
# check if parent device status has been changed to UNCLAIMABLE
|
||||||
|
@ -619,10 +651,8 @@ class _TestSRIOVPciDeviceObject(object):
|
||||||
devobj = self.sriov_pf_devices[0]
|
devobj = self.sriov_pf_devices[0]
|
||||||
devobj.claim(self.inst.uuid)
|
devobj.claim(self.inst.uuid)
|
||||||
devobj.allocate(self.inst)
|
devobj.allocate(self.inst)
|
||||||
self.assertEqual(devobj.status,
|
self.assertEqual(devobj.status, fields.PciDeviceStatus.ALLOCATED)
|
||||||
fields.PciDeviceStatus.ALLOCATED)
|
self.assertEqual(devobj.instance_uuid, self.inst.uuid)
|
||||||
self.assertEqual(devobj.instance_uuid,
|
|
||||||
self.inst.uuid)
|
|
||||||
self.assertEqual(len(self.inst.pci_devices), 1)
|
self.assertEqual(len(self.inst.pci_devices), 1)
|
||||||
# check if the all the dependants are UNAVAILABLE
|
# check if the all the dependants are UNAVAILABLE
|
||||||
self.assertTrue(all(
|
self.assertTrue(all(
|
||||||
|
@ -636,10 +666,22 @@ class _TestSRIOVPciDeviceObject(object):
|
||||||
devobj = self.sriov_vf_devices[0]
|
devobj = self.sriov_vf_devices[0]
|
||||||
devobj.claim(self.inst.uuid)
|
devobj.claim(self.inst.uuid)
|
||||||
devobj.allocate(self.inst)
|
devobj.allocate(self.inst)
|
||||||
self.assertEqual(devobj.status,
|
self.assertEqual(devobj.status, fields.PciDeviceStatus.ALLOCATED)
|
||||||
fields.PciDeviceStatus.ALLOCATED)
|
self.assertEqual(devobj.instance_uuid, self.inst.uuid)
|
||||||
self.assertEqual(devobj.instance_uuid,
|
self.assertEqual(len(self.inst.pci_devices), 1)
|
||||||
self.inst.uuid)
|
|
||||||
|
# check if parent device status has been changed to UNAVAILABLE
|
||||||
|
parent = self._get_parent_by_address(devobj.parent_addr)
|
||||||
|
self.assertEqual(fields.PciDeviceStatus.UNAVAILABLE, parent.status)
|
||||||
|
|
||||||
|
def test_allocate_VDPA(self):
|
||||||
|
self._create_fake_instance()
|
||||||
|
self._create_pci_devices(num_pfs=1, num_vfs=0, num_vdpa=2)
|
||||||
|
devobj = self.sriov_vdpa_devices[0]
|
||||||
|
devobj.claim(self.inst.uuid)
|
||||||
|
devobj.allocate(self.inst)
|
||||||
|
self.assertEqual(devobj.status, fields.PciDeviceStatus.ALLOCATED)
|
||||||
|
self.assertEqual(devobj.instance_uuid, self.inst.uuid)
|
||||||
self.assertEqual(len(self.inst.pci_devices), 1)
|
self.assertEqual(len(self.inst.pci_devices), 1)
|
||||||
|
|
||||||
# check if parent device status has been changed to UNAVAILABLE
|
# check if parent device status has been changed to UNAVAILABLE
|
||||||
|
@ -652,8 +694,17 @@ class _TestSRIOVPciDeviceObject(object):
|
||||||
devobj = self.sriov_pf_devices[0]
|
devobj = self.sriov_pf_devices[0]
|
||||||
self.sriov_vf_devices[0].status = fields.PciDeviceStatus.CLAIMED
|
self.sriov_vf_devices[0].status = fields.PciDeviceStatus.CLAIMED
|
||||||
|
|
||||||
self.assertRaises(exception.PciDeviceVFInvalidStatus,
|
self.assertRaises(
|
||||||
devobj.claim, self.inst)
|
exception.PciDeviceVFInvalidStatus, devobj.claim, self.inst)
|
||||||
|
|
||||||
|
def test_claim_PF_fail_VDPA(self):
|
||||||
|
self._create_fake_instance()
|
||||||
|
self._create_pci_devices(num_pfs=1, num_vfs=0, num_vdpa=2)
|
||||||
|
devobj = self.sriov_pf_devices[0]
|
||||||
|
self.sriov_vdpa_devices[0].status = fields.PciDeviceStatus.CLAIMED
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exception.PciDeviceVFInvalidStatus, devobj.claim, self.inst)
|
||||||
|
|
||||||
def test_claim_VF_fail(self):
|
def test_claim_VF_fail(self):
|
||||||
self._create_fake_instance()
|
self._create_fake_instance()
|
||||||
|
@ -662,8 +713,17 @@ class _TestSRIOVPciDeviceObject(object):
|
||||||
parent = self._get_parent_by_address(devobj.parent_addr)
|
parent = self._get_parent_by_address(devobj.parent_addr)
|
||||||
parent.status = fields.PciDeviceStatus.CLAIMED
|
parent.status = fields.PciDeviceStatus.CLAIMED
|
||||||
|
|
||||||
self.assertRaises(exception.PciDevicePFInvalidStatus,
|
self.assertRaises(
|
||||||
devobj.claim, self.inst)
|
exception.PciDevicePFInvalidStatus, devobj.claim, self.inst)
|
||||||
|
|
||||||
|
def test_claim_VDPA_fail(self):
|
||||||
|
self._create_fake_instance()
|
||||||
|
self._create_pci_devices(num_pfs=1, num_vfs=0, num_vdpa=2)
|
||||||
|
devobj = self.sriov_vdpa_devices[0]
|
||||||
|
parent = self._get_parent_by_address(devobj.parent_addr)
|
||||||
|
parent.status = fields.PciDeviceStatus.CLAIMED
|
||||||
|
self.assertRaises(
|
||||||
|
exception.PciDevicePFInvalidStatus, devobj.claim, self.inst)
|
||||||
|
|
||||||
def test_allocate_PF_fail(self):
|
def test_allocate_PF_fail(self):
|
||||||
self._create_fake_instance()
|
self._create_fake_instance()
|
||||||
|
@ -671,8 +731,8 @@ class _TestSRIOVPciDeviceObject(object):
|
||||||
devobj = self.sriov_pf_devices[0]
|
devobj = self.sriov_pf_devices[0]
|
||||||
self.sriov_vf_devices[0].status = fields.PciDeviceStatus.CLAIMED
|
self.sriov_vf_devices[0].status = fields.PciDeviceStatus.CLAIMED
|
||||||
|
|
||||||
self.assertRaises(exception.PciDeviceVFInvalidStatus,
|
self.assertRaises(
|
||||||
devobj.allocate, self.inst)
|
exception.PciDeviceVFInvalidStatus, devobj.allocate, self.inst)
|
||||||
|
|
||||||
def test_allocate_VF_fail(self):
|
def test_allocate_VF_fail(self):
|
||||||
self._create_fake_instance()
|
self._create_fake_instance()
|
||||||
|
@ -681,8 +741,27 @@ class _TestSRIOVPciDeviceObject(object):
|
||||||
parent = self._get_parent_by_address(devobj.parent_addr)
|
parent = self._get_parent_by_address(devobj.parent_addr)
|
||||||
parent.status = fields.PciDeviceStatus.CLAIMED
|
parent.status = fields.PciDeviceStatus.CLAIMED
|
||||||
|
|
||||||
self.assertRaises(exception.PciDevicePFInvalidStatus,
|
self.assertRaises(
|
||||||
devobj.allocate, self.inst)
|
exception.PciDevicePFInvalidStatus, devobj.allocate, self.inst)
|
||||||
|
|
||||||
|
def test_allocate_PF_fail_VDPA(self):
|
||||||
|
self._create_fake_instance()
|
||||||
|
self._create_pci_devices(num_pfs=1, num_vfs=0, num_vdpa=2)
|
||||||
|
devobj = self.sriov_pf_devices[0]
|
||||||
|
self.sriov_vdpa_devices[0].status = fields.PciDeviceStatus.CLAIMED
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exception.PciDeviceVFInvalidStatus, devobj.allocate, self.inst)
|
||||||
|
|
||||||
|
def test_allocate_VDPA_fail(self):
|
||||||
|
self._create_fake_instance()
|
||||||
|
self._create_pci_devices(num_pfs=1, num_vfs=0, num_vdpa=2)
|
||||||
|
devobj = self.sriov_vdpa_devices[0]
|
||||||
|
parent = self._get_parent_by_address(devobj.parent_addr)
|
||||||
|
parent.status = fields.PciDeviceStatus.CLAIMED
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exception.PciDevicePFInvalidStatus, devobj.allocate, self.inst)
|
||||||
|
|
||||||
def test_free_allocated_PF(self):
|
def test_free_allocated_PF(self):
|
||||||
self._create_fake_instance()
|
self._create_fake_instance()
|
||||||
|
@ -691,14 +770,13 @@ class _TestSRIOVPciDeviceObject(object):
|
||||||
devobj.claim(self.inst.uuid)
|
devobj.claim(self.inst.uuid)
|
||||||
devobj.allocate(self.inst)
|
devobj.allocate(self.inst)
|
||||||
devobj.free(self.inst)
|
devobj.free(self.inst)
|
||||||
self.assertEqual(devobj.status,
|
self.assertEqual(devobj.status, fields.PciDeviceStatus.AVAILABLE)
|
||||||
fields.PciDeviceStatus.AVAILABLE)
|
|
||||||
self.assertIsNone(devobj.instance_uuid)
|
self.assertIsNone(devobj.instance_uuid)
|
||||||
# check if the all the dependants are AVAILABLE
|
# check if the all the dependants are AVAILABLE
|
||||||
self.assertTrue(all(
|
self.assertTrue(all(
|
||||||
[dev.status == fields.PciDeviceStatus.AVAILABLE for
|
[dev.status == fields.PciDeviceStatus.AVAILABLE for
|
||||||
dev in self._get_children_by_parent_address(
|
dev in self._get_children_by_parent_address(
|
||||||
self.sriov_pf_devices[0].address)]))
|
self.sriov_pf_devices[0].address)]))
|
||||||
|
|
||||||
def test_free_allocated_VF(self):
|
def test_free_allocated_VF(self):
|
||||||
self._create_fake_instance()
|
self._create_fake_instance()
|
||||||
|
@ -708,20 +786,41 @@ class _TestSRIOVPciDeviceObject(object):
|
||||||
for devobj in dependents:
|
for devobj in dependents:
|
||||||
devobj.claim(self.inst.uuid)
|
devobj.claim(self.inst.uuid)
|
||||||
devobj.allocate(self.inst)
|
devobj.allocate(self.inst)
|
||||||
self.assertEqual(devobj.status,
|
self.assertEqual(devobj.status, fields.PciDeviceStatus.ALLOCATED)
|
||||||
fields.PciDeviceStatus.ALLOCATED)
|
|
||||||
for devobj in dependents[:-1]:
|
for devobj in dependents[:-1]:
|
||||||
devobj.free(self.inst)
|
devobj.free(self.inst)
|
||||||
# check if parent device status is still UNAVAILABLE
|
# check if parent device status is still UNAVAILABLE
|
||||||
parent = self._get_parent_by_address(devobj.parent_addr)
|
parent = self._get_parent_by_address(devobj.parent_addr)
|
||||||
self.assertEqual(fields.PciDeviceStatus.UNAVAILABLE,
|
self.assertEqual(
|
||||||
parent.status)
|
fields.PciDeviceStatus.UNAVAILABLE, parent.status)
|
||||||
devobj = dependents[-1]
|
devobj = dependents[-1]
|
||||||
devobj.free(self.inst)
|
devobj.free(self.inst)
|
||||||
# check if parent device status is now AVAILABLE
|
# check if parent device status is now AVAILABLE
|
||||||
parent = self._get_parent_by_address(devobj.parent_addr)
|
parent = self._get_parent_by_address(devobj.parent_addr)
|
||||||
self.assertEqual(fields.PciDeviceStatus.AVAILABLE,
|
self.assertEqual(
|
||||||
parent.status)
|
fields.PciDeviceStatus.AVAILABLE, parent.status)
|
||||||
|
|
||||||
|
def test_free_allocated_VDPA(self):
|
||||||
|
self._create_fake_instance()
|
||||||
|
self._create_pci_devices(num_pfs=2, num_vfs=0, num_vdpa=8)
|
||||||
|
vdpa = self.sriov_vdpa_devices[0]
|
||||||
|
dependents = self._get_children_by_parent_address(vdpa.parent_addr)
|
||||||
|
for devobj in dependents:
|
||||||
|
devobj.claim(self.inst.uuid)
|
||||||
|
devobj.allocate(self.inst)
|
||||||
|
self.assertEqual(devobj.status, fields.PciDeviceStatus.ALLOCATED)
|
||||||
|
for devobj in dependents[:-1]:
|
||||||
|
devobj.free(self.inst)
|
||||||
|
# check if parent device status is still UNAVAILABLE
|
||||||
|
parent = self._get_parent_by_address(devobj.parent_addr)
|
||||||
|
self.assertEqual(
|
||||||
|
fields.PciDeviceStatus.UNAVAILABLE, parent.status)
|
||||||
|
for devobj in dependents[-1:]:
|
||||||
|
devobj.free(self.inst)
|
||||||
|
# check if parent device status is now AVAILABLE
|
||||||
|
parent = self._get_parent_by_address(devobj.parent_addr)
|
||||||
|
self.assertEqual(
|
||||||
|
fields.PciDeviceStatus.AVAILABLE, parent.status)
|
||||||
|
|
||||||
|
|
||||||
class TestSRIOVPciDeviceListObject(test_objects._LocalTest,
|
class TestSRIOVPciDeviceListObject(test_objects._LocalTest,
|
||||||
|
|
|
@ -629,37 +629,75 @@ class PciDeviceVFPFStatsTestCase(test.NoDBTestCase):
|
||||||
def _create_pci_devices(self, vf_product_id=1515, pf_product_id=1528):
|
def _create_pci_devices(self, vf_product_id=1515, pf_product_id=1528):
|
||||||
self.sriov_pf_devices = []
|
self.sriov_pf_devices = []
|
||||||
for dev in range(2):
|
for dev in range(2):
|
||||||
pci_dev = {'compute_node_id': 1,
|
pci_dev = {
|
||||||
'address': '0000:81:00.%d' % dev,
|
'compute_node_id': 1,
|
||||||
'vendor_id': '8086',
|
'address': '0000:81:00.%d' % dev,
|
||||||
'product_id': '%d' % pf_product_id,
|
'vendor_id': '8086',
|
||||||
'status': 'available',
|
'product_id': '%d' % pf_product_id,
|
||||||
'request_id': None,
|
'status': 'available',
|
||||||
'dev_type': fields.PciDeviceType.SRIOV_PF,
|
'request_id': None,
|
||||||
'parent_addr': None,
|
'dev_type': fields.PciDeviceType.SRIOV_PF,
|
||||||
'numa_node': 0}
|
'parent_addr': None,
|
||||||
|
'numa_node': 0
|
||||||
|
}
|
||||||
dev_obj = objects.PciDevice.create(None, pci_dev)
|
dev_obj = objects.PciDevice.create(None, pci_dev)
|
||||||
dev_obj.child_devices = []
|
dev_obj.child_devices = []
|
||||||
self.sriov_pf_devices.append(dev_obj)
|
self.sriov_pf_devices.append(dev_obj)
|
||||||
|
|
||||||
self.sriov_vf_devices = []
|
self.sriov_vf_devices = []
|
||||||
for dev in range(8):
|
for dev in range(8):
|
||||||
pci_dev = {'compute_node_id': 1,
|
pci_dev = {
|
||||||
'address': '0000:81:10.%d' % dev,
|
'compute_node_id': 1,
|
||||||
'vendor_id': '8086',
|
'address': '0000:81:10.%d' % dev,
|
||||||
'product_id': '%d' % vf_product_id,
|
'vendor_id': '8086',
|
||||||
'status': 'available',
|
'product_id': '%d' % vf_product_id,
|
||||||
'request_id': None,
|
'status': 'available',
|
||||||
'dev_type': fields.PciDeviceType.SRIOV_VF,
|
'request_id': None,
|
||||||
'parent_addr': '0000:81:00.%d' % int(dev / 4),
|
'dev_type': fields.PciDeviceType.SRIOV_VF,
|
||||||
'numa_node': 0}
|
'parent_addr': '0000:81:00.%d' % int(dev / 4),
|
||||||
|
'numa_node': 0
|
||||||
|
}
|
||||||
dev_obj = objects.PciDevice.create(None, pci_dev)
|
dev_obj = objects.PciDevice.create(None, pci_dev)
|
||||||
dev_obj.parent_device = self.sriov_pf_devices[int(dev / 4)]
|
dev_obj.parent_device = self.sriov_pf_devices[int(dev / 4)]
|
||||||
dev_obj.parent_device.child_devices.append(dev_obj)
|
dev_obj.parent_device.child_devices.append(dev_obj)
|
||||||
self.sriov_vf_devices.append(dev_obj)
|
self.sriov_vf_devices.append(dev_obj)
|
||||||
|
|
||||||
|
self.vdpa_devices = []
|
||||||
|
for dev in range(8):
|
||||||
|
pci_dev = {
|
||||||
|
'compute_node_id': 1,
|
||||||
|
'address': '0000:82:10.%d' % dev,
|
||||||
|
'vendor_id': '8086',
|
||||||
|
'product_id': '%d' % vf_product_id,
|
||||||
|
'status': 'available',
|
||||||
|
'request_id': None,
|
||||||
|
'dev_type': fields.PciDeviceType.VDPA,
|
||||||
|
'parent_addr': '0000:81:00.%d' % int(dev / 4),
|
||||||
|
'numa_node': 0
|
||||||
|
}
|
||||||
|
dev_obj = objects.PciDevice.create(None, pci_dev)
|
||||||
|
dev_obj.parent_device = self.sriov_pf_devices[int(dev / 4)]
|
||||||
|
dev_obj.parent_device.child_devices.append(dev_obj)
|
||||||
|
self.vdpa_devices.append(dev_obj)
|
||||||
|
|
||||||
list(map(self.pci_stats.add_device, self.sriov_pf_devices))
|
list(map(self.pci_stats.add_device, self.sriov_pf_devices))
|
||||||
list(map(self.pci_stats.add_device, self.sriov_vf_devices))
|
list(map(self.pci_stats.add_device, self.sriov_vf_devices))
|
||||||
|
list(map(self.pci_stats.add_device, self.vdpa_devices))
|
||||||
|
|
||||||
|
def test_consume_VDPA_requests(self):
|
||||||
|
self._create_pci_devices()
|
||||||
|
pci_requests = [
|
||||||
|
objects.InstancePCIRequest(
|
||||||
|
count=8, spec=[{'dev_type': 'vdpa'}])]
|
||||||
|
devs = self.pci_stats.consume_requests(pci_requests)
|
||||||
|
self.assertEqual(8, len(devs))
|
||||||
|
self.assertEqual('vdpa', devs[0].dev_type)
|
||||||
|
free_devs = self.pci_stats.get_free_devs()
|
||||||
|
# Validate that the parents of these devs has been removed
|
||||||
|
# from pools.
|
||||||
|
for dev in devs:
|
||||||
|
self.assertNotIn(dev.parent_addr,
|
||||||
|
[free_dev.address for free_dev in free_devs])
|
||||||
|
|
||||||
def test_consume_VF_requests(self):
|
def test_consume_VF_requests(self):
|
||||||
self._create_pci_devices()
|
self._create_pci_devices()
|
||||||
|
|
Loading…
Reference in New Issue