diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst index fa7677055c..f2c51b3f73 100644 --- a/doc/source/microversion_testing.rst +++ b/doc/source/microversion_testing.rst @@ -366,6 +366,10 @@ Microversion tests implemented in Tempest .. _2.55: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id49 + * `2.57`_ + + .. _2.57: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id51 + * `2.60`_ .. _2.60: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id54 diff --git a/tempest/api/compute/servers/test_servers_microversions.py b/tempest/api/compute/servers/test_servers_microversions.py index f3863f1f89..2434884ff2 100644 --- a/tempest/api/compute/servers/test_servers_microversions.py +++ b/tempest/api/compute/servers/test_servers_microversions.py @@ -49,3 +49,18 @@ class ServerShowV254Test(base.BaseV2ComputeTest): key_name=keypair_name) waiters.wait_for_server_status(self.servers_client, server['id'], 'ACTIVE') + + +class ServerShowV257Test(base.BaseV2ComputeTest): + min_microversion = '2.57' + max_microversion = 'latest' + + @decorators.idempotent_id('803df848-080a-4261-8f11-b020cd9b6f60') + def test_rebuild_server(self): + server = self.create_test_server(wait_until='ACTIVE') + user_data = "ZWNobyAiaGVsbG8gd29ybGQi" + # Checking rebuild API response schema + self.servers_client.rebuild_server(server['id'], self.image_ref_alt, + user_data=user_data) + waiters.wait_for_server_status(self.servers_client, + server['id'], 'ACTIVE') diff --git a/tempest/lib/api_schema/response/compute/v2_57/__init__.py b/tempest/lib/api_schema/response/compute/v2_57/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tempest/lib/api_schema/response/compute/v2_57/servers.py b/tempest/lib/api_schema/response/compute/v2_57/servers.py new file mode 100644 index 0000000000..ed1ca7dfd9 --- /dev/null +++ b/tempest/lib/api_schema/response/compute/v2_57/servers.py @@ -0,0 +1,53 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import copy + +from tempest.lib.api_schema.response.compute.v2_54 import servers as servers254 +# ****** Schemas changed in microversion 2.57 ***************** + +# Note(gmann): This is schema for microversion 2.57 which includes the +# 'user_data' in the Response body of the following APIs: +# - ``POST '/servers/{server_id}/action (rebuild)`` + +user_data = { + 'oneOf': [ + { + 'type': 'string', + 'format': 'base64', + 'maxLength': 65535 + }, + {'type': 'null'} + ] +} + +rebuild_server = copy.deepcopy(servers254.rebuild_server) +rebuild_server['response_body']['properties']['server'][ + 'properties'].update({'user_data': user_data}) +rebuild_server['response_body']['properties']['server'][ + 'required'].append('user_data') + +rebuild_server_with_admin_pass = copy.deepcopy( + servers254.rebuild_server_with_admin_pass) +rebuild_server_with_admin_pass['response_body']['properties']['server'][ + 'properties'].update({'user_data': user_data}) +rebuild_server_with_admin_pass['response_body']['properties']['server'][ + 'required'].append('user_data') + +# ****** Schemas unchanged in microversion 2.57 since microversion 2.54 *** + +# NOTE(gmann): Below are the unchanged schema in this microversion. We need +# to keeo this schema in this file to have the generic way to select the +# right schema based on self.schema_versions_info mapping in service client. +get_server = copy.deepcopy(servers254.get_server) +list_servers_detail = copy.deepcopy(servers254.list_servers_detail) +update_server = copy.deepcopy(servers254.update_server) diff --git a/tempest/lib/common/jsonschema_validator.py b/tempest/lib/common/jsonschema_validator.py index bbdf38255a..9a35b76217 100644 --- a/tempest/lib/common/jsonschema_validator.py +++ b/tempest/lib/common/jsonschema_validator.py @@ -12,9 +12,11 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +import base64 import jsonschema from oslo_utils import timeutils +import six # JSON Schema validator and format checker used for JSON Schema validation JSONSCHEMA_VALIDATOR = jsonschema.Draft4Validator @@ -37,3 +39,19 @@ def _validate_datetime_format(instance): return False else: return True + + +@jsonschema.FormatChecker.cls_checks('base64') +def _validate_base64_format(instance): + try: + if isinstance(instance, six.text_type): + instance = instance.encode('utf-8') + base64.decodestring(instance) + except base64.binascii.Error: + return False + except TypeError: + # The name must be string type. If instance isn't string type, the + # TypeError will be raised at here. + return False + + return True diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py index e75cdb5f31..f6e0e698b0 100644 --- a/tempest/lib/services/compute/servers_client.py +++ b/tempest/lib/services/compute/servers_client.py @@ -30,6 +30,7 @@ from tempest.lib.api_schema.response.compute.v2_3 import servers as schemav23 from tempest.lib.api_schema.response.compute.v2_47 import servers as schemav247 from tempest.lib.api_schema.response.compute.v2_48 import servers as schemav248 from tempest.lib.api_schema.response.compute.v2_54 import servers as schemav254 +from tempest.lib.api_schema.response.compute.v2_57 import servers as schemav257 from tempest.lib.api_schema.response.compute.v2_6 import servers as schemav26 from tempest.lib.api_schema.response.compute.v2_9 import servers as schemav29 from tempest.lib.common import rest_client @@ -49,7 +50,8 @@ class ServersClient(base_compute_client.BaseComputeClient): {'min': '2.26', 'max': '2.46', 'schema': schemav226}, {'min': '2.47', 'max': '2.47', 'schema': schemav247}, {'min': '2.48', 'max': '2.53', 'schema': schemav248}, - {'min': '2.54', 'max': None, 'schema': schemav254}] + {'min': '2.54', 'max': '2.56', 'schema': schemav254}, + {'min': '2.57', 'max': None, 'schema': schemav257}] def __init__(self, auth_provider, service, region, enable_instance_password=True, **kwargs):