Detect port-resource-request-groups neutron API extension

The new neutron API extension signals the format change of the
resource_request field of the port. This patch only adds functions to
detect the existence of such extension. Later patches will adapt Nova
for the new format.

Depends-On: https://review.opendev.org/c/openstack/neutron-lib/+/803905

Change-Id: I4b400d499b9f594798f2da6d16f21204371a9f42
blueprint: qos-minimum-guaranteed-packet-rate
This commit is contained in:
Balazs Gibizer 2021-05-28 15:10:22 +02:00
parent f68d30bff3
commit 017b0a3d23
3 changed files with 81 additions and 0 deletions

View File

@ -29,6 +29,7 @@ MIGRATING_ATTR = 'migrating_to'
L3_NETWORK_TYPES = ['vxlan', 'gre', 'geneve']
ALLOCATION = 'allocation'
RESOURCE_REQUEST = 'resource_request'
REQUEST_GROUPS = 'request_groups'
SEGMENT = 'Segment'
NUMA_POLICY = 'numa_affinity_policy'
RESOURCE_REQUEST_GROUPS_EXTENSION = "Port Resource Request Groups"

View File

@ -995,6 +995,13 @@ class API:
return requests_and_created_ports
def _has_resource_request(self, context, port, neutron):
resource_request = port.get(constants.RESOURCE_REQUEST) or {}
if self._has_extended_resource_request_extension(context, neutron):
return bool(resource_request.get(constants.REQUEST_GROUPS, []))
else:
return bool(resource_request)
def allocate_for_instance(self, context, instance,
requested_networks,
security_groups=None, bind_host_id=None,
@ -1270,6 +1277,14 @@ class API:
self._refresh_neutron_extensions_cache(context, neutron=neutron)
return constants.SEGMENT in self.extensions
# TODO(gibi): Remove all branches where this is False after Neutron made
# the this extension mandatory. In Xena this extension will be optional to
# support the scenario where Neutron upgraded first. So Neutron can mark
# this mandatory earliest in Yoga.
def _has_extended_resource_request_extension(self, context, neutron=None):
self._refresh_neutron_extensions_cache(context, neutron=neutron)
return constants.RESOURCE_REQUEST_GROUPS_EXTENSION in self.extensions
def supports_port_binding_extension(self, context):
"""This is a simple check to see if the neutron "binding-extended"
extension exists and is enabled.

View File

@ -6571,6 +6571,71 @@ class TestAPI(TestAPIBase):
mock_debug.assert_called_with('No PCI device found for request %s',
uuids.pci_request_id, instance=instance)
@mock.patch(
'nova.network.neutron.API.'
'_has_extended_resource_request_extension')
def test__has_resource_request(self, mock_has_extended_res_req):
# Old format, resource_request in None. That is Neutron current
# behavior if the port has no QoS policy associated.
mock_has_extended_res_req.return_value = False
port_no_res_req = {"resource_request": None}
self.assertFalse(self.api._has_resource_request(
self.context, port_no_res_req, neutron=None)
)
# Old format, there is resource_request key but no resource is
# requested. We should never get this from Neutron today but we
# actually get it if there are QoS policy assigned to the port but
# there is no rule in that policy requesting resources.
port_old_empty_res_req = {"resource_request": {}}
self.assertFalse(self.api._has_resource_request(
self.context, port_old_empty_res_req, neutron=None)
)
# Old format, and the port has resource request.
port_old_res_req = {
"resource_request": {
"resources": {
"NET_BW_IGR_KILOBIT_PER_SEC": 1000,
}
}
}
self.assertTrue(self.api._has_resource_request(
self.context, port_old_res_req, neutron=None)
)
# New format tests are starting here
mock_has_extended_res_req.return_value = True
# New format, port has no QoS policy assigned
port_no_res_req = {"resource_request": None}
self.assertFalse(self.api._has_resource_request(
self.context, port_no_res_req, neutron=None)
)
# New format, port has a resource_request key but no resource is
# requested. Neutron never sends this, it sends None instead. We keep
# this here for completeness as the code actually handle this properly.
port_new_empty_res_req = {
"resource_request": {
"request_groups": []
}
}
self.assertFalse(self.api._has_resource_request(
self.context, port_new_empty_res_req, neutron=None)
)
# New format, port has a resource request
port_new_res_req = {
"resource_request": {
"request_groups": [
{
"resources": {
"NET_KILOPACKET_PER_SEC": 1000
}
},
],
"same_subtree": [],
}
}
self.assertTrue(self.api._has_resource_request(
self.context, port_new_res_req, neutron=None)
)
class TestAPIModuleMethods(test.NoDBTestCase):