From 808323e0c53ae5459c5ca453b744f7a4e2d3a445 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Mon, 16 Oct 2017 21:27:40 +0100 Subject: [PATCH] [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 --- .../placement/handlers/allocation.py | 103 ++++++++++++++-- .../handlers/allocation_candidate.py | 54 +++++++- nova/api/openstack/placement/microversion.py | 3 + .../placement/rest_api_version_history.rst | 13 ++ .../api/openstack/placement/fixtures.py | 1 + .../gabbits/allocation-bad-class.yaml | 4 +- .../gabbits/allocation-candidates.yaml | 28 +++++ .../placement/gabbits/allocations-1-12.yaml | 115 ++++++++++++++++++ .../gabbits/allocations-bug-1714072.yaml | 36 +++++- .../placement/gabbits/microversion.yaml | 4 +- .../gabbits/resource-class-in-use.yaml | 4 +- .../placement/gabbits/with-allocations.yaml | 19 +++ .../source/allocation_candidates.inc | 28 ++++- placement-api-ref/source/allocations.inc | 32 ++++- .../get-allocation_candidates-1.12.json | 68 +++++++++++ placement-api-ref/source/get-allocations.json | 4 +- placement-api-ref/source/parameters.yaml | 31 ++++- .../update-allocations-request-1.12.json | 17 +++ ...ymmetric-allocations-6ff7b270c32dcb7d.yaml | 11 ++ 19 files changed, 542 insertions(+), 33 deletions(-) create mode 100644 nova/tests/functional/api/openstack/placement/gabbits/allocations-1-12.yaml create mode 100644 placement-api-ref/source/get-allocation_candidates-1.12.json create mode 100644 placement-api-ref/source/update-allocations-request-1.12.json create mode 100644 releasenotes/notes/bp-symmetric-allocations-6ff7b270c32dcb7d.yaml diff --git a/nova/api/openstack/placement/handlers/allocation.py b/nova/api/openstack/placement/handlers/allocation.py index 2c885b4a1a61..1504ff415597 100644 --- a/nova/api/openstack/placement/handlers/allocation.py +++ b/nova/api/openstack/placement/handlers/allocation.py @@ -82,8 +82,64 @@ ALLOCATION_SCHEMA_V1_8['properties']['user_id'] = {'type': 'string', 'maxLength': 255} 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.""" allocation_data = collections.defaultdict(dict) @@ -102,10 +158,17 @@ def _allocations_dict(allocations, key_fetcher, resource_provider=None): result = {'allocations': allocation_data} if resource_provider: 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 -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. { @@ -124,11 +187,15 @@ def _serialize_allocations_for_consumer(allocations): '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, - lambda x: x.resource_provider.uuid) + lambda x: x.resource_provider.uuid, + want_version=want_version) def _serialize_allocations_for_resource_provider(allocations, @@ -161,6 +228,7 @@ def list_for_consumer(req): """List allocations associated with a consumer.""" context = req.environ['placement.context'] 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, # 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) allocations_json = jsonutils.dumps( - _serialize_allocations_for_consumer(allocations)) + _serialize_allocations_for_consumer(allocations, want_version)) req.response.status = 200 req.response.body = encodeutils.to_utf8(allocations_json) @@ -215,12 +283,22 @@ def _set_allocations(req, schema): data = util.extract_json(req.body, schema) 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 # that does not exist, raise a 400. allocation_objects = [] - for allocation in allocation_data: - resource_provider_uuid = allocation['resource_provider']['uuid'] - + for resource_provider_uuid, allocation in allocation_data.items(): try: resource_provider = rp_obj.ResourceProvider.get_by_uuid( context, resource_provider_uuid) @@ -276,12 +354,19 @@ def set_allocations(req): @wsgi_wrapper.PlacementWsgify # noqa -@microversion.version_handler('1.8') +@microversion.version_handler('1.8', '1.11') @util.require_content('application/json') def set_allocations(req): 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 def delete_allocations(req): context = req.environ['placement.context'] diff --git a/nova/api/openstack/placement/handlers/allocation_candidate.py b/nova/api/openstack/placement/handlers/allocation_candidate.py index 8313e4ea90d7..4a842bd7cadf 100644 --- a/nova/api/openstack/placement/handlers/allocation_candidate.py +++ b/nova/api/openstack/placement/handlers/allocation_candidate.py @@ -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 resources involved in the allocation request. The returned results is 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 allocation requests and provider summaries. @@ -141,7 +181,12 @@ def _transform_allocation_candidates(alloc_cands): '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) return { 'allocation_requests': a_reqs, @@ -160,6 +205,7 @@ def list_allocation_candidates(req): a collection of allocation requests and provider summaries """ context = req.environ['placement.context'] + want_version = req.environ[microversion.MICROVERSION_ENVIRON] schema = _GET_SCHEMA_1_10 util.validate_query_params(req, schema) @@ -173,7 +219,7 @@ def list_allocation_candidates(req): {'error': exc}) response = req.response - trx_cands = _transform_allocation_candidates(cands) + trx_cands = _transform_allocation_candidates(cands, want_version) json_data = jsonutils.dumps(trx_cands) response.body = encodeutils.to_utf8(json_data) response.content_type = 'application/json' diff --git a/nova/api/openstack/placement/microversion.py b/nova/api/openstack/placement/microversion.py index 892ef27761e7..410aab3bbe5d 100644 --- a/nova/api/openstack/placement/microversion.py +++ b/nova/api/openstack/placement/microversion.py @@ -49,6 +49,9 @@ VERSIONS = [ '1.9', # Adds GET /usages '1.10', # Adds GET /allocation_candidates resource endpoint '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 ] diff --git a/nova/api/openstack/placement/rest_api_version_history.rst b/nova/api/openstack/placement/rest_api_version_history.rst index 510cc8ef5e29..ef2c61c6f7d4 100644 --- a/nova/api/openstack/placement/rest_api_version_history.rst +++ b/nova/api/openstack/placement/rest_api_version_history.rst @@ -159,3 +159,16 @@ for resources. The ``/resource_providers/{rp_uuid}/allocations`` endpoint has been available 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. + +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. diff --git a/nova/tests/functional/api/openstack/placement/fixtures.py b/nova/tests/functional/api/openstack/placement/fixtures.py index 8b7ab07b3f3a..cbd3518b1cf9 100644 --- a/nova/tests/functional/api/openstack/placement/fixtures.py +++ b/nova/tests/functional/api/openstack/placement/fixtures.py @@ -148,6 +148,7 @@ class AllocationFixture(APIFixture): # Create some VCPU inventory and allocations. consumer_id = uuidutils.generate_uuid() + os.environ['CONSUMER_ID'] = consumer_id inventory = rp_obj.Inventory( self.context, resource_provider=rp, resource_class='VCPU', total=10, diff --git a/nova/tests/functional/api/openstack/placement/gabbits/allocation-bad-class.yaml b/nova/tests/functional/api/openstack/placement/gabbits/allocation-bad-class.yaml index de0ee1c8185c..ec08406419b8 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/allocation-bad-class.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/allocation-bad-class.yaml @@ -7,7 +7,9 @@ defaults: x-auth-token: admin accept: 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: diff --git a/nova/tests/functional/api/openstack/placement/gabbits/allocation-candidates.yaml b/nova/tests/functional/api/openstack/placement/gabbits/allocation-candidates.yaml index 8df07a46d443..52738b69ccb5 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/allocation-candidates.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/allocation-candidates.yaml @@ -83,3 +83,31 @@ tests: # 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].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] diff --git a/nova/tests/functional/api/openstack/placement/gabbits/allocations-1-12.yaml b/nova/tests/functional/api/openstack/placement/gabbits/allocations-1-12.yaml new file mode 100644 index 000000000000..13fafda3f8af --- /dev/null +++ b/nova/tests/functional/api/openstack/placement/gabbits/allocations-1-12.yaml @@ -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 diff --git a/nova/tests/functional/api/openstack/placement/gabbits/allocations-bug-1714072.yaml b/nova/tests/functional/api/openstack/placement/gabbits/allocations-bug-1714072.yaml index c376046a21de..fa25935b6f43 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/allocations-bug-1714072.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/allocations-bug-1714072.yaml @@ -11,7 +11,9 @@ defaults: x-auth-token: admin accept: 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: @@ -61,3 +63,35 @@ tests: status: 400 response_strings: - 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 diff --git a/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml b/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml index dcd4f4dce8a8..6255f6833ccb 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml @@ -39,13 +39,13 @@ tests: response_json_paths: $.errors[0].title: Not Acceptable -- name: latest microversion is 1.11 +- name: latest microversion is 1.12 GET: / request_headers: openstack-api-version: placement latest response_headers: vary: /OpenStack-API-Version/ - openstack-api-version: placement 1.11 + openstack-api-version: placement 1.12 - name: other accept header bad version GET: / diff --git a/nova/tests/functional/api/openstack/placement/gabbits/resource-class-in-use.yaml b/nova/tests/functional/api/openstack/placement/gabbits/resource-class-in-use.yaml index 62e152e15ca7..00125389262a 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/resource-class-in-use.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/resource-class-in-use.yaml @@ -9,7 +9,9 @@ defaults: x-auth-token: admin accept: 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: diff --git a/nova/tests/functional/api/openstack/placement/gabbits/with-allocations.yaml b/nova/tests/functional/api/openstack/placement/gabbits/with-allocations.yaml index ca5d738631cf..eaa498ebe765 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/with-allocations.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/with-allocations.yaml @@ -68,3 +68,22 @@ tests: response_json_paths: $.usages.DISK_GB: 20 $.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 diff --git a/placement-api-ref/source/allocation_candidates.inc b/placement-api-ref/source/allocation_candidates.inc index d9a2e20c010d..0a07a7c9e368 100644 --- a/placement-api-ref/source/allocation_candidates.inc +++ b/placement-api-ref/source/allocation_candidates.inc @@ -31,8 +31,26 @@ Request - 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 @@ -45,8 +63,8 @@ Response - capacity: capacity - used: used -Response Example ----------------- +Response Example (microversions 1.10 - 1.11) +-------------------------------------------- .. literalinclude:: get-allocation_candidates.json - :language: javascript \ No newline at end of file + :language: javascript diff --git a/placement-api-ref/source/allocations.inc b/placement-api-ref/source/allocations.inc index 0987250f6f92..e85f65d22ae2 100644 --- a/placement-api-ref/source/allocations.inc +++ b/placement-api-ref/source/allocations.inc @@ -32,6 +32,8 @@ Response - allocations: allocations_by_resource_provider - generation: resource_provider_generation - resources: resources + - project_id: project_id_body_1_12 + - user_id: user_id_body_1_12 Response Example ---------------- @@ -57,8 +59,26 @@ Error response codes: badRequest(400), itemNotFound(404), conflict(409) resource providers for any specified resource classes or inventories 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 @@ -67,11 +87,11 @@ Request - resources: resources - resource_provider: resource_provider_object - uuid: resource_provider_uuid - - project_id: project_id_body - - user_id: user_id_body + - project_id: project_id_body_1_8 + - user_id: user_id_body_1_8 -Request example ---------------- +Request example (microversions 1.0 - 1.11) +------------------------------------------ .. literalinclude:: update-allocations-request.json :language: javascript diff --git a/placement-api-ref/source/get-allocation_candidates-1.12.json b/placement-api-ref/source/get-allocation_candidates-1.12.json new file mode 100644 index 000000000000..0264a2d26fbf --- /dev/null +++ b/placement-api-ref/source/get-allocation_candidates-1.12.json @@ -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 + } + } + } + } +} diff --git a/placement-api-ref/source/get-allocations.json b/placement-api-ref/source/get-allocations.json index 3d12298b90b0..04b79a65f474 100644 --- a/placement-api-ref/source/get-allocations.json +++ b/placement-api-ref/source/get-allocations.json @@ -13,5 +13,7 @@ "VCPU": 2 } } - } + }, + "project_id": "7e67cbf7-7c38-4a32-b85b-0739c690991a", + "user_id": "067f691e-725a-451a-83e2-5c3d13e1dffc" } diff --git a/placement-api-ref/source/parameters.yaml b/placement-api-ref/source/parameters.yaml index 4744ab17f635..c9160c6909f1 100644 --- a/placement-api-ref/source/parameters.yaml +++ b/placement-api-ref/source/parameters.yaml @@ -143,6 +143,13 @@ allocations_by_resource_provider: required: true description: > 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: type: integer in: body @@ -173,9 +180,14 @@ min_unit: &min_unit min_unit_opt: <<: *min_unit required: false -project_id_body: +project_id_body: &project_id_body <<: *project_id 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 provider_summaries: type: object @@ -214,13 +226,21 @@ resource_provider_allocations: required: true description: > A dictionary of allocation records keyed by consumer uuid. -resource_provider_generation: +resource_provider_generation: &resource_provider_generation type: integer in: body required: true description: > A consistent view marker that assists with the management of 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: type: array in: body @@ -301,10 +321,15 @@ used: required: true description: > The amount of the resource that has been already allocated. -user_id_body: +user_id_body: &user_id_body <<: *user_id in: body 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 version_id: type: string diff --git a/placement-api-ref/source/update-allocations-request-1.12.json b/placement-api-ref/source/update-allocations-request-1.12.json new file mode 100644 index 000000000000..5cf6a05cbde7 --- /dev/null +++ b/placement-api-ref/source/update-allocations-request-1.12.json @@ -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" +} diff --git a/releasenotes/notes/bp-symmetric-allocations-6ff7b270c32dcb7d.yaml b/releasenotes/notes/bp-symmetric-allocations-6ff7b270c32dcb7d.yaml new file mode 100644 index 000000000000..89986ed20752 --- /dev/null +++ b/releasenotes/notes/bp-symmetric-allocations-6ff7b270c32dcb7d.yaml @@ -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.