diff --git a/tempest_lib/api_schema/response/compute/v2_1/snapshots.py b/tempest_lib/api_schema/response/compute/v2_1/snapshots.py new file mode 100644 index 0000000..01a524b --- /dev/null +++ b/tempest_lib/api_schema/response/compute/v2_1/snapshots.py @@ -0,0 +1,61 @@ +# Copyright 2015 Fujitsu(fnst) 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. + +common_snapshot_info = { + 'type': 'object', + 'properties': { + 'id': {'type': 'string'}, + 'volumeId': {'type': 'string'}, + 'status': {'type': 'string'}, + 'size': {'type': 'integer'}, + 'createdAt': {'type': 'string'}, + 'displayName': {'type': ['string', 'null']}, + 'displayDescription': {'type': ['string', 'null']} + }, + 'additionalProperties': False, + 'required': ['id', 'volumeId', 'status', 'size', + 'createdAt', 'displayName', 'displayDescription'] +} + +create_get_snapshot = { + 'status_code': [200], + 'response_body': { + 'type': 'object', + 'properties': { + 'snapshot': common_snapshot_info + }, + 'additionalProperties': False, + 'required': ['snapshot'] + } +} + +list_snapshots = { + 'status_code': [200], + 'response_body': { + 'type': 'object', + 'properties': { + 'snapshots': { + 'type': 'array', + 'items': common_snapshot_info + } + }, + 'additionalProperties': False, + 'required': ['snapshots'] + } +} + +delete_snapshot = { + 'status_code': [202] +} diff --git a/tempest_lib/services/compute/snapshots_client.py b/tempest_lib/services/compute/snapshots_client.py new file mode 100644 index 0000000..a73983b --- /dev/null +++ b/tempest_lib/services/compute/snapshots_client.py @@ -0,0 +1,71 @@ +# Copyright 2015 Fujitsu(fnst) 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. + +from oslo_serialization import jsonutils as json +from six.moves.urllib import parse as urllib + +from tempest_lib.api_schema.response.compute.v2_1 import snapshots as schema +from tempest_lib.common import rest_client +from tempest_lib import exceptions as lib_exc + + +class SnapshotsClient(rest_client.RestClient): + + def create_snapshot(self, volume_id, **kwargs): + post_body = { + 'volume_id': volume_id + } + post_body.update(kwargs) + post_body = json.dumps({'snapshot': post_body}) + resp, body = self.post('os-snapshots', post_body) + body = json.loads(body) + self.validate_response(schema.create_get_snapshot, resp, body) + return rest_client.ResponseBody(resp, body) + + def show_snapshot(self, snapshot_id): + url = "os-snapshots/%s" % snapshot_id + resp, body = self.get(url) + body = json.loads(body) + self.validate_response(schema.create_get_snapshot, resp, body) + return rest_client.ResponseBody(resp, body) + + def list_snapshots(self, detail=False, params=None): + url = 'os-snapshots' + + if detail: + url += '/detail' + if params: + url += '?%s' % urllib.urlencode(params) + resp, body = self.get(url) + body = json.loads(body) + self.validate_response(schema.list_snapshots, resp, body) + return rest_client.ResponseBody(resp, body) + + def delete_snapshot(self, snapshot_id): + resp, body = self.delete("os-snapshots/%s" % snapshot_id) + self.validate_response(schema.delete_snapshot, resp, body) + return rest_client.ResponseBody(resp, body) + + def is_resource_deleted(self, id): + try: + self.show_snapshot(id) + except lib_exc.NotFound: + return True + return False + + @property + def resource_type(self): + """Returns the primary type of resource this client works with.""" + return 'snapshot' diff --git a/tempest_lib/tests/services/compute/test_snapshots_client.py b/tempest_lib/tests/services/compute/test_snapshots_client.py new file mode 100644 index 0000000..008a7ea --- /dev/null +++ b/tempest_lib/tests/services/compute/test_snapshots_client.py @@ -0,0 +1,103 @@ +# Copyright 2015 NEC 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. + +from oslotest import mockpatch + +from tempest_lib import exceptions as lib_exc +from tempest_lib.services.compute import snapshots_client +from tempest_lib.tests import fake_auth_provider +from tempest_lib.tests.services.compute import base + + +class TestSnapshotsClient(base.BaseComputeServiceTest): + + FAKE_SNAPSHOT = { + "createdAt": "2015-10-02T16:27:54.724209", + "displayDescription": u"Another \u1234.", + "displayName": u"v\u1234-001", + "id": "100", + "size": 100, + "status": "available", + "volumeId": "12" + } + + FAKE_SNAPSHOTS = {"snapshots": [FAKE_SNAPSHOT]} + + def setUp(self): + super(TestSnapshotsClient, self).setUp() + fake_auth = fake_auth_provider.FakeAuthProvider() + self.client = snapshots_client.SnapshotsClient( + fake_auth, 'compute', 'regionOne') + + def _test_create_snapshot(self, bytes_body=False): + self.check_service_client_function( + self.client.create_snapshot, + 'tempest_lib.common.rest_client.RestClient.post', + {"snapshot": self.FAKE_SNAPSHOT}, + to_utf=bytes_body, status=200, + volume_id=self.FAKE_SNAPSHOT["volumeId"]) + + def test_create_snapshot_with_str_body(self): + self._test_create_snapshot() + + def test_create_shapshot_with_bytes_body(self): + self._test_create_snapshot(bytes_body=True) + + def _test_show_snapshot(self, bytes_body=False): + self.check_service_client_function( + self.client.show_snapshot, + 'tempest_lib.common.rest_client.RestClient.get', + {"snapshot": self.FAKE_SNAPSHOT}, + to_utf=bytes_body, snapshot_id=self.FAKE_SNAPSHOT["id"]) + + def test_show_snapshot_with_str_body(self): + self._test_show_snapshot() + + def test_show_snapshot_with_bytes_body(self): + self._test_show_snapshot(bytes_body=True) + + def _test_list_snapshots(self, bytes_body=False, **params): + self.check_service_client_function( + self.client.list_snapshots, + 'tempest_lib.common.rest_client.RestClient.get', + self.FAKE_SNAPSHOTS, to_utf=bytes_body, **params) + + def test_list_snapshots_with_str_body(self): + self._test_list_snapshots() + + def test_list_snapshots_with_byte_body(self): + self._test_list_snapshots(bytes_body=True) + + def test_list_snapshots_with_params(self): + self._test_list_snapshots('fake') + + def test_delete_snapshot(self): + self.check_service_client_function( + self.client.delete_snapshot, + 'tempest_lib.common.rest_client.RestClient.delete', + {}, status=202, snapshot_id=self.FAKE_SNAPSHOT['id']) + + def test_is_resource_deleted_true(self): + module = ('tempest_lib.services.compute.snapshots_client.' + 'SnapshotsClient.show_snapshot') + self.useFixture(mockpatch.Patch( + module, side_effect=lib_exc.NotFound)) + self.assertTrue(self.client.is_resource_deleted('fake-id')) + + def test_is_resource_deleted_false(self): + module = ('tempest_lib.services.compute.snapshots_client.' + 'SnapshotsClient.show_snapshot') + self.useFixture(mockpatch.Patch( + module, return_value={})) + self.assertFalse(self.client.is_resource_deleted('fake-id'))