From 0b7946f5a3dd62003bdfead068dd58bd58ed6d18 Mon Sep 17 00:00:00 2001 From: Tetsuro Nakamura Date: Tue, 31 Jul 2018 19:10:56 +0900 Subject: [PATCH] Ensure the order of AllocationRequestResources Getting allocation candidates with sharing providers, placement creates a list of AllocationRequestResources to get all the possible combinations of resource providers in the same aggregate. However, the order of the list was arbitrary, which could cause a bug later in duplicate check of the combination. This patch ensures that the list is ordered by the resource class id. Note: This bug is only exposed when it is tested with python3.6, where order-preserving aspect is added to the dict object. Change-Id: I2e236fbbc3a4cfd3bd66d50198de643e06d62331 Closes-Bug: #1784577 --- .../placement/objects/resource_provider.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/nova/api/openstack/placement/objects/resource_provider.py b/nova/api/openstack/placement/objects/resource_provider.py index 1c7e5a01c2e1..71ef987e7357 100644 --- a/nova/api/openstack/placement/objects/resource_provider.py +++ b/nova/api/openstack/placement/objects/resource_provider.py @@ -3514,14 +3514,28 @@ def _alloc_candidates_multiple_providers(ctx, requested_resources, # Let's look into each tree for root_id, alloc_dict in tree_dict.items(): # Get request_groups, which is a list of lists of - # AllocationRequestResource per requested resource class. - request_groups = alloc_dict.values() + # AllocationRequestResource(ARR) per requested resource class(rc). + # For example, if we have the alloc_dict: + # {rc1_id: [ARR(rc1, rp1), ARR(rc1, rp2)], + # rc2_id: [ARR(rc2, rp1), ARR(rc2, rp2)], + # rc3_id: [ARR(rc3, rp1)]} + # then the request_groups would be something like + # [[ARR(rc1, rp1), ARR(rc1, rp2)], + # [ARR(rc2, rp1), ARR(rc2, rp2)], + # [ARR(rc3, rp1)]] + # , which should be ordered by the resource class id. + request_groups = [val for key, val in sorted(alloc_dict.items())] root_summary = summaries[root_id] root_uuid = root_summary.resource_provider.uuid # Using itertools.product, we get all the combinations of resource # providers in a tree. + # For example, the sample in the comment above becomes: + # [(ARR(rc1, ss1), ARR(rc2, ss1), ARR(rc3, ss1)), + # (ARR(rc1, ss1), ARR(rc2, ss2), ARR(rc3, ss1)), + # (ARR(rc1, ss2), ARR(rc2, ss1), ARR(rc3, ss1)), + # (ARR(rc1, ss2), ARR(rc2, ss2), ARR(rc3, ss1))] for res_requests in itertools.product(*request_groups): all_prov_ids = _check_traits_for_alloc_request(res_requests, summaries, prov_traits, required_traits, forbidden_traits)