[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:
Chris Dent 2017-10-16 21:27:40 +01:00
parent 9633ebdf37
commit 808323e0c5
19 changed files with 542 additions and 33 deletions

View File

@ -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']

View File

@ -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'

View File

@ -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
] ]

View File

@ -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.

View File

@ -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,

View File

@ -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:

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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: /

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View 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
}
}
}
}
}

View File

@ -13,5 +13,7 @@
"VCPU": 2 "VCPU": 2
} }
} }
} },
"project_id": "7e67cbf7-7c38-4a32-b85b-0739c690991a",
"user_id": "067f691e-725a-451a-83e2-5c3d13e1dffc"
} }

View File

@ -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

View File

@ -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"
}

View File

@ -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.