From a53aef47b20479d54efbc0f43d96a804b585a77b Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Sat, 9 Mar 2019 00:41:02 +0000 Subject: [PATCH] Remove ResourceProviderList class The get_all_by_filters class method is now module level. Callers and tests are updated accordingly. As there is no longer any package using common.py, it is removed. Looking at this, it now seems obvious that 'get_all_by_filters' is oxymoronic but changing it now didn't seem appropriate. We may wish to do that in future work. Change-Id: Ib9365200ebec58002c2456435f858466c6afea7f --- placement/handlers/allocation.py | 5 +- placement/handlers/resource_provider.py | 3 +- placement/objects/common.py | 38 -- placement/objects/resource_provider.py | 376 +++++++++--------- .../functional/db/test_resource_provider.py | 68 ++-- 5 files changed, 222 insertions(+), 268 deletions(-) delete mode 100644 placement/objects/common.py diff --git a/placement/handlers/allocation.py b/placement/handlers/allocation.py index 9176a5462..fd1c159ea 100644 --- a/placement/handlers/allocation.py +++ b/placement/handlers/allocation.py @@ -321,10 +321,9 @@ def _resource_providers_by_uuid(ctx, rp_uuids): # TODO(jaypipes): Clearly, this is not efficient to do one query for # each resource provider UUID in the allocations instead of doing a # single query for all the UUIDs. However, since - # ResourceProviderList.get_all_by_filters() is way too complicated for + # rp_obj.get_all_by_filters() is way too complicated for # this purpose and doesn't raise NotFound anyway, we'll do this. - # Perhaps consider adding a ResourceProviderList.get_all_by_uuids() - # later on? + # Perhaps consider adding a rp_obj.get_all_by_uuids() later on? try: res[rp_uuid] = rp_obj.ResourceProvider.get_by_uuid(ctx, rp_uuid) except exception.NotFound: diff --git a/placement/handlers/resource_provider.py b/placement/handlers/resource_provider.py index 2b1ca208b..940eb25a0 100644 --- a/placement/handlers/resource_provider.py +++ b/placement/handlers/resource_provider.py @@ -236,8 +236,7 @@ def list_resource_providers(req): value, allow_forbidden=allow_forbidden) filters[attr] = value try: - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( - context, filters) + resource_providers = rp_obj.get_all_by_filters(context, filters) except exception.ResourceClassNotFound as exc: raise webob.exc.HTTPBadRequest( _('Invalid resource class in resources parameter: %(error)s') % diff --git a/placement/objects/common.py b/placement/objects/common.py deleted file mode 100644 index dbc910898..000000000 --- a/placement/objects/common.py +++ /dev/null @@ -1,38 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class ObjectList(object): - # For FooList, ITEM_CLS = Foo - ITEM_CLS = None - - """Provide listiness for objects which are a list of other objects.""" - def __init__(self, objects=None): - self.objects = objects or [] - - def __len__(self): - """List length is a proxy for truthiness.""" - return len(self.objects) - - def __getitem__(self, index): - return self.objects[index] - - def __repr__(self): - strings = [repr(x) for x in self.objects] - return "%s[%s]" % (self.__class__.__name__, ", ".join(strings)) - - @classmethod - def _set_objects(cls, context, db_list): - list_obj = cls() - for db_item in db_list: - list_obj.objects.append(cls.ITEM_CLS(context, **db_item)) - return list_obj diff --git a/placement/objects/resource_provider.py b/placement/objects/resource_provider.py index 6220eb4ce..f362ca9d9 100644 --- a/placement/objects/resource_provider.py +++ b/placement/objects/resource_provider.py @@ -34,7 +34,6 @@ from placement.db.sqlalchemy import models from placement import db_api from placement import exception from placement.i18n import _ -from placement.objects import common as common_obj from placement.objects import inventory as inv_obj from placement.objects import rp_candidates from placement.objects import trait as trait_obj @@ -1089,9 +1088,8 @@ class ResourceProvider(object): # However as the RP's current parent is None the above # condition is the same as "the new parent cannot be any RP # from the current RP tree". - same_tree = ResourceProviderList.get_all_by_filters( - context, - filters={'in_tree': self.uuid}) + same_tree = get_all_by_filters( + context, filters={'in_tree': self.uuid}) rp_uuids_in_the_same_tree = [rp.uuid for rp in same_tree] if parent_uuid in rp_uuids_in_the_same_tree: raise exception.ObjectActionError( @@ -1282,206 +1280,202 @@ def get_providers_with_shared_capacity(ctx, rc_id, amount, member_of=None): return [r[0] for r in ctx.session.execute(sel)] -class ResourceProviderList(common_obj.ObjectList): - ITEM_CLS = ResourceProvider +@db_api.placement_context_manager.reader +def _get_all_by_filters_from_db(context, filters): + # Eg. filters can be: + # filters = { + # 'name': , + # 'uuid': , + # 'member_of': [[, ], + # []] + # 'resources': { + # 'VCPU': 1, + # 'MEMORY_MB': 1024 + # }, + # 'in_tree': , + # 'required': [, ...] + # } + if not filters: + filters = {} + else: + # Since we modify the filters, copy them so that we don't modify + # them in the calling program. + filters = copy.deepcopy(filters) + name = filters.pop('name', None) + uuid = filters.pop('uuid', None) + member_of = filters.pop('member_of', []) + required = set(filters.pop('required', [])) + forbidden = set([trait for trait in required + if trait.startswith('!')]) + required = required - forbidden + forbidden = set([trait.lstrip('!') for trait in forbidden]) - @staticmethod - @db_api.placement_context_manager.reader - def _get_all_by_filters_from_db(context, filters): - # Eg. filters can be: - # filters = { - # 'name': , - # 'uuid': , - # 'member_of': [[, ], - # []] - # 'resources': { - # 'VCPU': 1, - # 'MEMORY_MB': 1024 - # }, - # 'in_tree': , - # 'required': [, ...] - # } - if not filters: - filters = {} - else: - # Since we modify the filters, copy them so that we don't modify - # them in the calling program. - filters = copy.deepcopy(filters) - name = filters.pop('name', None) - uuid = filters.pop('uuid', None) - member_of = filters.pop('member_of', []) - required = set(filters.pop('required', [])) - forbidden = set([trait for trait in required - if trait.startswith('!')]) - required = required - forbidden - forbidden = set([trait.lstrip('!') for trait in forbidden]) + resources = filters.pop('resources', {}) + # NOTE(sbauza): We want to key the dict by the resource class IDs + # and we want to make sure those class names aren't incorrect. + resources = {rc_cache.RC_CACHE.id_from_string(r_name): amount + for r_name, amount in resources.items()} + rp = sa.alias(_RP_TBL, name="rp") + root_rp = sa.alias(_RP_TBL, name="root_rp") + parent_rp = sa.alias(_RP_TBL, name="parent_rp") - resources = filters.pop('resources', {}) - # NOTE(sbauza): We want to key the dict by the resource class IDs - # and we want to make sure those class names aren't incorrect. - resources = {rc_cache.RC_CACHE.id_from_string(r_name): amount - for r_name, amount in resources.items()} - rp = sa.alias(_RP_TBL, name="rp") - root_rp = sa.alias(_RP_TBL, name="root_rp") - parent_rp = sa.alias(_RP_TBL, name="parent_rp") + cols = [ + rp.c.id, + rp.c.uuid, + rp.c.name, + rp.c.generation, + rp.c.updated_at, + rp.c.created_at, + root_rp.c.uuid.label("root_provider_uuid"), + parent_rp.c.uuid.label("parent_provider_uuid"), + ] - cols = [ - rp.c.id, - rp.c.uuid, - rp.c.name, - rp.c.generation, - rp.c.updated_at, - rp.c.created_at, - root_rp.c.uuid.label("root_provider_uuid"), - parent_rp.c.uuid.label("parent_provider_uuid"), - ] + # TODO(jaypipes): Convert this to an inner join once all + # root_provider_id values are NOT NULL + rp_to_root = sa.outerjoin( + rp, root_rp, + rp.c.root_provider_id == root_rp.c.id) + rp_to_parent = sa.outerjoin( + rp_to_root, parent_rp, + rp.c.parent_provider_id == parent_rp.c.id) - # TODO(jaypipes): Convert this to an inner join once all - # root_provider_id values are NOT NULL - rp_to_root = sa.outerjoin( - rp, root_rp, - rp.c.root_provider_id == root_rp.c.id) - rp_to_parent = sa.outerjoin( - rp_to_root, parent_rp, - rp.c.parent_provider_id == parent_rp.c.id) + query = sa.select(cols).select_from(rp_to_parent) - query = sa.select(cols).select_from(rp_to_parent) - - if name: - query = query.where(rp.c.name == name) - if uuid: - query = query.where(rp.c.uuid == uuid) - if 'in_tree' in filters: - # The 'in_tree' parameter is the UUID of a resource provider that - # the caller wants to limit the returned providers to only those - # within its "provider tree". So, we look up the resource provider - # having the UUID specified by the 'in_tree' parameter and grab the - # root_provider_id value of that record. We can then ask for only - # those resource providers having a root_provider_id of that value. - tree_uuid = filters.pop('in_tree') - tree_ids = provider_ids_from_uuid(context, tree_uuid) - if tree_ids is None: - # List operations should simply return an empty list when a - # non-existing resource provider UUID is given. - return [] - root_id = tree_ids.root_id - # TODO(jaypipes): Remove this OR condition when root_provider_id - # is not nullable in the database and all resource provider records - # have populated the root provider ID. - where_cond = sa.or_( - rp.c.id == root_id, - rp.c.root_provider_id == root_id) - query = query.where(where_cond) - - # Get the provider IDs matching any specified traits and/or aggregates - rp_ids, forbidden_rp_ids = get_provider_ids_for_traits_and_aggs( - context, required, forbidden, member_of) - if rp_ids is None: - # If no providers match the traits/aggs, we can short out + if name: + query = query.where(rp.c.name == name) + if uuid: + query = query.where(rp.c.uuid == uuid) + if 'in_tree' in filters: + # The 'in_tree' parameter is the UUID of a resource provider that + # the caller wants to limit the returned providers to only those + # within its "provider tree". So, we look up the resource provider + # having the UUID specified by the 'in_tree' parameter and grab the + # root_provider_id value of that record. We can then ask for only + # those resource providers having a root_provider_id of that value. + tree_uuid = filters.pop('in_tree') + tree_ids = provider_ids_from_uuid(context, tree_uuid) + if tree_ids is None: + # List operations should simply return an empty list when a + # non-existing resource provider UUID is given. return [] - if rp_ids: - query = query.where(rp.c.id.in_(rp_ids)) - # forbidden providers, if found, are mutually exclusive with matching - # providers above, so we only need to include this clause if we didn't - # use the positive filter above. - elif forbidden_rp_ids: - query = query.where(~rp.c.id.in_(forbidden_rp_ids)) + root_id = tree_ids.root_id + # TODO(jaypipes): Remove this OR condition when root_provider_id + # is not nullable in the database and all resource provider records + # have populated the root provider ID. + where_cond = sa.or_( + rp.c.id == root_id, + rp.c.root_provider_id == root_id) + query = query.where(where_cond) - if not resources: - # Returns quickly the list in case we don't need to check the - # resource usage - res = context.session.execute(query).fetchall() - return [dict(r) for r in res] - - # NOTE(sbauza): In case we want to look at the resource criteria, then - # the SQL generated from this case looks something like: - # SELECT - # rp.* - # FROM resource_providers AS rp - # JOIN inventories AS inv - # ON rp.id = inv.resource_provider_id - # LEFT JOIN ( - # SELECT resource_provider_id, resource_class_id, SUM(used) AS used - # FROM allocations - # WHERE resource_class_id IN ($RESOURCE_CLASSES) - # GROUP BY resource_provider_id, resource_class_id - # ) AS usage - # ON inv.resource_provider_id = usage.resource_provider_id - # AND inv.resource_class_id = usage.resource_class_id - # AND (inv.resource_class_id = $X AND (used + $AMOUNT_X <= ( - # total - reserved) * inv.allocation_ratio) AND - # inv.min_unit <= $AMOUNT_X AND inv.max_unit >= $AMOUNT_X AND - # $AMOUNT_X % inv.step_size == 0) - # OR (inv.resource_class_id = $Y AND (used + $AMOUNT_Y <= ( - # total - reserved) * inv.allocation_ratio) AND - # inv.min_unit <= $AMOUNT_Y AND inv.max_unit >= $AMOUNT_Y AND - # $AMOUNT_Y % inv.step_size == 0) - # OR (inv.resource_class_id = $Z AND (used + $AMOUNT_Z <= ( - # total - reserved) * inv.allocation_ratio) AND - # inv.min_unit <= $AMOUNT_Z AND inv.max_unit >= $AMOUNT_Z AND - # $AMOUNT_Z % inv.step_size == 0)) - # GROUP BY rp.id - # HAVING - # COUNT(DISTINCT(inv.resource_class_id)) == len($RESOURCE_CLASSES) - # - # with a possible additional WHERE clause for the name and uuid that - # comes from the above filters - - # First JOIN between inventories and RPs is here - inv_join = sa.join( - rp_to_parent, - _INV_TBL, - rp.c.id == _INV_TBL.c.resource_provider_id) - - # Now, below is the LEFT JOIN for getting the allocations usage - usage = _usage_select(list(resources)) - usage_join = sa.outerjoin( - inv_join, usage, sa.and_( - usage.c.resource_provider_id == ( - _INV_TBL.c.resource_provider_id), - usage.c.resource_class_id == _INV_TBL.c.resource_class_id)) - - # And finally, we verify for each resource class if the requested - # amount isn't more than the left space (considering the allocation - # ratio, the reserved space and the min and max amount possible sizes) - where_clauses = [ - sa.and_( - _INV_TBL.c.resource_class_id == r_idx, - _capacity_check_clause(amount, usage) - ) - for (r_idx, amount) in resources.items()] - query = query.select_from(usage_join) - query = query.where(sa.or_(*where_clauses)) - query = query.group_by(rp.c.id, root_rp.c.uuid, parent_rp.c.uuid) - # NOTE(sbauza): Only RPs having all the asked resources can be provided - query = query.having(sql.func.count( - sa.distinct(_INV_TBL.c.resource_class_id)) == len(resources)) + # Get the provider IDs matching any specified traits and/or aggregates + rp_ids, forbidden_rp_ids = get_provider_ids_for_traits_and_aggs( + context, required, forbidden, member_of) + if rp_ids is None: + # If no providers match the traits/aggs, we can short out + return [] + if rp_ids: + query = query.where(rp.c.id.in_(rp_ids)) + # forbidden providers, if found, are mutually exclusive with matching + # providers above, so we only need to include this clause if we didn't + # use the positive filter above. + elif forbidden_rp_ids: + query = query.where(~rp.c.id.in_(forbidden_rp_ids)) + if not resources: + # Returns quickly the list in case we don't need to check the + # resource usage res = context.session.execute(query).fetchall() return [dict(r) for r in res] - @classmethod - def get_all_by_filters(cls, context, filters=None): - """Returns a list of `ResourceProvider` objects that have sufficient - resources in their inventories to satisfy the amounts specified in the - `filters` parameter. + # NOTE(sbauza): In case we want to look at the resource criteria, then + # the SQL generated from this case looks something like: + # SELECT + # rp.* + # FROM resource_providers AS rp + # JOIN inventories AS inv + # ON rp.id = inv.resource_provider_id + # LEFT JOIN ( + # SELECT resource_provider_id, resource_class_id, SUM(used) AS used + # FROM allocations + # WHERE resource_class_id IN ($RESOURCE_CLASSES) + # GROUP BY resource_provider_id, resource_class_id + # ) AS usage + # ON inv.resource_provider_id = usage.resource_provider_id + # AND inv.resource_class_id = usage.resource_class_id + # AND (inv.resource_class_id = $X AND (used + $AMOUNT_X <= ( + # total - reserved) * inv.allocation_ratio) AND + # inv.min_unit <= $AMOUNT_X AND inv.max_unit >= $AMOUNT_X AND + # $AMOUNT_X % inv.step_size == 0) + # OR (inv.resource_class_id = $Y AND (used + $AMOUNT_Y <= ( + # total - reserved) * inv.allocation_ratio) AND + # inv.min_unit <= $AMOUNT_Y AND inv.max_unit >= $AMOUNT_Y AND + # $AMOUNT_Y % inv.step_size == 0) + # OR (inv.resource_class_id = $Z AND (used + $AMOUNT_Z <= ( + # total - reserved) * inv.allocation_ratio) AND + # inv.min_unit <= $AMOUNT_Z AND inv.max_unit >= $AMOUNT_Z AND + # $AMOUNT_Z % inv.step_size == 0)) + # GROUP BY rp.id + # HAVING + # COUNT(DISTINCT(inv.resource_class_id)) == len($RESOURCE_CLASSES) + # + # with a possible additional WHERE clause for the name and uuid that + # comes from the above filters - If no resource providers can be found, the function will return an - empty list. + # First JOIN between inventories and RPs is here + inv_join = sa.join( + rp_to_parent, + _INV_TBL, + rp.c.id == _INV_TBL.c.resource_provider_id) - :param context: `placement.context.RequestContext` that may be used to - grab a DB connection. - :param filters: Can be `name`, `uuid`, `member_of`, `in_tree` or - `resources` where `member_of` is a list of list of - aggregate UUIDs, `in_tree` is a UUID of a resource - provider that we can use to find the root provider ID - of the tree of providers to filter results by and - `resources` is a dict of amounts keyed by resource - classes. - :type filters: dict - """ - resource_providers = cls._get_all_by_filters_from_db(context, filters) - return cls._set_objects(context, resource_providers) + # Now, below is the LEFT JOIN for getting the allocations usage + usage = _usage_select(list(resources)) + usage_join = sa.outerjoin( + inv_join, usage, sa.and_( + usage.c.resource_provider_id == ( + _INV_TBL.c.resource_provider_id), + usage.c.resource_class_id == _INV_TBL.c.resource_class_id)) + + # And finally, we verify for each resource class if the requested + # amount isn't more than the left space (considering the allocation + # ratio, the reserved space and the min and max amount possible sizes) + where_clauses = [ + sa.and_( + _INV_TBL.c.resource_class_id == r_idx, + _capacity_check_clause(amount, usage) + ) + for (r_idx, amount) in resources.items()] + query = query.select_from(usage_join) + query = query.where(sa.or_(*where_clauses)) + query = query.group_by(rp.c.id, root_rp.c.uuid, parent_rp.c.uuid) + # NOTE(sbauza): Only RPs having all the asked resources can be provided + query = query.having(sql.func.count( + sa.distinct(_INV_TBL.c.resource_class_id)) == len(resources)) + + res = context.session.execute(query).fetchall() + return [dict(r) for r in res] + + +def get_all_by_filters(context, filters=None): + """Returns a list of `ResourceProvider` objects that have sufficient + resources in their inventories to satisfy the amounts specified in the + `filters` parameter. + + If no resource providers can be found, the function will return an + empty list. + + :param context: `placement.context.RequestContext` that may be used to + grab a DB connection. + :param filters: Can be `name`, `uuid`, `member_of`, `in_tree` or + `resources` where `member_of` is a list of list of + aggregate UUIDs, `in_tree` is a UUID of a resource + provider that we can use to find the root provider ID + of the tree of providers to filter results by and + `resources` is a dict of amounts keyed by resource + classes. + :type filters: dict + """ + resource_providers = _get_all_by_filters_from_db(context, filters) + return [ResourceProvider(context, **rp) for rp in resource_providers] @db_api.placement_context_manager.reader diff --git a/placement/tests/functional/db/test_resource_provider.py b/placement/tests/functional/db/test_resource_provider.py index 382cdc8db..81c76585d 100644 --- a/placement/tests/functional/db/test_resource_provider.py +++ b/placement/tests/functional/db/test_resource_provider.py @@ -186,7 +186,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): # Check the new-style providers remains in a tree, # which means the root provider ids are not changed - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'in_tree': uuidsentinel.root_rp, @@ -282,7 +282,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): tb.add_inventory(grandchild_rp, orc.VCPU, 1) # Check all providers returned when getting by root UUID - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'in_tree': uuidsentinel.root_rp, @@ -291,7 +291,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): self.assertEqual(3, len(rps)) # Check all providers returned when getting by child UUID - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'in_tree': uuidsentinel.child_rp, @@ -300,7 +300,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): self.assertEqual(3, len(rps)) # Check all providers returned when getting by grandchild UUID - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'in_tree': uuidsentinel.grandchild_rp, @@ -313,7 +313,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): # No aggregate associations yet, so expect no records when adding a # member_of filter - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'member_of': [[uuidsentinel.agg]], @@ -326,7 +326,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): # the grandchild is returned when asking for the grandchild's tree # along with the aggregate as member_of grandchild_rp.set_aggregates([uuidsentinel.agg]) - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'member_of': [[uuidsentinel.agg]], @@ -337,7 +337,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): self.assertEqual(uuidsentinel.grandchild_rp, rps[0].uuid) # Try filtering on an unknown UUID and verify no results - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'uuid': uuidsentinel.unknown_rp, @@ -348,7 +348,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): # And now check that filtering for just the child's UUID along with the # tree produces just a single provider (the child) - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'uuid': uuidsentinel.child_rp, @@ -361,7 +361,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): # Ensure that the resources filter also continues to work properly with # the in_tree filter. Request resources that none of the providers # currently have and ensure no providers are returned - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'in_tree': uuidsentinel.grandchild_rp, @@ -373,7 +373,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): self.assertEqual(0, len(rps)) # And now ask for one VCPU, which should only return us the grandchild - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'in_tree': uuidsentinel.grandchild_rp, @@ -387,7 +387,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): # Finally, verify we still get the grandchild if filtering on the # parent's UUID as in_tree - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'in_tree': uuidsentinel.child_rp, @@ -426,13 +426,13 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): """ # Passing a non-existing resource provider UUID should return an empty # list - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'in_tree': uuidsentinel.rp1, } ) - self.assertEqual([], rps.objects) + self.assertEqual([], rps) rp_tbl = rp_obj._RP_TBL conn = self.placement_db.get_engine().connect() @@ -454,7 +454,7 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase): # don't have any migrations messing with the end result. with mock.patch('placement.objects.resource_provider.' '_set_root_provider_id'): - rps = rp_obj.ResourceProviderList.get_all_by_filters( + rps = rp_obj.get_all_by_filters( self.ctx, filters={ 'in_tree': uuidsentinel.rp1, @@ -796,13 +796,13 @@ class ResourceProviderListTestCase(tb.PlacementDbBaseTestCase): 'rp_name_' + rp_i, uuid=getattr(uuidsentinel, 'rp_uuid_' + rp_i)) - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx) self.assertEqual(2, len(resource_providers)) - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, filters={'name': u'rp_name_1'}) self.assertEqual(1, len(resource_providers)) - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, filters={'uuid': uuidsentinel.rp_uuid_2}) self.assertEqual(1, len(resource_providers)) self.assertEqual('rp_name_2', resource_providers[0].name) @@ -824,55 +824,55 @@ class ResourceProviderListTestCase(tb.PlacementDbBaseTestCase): # Both RPs should accept that request given the only current allocation # for the first RP is leaving one VCPU - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, {'resources': {orc.VCPU: 1}}) self.assertEqual(2, len(resource_providers)) # Now, when asking for 2 VCPUs, only the second RP should accept that # given the current allocation for the first RP - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, {'resources': {orc.VCPU: 2}}) self.assertEqual(1, len(resource_providers)) # Adding a second resource request should be okay for the 2nd RP # given it has enough disk but we also need to make sure that the # first RP is not acceptable because of the VCPU request - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, {'resources': {orc.VCPU: 2, orc.DISK_GB: 1022}}) self.assertEqual(1, len(resource_providers)) # Now, we are asking for both disk and VCPU resources that all the RPs # can't accept (as the 2nd RP is having a reserved size) - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, {'resources': {orc.VCPU: 2, orc.DISK_GB: 1024}}) self.assertEqual(0, len(resource_providers)) # We also want to verify that asking for a specific RP can also be # checking the resource usage. - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, {'name': u'rp_name_1', 'resources': {orc.VCPU: 1}}) self.assertEqual(1, len(resource_providers)) # Let's verify that the min and max units are checked too # Case 1: amount is in between min and max and modulo step_size - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, {'resources': {orc.MEMORY_MB: 2}}) self.assertEqual(2, len(resource_providers)) # Case 2: amount is less than min_unit - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, {'resources': {orc.MEMORY_MB: 1}}) self.assertEqual(0, len(resource_providers)) # Case 3: amount is more than min_unit - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, {'resources': {orc.MEMORY_MB: 5}}) self.assertEqual(0, len(resource_providers)) # Case 4: amount is not modulo step_size - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, {'resources': {orc.MEMORY_MB: 3}}) self.assertEqual(0, len(resource_providers)) def test_get_all_by_filters_with_resources_not_existing(self): self.assertRaises( exception.ResourceClassNotFound, - rp_obj.ResourceProviderList.get_all_by_filters, + rp_obj.get_all_by_filters, self.ctx, {'resources': {'FOOBAR': 3}}) def test_get_all_by_filters_aggregate(self): @@ -882,7 +882,7 @@ class ResourceProviderListTestCase(tb.PlacementDbBaseTestCase): 'rp_name_' + str(rp_i), *aggs, uuid=getattr(uuidsentinel, 'rp_uuid_' + str(rp_i))) - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, filters={'member_of': [[uuidsentinel.agg_a]]}) self.assertEqual(2, len(resource_providers)) @@ -892,24 +892,24 @@ class ResourceProviderListTestCase(tb.PlacementDbBaseTestCase): self.assertNotIn('rp_name_2', names) self.assertNotIn('rp_name_4', names) - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, filters={'member_of': [[uuidsentinel.agg_a, uuidsentinel.agg_b]]}) self.assertEqual(2, len(resource_providers)) - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, filters={'member_of': [[uuidsentinel.agg_a, uuidsentinel.agg_b]], 'name': u'rp_name_1'}) self.assertEqual(1, len(resource_providers)) - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, filters={'member_of': [[uuidsentinel.agg_a, uuidsentinel.agg_b]], 'name': u'barnabas'}) self.assertEqual(0, len(resource_providers)) - resource_providers = rp_obj.ResourceProviderList.get_all_by_filters( + resource_providers = rp_obj.get_all_by_filters( self.ctx, filters={'member_of': [[uuidsentinel.agg_1, uuidsentinel.agg_2]]}) self.assertEqual(0, len(resource_providers)) @@ -931,7 +931,7 @@ class ResourceProviderListTestCase(tb.PlacementDbBaseTestCase): tb.set_traits(rp, *traits) # Three rps (1, 2, 3) should have CUSTOM_TRAIT_A - custom_a_rps = rp_obj.ResourceProviderList.get_all_by_filters( + custom_a_rps = rp_obj.get_all_by_filters( self.ctx, filters={'required': ['CUSTOM_TRAIT_A']}) self.assertEqual(3, len(custom_a_rps)) rp_names = [a_rp.name for a_rp in custom_a_rps] @@ -940,7 +940,7 @@ class ResourceProviderListTestCase(tb.PlacementDbBaseTestCase): # One rp (rp 1) if we forbid CUSTOM_TRAIT_B, with a single trait of # CUSTOM_TRAIT_A - custom_a_rps = rp_obj.ResourceProviderList.get_all_by_filters( + custom_a_rps = rp_obj.get_all_by_filters( self.ctx, filters={'required': ['CUSTOM_TRAIT_A', '!CUSTOM_TRAIT_B']}) self.assertEqual(1, len(custom_a_rps))