[placement] Symmetric GET and PUT /allocations/{consumer_uuid}
In a new microversion, 1.12, include project_id and user_id in the output of GET /allocations/{consumer_uuid} and add JSON schema to enable PUT to /allocations/{consumer_uuid} using the same dict-based format for request body that is used in the GET response. In later commits a similar format will be used in POST /allocations. This symmetry is general good form and also will make client code a little easier. Since GET /allocation_candiates includes objects which are capable of being PUT to /allocations/{consumer_uuid}, its response body has been updated as well, to change the 'allocation_requests' object to use the dict-based format. Internally to handlers/allocation.py the same method (_set_allocations) is used for every microversion. Any previous data structure is transformed into the dict-ish form. This means that pre-existing tests (like allocation-bad-class.yaml) continue to exercise the problems it was made for, but needs to be pinned to an older microversion, rather than being latest. Info about these changes is added to placement-api-ref, rest_api_version_history and a reno. Change-Id: I49f5680c15413bce27f2abba68b699f3ea95dcdc Implements: bp symmetric-allocations Closes-Bug: #1708204
This commit is contained in:
parent
9633ebdf37
commit
808323e0c5
@ -82,8 +82,64 @@ ALLOCATION_SCHEMA_V1_8['properties']['user_id'] = {'type': 'string',
|
|||||||
'maxLength': 255}
|
'maxLength': 255}
|
||||||
ALLOCATION_SCHEMA_V1_8['required'].extend(['project_id', 'user_id'])
|
ALLOCATION_SCHEMA_V1_8['required'].extend(['project_id', 'user_id'])
|
||||||
|
|
||||||
|
# Update the allocation schema to achieve symmetry with the representation
|
||||||
|
# used when GET /allocations/{consumer_uuid} is called.
|
||||||
|
# NOTE(cdent): Explicit duplication here for sake of comprehensibility.
|
||||||
|
ALLOCATION_SCHEMA_V1_12 = {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"allocations": {
|
||||||
|
"type": "object",
|
||||||
|
"minProperties": 1,
|
||||||
|
# resource provider id
|
||||||
|
"patternProperties": {
|
||||||
|
"^[0-9a-fA-F-]{36}$": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
# generation is optional
|
||||||
|
"generation": {
|
||||||
|
"type": "integer",
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
"type": "object",
|
||||||
|
"minProperties": 1,
|
||||||
|
# resource class
|
||||||
|
"patternProperties": {
|
||||||
|
"^[0-9A-Z_]+$": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": False
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["resources"],
|
||||||
|
"additionalProperties": False
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": False
|
||||||
|
},
|
||||||
|
"project_id": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"maxLength": 255
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"maxLength": 255
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"allocations",
|
||||||
|
"project_id",
|
||||||
|
"user_id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
def _allocations_dict(allocations, key_fetcher, resource_provider=None):
|
|
||||||
|
def _allocations_dict(allocations, key_fetcher, resource_provider=None,
|
||||||
|
want_version=None):
|
||||||
"""Turn allocations into a dict of resources keyed by key_fetcher."""
|
"""Turn allocations into a dict of resources keyed by key_fetcher."""
|
||||||
allocation_data = collections.defaultdict(dict)
|
allocation_data = collections.defaultdict(dict)
|
||||||
|
|
||||||
@ -102,10 +158,17 @@ def _allocations_dict(allocations, key_fetcher, resource_provider=None):
|
|||||||
result = {'allocations': allocation_data}
|
result = {'allocations': allocation_data}
|
||||||
if resource_provider:
|
if resource_provider:
|
||||||
result['resource_provider_generation'] = resource_provider.generation
|
result['resource_provider_generation'] = resource_provider.generation
|
||||||
|
else:
|
||||||
|
if allocations and want_version and want_version.matches((1, 12)):
|
||||||
|
# We're looking at a list of allocations by consumer id so
|
||||||
|
# project and user are consistent across the list
|
||||||
|
result['project_id'] = allocations[0].project_id
|
||||||
|
result['user_id'] = allocations[0].user_id
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _serialize_allocations_for_consumer(allocations):
|
def _serialize_allocations_for_consumer(allocations, want_version=None):
|
||||||
"""Turn a list of allocations into a dict by resource provider uuid.
|
"""Turn a list of allocations into a dict by resource provider uuid.
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -124,11 +187,15 @@ def _serialize_allocations_for_consumer(allocations):
|
|||||||
'VCPU': 3
|
'VCPU': 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
# project_id and user_id are added with microverion 1.12
|
||||||
|
'project_id': PROJECT_ID,
|
||||||
|
'user_id': USER_ID
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
return _allocations_dict(allocations,
|
return _allocations_dict(allocations,
|
||||||
lambda x: x.resource_provider.uuid)
|
lambda x: x.resource_provider.uuid,
|
||||||
|
want_version=want_version)
|
||||||
|
|
||||||
|
|
||||||
def _serialize_allocations_for_resource_provider(allocations,
|
def _serialize_allocations_for_resource_provider(allocations,
|
||||||
@ -161,6 +228,7 @@ def list_for_consumer(req):
|
|||||||
"""List allocations associated with a consumer."""
|
"""List allocations associated with a consumer."""
|
||||||
context = req.environ['placement.context']
|
context = req.environ['placement.context']
|
||||||
consumer_id = util.wsgi_path_item(req.environ, 'consumer_uuid')
|
consumer_id = util.wsgi_path_item(req.environ, 'consumer_uuid')
|
||||||
|
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
|
||||||
|
|
||||||
# NOTE(cdent): There is no way for a 404 to be returned here,
|
# NOTE(cdent): There is no way for a 404 to be returned here,
|
||||||
# only an empty result. We do not have a way to validate a
|
# only an empty result. We do not have a way to validate a
|
||||||
@ -169,7 +237,7 @@ def list_for_consumer(req):
|
|||||||
context, consumer_id)
|
context, consumer_id)
|
||||||
|
|
||||||
allocations_json = jsonutils.dumps(
|
allocations_json = jsonutils.dumps(
|
||||||
_serialize_allocations_for_consumer(allocations))
|
_serialize_allocations_for_consumer(allocations, want_version))
|
||||||
|
|
||||||
req.response.status = 200
|
req.response.status = 200
|
||||||
req.response.body = encodeutils.to_utf8(allocations_json)
|
req.response.body = encodeutils.to_utf8(allocations_json)
|
||||||
@ -215,12 +283,22 @@ def _set_allocations(req, schema):
|
|||||||
data = util.extract_json(req.body, schema)
|
data = util.extract_json(req.body, schema)
|
||||||
allocation_data = data['allocations']
|
allocation_data = data['allocations']
|
||||||
|
|
||||||
|
# Normalize allocation data to dict.
|
||||||
|
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
|
||||||
|
if not want_version.matches((1, 12)):
|
||||||
|
allocations_dict = {}
|
||||||
|
# Allocation are list-ish, transform to dict-ish
|
||||||
|
for allocation in allocation_data:
|
||||||
|
resource_provider_uuid = allocation['resource_provider']['uuid']
|
||||||
|
allocations_dict[resource_provider_uuid] = {
|
||||||
|
'resources': allocation['resources']
|
||||||
|
}
|
||||||
|
allocation_data = allocations_dict
|
||||||
|
|
||||||
# If the body includes an allocation for a resource provider
|
# If the body includes an allocation for a resource provider
|
||||||
# that does not exist, raise a 400.
|
# that does not exist, raise a 400.
|
||||||
allocation_objects = []
|
allocation_objects = []
|
||||||
for allocation in allocation_data:
|
for resource_provider_uuid, allocation in allocation_data.items():
|
||||||
resource_provider_uuid = allocation['resource_provider']['uuid']
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resource_provider = rp_obj.ResourceProvider.get_by_uuid(
|
resource_provider = rp_obj.ResourceProvider.get_by_uuid(
|
||||||
context, resource_provider_uuid)
|
context, resource_provider_uuid)
|
||||||
@ -276,12 +354,19 @@ def set_allocations(req):
|
|||||||
|
|
||||||
|
|
||||||
@wsgi_wrapper.PlacementWsgify # noqa
|
@wsgi_wrapper.PlacementWsgify # noqa
|
||||||
@microversion.version_handler('1.8')
|
@microversion.version_handler('1.8', '1.11')
|
||||||
@util.require_content('application/json')
|
@util.require_content('application/json')
|
||||||
def set_allocations(req):
|
def set_allocations(req):
|
||||||
return _set_allocations(req, ALLOCATION_SCHEMA_V1_8)
|
return _set_allocations(req, ALLOCATION_SCHEMA_V1_8)
|
||||||
|
|
||||||
|
|
||||||
|
@wsgi_wrapper.PlacementWsgify # noqa
|
||||||
|
@microversion.version_handler('1.12')
|
||||||
|
@util.require_content('application/json')
|
||||||
|
def set_allocations(req):
|
||||||
|
return _set_allocations(req, ALLOCATION_SCHEMA_V1_12)
|
||||||
|
|
||||||
|
|
||||||
@wsgi_wrapper.PlacementWsgify
|
@wsgi_wrapper.PlacementWsgify
|
||||||
def delete_allocations(req):
|
def delete_allocations(req):
|
||||||
context = req.environ['placement.context']
|
context = req.environ['placement.context']
|
||||||
|
@ -45,7 +45,47 @@ _GET_SCHEMA_1_10 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _transform_allocation_requests(alloc_reqs):
|
def _transform_allocation_requests_dict(alloc_reqs):
|
||||||
|
"""Turn supplied list of AllocationRequest objects into a list of
|
||||||
|
allocations dicts keyed by resource provider uuid of resources involved
|
||||||
|
in the allocation request. The returned results are intended to be used
|
||||||
|
as the body of a PUT /allocations/{consumer_uuid} HTTP request at
|
||||||
|
micoversion 1.12 (and beyond). The JSON objects look like the following:
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"allocations": {
|
||||||
|
$rp_uuid1: {
|
||||||
|
"resources": {
|
||||||
|
"MEMORY_MB": 512
|
||||||
|
...
|
||||||
|
}
|
||||||
|
},
|
||||||
|
$rp_uuid2: {
|
||||||
|
"resources": {
|
||||||
|
"DISK_GB": 1024
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
results = []
|
||||||
|
|
||||||
|
for ar in alloc_reqs:
|
||||||
|
# A default dict of {$rp_uuid: "resources": {})
|
||||||
|
rp_resources = collections.defaultdict(lambda: dict(resources={}))
|
||||||
|
for rr in ar.resource_requests:
|
||||||
|
res_dict = rp_resources[rr.resource_provider.uuid]['resources']
|
||||||
|
res_dict[rr.resource_class] = rr.amount
|
||||||
|
results.append(dict(allocations=rp_resources))
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def _transform_allocation_requests_list(alloc_reqs):
|
||||||
"""Turn supplied list of AllocationRequest objects into a list of dicts of
|
"""Turn supplied list of AllocationRequest objects into a list of dicts of
|
||||||
resources involved in the allocation request. The returned results is
|
resources involved in the allocation request. The returned results is
|
||||||
intended to be able to be used as the body of a PUT
|
intended to be able to be used as the body of a PUT
|
||||||
@ -132,7 +172,7 @@ def _transform_provider_summaries(p_sums):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _transform_allocation_candidates(alloc_cands):
|
def _transform_allocation_candidates(alloc_cands, want_version):
|
||||||
"""Turn supplied AllocationCandidates object into a dict containing
|
"""Turn supplied AllocationCandidates object into a dict containing
|
||||||
allocation requests and provider summaries.
|
allocation requests and provider summaries.
|
||||||
|
|
||||||
@ -141,7 +181,12 @@ def _transform_allocation_candidates(alloc_cands):
|
|||||||
'provider_summaries': <PROVIDER_SUMMARIES>,
|
'provider_summaries': <PROVIDER_SUMMARIES>,
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
a_reqs = _transform_allocation_requests(alloc_cands.allocation_requests)
|
if want_version.matches((1, 12)):
|
||||||
|
a_reqs = _transform_allocation_requests_dict(
|
||||||
|
alloc_cands.allocation_requests)
|
||||||
|
else:
|
||||||
|
a_reqs = _transform_allocation_requests_list(
|
||||||
|
alloc_cands.allocation_requests)
|
||||||
p_sums = _transform_provider_summaries(alloc_cands.provider_summaries)
|
p_sums = _transform_provider_summaries(alloc_cands.provider_summaries)
|
||||||
return {
|
return {
|
||||||
'allocation_requests': a_reqs,
|
'allocation_requests': a_reqs,
|
||||||
@ -160,6 +205,7 @@ def list_allocation_candidates(req):
|
|||||||
a collection of allocation requests and provider summaries
|
a collection of allocation requests and provider summaries
|
||||||
"""
|
"""
|
||||||
context = req.environ['placement.context']
|
context = req.environ['placement.context']
|
||||||
|
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
|
||||||
schema = _GET_SCHEMA_1_10
|
schema = _GET_SCHEMA_1_10
|
||||||
util.validate_query_params(req, schema)
|
util.validate_query_params(req, schema)
|
||||||
|
|
||||||
@ -173,7 +219,7 @@ def list_allocation_candidates(req):
|
|||||||
{'error': exc})
|
{'error': exc})
|
||||||
|
|
||||||
response = req.response
|
response = req.response
|
||||||
trx_cands = _transform_allocation_candidates(cands)
|
trx_cands = _transform_allocation_candidates(cands, want_version)
|
||||||
json_data = jsonutils.dumps(trx_cands)
|
json_data = jsonutils.dumps(trx_cands)
|
||||||
response.body = encodeutils.to_utf8(json_data)
|
response.body = encodeutils.to_utf8(json_data)
|
||||||
response.content_type = 'application/json'
|
response.content_type = 'application/json'
|
||||||
|
@ -49,6 +49,9 @@ VERSIONS = [
|
|||||||
'1.9', # Adds GET /usages
|
'1.9', # Adds GET /usages
|
||||||
'1.10', # Adds GET /allocation_candidates resource endpoint
|
'1.10', # Adds GET /allocation_candidates resource endpoint
|
||||||
'1.11', # Adds 'allocations' link to the GET /resource_providers response
|
'1.11', # Adds 'allocations' link to the GET /resource_providers response
|
||||||
|
'1.12', # Add project_id and user_id to GET /allocations/{consumer_uuid}
|
||||||
|
# and PUT to /allocations/{consumer_uuid} in the same dict form
|
||||||
|
# as GET
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,3 +159,16 @@ for resources.
|
|||||||
The ``/resource_providers/{rp_uuid}/allocations`` endpoint has been available
|
The ``/resource_providers/{rp_uuid}/allocations`` endpoint has been available
|
||||||
since version 1.0, but was not listed in the ``links`` section of the
|
since version 1.0, but was not listed in the ``links`` section of the
|
||||||
``GET /resource_providers`` response. The link is included as of version 1.11.
|
``GET /resource_providers`` response. The link is included as of version 1.11.
|
||||||
|
|
||||||
|
1.12 PUT dict format to /allocations/{consumer_uuid}
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
In version 1.12 the request body of a ``PUT /allocations/{consumer_uuid}``
|
||||||
|
is expected to have an `object` for the ``allocations`` property, not as
|
||||||
|
`array` as with earlier microversions. This puts the request body more in
|
||||||
|
alignment with the structure of the ``GET /allocations/{consumer_uuid}``
|
||||||
|
response body. Because the `PUT` request requires `user_id` and
|
||||||
|
`project_id` in the request body, these fields are added to the `GET`
|
||||||
|
response. In addition, the response body for ``GET /allocation_candidates``
|
||||||
|
is updated so the allocations in the ``alocation_requests`` object work
|
||||||
|
with the new `PUT` format.
|
||||||
|
@ -148,6 +148,7 @@ class AllocationFixture(APIFixture):
|
|||||||
|
|
||||||
# Create some VCPU inventory and allocations.
|
# Create some VCPU inventory and allocations.
|
||||||
consumer_id = uuidutils.generate_uuid()
|
consumer_id = uuidutils.generate_uuid()
|
||||||
|
os.environ['CONSUMER_ID'] = consumer_id
|
||||||
inventory = rp_obj.Inventory(
|
inventory = rp_obj.Inventory(
|
||||||
self.context, resource_provider=rp,
|
self.context, resource_provider=rp,
|
||||||
resource_class='VCPU', total=10,
|
resource_class='VCPU', total=10,
|
||||||
|
@ -7,7 +7,9 @@ defaults:
|
|||||||
x-auth-token: admin
|
x-auth-token: admin
|
||||||
accept: application/json
|
accept: application/json
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
openstack-api-version: placement latest
|
# Using <= 1.11 allows the PUT /allocations/{uuid} below
|
||||||
|
# to work with the older request form.
|
||||||
|
openstack-api-version: placement 1.11
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
|
|
||||||
|
@ -83,3 +83,31 @@ tests:
|
|||||||
# storage show correct capacity and usage
|
# storage show correct capacity and usage
|
||||||
$.provider_summaries["$ENVIRON['SS_UUID']"].resources[DISK_GB].capacity: 1900 # 1.0 * 2000 - 100G
|
$.provider_summaries["$ENVIRON['SS_UUID']"].resources[DISK_GB].capacity: 1900 # 1.0 * 2000 - 100G
|
||||||
$.provider_summaries["$ENVIRON['SS_UUID']"].resources[DISK_GB].used: 0
|
$.provider_summaries["$ENVIRON['SS_UUID']"].resources[DISK_GB].used: 0
|
||||||
|
|
||||||
|
# Verify the 1.12 format of the allocation_requests sub object which
|
||||||
|
# changes from a list-list to dict-ish format.
|
||||||
|
- name: get allocation candidates 1.12 dictish
|
||||||
|
GET: /allocation_candidates?resources=VCPU:1,MEMORY_MB:1024,DISK_GB:100
|
||||||
|
request_headers:
|
||||||
|
openstack-api-version: placement 1.12
|
||||||
|
response_json_paths:
|
||||||
|
# There are 3 providers involved. 2 compute nodes, 1 shared storage
|
||||||
|
# provider
|
||||||
|
$.provider_summaries.`len`: 3
|
||||||
|
# However, there are only 2 allocation requests, one for each compute
|
||||||
|
# node that provides the VCPU/MEMORY_MB and DISK_GB provided by the
|
||||||
|
# shared storage provider
|
||||||
|
$.allocation_requests.`len`: 2
|
||||||
|
# Verify that compute node #1 only has VCPU and MEMORY_MB listed in the
|
||||||
|
# resource requests. This validates the entire resources key.
|
||||||
|
$.allocation_requests..allocations["$ENVIRON['CN1_UUID']"].resources:
|
||||||
|
VCPU: 1
|
||||||
|
MEMORY_MB: 1024
|
||||||
|
# Verify that compute node #2 only has VCPU and MEMORY_MB listed in the
|
||||||
|
# resource requests
|
||||||
|
$.allocation_requests..allocations["$ENVIRON['CN2_UUID']"].resources:
|
||||||
|
VCPU: 1
|
||||||
|
MEMORY_MB: 1024
|
||||||
|
# Verify that shared storage provider only has DISK_GB listed in the
|
||||||
|
# resource requests, but is listed twice
|
||||||
|
$.allocation_requests..allocations["$ENVIRON['SS_UUID']"].resources[DISK_GB]: [100, 100]
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
fixtures:
|
||||||
|
- APIFixture
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
request_headers:
|
||||||
|
x-auth-token: admin
|
||||||
|
accept: application/json
|
||||||
|
content-type: application/json
|
||||||
|
openstack-api-version: placement 1.12
|
||||||
|
|
||||||
|
tests:
|
||||||
|
|
||||||
|
- name: put an allocation listish
|
||||||
|
PUT: /allocations/a0b15655-273a-4b3d-9792-2e579b7d5ad9
|
||||||
|
data:
|
||||||
|
allocations:
|
||||||
|
- resource_provider:
|
||||||
|
uuid: $ENVIRON['RP_UUID']
|
||||||
|
resources:
|
||||||
|
DISK_GB: 10
|
||||||
|
project_id: $ENVIRON['PROJECT_ID']
|
||||||
|
user_id: $ENVIRON['USER_ID']
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- JSON does not validate
|
||||||
|
|
||||||
|
- name: put resource provider not uuid
|
||||||
|
PUT: /allocations/a0b15655-273a-4b3d-9792-2e579b7d5ad9
|
||||||
|
data:
|
||||||
|
allocations:
|
||||||
|
nice_house_friend:
|
||||||
|
resources:
|
||||||
|
VCPU: 1
|
||||||
|
DISK_GB: 20
|
||||||
|
project_id: 42a32c07-3eeb-4401-9373-68a8cdca6784
|
||||||
|
user_id: 66cb2f29-c86d-47c3-8af5-69ae7b778c70
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- JSON does not validate
|
||||||
|
- does not match any of the regexes
|
||||||
|
|
||||||
|
- name: put resource class not valid
|
||||||
|
PUT: /allocations/a0b15655-273a-4b3d-9792-2e579b7d5ad9
|
||||||
|
data:
|
||||||
|
allocations:
|
||||||
|
$ENVIRON['RP_UUID']:
|
||||||
|
resources:
|
||||||
|
vcpu: 1
|
||||||
|
DISK_GB: 20
|
||||||
|
project_id: 42a32c07-3eeb-4401-9373-68a8cdca6784
|
||||||
|
user_id: 66cb2f29-c86d-47c3-8af5-69ae7b778c70
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- JSON does not validate
|
||||||
|
- does not match any of the regexes
|
||||||
|
|
||||||
|
- name: put empty allocations
|
||||||
|
PUT: /allocations/a0b15655-273a-4b3d-9792-2e579b7d5ad9
|
||||||
|
data:
|
||||||
|
allocations: {}
|
||||||
|
project_id: 42a32c07-3eeb-4401-9373-68a8cdca6784
|
||||||
|
user_id: 66cb2f29-c86d-47c3-8af5-69ae7b778c70
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- JSON does not validate
|
||||||
|
- does not have enough properties
|
||||||
|
|
||||||
|
- name: create the resource provider
|
||||||
|
POST: /resource_providers
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
name: $ENVIRON['RP_NAME']
|
||||||
|
uuid: $ENVIRON['RP_UUID']
|
||||||
|
status: 201
|
||||||
|
|
||||||
|
- name: set some inventory
|
||||||
|
PUT: /resource_providers/$ENVIRON['RP_UUID']/inventories
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
data:
|
||||||
|
resource_provider_generation: 0
|
||||||
|
inventories:
|
||||||
|
DISK_GB:
|
||||||
|
total: 2048
|
||||||
|
min_unit: 10
|
||||||
|
max_unit: 1024
|
||||||
|
VCPU:
|
||||||
|
total: 96
|
||||||
|
status: 200
|
||||||
|
|
||||||
|
- name: put an allocation dictish
|
||||||
|
PUT: /allocations/a0b15655-273a-4b3d-9792-2e579b7d5ad9
|
||||||
|
data:
|
||||||
|
allocations:
|
||||||
|
$ENVIRON['RP_UUID']:
|
||||||
|
resources:
|
||||||
|
VCPU: 1
|
||||||
|
DISK_GB: 20
|
||||||
|
project_id: 42a32c07-3eeb-4401-9373-68a8cdca6784
|
||||||
|
user_id: 66cb2f29-c86d-47c3-8af5-69ae7b778c70
|
||||||
|
status: 204
|
||||||
|
|
||||||
|
- name: get that allocation
|
||||||
|
GET: $LAST_URL
|
||||||
|
|
||||||
|
- name: put that same allocation back
|
||||||
|
PUT: $LAST_URL
|
||||||
|
data:
|
||||||
|
# there's a generation in allocations, ignored
|
||||||
|
allocations: $RESPONSE['$.allocations']
|
||||||
|
# project_id and user_id not in the get response so we add it
|
||||||
|
project_id: 42a32c07-3eeb-4401-9373-68a8cdca6784
|
||||||
|
user_id: 66cb2f29-c86d-47c3-8af5-69ae7b778c70
|
||||||
|
status: 204
|
@ -11,7 +11,9 @@ defaults:
|
|||||||
x-auth-token: admin
|
x-auth-token: admin
|
||||||
accept: application/json
|
accept: application/json
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
openstack-api-version: placement latest
|
# Default to <= 1.11 so the PUT /allocations in here that use the
|
||||||
|
# older list-ish format continue to work.
|
||||||
|
openstack-api-version: placement 1.11
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
|
|
||||||
@ -61,3 +63,35 @@ tests:
|
|||||||
status: 400
|
status: 400
|
||||||
response_strings:
|
response_strings:
|
||||||
- does not have enough properties
|
- does not have enough properties
|
||||||
|
|
||||||
|
# The next two tests confirm that the bug identified by
|
||||||
|
# this file's name is not present in the PUT /allocations/{consumer_uuid}
|
||||||
|
# format added by microversion 1.12.
|
||||||
|
|
||||||
|
- name: put a successful dictish allocation
|
||||||
|
PUT: /allocations/c9f0186b-64f8-44fb-b6c9-83008d8d6940
|
||||||
|
request_headers:
|
||||||
|
openstack-api-version: placement 1.12
|
||||||
|
data:
|
||||||
|
allocations:
|
||||||
|
$HISTORY['get resource provider'].$RESPONSE['$.uuid']:
|
||||||
|
resources:
|
||||||
|
VCPU: 1
|
||||||
|
MEMORY_MB: 1
|
||||||
|
project_id: 42a32c07-3eeb-4401-9373-68a8cdca6784
|
||||||
|
user_id: 66cb2f29-c86d-47c3-8af5-69ae7b778c70
|
||||||
|
status: 204
|
||||||
|
|
||||||
|
- name: fail with empty resources dictish
|
||||||
|
PUT: /allocations/c9f0186b-64f8-44fb-b6c9-83008d8d6940
|
||||||
|
request_headers:
|
||||||
|
openstack-api-version: placement 1.12
|
||||||
|
data:
|
||||||
|
allocations:
|
||||||
|
$HISTORY['get resource provider'].$RESPONSE['$.uuid']:
|
||||||
|
resources: {}
|
||||||
|
project_id: 42a32c07-3eeb-4401-9373-68a8cdca6784
|
||||||
|
user_id: 66cb2f29-c86d-47c3-8af5-69ae7b778c70
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- does not have enough properties
|
||||||
|
@ -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.11
|
- name: latest microversion is 1.12
|
||||||
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.11
|
openstack-api-version: placement 1.12
|
||||||
|
|
||||||
- name: other accept header bad version
|
- name: other accept header bad version
|
||||||
GET: /
|
GET: /
|
||||||
|
@ -9,7 +9,9 @@ defaults:
|
|||||||
x-auth-token: admin
|
x-auth-token: admin
|
||||||
accept: application/json
|
accept: application/json
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
openstack-api-version: placement latest
|
# We need version 1.11 as the PUT /allocations below is
|
||||||
|
# using the < 1.12 data format.
|
||||||
|
openstack-api-version: placement 1.11
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
|
|
||||||
|
@ -68,3 +68,22 @@ tests:
|
|||||||
response_json_paths:
|
response_json_paths:
|
||||||
$.usages.DISK_GB: 20
|
$.usages.DISK_GB: 20
|
||||||
$.usages.VCPU: 1
|
$.usages.VCPU: 1
|
||||||
|
|
||||||
|
- name: get allocations without project and user
|
||||||
|
GET: /allocations/$ENVIRON['CONSUMER_ID']
|
||||||
|
request_headers:
|
||||||
|
openstack-api-version: placement 1.11
|
||||||
|
accept: application/json
|
||||||
|
response_json_paths:
|
||||||
|
# only one key in the top level object
|
||||||
|
$.`len`: 1
|
||||||
|
|
||||||
|
- name: get allocations with project and user
|
||||||
|
GET: /allocations/$ENVIRON['CONSUMER_ID']
|
||||||
|
request_headers:
|
||||||
|
openstack-api-version: placement 1.12
|
||||||
|
accept: application/json
|
||||||
|
response_json_paths:
|
||||||
|
$.project_id: $ENVIRON['PROJECT_ID']
|
||||||
|
$.user_id: $ENVIRON['USER_ID']
|
||||||
|
$.`len`: 3
|
||||||
|
@ -31,8 +31,26 @@ Request
|
|||||||
|
|
||||||
- resources: resources_query_required
|
- resources: resources_query_required
|
||||||
|
|
||||||
Response
|
Response (microversions 1.12 - )
|
||||||
--------
|
--------------------------------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- allocation_requests: allocation_requests
|
||||||
|
- provider_summaries: provider_summaries
|
||||||
|
- allocations: allocations_by_resource_provider
|
||||||
|
- resources: resources
|
||||||
|
- capacity: capacity
|
||||||
|
- used: used
|
||||||
|
|
||||||
|
Response Example (microversions 1.12 - )
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
.. literalinclude:: get-allocation_candidates-1.12.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
Response (microversions 1.10 - 1.11)
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
.. rest_parameters:: parameters.yaml
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
@ -45,8 +63,8 @@ Response
|
|||||||
- capacity: capacity
|
- capacity: capacity
|
||||||
- used: used
|
- used: used
|
||||||
|
|
||||||
Response Example
|
Response Example (microversions 1.10 - 1.11)
|
||||||
----------------
|
--------------------------------------------
|
||||||
|
|
||||||
.. literalinclude:: get-allocation_candidates.json
|
.. literalinclude:: get-allocation_candidates.json
|
||||||
:language: javascript
|
:language: javascript
|
@ -32,6 +32,8 @@ Response
|
|||||||
- allocations: allocations_by_resource_provider
|
- allocations: allocations_by_resource_provider
|
||||||
- generation: resource_provider_generation
|
- generation: resource_provider_generation
|
||||||
- resources: resources
|
- resources: resources
|
||||||
|
- project_id: project_id_body_1_12
|
||||||
|
- user_id: user_id_body_1_12
|
||||||
|
|
||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
@ -57,8 +59,26 @@ Error response codes: badRequest(400), itemNotFound(404), conflict(409)
|
|||||||
resource providers for any specified resource classes or inventories
|
resource providers for any specified resource classes or inventories
|
||||||
are updated by another thread while attempting the operation.
|
are updated by another thread while attempting the operation.
|
||||||
|
|
||||||
Request
|
Request (microversions 1.12 - )
|
||||||
-------
|
-------------------------------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- consumer_uuid: consumer_uuid
|
||||||
|
- allocations: allocations_dict
|
||||||
|
- resources: resources
|
||||||
|
- project_id: project_id_body
|
||||||
|
- user_id: user_id_body
|
||||||
|
- generation: resource_provider_generation_optional
|
||||||
|
|
||||||
|
Request example (microversions 1.12 - )
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
.. literalinclude:: update-allocations-request-1.12.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
Request (microversions 1.0 - 1.11)
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
.. rest_parameters:: parameters.yaml
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
@ -67,11 +87,11 @@ Request
|
|||||||
- resources: resources
|
- resources: resources
|
||||||
- resource_provider: resource_provider_object
|
- resource_provider: resource_provider_object
|
||||||
- uuid: resource_provider_uuid
|
- uuid: resource_provider_uuid
|
||||||
- project_id: project_id_body
|
- project_id: project_id_body_1_8
|
||||||
- user_id: user_id_body
|
- user_id: user_id_body_1_8
|
||||||
|
|
||||||
Request example
|
Request example (microversions 1.0 - 1.11)
|
||||||
---------------
|
------------------------------------------
|
||||||
|
|
||||||
.. literalinclude:: update-allocations-request.json
|
.. literalinclude:: update-allocations-request.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
68
placement-api-ref/source/get-allocation_candidates-1.12.json
Normal file
68
placement-api-ref/source/get-allocation_candidates-1.12.json
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"allocation_requests": [
|
||||||
|
{
|
||||||
|
"allocations": {
|
||||||
|
"a99bad54-a275-4c4f-a8a3-ac00d57e5c64": {
|
||||||
|
"resources": {
|
||||||
|
"DISK_GB": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"35791f28-fb45-4717-9ea9-435b3ef7c3b3": {
|
||||||
|
"resources": {
|
||||||
|
"VCPU": 1,
|
||||||
|
"MEMORY_MB": 1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allocations": {
|
||||||
|
"a99bad54-a275-4c4f-a8a3-ac00d57e5c64": {
|
||||||
|
"resources": {
|
||||||
|
"DISK_GB": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"915ef8ed-9b91-4e38-8802-2e4224ad54cd": {
|
||||||
|
"resources": {
|
||||||
|
"VCPU": 1,
|
||||||
|
"MEMORY_MB": 1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"provider_summaries": {
|
||||||
|
"a99bad54-a275-4c4f-a8a3-ac00d57e5c64": {
|
||||||
|
"resources": {
|
||||||
|
"DISK_GB": {
|
||||||
|
"used": 0,
|
||||||
|
"capacity": 1900
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"915ef8ed-9b91-4e38-8802-2e4224ad54cd": {
|
||||||
|
"resources": {
|
||||||
|
"VCPU": {
|
||||||
|
"used": 0,
|
||||||
|
"capacity": 384
|
||||||
|
},
|
||||||
|
"MEMORY_MB": {
|
||||||
|
"used": 0,
|
||||||
|
"capacity": 196608
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"35791f28-fb45-4717-9ea9-435b3ef7c3b3": {
|
||||||
|
"resources": {
|
||||||
|
"VCPU": {
|
||||||
|
"used": 0,
|
||||||
|
"capacity": 384
|
||||||
|
},
|
||||||
|
"MEMORY_MB": {
|
||||||
|
"used": 0,
|
||||||
|
"capacity": 196608
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,5 +13,7 @@
|
|||||||
"VCPU": 2
|
"VCPU": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"project_id": "7e67cbf7-7c38-4a32-b85b-0739c690991a",
|
||||||
|
"user_id": "067f691e-725a-451a-83e2-5c3d13e1dffc"
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,13 @@ allocations_by_resource_provider:
|
|||||||
required: true
|
required: true
|
||||||
description: >
|
description: >
|
||||||
A dictionary of allocations keyed by resource provider uuid.
|
A dictionary of allocations keyed by resource provider uuid.
|
||||||
|
allocations_dict:
|
||||||
|
type: object
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
min_version: 1.12
|
||||||
|
description: >
|
||||||
|
A dictionary of resource allocations keyed by resource provider uuid.
|
||||||
capacity:
|
capacity:
|
||||||
type: integer
|
type: integer
|
||||||
in: body
|
in: body
|
||||||
@ -173,9 +180,14 @@ min_unit: &min_unit
|
|||||||
min_unit_opt:
|
min_unit_opt:
|
||||||
<<: *min_unit
|
<<: *min_unit
|
||||||
required: false
|
required: false
|
||||||
project_id_body:
|
project_id_body: &project_id_body
|
||||||
<<: *project_id
|
<<: *project_id
|
||||||
in: body
|
in: body
|
||||||
|
project_id_body_1_12:
|
||||||
|
<<: *project_id_body
|
||||||
|
min_version: 1.12
|
||||||
|
project_id_body_1_8:
|
||||||
|
<<: *project_id_body
|
||||||
min_version: 1.8
|
min_version: 1.8
|
||||||
provider_summaries:
|
provider_summaries:
|
||||||
type: object
|
type: object
|
||||||
@ -214,13 +226,21 @@ resource_provider_allocations:
|
|||||||
required: true
|
required: true
|
||||||
description: >
|
description: >
|
||||||
A dictionary of allocation records keyed by consumer uuid.
|
A dictionary of allocation records keyed by consumer uuid.
|
||||||
resource_provider_generation:
|
resource_provider_generation: &resource_provider_generation
|
||||||
type: integer
|
type: integer
|
||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
description: >
|
description: >
|
||||||
A consistent view marker that assists with the management of
|
A consistent view marker that assists with the management of
|
||||||
concurrent resource provider updates.
|
concurrent resource provider updates.
|
||||||
|
resource_provider_generation_optional:
|
||||||
|
<<: *resource_provider_generation
|
||||||
|
required: false
|
||||||
|
description: >
|
||||||
|
A consistent view marker that assists with the management of
|
||||||
|
concurrent resource provider updates. The value is ignored;
|
||||||
|
it is present to preserve symmetry between read and
|
||||||
|
write representations.
|
||||||
resource_provider_links:
|
resource_provider_links:
|
||||||
type: array
|
type: array
|
||||||
in: body
|
in: body
|
||||||
@ -301,10 +321,15 @@ used:
|
|||||||
required: true
|
required: true
|
||||||
description: >
|
description: >
|
||||||
The amount of the resource that has been already allocated.
|
The amount of the resource that has been already allocated.
|
||||||
user_id_body:
|
user_id_body: &user_id_body
|
||||||
<<: *user_id
|
<<: *user_id
|
||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
|
user_id_body_1_12:
|
||||||
|
<<: *user_id_body
|
||||||
|
min_version: 1.12
|
||||||
|
user_id_body_1_8:
|
||||||
|
<<: *user_id_body
|
||||||
min_version: 1.8
|
min_version: 1.8
|
||||||
version_id:
|
version_id:
|
||||||
type: string
|
type: string
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"allocations": {
|
||||||
|
"4e061c03-611e-4caa-bf26-999dcff4284e": {
|
||||||
|
"resources": {
|
||||||
|
"DISK_GB": 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"89873422-1373-46e5-b467-f0c5e6acf08f": {
|
||||||
|
"resources": {
|
||||||
|
"MEMORY_MB": 1024,
|
||||||
|
"VCPU": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"user_id": "66cb2f29-c86d-47c3-8af5-69ae7b778c70",
|
||||||
|
"project_id": "42a32c07-3eeb-4401-9373-68a8cdca6784"
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The 1.12 version of the placement API changes handling of the `PUT
|
||||||
|
/allocations/{consumer_uuid}` request to use a dict-based structure for
|
||||||
|
the JSON request body to make it more aligned with the response body of
|
||||||
|
`GET /allocations/{consumer_uuid}`. Because `PUT` requires `user_id`
|
||||||
|
and `project_id` in the request body, these fields are added to the
|
||||||
|
`GET` response. In addition, the response body for
|
||||||
|
``GET /allocation_candidates`` is updated so the allocations in the
|
||||||
|
``alocation_requests`` object work with the new `PUT` format.
|
Loading…
Reference in New Issue
Block a user