HTTP interface for resource providers by aggregates

In a new 1.3 microversion, the GET /resource_providers handler gains
support for a new query parameter 'member_of' which takes a value of
'in:' and a comma separated list of aggregate uuids, or a single
aggregate uuid.

The response is the list of resource providers that are associated
with any of those aggregates, or an empty list if there are none.

If in an old microversion, the query parameter is not accepted and a
400 is returned.

Change-Id: I82fc2003ce85dcadfecfea506e7d4adb47258c7a
This commit is contained in:
Chris Dent 2016-12-06 22:30:47 +00:00
parent c08147882b
commit 8e797aad7c
6 changed files with 142 additions and 3 deletions

View File

@ -18,6 +18,7 @@ from oslo_serialization import jsonutils
from oslo_utils import uuidutils from oslo_utils import uuidutils
import webob import webob
from nova.api.openstack.placement import microversion
from nova.api.openstack.placement import util from nova.api.openstack.placement import util
from nova import exception from nova import exception
from nova.i18n import _ from nova.i18n import _
@ -162,8 +163,11 @@ def list_resource_providers(req):
a collection of resource providers. a collection of resource providers.
""" """
context = req.environ['placement.context'] context = req.environ['placement.context']
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
allowed_filters = set(objects.ResourceProviderList.allowed_filters) allowed_filters = set(objects.ResourceProviderList.allowed_filters)
if not want_version.matches((1, 3)):
allowed_filters.remove('member_of')
passed_filters = set(req.GET.keys()) passed_filters = set(req.GET.keys())
invalid_filters = passed_filters - allowed_filters invalid_filters = passed_filters - allowed_filters
if invalid_filters: if invalid_filters:
@ -180,7 +184,18 @@ def list_resource_providers(req):
filters = {} filters = {}
for attr in objects.ResourceProviderList.allowed_filters: for attr in objects.ResourceProviderList.allowed_filters:
if attr in req.GET: if attr in req.GET:
filters[attr] = req.GET[attr] value = req.GET[attr]
# special case member_of to always make its value a
# list, either by accepting the single value, or if it
# starts with 'in:' splitting on ','.
# NOTE(cdent): This will all change when we start using
# JSONSchema validation of query params.
if attr == 'member_of':
if value.startswith('in:'):
value = value[3:].split(',')
else:
value = [value]
filters[attr] = value
resource_providers = objects.ResourceProviderList.get_all_by_filters( resource_providers = objects.ResourceProviderList.get_all_by_filters(
context, filters) context, filters)

View File

@ -37,6 +37,8 @@ VERSIONS = [
'1.0', '1.0',
'1.1', # initial support for aggregate.get_aggregates and set_aggregates '1.1', # initial support for aggregate.get_aggregates and set_aggregates
'1.2', # Adds /resource_classes resource endpoint '1.2', # Adds /resource_classes resource endpoint
'1.3', # Adds 'member_of' query parameter to get resource providers
# that are members of any of the listed aggregates
] ]

View File

@ -44,3 +44,11 @@ The following new routes are added:
Custom resource classes must begin with the prefix "CUSTOM\_" and contain only Custom resource classes must begin with the prefix "CUSTOM\_" and contain only
the letters A through Z, the numbers 0 through 9 and the underscore "\_" the letters A through Z, the numbers 0 through 9 and the underscore "\_"
character. character.
1.3 member_of query parameter
-----------------------------
Version 1.3 adds support for listing resource providers that are members of
any of the list of aggregates provided using a ``member_of`` query parameter:
* /resource_providers?member_of=in:{agg1_uuid},{agg2_uuid},{agg3_uuid}

View File

@ -37,13 +37,13 @@ tests:
response_strings: response_strings:
- "Unacceptable version header: 0.5" - "Unacceptable version header: 0.5"
- name: latest microversion is 1.2 - name: latest microversion is 1.3
GET: / GET: /
request_headers: request_headers:
openstack-api-version: placement latest openstack-api-version: placement latest
response_headers: response_headers:
vary: /OpenStack-API-Version/ vary: /OpenStack-API-Version/
openstack-api-version: placement 1.2 openstack-api-version: placement 1.3
- name: other accept header bad version - name: other accept header bad version
GET: / GET: /

View File

