Merge "Add response schema validation for volume types"
This commit is contained in:
@@ -92,15 +92,12 @@ class VolumeTypesTest(base.BaseVolumeAdminTest):
|
||||
'extra_specs': extra_specs,
|
||||
'os-volume-type-access:is_public': True}
|
||||
body = self.create_volume_type(**params)
|
||||
self.assertIn('name', body)
|
||||
self.assertEqual(name, body['name'],
|
||||
"The created volume_type name is not equal "
|
||||
"to the requested name")
|
||||
self.assertEqual(description, body['description'],
|
||||
"The created volume_type_description name is "
|
||||
"not equal to the requested name")
|
||||
self.assertIsNotNone(body['id'],
|
||||
"Field volume_type id is empty or not found.")
|
||||
fetched_volume_type = self.admin_volume_types_client.show_volume_type(
|
||||
body['id'])['volume_type']
|
||||
self.assertEqual(name, fetched_volume_type['name'],
|
||||
|
||||
176
tempest/lib/api_schema/response/volume/volume_types.py
Normal file
176
tempest/lib/api_schema/response/volume/volume_types.py
Normal file
@@ -0,0 +1,176 @@
|
||||
# Copyright 2018 ZTE Corporation. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
extra_specs_info = {
|
||||
'type': 'object',
|
||||
'patternProperties': {
|
||||
'^.+$': {'type': 'string'}
|
||||
}
|
||||
}
|
||||
|
||||
common_show_volume_type = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'extra_specs': extra_specs_info,
|
||||
'name': {'type': 'string'},
|
||||
'is_public': {'type': 'boolean'},
|
||||
'description': {'type': ['string', 'null']},
|
||||
'id': {'type': 'string', 'format': 'uuid'},
|
||||
'os-volume-type-access:is_public': {'type': 'boolean'},
|
||||
'qos_specs_id': {'type': ['string', 'null'], 'format': 'uuid'}
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['name', 'is_public', 'description', 'id',
|
||||
'os-volume-type-access:is_public']
|
||||
}
|
||||
|
||||
show_volume_type = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'volume_type': common_show_volume_type,
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['volume_type']
|
||||
}
|
||||
}
|
||||
|
||||
delete_volume_type = {'status_code': [202]}
|
||||
|
||||
create_volume_type = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'volume_type': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'extra_specs': extra_specs_info,
|
||||
'name': {'type': 'string'},
|
||||
'is_public': {'type': 'boolean'},
|
||||
'description': {'type': ['string', 'null']},
|
||||
'id': {'type': 'string', 'format': 'uuid'},
|
||||
'os-volume-type-access:is_public': {'type': 'boolean'}
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['name', 'is_public', 'id',
|
||||
'description', 'os-volume-type-access:is_public']
|
||||
},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['volume_type']
|
||||
}
|
||||
}
|
||||
|
||||
list_volume_types = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'volume_types': {
|
||||
'type': 'array',
|
||||
'items': common_show_volume_type
|
||||
}
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['volume_types']
|
||||
}
|
||||
}
|
||||
|
||||
list_volume_types_extra_specs = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'extra_specs': extra_specs_info
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['extra_specs']
|
||||
}
|
||||
}
|
||||
|
||||
show_volume_types_extra_specs = {
|
||||
'status_code': [200],
|
||||
'response_body': extra_specs_info
|
||||
}
|
||||
|
||||
create_volume_types_extra_specs = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'extra_specs': extra_specs_info
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['extra_specs']
|
||||
}
|
||||
}
|
||||
|
||||
delete_volume_types_extra_specs = {'status_code': [202]}
|
||||
|
||||
update_volume_types = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'volume_type': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'extra_specs': extra_specs_info,
|
||||
'name': {'type': 'string'},
|
||||
'is_public': {'type': 'boolean'},
|
||||
'description': {'type': ['string', 'null']},
|
||||
'id': {'type': 'string', 'format': 'uuid'}
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['name', 'is_public', 'description', 'id']
|
||||
},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['volume_type']
|
||||
}
|
||||
}
|
||||
|
||||
update_volume_type_extra_specs = {
|
||||
'status_code': [200],
|
||||
'response_body': extra_specs_info
|
||||
}
|
||||
|
||||
add_type_access = {'status_code': [202]}
|
||||
|
||||
remove_type_access = {'status_code': [202]}
|
||||
|
||||
list_type_access = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'volume_type_access': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'volume_type_id': {'type': 'string', 'format': 'uuid'},
|
||||
'project_id': {'type': 'string', 'format': 'uuid'},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['volume_type_id', 'project_id']
|
||||
}
|
||||
}
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['volume_type_access']
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
from oslo_serialization import jsonutils as json
|
||||
from six.moves.urllib import parse as urllib
|
||||
|
||||
from tempest.lib.api_schema.response.volume import volume_types as schema
|
||||
from tempest.lib.common import rest_client
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
|
||||
@@ -48,7 +49,7 @@ class TypesClient(rest_client.RestClient):
|
||||
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.list_volume_types, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_volume_type(self, volume_type_id):
|
||||
@@ -61,7 +62,7 @@ class TypesClient(rest_client.RestClient):
|
||||
url = "types/%s" % volume_type_id
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.show_volume_type, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def create_volume_type(self, **kwargs):
|
||||
@@ -74,7 +75,7 @@ class TypesClient(rest_client.RestClient):
|
||||
post_body = json.dumps({'volume_type': kwargs})
|
||||
resp, body = self.post('types', post_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.create_volume_type, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def delete_volume_type(self, volume_type_id):
|
||||
@@ -85,7 +86,7 @@ class TypesClient(rest_client.RestClient):
|
||||
https://docs.openstack.org/api-ref/block-storage/v3/index.html#delete-a-volume-type
|
||||
"""
|
||||
resp, body = self.delete("types/%s" % volume_type_id)
|
||||
self.expected_success(202, resp.status)
|
||||
self.validate_response(schema.delete_volume_type, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def list_volume_types_extra_specs(self, volume_type_id, **params):
|
||||
@@ -101,7 +102,8 @@ class TypesClient(rest_client.RestClient):
|
||||
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(
|
||||
schema.list_volume_types_extra_specs, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_volume_type_extra_specs(self, volume_type_id, extra_specs_name):
|
||||
@@ -109,7 +111,8 @@ class TypesClient(rest_client.RestClient):
|
||||
url = "types/%s/extra_specs/%s" % (volume_type_id, extra_specs_name)
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(
|
||||
schema.show_volume_types_extra_specs, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def create_volume_type_extra_specs(self, volume_type_id, extra_specs):
|
||||
@@ -122,14 +125,16 @@ class TypesClient(rest_client.RestClient):
|
||||
post_body = json.dumps({'extra_specs': extra_specs})
|
||||
resp, body = self.post(url, post_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(
|
||||
schema.create_volume_types_extra_specs, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def delete_volume_type_extra_specs(self, volume_type_id, extra_spec_name):
|
||||
"""Deletes the specified volume type extra spec."""
|
||||
resp, body = self.delete("types/%s/extra_specs/%s" % (
|
||||
volume_type_id, extra_spec_name))
|
||||
self.expected_success(202, resp.status)
|
||||
self.validate_response(
|
||||
schema.delete_volume_types_extra_specs, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_volume_type(self, volume_type_id, **kwargs):
|
||||
@@ -142,7 +147,7 @@ class TypesClient(rest_client.RestClient):
|
||||
put_body = json.dumps({'volume_type': kwargs})
|
||||
resp, body = self.put('types/%s' % volume_type_id, put_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.update_volume_types, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_volume_type_extra_specs(self, volume_type_id, extra_spec_name,
|
||||
@@ -162,7 +167,8 @@ class TypesClient(rest_client.RestClient):
|
||||
put_body = json.dumps(extra_specs)
|
||||
resp, body = self.put(url, put_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(
|
||||
schema.update_volume_type_extra_specs, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def add_type_access(self, volume_type_id, **kwargs):
|
||||
@@ -175,7 +181,7 @@ class TypesClient(rest_client.RestClient):
|
||||
post_body = json.dumps({'addProjectAccess': kwargs})
|
||||
url = 'types/%s/action' % volume_type_id
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
self.validate_response(schema.add_type_access, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def remove_type_access(self, volume_type_id, **kwargs):
|
||||
@@ -188,7 +194,7 @@ class TypesClient(rest_client.RestClient):
|
||||
post_body = json.dumps({'removeProjectAccess': kwargs})
|
||||
url = 'types/%s/action' % volume_type_id
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
self.validate_response(schema.remove_type_access, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def list_type_access(self, volume_type_id):
|
||||
@@ -201,5 +207,5 @@ class TypesClient(rest_client.RestClient):
|
||||
url = 'types/%s/os-volume-type-access' % volume_type_id
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.list_type_access, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
Reference in New Issue
Block a user