Skip to content

Commit 672b288

Browse files
author
Balazs Gibizer
committed
Refactor _claim_pci_device_for_interface_attach to prepare for qos
This removes some of the non PCI specific part of the _claim_pci_device_for_interface_attach() to reuse them later for the qos handling. The goal is to have the create_resource_requests separated from the actual PCI claim. Change-Id: Id19702da05cac25192f6aa21f8f4449602ef7729 Blueprint: support-interface-attach-with-qos-ports
1 parent 160e229 commit 672b288

File tree

4 files changed

+66
-49
lines changed

4 files changed

+66
-49
lines changed

nova/compute/manager.py

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7518,68 +7518,36 @@ def _claim_pci_device_for_interface_attach(
75187518
self,
75197519
context: nova.context.RequestContext,
75207520
instance: 'objects.Instance',
7521-
requested_networks: 'objects.NetworkRequestsList'
7521+
pci_reqs: 'objects.InstancePCIRequests',
75227522
) -> ty.Optional['objects.PciDevice']:
7523-
"""Claim PCI device if the requested interface needs it
7524-
7525-
If a PCI device is claimed then the requested_networks is updated
7526-
with the pci request id and the pci_requests and pci_devices fields
7527-
of the instance is also updated accordingly.
7523+
"""Claim PCI devices if there are PCI requests
75287524

