blob: e035e666382b85d07bee8d1e093599c46c613be4 [file] [log] [blame]
ghanshyam933d9822017-03-13 06:09:02 +00001=================================
2Microversion Testing With Tempest
3=================================
ghanshyambd460ac2016-03-16 16:28:56 +09004
ghanshyam933d9822017-03-13 06:09:02 +00005Many OpenStack Services provide their APIs with `microversion`_
6support and want to test them in Tempest.
ghanshyambd460ac2016-03-16 16:28:56 +09007
ghanshyam933d9822017-03-13 06:09:02 +00008.. _microversion: http://specs.openstack.org/openstack/api-wg/guidelines/microversion_specification.html
9
10This document covers how to test microversions for each project and
11whether tests should live in Tempest or on project side.
12
13Tempest Scope For Microversion Testing
14""""""""""""""""""""""""""""""""""""""
15APIs microversions for any OpenStack service grow rapidly and
16testing each and every microversion in Tempest is not feasible and
17efficient way.
18Also not every API microversion changes the complete system behavior
19and many of them only change the API or DB layer to accept and return more
20data on API.
21
22Tempest is an integration test suite, but not all API microversion testing fall under this category.
23As a result, Tempest mainly covers integration test cases for microversions, Other testing coverage
24for microversion should be hosted on project side as functional tests or via Tempest plugin as per
25project guidelines.
26
27.. note:: Integration tests are those tests which involve more than one service to
28 verify the expected behavior by single or combination of API requests.
29 If a test is just to verify the API behavior as success and failure cases
30 or verify its expected response object, then it does not fall under integration
31 tests.
32
33Tempest will cover only integration testing of applicable microversions with
34below exceptions:
35
Masayuki Igawab78b9232017-11-17 16:12:37 +090036#. Test covers a feature which is important for interoperability. This covers tests requirement
37 from Defcore.
38#. Test needed to fill Schema gaps.
39 Tempest validates API responses with defined JSON schema. API responses can be different on
40 each microversion and the JSON schemas need to be defined separately for the microversion.
41 While implementing new integration tests for a specific microversion, there
42 may be a gap in the JSON schemas (caused by previous microversions) implemented
43 in Tempest.
44 Filling that gap while implementing the new integration test cases is not efficient due to
45 many reasons:
ghanshyam933d9822017-03-13 06:09:02 +000046
Masayuki Igawab78b9232017-11-17 16:12:37 +090047 * Hard to review
48 * Sync between multiple integration tests patches which try to fill the same schema gap at same
49 time
50 * Might delay the microversion change on project side where project team wants Tempest
51 tests to verify the results.
ghanshyam933d9822017-03-13 06:09:02 +000052
Masayuki Igawab78b9232017-11-17 16:12:37 +090053 Tempest will allow to fill the schema gaps at the end of each cycle, or more
54 often if required.
55 Schema gap can be filled with testing those with a minimal set of tests. Those
56 tests might not be integration tests and might be already covered on project
57 side also.
58 This exception is needed because:
ghanshyam933d9822017-03-13 06:09:02 +000059
Masayuki Igawab78b9232017-11-17 16:12:37 +090060 * Allow to create microversion response schema in Tempest at the same time that projects are
61 implementing their API microversions. This will make implementation easier for adding
62 required tests before a new microversion change can be merged in the corresponding project
63 and hence accelerate the development of microversions.
64 * New schema must be verified by at least one test case which exercises such schema.
ghanshyam933d9822017-03-13 06:09:02 +000065
Masayuki Igawab78b9232017-11-17 16:12:37 +090066 For example:
67 If any projects implemented 4 API microversion say- v2.3, v2.4, v2.5, v2.6
68 Assume microversion v2.3, v2.4, v2.6 change the API Response which means Tempest
69 needs to add JSON schema for v2.3, v2.4, v2.6.
70 In that case if only 1 or 2 tests can verify all new schemas then we do not need
71 separate tests for each new schemas. In worst case, we have to add 3 separate tests.
72#. Test covers service behavior at large scale with involvement of more deep layer like hypervisor
73 etc not just API/DB layer. This type of tests will be added case by case basis and
74 with project team consultation about why it cannot be covered on project side and worth to test
75 in Tempest.
ghanshyam933d9822017-03-13 06:09:02 +000076
77Project Scope For Microversion Testing
78""""""""""""""""""""""""""""""""""""""
79All microversions testing which are not covered under Tempest as per above section, should be
80tested on project side as functional tests or as Tempest plugin as per project decision.
ghanshyambd460ac2016-03-16 16:28:56 +090081
82
83Configuration options for Microversion
84""""""""""""""""""""""""""""""""""""""
85
86* Add configuration options for specifying test target Microversions.
87 We need to specify test target Microversions because the supported
ghanshyame5607282016-03-24 17:22:10 +090088 Microversions may be different between OpenStack clouds. For operating
ghanshyambd460ac2016-03-16 16:28:56 +090089 multiple Microversion tests in a single Tempest operation, configuration
90 options should represent the range of test target Microversions.
91 New configuration options are:
Matt Riedemann3ea70c22016-06-08 08:55:58 -040092
ghanshyame5607282016-03-24 17:22:10 +090093 * min_microversion
94 * max_microversion
95
ghanshyambd460ac2016-03-16 16:28:56 +090096 Those should be defined under respective section of each service.
Yushiro FURUKAWA836361d2016-09-30 23:26:58 +090097 For example:
98
99 .. code-block:: ini
Masayuki Igawae63cf0f2016-05-25 10:25:21 +0900100
ghanshyambd460ac2016-03-16 16:28:56 +0900101 [compute]
102 min_microversion = None
103 max_microversion = latest
104
105
106How To Implement Microversion Tests
107"""""""""""""""""""""""""""""""""""
108
ghanshyam933d9822017-03-13 06:09:02 +0000109Tempest provides stable interfaces to test API Microversion.
110For Details, see: `API Microversion testing Framework`_
111This document explains how to implement Microversion tests using those
112interfaces.
113
chenxinge98720a2017-07-19 03:42:23 +0000114.. _API Microversion testing Framework: https://docs.openstack.org/tempest/latest/library/api_microversion_testing.html
ghanshyam933d9822017-03-13 06:09:02 +0000115
116
ghanshyame5607282016-03-24 17:22:10 +0900117Step1: Add skip logic based on configured Microversion range
ghanshyambd460ac2016-03-16 16:28:56 +0900118''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
119
120Add logic to skip the tests based on Tests class and configured Microversion
121range.
122api_version_utils.check_skip_with_microversion function can be used
Tong Liue0a3b8e2016-03-24 20:32:07 +0000123to automatically skip the tests which do not fall under configured
ghanshyambd460ac2016-03-16 16:28:56 +0900124Microversion range.
Yushiro FURUKAWA836361d2016-09-30 23:26:58 +0900125For example:
126
127.. code-block:: python
ghanshyambd460ac2016-03-16 16:28:56 +0900128
129 class BaseTestCase1(api_version_utils.BaseMicroversionTest):
130
131 [..]
132 @classmethod
133 def skip_checks(cls):
134 super(BaseTestCase1, cls).skip_checks()
135 api_version_utils.check_skip_with_microversion(cls.min_microversion,
136 cls.max_microversion,
137 CONF.compute.min_microversion,
138 CONF.compute.max_microversion)
139
140Skip logic can be added in tests base class or any specific test class depends on
141tests class structure.
142
143Step2: Selected API request microversion
144''''''''''''''''''''''''''''''''''''''''
145
146Select appropriate Microversion which needs to be used
147to send with API request.
148api_version_utils.select_request_microversion function can be used
ghanshyame5607282016-03-24 17:22:10 +0900149to select the appropriate Microversion which will be used for API request.
Yushiro FURUKAWA836361d2016-09-30 23:26:58 +0900150For example:
151
152.. code-block:: python
ghanshyambd460ac2016-03-16 16:28:56 +0900153
154 @classmethod
155 def resource_setup(cls):
156 super(BaseTestCase1, cls).resource_setup()
157 cls.request_microversion = (
158 api_version_utils.select_request_microversion(
159 cls.min_microversion,
160 CONF.compute.min_microversion))
161
162
163Step3: Set Microversion on Service Clients
164''''''''''''''''''''''''''''''''''''''''''
165
166Microversion selected by Test Class in previous step needs to be set on
ghanshyame5607282016-03-24 17:22:10 +0900167service clients so that APIs can be requested with selected Microversion.
ghanshyambd460ac2016-03-16 16:28:56 +0900168
169Microversion can be defined as global variable on service clients which
170can be set using fixture.
ghanshyame5607282016-03-24 17:22:10 +0900171Also Microversion header name needs to be defined on service clients which
ghanshyambd460ac2016-03-16 16:28:56 +0900172should be constant because it is not supposed to be changed by project
173as per API contract.
Yushiro FURUKAWA836361d2016-09-30 23:26:58 +0900174For example:
175
176.. code-block:: python
ghanshyambd460ac2016-03-16 16:28:56 +0900177
178 COMPUTE_MICROVERSION = None
179
180 class BaseClient1(rest_client.RestClient):
181 api_microversion_header_name = 'X-OpenStack-Nova-API-Version'
182
ghanshyame5607282016-03-24 17:22:10 +0900183Now test class can set the selected Microversion on required service clients
184using fixture which can take care of resetting the same once tests is completed.
Yushiro FURUKAWA836361d2016-09-30 23:26:58 +0900185For example:
186
187.. code-block:: python
ghanshyambd460ac2016-03-16 16:28:56 +0900188
189 def setUp(self):
ghanshyame5607282016-03-24 17:22:10 +0900190 super(BaseTestCase1, self).setUp()
ghanshyambd460ac2016-03-16 16:28:56 +0900191 self.useFixture(api_microversion_fixture.APIMicroversionFixture(
192 self.request_microversion))
193
ghanshyame5607282016-03-24 17:22:10 +0900194Service clients needs to add set Microversion in API request header which
ghanshyambd460ac2016-03-16 16:28:56 +0900195can be done by overriding the get_headers() method of rest_client.
Yushiro FURUKAWA836361d2016-09-30 23:26:58 +0900196For example:
197
198.. code-block:: python
ghanshyambd460ac2016-03-16 16:28:56 +0900199
200 COMPUTE_MICROVERSION = None
201
202 class BaseClient1(rest_client.RestClient):
203 api_microversion_header_name = 'X-OpenStack-Nova-API-Version'
204
205 def get_headers(self):
206 headers = super(BaseClient1, self).get_headers()
207 if COMPUTE_MICROVERSION:
208 headers[self.api_microversion_header_name] = COMPUTE_MICROVERSION
209 return headers
210
211
212Step4: Separate Test classes for each Microversion
213''''''''''''''''''''''''''''''''''''''''''''''''''
214
ghanshyame5607282016-03-24 17:22:10 +0900215This is last step to implement Microversion test class.
ghanshyambd460ac2016-03-16 16:28:56 +0900216
ghanshyame5607282016-03-24 17:22:10 +0900217For any Microversion tests, basically we need to implement a
ghanshyambd460ac2016-03-16 16:28:56 +0900218separate test class. In addition, each test class defines its
ghanshyame5607282016-03-24 17:22:10 +0900219Microversion range with class variable like min_microversion
ghanshyambd460ac2016-03-16 16:28:56 +0900220and max_microversion. Tests will be valid for that defined range.
ghanshyame5607282016-03-24 17:22:10 +0900221If that range is out of configured Microversion range then, test
ghanshyambd460ac2016-03-16 16:28:56 +0900222will be skipped.
223
Matt Riedemann3ea70c22016-06-08 08:55:58 -0400224.. note:: Microversion testing is supported at test class level not at
225 individual test case level.
226
ghanshyambd460ac2016-03-16 16:28:56 +0900227For example:
228
Yushiro FURUKAWA836361d2016-09-30 23:26:58 +0900229Below test is applicable for Microversion from 2.2 till 2.9:
230
231.. code-block:: python
ghanshyambd460ac2016-03-16 16:28:56 +0900232
233 class BaseTestCase1(api_version_utils.BaseMicroversionTest,
234 tempest.test.BaseTestCase):
235
236 [..]
237
238
239 class Test1(BaseTestCase1):
240 min_microversion = '2.2'
241 max_microversion = '2.9'
242
243 [..]
244
Yushiro FURUKAWA836361d2016-09-30 23:26:58 +0900245Below test is applicable for Microversion from 2.10 till latest:
246
247.. code-block:: python
ghanshyambd460ac2016-03-16 16:28:56 +0900248
249 class Test2(BaseTestCase1):
250 min_microversion = '2.10'
251 max_microversion = 'latest'
252
253 [..]
254
255
ghanshyambd460ac2016-03-16 16:28:56 +0900256Notes about Compute Microversion Tests
Masayuki Igawae63cf0f2016-05-25 10:25:21 +0900257""""""""""""""""""""""""""""""""""""""
258
ghanshyambd460ac2016-03-16 16:28:56 +0900259Some of the compute Microversion tests have been already implemented
ghanshyame5607282016-03-24 17:22:10 +0900260with the Microversion testing framework. So for further tests only
ghanshyambd460ac2016-03-16 16:28:56 +0900261step 4 is needed.
262
263Along with that JSON response schema might need versioning if needed.
264
265Compute service clients strictly validate the response against defined JSON
266schema and does not allow additional elements in response.
Tong Liue0a3b8e2016-03-24 20:32:07 +0000267So if that Microversion changed the API response then schema needs to be versioned.
268New JSON schema file needs to be defined with new response attributes and service
ghanshyambd460ac2016-03-16 16:28:56 +0900269client methods will select the schema based on requested microversion.
270
Tong Liue0a3b8e2016-03-24 20:32:07 +0000271If Microversion tests are implemented randomly meaning not
ghanshyame5607282016-03-24 17:22:10 +0900272in sequence order(v2.20 tests added and previous Microversion tests are not yet added)
Tong Liue0a3b8e2016-03-24 20:32:07 +0000273then, still schema might need to be version for older Microversion if they changed
ghanshyambd460ac2016-03-16 16:28:56 +0900274the response.
ghanshyame5607282016-03-24 17:22:10 +0900275This is because Nova Microversion includes all the previous Microversions behavior.
ghanshyambd460ac2016-03-16 16:28:56 +0900276
277For Example:
ghanshyame5607282016-03-24 17:22:10 +0900278 Implementing the v2.20 Microversion tests before v2.9 and 2.19-
ghanshyambd460ac2016-03-16 16:28:56 +0900279 v2.20 API request will respond as latest behavior of Nova till v2.20,
280 and in v2.9 and 2.19, server response has been changed so response schema needs
Tong Liue0a3b8e2016-03-24 20:32:07 +0000281 to be versioned accordingly.
ghanshyambd460ac2016-03-16 16:28:56 +0900282
283That can be done by using the get_schema method in below module:
284
285The base_compute_client module
286''''''''''''''''''''''''''''''
287
288.. automodule:: tempest.lib.services.compute.base_compute_client
289 :members:
290
291
292Microversion tests implemented in Tempest
293"""""""""""""""""""""""""""""""""""""""""
294
295* Compute
296
Masayuki Igawab78b9232017-11-17 16:12:37 +0900297 * `2.1`_
ghanshyambd460ac2016-03-16 16:28:56 +0900298
Masayuki Igawab78b9232017-11-17 16:12:37 +0900299 .. _2.1: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id1
ghanshyambd460ac2016-03-16 16:28:56 +0900300
Masayuki Igawab78b9232017-11-17 16:12:37 +0900301 * `2.2`_
ghanshyambd460ac2016-03-16 16:28:56 +0900302
Masayuki Igawab78b9232017-11-17 16:12:37 +0900303 .. _2.2: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id2
ghanshyamba48c902016-04-15 13:42:35 +0900304
zhufle72760f2018-01-03 13:53:08 +0800305 * `2.6`_
306
307 .. _2.6: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id5
308
ghanshyama8ace722018-04-20 08:45:10 +0000309 * `2.9`_
310
311 .. _2.9: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id8
312
Masayuki Igawab78b9232017-11-17 16:12:37 +0900313 * `2.10`_
ghanshyamba48c902016-04-15 13:42:35 +0900314
Masayuki Igawab78b9232017-11-17 16:12:37 +0900315 .. _2.10: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id9
Matt Riedemann3ea70c22016-06-08 08:55:58 -0400316
ghanshyama8ace722018-04-20 08:45:10 +0000317 * `2.19`_
318
319 .. _2.19: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id17
320
Masayuki Igawab78b9232017-11-17 16:12:37 +0900321 * `2.20`_
Matt Riedemann3ea70c22016-06-08 08:55:58 -0400322
Masayuki Igawab78b9232017-11-17 16:12:37 +0900323 .. _2.20: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id18
Eli Qiaoe07eacc2016-03-03 13:49:37 +0800324
zhufle72760f2018-01-03 13:53:08 +0800325 * `2.21`_
326
327 .. _2.21: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id19
328
Masayuki Igawab78b9232017-11-17 16:12:37 +0900329 * `2.25`_
Eli Qiaoe07eacc2016-03-03 13:49:37 +0800330
Masayuki Igawab78b9232017-11-17 16:12:37 +0900331 .. _2.25: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#maximum-in-mitaka
Matt Riedemann3e4a46a2016-07-27 14:41:32 -0400332
ghanshyama8ace722018-04-20 08:45:10 +0000333 * `2.26`_
334
335 .. _2.26: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id23
336
Masayuki Igawab78b9232017-11-17 16:12:37 +0900337 * `2.32`_
Artom Lifshitzfc8f8e62016-04-13 11:08:32 +0000338
Masayuki Igawab78b9232017-11-17 16:12:37 +0900339 .. _2.32: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id29
Artom Lifshitzfc8f8e62016-04-13 11:08:32 +0000340
Masayuki Igawab78b9232017-11-17 16:12:37 +0900341 * `2.37`_
Matt Riedemann3e4a46a2016-07-27 14:41:32 -0400342
Masayuki Igawab78b9232017-11-17 16:12:37 +0900343 .. _2.37: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id34
Matt Riedemann07845fa2017-01-30 20:18:08 -0500344
Masayuki Igawab78b9232017-11-17 16:12:37 +0900345 * `2.42`_
Matt Riedemann07845fa2017-01-30 20:18:08 -0500346
Masayuki Igawab78b9232017-11-17 16:12:37 +0900347 .. _2.42: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#maximum-in-ocata
ghanshyam58fbcd02017-03-13 04:37:17 +0000348
Masayuki Igawab78b9232017-11-17 16:12:37 +0900349 * `2.47`_
Sergey Nikitin8654e5b2017-06-04 22:09:56 +0400350
Masayuki Igawab78b9232017-11-17 16:12:37 +0900351 .. _2.47: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id42
Sergey Nikitin8654e5b2017-06-04 22:09:56 +0400352
Masayuki Igawab78b9232017-11-17 16:12:37 +0900353 * `2.48`_
Sergey Nikitin0cb4f222017-02-03 13:16:33 +0400354
Masayuki Igawab78b9232017-11-17 16:12:37 +0900355 .. _2.48: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id43
Sergey Nikitin0cb4f222017-02-03 13:16:33 +0400356
Artom Lifshitzb6b2bba2016-10-31 14:56:40 -0400357 * `2.49`_
358
359 .. _2.49: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id44
360
ghanshyam85a4b0a2018-04-24 11:09:25 +0300361 * `2.54`_
362
Felipe Monteirodd09bd92018-07-07 16:25:18 -0400363 .. _2.54: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id49
ghanshyam85a4b0a2018-04-24 11:09:25 +0300364
ghanshyam52c5d282018-04-23 08:43:25 +0000365 * `2.55`_
366
Felipe Monteirodd09bd92018-07-07 16:25:18 -0400367 .. _2.55: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id50
ghanshyam52c5d282018-04-23 08:43:25 +0000368
Ghanshyamd5394652018-04-26 07:59:32 +0000369 * `2.57`_
370
Felipe Monteirodd09bd92018-07-07 16:25:18 -0400371 .. _2.57: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id52
Ghanshyamd5394652018-04-26 07:59:32 +0000372
Matt Riedemann81fa9b62016-01-14 13:04:38 -0800373 * `2.60`_
374
Jackie Truong1fa44642017-10-25 16:42:08 -0400375 .. _2.60: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#maximum-in-queens
376
377 * `2.63`_
378
379 .. _2.63: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id57
Matt Riedemann81fa9b62016-01-14 13:04:38 -0800380
ghanshyam58fbcd02017-03-13 04:37:17 +0000381* Volume
382
Masayuki Igawab78b9232017-11-17 16:12:37 +0900383 * `3.3`_
ghanshyam58fbcd02017-03-13 04:37:17 +0000384
Masayuki Igawab78b9232017-11-17 16:12:37 +0900385 .. _3.3: https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id3
ghanshyamdc6e2a82017-09-28 07:21:59 +0000386
Masayuki Igawab78b9232017-11-17 16:12:37 +0900387 * `3.9`_
ghanshyamdc6e2a82017-09-28 07:21:59 +0000388
Masayuki Igawab78b9232017-11-17 16:12:37 +0900389 .. _3.9: https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id9
ghanshyamdc6e2a82017-09-28 07:21:59 +0000390
Masayuki Igawab78b9232017-11-17 16:12:37 +0900391 * `3.11`_
ghanshyamdc6e2a82017-09-28 07:21:59 +0000392
Masayuki Igawab78b9232017-11-17 16:12:37 +0900393 .. _3.11: https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id11
ghanshyamdc6e2a82017-09-28 07:21:59 +0000394
Masayuki Igawab78b9232017-11-17 16:12:37 +0900395 * `3.12`_
ghanshyamdc6e2a82017-09-28 07:21:59 +0000396
Masayuki Igawab78b9232017-11-17 16:12:37 +0900397 .. _3.12: https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id12
ghanshyamdc6e2a82017-09-28 07:21:59 +0000398
jeremy.zhang2abe00a2017-11-21 10:14:09 +0800399 * `3.13`_
400
401 .. _3.13: https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id13
402
Masayuki Igawab78b9232017-11-17 16:12:37 +0900403 * `3.14`_
ghanshyamdc6e2a82017-09-28 07:21:59 +0000404
Masayuki Igawab78b9232017-11-17 16:12:37 +0900405 .. _3.14: https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id14
ghanshyamdc6e2a82017-09-28 07:21:59 +0000406
Masayuki Igawab78b9232017-11-17 16:12:37 +0900407 * `3.19`_
ghanshyamdc6e2a82017-09-28 07:21:59 +0000408
Masayuki Igawab78b9232017-11-17 16:12:37 +0900409 .. _3.19: https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id18
ghanshyamdc6e2a82017-09-28 07:21:59 +0000410
Masayuki Igawab78b9232017-11-17 16:12:37 +0900411 * `3.20`_
ghanshyamdc6e2a82017-09-28 07:21:59 +0000412
Masayuki Igawab78b9232017-11-17 16:12:37 +0900413 .. _3.20: https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id19