placement: adds REST API for nested providers
Adds a new microversion (1.14) to the placement REST API for supporting nested resource providers. For POST /resource_providers and PUT /resource_providers/{uuid}, a new optional 'parent_provider_uuid' field is added to the request payload. For GET /resource_providers/{uuid} responses, the 'parent_provider_uuid' field and a convenience field called 'root_provider_uuid' are provided. For GET /resource_providers, a new '?in_tree=<rp_uuid>' parameter is supported. This parameter accepts a UUID of a resource provider. This will cause the resulting list of resource providers to be only the providers within the same "provider tree" as the provider identified by <rp_uuid> Clients for the placement REST API can specify either 'OpenStack-API-Version: placement 1.14' or 'placement latest' to handle the new 'parent_provider_uuid' attribute and to query for resource providers in a provider tree. Change-Id: I4db74e4dc682bc03df6ec94cd1c3a5f5dc927a7b blueprint: nested-resource-providers APIImpact
This commit is contained in:
parent
6c043b7ea6
commit
5734d078fc
@ -41,13 +41,30 @@ POST_RESOURCE_PROVIDER_SCHEMA = {
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"name"
|
"name"
|
||||||
],
|
],
|
||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
}
|
}
|
||||||
# Remove uuid to create the schema for PUTting a resource provider
|
# Remove uuid to create the schema for PUTting a resource provider
|
||||||
PUT_RESOURCE_PROVIDER_SCHEMA = copy.deepcopy(POST_RESOURCE_PROVIDER_SCHEMA)
|
PUT_RESOURCE_PROVIDER_SCHEMA = copy.deepcopy(POST_RESOURCE_PROVIDER_SCHEMA)
|
||||||
PUT_RESOURCE_PROVIDER_SCHEMA['properties'].pop('uuid')
|
PUT_RESOURCE_PROVIDER_SCHEMA['properties'].pop('uuid')
|
||||||
|
|
||||||
|
# Placement API microversion 1.14 adds an optional parent_provider_uuid field
|
||||||
|
# to the POST and PUT request schemas
|
||||||
|
POST_RP_SCHEMA_V1_14 = copy.deepcopy(POST_RESOURCE_PROVIDER_SCHEMA)
|
||||||
|
POST_RP_SCHEMA_V1_14["properties"]["parent_provider_uuid"] = {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
PUT_RP_SCHEMA_V1_14 = copy.deepcopy(POST_RP_SCHEMA_V1_14)
|
||||||
|
PUT_RP_SCHEMA_V1_14['properties'].pop('uuid')
|
||||||
|
|
||||||
# Represents the allowed query string parameters to the GET /resource_providers
|
# Represents the allowed query string parameters to the GET /resource_providers
|
||||||
# API call
|
# API call
|
||||||
GET_RPS_SCHEMA_1_0 = {
|
GET_RPS_SCHEMA_1_0 = {
|
||||||
@ -80,6 +97,17 @@ GET_RPS_SCHEMA_1_4['properties']['resources'] = {
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Placement API microversion 1.14 adds support for requesting resource
|
||||||
|
# providers within a tree of providers. The 'in_tree' query string parameter
|
||||||
|
# should be the UUID of a resource provider. The result of the GET call will
|
||||||
|
# include only those resource providers in the same "provider tree" as the
|
||||||
|
# provider with the UUID represented by 'in_tree'
|
||||||
|
GET_RPS_SCHEMA_1_14 = copy.deepcopy(GET_RPS_SCHEMA_1_4)
|
||||||
|
GET_RPS_SCHEMA_1_14['properties']['in_tree'] = {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _serialize_links(environ, resource_provider):
|
def _serialize_links(environ, resource_provider):
|
||||||
url = util.resource_provider_url(environ, resource_provider)
|
url = util.resource_provider_url(environ, resource_provider)
|
||||||
@ -97,20 +125,23 @@ def _serialize_links(environ, resource_provider):
|
|||||||
return links
|
return links
|
||||||
|
|
||||||
|
|
||||||
def _serialize_provider(environ, resource_provider):
|
def _serialize_provider(environ, resource_provider, want_version):
|
||||||
data = {
|
data = {
|
||||||
'uuid': resource_provider.uuid,
|
'uuid': resource_provider.uuid,
|
||||||
'name': resource_provider.name,
|
'name': resource_provider.name,
|
||||||
'generation': resource_provider.generation,
|
'generation': resource_provider.generation,
|
||||||
'links': _serialize_links(environ, resource_provider)
|
'links': _serialize_links(environ, resource_provider)
|
||||||
}
|
}
|
||||||
|
if want_version.matches((1, 14)):
|
||||||
|
data['parent_provider_uuid'] = resource_provider.parent_provider_uuid
|
||||||
|
data['root_provider_uuid'] = resource_provider.root_provider_uuid
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def _serialize_providers(environ, resource_providers):
|
def _serialize_providers(environ, resource_providers, want_version):
|
||||||
output = []
|
output = []
|
||||||
for provider in resource_providers:
|
for provider in resource_providers:
|
||||||
provider_data = _serialize_provider(environ, provider)
|
provider_data = _serialize_provider(environ, provider, want_version)
|
||||||
output.append(provider_data)
|
output.append(provider_data)
|
||||||
return {"resource_providers": output}
|
return {"resource_providers": output}
|
||||||
|
|
||||||
@ -124,12 +155,15 @@ def create_resource_provider(req):
|
|||||||
header pointing to the newly created resource provider.
|
header pointing to the newly created resource provider.
|
||||||
"""
|
"""
|
||||||
context = req.environ['placement.context']
|
context = req.environ['placement.context']
|
||||||
data = util.extract_json(req.body, POST_RESOURCE_PROVIDER_SCHEMA)
|
schema = POST_RESOURCE_PROVIDER_SCHEMA
|
||||||
|
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
|
||||||
|
if want_version.matches((1, 14)):
|
||||||
|
schema = POST_RP_SCHEMA_V1_14
|
||||||
|
data = util.extract_json(req.body, schema)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
uuid = data.get('uuid', uuidutils.generate_uuid())
|
uuid = data.setdefault('uuid', uuidutils.generate_uuid())
|
||||||
resource_provider = rp_obj.ResourceProvider(
|
resource_provider = rp_obj.ResourceProvider(context, **data)
|
||||||
context, name=data['name'], uuid=uuid)
|
|
||||||
resource_provider.create()
|
resource_provider.create()
|
||||||
except db_exc.DBDuplicateEntry as exc:
|
except db_exc.DBDuplicateEntry as exc:
|
||||||
# Whether exc.columns has one or two entries (in the event
|
# Whether exc.columns has one or two entries (in the event
|
||||||
@ -192,8 +226,9 @@ def get_resource_provider(req):
|
|||||||
resource_provider = rp_obj.ResourceProvider.get_by_uuid(
|
resource_provider = rp_obj.ResourceProvider.get_by_uuid(
|
||||||
context, uuid)
|
context, uuid)
|
||||||
|
|
||||||
|
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
|
||||||
req.response.body = encodeutils.to_utf8(jsonutils.dumps(
|
req.response.body = encodeutils.to_utf8(jsonutils.dumps(
|
||||||
_serialize_provider(req.environ, resource_provider)))
|
_serialize_provider(req.environ, resource_provider, want_version)))
|
||||||
req.response.content_type = 'application/json'
|
req.response.content_type = 'application/json'
|
||||||
return req.response
|
return req.response
|
||||||
|
|
||||||
@ -210,15 +245,17 @@ def list_resource_providers(req):
|
|||||||
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
|
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
|
||||||
|
|
||||||
schema = GET_RPS_SCHEMA_1_0
|
schema = GET_RPS_SCHEMA_1_0
|
||||||
if want_version == (1, 3):
|
if want_version.matches((1, 14)):
|
||||||
schema = GET_RPS_SCHEMA_1_3
|
schema = GET_RPS_SCHEMA_1_14
|
||||||
if want_version >= (1, 4):
|
elif want_version.matches((1, 4)):
|
||||||
schema = GET_RPS_SCHEMA_1_4
|
schema = GET_RPS_SCHEMA_1_4
|
||||||
|
elif want_version.matches((1, 3)):
|
||||||
|
schema = GET_RPS_SCHEMA_1_3
|
||||||
|
|
||||||
util.validate_query_params(req, schema)
|
util.validate_query_params(req, schema)
|
||||||
|
|
||||||
filters = {}
|
filters = {}
|
||||||
for attr in ['uuid', 'name', 'member_of']:
|
for attr in ['uuid', 'name', 'member_of', 'in_tree']:
|
||||||
if attr in req.GET:
|
if attr in req.GET:
|
||||||
value = req.GET[attr]
|
value = req.GET[attr]
|
||||||
# special case member_of to always make its value a
|
# special case member_of to always make its value a
|
||||||
@ -250,8 +287,8 @@ def list_resource_providers(req):
|
|||||||
{'error': exc})
|
{'error': exc})
|
||||||
|
|
||||||
response = req.response
|
response = req.response
|
||||||
response.body = encodeutils.to_utf8(
|
response.body = encodeutils.to_utf8(jsonutils.dumps(
|
||||||
jsonutils.dumps(_serialize_providers(req.environ, resource_providers)))
|
_serialize_providers(req.environ, resource_providers, want_version)))
|
||||||
response.content_type = 'application/json'
|
response.content_type = 'application/json'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@ -271,9 +308,16 @@ def update_resource_provider(req):
|
|||||||
resource_provider = rp_obj.ResourceProvider.get_by_uuid(
|
resource_provider = rp_obj.ResourceProvider.get_by_uuid(
|
||||||
context, uuid)
|
context, uuid)
|
||||||
|
|
||||||
data = util.extract_json(req.body, PUT_RESOURCE_PROVIDER_SCHEMA)
|
schema = PUT_RESOURCE_PROVIDER_SCHEMA
|
||||||
|
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
|
||||||
|
if want_version.matches((1, 14)):
|
||||||
|
schema = PUT_RP_SCHEMA_V1_14
|
||||||
|
|
||||||
resource_provider.name = data['name']
|
data = util.extract_json(req.body, schema)
|
||||||
|
|
||||||
|
for field in rp_obj.ResourceProvider.SETTABLE_FIELDS:
|
||||||
|
if field in data:
|
||||||
|
setattr(resource_provider, field, data[field])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resource_provider.save()
|
resource_provider.save()
|
||||||
@ -287,7 +331,7 @@ def update_resource_provider(req):
|
|||||||
{'rp_uuid': uuid, 'error': exc})
|
{'rp_uuid': uuid, 'error': exc})
|
||||||
|
|
||||||
req.response.body = encodeutils.to_utf8(jsonutils.dumps(
|
req.response.body = encodeutils.to_utf8(jsonutils.dumps(
|
||||||
_serialize_provider(req.environ, resource_provider)))
|
_serialize_provider(req.environ, resource_provider, want_version)))
|
||||||
req.response.status = 200
|
req.response.status = 200
|
||||||
req.response.content_type = 'application/json'
|
req.response.content_type = 'application/json'
|
||||||
return req.response
|
return req.response
|
||||||
|
@ -54,6 +54,9 @@ VERSIONS = [
|
|||||||
# as GET. The 'allocation_requests' format in GET
|
# as GET. The 'allocation_requests' format in GET
|
||||||
# /allocation_candidates is updated to be the same as well.
|
# /allocation_candidates is updated to be the same as well.
|
||||||
'1.13', # Adds POST /allocations to set allocations for multiple consumers
|
'1.13', # Adds POST /allocations to set allocations for multiple consumers
|
||||||
|
# as GET
|
||||||
|
'1.14', # Adds parent and root provider UUID on resource provider
|
||||||
|
# representation and 'in_tree' filter on GET /resource_providers
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,3 +178,22 @@ with the new `PUT` format.
|
|||||||
|
|
||||||
Version 1.13 gives the ability to set or clear allocations for more than
|
Version 1.13 gives the ability to set or clear allocations for more than
|
||||||
one consumer uuid with a request to ``POST /allocations``.
|
one consumer uuid with a request to ``POST /allocations``.
|
||||||
|
|
||||||
|
1.14 Add nested resource providers
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
The 1.14 version introduces the concept of nested resource providers. The
|
||||||
|
resource provider resource now contains two new attributes:
|
||||||
|
|
||||||
|
* ``parent_provider_uuid`` indicates the provider's direct parent, or null if
|
||||||
|
there is no parent. This attribute can be set in the call to ``POST
|
||||||
|
/resource_providers`` and ``PUT /resource_providers/{uuid}`` if the attribute
|
||||||
|
has not already been set to a non-NULL value (i.e. we do not support
|
||||||
|
"reparenting" a provider)
|
||||||
|
* ``root_provider_uuid`` indicates the UUID of the root resource provider in
|
||||||
|
the provider's tree. This is a read-only attribute
|
||||||
|
|
||||||
|
A new ``in_tree=<UUID>`` parameter is now available in the ``GET
|
||||||
|
/resource-providers`` API call. Supplying a UUID value for the ``in_tree``
|
||||||
|
parameter will cause all resource providers within the "provider tree" of the
|
||||||
|
provider matching ``<UUID>`` to be returned.
|
||||||
|
@ -85,6 +85,8 @@ class APIFixture(fixture.GabbiFixture):
|
|||||||
os.environ['INSTANCE_UUID'] = uuidutils.generate_uuid()
|
os.environ['INSTANCE_UUID'] = uuidutils.generate_uuid()
|
||||||
os.environ['MIGRATION_UUID'] = uuidutils.generate_uuid()
|
os.environ['MIGRATION_UUID'] = uuidutils.generate_uuid()
|
||||||
os.environ['CONSUMER_UUID'] = uuidutils.generate_uuid()
|
os.environ['CONSUMER_UUID'] = uuidutils.generate_uuid()
|
||||||
|
os.environ['PARENT_PROVIDER_UUID'] = uuidutils.generate_uuid()
|
||||||
|
os.environ['ALT_PARENT_PROVIDER_UUID'] = uuidutils.generate_uuid()
|
||||||
|
|
||||||
def stop_fixture(self):
|
def stop_fixture(self):
|
||||||
self.api_db_fixture.cleanup()
|
self.api_db_fixture.cleanup()
|
||||||
|
@ -39,13 +39,13 @@ tests:
|
|||||||
response_json_paths:
|
response_json_paths:
|
||||||
$.errors[0].title: Not Acceptable
|
$.errors[0].title: Not Acceptable
|
||||||
|
|
||||||
- name: latest microversion is 1.13
|
- name: latest microversion is 1.14
|
||||||
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.13
|
openstack-api-version: placement 1.14
|
||||||
|
|
||||||
- name: other accept header bad version
|
- name: other accept header bad version
|
||||||
GET: /
|
GET: /
|
||||||
|
@ -6,6 +6,7 @@ defaults:
|
|||||||
request_headers:
|
request_headers:
|
||||||
x-auth-token: admin
|
x-auth-token: admin
|
||||||
accept: application/json
|
accept: application/json
|
||||||
|
openstack-api-version: placement latest
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
|
|
||||||
@ -80,6 +81,7 @@ tests:
|
|||||||
response_json_paths:
|
response_json_paths:
|
||||||
$.uuid: $ENVIRON['RP_UUID']
|
$.uuid: $ENVIRON['RP_UUID']
|
||||||
$.name: $ENVIRON['RP_NAME']
|
$.name: $ENVIRON['RP_NAME']
|
||||||
|
$.parent_provider_uuid: null
|
||||||
$.generation: 0
|
$.generation: 0
|
||||||
$.links[?rel = "self"].href: /resource_providers/$ENVIRON['RP_UUID']
|
$.links[?rel = "self"].href: /resource_providers/$ENVIRON['RP_UUID']
|
||||||
$.links[?rel = "inventories"].href: /resource_providers/$ENVIRON['RP_UUID']/inventories
|
$.links[?rel = "inventories"].href: /resource_providers/$ENVIRON['RP_UUID']/inventories
|
||||||
@ -107,6 +109,7 @@ tests:
|
|||||||
$.resource_providers[0].uuid: $ENVIRON['RP_UUID']
|
$.resource_providers[0].uuid: $ENVIRON['RP_UUID']
|
||||||
$.resource_providers[0].name: $ENVIRON['RP_NAME']
|
$.resource_providers[0].name: $ENVIRON['RP_NAME']
|
||||||
$.resource_providers[0].generation: 0
|
$.resource_providers[0].generation: 0
|
||||||
|
$.resource_providers[0].parent_provider_uuid: null
|
||||||
$.resource_providers[0].links[?rel = "self"].href: /resource_providers/$ENVIRON['RP_UUID']
|
$.resource_providers[0].links[?rel = "self"].href: /resource_providers/$ENVIRON['RP_UUID']
|
||||||
$.resource_providers[0].links[?rel = "inventories"].href: /resource_providers/$ENVIRON['RP_UUID']/inventories
|
$.resource_providers[0].links[?rel = "inventories"].href: /resource_providers/$ENVIRON['RP_UUID']/inventories
|
||||||
$.resource_providers[0].links[?rel = "usages"].href: /resource_providers/$ENVIRON['RP_UUID']/usages
|
$.resource_providers[0].links[?rel = "usages"].href: /resource_providers/$ENVIRON['RP_UUID']/usages
|
||||||
@ -174,7 +177,7 @@ tests:
|
|||||||
$.resource_providers[0].links[?rel = "inventories"].href: /resource_providers/$ENVIRON['RP_UUID']/inventories
|
$.resource_providers[0].links[?rel = "inventories"].href: /resource_providers/$ENVIRON['RP_UUID']/inventories
|
||||||
$.resource_providers[0].links[?rel = "usages"].href: /resource_providers/$ENVIRON['RP_UUID']/usages
|
$.resource_providers[0].links[?rel = "usages"].href: /resource_providers/$ENVIRON['RP_UUID']/usages
|
||||||
|
|
||||||
- name: update a resource provider
|
- name: update a resource provider's name
|
||||||
PUT: /resource_providers/$RESPONSE['$.resource_providers[0].uuid']
|
PUT: /resource_providers/$RESPONSE['$.resource_providers[0].uuid']
|
||||||
request_headers:
|
request_headers:
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
@ -208,6 +211,174 @@ tests:
|
|||||||
response_json_paths:
|
response_json_paths:
|
||||||
$.errors[0].title: Bad Request
|
$.errors[0].title: Bad Request
|
||||||
|
|
||||||
|
# This section of tests validate nested resource provider relationships and
|
||||||
|
# constraints. We attempt to set the parent provider UUID for the primary
|
||||||
|
# resource provider to a UUID value of a provider we have not yet created and
|
||||||
|
# expect a failure. We then create that parent provider record and attempt to
|
||||||
|
# set the same parent provider UUID without also setting the root provider UUID
|
||||||
|
# to the same value, with an expected failure. Finally, we set the primary
|
||||||
|
# provider's root AND parent to the new provider UUID and verify success.
|
||||||
|
|
||||||
|
- name: test POST microversion limits nested providers
|
||||||
|
POST: /resource_providers
|
||||||
|
request_headers:
|
||||||
|
openstack-api-version: placement 1.13
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
name: child
|
||||||
|
parent_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- 'JSON does not validate'
|
||||||
|
|
||||||
|
- name: test PUT microversion limits nested providers
|
||||||
|
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||||
|
request_headers:
|
||||||
|
openstack-api-version: placement 1.13
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
name: child
|
||||||
|
parent_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- 'JSON does not validate'
|
||||||
|
|
||||||
|
- name: fail trying to set a root provider UUID
|
||||||
|
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
root_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- 'JSON does not validate'
|
||||||
|
|
||||||
|
- name: fail trying to self-parent
|
||||||
|
POST: /resource_providers
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
name: child
|
||||||
|
uuid: $ENVIRON['ALT_PARENT_PROVIDER_UUID']
|
||||||
|
parent_provider_uuid: $ENVIRON['ALT_PARENT_PROVIDER_UUID']
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- 'parent provider UUID cannot be same as UUID'
|
||||||
|
|
||||||
|
- name: update a parent provider UUID to non-existing provider
|
||||||
|
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
name: parent
|
||||||
|
parent_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- 'parent provider UUID does not exist'
|
||||||
|
|
||||||
|
- name: now create the parent provider
|
||||||
|
POST: /resource_providers
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
name: parent
|
||||||
|
uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
status: 201
|
||||||
|
|
||||||
|
- name: get provider with old microversion no root provider UUID field
|
||||||
|
GET: /resource_providers/$ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
request_headers:
|
||||||
|
openstack-api-version: placement 1.13
|
||||||
|
content-type: application/json
|
||||||
|
response_json_paths:
|
||||||
|
$.`len`: 4
|
||||||
|
name: parent
|
||||||
|
status: 200
|
||||||
|
|
||||||
|
- name: get provider has root provider UUID field
|
||||||
|
GET: /resource_providers/$ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
response_json_paths:
|
||||||
|
$.`len`: 6
|
||||||
|
name: parent
|
||||||
|
root_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
parent_provider_uuid: null
|
||||||
|
status: 200
|
||||||
|
|
||||||
|
- name: update a parent
|
||||||
|
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
name: child
|
||||||
|
parent_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
status: 200
|
||||||
|
|
||||||
|
- name: get provider has new parent and root provider UUID field
|
||||||
|
GET: /resource_providers/$ENVIRON['RP_UUID']
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
response_json_paths:
|
||||||
|
name: child
|
||||||
|
root_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
parent_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
status: 200
|
||||||
|
|
||||||
|
- name: fail trying to un-parent
|
||||||
|
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
name: child
|
||||||
|
parent_provider_uuid: null
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- 'un-parenting a provider is not currently allowed'
|
||||||
|
|
||||||
|
- name: list all resource providers in a tree that does not exist
|
||||||
|
GET: /resource_providers?in_tree=$ENVIRON['ALT_PARENT_PROVIDER_UUID']
|
||||||
|
response_json_paths:
|
||||||
|
$.resource_providers.`len`: 0
|
||||||
|
|
||||||
|
- name: list all resource providers in a tree with multiple providers in tree
|
||||||
|
GET: /resource_providers?in_tree=$ENVIRON['RP_UUID']
|
||||||
|
response_json_paths:
|
||||||
|
$.resource_providers.`len`: 2
|
||||||
|
# Verify that we have both the parent and child in the list
|
||||||
|
$.resource_providers[?uuid="$ENVIRON['PARENT_PROVIDER_UUID']"].root_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
$.resource_providers[?uuid="$ENVIRON['RP_UUID']"].root_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
|
||||||
|
|
||||||
|
- name: create a new parent provider
|
||||||
|
POST: /resource_providers
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
name: altwparent
|
||||||
|
uuid: $ENVIRON['ALT_PARENT_PROVIDER_UUID']
|
||||||
|
status: 201
|
||||||
|
response_headers:
|
||||||
|
location: //resource_providers/[a-f0-9-]+/
|
||||||
|
response_forbidden_headers:
|
||||||
|
- content-type
|
||||||
|
|
||||||
|
- name: list all resource providers in a tree
|
||||||
|
GET: /resource_providers?in_tree=$ENVIRON['ALT_PARENT_PROVIDER_UUID']
|
||||||
|
response_json_paths:
|
||||||
|
$.resource_providers.`len`: 1
|
||||||
|
$.resource_providers[?uuid="$ENVIRON['ALT_PARENT_PROVIDER_UUID']"].root_provider_uuid: $ENVIRON['ALT_PARENT_PROVIDER_UUID']
|
||||||
|
|
||||||
|
- name: fail trying to re-parent to a different provider
|
||||||
|
PUT: /resource_providers/$ENVIRON['RP_UUID']
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
name: child
|
||||||
|
parent_provider_uuid: $ENVIRON['ALT_PARENT_PROVIDER_UUID']
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- 're-parenting a provider is not currently allowed'
|
||||||
|
|
||||||
- name: create a new provider
|
- name: create a new provider
|
||||||
POST: /resource_providers
|
POST: /resource_providers
|
||||||
request_headers:
|
request_headers:
|
||||||
@ -221,7 +392,7 @@ tests:
|
|||||||
request_headers:
|
request_headers:
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
data:
|
data:
|
||||||
name: new name
|
name: child
|
||||||
status: 409
|
status: 409
|
||||||
response_json_paths:
|
response_json_paths:
|
||||||
$.errors[0].title: Conflict
|
$.errors[0].title: Conflict
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "NFS Share",
|
"name": "NFS Share",
|
||||||
"uuid": "7d2590ae-fb85-4080-9306-058b4c915e3f"
|
"uuid": "7d2590ae-fb85-4080-9306-058b4c915e3f",
|
||||||
|
"parent_provider_uuid": "542df8ed-9be2-49b9-b4db-6d3183ff8ec8"
|
||||||
}
|
}
|
||||||
|
@ -27,5 +27,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "Ceph Storage Pool",
|
"name": "Ceph Storage Pool",
|
||||||
"uuid": "3b4005be-d64b-456f-ba36-0ffd02718868"
|
"uuid": "3b4005be-d64b-456f-ba36-0ffd02718868",
|
||||||
|
"parent_provider_uuid": "542df8ed-9be2-49b9-b4db-6d3183ff8ec8",
|
||||||
|
"root_provider_uuid": "542df8ed-9be2-49b9-b4db-6d3183ff8ec8"
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,9 @@
|
|||||||
"rel": "allocations"
|
"rel": "allocations"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "vgr.localdomain"
|
"name": "vgr.localdomain",
|
||||||
|
"parent_provider_uuid": "542df8ed-9be2-49b9-b4db-6d3183ff8ec8",
|
||||||
|
"root_provider_uuid": "542df8ed-9be2-49b9-b4db-6d3183ff8ec8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"generation": 2,
|
"generation": 2,
|
||||||
@ -60,7 +62,9 @@
|
|||||||
"rel": "allocations"
|
"rel": "allocations"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "pony1"
|
"name": "pony1",
|
||||||
|
"parent_provider_uuid": null,
|
||||||
|
"root_provider_uuid": "d0b381e9-8761-42de-8e6c-bba99a96d5f5"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,14 @@ resource_provider_name_query:
|
|||||||
required: false
|
required: false
|
||||||
description: >
|
description: >
|
||||||
The name of a resource provider to filter the list.
|
The name of a resource provider to filter the list.
|
||||||
|
resource_provider_tree_query:
|
||||||
|
type: string
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
description: >
|
||||||
|
A UUID of a resource provider. The returned resource providers will be in
|
||||||
|
the same "provider tree" as the specified provider.
|
||||||
|
min_version: 1.14
|
||||||
resource_provider_uuid_query:
|
resource_provider_uuid_query:
|
||||||
<<: *resource_provider_uuid_path
|
<<: *resource_provider_uuid_path
|
||||||
in: query
|
in: query
|
||||||
@ -290,6 +298,34 @@ resource_provider_object:
|
|||||||
required: true
|
required: true
|
||||||
description: >
|
description: >
|
||||||
A dictionary which contains the UUID of the resource provider.
|
A dictionary which contains the UUID of the resource provider.
|
||||||
|
resource_provider_parent_provider_uuid:
|
||||||
|
type: string
|
||||||
|
in: body
|
||||||
|
required: false
|
||||||
|
description: >
|
||||||
|
The UUID of the immediate parent of the resource provider.
|
||||||
|
min_version: 1.14
|
||||||
|
resource_provider_parent_provider_uuid_required:
|
||||||
|
type: string
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
description: >
|
||||||
|
The UUID of the immediate parent of the resource provider.
|
||||||
|
min_version: 1.14
|
||||||
|
resource_provider_root_provider_uuid:
|
||||||
|
type: string
|
||||||
|
in: body
|
||||||
|
required: false
|
||||||
|
description: >
|
||||||
|
Read-only UUID of the top-most provider in this provider tree.
|
||||||
|
min_version: 1.14
|
||||||
|
resource_provider_root_provider_uuid_required:
|
||||||
|
type: string
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
description: >
|
||||||
|
Read-only UUID of the top-most provider in this provider tree.
|
||||||
|
min_version: 1.14
|
||||||
resource_provider_usages:
|
resource_provider_usages:
|
||||||
type: object
|
type: object
|
||||||
in: body
|
in: body
|
||||||
|
@ -34,7 +34,8 @@ Response
|
|||||||
- uuid: resource_provider_uuid
|
- uuid: resource_provider_uuid
|
||||||
- links: resource_provider_links
|
- links: resource_provider_links
|
||||||
- name: resource_provider_name
|
- name: resource_provider_name
|
||||||
|
- parent_provider_uuid: resource_provider_parent_provider_uuid_required
|
||||||
|
- root_provider_uuid: resource_provider_root_provider_uuid_required
|
||||||
|
|
||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
@ -63,6 +64,7 @@ Request
|
|||||||
|
|
||||||
- uuid: resource_provider_uuid_path
|
- uuid: resource_provider_uuid_path
|
||||||
- name: resource_provider_name
|
- name: resource_provider_name
|
||||||
|
- parent_provider_uuid: resource_provider_parent_provider_uuid
|
||||||
|
|
||||||
Request example
|
Request example
|
||||||
---------------
|
---------------
|
||||||
@ -79,6 +81,8 @@ Response
|
|||||||
- uuid: resource_provider_uuid
|
- uuid: resource_provider_uuid
|
||||||
- links: resource_provider_links
|
- links: resource_provider_links
|
||||||
- name: resource_provider_name
|
- name: resource_provider_name
|
||||||
|
- parent_provider_uuid: resource_provider_parent_provider_uuid_required
|
||||||
|
- root_provider_uuid: resource_provider_root_provider_uuid_required
|
||||||
|
|
||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
|
@ -28,6 +28,7 @@ of all filters are merged with a boolean `AND`.
|
|||||||
- uuid: resource_provider_uuid_query
|
- uuid: resource_provider_uuid_query
|
||||||
- member_of: member_of
|
- member_of: member_of
|
||||||
- resources: resources_query
|
- resources: resources_query
|
||||||
|
- in_tree: resource_provider_tree_query
|
||||||
|
|
||||||
Response
|
Response
|
||||||
--------
|
--------
|
||||||
@ -39,7 +40,8 @@ Response
|
|||||||
- uuid: resource_provider_uuid
|
- uuid: resource_provider_uuid
|
||||||
- links: resource_provider_links
|
- links: resource_provider_links
|
||||||
- name: resource_provider_name
|
- name: resource_provider_name
|
||||||
|
- parent_provider_uuid: resource_provider_parent_provider_uuid
|
||||||
|
- root_provider_uuid: resource_provider_root_provider_uuid
|
||||||
|
|
||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
@ -69,6 +71,8 @@ Request
|
|||||||
|
|
||||||
- name: resource_provider_name
|
- name: resource_provider_name
|
||||||
- uuid: resource_provider_uuid_opt
|
- uuid: resource_provider_uuid_opt
|
||||||
|
- parent_provider_uuid: resource_provider_parent_provider_uuid
|
||||||
|
- root_provider_uuid: resource_provider_root_provider_uuid
|
||||||
|
|
||||||
Request example
|
Request example
|
||||||
---------------
|
---------------
|
||||||
|
@ -1 +1,4 @@
|
|||||||
{"name": "Shared storage"}
|
{
|
||||||
|
"name": "Shared storage",
|
||||||
|
"parent_provider_uuid": "542df8ed-9be2-49b9-b4db-6d3183ff8ec8"
|
||||||
|
}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- New placement REST API microversion 1.14 is added to support nested
|
||||||
|
resource providers. Users of the placement REST API can now pass a
|
||||||
|
``in_tree=<UUID>`` parameter to the ``GET /resource_providers`` REST API
|
||||||
|
call. This will trigger the placement service to return all resource
|
||||||
|
provider records within the "provider tree" of the resource provider with
|
||||||
|
the supplied UUID value. The resource provider representation now includes
|
||||||
|
a ``parent_provider_uuid`` value that indicates the UUID of the immediate
|
||||||
|
parent resource provider, or ``null`` if the provider has no parent. For
|
||||||
|
convenience, the resource provider resource also contains a
|
||||||
|
``root_provider_uuid`` field that is populated with the UUID of the
|
||||||
|
top-most resource provider in the provider tree.
|
Loading…
Reference in New Issue
Block a user