Add response schema validation for volume snapshots
This is to add response schema validation for volume snapshots. Change-Id: I7de5569ed58fb6a3bf8115f89163cd951c19d951 partially-implements: blueprint volume-response-schema-validation
This commit is contained in:
parent
0c71fc29a1
commit
adb162024d
|
@ -0,0 +1,198 @@
|
|||
# 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.
|
||||
import copy
|
||||
|
||||
from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
|
||||
|
||||
metadata = {
|
||||
'type': 'object',
|
||||
'patternProperties': {
|
||||
'^.+$': {'type': 'string'}
|
||||
}
|
||||
}
|
||||
|
||||
common_snapshot_schema = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'status': {'type': 'string'},
|
||||
'description': {'type': ['string', 'null']},
|
||||
'created_at': parameter_types.date_time,
|
||||
'name': {'type': 'string'},
|
||||
'volume_id': {'type': 'string', 'format': 'uuid'},
|
||||
'metadata': metadata,
|
||||
'id': {'type': 'string', 'format': 'uuid'},
|
||||
'size': {'type': 'integer'},
|
||||
'updated_at': parameter_types.date_time_or_null,
|
||||
# TODO(zhufl): user_id is added in 3.41, we should move it
|
||||
# to the 3.41 schema file when microversion is supported
|
||||
# in volume interfaces
|
||||
# 'user_id': {'type': 'string', 'format': 'uuid'}
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['status', 'description', 'created_at', 'metadata',
|
||||
'name', 'volume_id', 'id', 'size', 'updated_at']
|
||||
}
|
||||
|
||||
common_snapshot_detail_schema = copy.deepcopy(common_snapshot_schema)
|
||||
common_snapshot_detail_schema['properties'].update(
|
||||
{'os-extended-snapshot-attributes:progress': {'type': 'string'},
|
||||
'os-extended-snapshot-attributes:project_id': {
|
||||
'type': 'string', 'format': 'uuid'}})
|
||||
common_snapshot_detail_schema['required'].extend(
|
||||
['os-extended-snapshot-attributes:progress',
|
||||
'os-extended-snapshot-attributes:project_id'])
|
||||
|
||||
list_snapshots_no_detail = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'snapshots': {
|
||||
'type': 'array',
|
||||
'items': common_snapshot_schema
|
||||
},
|
||||
'snapshots_links': parameter_types.links,
|
||||
# TODO(zhufl): count is added in 3.45, we should move
|
||||
# it to the 3.45 schema file when microversion is
|
||||
# supported in volume interfaces
|
||||
# 'count': {'type': 'integer'}
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['snapshots'],
|
||||
}
|
||||
}
|
||||
|
||||
list_snapshots_with_detail = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'snapshots': {
|
||||
'type': 'array',
|
||||
'items': common_snapshot_detail_schema
|
||||
},
|
||||
'snapshots_links': parameter_types.links,
|
||||
# TODO(zhufl): count is added in 3.45, we should move
|
||||
# it to the 3.45 schema file when microversion is
|
||||
# supported in volume interfaces
|
||||
# 'count': {'type': 'integer'},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['snapshots'],
|
||||
}
|
||||
}
|
||||
|
||||
show_snapshot = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'snapshot': common_snapshot_detail_schema
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['snapshot'],
|
||||
}
|
||||
}
|
||||
|
||||
create_snapshot = {
|
||||
'status_code': [202],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'snapshot': common_snapshot_schema
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['snapshot'],
|
||||
}
|
||||
}
|
||||
|
||||
update_snapshot = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'snapshot': common_snapshot_schema
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['snapshot'],
|
||||
}
|
||||
}
|
||||
|
||||
delete_snapshot = {'status_code': [202]}
|
||||
reset_snapshot_status = {'status_code': [202]}
|
||||
update_snapshot_status = {'status_code': [202]}
|
||||
|
||||
create_snapshot_metadata = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'metadata': metadata
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['metadata'],
|
||||
}
|
||||
}
|
||||
|
||||
show_snapshot_metadata = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'metadata': metadata
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['metadata'],
|
||||
}
|
||||
}
|
||||
|
||||
update_snapshot_metadata = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'metadata': metadata
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['metadata'],
|
||||
}
|
||||
}
|
||||
|
||||
show_snapshot_metadata_item = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'meta': metadata
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['meta'],
|
||||
}
|
||||
}
|
||||
|
||||
update_snapshot_metadata_item = {
|
||||
'status_code': [200],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'meta': metadata
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['meta'],
|
||||
}
|
||||
}
|
||||
|
||||
delete_snapshot_metadata_item = {'status_code': [200]}
|
||||
force_delete_snapshot = {'status_code': [202]}
|
||||
unmanage_snapshot = {'status_code': [202]}
|
|
@ -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 snapshots as schema
|
||||
from tempest.lib.common import rest_client
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
|
||||
|
@ -32,14 +33,16 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
https://docs.openstack.org/api-ref/block-storage/v3/index.html#list-snapshots-and-details
|
||||
"""
|
||||
url = 'snapshots'
|
||||
list_schema = schema.list_snapshots_no_detail
|
||||
if detail:
|
||||
url += '/detail'
|
||||
list_schema = schema.list_snapshots_with_detail
|
||||
if params:
|
||||
url += '?%s' % urllib.urlencode(params)
|
||||
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(list_schema, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_snapshot(self, snapshot_id):
|
||||
|
@ -52,7 +55,7 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
url = "snapshots/%s" % snapshot_id
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.show_snapshot, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def create_snapshot(self, **kwargs):
|
||||
|
@ -65,7 +68,7 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
post_body = json.dumps({'snapshot': kwargs})
|
||||
resp, body = self.post('snapshots', post_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(202, resp.status)
|
||||
self.validate_response(schema.create_snapshot, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_snapshot(self, snapshot_id, **kwargs):
|
||||
|
@ -78,7 +81,7 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
put_body = json.dumps({'snapshot': kwargs})
|
||||
resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.update_snapshot, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def delete_snapshot(self, snapshot_id):
|
||||
|
@ -89,7 +92,7 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
https://docs.openstack.org/api-ref/block-storage/v3/index.html#delete-a-snapshot
|
||||
"""
|
||||
resp, body = self.delete("snapshots/%s" % snapshot_id)
|
||||
self.expected_success(202, resp.status)
|
||||
self.validate_response(schema.delete_snapshot, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def is_resource_deleted(self, id):
|
||||
|
@ -108,7 +111,7 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
"""Reset the specified snapshot's status."""
|
||||
post_body = json.dumps({'os-reset_status': {"status": status}})
|
||||
resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
self.validate_response(schema.reset_snapshot_status, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_snapshot_status(self, snapshot_id, **kwargs):
|
||||
|
@ -121,7 +124,7 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
post_body = json.dumps({'os-update_snapshot_status': kwargs})
|
||||
url = 'snapshots/%s/action' % snapshot_id
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
self.validate_response(schema.update_snapshot_status, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def create_snapshot_metadata(self, snapshot_id, metadata):
|
||||
|
@ -135,7 +138,7 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
url = "snapshots/%s/metadata" % snapshot_id
|
||||
resp, body = self.post(url, put_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.create_snapshot_metadata, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_snapshot_metadata(self, snapshot_id):
|
||||
|
@ -148,7 +151,7 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
url = "snapshots/%s/metadata" % snapshot_id
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.show_snapshot_metadata, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_snapshot_metadata(self, snapshot_id, **kwargs):
|
||||
|
@ -162,7 +165,7 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
url = "snapshots/%s/metadata" % snapshot_id
|
||||
resp, body = self.put(url, put_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.update_snapshot_metadata, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_snapshot_metadata_item(self, snapshot_id, id):
|
||||
|
@ -170,7 +173,7 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
url = "snapshots/%s/metadata/%s" % (snapshot_id, id)
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(schema.show_snapshot_metadata_item, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_snapshot_metadata_item(self, snapshot_id, id, **kwargs):
|
||||
|
@ -184,21 +187,23 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
url = "snapshots/%s/metadata/%s" % (snapshot_id, id)
|
||||
resp, body = self.put(url, put_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(
|
||||
schema.update_snapshot_metadata_item, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def delete_snapshot_metadata_item(self, snapshot_id, id):
|
||||
"""Delete metadata item for the snapshot."""
|
||||
url = "snapshots/%s/metadata/%s" % (snapshot_id, id)
|
||||
resp, body = self.delete(url)
|
||||
self.expected_success(200, resp.status)
|
||||
self.validate_response(
|
||||
schema.delete_snapshot_metadata_item, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def force_delete_snapshot(self, snapshot_id):
|
||||
"""Force Delete Snapshot."""
|
||||
post_body = json.dumps({'os-force_delete': {}})
|
||||
resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
self.validate_response(schema.force_delete_snapshot, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def unmanage_snapshot(self, snapshot_id):
|
||||
|
@ -206,5 +211,5 @@ class SnapshotsClient(rest_client.RestClient):
|
|||
post_body = json.dumps({'os-unmanage': {}})
|
||||
url = 'snapshots/%s/action' % (snapshot_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
self.validate_response(schema.unmanage_snapshot, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
|
|
@ -274,19 +274,22 @@ class TestSnapshotService(BaseCmdServiceTests):
|
|||
"name": "test"
|
||||
},
|
||||
"name": "test-volume-snapshot",
|
||||
"user_id": "40c2102f4a554b848d96b14f3eec39ed",
|
||||
"volume_id": "173f7b48-c4c1-4e70-9acc-086b39073506",
|
||||
"created_at": "2015-11-29T02:25:51.000000",
|
||||
"size": 1,
|
||||
"updated_at": "2015-11-20T05:36:40.000000",
|
||||
"os-extended-snapshot-attributes:progress": "100%",
|
||||
"id": "b1323cda-8e4b-41c1-afc5-2fc791809c8c",
|
||||
"description": "volume snapshot"
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"name": "saved-snapshot",
|
||||
"metadata": {},
|
||||
"id": "1ad4c789-7e8w-4dwg-afc5",
|
||||
"size": 1,
|
||||
"volume_id": "af7c41be-1ff6-4233-a690-7ed61c34347f",
|
||||
"created_at": "2015-11-20T05:39:40.000000",
|
||||
"updated_at": "2015-11-20T05:39:40.000000",
|
||||
"description": "snapshot in saved state"
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue