From 388db7e6e2521bb66a19459f85adf1110a8d50ca Mon Sep 17 00:00:00 2001 From: Eric Fried Date: Thu, 1 Mar 2018 12:30:37 +0000 Subject: [PATCH] placement: Return new provider from POST /rps To facilitate opaqueness of resource provider generation internals, we need to return the (initial) generation when a provider is created. For consistency with other APIs, we will do this by returning the entire resource provider record (which includes the generation) from POST /resource_providers. Change-Id: I8624e194fe0173531c5aa2119c903e3c68b8c6cd blueprint: generation-from-create-provider --- .../placement/handlers/resource_provider.py | 12 ++++- nova/api/openstack/placement/microversion.py | 1 + .../placement/rest_api_version_history.rst | 9 ++++ .../placement/gabbits/aggregate.yaml | 2 +- .../placement/gabbits/microversion.yaml | 4 +- .../gabbits/resource-provider-aggregates.yaml | 4 +- .../resource-provider-resources-query.yaml | 4 +- .../placement/gabbits/resource-provider.yaml | 44 ++++++++++++++++--- .../placement/gabbits/shared-resources.yaml | 6 +-- placement-api-ref/source/parameters.yaml | 15 ++++++- .../source/resource_provider.inc | 2 +- .../source/resource_providers.inc | 28 ++++++++++-- .../create-resource_provider.json | 33 ++++++++++++++ ...from-create-provider-203a0ac1ebfe64d9.yaml | 9 ++++ 14 files changed, 146 insertions(+), 27 deletions(-) create mode 100644 placement-api-ref/source/samples/resource_providers/create-resource_provider.json create mode 100644 releasenotes/notes/placement-generation-from-create-provider-203a0ac1ebfe64d9.yaml diff --git a/nova/api/openstack/placement/handlers/resource_provider.py b/nova/api/openstack/placement/handlers/resource_provider.py index f30ad602c269..fb0b3c849b71 100644 --- a/nova/api/openstack/placement/handlers/resource_provider.py +++ b/nova/api/openstack/placement/handlers/resource_provider.py @@ -105,8 +105,16 @@ def create_resource_provider(req): req.response.location = util.resource_provider_url( req.environ, resource_provider) - req.response.status = 201 - req.response.content_type = None + if want_version.matches(min_version=(1, 20)): + req.response.body = encodeutils.to_utf8(jsonutils.dumps( + _serialize_provider(req.environ, resource_provider, want_version))) + req.response.content_type = 'application/json' + modified = util.pick_last_modified(None, resource_provider) + req.response.last_modified = modified + req.response.cache_control = 'no-cache' + else: + req.response.status = 201 + req.response.content_type = None return req.response diff --git a/nova/api/openstack/placement/microversion.py b/nova/api/openstack/placement/microversion.py index ae6b73b31aaa..cdbce19ad8f0 100644 --- a/nova/api/openstack/placement/microversion.py +++ b/nova/api/openstack/placement/microversion.py @@ -63,6 +63,7 @@ VERSIONS = [ '1.18', # Support ?required= queryparam on GET /resource_providers '1.19', # Include generation and conflict detection in provider aggregates # APIs + '1.20', # Return 200 with provider payload from POST /resource_providers ] diff --git a/nova/api/openstack/placement/rest_api_version_history.rst b/nova/api/openstack/placement/rest_api_version_history.rst index 21208f4f1a07..5b5face75e81 100644 --- a/nova/api/openstack/placement/rest_api_version_history.rst +++ b/nova/api/openstack/placement/rest_api_version_history.rst @@ -243,3 +243,12 @@ response to be identical, and to include the ``resource_provider_generation``. As with other generation-aware APIs, if the ``resource_provider_generation`` specified in the `PUT` request does not match the generation known by the server, a 409 Conflict error is returned. + +1.20 Return 200 with provider payload from POST /resource_providers +------------------------------------------------------------------- + +The `POST /resource_providers` API, on success, returns 200 with a payload +representing the newly-created resource provider, in the same format as the +corresponding `GET /resource_providers/{uuid}` call. This is to allow the +caller to glean automatically-set fields, such as UUID and generation, without +a subsequent GET. diff --git a/nova/tests/functional/api/openstack/placement/gabbits/aggregate.yaml b/nova/tests/functional/api/openstack/placement/gabbits/aggregate.yaml index 74fced612576..0d87a15d2459 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/aggregate.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/aggregate.yaml @@ -32,7 +32,7 @@ tests: data: name: $ENVIRON['RP_NAME'] uuid: $ENVIRON['RP_UUID'] - status: 201 + status: 200 response_headers: location: //resource_providers/[a-f0-9-]+/ diff --git a/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml b/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml index a8bb64b83338..9d833ec7a628 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.19 +- name: latest microversion is 1.20 GET: / request_headers: openstack-api-version: placement latest response_headers: vary: /OpenStack-API-Version/ - openstack-api-version: placement 1.19 + openstack-api-version: placement 1.20 - name: other accept header bad version GET: / diff --git a/nova/tests/functional/api/openstack/placement/gabbits/resource-provider-aggregates.yaml b/nova/tests/functional/api/openstack/placement/gabbits/resource-provider-aggregates.yaml index 087f359c95ff..18128666c559 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/resource-provider-aggregates.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/resource-provider-aggregates.yaml @@ -17,14 +17,14 @@ tests: data: name: rp_1 uuid: 893337e9-1e55-49f0-bcfe-6a2f16fbf2f7 - status: 201 + status: 200 - name: post new provider 2 POST: /resource_providers data: name: rp_2 uuid: 5202c48f-c960-4eec-bde3-89c4f22a17b9 - status: 201 + status: 200 - name: get by aggregates no result GET: '/resource_providers?member_of=in:83a3d69d-8920-48e2-8914-cadfd8fa2f91' diff --git a/nova/tests/functional/api/openstack/placement/gabbits/resource-provider-resources-query.yaml b/nova/tests/functional/api/openstack/placement/gabbits/resource-provider-resources-query.yaml index e873e810709f..48952b122f87 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/resource-provider-resources-query.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/resource-provider-resources-query.yaml @@ -27,11 +27,9 @@ tests: data: name: $ENVIRON['ALT_RP_NAME'] uuid: $ENVIRON['ALT_RP_UUID'] - status: 201 + status: 200 response_headers: location: //resource_providers/[a-f0-9-]+/ - response_forbidden_headers: - - content-type - name: now 2 providers listed GET: /resource_providers diff --git a/nova/tests/functional/api/openstack/placement/gabbits/resource-provider.yaml b/nova/tests/functional/api/openstack/placement/gabbits/resource-provider.yaml index 12305169460b..d0332f0ad081 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/resource-provider.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/resource-provider.yaml @@ -40,10 +40,11 @@ tests: response_strings: - admin required -- name: post new resource provider +- name: post new resource provider - old microversion POST: /resource_providers request_headers: content-type: application/json + openstack-api-version: placement 1.19 data: name: $ENVIRON['RP_NAME'] uuid: $ENVIRON['RP_UUID'] @@ -53,6 +54,29 @@ tests: response_forbidden_headers: - content-type +- name: delete it + DELETE: $LOCATION + status: 204 + +- name: post new resource provider - new microversion + POST: /resource_providers + request_headers: + content-type: application/json + data: + name: $ENVIRON['RP_NAME'] + uuid: $ENVIRON['RP_UUID'] + status: 200 + response_headers: + location: //resource_providers/[a-f0-9-]+/ + response_json_paths: + $.uuid: $ENVIRON['RP_UUID'] + $.name: $ENVIRON['RP_NAME'] + $.parent_provider_uuid: null + $.generation: 0 + $.links[?rel = "self"].href: /resource_providers/$ENVIRON['RP_UUID'] + $.links[?rel = "inventories"].href: /resource_providers/$ENVIRON['RP_UUID']/inventories + $.links[?rel = "usages"].href: /resource_providers/$ENVIRON['RP_UUID']/usages + # On this one, don't test for which field was a duplicate because # that depends on how the database reports columns. - name: try to create same all again @@ -307,7 +331,12 @@ tests: data: name: parent uuid: $ENVIRON['PARENT_PROVIDER_UUID'] - status: 201 + status: 200 + response_json_paths: + $.uuid: $ENVIRON['PARENT_PROVIDER_UUID'] + $.name: parent + $.parent_provider_uuid: null + $.generation: 0 - name: get provider with old microversion no root provider UUID field GET: /resource_providers/$ENVIRON['PARENT_PROVIDER_UUID'] @@ -380,11 +409,12 @@ tests: data: name: altwparent uuid: $ENVIRON['ALT_PARENT_PROVIDER_UUID'] - status: 201 + status: 200 response_headers: location: //resource_providers/[a-f0-9-]+/ - response_forbidden_headers: - - content-type + response_json_paths: + $.uuid: $ENVIRON['ALT_PARENT_PROVIDER_UUID'] + $.name: altwparent - name: list all resource providers in a tree GET: /resource_providers?in_tree=$ENVIRON['ALT_PARENT_PROVIDER_UUID'] @@ -510,7 +540,7 @@ tests: content-type: application/json data: name: cow - status: 201 + status: 200 - name: try to rename that provider to existing name PUT: $LOCATION @@ -565,7 +595,7 @@ tests: content-type: application/json data: name: a name - status: 201 + status: 200 response_headers: location: //resource_providers/[a-f0-9-]+/ diff --git a/nova/tests/functional/api/openstack/placement/gabbits/shared-resources.yaml b/nova/tests/functional/api/openstack/placement/gabbits/shared-resources.yaml index 4517288bae6a..29c22e3d54d9 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/shared-resources.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/shared-resources.yaml @@ -23,7 +23,7 @@ tests: data: name: cn1 uuid: 8d830468-6395-46b0-b56a-f934a1d60bbe - status: 201 + status: 200 - name: cn1 inventory PUT: /resource_providers/8d830468-6395-46b0-b56a-f934a1d60bbe/inventories @@ -41,7 +41,7 @@ tests: data: name: cn2 uuid: ed6ea55d-01ce-4e11-ba97-13a4e5540b3e - status: 201 + status: 200 - name: cn2 inventory PUT: /resource_providers/ed6ea55d-01ce-4e11-ba97-13a4e5540b3e/inventories @@ -65,7 +65,7 @@ tests: data: uuid: d450bd39-3b01-4355-9ea1-594f96594cf1 name: custom magic share - status: 201 + status: 200 - name: shared 1 inventory PUT: /resource_providers/d450bd39-3b01-4355-9ea1-594f96594cf1/inventories diff --git a/placement-api-ref/source/parameters.yaml b/placement-api-ref/source/parameters.yaml index 393487908fe5..d5941c16050b 100644 --- a/placement-api-ref/source/parameters.yaml +++ b/placement-api-ref/source/parameters.yaml @@ -313,7 +313,7 @@ resource_provider_generation_optional: resource_provider_generation_v1_19: <<: *resource_provider_generation min_version: 1.19 -resource_provider_links: +resource_provider_links: &resource_provider_links type: array in: body required: true @@ -326,6 +326,11 @@ resource_provider_links: Traits relationship link is available starting from version 1.6. Allocations relationship link is available starting from version 1.11. +resource_provider_links_v1_20: + <<: *resource_provider_links + description: | + A list of links associated with the resource provider. + resource_provider_name: type: string in: body @@ -344,14 +349,20 @@ resource_provider_parent_provider_uuid: &resource_provider_parent_provider_uuid required: false description: > The UUID of the immediate parent of the resource provider. +resource_provider_parent_provider_uuid_1_14: &resource_provider_parent_provider_uuid_1_14 + <<: *resource_provider_parent_provider_uuid min_version: 1.14 resource_provider_parent_provider_uuid_required: <<: *resource_provider_parent_provider_uuid required: true -resource_provider_root_provider_uuid_required: +resource_provider_root_provider_uuid_no_min: &resource_provider_root_provider_uuid_no_min type: string in: body required: true + description: > + UUID of the top-most provider in this provider tree. +resource_provider_root_provider_uuid_required: + <<: *resource_provider_root_provider_uuid_no_min description: > Read-only UUID of the top-most provider in this provider tree. min_version: 1.14 diff --git a/placement-api-ref/source/resource_provider.inc b/placement-api-ref/source/resource_provider.inc index 8676ca239b1d..66b9fd11d1b2 100644 --- a/placement-api-ref/source/resource_provider.inc +++ b/placement-api-ref/source/resource_provider.inc @@ -64,7 +64,7 @@ Request - uuid: resource_provider_uuid_path - name: resource_provider_name - - parent_provider_uuid: resource_provider_parent_provider_uuid + - parent_provider_uuid: resource_provider_parent_provider_uuid_1_14 Request example --------------- diff --git a/placement-api-ref/source/resource_providers.inc b/placement-api-ref/source/resource_providers.inc index 29ab33a7213e..2e042b2fd266 100644 --- a/placement-api-ref/source/resource_providers.inc +++ b/placement-api-ref/source/resource_providers.inc @@ -63,7 +63,8 @@ Create resource provider Create a new resource provider. -Normal Response Codes: 201 +Normal Response Codes: 201 (microversions 1.0 - 1.19), 200 (microversions +1.20 - ) Error response codes: conflict(409) @@ -78,7 +79,7 @@ Request - name: resource_provider_name - uuid: resource_provider_uuid_opt - - parent_provider_uuid: resource_provider_parent_provider_uuid + - parent_provider_uuid: resource_provider_parent_provider_uuid_1_14 Request example --------------- @@ -86,11 +87,30 @@ Request example .. literalinclude:: ./samples/resource_providers/create-resource_providers-request.json :language: javascript -Response --------- +Response (microversions 1.0 - 1.19) +----------------------------------- .. rest_parameters:: parameters.yaml - Location: location No body content is returned on a successful POST. + +Response (microversions 1.20 - ) +-------------------------------- + +.. rest_parameters:: parameters.yaml + + - Location: location + - generation: resource_provider_generation + - uuid: resource_provider_uuid + - links: resource_provider_links_v1_20 + - name: resource_provider_name + - parent_provider_uuid: resource_provider_parent_provider_uuid + - root_provider_uuid: resource_provider_root_provider_uuid_no_min + +Response Example (microversions 1.20 - ) +---------------------------------------- + +.. literalinclude:: ./samples/resource_providers/create-resource_provider.json + :language: javascript diff --git a/placement-api-ref/source/samples/resource_providers/create-resource_provider.json b/placement-api-ref/source/samples/resource_providers/create-resource_provider.json new file mode 100644 index 000000000000..80ced75c6e96 --- /dev/null +++ b/placement-api-ref/source/samples/resource_providers/create-resource_provider.json @@ -0,0 +1,33 @@ +{ + "generation": 0, + "links": [ + { + "href": "/placement/resource_providers/7d2590ae-fb85-4080-9306-058b4c915e3f", + "rel": "self" + }, + { + "href": "/placement/resource_providers/7d2590ae-fb85-4080-9306-058b4c915e3f/aggregates", + "rel": "aggregates" + }, + { + "href": "/placement/resource_providers/7d2590ae-fb85-4080-9306-058b4c915e3f/inventories", + "rel": "inventories" + }, + { + "href": "/placement/resource_providers/7d2590ae-fb85-4080-9306-058b4c915e3f/usages", + "rel": "usages" + }, + { + "href": "/placement/resource_providers/7d2590ae-fb85-4080-9306-058b4c915e3f/traits", + "rel": "traits" + }, + { + "href": "/placement/resource_providers/7d2590ae-fb85-4080-9306-058b4c915e3f/allocations", + "rel": "allocations" + } + ], + "name": "NFS Share", + "uuid": "7d2590ae-fb85-4080-9306-058b4c915e3f", + "parent_provider_uuid": "542df8ed-9be2-49b9-b4db-6d3183ff8ec8", + "root_provider_uuid": "542df8ed-9be2-49b9-b4db-6d3183ff8ec8" +} diff --git a/releasenotes/notes/placement-generation-from-create-provider-203a0ac1ebfe64d9.yaml b/releasenotes/notes/placement-generation-from-create-provider-203a0ac1ebfe64d9.yaml new file mode 100644 index 000000000000..522f6d29579a --- /dev/null +++ b/releasenotes/notes/placement-generation-from-create-provider-203a0ac1ebfe64d9.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + In placement API microversion 1.20, a successful `POST /resource_providers` + returns 200 with a payload representing the newly-created resource + provider. The format is the same format as the result of the corresponding + ``GET /resource_providers/{uuid}`` call. This is to allow the caller to + glean automatically-set fields, such as UUID and generation, without a + subsequent GET.