diff --git a/placement/objects/resource_provider.py b/placement/objects/resource_provider.py index 69c1ebcd4..293c14a30 100644 --- a/placement/objects/resource_provider.py +++ b/placement/objects/resource_provider.py @@ -4120,20 +4120,20 @@ class AllocationCandidates(base.VersionedObject): alloc_request_objs, summary_objs = _merge_candidates( candidates, group_policy=group_policy) + return cls._limit_results(alloc_request_objs, summary_objs, limit) + + @staticmethod + def _limit_results(alloc_request_objs, summary_objs, limit): # Limit the number of allocation request objects. We do this after # creating all of them so that we can do a random slice without # needing to mess with the complex sql above or add additional # columns to the DB. - if limit and limit <= len(alloc_request_objs): + if limit and limit < len(alloc_request_objs): if CONF.placement.randomize_allocation_candidates: alloc_request_objs = random.sample(alloc_request_objs, limit) else: alloc_request_objs = alloc_request_objs[:limit] - elif CONF.placement.randomize_allocation_candidates: - random.shuffle(alloc_request_objs) - - # Limit summaries to only those mentioned in the allocation requests. - if limit and limit <= len(alloc_request_objs): + # Limit summaries to only those mentioned in the allocation reqs. kept_summary_objs = [] alloc_req_rp_uuids = set() # Extract resource provider uuids from the resource requests. @@ -4147,10 +4147,11 @@ class AllocationCandidates(base.VersionedObject): if rp_uuid not in alloc_req_rp_uuids: continue kept_summary_objs.append(summary) - else: - kept_summary_objs = summary_objs + summary_objs = kept_summary_objs + elif CONF.placement.randomize_allocation_candidates: + random.shuffle(alloc_request_objs) - return alloc_request_objs, kept_summary_objs + return alloc_request_objs, summary_objs @db_api.placement_context_manager.writer diff --git a/placement/tests/unit/objects/test_resource_provider.py b/placement/tests/unit/objects/test_resource_provider.py index ebc2227ae..c9cb3fd25 100644 --- a/placement/tests/unit/objects/test_resource_provider.py +++ b/placement/tests/unit/objects/test_resource_provider.py @@ -328,3 +328,34 @@ class TestTraits(_TestCase): rp.set_traits(traits) mock_set_traits.assert_called_once_with(self.context, rp, traits) mock_reset.assert_called_once_with() + + +class TestAllocationCandidatesNoDB(_TestCase): + def test_limit_results(self): + # UUIDs don't have to be real UUIDs to test the logic + aro_in = [ + mock.Mock( + resource_requests=[ + mock.Mock(resource_provider=mock.Mock(uuid=uuid)) + for uuid in (1, 0, 4, 8)]), + mock.Mock( + resource_requests=[ + mock.Mock(resource_provider=mock.Mock(uuid=uuid)) + for uuid in (4, 8, 5)]), + mock.Mock( + resource_requests=[ + mock.Mock(resource_provider=mock.Mock(uuid=uuid)) + for uuid in (1, 7, 6, 4, 8, 5)]), + ] + sum1 = mock.Mock(resource_provider=mock.Mock(uuid=1)) + sum0 = mock.Mock(resource_provider=mock.Mock(uuid=0)) + sum4 = mock.Mock(resource_provider=mock.Mock(uuid=4)) + sum8 = mock.Mock(resource_provider=mock.Mock(uuid=8)) + sum5 = mock.Mock(resource_provider=mock.Mock(uuid=5)) + sum7 = mock.Mock(resource_provider=mock.Mock(uuid=7)) + sum6 = mock.Mock(resource_provider=mock.Mock(uuid=6)) + sum_in = [sum1, sum0, sum4, sum8, sum5, sum7, sum6] + aro, sum = resource_provider.AllocationCandidates._limit_results( + aro_in, sum_in, 2) + self.assertEqual(aro_in[:2], aro) + self.assertEqual(set([sum1, sum0, sum4, sum8, sum5]), set(sum))