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
util.validate_query_params(req, schema)
resources = util.normalize_resources_qs_param(req.GET['resources'])
filters = {
'resources': resources,
}
requests = util.parse_qs_request_groups(req.GET)
try:
cands = rp_obj.AllocationCandidates.get_by_filters(context, filters)
cands = rp_obj.AllocationCandidates.get_by_requests(context, requests)
except exception.ResourceClassNotFound as exc:
raise webob.exc.HTTPBadRequest(
_('Invalid resource class in resources parameter: %(error)s') %

View File

@ -2443,24 +2443,17 @@ class AllocationCandidates(base.NovaObject):
}
@classmethod
def get_by_filters(cls, context, filters):
def get_by_requests(cls, context, requests):
"""Returns an AllocationCandidates object containing all resource
providers matching a set of supplied resource constraints, with a set
of allocation requests constructed from that list of resource
providers.
:param filters: A dict of filters containing one or more of the
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.
:param requests: List of nova.api.openstack.placement.util.RequestGroup
"""
_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(
context,
allocation_requests=alloc_reqs,
@ -2471,13 +2464,19 @@ class AllocationCandidates(base.NovaObject):
# minimize the complexity of this method.
@staticmethod
@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
# requested resources or are associated with the providers that
# share one or more of the requested resource(s)
resources = filters.get('resources')
if not resources:
raise ValueError(_("Supply a resources collection in filters."))
# TODO(efried): Handle traits; handle non-sharing groups.
# For now, this extracts just the data expected by 1.10 - no API change
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
resources = {

View File

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