Merge "Refactor _claim_pci_device_for_interface_attach to prepare for qos"
This commit is contained in:
commit
b34a1ca645
nova
@ -7518,68 +7518,36 @@ class ComputeManager(manager.Manager):
|
|||||||
self,
|
self,
|
||||||
context: nova.context.RequestContext,
|
context: nova.context.RequestContext,
|
||||||
instance: 'objects.Instance',
|
instance: 'objects.Instance',
|
||||||
requested_networks: 'objects.NetworkRequestsList'
|
pci_reqs: 'objects.InstancePCIRequests',
|
||||||
) -> ty.Optional['objects.PciDevice']:
|
) -> ty.Optional['objects.PciDevice']:
|
||||||
"""Claim PCI device if the requested interface needs it
|
"""Claim PCI devices if there are PCI requests
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
:param context: nova.context.RequestContext
|
:param context: nova.context.RequestContext
|
||||||
:param instance: the objects.Instance to where the interface is being
|
:param instance: the objects.Instance to where the interface is being
|
||||||
attached
|
attached
|
||||||
:param requested_networks: the objects.NetworkRequestList describing
|
:param pci_reqs: A InstancePCIRequests object describing the
|
||||||
the requested interface. The requested_networks.objects list shall
|
needed PCI devices
|
||||||
have a single item.
|
|
||||||
:raises InterfaceAttachPciClaimFailed: if the PCI device claim fails
|
: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
|
:returns: An objects.PciDevice describing the claimed PCI device for
|
||||||
the interface or None if no device is requested
|
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:
|
if not pci_reqs.requests:
|
||||||
# The requested port does not require a PCI device so nothing to do
|
|
||||||
return None
|
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(
|
devices = self.rt.claim_pci_devices(
|
||||||
context, pci_reqs, instance.numa_topology)
|
context, pci_reqs, instance.numa_topology)
|
||||||
|
|
||||||
if not devices:
|
if not devices:
|
||||||
LOG.info('Failed to claim PCI devices during interface attach '
|
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(
|
raise exception.InterfaceAttachPciClaimFailed(
|
||||||
instance_uuid=instance.uuid)
|
instance_uuid=instance.uuid)
|
||||||
|
|
||||||
|
# NOTE(gibi): We assume that maximum one PCI devices is attached per
|
||||||
|
# interface attach request.
|
||||||
device = devices[0]
|
device = devices[0]
|
||||||
|
instance.pci_devices.objects.append(device)
|
||||||
# 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)
|
|
||||||
|
|
||||||
return device
|
return device
|
||||||
|
|
||||||
@ -7643,8 +7611,35 @@ class ComputeManager(manager.Manager):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
pci_device = self._claim_pci_device_for_interface_attach(
|
if len(requested_networks) != 1:
|
||||||
context, instance, requested_networks)
|
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(
|
network_info = self.network_api.allocate_for_instance(
|
||||||
context,
|
context,
|
||||||
|
@ -1225,6 +1225,7 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
|
|||||||
pci_req for pci_req in self.pci_requests.requests
|
pci_req for pci_req in self.pci_requests.requests
|
||||||
if pci_req.request_id != pci_device.request_id]
|
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):
|
def add_pci_device_and_request(self, pci_device, pci_request):
|
||||||
self.pci_requests.requests.append(pci_request)
|
self.pci_requests.requests.append(pci_request)
|
||||||
self.pci_devices.objects.append(pci_device)
|
self.pci_devices.objects.append(pci_device)
|
||||||
|
@ -10145,11 +10145,12 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
mock.patch.dict(self.compute.driver.capabilities,
|
mock.patch.dict(self.compute.driver.capabilities,
|
||||||
supports_attach_interface=True),
|
supports_attach_interface=True),
|
||||||
mock.patch('oslo_concurrency.lockutils.lock'),
|
mock.patch('oslo_concurrency.lockutils.lock'),
|
||||||
|
mock.patch("nova.network.neutron.API.create_resource_requests"),
|
||||||
mock.patch.object(
|
mock.patch.object(
|
||||||
self.compute,
|
self.compute,
|
||||||
"_claim_pci_device_for_interface_attach",
|
"_claim_pci_device_for_interface_attach",
|
||||||
return_value=None)
|
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,
|
vif = self.compute.attach_interface(self.context,
|
||||||
instance,
|
instance,
|
||||||
network_id,
|
network_id,
|
||||||
@ -10175,7 +10176,12 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
mock.ANY, delay=mock.ANY, do_log=mock.ANY, fair=mock.ANY,
|
mock.ANY, delay=mock.ANY, do_log=mock.ANY, fair=mock.ANY,
|
||||||
semaphores=mock.ANY)
|
semaphores=mock.ANY)
|
||||||
mock_claim_pci.assert_called_once_with(
|
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
|
return nwinfo, port_id
|
||||||
|
|
||||||
@mock.patch.object(compute_utils, 'notify_about_instance_action')
|
@mock.patch.object(compute_utils, 'notify_about_instance_action')
|
||||||
@ -10262,10 +10268,11 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
mock.patch.dict(self.compute.driver.capabilities,
|
mock.patch.dict(self.compute.driver.capabilities,
|
||||||
supports_attach_interface=True,
|
supports_attach_interface=True,
|
||||||
supports_tagged_attach_interface=True),
|
supports_tagged_attach_interface=True),
|
||||||
|
mock.patch("nova.network.neutron.API.create_resource_requests"),
|
||||||
mock.patch.object(self.compute,
|
mock.patch.object(self.compute,
|
||||||
'_claim_pci_device_for_interface_attach',
|
'_claim_pci_device_for_interface_attach',
|
||||||
return_value=None)
|
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,
|
vif = self.compute.attach_interface(self.context,
|
||||||
instance,
|
instance,
|
||||||
network_id,
|
network_id,
|
||||||
@ -10289,7 +10296,11 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
mock.call(self.context, instance, self.compute.host,
|
mock.call(self.context, instance, self.compute.host,
|
||||||
action='interface_attach', phase='end')])
|
action='interface_attach', phase='end')])
|
||||||
mock_claim_pci.assert_called_once_with(
|
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
|
return nwinfo, port_id
|
||||||
|
|
||||||
@ -10329,11 +10340,12 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
'deallocate_port_for_instance'),
|
'deallocate_port_for_instance'),
|
||||||
mock.patch.dict(self.compute.driver.capabilities,
|
mock.patch.dict(self.compute.driver.capabilities,
|
||||||
supports_attach_interface=True),
|
supports_attach_interface=True),
|
||||||
|
mock.patch("nova.network.neutron.API.create_resource_requests"),
|
||||||
mock.patch.object(self.compute,
|
mock.patch.object(self.compute,
|
||||||
'_claim_pci_device_for_interface_attach',
|
'_claim_pci_device_for_interface_attach',
|
||||||
return_value=None),
|
return_value=None),
|
||||||
) as (mock_notify, mock_attach, mock_allocate, mock_deallocate,
|
) 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_allocate.return_value = nwinfo
|
||||||
mock_attach.side_effect = exception.NovaException("attach_failed")
|
mock_attach.side_effect = exception.NovaException("attach_failed")
|
||||||
@ -10361,7 +10373,11 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
exception=mock_attach.side_effect,
|
exception=mock_attach.side_effect,
|
||||||
phase='error')])
|
phase='error')])
|
||||||
mock_claim_pci.assert_called_once_with(
|
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):
|
def test_attach_sriov_interface_failed_in_driver(self):
|
||||||
new_type = flavors.get_flavor_by_flavor_id('4')
|
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,
|
f_instance = objects.Instance._from_db_object(self.context,
|
||||||
objects.Instance(),
|
objects.Instance(),
|
||||||
db_instance)
|
db_instance)
|
||||||
|
f_instance.flavor = objects.Flavor()
|
||||||
|
f_instance.system_metadata = {}
|
||||||
e = exception.InterfaceAttachFailed(instance_uuid=f_instance.uuid)
|
e = exception.InterfaceAttachFailed(instance_uuid=f_instance.uuid)
|
||||||
|
|
||||||
|
@mock.patch('nova.network.neutron.API.create_resource_requests')
|
||||||
@mock.patch.object(self.compute,
|
@mock.patch.object(self.compute,
|
||||||
'_claim_pci_device_for_interface_attach',
|
'_claim_pci_device_for_interface_attach',
|
||||||
return_value=None)
|
return_value=None)
|
||||||
@ -2555,7 +2558,9 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
|||||||
'allocate_for_instance', side_effect=e)
|
'allocate_for_instance', side_effect=e)
|
||||||
@mock.patch.object(self.compute, '_instance_update',
|
@mock.patch.object(self.compute, '_instance_update',
|
||||||
side_effect=lambda *a, **k: {})
|
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.assertRaises(exception.InterfaceAttachFailed,
|
||||||
self.compute.attach_interface,
|
self.compute.attach_interface,
|
||||||
self.context, f_instance, uuids.network_id,
|
self.context, f_instance, uuids.network_id,
|
||||||
|
Loading…
Reference in New Issue
Block a user