Merge "build ProviderSummary objects in sep function"

This commit is contained in:
Zuul 2017-11-17 20:02:25 +00:00 committed by Gerrit Code Review
commit 57728836f2
1 changed files with 70 additions and 64 deletions

View File

@ -2518,6 +2518,59 @@ def _get_provider_ids_matching_all(ctx, resources):
return [r[0] for r in ctx.session.execute(sel)] return [r[0] for r in ctx.session.execute(sel)]
def _build_provider_summaries(context, usages):
"""Given a list of dicts of usage information, returns a dict, keyed by
resource provider ID, of ProviderSummary objects.
:param context: nova.context.Context object
:param usages: A list of dicts with the following format:
{
'resource_provider_id': <internal resource provider ID>,
'resource_provider_uuid': <UUID>,
'resource_class_id': <internal resource class ID>,
'total': integer,
'reserved': integer,
'allocation_ratio': float,
}
"""
# Build up a dict, keyed by internal resource provider ID, of
# ProviderSummary objects containing one or more ProviderSummaryResource
# objects representing the resources the provider has inventory for.
summaries = {}
for usage in usages:
rp_id = usage['resource_provider_id']
rp_uuid = usage['resource_provider_uuid']
rc_id = usage['resource_class_id']
# NOTE(jaypipes): usage['used'] may be None due to the LEFT JOIN of
# the usages subquery, so we coerce NULL values to 0 here.
used = usage['used'] or 0
allocation_ratio = usage['allocation_ratio']
cap = int((usage['total'] - usage['reserved']) * allocation_ratio)
summary = summaries.get(rp_id)
if not summary:
summary = ProviderSummary(
context,
resource_provider=ResourceProvider(
context,
uuid=rp_uuid,
),
resources=[],
)
summaries[rp_id] = summary
rc_name = _RC_CACHE.string_from_id(rc_id)
rpsr = ProviderSummaryResource(
context,
resource_class=rc_name,
capacity=cap,
used=used,
)
summary.resources.append(rpsr)
return summaries
@base.NovaObjectRegistry.register_if(False) @base.NovaObjectRegistry.register_if(False)
class AllocationCandidates(base.NovaObject): class AllocationCandidates(base.NovaObject):
"""The AllocationCandidates object is a collection of possible allocations """The AllocationCandidates object is a collection of possible allocations
@ -2617,9 +2670,10 @@ class AllocationCandidates(base.NovaObject):
# We need to grab usage information for all the providers identified as # We need to grab usage information for all the providers identified as
# potentially fulfilling part of the resource request. This includes # potentially fulfilling part of the resource request. This includes
# "root providers" returned from _get_all_with_shared() as well as all # non-sharing providers returned from the above call to either
# the providers of shared resources. Here, we simply grab a unique set # _get_all_with_shared() or _get_provider_ids_matching_all() as well as
# of all those resource provider internal IDs by set union'ing them # all the providers of shared resources. Here, we simply grab a unique
# set of all those resource provider internal IDs by set union'ing them
# together # together
all_rp_ids = set(non_sharing_rp_ids) all_rp_ids = set(non_sharing_rp_ids)
for rps in sharing_providers.values(): for rps in sharing_providers.values():
@ -2637,33 +2691,9 @@ class AllocationCandidates(base.NovaObject):
list(resources.keys()), list(resources.keys()),
) )
# Build up a dict, keyed by internal resource provider ID, of usage # Get a dict, keyed by resource provider internal ID, of
# information from which we will then build both allocation request and # ProviderSummary objects for all providers involved in the request
# provider summary information summaries = _build_provider_summaries(context, usages)
summaries = {}
for usage in usages:
u_rp_id = usage['resource_provider_id']
u_rp_uuid = usage['resource_provider_uuid']
u_rc_id = usage['resource_class_id']
# NOTE(jaypipes): usage['used'] may be None due to the LEFT JOIN of
# the usages subquery, so we coerce NULL values to 0 here.
used = usage['used'] or 0
allocation_ratio = usage['allocation_ratio']
cap = int((usage['total'] - usage['reserved']) * allocation_ratio)
summary = summaries.get(u_rp_id)
if not summary:
summary = {
'uuid': u_rp_uuid,
'resources': {},
# TODO(jaypipes): Fill in the provider's traits...
'traits': [],
}
summaries[u_rp_id] = summary
summary['resources'][u_rc_id] = {
'capacity': cap,
'used': used,
}
# Next, build up a list of allocation requests. These allocation # Next, build up a list of allocation requests. These allocation
# requests are AllocationRequest objects, containing resource provider # requests are AllocationRequest objects, containing resource provider
@ -2675,11 +2705,11 @@ class AllocationCandidates(base.NovaObject):
# AllocationRequestResource objects that represent each resource # AllocationRequestResource objects that represent each resource
# provider for a shared resource # provider for a shared resource
sharing_resource_requests = collections.defaultdict(list) sharing_resource_requests = collections.defaultdict(list)
for shared_rc_id in sharing_providers.keys(): for shared_rc_id in sharing_providers:
sharing = sharing_providers[shared_rc_id] sharing = sharing_providers[shared_rc_id]
for sharing_rp_id in sharing: for sharing_rp_id in sharing:
sharing_summary = summaries[sharing_rp_id] sharing_summary = summaries[sharing_rp_id]
sharing_rp_uuid = sharing_summary['uuid'] sharing_rp_uuid = sharing_summary.resource_provider.uuid
sharing_res_req = AllocationRequestResource( sharing_res_req = AllocationRequestResource(
context, context,
resource_provider=ResourceProvider( resource_provider=ResourceProvider(
@ -2701,14 +2731,18 @@ class AllocationCandidates(base.NovaObject):
# request written for it, we just ignore it and continue # request written for it, we just ignore it and continue
continue continue
rp_summary = summaries[rp_id] rp_summary = summaries[rp_id]
rp_uuid = rp_summary['uuid'] rp_uuid = rp_summary.resource_provider.uuid
local_resources = set( local_resources = set(
rc_id for rc_id in resources.keys() rc_id for rc_id in resources.keys()
if rc_id in rp_summary['resources'] if _RC_CACHE.string_from_id(rc_id) in [
res.resource_class for res in rp_summary.resources
]
) )
shared_resources = set( shared_resources = set(
rc_id for rc_id in resources.keys() rc_id for rc_id in resources.keys()
if rc_id not in rp_summary['resources'] if _RC_CACHE.string_from_id(rc_id) not in [
res.resource_class for res in rp_summary.resources
]
) )
# Determine if the root provider actually has all the resources # Determine if the root provider actually has all the resources
# requested. If not, we need to add an AllocationRequest # requested. If not, we need to add an AllocationRequest
@ -2780,32 +2814,4 @@ class AllocationCandidates(base.NovaObject):
) )
alloc_request_objs.append(req_obj) alloc_request_objs.append(req_obj)
# Finally, construct the object representations for the provider return alloc_request_objs, list(summaries.values())
# summaries we built above. These summaries may be used by the
# scheduler (or any other caller) to sort and weigh for its eventual
# placement and claim decisions
summary_objs = []
for rp_id, summary in summaries.items():
rp_uuid = summary['uuid']
rps_resources = []
for rc_id, usage in summary['resources'].items():
rc_name = _RC_CACHE.string_from_id(rc_id)
rpsr_obj = ProviderSummaryResource(
context,
resource_class=rc_name,
capacity=usage['capacity'],
used=usage['used'],
)
rps_resources.append(rpsr_obj)
summary_obj = ProviderSummary(
context,
resource_provider=ResourceProvider(
context,
uuid=rp_uuid,
),
resources=rps_resources,
)
summary_objs.append(summary_obj)
return alloc_request_objs, summary_objs