75297525
:param context: nova.context.RequestContext
75307526
:param instance: the objects.Instance to where the interface is being
75317527
attached
7532-
:param requested_networks: the objects.NetworkRequestList describing
7533-
the requested interface. The requested_networks.objects list shall
7534-
have a single item.
7528+
:param pci_reqs: A InstancePCIRequests object describing the
7529+
needed PCI devices
75357530
:raises InterfaceAttachPciClaimFailed: if the PCI device claim fails
7536-
:raises InterfaceAttachFailed: if more than one interface is requested
75377531
:returns: An objects.PciDevice describing the claimed PCI device for
75387532
the interface or None if no device is requested
75397533
"""
75407534

7541-
if len(requested_networks) != 1:
7542-
LOG.warning(
7543-
"Interface attach only supports one interface per attach "
7544-
"request", instance=instance)
7545-
raise exception.InterfaceAttachFailed(instance_uuid=instance.uuid)
7546-
7547-
requested_network = requested_networks[0]
7548-
7549-
pci_numa_affinity_policy = hardware.get_pci_numa_policy_constraint(
7550-
instance.flavor, instance.image_meta)
7551-
pci_reqs = objects.InstancePCIRequests(
7552-
requests=[], instance_uuid=instance.uuid)
7553-
self.network_api.create_resource_requests(
7554-
context, requested_networks, pci_reqs,
7555-
affinity_policy=pci_numa_affinity_policy)
7556-
75577535
if not pci_reqs.requests:
7558-
# The requested port does not require a PCI device so nothing to do
75597536
return None
75607537

7561-
if len(pci_reqs.requests) > 1:
7562-
LOG.warning(
7563-
"Interface attach only supports one interface per attach "
7564-
"request", instance=instance)
7565-
raise exception.InterfaceAttachFailed(instance_uuid=instance.uuid)
7566-
7567-
pci_req = pci_reqs.requests[0]
7568-
75697538
devices = self.rt.claim_pci_devices(
75707539
context, pci_reqs, instance.numa_topology)
75717540

75727541
if not devices:
75737542
LOG.info('Failed to claim PCI devices during interface attach '
7574-
'for PCI request %s', pci_req, instance=instance)
7543+
'for PCI request %s', pci_reqs, instance=instance)
75757544
raise exception.InterfaceAttachPciClaimFailed(
75767545
instance_uuid=instance.uuid)
75777546

7547+
# NOTE(gibi): We assume that maximum one PCI devices is attached per
7548+
# interface attach request.
75787549
device = devices[0]
7579-
7580-
# Update the requested network with the pci request id
7581-
requested_network.pci_request_id = pci_req.request_id
7582-
instance.add_pci_device_and_request(device, pci_req)
7550+
instance.pci_devices.objects.append(device)
75837551

75847552
return device
75857553

@@ -7643,8 +7611,35 @@ def _attach_interface(self, context, instance, network_id, port_id,
76437611
]
76447612
)
76457613

7646-
pci_device = self._claim_pci_device_for_interface_attach(
7647-
context, instance, requested_networks)
7614+
if len(requested_networks) != 1:
7615+
LOG.warning(
7616+
"Interface attach only supports one interface per attach "
7617+
"request", instance=instance)
7618+
raise exception.InterfaceAttachFailed(instance_uuid=instance.uuid)
7619+
7620+
pci_numa_affinity_policy = hardware.get_pci_numa_policy_constraint(
7621+
instance.flavor, instance.image_meta)
7622+
pci_reqs = objects.InstancePCIRequests(
7623+
requests=[], instance_uuid=instance.uuid)
7624+
self.network_api.create_resource_requests(
7625+
context, requested_networks, pci_reqs,
7626+
affinity_policy=pci_numa_affinity_policy)
7627+
7628+
# We only support one port per attach request so we at most have one
7629+
# pci request
7630+
pci_req = None
7631+
if pci_reqs.requests:
7632+
pci_req = pci_reqs.requests[0]
7633+
requested_networks[0].pci_request_id = pci_req.request_id
7634+
instance.pci_requests.requests.append(pci_req)
7635+
7636+
try:
7637+
pci_device = self._claim_pci_device_for_interface_attach(
7638+
context, instance, pci_reqs)
7639+
except exception.InterfaceAttachPciClaimFailed:
7640+
with excutils.save_and_reraise_exception():
7641+
if pci_req:
7642+
instance.pci_requests.requests.remove(pci_req)
76487643

76497644
network_info = self.network_api.allocate_for_instance(
76507645
context,

nova/objects/instance.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,7 @@ def remove_pci_device_and_request(self, pci_device):
12251225
pci_req for pci_req in self.pci_requests.requests
12261226
if pci_req.request_id != pci_device.request_id]
12271227

1228+
# TODO(gibi): remove this as it is unused
12281229
def add_pci_device_and_request(self, pci_device, pci_request):
12291230
self.pci_requests.requests.append(pci_request)
12301231
self.pci_devices.objects.append(pci_device)

nova/tests/unit/compute/test_compute.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10145,11 +10145,12 @@ def test_attach_interface(self, mock_notify):
1014510145
mock.patch.dict(self.compute.driver.capabilities,
1014610146
supports_attach_interface=True),
1014710147
mock.patch('oslo_concurrency.lockutils.lock'),
10148+
mock.patch("nova.network.neutron.API.create_resource_requests"),
1014810149
mock.patch.object(
1014910150
self.compute,
1015010151
"_claim_pci_device_for_interface_attach",
1015110152
return_value=None)
10152-
) as (cap, mock_lock, mock_claim_pci):
10153+
) as (cap, mock_lock, mock_create_resource_req, mock_claim_pci):
1015310154
vif = self.compute.attach_interface(self.context,
1015410155
instance,
1015510156
network_id,
@@ -10175,7 +10176,12 @@ def test_attach_interface(self, mock_notify):
1017510176
mock.ANY, delay=mock.ANY, do_log=mock.ANY, fair=mock.ANY,
1017610177
semaphores=mock.ANY)
1017710178
mock_claim_pci.assert_called_once_with(
10178-
self.context, instance, network_requests)
10179+
self.context, instance,
10180+
test.MatchType(objects.InstancePCIRequests))
10181+
pci_reqs = mock_claim_pci.mock_calls[0][1][2]
10182+
self.assertEqual(instance.uuid, pci_reqs.instance_uuid)
10183+
self.assertEqual([], pci_reqs.requests)
10184+
1017910185
return nwinfo, port_id
1018010186

1018110187
@mock.patch.object(compute_utils, 'notify_about_instance_action')
@@ -10262,10 +10268,11 @@ def test_interface_tagged_attach(self, mock_notify):
1026210268
mock.patch.dict(self.compute.driver.capabilities,
1026310269
supports_attach_interface=True,
1026410270
supports_tagged_attach_interface=True),
10271+
mock.patch("nova.network.neutron.API.create_resource_requests"),
1026510272
mock.patch.object(self.compute,
1026610273
'_claim_pci_device_for_interface_attach',
1026710274
return_value=None)
10268-
) as (mock_capabilities, mock_claim_pci):
10275+
) as (mock_capabilities, mock_create_resource_req, mock_claim_pci):
1026910276
vif = self.compute.attach_interface(self.context,
1027010277
instance,
1027110278
network_id,
@@ -10289,7 +10296,11 @@ def test_interface_tagged_attach(self, mock_notify):
1028910296
mock.call(self.context, instance, self.compute.host,
1029010297
action='interface_attach', phase='end')])
1029110298
mock_claim_pci.assert_called_once_with(
10292-
self.context, instance, network_requests)
10299+
self.context, instance,
10300+
test.MatchType(objects.InstancePCIRequests))
10301+
pci_reqs = mock_claim_pci.mock_calls[0][1][2]
10302+
self.assertEqual(instance.uuid, pci_reqs.instance_uuid)
10303+
self.assertEqual([], pci_reqs.requests)
1029310304

1029410305
return nwinfo, port_id
1029510306

@@ -10329,11 +10340,12 @@ def test_attach_interface_failed(self):
1032910340
'deallocate_port_for_instance'),
1033010341
mock.patch.dict(self.compute.driver.capabilities,
1033110342
supports_attach_interface=True),
10343+
mock.patch("nova.network.neutron.API.create_resource_requests"),
1033210344
mock.patch.object(self.compute,
1033310345
'_claim_pci_device_for_interface_attach',
1033410346
return_value=None),
1033510347
) as (mock_notify, mock_attach, mock_allocate, mock_deallocate,
10336-
mock_dict, mock_claim_pci):
10348+
mock_dict, mock_create_resource_req, mock_claim_pci):
1033710349

1033810350
mock_allocate.return_value = nwinfo
1033910351
mock_attach.side_effect = exception.NovaException("attach_failed")
@@ -10361,7 +10373,11 @@ def test_attach_interface_failed(self):
1036110373
exception=mock_attach.side_effect,
1036210374
phase='error')])
1036310375
mock_claim_pci.assert_called_once_with(
10364-
self.context, instance, network_requests)
10376+
self.context, instance,
10377+
test.MatchType(objects.InstancePCIRequests))
10378+
pci_reqs = mock_claim_pci.mock_calls[0][1][2]
10379+
self.assertEqual(instance.uuid, pci_reqs.instance_uuid)
10380+
self.assertEqual([], pci_reqs.requests)
1036510381

1036610382
def test_attach_sriov_interface_failed_in_driver(self):
1036710383
new_type = flavors.get_flavor_by_flavor_id('4')

nova/tests/unit/compute/test_compute_mgr.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2543,8 +2543,11 @@ def test_attach_interface_failure(self):
25432543
f_instance = objects.Instance._from_db_object(self.context,
25442544
objects.Instance(),
25452545
db_instance)
2546+
f_instance.flavor = objects.Flavor()
2547+
f_instance.system_metadata = {}
25462548
e = exception.InterfaceAttachFailed(instance_uuid=f_instance.uuid)
25472549

2550+
@mock.patch('nova.network.neutron.API.create_resource_requests')
25482551
@mock.patch.object(self.compute,
25492552
'_claim_pci_device_for_interface_attach',
25502553
return_value=None)
@@ -2555,7 +2558,9 @@ def test_attach_interface_failure(self):
25552558
'allocate_for_instance', side_effect=e)
25562559
@mock.patch.object(self.compute, '_instance_update',
25572560
side_effect=lambda *a, **k: {})
2558-
def do_test(update, meth, add_fault, notify, event, mock_claim_pci):
2561+
def do_test(
2562+
update, meth, add_fault, notify, event, mock_claim_pci,
2563+
mock_create_resource_req):
25592564
self.assertRaises(exception.InterfaceAttachFailed,
25602565
self.compute.attach_interface,
25612566
self.context, f_instance, uuids.network_id,

0 commit comments

Comments
 (0)