Merge "Fix allocation_candidates not to ignore shared RPs"
This commit is contained in:
commit
c683518ecb
@ -3301,6 +3301,10 @@ def _alloc_candidates_with_shared(ctx, requested_resources, required_traits,
|
|||||||
prov_aggregates = _provider_aggregates(ctx, all_rp_ids)
|
prov_aggregates = _provider_aggregates(ctx, all_rp_ids)
|
||||||
|
|
||||||
for ns_rp_id in ns_rp_ids:
|
for ns_rp_id in ns_rp_ids:
|
||||||
|
# Build a dict, keyed by resource class ID, of lists of
|
||||||
|
# AllocationRequestResource objects
|
||||||
|
res_req_dict = collections.defaultdict(list)
|
||||||
|
|
||||||
if ns_rp_id not in summaries:
|
if ns_rp_id not in summaries:
|
||||||
# This resource provider is not providing any resources that have
|
# This resource provider is not providing any resources that have
|
||||||
# been requested. This means that this resource provider has some
|
# been requested. This means that this resource provider has some
|
||||||
@ -3319,13 +3323,6 @@ def _alloc_candidates_with_shared(ctx, requested_resources, required_traits,
|
|||||||
rc_id for rc_id in requested_resources
|
rc_id for rc_id in requested_resources
|
||||||
if _RC_CACHE.string_from_id(rc_id) in ns_resource_class_names
|
if _RC_CACHE.string_from_id(rc_id) in ns_resource_class_names
|
||||||
)
|
)
|
||||||
shared_resources = set(requested_resources) - ns_resources
|
|
||||||
|
|
||||||
# We need to figure out which traits are NOT provided by the "local"
|
|
||||||
# provider and that would need to be provided by the sharing
|
|
||||||
# provider(s)
|
|
||||||
ns_prov_traits = set(prov_traits.get(ns_rp_id, []))
|
|
||||||
missing_traits = set(required_traits) - ns_prov_traits
|
|
||||||
|
|
||||||
has_none = len(ns_resources) == 0
|
has_none = len(ns_resources) == 0
|
||||||
if has_none:
|
if has_none:
|
||||||
@ -3335,18 +3332,16 @@ def _alloc_candidates_with_shared(ctx, requested_resources, required_traits,
|
|||||||
# list it in provider_summaries.
|
# list it in provider_summaries.
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Add an AllocationRequest that includes resources from the
|
# Get AllocationRequestResource(s) from the non-sharing provider
|
||||||
# non-sharing provider AND shared resources from each sharing
|
for rc_id, amount in requested_resources.items():
|
||||||
# provider of that resource class. This is where we construct all the
|
if rc_id not in ns_resources:
|
||||||
# possible permutations of non-shared resources and shared resources.
|
continue
|
||||||
ns_res_requests = [
|
res_req_dict[rc_id].append(
|
||||||
AllocationRequestResource(
|
AllocationRequestResource(
|
||||||
ctx, resource_provider=ResourceProvider(ctx, uuid=ns_rp_uuid),
|
ctx, resource_provider=ResourceProvider(ctx,
|
||||||
resource_class=_RC_CACHE.string_from_id(rc_id),
|
uuid=ns_rp_uuid),
|
||||||
amount=amount,
|
resource_class=_RC_CACHE.string_from_id(rc_id),
|
||||||
) for rc_id, amount in requested_resources.items()
|
amount=amount))
|
||||||
if rc_id in ns_resources
|
|
||||||
]
|
|
||||||
|
|
||||||
# Build a dict, keyed by resource class ID, of lists of
|
# Build a dict, keyed by resource class ID, of lists of
|
||||||
# AllocationRequestResource objects that represent each
|
# AllocationRequestResource objects that represent each
|
||||||
@ -3355,48 +3350,50 @@ def _alloc_candidates_with_shared(ctx, requested_resources, required_traits,
|
|||||||
ctx, ns_rp_id, requested_resources,
|
ctx, ns_rp_id, requested_resources,
|
||||||
sharing, summaries, prov_aggregates)
|
sharing, summaries, prov_aggregates)
|
||||||
|
|
||||||
# A list of lists of AllocationRequestResource objects for each type of
|
# Get AllocationRequestResource(s) from sharing provider(s)
|
||||||
# shared resource class
|
for rc_id in sharing_resource_requests:
|
||||||
shared_request_groups = [
|
sharing_res_reqs = sharing_resource_requests[rc_id]
|
||||||
sharing_resource_requests[shared_rc_id]
|
res_req_dict[rc_id].extend(sharing_res_reqs)
|
||||||
for shared_rc_id in shared_resources
|
|
||||||
]
|
|
||||||
for shared_res_requests in itertools.product(*shared_request_groups):
|
|
||||||
# Before we add the allocation request to our list, we first need
|
|
||||||
# to ensure that the sharing providers involved in this allocation
|
|
||||||
# request have all of the traits that the non-sharing providers
|
|
||||||
# don't have
|
|
||||||
sharing_prov_ids = set()
|
|
||||||
sharing_traits = set()
|
|
||||||
for shared_res_req in shared_res_requests:
|
|
||||||
sharing_rp_uuid = shared_res_req.resource_provider.uuid
|
|
||||||
shared_rp_id = None
|
|
||||||
for rp_id, summary in summaries.items():
|
|
||||||
if summary.resource_provider.uuid == sharing_rp_uuid:
|
|
||||||
shared_rp_id = rp_id
|
|
||||||
break
|
|
||||||
sharing_prov_ids.add(shared_rp_id)
|
|
||||||
share_prov_traits = prov_traits.get(shared_rp_id, [])
|
|
||||||
sharing_traits |= set(share_prov_traits)
|
|
||||||
|
|
||||||
# Check if there are missing traits with sharing providers
|
# Get request_groups, lists of lists of AllocationRequestResource
|
||||||
still_missing_traits = missing_traits - sharing_traits
|
# for each resource class, which makes no distinction between
|
||||||
if still_missing_traits:
|
# non-sharing resource providers and sharing resource providers.
|
||||||
LOG.debug('Excluding non-sharing provider %s with sharing '
|
request_groups = res_req_dict.values()
|
||||||
'providers %s: missing traits %s are not satisfied '
|
|
||||||
'by sharing providers.',
|
# Add an AllocationRequest that includes resources from the
|
||||||
ns_rp_uuid, sharing_prov_ids,
|
# non-sharing provider AND shared resources from each sharing
|
||||||
','.join(still_missing_traits))
|
# provider of that resource class. This is where we construct all the
|
||||||
|
# possible permutations of non-shared resources and shared resources.
|
||||||
|
for res_requests in itertools.product(*request_groups):
|
||||||
|
# Before we add the allocation request to our list, we first need
|
||||||
|
# to ensure that the resource providers involved in this allocation
|
||||||
|
# request have all of the traits
|
||||||
|
all_prov_ids = set()
|
||||||
|
all_traits = set()
|
||||||
|
for res_req in res_requests:
|
||||||
|
rp_uuid = res_req.resource_provider.uuid
|
||||||
|
rp_id = None
|
||||||
|
for id, summary in summaries.items():
|
||||||
|
if summary.resource_provider.uuid == rp_uuid:
|
||||||
|
rp_id = id
|
||||||
|
break
|
||||||
|
all_prov_ids.add(rp_id)
|
||||||
|
all_traits |= set(prov_traits.get(rp_id, []))
|
||||||
|
|
||||||
|
# Check if there are missing traits
|
||||||
|
missing_traits = set(required_traits) - all_traits
|
||||||
|
if missing_traits:
|
||||||
|
LOG.debug('Excluding a set of allocation candidate %s : '
|
||||||
|
'missing traits %s are not satisfied.',
|
||||||
|
all_prov_ids, ','.join(missing_traits))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check if we already have this combination in alloc_requests
|
# Check if we already have this combination in alloc_requests
|
||||||
prov_ids = set([ns_rp_id]) | sharing_prov_ids
|
if all_prov_ids in alloc_prov_ids:
|
||||||
if prov_ids in alloc_prov_ids:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
alloc_prov_ids.append(prov_ids)
|
alloc_prov_ids.append(all_prov_ids)
|
||||||
resource_requests = ns_res_requests + list(shared_res_requests)
|
req = AllocationRequest(ctx, resource_requests=list(res_requests))
|
||||||
req = AllocationRequest(ctx, resource_requests=resource_requests)
|
|
||||||
alloc_requests.append(req)
|
alloc_requests.append(req)
|
||||||
|
|
||||||
# The process above may have removed some previously-identified resource
|
# The process above may have removed some previously-identified resource
|
||||||
|
@ -1009,11 +1009,9 @@ class AllocationCandidatesTestCase(ProviderDBBase):
|
|||||||
[('cn', fields.ResourceClass.VCPU, 1),
|
[('cn', fields.ResourceClass.VCPU, 1),
|
||||||
('cn', fields.ResourceClass.MEMORY_MB, 64),
|
('cn', fields.ResourceClass.MEMORY_MB, 64),
|
||||||
('cn', fields.ResourceClass.DISK_GB, 1500)],
|
('cn', fields.ResourceClass.DISK_GB, 1500)],
|
||||||
# TODO(efried): Due to bug #1724613, the cn + ss candidate is not
|
[('cn', fields.ResourceClass.VCPU, 1),
|
||||||
# returned. Uncomment this when the bug is fixed.
|
('cn', fields.ResourceClass.MEMORY_MB, 64),
|
||||||
# [('cn', fields.ResourceClass.VCPU, 1),
|
('ss', fields.ResourceClass.DISK_GB, 1500)],
|
||||||
# ('cn', fields.ResourceClass.MEMORY_MB, 64),
|
|
||||||
# ('ss', fields.ResourceClass.DISK_GB, 1500)],
|
|
||||||
]
|
]
|
||||||
|
|
||||||
self._validate_allocation_requests(expected, alloc_cands)
|
self._validate_allocation_requests(expected, alloc_cands)
|
||||||
@ -1047,17 +1045,13 @@ class AllocationCandidatesTestCase(ProviderDBBase):
|
|||||||
|
|
||||||
# TODO(efried): Bug #1724633: we'd *like* to get no candidates, because
|
# TODO(efried): Bug #1724633: we'd *like* to get no candidates, because
|
||||||
# there's no single DISK_GB resource with both STORAGE_DISK_SSD and
|
# there's no single DISK_GB resource with both STORAGE_DISK_SSD and
|
||||||
# CUSTOM_RAID traits. So this is the ideal expected value:
|
# CUSTOM_RAID traits.
|
||||||
expected = []
|
# expected = []
|
||||||
# TODO(efried): But under the design as currently conceived, we would
|
expected = [
|
||||||
# expect to get the cn + ss candidate, because that combination
|
[('cn', fields.ResourceClass.VCPU, 1),
|
||||||
# satisfies both traits:
|
('cn', fields.ResourceClass.MEMORY_MB, 64),
|
||||||
# expected = [
|
('ss', fields.ResourceClass.DISK_GB, 1500)],
|
||||||
# [('cn', fields.ResourceClass.VCPU, 1),
|
]
|
||||||
# ('cn', fields.ResourceClass.MEMORY_MB, 64),
|
|
||||||
# ('ss', fields.ResourceClass.DISK_GB, 1500)],
|
|
||||||
# ]
|
|
||||||
# So we're getting the right value, but we really shouldn't be.
|
|
||||||
self._validate_allocation_requests(expected, alloc_cands)
|
self._validate_allocation_requests(expected, alloc_cands)
|
||||||
|
|
||||||
def test_only_one_sharing_provider(self):
|
def test_only_one_sharing_provider(self):
|
||||||
@ -1281,11 +1275,9 @@ class AllocationCandidatesTestCase(ProviderDBBase):
|
|||||||
[('cn1', fields.ResourceClass.VCPU, 1),
|
[('cn1', fields.ResourceClass.VCPU, 1),
|
||||||
('cn1', fields.ResourceClass.MEMORY_MB, 64),
|
('cn1', fields.ResourceClass.MEMORY_MB, 64),
|
||||||
('cn1', fields.ResourceClass.DISK_GB, 1500)],
|
('cn1', fields.ResourceClass.DISK_GB, 1500)],
|
||||||
# TODO(efried): We expect the rest of the results to look like:
|
[('cn1', fields.ResourceClass.VCPU, 1),
|
||||||
# Bug 1731072 bullet (1) (also bug 1724613)
|
('cn1', fields.ResourceClass.MEMORY_MB, 64),
|
||||||
# [('cn1', fields.ResourceClass.VCPU, 1),
|
('ss1', fields.ResourceClass.DISK_GB, 1500)],
|
||||||
# ('cn1', fields.ResourceClass.MEMORY_MB, 64),
|
|
||||||
# ('ss1', fields.ResourceClass.DISK_GB, 1500)],
|
|
||||||
]
|
]
|
||||||
|
|
||||||
self._validate_allocation_requests(expected, alloc_cands)
|
self._validate_allocation_requests(expected, alloc_cands)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user