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:
parent
c08147882b
commit
8e797aad7c
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -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}
|
||||||
|
@ -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: /
|
||||||
|
@ -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/'
|
@ -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.
|
Loading…
Reference in New Issue
Block a user