@ -0,0 +1,100 @@
# Tests filtering resource providers by aggregates
fixtures:
- APIFixture
defaults:
request_headers:
x-auth-token: admin
content-type: application/json
accept: application/json
openstack-api-version: placement latest
tests:
- name: post new provider 1
POST: /resource_providers
data:
name: rp_1
uuid: 893337e9-1e55-49f0-bcfe-6a2f16fbf2f7
status: 201
- name: post new provider 2
POST: /resource_providers
data:
name: rp_2
uuid: 5202c48f-c960-4eec-bde3-89c4f22a17b9
status: 201
- name: get by aggregates no result
GET: '/resource_providers?member_of=in:83a3d69d-8920-48e2-8914-cadfd8fa2f91'
response_json_paths:
$.resource_providers: []
- name: associate an aggregate with rp1
PUT: /resource_providers/893337e9-1e55-49f0-bcfe-6a2f16fbf2f7/aggregates
data:
- 83a3d69d-8920-48e2-8914-cadfd8fa2f91
status: 200
- name: get by aggregates one result
GET: '/resource_providers?member_of=in:83a3d69d-8920-48e2-8914-cadfd8fa2f91'
response_json_paths:
$.resource_providers[0].uuid: 893337e9-1e55-49f0-bcfe-6a2f16fbf2f7
- name: get by aggregates one result no in
GET: '/resource_providers?member_of=83a3d69d-8920-48e2-8914-cadfd8fa2f91'
response_json_paths:
$.resource_providers[0].uuid: 893337e9-1e55-49f0-bcfe-6a2f16fbf2f7
- name: associate an aggregate with rp2
PUT: /resource_providers/5202c48f-c960-4eec-bde3-89c4f22a17b9/aggregates
data:
- 83a3d69d-8920-48e2-8914-cadfd8fa2f91
status: 200
- name: get by aggregates two result
GET: '/resource_providers?member_of=in:83a3d69d-8920-48e2-8914-cadfd8fa2f91'
response_json_paths:
$.resource_providers.`len`: 2
$.resource_providers[0].uuid: /5202c48f-c960-4eec-bde3-89c4f22a17b9|893337e9-1e55-49f0-bcfe-6a2f16fbf2f7/
$.resource_providers[1].uuid: /5202c48f-c960-4eec-bde3-89c4f22a17b9|893337e9-1e55-49f0-bcfe-6a2f16fbf2f7/
- name: associate another aggregate with rp2
PUT: /resource_providers/5202c48f-c960-4eec-bde3-89c4f22a17b9/aggregates
data:
- 99652f11-9f77-46b9-80b7-4b1989be9f8c
status: 200
- name: get by both aggregates two
GET: '/resource_providers?member_of=in:83a3d69d-8920-48e2-8914-cadfd8fa2f91,99652f11-9f77-46b9-80b7-4b1989be9f8c'
response_json_paths:
$.resource_providers.`len`: 2
$.resource_providers[0].uuid: /5202c48f-c960-4eec-bde3-89c4f22a17b9|893337e9-1e55-49f0-bcfe-6a2f16fbf2f7/
$.resource_providers[1].uuid: /5202c48f-c960-4eec-bde3-89c4f22a17b9|893337e9-1e55-49f0-bcfe-6a2f16fbf2f7/
- name: clear aggregates on rp1
PUT: /resource_providers/893337e9-1e55-49f0-bcfe-6a2f16fbf2f7/aggregates
data: []
status: 200
- name: get by both aggregates one
desc: only one result because we disassociated aggregates in the PUT above
GET: '/resource_providers?member_of=in:83a3d69d-8920-48e2-8914-cadfd8fa2f91,99652f11-9f77-46b9-80b7-4b1989be9f8c'
response_json_paths:
$.resource_providers.`len`: 1
$.resource_providers[0].uuid: 5202c48f-c960-4eec-bde3-89c4f22a17b9
- name: error on old microverison
GET: '/resource_providers?member_of=in:83a3d69d-8920-48e2-8914-cadfd8fa2f91,99652f11-9f77-46b9-80b7-4b1989be9f8c'
request_headers:
openstack-api-version: placement 1.1
status: 400
response_json_paths:
$.errors[0].detail: '/Invalid filters: member_of/'
- name: error on bogus query parameter
GET: '/resource_providers?assoc_with_aggregate=in:83a3d69d-8920-48e2-8914-cadfd8fa2f91,99652f11-9f77-46b9-80b7-4b1989be9f8c'
status: 400
response_json_paths:
$.errors[0].detail: '/Invalid filters: assoc_with_aggregate/'

View File

@ -0,0 +1,14 @@
---
features:
- |
A new Placement API microversion 1.3 is added with support for filtering
the list of resource providers to include only those resource providers
which are members of any of the aggregates listed by uuid in the `member_of`
query parameter. The parameter is used when making a
`GET /resource_providers` request. The value of the parameter uses the
`in:` syntax to provide a list of aggregate uuids as follows::
/resource_providers?member_of=in:09c931b0-c0d7-4e80-8e01-9e6511db8259,f8ab4fa2-804f-402e-b675-7918bd04b173
If other filtering query parameters are present, the results are a boolean
AND of all the filters.