Merge "placement: AllocCands.get_by_{filters => requests}"

This commit is contained in:
Zuul 2017-11-14 22:09:57 +00:00 committed by Gerrit Code Review
commit ffeb538eb2
3 changed files with 54 additions and 50 deletions

View File

@ -163,13 +163,10 @@ def list_allocation_candidates(req):
schema = _GET_SCHEMA_1_10 schema = _GET_SCHEMA_1_10
util.validate_query_params(req, schema) util.validate_query_params(req, schema)
resources = util.normalize_resources_qs_param(req.GET['resources']) requests = util.parse_qs_request_groups(req.GET)
filters = {
'resources': resources,
}
try: try:
cands = rp_obj.AllocationCandidates.get_by_filters(context, filters) cands = rp_obj.AllocationCandidates.get_by_requests(context, requests)
except exception.ResourceClassNotFound as exc: except exception.ResourceClassNotFound as exc:
raise webob.exc.HTTPBadRequest( raise webob.exc.HTTPBadRequest(
_('Invalid resource class in resources parameter: %(error)s') % _('Invalid resource class in resources parameter: %(error)s') %

View File

@ -2443,24 +2443,17 @@ class AllocationCandidates(base.NovaObject):
} }
@classmethod @classmethod
def get_by_filters(cls, context, filters): def get_by_requests(cls, context, requests):
"""Returns an AllocationCandidates object containing all resource """Returns an AllocationCandidates object containing all resource
providers matching a set of supplied resource constraints, with a set providers matching a set of supplied resource constraints, with a set
of allocation requests constructed from that list of resource of allocation requests constructed from that list of resource
providers. providers.
:param filters: A dict of filters containing one or more of the :param requests: List of nova.api.openstack.placement.util.RequestGroup
following keys:
'resources': A dict, keyed by resource class name, of amounts of
that resource being requested. The resource provider
must either have capacity for the amount being
requested or be associated via aggregate to a provider
that shares this resource and has capacity for the
requested amount.
""" """
_ensure_rc_cache(context) _ensure_rc_cache(context)
alloc_reqs, provider_summaries = cls._get_by_filters(context, filters) alloc_reqs, provider_summaries = cls._get_by_requests(context,
requests)
return cls( return cls(
context, context,
allocation_requests=alloc_reqs, allocation_requests=alloc_reqs,
@ -2471,13 +2464,19 @@ class AllocationCandidates(base.NovaObject):
# minimize the complexity of this method. # minimize the complexity of this method.
@staticmethod @staticmethod
@db_api.api_context_manager.reader @db_api.api_context_manager.reader
def _get_by_filters(context, filters): def _get_by_requests(context, requests):
# We first get the list of "root providers" that either have the # We first get the list of "root providers" that either have the
# requested resources or are associated with the providers that # requested resources or are associated with the providers that
# share one or more of the requested resource(s) # share one or more of the requested resource(s)
resources = filters.get('resources') # TODO(efried): Handle traits; handle non-sharing groups.
if not resources: # For now, this extracts just the data expected by 1.10 - no API change
raise ValueError(_("Supply a resources collection in filters.")) resources = [request_group.resources for request_group in requests
if not request_group.use_same_provider]
if len(resources) != 1:
raise ValueError(_("The requests parameter must contain one "
"RequestGroup with use_same_provider=False and "
"nonempty resources."))
resources = resources[0]
# Transform resource string names to internal integer IDs # Transform resource string names to internal integer IDs
resources = { resources = {

View File

@ -9,6 +9,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from nova.api.openstack.placement import lib as placement_lib
from nova import context from nova import context
from nova import exception from nova import exception
from nova.objects import fields from nova.objects import fields
@ -62,7 +63,7 @@ def _find_summary_for_resource(p_sum, rc_name):
class AllocationCandidatesTestCase(test.NoDBTestCase): class AllocationCandidatesTestCase(test.NoDBTestCase):
"""Tests a variety of scenarios with both shared and non-shared resource """Tests a variety of scenarios with both shared and non-shared resource
providers that the AllocationCandidates.get_by_filters() method returns a providers that the AllocationCandidates.get_by_requests() method returns a
set of alternative allocation requests and provider summaries that may be set of alternative allocation requests and provider summaries that may be
used by the scheduler to sort/weigh the options it has for claiming used by the scheduler to sort/weigh the options it has for claiming
resources against providers. resources against providers.
@ -84,16 +85,12 @@ class AllocationCandidatesTestCase(test.NoDBTestCase):
# _validate_allocation_requests to make failure results more readable. # _validate_allocation_requests to make failure results more readable.
self.rp_uuid_to_name = {} self.rp_uuid_to_name = {}
def _get_allocation_candidates(self, resources=None): def _get_allocation_candidates(self, requests=None):
# The resources we will request if requests is None:
if resources is None: requests = [placement_lib.RequestGroup(
resources = self.requested_resources use_same_provider=False,
return rp_obj.AllocationCandidates.get_by_filters( resources=self.requested_resources)]
self.ctx, return rp_obj.AllocationCandidates.get_by_requests(self.ctx, requests)
filters={
'resources': resources,
},
)
def _create_provider(self, name, *aggs): def _create_provider(self, name, *aggs):
rp = rp_obj.ResourceProvider(self.ctx, name=name, rp = rp_obj.ResourceProvider(self.ctx, name=name,
@ -119,7 +116,7 @@ class AllocationCandidatesTestCase(test.NoDBTestCase):
], ],
... ...
] ]
:param candidates: The result from AllocationCandidates.get_by_filters. :param candidates: The result from AllocationCandidates.get_by_requests
""" """
# Extract/convert allocation requests from candidates # Extract/convert allocation requests from candidates
observed = [] observed = []
@ -200,7 +197,7 @@ class AllocationCandidatesTestCase(test.NoDBTestCase):
# resources in each allocation request, one each for VCPU, RAM, and # resources in each allocation request, one each for VCPU, RAM, and
# disk. The amounts of the requests should correspond to the requested # disk. The amounts of the requests should correspond to the requested
# resource amounts in the filter:resources dict passed to # resource amounts in the filter:resources dict passed to
# AllocationCandidates.get_by_filters(). # AllocationCandidates.get_by_requests().
expected = [ expected = [
[('cn1', fields.ResourceClass.VCPU, 1), [('cn1', fields.ResourceClass.VCPU, 1),
('cn1', fields.ResourceClass.MEMORY_MB, 64), ('cn1', fields.ResourceClass.MEMORY_MB, 64),
@ -297,7 +294,7 @@ class AllocationCandidatesTestCase(test.NoDBTestCase):
# resources in each allocation request, one each for VCPU, RAM, and # resources in each allocation request, one each for VCPU, RAM, and
# disk. The amounts of the requests should correspond to the requested # disk. The amounts of the requests should correspond to the requested
# resource amounts in the filter:resources dict passed to # resource amounts in the filter:resources dict passed to
# AllocationCandidates.get_by_filters(). The providers for VCPU and # AllocationCandidates.get_by_requests(). The providers for VCPU and
# MEMORY_MB should be the compute nodes while the provider for the # MEMORY_MB should be the compute nodes while the provider for the
# DISK_GB should be the shared storage pool # DISK_GB should be the shared storage pool
expected = [ expected = [
@ -316,9 +313,12 @@ class AllocationCandidatesTestCase(test.NoDBTestCase):
# #1705071, this resulted in a KeyError # #1705071, this resulted in a KeyError
alloc_cands = self._get_allocation_candidates( alloc_cands = self._get_allocation_candidates(
resources={ requests=[placement_lib.RequestGroup(
'DISK_GB': 10, use_same_provider=False,
} resources={
'DISK_GB': 10,
}
)]
) )
# We should only have provider summary information for the sharing # We should only have provider summary information for the sharing
@ -383,14 +383,15 @@ class AllocationCandidatesTestCase(test.NoDBTestCase):
} }
alloc_cands = self._get_allocation_candidates( alloc_cands = self._get_allocation_candidates(
resources=requested_resources) requests=[placement_lib.RequestGroup(
use_same_provider=False, resources=requested_resources)])
# Verify the allocation requests that are returned. There should be 2 # Verify the allocation requests that are returned. There should be 2
# allocation requests, one for each compute node, containing 3 # allocation requests, one for each compute node, containing 3
# resources in each allocation request, one each for VCPU, RAM, and # resources in each allocation request, one each for VCPU, RAM, and
# MAGIC. The amounts of the requests should correspond to the requested # MAGIC. The amounts of the requests should correspond to the requested
# resource amounts in the filter:resources dict passed to # resource amounts in the filter:resources dict passed to
# AllocationCandidates.get_by_filters(). The providers for VCPU and # AllocationCandidates.get_by_requests(). The providers for VCPU and
# MEMORY_MB should be the compute nodes while the provider for the # MEMORY_MB should be the compute nodes while the provider for the
# MAGIC should be the shared custom resource provider. # MAGIC should be the shared custom resource provider.
expected = [ expected = [
@ -501,11 +502,15 @@ class AllocationCandidatesTestCase(test.NoDBTestCase):
# The shared storage's disk is RAID # The shared storage's disk is RAID
_set_traits(ss, 'MISC_SHARES_VIA_AGGREGATE', 'CUSTOM_RAID') _set_traits(ss, 'MISC_SHARES_VIA_AGGREGATE', 'CUSTOM_RAID')
alloc_cands = rp_obj.AllocationCandidates.get_by_filters( alloc_cands = rp_obj.AllocationCandidates.get_by_requests(
self.ctx, filters={ self.ctx, [
'resources': self.requested_resources, placement_lib.RequestGroup(
'traits': ['HW_CPU_X86_SSE', 'STORAGE_DISK_SSD', 'CUSTOM_RAID'] use_same_provider=False,
} resources=self.requested_resources,
required_traits=set(['HW_CPU_X86_SSE', 'STORAGE_DISK_SSD',
'CUSTOM_RAID'])
)
]
) )
# TODO(efried): Okay, bear with me here: # TODO(efried): Okay, bear with me here:
@ -543,12 +548,15 @@ class AllocationCandidatesTestCase(test.NoDBTestCase):
_set_traits(ss2, "MISC_SHARES_VIA_AGGREGATE") _set_traits(ss2, "MISC_SHARES_VIA_AGGREGATE")
_add_inventory(ss2, fields.ResourceClass.DISK_GB, 1600) _add_inventory(ss2, fields.ResourceClass.DISK_GB, 1600)
alloc_cands = self._get_allocation_candidates( alloc_cands = self._get_allocation_candidates(requests=[
resources={ placement_lib.RequestGroup(
'IPV4_ADDRESS': 2, use_same_provider=False,
'SRIOV_NET_VF': 1, resources={
'DISK_GB': 1500, 'IPV4_ADDRESS': 2,
} 'SRIOV_NET_VF': 1,
'DISK_GB': 1500,
}
)]
) )
# TODO(efried): Bug https://bugs.launchpad.net/nova/+bug/1730730 # TODO(efried): Bug https://bugs.launchpad.net/nova/+bug/1730730