From dae4b6df5f354355cf56eee2547314b2282670f4 Mon Sep 17 00:00:00 2001 From: ghanshyam Date: Fri, 12 Jan 2018 07:49:15 +0000 Subject: [PATCH] Cinder Tempest plugin tests: Switch to stable interface All the cinder tempest plugin tests are inherited from tempest/api/volume/base.py which is not stable class and can be changed anytime by tempest. One recent case where some changes in base class on tempest side could have break the cinder tests- http://logs.openstack.org/07/522707/3/check/legacy-tempest-dsvm-full-devstack-plugin-ceph/a92cd60/logs/testr_results.html.gz This commit switch cinder tests to use test.py which is stable interface for plugin and create a base class with commonly used function & variable. Change-Id: I0edda1fa23aed0b3d25691d5f4440a7234decc9a Closes-Bug: #1734821 --- cinder/tests/tempest/api/volume/base.py | 170 ++++++++++++++++++ .../api/volume/test_consistencygroups.py | 24 +-- .../tempest/api/volume/test_volume_backup.py | 7 +- .../tempest/api/volume/test_volume_revert.py | 4 +- .../tempest/api/volume/test_volume_unicode.py | 15 +- 5 files changed, 199 insertions(+), 21 deletions(-) create mode 100644 cinder/tests/tempest/api/volume/base.py diff --git a/cinder/tests/tempest/api/volume/base.py b/cinder/tests/tempest/api/volume/base.py new file mode 100644 index 0000000..b3765e0 --- /dev/null +++ b/cinder/tests/tempest/api/volume/base.py @@ -0,0 +1,170 @@ +# Copyright 2017 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 tempest.api.volume import api_microversion_fixture +from tempest.common import compute +from tempest.common import waiters +from tempest import config +from tempest.lib.common import api_version_utils +from tempest.lib.common.utils import data_utils +from tempest.lib.common.utils import test_utils +from tempest.lib import exceptions +from tempest import test + +CONF = config.CONF + + +class BaseVolumeTest(api_version_utils.BaseMicroversionTest, + test.BaseTestCase): + """Base test case class for all Cinder API tests.""" + + _api_version = 2 + credentials = ['primary'] + + @classmethod + def skip_checks(cls): + super(BaseVolumeTest, cls).skip_checks() + + if not CONF.service_available.cinder: + skip_msg = ("%s skipped as Cinder is not available" % cls.__name__) + raise cls.skipException(skip_msg) + if cls._api_version == 2: + if not CONF.volume_feature_enabled.api_v2: + msg = "Volume API v2 is disabled" + raise cls.skipException(msg) + elif cls._api_version == 3: + if not CONF.volume_feature_enabled.api_v3: + msg = "Volume API v3 is disabled" + raise cls.skipException(msg) + else: + msg = ("Invalid Cinder API version (%s)" % cls._api_version) + raise exceptions.InvalidConfiguration(msg) + + api_version_utils.check_skip_with_microversion( + cls.min_microversion, cls.max_microversion, + CONF.volume.min_microversion, CONF.volume.max_microversion) + + @classmethod + def setup_clients(cls): + super(BaseVolumeTest, cls).setup_clients() + if cls._api_version == 3: + cls.backups_client = cls.os_primary.backups_v3_client + cls.volumes_client = cls.os_primary.volumes_v3_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 + + @classmethod + def setup_credentials(cls): + cls.set_network_resources() + super(BaseVolumeTest, cls).setup_credentials() + + def setUp(self): + super(BaseVolumeTest, self).setUp() + self.useFixture(api_microversion_fixture.APIMicroversionFixture( + self.request_microversion)) + + @classmethod + def resource_setup(cls): + super(BaseVolumeTest, cls).resource_setup() + cls.request_microversion = ( + api_version_utils.select_request_microversion( + cls.min_microversion, + CONF.volume.min_microversion)) + + @classmethod + def create_volume(cls, wait_until='available', **kwargs): + """Wrapper utility that returns a test volume. + + :param wait_until: wait till volume status. + """ + if 'size' not in kwargs: + kwargs['size'] = CONF.volume.volume_size + + if 'imageRef' in kwargs: + image = cls.os_primary.image_client_v2.show_image( + kwargs['imageRef']) + min_disk = image['min_disk'] + kwargs['size'] = max(kwargs['size'], min_disk) + + if 'name' not in kwargs: + name = data_utils.rand_name(cls.__name__ + '-Volume') + kwargs['name'] = name + + volume = cls.volumes_client.create_volume(**kwargs)['volume'] + cls.addClassResourceCleanup( + cls.volumes_client.wait_for_resource_deletion, volume['id']) + cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc, + cls.volumes_client.delete_volume, + volume['id']) + waiters.wait_for_volume_resource_status(cls.volumes_client, + volume['id'], wait_until) + return volume + + @classmethod + def create_snapshot(cls, volume_id=1, **kwargs): + """Wrapper utility that returns a test snapshot.""" + if 'name' not in kwargs: + name = data_utils.rand_name(cls.__name__ + '-Snapshot') + kwargs['name'] = name + + snapshot = cls.snapshots_client.create_snapshot( + volume_id=volume_id, **kwargs)['snapshot'] + cls.addClassResourceCleanup( + cls.snapshots_client.wait_for_resource_deletion, snapshot['id']) + cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc, + cls.snapshots_client.delete_snapshot, + snapshot['id']) + waiters.wait_for_volume_resource_status(cls.snapshots_client, + snapshot['id'], 'available') + return snapshot + + def create_backup(self, volume_id, backup_client=None, **kwargs): + """Wrapper utility that returns a test backup.""" + if backup_client is None: + backup_client = self.backups_client + if 'name' not in kwargs: + name = data_utils.rand_name(self.__class__.__name__ + '-Backup') + kwargs['name'] = name + + backup = backup_client.create_backup( + volume_id=volume_id, **kwargs)['backup'] + self.addCleanup(backup_client.delete_backup, backup['id']) + waiters.wait_for_volume_resource_status(backup_client, backup['id'], + 'available') + return backup + + def create_server(self, wait_until='ACTIVE', **kwargs): + name = kwargs.pop( + 'name', + data_utils.rand_name(self.__class__.__name__ + '-instance')) + + tenant_network = self.get_tenant_network() + body, _ = compute.create_test_server( + self.os_primary, + tenant_network=tenant_network, + name=name, + wait_until=wait_until, + **kwargs) + + self.addCleanup(test_utils.call_and_ignore_notfound_exc, + waiters.wait_for_server_termination, + self.os_primary.servers_client, body['id']) + self.addCleanup(test_utils.call_and_ignore_notfound_exc, + self.os_primary.servers_client.delete_server, + body['id']) + return body diff --git a/cinder/tests/tempest/api/volume/test_consistencygroups.py b/cinder/tests/tempest/api/volume/test_consistencygroups.py index 529d96e..18ba654 100644 --- a/cinder/tests/tempest/api/volume/test_consistencygroups.py +++ b/cinder/tests/tempest/api/volume/test_consistencygroups.py @@ -14,23 +14,23 @@ # License for the specific language governing permissions and limitations # under the License. -from tempest.api.volume import base from tempest.common import waiters from tempest import config from tempest.lib.common.utils import data_utils from tempest.lib import decorators +from cinder.tests.tempest.api.volume import base from cinder.tests.tempest import cinder_clients CONF = config.CONF -class ConsistencyGroupsV2Test(base.BaseVolumeAdminTest): - +class ConsistencyGroupsV2Test(base.BaseVolumeTest): @classmethod def setup_clients(cls): cls._api_version = 2 super(ConsistencyGroupsV2Test, cls).setup_clients() + cls.admin_volume_client = cls.os_admin.volumes_v2_client manager = cinder_clients.Manager(cls.os_admin) cls.consistencygroups_adm_client = manager.consistencygroups_adm_client @@ -54,14 +54,14 @@ class ConsistencyGroupsV2Test(base.BaseVolumeAdminTest): def _delete_cgsnapshot(self, cgsnapshot_id, cg_id): self.consistencygroups_adm_client.delete_cgsnapshot(cgsnapshot_id) vols = self.admin_volume_client.list_volumes(detail=True)['volumes'] - snapshots = self.admin_snapshots_client.list_snapshots( + snapshots = self.os_admin.snapshots_v2_client.list_snapshots( detail=True)['snapshots'] for vol in vols: for snap in snapshots: if (vol['consistencygroup_id'] == cg_id and vol['id'] == snap['volume_id']): - self.snapshots_client.wait_for_resource_deletion( - snap['id']) + (self.snapshots_client. + wait_for_resource_deletion(snap['id'])) self.consistencygroups_adm_client.wait_for_cgsnapshot_deletion( cgsnapshot_id) @@ -69,7 +69,7 @@ class ConsistencyGroupsV2Test(base.BaseVolumeAdminTest): def test_consistencygroup_create_delete(self): # Create volume type name = data_utils.rand_name("volume-type") - volume_type = self.admin_volume_types_client.create_volume_type( + volume_type = self.os_admin.volume_types_v2_client.create_volume_type( name=name)['volume_type'] # Create CG @@ -106,7 +106,8 @@ class ConsistencyGroupsV2Test(base.BaseVolumeAdminTest): # Clean up self._delete_consistencygroup(cg['id']) - self.admin_volume_types_client.delete_volume_type(volume_type['id']) + self.os_admin.volume_types_v2_client.delete_volume_type( + volume_type['id']) @decorators.idempotent_id('2134dd52-f333-4456-bb05-6cb0f009a44f') def test_consistencygroup_cgsnapshot_create_delete(self): @@ -141,12 +142,13 @@ class ConsistencyGroupsV2Test(base.BaseVolumeAdminTest): self.consistencygroups_adm_client.create_cgsnapshot) cgsnapshot = create_cgsnapshot(cg['id'], name=cgsnapshot_name)['cgsnapshot'] - snapshots = self.admin_snapshots_client.list_snapshots( + snapshots = self.os_admin.snapshots_v2_client.list_snapshots( detail=True)['snapshots'] for snap in snapshots: if volume['id'] == snap['volume_id']: waiters.wait_for_volume_resource_status( - self.admin_snapshots_client, snap['id'], 'available') + self.os_admin.snapshots_v2_client, + snap['id'], 'available') self.consistencygroups_adm_client.wait_for_cgsnapshot_status( cgsnapshot['id'], 'available') self.assertEqual(cgsnapshot_name, cgsnapshot['name']) @@ -205,7 +207,7 @@ class ConsistencyGroupsV2Test(base.BaseVolumeAdminTest): for snap in snapshots: if volume['id'] == snap['volume_id']: waiters.wait_for_volume_resource_status( - self.admin_snapshots_client, snap['id'], 'available') + self.os_admin.snapshots_v2_client, snap['id'], 'available') self.consistencygroups_adm_client.wait_for_cgsnapshot_status( cgsnapshot['id'], 'available') self.assertEqual(cgsnapshot_name, cgsnapshot['name']) diff --git a/cinder/tests/tempest/api/volume/test_volume_backup.py b/cinder/tests/tempest/api/volume/test_volume_backup.py index ec8efd8..765585e 100644 --- a/cinder/tests/tempest/api/volume/test_volume_backup.py +++ b/cinder/tests/tempest/api/volume/test_volume_backup.py @@ -13,16 +13,17 @@ # License for the specific language governing permissions and limitations # under the License. -from tempest.api.volume import base as volume_base from tempest.common import waiters from tempest import config from tempest.lib.common.utils import data_utils from tempest.lib import decorators +from cinder.tests.tempest.api.volume import base + CONF = config.CONF -class VolumesBackupsTest(volume_base.BaseVolumeTest): +class VolumesBackupsTest(base.BaseVolumeTest): @classmethod def skip_checks(cls): @@ -107,7 +108,7 @@ class VolumesBackupsTest(volume_base.BaseVolumeTest): wait_until='ACTIVE') # Delete VM - self.servers_client.delete_server(server['id']) + self.os_primary.servers_client.delete_server(server['id']) # Create incremental backup waiters.wait_for_volume_resource_status(self.volumes_client, volume['id'], 'available') diff --git a/cinder/tests/tempest/api/volume/test_volume_revert.py b/cinder/tests/tempest/api/volume/test_volume_revert.py index 1f4bead..d82ada6 100644 --- a/cinder/tests/tempest/api/volume/test_volume_revert.py +++ b/cinder/tests/tempest/api/volume/test_volume_revert.py @@ -13,17 +13,17 @@ # License for the specific language governing permissions and limitations # under the License. -from tempest.api.volume import base as volume_base from tempest.common import waiters from tempest import config from tempest.lib import decorators +from cinder.tests.tempest.api.volume import base from cinder.tests.tempest import cinder_clients CONF = config.CONF -class VolumeRevertTests(volume_base.BaseVolumeTest): +class VolumeRevertTests(base.BaseVolumeTest): min_microversion = '3.40' @classmethod diff --git a/cinder/tests/tempest/api/volume/test_volume_unicode.py b/cinder/tests/tempest/api/volume/test_volume_unicode.py index eab9f3c..db280d3 100644 --- a/cinder/tests/tempest/api/volume/test_volume_unicode.py +++ b/cinder/tests/tempest/api/volume/test_volume_unicode.py @@ -14,15 +14,17 @@ # License for the specific language governing permissions and limitations # under the License. -from tempest.api.volume import base as volume_base from tempest.common import waiters from tempest import config from tempest.lib.common.utils import data_utils +from tempest.lib.common.utils import test_utils + +from cinder.tests.tempest.api.volume import base CONF = config.CONF -class CinderUnicodeTest(volume_base.BaseVolumeTest): +class CinderUnicodeTest(base.BaseVolumeTest): @classmethod def resource_setup(cls): @@ -42,8 +44,11 @@ class CinderUnicodeTest(volume_base.BaseVolumeTest): kwargs['size'] = CONF.volume.volume_size volume = cls.volumes_client.create_volume(**kwargs)['volume'] - cls.volumes.append(volume) - + cls.addClassResourceCleanup( + cls.volumes_client.wait_for_resource_deletion, volume['id']) + cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc, + cls.volumes_client.delete_volume, + volume['id']) waiters.wait_for_volume_resource_status(cls.volumes_client, volume['id'], 'available') @@ -53,7 +58,7 @@ class CinderUnicodeTest(volume_base.BaseVolumeTest): def test_create_delete_unicode_volume_name(self): """Create a volume with a unicode name and view it.""" - result = self.volumes_client.show_volume(self.volumes[0]['id']) + result = self.volumes_client.show_volume(self.volume['id']) fetched_volume = result['volume'] self.assertEqual(fetched_volume['name'], self.volume_name)