Browse Source

[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
tags/16.0.0.0b2
Chris Dent 2 years ago
parent
commit
697c2d89ee

+ 36
- 1
nova/api/openstack/placement/handlers/resource_class.py View File

@@ -164,7 +164,7 @@ def list_resource_classes(req):
164 164
 
165 165
 
166 166
 @wsgi_wrapper.PlacementWsgify
167
-@microversion.version_handler('1.2')
167
+@microversion.version_handler('1.2', '1.6')
168 168
 @util.require_content('application/json')
169 169
 def update_resource_class(req):
170 170
     """PUT to update a single resource class.
@@ -199,3 +199,38 @@ def update_resource_class(req):
199 199
     req.response.status = 200
200 200
     req.response.content_type = 'application/json'
201 201
     return req.response
202
+
203
+
204
+@wsgi_wrapper.PlacementWsgify  # noqa
205
+@microversion.version_handler('1.7')
206
+def 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

+ 1
- 0
nova/api/openstack/placement/microversion.py View File

@@ -43,6 +43,7 @@ VERSIONS = [
43 43
     '1.5',  # Adds DELETE /resource_providers/{uuid}/inventories
44 44
     '1.6',  # Adds /traits and /resource_providers{uuid}/traits resource
45 45
             # endpoints
46
+    '1.7',  # PUT /resource_classes/{name} is bodiless create or update
46 47
 ]
47 48
 
48 49
 

+ 10
- 0
nova/api/openstack/placement/rest_api_version_history.rst View File

@@ -113,3 +113,13 @@ The following new routes are added:
113 113
 Custom traits must begin with the prefix "CUSTOM\_" and contain only
114 114
 the letters A through Z, the numbers 0 through 9 and the underscore "\_"
115 115
 character.
116
+
117
+1.7 Idempotent PUT /resource_classes/{name}
118
+-------------------------------------------
119
+
120
+The 1.7 version changes handling of `PUT /resource_classes/{name}` to be a
121
+create or verification of the resource class with `{name}`. If the resource
122
+class is a custom resource class and does not already exist it will be created
123
+and a ``201`` response code returned. If the class already exists the response
124
+code will be ``204``. This makes it possible to check or create a resource
125
+class in one request.

+ 2
- 2
nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml View File

@@ -39,13 +39,13 @@ tests:
39 39
   response_json_paths:
40 40
       $.errors[0].title: Not Acceptable
41 41
 
42
-- name: latest microversion is 1.6
42
+- name: latest microversion is 1.7
43 43
   GET: /
44 44
   request_headers:
45 45
       openstack-api-version: placement latest
46 46
   response_headers:
47 47
       vary: /OpenStack-API-Version/
48
-      openstack-api-version: placement 1.6
48
+      openstack-api-version: placement 1.7
49 49
 
50 50
 - name: other accept header bad version
51 51
   GET: /

+ 21
- 0
nova/tests/functional/api/openstack/placement/gabbits/resource-classes-1-6.yaml View File

@@ -0,0 +1,21 @@
1
+# Confirm that 1.7 behavior of PUT resource classes is not in
2
+# microversion 1.6.
3
+fixtures:
4
+    - APIFixture
5
+
6
+defaults:
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
+
13
+tests:
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:"

+ 49
- 0
nova/tests/functional/api/openstack/placement/gabbits/resource-classes-1-7.yaml View File

@@ -0,0 +1,49 @@
1
+fixtures:
2
+    - APIFixture
3
+
4
+defaults:
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
+
11
+tests:
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/

+ 5
- 0
nova/tests/functional/api/openstack/placement/gabbits/resource-classes.yaml View File

@@ -125,6 +125,7 @@ tests:
125 125
   PUT: /resource_classes/VCPU
126 126
   request_headers:
127 127
     content-type: application/json
128
+    OpenStack-API-Version: placement 1.6
128 129
   data:
129 130
       name: VCPU_ALTERNATE
130 131
   status: 400
@@ -137,6 +138,7 @@ tests:
137 138
   PUT: /resource_classes/$ENVIRON['CUSTOM_RES_CLASS']
138 139
   request_headers:
139 140
     content-type: application/json
141
+    OpenStack-API-Version: placement 1.6
140 142
   data:
141 143
       name: VCPU
142 144
   status: 400
@@ -157,6 +159,7 @@ tests:
157 159
   PUT: /resource_classes/CUSTOM_NFV_FOO
158 160
   request_headers:
159 161
     content-type: application/json
162
+    OpenStack-API-Version: placement 1.6
160 163
   data:
161 164
       name: $ENVIRON['CUSTOM_RES_CLASS']
162 165
   status: 409
@@ -170,6 +173,7 @@ tests:
170 173
   PUT: /resource_classes/$ENVIRON['CUSTOM_RES_CLASS']
171 174
   request_headers:
172 175
     content-type: application/json
176
+    OpenStack-API-Version: placement 1.6
173 177
   data:
174 178
       name: CUSTOM_NFV_BAR
175 179
   status: 200
@@ -234,6 +238,7 @@ tests:
234 238
   PUT: /resource_classes/$ENVIRON['CUSTOM_RES_CLASS']
235 239
   request_headers:
236 240
       content-type: application/json
241
+      OpenStack-API-Version: placement 1.6
237 242
   data:
238 243
       name: *name_exceeds_max_length_check
239 244
   status: 400

+ 10
- 0
releasenotes/notes/idempotent-put-resource-class-dc7a267c823b7995.yaml View File

@@ -0,0 +1,10 @@
1
+---
2
+features:
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.

Loading…
Cancel
Save