diff --git a/releasenotes/notes/add-update-backup-api-to-v3-backups-client-e8465b2b66617dc0.yaml b/releasenotes/notes/add-update-backup-api-to-v3-backups-client-e8465b2b66617dc0.yaml new file mode 100644 index 0000000000..7cd6887ef4 --- /dev/null +++ b/releasenotes/notes/add-update-backup-api-to-v3-backups-client-e8465b2b66617dc0.yaml @@ -0,0 +1,10 @@ +--- +features: + - | + Define v3 backups_client for the volume service as a library interface, + allowing other projects to use this module as a stable library without + maintenance changes. + Add update backup API to v3 backups_client library, min_microversion + of this API is 3.9. + + * backups_client(v3) diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py index 394c453673..ef69ba3de8 100644 --- a/tempest/api/volume/base.py +++ b/tempest/api/volume/base.py @@ -69,11 +69,14 @@ class BaseVolumeTest(api_version_utils.BaseMicroversionTest, if CONF.service_available.glance: cls.images_client = cls.os_primary.image_client_v2 - cls.snapshots_client = cls.os_primary.snapshots_v2_client - cls.volumes_client = cls.os_primary.volumes_v2_client if cls._api_version == 3: + cls.backups_client = cls.os_primary.backups_v3_client cls.volumes_client = cls.os_primary.volumes_v3_client - cls.backups_client = cls.os_primary.backups_v2_client + else: + cls.backups_client = cls.os_primary.backups_v2_client + cls.volumes_client = cls.os_primary.volumes_v2_client + + cls.snapshots_client = cls.os_primary.snapshots_v2_client cls.volumes_extension_client =\ cls.os_primary.volumes_v2_extension_client cls.availability_zone_client = ( diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py index 4b4aeec71b..1f91db67d3 100644 --- a/tempest/api/volume/test_volumes_backup.py +++ b/tempest/api/volume/test_volumes_backup.py @@ -140,3 +140,39 @@ class VolumesBackupsTest(base.BaseVolumeTest): restored_volume_id)['volume'] self.assertEqual('true', restored_volume_info['bootable']) + + +class VolumesBackupsV39Test(base.BaseVolumeTest): + + _api_version = 3 + min_microversion = '3.9' + max_microversion = 'latest' + + @classmethod + def skip_checks(cls): + super(VolumesBackupsV39Test, cls).skip_checks() + if not CONF.volume_feature_enabled.backup: + raise cls.skipException("Cinder backup feature disabled") + + @decorators.idempotent_id('9b374cbc-be5f-4d37-8848-7efb8a873dcc') + def test_update_backup(self): + # Create volume and backup + volume = self.create_volume() + backup = self.create_backup(volume_id=volume['id']) + + # Update backup and assert response body for update_backup method + update_kwargs = { + 'name': data_utils.rand_name(self.__class__.__name__ + '-Backup'), + 'description': data_utils.rand_name("volume-backup-description") + } + update_backup = self.backups_client.update_backup( + backup['id'], **update_kwargs)['backup'] + self.assertEqual(backup['id'], update_backup['id']) + self.assertEqual(update_kwargs['name'], update_backup['name']) + self.assertIn('links', update_backup) + + # Assert response body for show_backup method + retrieved_backup = self.backups_client.show_backup( + backup['id'])['backup'] + for key in update_kwargs: + self.assertEqual(update_kwargs[key], retrieved_backup[key]) diff --git a/tempest/clients.py b/tempest/clients.py index c3357bba16..467ef9cd5c 100644 --- a/tempest/clients.py +++ b/tempest/clients.py @@ -235,6 +235,7 @@ class Manager(clients.ServiceClients): self.volume_services_v2_client = self.volume_v2.ServicesClient() self.backups_client = self.volume_v1.BackupsClient() self.backups_v2_client = self.volume_v2.BackupsClient() + self.backups_v3_client = self.volume_v3.BackupsClient() self.encryption_types_client = self.volume_v1.EncryptionTypesClient() self.encryption_types_v2_client = \ self.volume_v2.EncryptionTypesClient() diff --git a/tempest/lib/services/volume/v2/backups_client.py b/tempest/lib/services/volume/v2/backups_client.py index 2b5e82d9b2..a44ed0b74d 100644 --- a/tempest/lib/services/volume/v2/backups_client.py +++ b/tempest/lib/services/volume/v2/backups_client.py @@ -17,9 +17,10 @@ from oslo_serialization import jsonutils as json from tempest.lib.common import rest_client from tempest.lib import exceptions as lib_exc +from tempest.lib.services.volume import base_client -class BackupsClient(rest_client.RestClient): +class BackupsClient(base_client.BaseClient): """Volume V2 Backups client""" api_version = "v2" diff --git a/tempest/lib/services/volume/v3/__init__.py b/tempest/lib/services/volume/v3/__init__.py index a351d61c88..ff58fc2e4b 100644 --- a/tempest/lib/services/volume/v3/__init__.py +++ b/tempest/lib/services/volume/v3/__init__.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations under # the License. +from tempest.lib.services.volume.v3.backups_client import BackupsClient from tempest.lib.services.volume.v3.base_client import BaseClient from tempest.lib.services.volume.v3.group_types_client import GroupTypesClient from tempest.lib.services.volume.v3.groups_client import GroupsClient @@ -19,5 +20,5 @@ from tempest.lib.services.volume.v3.messages_client import MessagesClient from tempest.lib.services.volume.v3.versions_client import VersionsClient from tempest.lib.services.volume.v3.volumes_client import VolumesClient -__all__ = ['BaseClient', 'GroupsClient', 'GroupTypesClient', +__all__ = ['BackupsClient', 'BaseClient', 'GroupsClient', 'GroupTypesClient', 'MessagesClient', 'VersionsClient', 'VolumesClient'] diff --git a/tempest/lib/services/volume/v3/backups_client.py b/tempest/lib/services/volume/v3/backups_client.py new file mode 100644 index 0000000000..e742e3901b --- /dev/null +++ b/tempest/lib/services/volume/v3/backups_client.py @@ -0,0 +1,37 @@ +# Copyright 2017 FiberHome Telecommunication Technologies CO.,LTD +# 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 tempest.lib.common import rest_client +from tempest.lib.services.volume.v2 import backups_client + + +class BackupsClient(backups_client.BackupsClient): + """Volume V3 Backups client""" + api_version = "v3" + + def update_backup(self, backup_id, **kwargs): + """Updates the specified volume backup. + + For a full list of available parameters, please refer to the official + API reference: + https://developer.openstack.org/api-ref/block-storage/v3/#update-a-backup + """ + put_body = json.dumps({'backup': kwargs}) + resp, body = self.put('backups/%s' % backup_id, put_body) + body = json.loads(body) + self.expected_success(200, resp.status) + return rest_client.ResponseBody(resp, body) diff --git a/tempest/tests/lib/services/volume/v3/test_backups_client.py b/tempest/tests/lib/services/volume/v3/test_backups_client.py new file mode 100644 index 0000000000..f1ce987972 --- /dev/null +++ b/tempest/tests/lib/services/volume/v3/test_backups_client.py @@ -0,0 +1,50 @@ +# Copyright 2017 FiberHome Telecommunication Technologies CO.,LTD +# 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 tempest.lib.services.volume.v3 import backups_client +from tempest.tests.lib import fake_auth_provider +from tempest.tests.lib.services import base + + +class TestBackupsClient(base.BaseServiceTest): + + FAKE_BACKUP_UPDATE = { + "backup": { + "id": "4c65c15f-a5c5-464b-b92a-90e4c04636a7", + "name": "fake-backup-name", + "links": "fake-links" + } + } + + def setUp(self): + super(TestBackupsClient, self).setUp() + fake_auth = fake_auth_provider.FakeAuthProvider() + self.client = backups_client.BackupsClient(fake_auth, + 'volume', + 'regionOne') + + def _test_update_backup(self, bytes_body=False): + self.check_service_client_function( + self.client.update_backup, + 'tempest.lib.common.rest_client.RestClient.put', + self.FAKE_BACKUP_UPDATE, + bytes_body, + backup_id='4c65c15f-a5c5-464b-b92a-90e4c04636a7') + + def test_update_backup_with_str_body(self): + self._test_update_backup() + + def test_update_backup_with_bytes_body(self): + self._test_update_backup(bytes_body=True)