Correctly limit provider summaries when nested

When making a GET /allocation_candidates request with the 'limit'
parameter, include all the providers in the same tree as the providers
mentioned in the allocation requests. That is, in a nested situation,
if we limit the allocation requests to 10, we would usually expect
considerably more than 10 providers in provider summaries, to include
any non-contributing providers in the same tree.

Accomplish this by filtering provider summaries on root_provider_uuid
instead of individual provider uuid.

A gabbi test is added which exercises this in a nested situation.

An existing test is updated to reflect the new filtering style. It
does not exercise the nested scenario.

A reno is added indicating the fix.

Change-Id: I136bd7cd89f1bd54f0d1691268545850af234f18
Story: 2005859
Task: 33654
This commit is contained in:
Chris Dent 2019-06-11 14:29:55 +01:00
parent c919b1f568
commit e1783b0087
4 changed files with 47 additions and 16 deletions

View File

@ -188,16 +188,17 @@ class AllocationCandidates(object):
alloc_request_objs = alloc_request_objs[:limit]
# 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.
alloc_req_root_uuids = set()
# Extract root resource provider uuids from the resource requests.
for aro in alloc_request_objs:
for arr in aro.resource_requests:
alloc_req_rp_uuids.add(arr.resource_provider.uuid)
alloc_req_root_uuids.add(
arr.resource_provider.root_provider_uuid)
for summary in summary_objs:
rp_uuid = summary.resource_provider.uuid
rp_root_uuid = summary.resource_provider.root_provider_uuid
# Skip a summary if we are limiting and haven't selected an
# allocation request that uses the resource provider.
if rp_uuid not in alloc_req_rp_uuids:
if rp_root_uuid not in alloc_req_root_uuids:
continue
kept_summary_objs.append(summary)
summary_objs = kept_summary_objs

View File

@ -427,6 +427,19 @@ tests:
$.allocation_requests..allocations["$ENVIRON['PF2_1_UUID']"].resources.SRIOV_NET_VF: 4
$.allocation_requests..allocations["$ENVIRON['PF2_2_UUID']"].resources.SRIOV_NET_VF: 4
- name: get allocation candidates nested limit
desc: confirm provider summaries are complete, fixes story/2005859
GET: /allocation_candidates?resources=VCPU:1,SRIOV_NET_VF:4&limit=1
status: 200
request_headers:
openstack-api-version: placement 1.29
response_json_paths:
$.allocation_requests.`len`: 1
$.allocation_requests[0].allocations.`len`: 2
# We expect all the providers that share roots with the allocations.
# In this case it the compute node, its two numa nodes and its two pfs.
$.provider_summaries.`len`: 5
# Make sure that old microversions can return combinations where
# sharing providers are involved
- name: get allocation candidates shared and nested old microversion

View File

@ -18,28 +18,34 @@ from placement.tests.unit.objects import base
class TestAllocationCandidatesNoDB(base.TestCase):
def test_limit_results(self):
# UUIDs don't have to be real UUIDs to test the logic
# Results are limited based on their root provider uuid, not uuid.
# For a more "real" test of this functionality, one that exercises
# nested providers, see the 'get allocation candidates nested limit'
# test in the 'allocation-candidates.yaml' gabbit.
aro_in = [
mock.Mock(
resource_requests=[
mock.Mock(resource_provider=mock.Mock(uuid=uuid))
mock.Mock(resource_provider=mock.Mock(
root_provider_uuid=uuid))
for uuid in (1, 0, 4, 8)]),
mock.Mock(
resource_requests=[
mock.Mock(resource_provider=mock.Mock(uuid=uuid))
mock.Mock(resource_provider=mock.Mock(
root_provider_uuid=uuid))
for uuid in (4, 8, 5)]),
mock.Mock(
resource_requests=[
mock.Mock(resource_provider=mock.Mock(uuid=uuid))
mock.Mock(resource_provider=mock.Mock(
root_provider_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))
sum1 = mock.Mock(resource_provider=mock.Mock(root_provider_uuid=1))
sum0 = mock.Mock(resource_provider=mock.Mock(root_provider_uuid=0))
sum4 = mock.Mock(resource_provider=mock.Mock(root_provider_uuid=4))
sum8 = mock.Mock(resource_provider=mock.Mock(root_provider_uuid=8))
sum5 = mock.Mock(resource_provider=mock.Mock(root_provider_uuid=5))
sum7 = mock.Mock(resource_provider=mock.Mock(root_provider_uuid=7))
sum6 = mock.Mock(resource_provider=mock.Mock(root_provider_uuid=6))
sum_in = [sum1, sum0, sum4, sum8, sum5, sum7, sum6]
aro, sum = allocation_candidate.AllocationCandidates._limit_results(
self.context, aro_in, sum_in, 2)

View File

@ -0,0 +1,11 @@
---
fixes:
- |
Limiting nested resource providers with the ``limit=N`` query parameter
when calling ``GET /allocation_candidates`` could result in incomplete
provider summaries. This is now fixed so that all resource providers that
are in the same trees as any provider mentioned in the limited allocation
requests are shown in the provider summaries collection. For more
information see `story/2005859`_.
.. _story/2005859: https://storyboard.openstack.org/#!/story/2005859