Add same_subtree field to RequestLevelParams

Extend RequestLevelParams o.v.o to store lists of request group name
suffixes that later will be used as same_subtree query parameters
in the Placement GET /allocation_candidates API calls

This patch adds logic to parse the same_subtree field out from the port
resource_request as well as additional helpers used later on to combine
RequestLevelParams objects coming from different ports.

Change-Id: I523737ef88850a4e2646221a52106016c9595847
blueprint: qos-minimum-guaranteed-packet-rate
This commit is contained in:
Balazs Gibizer
2021-05-11 16:40:39 +02:00
parent 8f5b7c67ca
commit 9de8bfb6e6
3 changed files with 92 additions and 2 deletions

View File

@@ -1293,16 +1293,55 @@ class RequestLevelParams(base.NovaObject):
RequestGroup).
"""
# Version 1.0: Initial version
VERSION = '1.0'
# Version 1.1: Add same_subtree field
VERSION = '1.1'
fields = {
# Traits required on the root provider
'root_required': fields.SetOfStringsField(default=set()),
# Traits forbidden on the root provider
'root_forbidden': fields.SetOfStringsField(default=set()),
# Lists of request group suffixes that needs to be allocated from the
# same provider subtree
'same_subtree': fields.ListOfListsOfStringsField(default=list()),
# NOTE(efried): group_policy would be appropriate to include here, once
# we have a use case for it.
}
def obj_load_attr(self, attrname):
self.obj_set_defaults(attrname)
def obj_make_compatible(self, primitive, target_version):
super().obj_make_compatible(primitive, target_version)
target_version = versionutils.convert_version_to_tuple(target_version)
if target_version < (1, 1):
if 'same_subtree' in primitive:
del primitive['same_subtree']
@classmethod
def from_port_request(cls, port_resource_request):
"""Extracts request level global parameters from the resource_request
of a neutron port.
Neutron only uses same_subtree at the moment.
"""
same_subtree = port_resource_request.get('same_subtree')
if same_subtree:
# NOTE(gibi): A single port only has a single list of groups
# requesting same subtree, but the RequestLevelParams maintains a
# list of such subtree requests
return cls(same_subtree=[same_subtree])
return cls()
def extend_with(self, other_req_lvl_params):
"""Extends the existing object with parameter values from another
RequestLevelParams object. That new set of requirements are connected
with the existing ones with a logical AND operation.
"""
self.root_required = self.root_required.union(
other_req_lvl_params.root_required)
self.root_forbidden = self.root_forbidden.union(
other_req_lvl_params.root_forbidden)
self.same_subtree.extend(other_req_lvl_params.same_subtree)

View File

@@ -1123,7 +1123,7 @@ object_data = {
'Quotas': '1.3-3b2b91371f60e788035778fc5f87797d',
'QuotasNoOp': '1.3-d1593cf969c81846bc8192255ea95cce',
'RequestGroup': '1.3-0458d350a8ec9d0673f9be5640a990ce',
'RequestLevelParams': '1.0-1e5c8c18bd44cd233c8b32509c99d06f',
'RequestLevelParams': '1.1-3a718a0ae0bfdec669e7108631b3f313',
'RequestSpec': '1.14-2cdbda368ca07e10905dc5fe96908a58',
'Resource': '1.0-d8a2abbb380da583b995fd118f6a8953',
'ResourceList': '1.0-4a53826625cc280e15fae64a575e0879',

View File

@@ -1692,3 +1692,54 @@ class TestMappingRequestGroupsToProviders(test.NoDBTestCase):
allocations, provider_traits)
self.assertIn('allocations leftover', mock_debug.mock_calls[3][1][0])
class TestRequestLevelParams(test.NoDBTestCase):
def setUp(self):
super().setUp()
self.user_id = uuids.user_id
self.project_id = uuids.project_id
self.context = context.RequestContext(uuids.user_id, uuids.project_id)
def test_obj_make_compatible(self):
obj = request_spec.RequestLevelParams(
self.context,
root_required={"CUSTOM_FOO", "CUSTOM_BAR"},
root_forbidden={"CUSTOM_BAZ"},
same_subtree=[["group1", "group2"], ["group3", "group4"]])
manifest = ovo_base.obj_tree_get_versions(obj.obj_name())
obj_primitive = obj.obj_to_primitive(
target_version='1.1',
version_manifest=manifest)['nova_object.data']
self.assertIn('root_required', obj_primitive)
self.assertIn('root_forbidden', obj_primitive)
self.assertIn('same_subtree', obj_primitive)
obj_primitive = obj.obj_to_primitive(
target_version='1.0',
version_manifest=manifest)['nova_object.data']
self.assertIn('root_required', obj_primitive)
self.assertIn('root_forbidden', obj_primitive)
self.assertNotIn('same_subtree', obj_primitive)
def test_extend_with(self):
obj1 = request_spec.RequestLevelParams(
self.context,
root_required={"CUSTOM_FOO"},
root_forbidden={"CUSTOM_BAZ"},
same_subtree=[["group1", "group2"]])
obj2 = request_spec.RequestLevelParams(
self.context,
root_required={"CUSTOM_BAR"},
root_forbidden={"CUSTOM_FOOBAR"},
same_subtree=[["group3", "group4"]])
obj1.extend_with(obj2)
self.assertEqual({"CUSTOM_FOO", "CUSTOM_BAR"}, obj1.root_required)
self.assertEqual({"CUSTOM_BAZ", "CUSTOM_FOOBAR"}, obj1.root_forbidden)
self.assertEqual(
[["group1", "group2"], ["group3", "group4"]],
obj1.same_subtree)