summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Dent <cdent@anticdent.org>2017-03-22 20:05:37 +0000
committerChris Dent <cdent@anticdent.org>2017-04-20 15:51:37 +0000
commit697c2d89ee5a4c2fc45f34ad28165f397c602399 (patch)
tree96bf54f87f594d17ca5f0df97f2913fc6c58f663
parent7e6c905d7d9b9b7a33e0fb4a5de81e0366ab1ba3 (diff)
[placement] Idempotent PUT /resource_classes/{name}
In a microversion 1.7 change PUT /resource_classes/{name} so that creation and existence validation of a custom resource class can happen in a single request and prevent the previous behavior of being able to update a single resource class to a new name, which is not desirable. The previous update_resource_class is still in place to support microversion 1.2-1.6. The original resource-classs.yaml sets the default microversion header to 'latest' so for those existing tests that are using the old style of PUT, a '1.6' header has been added. New files for version 1.6 (to add a "no 1.7 behavior here" test) and 1.7 (testing the new PUT behavior and explicitly verifying POST to create is still around) are added. Change-Id: I95f62ab2cb1ab76d18fb52b93f87ed28e4e7b5f3 Implements: bp placement-put-resource-class
Notes
Notes (review): Verified+1: IBM PowerKVM CI <kvmpower@linux.vnet.ibm.com> Verified+1: Citrix XenServer CI Code-Review+1: Ed Leafe <ed@leafe.com> Code-Review+2: Alex Xu <hejie.xu@intel.com> Code-Review+2: John Garbutt <john@johngarbutt.com> Workflow+1: John Garbutt <john@johngarbutt.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Fri, 28 Apr 2017 15:11:50 +0000 Reviewed-on: https://review.openstack.org/448791 Project: openstack/nova Branch: refs/heads/master
-rw-r--r--nova/api/openstack/placement/handlers/resource_class.py37
-rw-r--r--nova/api/openstack/placement/microversion.py1
-rw-r--r--nova/api/openstack/placement/rest_api_version_history.rst10
-rw-r--r--nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml4
-rw-r--r--nova/tests/functional/api/openstack/placement/gabbits/resource-classes-1-6.yaml21
-rw-r--r--nova/tests/functional/api/openstack/placement/gabbits/resource-classes-1-7.yaml49
-rw-r--r--nova/tests/functional/api/openstack/placement/gabbits/resource-classes.yaml5
-rw-r--r--releasenotes/notes/idempotent-put-resource-class-dc7a267c823b7995.yaml10
8 files changed, 134 insertions, 3 deletions
diff --git a/nova/api/openstack/placement/handlers/resource_class.py b/nova/api/openstack/placement/handlers/resource_class.py
index f224d14..32b56fe 100644
--- a/nova/api/openstack/placement/handlers/resource_class.py
+++ b/nova/api/openstack/placement/handlers/resource_class.py
@@ -164,7 +164,7 @@ def list_resource_classes(req):
164 164
165 165
166@wsgi_wrapper.PlacementWsgify 166@wsgi_wrapper.PlacementWsgify
167@microversion.version_handler('1.2') 167@microversion.version_handler('1.2', '1.6')
168@util.require_content('application/json') 168@util.require_content('application/json')
169def update_resource_class(req): 169def update_resource_class(req):
170 """PUT to update a single resource class. 170 """PUT to update a single resource class.
@@ -199,3 +199,38 @@ def update_resource_class(req):
199 req.response.status = 200 199 req.response.status = 200
200 req.response.content_type = 'application/json' 200 req.response.content_type = 'application/json'
201 return req.response 201 return req.response
202
203
204@wsgi_wrapper.PlacementWsgify # noqa
205@microversion.version_handler('1.7')
206def update_resource_class(req):
207 """PUT to create or validate the existence of single resource class.
208
209 On a successful create return 201. Return 204 if the class already
210 exists. If the resource class is not a custom resource class, return
211 a 400. 409 might be a better choice, but 400 aligns with previous code.
212 """
213 name = util.wsgi_path_item(req.environ, 'name')
214 context = req.environ['placement.context']
215
216 # Use JSON validation to validation resource class name.
217 util.extract_json('{"name": "%s"}' % name, PUT_RC_SCHEMA_V1_2)
218
219 status = 204
220 try:
221 rc = objects.ResourceClass.get_by_name(context, name)
222 except exception.NotFound:
223 try:
224 rc = objects.ResourceClass(context, name=name)
225 rc.create()
226 status = 201
227 # We will not see ResourceClassCannotUpdateStandard because
228 # that was already caught when validating the {name}.
229 except exception.ResourceClassExists:
230 # Someone just now created the class, so stick with 204
231 pass
232
233 req.response.status = status
234 req.response.content_type = None
235 req.response.location = util.resource_class_url(req.environ, rc)
236 return req.response
diff --git a/nova/api/openstack/placement/microversion.py b/nova/api/openstack/placement/microversion.py
index 0771c71..fac1808 100644
--- a/nova/api/openstack/placement/microversion.py
+++ b/nova/api/openstack/placement/microversion.py
@@ -43,6 +43,7 @@ VERSIONS = [
43 '1.5', # Adds DELETE /resource_providers/{uuid}/inventories 43 '1.5', # Adds DELETE /resource_providers/{uuid}/inventories
44 '1.6', # Adds /traits and /resource_providers{uuid}/traits resource 44 '1.6', # Adds /traits and /resource_providers{uuid}/traits resource
45 # endpoints 45 # endpoints
46 '1.7', # PUT /resource_classes/{name} is bodiless create or update
46] 47]
47 48
48 49
diff --git a/nova/api/openstack/placement/rest_api_version_history.rst b/nova/api/openstack/placement/rest_api_version_history.rst
index 293ea43..dfd5f9d 100644
--- a/nova/api/openstack/placement/rest_api_version_history.rst
+++ b/nova/api/openstack/placement/rest_api_version_history.rst
@@ -113,3 +113,13 @@ The following new routes are added:
113Custom traits must begin with the prefix "CUSTOM\_" and contain only 113Custom traits must begin with the prefix "CUSTOM\_" and contain only
114the letters A through Z, the numbers 0 through 9 and the underscore "\_" 114the letters A through Z, the numbers 0 through 9 and the underscore "\_"
115character. 115character.
116
1171.7 Idempotent PUT /resource_classes/{name}
118-------------------------------------------
119
120The 1.7 version changes handling of `PUT /resource_classes/{name}` to be a
121create or verification of the resource class with `{name}`. If the resource
122class is a custom resource class and does not already exist it will be created
123and a ``201`` response code returned. If the class already exists the response
124code will be ``204``. This makes it possible to check or create a resource
125class in one request.
diff --git a/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml b/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml
index 2b293f5..50a9ec5 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:
39 response_json_paths: 39 response_json_paths:
40 $.errors[0].title: Not Acceptable 40 $.errors[0].title: Not Acceptable
41 41
42- name: latest microversion is 1.6 42- name: latest microversion is 1.7
43 GET: / 43 GET: /
44 request_headers: 44 request_headers:
45 openstack-api-version: placement latest 45 openstack-api-version: placement latest
46 response_headers: 46 response_headers:
47 vary: /OpenStack-API-Version/ 47 vary: /OpenStack-API-Version/
48 openstack-api-version: placement 1.6 48 openstack-api-version: placement 1.7
49 49
50- name: other accept header bad version 50- name: other accept header bad version
51 GET: / 51 GET: /
diff --git a/nova/tests/functional/api/openstack/placement/gabbits/resource-classes-1-6.yaml b/nova/tests/functional/api/openstack/placement/gabbits/resource-classes-1-6.yaml
new file mode 100644
index 0000000..30f250d
--- /dev/null
+++ b/nova/tests/functional/api/openstack/placement/gabbits/resource-classes-1-6.yaml
@@ -0,0 +1,21 @@
1# Confirm that 1.7 behavior of PUT resource classes is not in
2# microversion 1.6.
3fixtures:
4 - APIFixture
5
6defaults:
7 request_headers:
8 x-auth-token: admin
9 accept: application/json
10 content-type: application/json
11 OpenStack-API-Version: placement 1.6
12
13tests:
14
15- name: bodiless put
16 PUT: /resource_classes/CUSTOM_COW
17 status: 400
18 response_strings:
19 # We don't check much of this string because it is different
20 # between python 2 and 3.
21 - "Malformed JSON:"
diff --git a/nova/tests/functional/api/openstack/placement/gabbits/resource-classes-1-7.yaml b/nova/tests/functional/api/openstack/placement/gabbits/resource-classes-1-7.yaml
new file mode 100644
index 0000000..2187c24
--- /dev/null
+++ b/nova/tests/functional/api/openstack/placement/gabbits/resource-classes-1-7.yaml
@@ -0,0 +1,49 @@
1fixtures:
2 - APIFixture
3
4defaults:
5 request_headers:
6 x-auth-token: admin
7 accept: application/json
8 content-type: application/json
9 OpenStack-API-Version: placement 1.7
10
11tests:
12
13- name: create new custom class with put
14 PUT: /resource_classes/CUSTOM_COW
15 status: 201
16 response_headers:
17 location: //resource_classes/CUSTOM_COW/
18
19- name: verify that class with put
20 PUT: /resource_classes/CUSTOM_COW
21 status: 204
22 response_headers:
23 location: //resource_classes/CUSTOM_COW/
24
25- name: fail to put non custom class
26 PUT: /resource_classes/COW
27 status: 400
28 response_strings:
29 - "Failed validating 'pattern'"
30
31- name: try to put standard class
32 PUT: /resource_classes/VCPU
33 status: 400
34 response_strings:
35 - "Failed validating 'pattern'"
36
37- name: try to put too long class
38 PUT: /resource_classes/CUSTOM_SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
39 status: 400
40 response_strings:
41 - "Failed validating 'maxLength'"
42
43- name: post to create still works
44 POST: /resource_classes
45 data:
46 name: CUSTOM_SHEEP
47 status: 201
48 response_headers:
49 location: //resource_classes/CUSTOM_SHEEP/
diff --git a/nova/tests/functional/api/openstack/placement/gabbits/resource-classes.yaml b/nova/tests/functional/api/openstack/placement/gabbits/resource-classes.yaml
index 9c3dd5e..8fd2045 100644
--- a/nova/tests/functional/api/openstack/placement/gabbits/resource-classes.yaml
+++ b/nova/tests/functional/api/openstack/placement/gabbits/resource-classes.yaml
@@ -125,6 +125,7 @@ tests:
125 PUT: /resource_classes/VCPU 125 PUT: /resource_classes/VCPU
126 request_headers: 126 request_headers:
127 content-type: application/json 127 content-type: application/json
128 OpenStack-API-Version: placement 1.6
128 data: 129 data:
129 name: VCPU_ALTERNATE 130 name: VCPU_ALTERNATE
130 status: 400 131 status: 400
@@ -137,6 +138,7 @@ tests:
137 PUT: /resource_classes/$ENVIRON['CUSTOM_RES_CLASS'] 138 PUT: /resource_classes/$ENVIRON['CUSTOM_RES_CLASS']
138 request_headers: 139 request_headers:
139 content-type: application/json 140 content-type: application/json
141 OpenStack-API-Version: placement 1.6
140 data: 142 data:
141 name: VCPU 143 name: VCPU
142 status: 400 144 status: 400
@@ -157,6 +159,7 @@ tests:
157 PUT: /resource_classes/CUSTOM_NFV_FOO 159 PUT: /resource_classes/CUSTOM_NFV_FOO
158 request_headers: 160 request_headers:
159 content-type: application/json 161 content-type: application/json
162 OpenStack-API-Version: placement 1.6
160 data: 163 data:
161 name: $ENVIRON['CUSTOM_RES_CLASS'] 164 name: $ENVIRON['CUSTOM_RES_CLASS']
162 status: 409 165 status: 409
@@ -170,6 +173,7 @@ tests:
170 PUT: /resource_classes/$ENVIRON['CUSTOM_RES_CLASS'] 173 PUT: /resource_classes/$ENVIRON['CUSTOM_RES_CLASS']
171 request_headers: 174 request_headers:
172 content-type: application/json 175 content-type: application/json
176 OpenStack-API-Version: placement 1.6
173 data: 177 data:
174 name: CUSTOM_NFV_BAR 178 name: CUSTOM_NFV_BAR
175 status: 200 179 status: 200
@@ -234,6 +238,7 @@ tests:
234 PUT: /resource_classes/$ENVIRON['CUSTOM_RES_CLASS'] 238 PUT: /resource_classes/$ENVIRON['CUSTOM_RES_CLASS']
235 request_headers: 239 request_headers:
236 content-type: application/json 240 content-type: application/json
241 OpenStack-API-Version: placement 1.6
237 data: 242 data:
238 name: *name_exceeds_max_length_check 243 name: *name_exceeds_max_length_check
239 status: 400 244 status: 400
diff --git a/releasenotes/notes/idempotent-put-resource-class-dc7a267c823b7995.yaml b/releasenotes/notes/idempotent-put-resource-class-dc7a267c823b7995.yaml
new file mode 100644
index 0000000..3892d27
--- /dev/null
+++ b/releasenotes/notes/idempotent-put-resource-class-dc7a267c823b7995.yaml
@@ -0,0 +1,10 @@
1---
2features:
3 - |
4 The 1.7 version of the placement API changes handling of
5 `PUT /resource_classes/{name}` to be a create or verification of the
6 resource class with `{name}`. If the resource class is a custom resource
7 class and does not already exist it will be created and a ``201`` response
8 code returned. If the class already exists the response code will be
9 ``204``. This makes it possible to check or create a resource class in one
10 request.