Merge "Refactor _claim_pci_device_for_interface_attach to prepare for qos"
This commit is contained in:
commit
b34a1ca645
@ -7518,68 +7518,36 @@ class ComputeManager(manager.Manager):
|
||||
self,
|
||||
context: nova.context.RequestContext,
|
||||
instance: 'objects.Instance',
|
||||
requested_networks: 'objects.NetworkRequestsList'
|
||||
pci_reqs: 'objects.InstancePCIRequests',
|
||||
) -> ty.Optional['objects.PciDevice']:
|
||||
"""Claim PCI device if the requested interface needs it
|
||||
|
||||
If a PCI device is claimed then the requested_networks is updated
|
||||
with the pci request id and the pci_requests and pci_devices fields
|
||||
of the instance is also updated accordingly.
|
||||
"""Claim PCI devices if there are PCI requests
|
||||
|
||||
:param context: nova.context.RequestContext
|
||||
:param instance: the objects.Instance to where the interface is being
|
||||
attached
|
||||
:param requested_networks: the objects.NetworkRequestList describing
|
||||
the requested interface. The requested_networks.objects list shall
|
||||
have a single item.
|
||||
:param pci_reqs: A InstancePCIRequests object describing the
|
||||
needed PCI devices
|
||||
:raises InterfaceAttachPciClaimFailed: if the PCI device claim fails
|
||||
:raises InterfaceAttachFailed: if more than one interface is requested
|
||||
:returns: An objects.PciDevice describing the claimed PCI device for
|
||||
the interface or None if no device is requested
|
||||
"""
|
||||
|
||||
if len(requested_networks) != 1:
|
||||
LOG.warning(
|
||||
"Interface attach only supports one interface per attach "
|
||||
"request", instance=instance)
|
||||
raise exception.InterfaceAttachFailed(instance_uuid=instance.uuid)
|
||||
|
||||
requested_network = requested_networks[0]
|
||||
|
||||
pci_numa_affinity_policy = hardware.get_pci_numa_policy_constraint(
|
||||
instance.flavor, instance.image_meta)
|
||||
pci_reqs = objects.InstancePCIRequests(
|
||||
requests=[], instance_uuid=instance.uuid)
|
||||
self.network_api.create_resource_requests(
|
||||
context, requested_networks, pci_reqs,
|
||||
affinity_policy=pci_numa_affinity_policy)
|
||||
|
||||
if not pci_reqs.requests:
|
||||
# The requested port does not require a PCI device so nothing to do
|
||||
return None
|
||||
|
||||
if len(pci_reqs.requests) > 1:
|
||||
LOG.warning(
|
||||
"Interface attach only supports one interface per attach "
|
||||
"request", instance=instance)
|
||||
raise exception.InterfaceAttachFailed(instance_uuid=instance.uuid)
|
||||
|
||||
pci_req = pci_reqs.requests[0]
|
||||
|
||||
devices = self.rt.claim_pci_devices(
|
||||
context, pci_reqs, instance.numa_topology)
|
||||
|
||||
if not devices:
|
||||
LOG.info('Failed to claim PCI devices during interface attach '
|
||||
'for PCI request %s', pci_req, instance=instance)
|
||||
'for PCI request %s', pci_reqs, instance=instance)
|
||||
raise exception.InterfaceAttachPciClaimFailed(
|
||||
instance_uuid=instance.uuid)
|
||||
|
||||
# NOTE(gibi): We assume that maximum one PCI devices is attached per
|
||||
# interface attach request.
|
||||
device = devices[0]
|
||||
|
||||
# Update the requested network with the pci request id
|
||||
requested_network.pci_request_id = pci_req.request_id
|
||||
instance.add_pci_device_and_request(device, pci_req)
|
||||
instance.pci_devices.objects.append(device)
|
||||
|
||||
return device
|
||||
|
||||
@ -7643,8 +7611,35 @@ class ComputeManager(manager.Manager):
|
||||
]
|
||||
)
|
||||
|
||||
pci_device = self._claim_pci_device_for_interface_attach(
|
||||
context, instance, requested_networks)
|
||||
if len(requested_networks) != 1:
|
||||
LOG.warning(
|
||||
"Interface attach only supports one interface per attach "
|
||||
"request", instance=instance)
|
||||
raise exception.InterfaceAttachFailed(instance_uuid=instance.uuid)
|
||||
|
||||
pci_numa_affinity_policy = hardware.get_pci_numa_policy_constraint(
|
||||
instance.flavor, instance.image_meta)
|
||||
pci_reqs = objects.InstancePCIRequests(
|
||||
requests=[], instance_uuid=instance.uuid)
|
||||
self.network_api.create_resource_requests(
|
||||
context, requested_networks, pci_reqs,
|
||||
affinity_policy=pci_numa_affinity_policy)
|
||||
|
||||
# We only support one port per attach request so we at most have one
|
||||
# pci request
|
||||
pci_req = None
|
||||
if pci_reqs.requests:
|
||||
pci_req = pci_reqs.requests[0]
|
||||
requested_networks[0].pci_request_id = pci_req.request_id
|
||||
instance.pci_requests.requests.append(pci_req)
|
||||
|
||||
try:
|
||||
pci_device = self._claim_pci_device_for_interface_attach(
|
||||
context, instance, pci_reqs)
|
||||
except exception.InterfaceAttachPciClaimFailed:
|
||||
with excutils.save_and_reraise_exception():
|
||||
if pci_req:
|
||||
instance.pci_requests.requests.remove(pci_req)
|
||||
|
||||
network_info = self.network_api.allocate_for_instance(
|
||||
context,
|
||||
|
@ -1225,6 +1225,7 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
|
||||
pci_req for pci_req in self.pci_requests.requests
|
||||
if pci_req.request_id != pci_device.request_id]
|
||||
|
||||
# TODO(gibi): remove this as it is unused
|
||||
def add_pci_device_and_request(self, pci_device, pci_request):
|
||||
self.pci_requests.requests.append(pci_request)
|
||||
self.pci_devices.objects.append(pci_device)
|
||||
|
@ -10145,11 +10145,12 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
mock.patch.dict(self.compute.driver.capabilities,
|
||||
supports_attach_interface=True),
|
||||
mock.patch('oslo_concurrency.lockutils.lock'),
|
||||
mock.patch("nova.network.neutron.API.create_resource_requests"),
|
||||
mock.patch.object(
|
||||
self.compute,
|
||||
"_claim_pci_device_for_interface_attach",
|
||||
return_value=None)
|
||||
) as (cap, mock_lock, mock_claim_pci):
|
||||
) as (cap, mock_lock, mock_create_resource_req, mock_claim_pci):
|
||||
vif = self.compute.attach_interface(self.context,
|
||||
instance,
|
||||
network_id,
|
||||
@ -10175,7 +10176,12 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
mock.ANY, delay=mock.ANY, do_log=mock.ANY, fair=mock.ANY,
|
||||
semaphores=mock.ANY)
|
||||
mock_claim_pci.assert_called_once_with(
|
||||
self.context, instance, network_requests)
|
||||
self.context, instance,
|
||||
test.MatchType(objects.InstancePCIRequests))
|
||||
pci_reqs = mock_claim_pci.mock_calls[0][1][2]
|
||||
self.assertEqual(instance.uuid, pci_reqs.instance_uuid)
|
||||
self.assertEqual([], pci_reqs.requests)
|
||||
|
||||
return nwinfo, port_id
|
||||
|
||||
@mock.patch.object(compute_utils, 'notify_about_instance_action')
|
||||
@ -10262,10 +10268,11 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
mock.patch.dict(self.compute.driver.capabilities,
|
||||
supports_attach_interface=True,
|
||||
supports_tagged_attach_interface=True),
|
||||
mock.patch("nova.network.neutron.API.create_resource_requests"),
|
||||
mock.patch.object(self.compute,
|
||||
'_claim_pci_device_for_interface_attach',
|
||||
return_value=None)
|
||||
) as (mock_capabilities, mock_claim_pci):
|
||||
) as (mock_capabilities, mock_create_resource_req, mock_claim_pci):
|
||||
vif = self.compute.attach_interface(self.context,
|
||||
instance,
|
||||
network_id,
|
||||
@ -10289,7 +10296,11 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
mock.call(self.context, instance, self.compute.host,
|
||||
action='interface_attach', phase='end')])
|
||||
mock_claim_pci.assert_called_once_with(
|
||||
self.context, instance, network_requests)
|
||||
self.context, instance,
|
||||
test.MatchType(objects.InstancePCIRequests))
|
||||
pci_reqs = mock_claim_pci.mock_calls[0][1][2]
|
||||
self.assertEqual(instance.uuid, pci_reqs.instance_uuid)
|
||||
self.assertEqual([], pci_reqs.requests)
|
||||
|
||||
return nwinfo, port_id
|
||||
|
||||
@ -10329,11 +10340,12 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
'deallocate_port_for_instance'),
|
||||
mock.patch.dict(self.compute.driver.capabilities,
|
||||
supports_attach_interface=True),
|
||||
mock.patch("nova.network.neutron.API.create_resource_requests"),
|
||||
mock.patch.object(self.compute,
|
||||
'_claim_pci_device_for_interface_attach',
|
||||
return_value=None),
|
||||
) as (mock_notify, mock_attach, mock_allocate, mock_deallocate,
|
||||
mock_dict, mock_claim_pci):
|
||||
mock_dict, mock_create_resource_req, mock_claim_pci):
|
||||
|
||||
mock_allocate.return_value = nwinfo
|
||||
mock_attach.side_effect = exception.NovaException("attach_failed")
|
||||
@ -10361,7 +10373,11 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
exception=mock_attach.side_effect,
|
||||
phase='error')])
|
||||
mock_claim_pci.assert_called_once_with(
|
||||
self.context, instance, network_requests)
|
||||
self.context, instance,
|
||||
test.MatchType(objects.InstancePCIRequests))
|
||||
pci_reqs = mock_claim_pci.mock_calls[0][1][2]
|
||||
self.assertEqual(instance.uuid, pci_reqs.instance_uuid)
|
||||
self.assertEqual([], pci_reqs.requests)
|
||||
|
||||
def test_attach_sriov_interface_failed_in_driver(self):
|
||||
new_type = flavors.get_flavor_by_flavor_id('4')
|
||||
|
@ -2543,8 +2543,11 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
||||
f_instance = objects.Instance._from_db_object(self.context,
|
||||
objects.Instance(),
|
||||
db_instance)
|
||||
f_instance.flavor = objects.Flavor()
|
||||
f_instance.system_metadata = {}
|
||||
e = exception.InterfaceAttachFailed(instance_uuid=f_instance.uuid)
|
||||
|
||||
@mock.patch('nova.network.neutron.API.create_resource_requests')
|
||||
@mock.patch.object(self.compute,
|
||||
'_claim_pci_device_for_interface_attach',
|
||||
return_value=None)
|
||||
@ -2555,7 +2558,9 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
||||
'allocate_for_instance', side_effect=e)
|
||||
@mock.patch.object(self.compute, '_instance_update',
|
||||
side_effect=lambda *a, **k: {})
|
||||
def do_test(update, meth, add_fault, notify, event, mock_claim_pci):
|
||||
def do_test(
|
||||
update, meth, add_fault, notify, event, mock_claim_pci,
|
||||
mock_create_resource_req):
|
||||
self.assertRaises(exception.InterfaceAttachFailed,
|
||||
self.compute.attach_interface,
|
||||
self.context, f_instance, uuids.network_id,
|
||||
|
Loading…
Reference in New Issue
Block a user