From 4f234eb0aa7ab63bc42e19f78b60ffd42777e066 Mon Sep 17 00:00:00 2001 From: lolwww Date: Tue, 25 Jun 2019 14:15:23 +0300 Subject: [PATCH 1/6] Add cinder-backup-swift tests --- .../cinder_backup_swift/__init__.py | 15 +++++ .../charm_tests/cinder_backup_swift/setup.py | 51 +++++++++++++++++ .../charm_tests/cinder_backup_swift/tests.py | 54 ++++++++++++++++++ zaza/openstack/utilities/openstack.py | 57 +++++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 zaza/openstack/charm_tests/cinder_backup_swift/__init__.py create mode 100644 zaza/openstack/charm_tests/cinder_backup_swift/setup.py create mode 100644 zaza/openstack/charm_tests/cinder_backup_swift/tests.py diff --git a/zaza/openstack/charm_tests/cinder_backup_swift/__init__.py b/zaza/openstack/charm_tests/cinder_backup_swift/__init__.py new file mode 100644 index 0000000..3d7e48c --- /dev/null +++ b/zaza/openstack/charm_tests/cinder_backup_swift/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2018 Canonical Ltd. +# +# 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. + +"""Collection of code for setting up and testing cinder-backup-swift.""" diff --git a/zaza/openstack/charm_tests/cinder_backup_swift/setup.py b/zaza/openstack/charm_tests/cinder_backup_swift/setup.py new file mode 100644 index 0000000..d71b39d --- /dev/null +++ b/zaza/openstack/charm_tests/cinder_backup_swift/setup.py @@ -0,0 +1,51 @@ +# Copyright 2018 Canonical Ltd. +# +# 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. + +"""Code for configuring cinder-backup-swift.""" + +import zaza.model as zaza_model +import time + + +def basic_setup(): + """Run setup for testing cinder-backup-swift. + + Cinder backup setup for testing cinder-backup is currently part of + cinder-backup functional tests. + Volume backup setup for other tests to use should go here. + """ + + +def configure_cinder_backup(): + """Configure cinder-backup-swift.""" + keystone_ip = zaza_model.get_app_ips( + 'swift-keystone')[0] + swift_ip = zaza_model.get_app_ips( + 'swift-proxy')[0] + auth_ver = (zaza_model.get_application_config('swift-keystone') + .get('preferred-api-version').get('value')) + if auth_ver == 2: + auth_url = 'http://{}:5000/v2.0'.format(keystone_ip) + endpoint_url = 'http://{}:8080/v1/AUTH_'.format(swift_ip) + else: + auth_url = 'http://{}:5000/v3'.format(keystone_ip) + endpoint_url = 'http://{}:8080/v1/AUTH'.format(swift_ip) + cinder_backup_swift_conf = { + 'endpoint-url': endpoint_url, + 'auth-url': auth_url + } + juju_service = 'cinder-backup-swift' + zaza_model.set_application_config(juju_service, cinder_backup_swift_conf) + zaza_model.wait_for_application_states() + time.sleep(300) diff --git a/zaza/openstack/charm_tests/cinder_backup_swift/tests.py b/zaza/openstack/charm_tests/cinder_backup_swift/tests.py new file mode 100644 index 0000000..2fb1f36 --- /dev/null +++ b/zaza/openstack/charm_tests/cinder_backup_swift/tests.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +# Copyright 2018 Canonical Ltd. +# +# 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. + +"""Encapsulate cinder-backup testing.""" + +import logging + +import zaza.openstack.utilities.openstack as openstack_utils +import zaza.openstack.charm_tests.test_utils as test_utils + + +class CinderBackupSwiftTest(test_utils.OpenStackBaseTest): + """Encapsulate cinder-backup tests.""" + + @classmethod + def setUpClass(cls): + """Run class setup for running cinder tests.""" + super(CinderBackupSwiftTest, cls).setUpClass() + cls.cinder_client = openstack_utils.get_cinder_session_client( + cls.keystone_session) + + def test_cinder_volume_backup_create_delete(self): + """Create an volume backup and then delete it.""" + # Create volume + logging.info('Creating volume') + size = 1 + volume = openstack_utils.create_volume( + self.cinder_client, + size) + # Create volume backup + logging.info('Creating volume backup') + volume_backup = openstack_utils.create_volume_backup( + self.cinder_client, + volume.id) + # Delete volume backup + logging.info('Deleting volume backup') + openstack_utils.delete_resource( + self.cinder_client, + volume_backup.id) + logging.info('Deleting volume') + openstack_utils.delete_resource(self.cinder_client, volume.id) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index bc2b441..f128b05 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -1769,6 +1769,63 @@ def create_image(glance, image_url, image_name, image_cache_dir=None, tags=[]): return image +def create_volume(cinder, size, name=None, image=None): + """Create cinder volume. + :param cinder: Authenticated cinderclient + :type cinder: cinder.Client + :param size: Size of the volume + :type size: int + :param name: display name for new volume + :type name: Option[str, None] + :param image: Image to download to volume. + :type image: Option[str, None] + :returns: cinder volume pointer + :rtype: cinderclient.common.utils.RequestIdProxy + """ + logging.debug('Creating volume') + if not size: + raise Exception("Size for volume not specified") + # Create volume + volume = cinder.volumes.create( + size=size, + name=name, + imageRef=image) + + resource_reaches_status( + cinder.volumes, + volume.id, + expected_status='available', + msg='Volume status wait') + return volume + + +def create_volume_backup(cinder, volume_id, name=None): + """Create cinder volume backup. + :param cinder: Authenticated cinderclient + :type cinder: cinder.Client + :param volume_id: the source volume's id for backup + :type volume_id: str + :param name: display name for new volume backup + :type name: Option[str, None] + :returns: cinder volume backup pointer + :rtype: cinderclient.common.utils.RequestIdProxy + """ + logging.debug('Creating volume backup') + if not volume_id: + raise Exception("volume_id not specified") + # Create volume backup + volume_backup = cinder.backups.create( + volume_id, + name=name) + + resource_reaches_status( + cinder.backups, + volume_backup.id, + expected_status='available', + msg='Volume status wait') + return volume_backup + + def create_ssh_key(nova_client, keypair_name, replace=False): """Create ssh key. From 6180153bbe55af62f09f600267b2b9d3d267f6fd Mon Sep 17 00:00:00 2001 From: lolwww Date: Wed, 26 Jun 2019 01:03:58 +0300 Subject: [PATCH 2/6] Adding delete_volume methods to openstack utilities --- .../charm_tests/cinder_backup_swift/tests.py | 4 ++-- zaza/openstack/utilities/openstack.py | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/zaza/openstack/charm_tests/cinder_backup_swift/tests.py b/zaza/openstack/charm_tests/cinder_backup_swift/tests.py index 2fb1f36..8f4eae7 100644 --- a/zaza/openstack/charm_tests/cinder_backup_swift/tests.py +++ b/zaza/openstack/charm_tests/cinder_backup_swift/tests.py @@ -47,8 +47,8 @@ class CinderBackupSwiftTest(test_utils.OpenStackBaseTest): volume.id) # Delete volume backup logging.info('Deleting volume backup') - openstack_utils.delete_resource( + openstack_utils.delete_volume_backup( self.cinder_client, volume_backup.id) logging.info('Deleting volume') - openstack_utils.delete_resource(self.cinder_client, volume.id) + openstack_utils.delete_volume(self.cinder_client, volume.id) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index f128b05..c6450d7 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -1690,6 +1690,28 @@ def delete_image(glance, img_id): delete_resource(glance.images, img_id, msg="glance image") +def delete_volume(cinder, vol_id): + """Delete the given volume from cinder. + :param cinder: Authenticated cinderclient + :type cinder: cinderclient.Client + :param vol_id: unique name or id for the openstack resource + :type vol_id: str + """ + resource_removed.retry.stop = tenacity.stop_after_attempt(5) + delete_resource(cinder.volumes, vol_id, msg="deleting cinder volume") + + +def delete_volume_backup(cinder, vol_backup_id): + """Delete the given volume from cinder. + :param cinder: Authenticated cinderclient + :type cinder: cinderclient.Client + :param vol_backup_id: unique name or id for the openstack resource + :type vol_backup_id: str + """ + resource_removed.retry.stop = tenacity.stop_after_attempt(5) + delete_resource(cinder.backups, vol_backup_id, + msg="deleting cinder volume backup") + def upload_image_to_glance(glance, local_path, image_name, disk_format='qcow2', visibility='public', container_format='bare'): """Upload the given image to glance and apply the given label. From 6dcc83af878a05bb63ed70af08c5953fbee32a31 Mon Sep 17 00:00:00 2001 From: lolwww Date: Wed, 26 Jun 2019 13:26:33 +0300 Subject: [PATCH 3/6] Fix retry for delete_volume method --- zaza/openstack/utilities/openstack.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index c6450d7..4e52b2a 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -1690,6 +1690,8 @@ def delete_image(glance, img_id): delete_resource(glance.images, img_id, msg="glance image") +@tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, max=60), + reraise=True, stop=tenacity.stop_after_attempt(5)) def delete_volume(cinder, vol_id): """Delete the given volume from cinder. :param cinder: Authenticated cinderclient @@ -1697,10 +1699,11 @@ def delete_volume(cinder, vol_id): :param vol_id: unique name or id for the openstack resource :type vol_id: str """ - resource_removed.retry.stop = tenacity.stop_after_attempt(5) delete_resource(cinder.volumes, vol_id, msg="deleting cinder volume") +@tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, max=60), + reraise=True, stop=tenacity.stop_after_attempt(5)) def delete_volume_backup(cinder, vol_backup_id): """Delete the given volume from cinder. :param cinder: Authenticated cinderclient @@ -1708,7 +1711,6 @@ def delete_volume_backup(cinder, vol_backup_id): :param vol_backup_id: unique name or id for the openstack resource :type vol_backup_id: str """ - resource_removed.retry.stop = tenacity.stop_after_attempt(5) delete_resource(cinder.backups, vol_backup_id, msg="deleting cinder volume backup") From 514d11336504e3cbd000ffbf6636023a28d6be97 Mon Sep 17 00:00:00 2001 From: lolwww Date: Thu, 27 Jun 2019 23:43:17 +0300 Subject: [PATCH 4/6] Add check for volume backup_driver, remove unneeded code --- .../charm_tests/cinder_backup_swift/setup.py | 18 +++++---------- .../charm_tests/cinder_backup_swift/tests.py | 10 ++++++++- zaza/openstack/utilities/openstack.py | 22 ++++++++++++------- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/zaza/openstack/charm_tests/cinder_backup_swift/setup.py b/zaza/openstack/charm_tests/cinder_backup_swift/setup.py index d71b39d..394d9c5 100644 --- a/zaza/openstack/charm_tests/cinder_backup_swift/setup.py +++ b/zaza/openstack/charm_tests/cinder_backup_swift/setup.py @@ -15,17 +15,7 @@ """Code for configuring cinder-backup-swift.""" import zaza.model as zaza_model -import time - - -def basic_setup(): - """Run setup for testing cinder-backup-swift. - - Cinder backup setup for testing cinder-backup is currently part of - cinder-backup functional tests. - Volume backup setup for other tests to use should go here. - """ - +import zaza.openstack.charm_tests.test_utils def configure_cinder_backup(): """Configure cinder-backup-swift.""" @@ -48,4 +38,8 @@ def configure_cinder_backup(): juju_service = 'cinder-backup-swift' zaza_model.set_application_config(juju_service, cinder_backup_swift_conf) zaza_model.wait_for_application_states() - time.sleep(300) + _singleton = zaza.openstack.charm_tests.test_utils.OpenStackBaseTest() + _singleton.setUpClass() + with _singleton.config_change(cinder_backup_swift_conf, cinder_backup_swift_conf): + # wait for configuration to be applied then return + pass diff --git a/zaza/openstack/charm_tests/cinder_backup_swift/tests.py b/zaza/openstack/charm_tests/cinder_backup_swift/tests.py index 8f4eae7..9cc058c 100644 --- a/zaza/openstack/charm_tests/cinder_backup_swift/tests.py +++ b/zaza/openstack/charm_tests/cinder_backup_swift/tests.py @@ -33,7 +33,7 @@ class CinderBackupSwiftTest(test_utils.OpenStackBaseTest): cls.keystone_session) def test_cinder_volume_backup_create_delete(self): - """Create an volume backup and then delete it.""" + """Create volume backup and then delete it.""" # Create volume logging.info('Creating volume') size = 1 @@ -45,6 +45,14 @@ class CinderBackupSwiftTest(test_utils.OpenStackBaseTest): volume_backup = openstack_utils.create_volume_backup( self.cinder_client, volume.id) + record = openstack_utils.get_volume_backup_metadata( + self.cinder_client, + volume_backup.id + ) + + #Check if backup was created via Swift + assert record['backup_service'] == 'cinder.backup.drivers.swift.SwiftBackupDriver' + # Delete volume backup logging.info('Deleting volume backup') openstack_utils.delete_volume_backup( diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 4e52b2a..33ef570 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -1690,8 +1690,6 @@ def delete_image(glance, img_id): delete_resource(glance.images, img_id, msg="glance image") -@tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, max=60), - reraise=True, stop=tenacity.stop_after_attempt(5)) def delete_volume(cinder, vol_id): """Delete the given volume from cinder. :param cinder: Authenticated cinderclient @@ -1702,8 +1700,6 @@ def delete_volume(cinder, vol_id): delete_resource(cinder.volumes, vol_id, msg="deleting cinder volume") -@tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, max=60), - reraise=True, stop=tenacity.stop_after_attempt(5)) def delete_volume_backup(cinder, vol_backup_id): """Delete the given volume from cinder. :param cinder: Authenticated cinderclient @@ -1807,8 +1803,6 @@ def create_volume(cinder, size, name=None, image=None): :rtype: cinderclient.common.utils.RequestIdProxy """ logging.debug('Creating volume') - if not size: - raise Exception("Size for volume not specified") # Create volume volume = cinder.volumes.create( size=size, @@ -1835,8 +1829,6 @@ def create_volume_backup(cinder, volume_id, name=None): :rtype: cinderclient.common.utils.RequestIdProxy """ logging.debug('Creating volume backup') - if not volume_id: - raise Exception("volume_id not specified") # Create volume backup volume_backup = cinder.backups.create( volume_id, @@ -1850,6 +1842,20 @@ def create_volume_backup(cinder, volume_id, name=None): return volume_backup +def get_volume_backup_metadata(cinder, backup_id): + """Get cinder volume backup record + :param cinder: Authenticated cinderclient + :type cinder: cinder.Client + :param backup_id: the source backup id + """ + logging.debug('Request volume backup record') + # Request volume backup record + volume_backup_record = cinder.backups.export_record( + backup_id) + + return volume_backup_record + + def create_ssh_key(nova_client, keypair_name, replace=False): """Create ssh key. From 6678a4e5bc4448d59d5890f7a791ab90c5505c8e Mon Sep 17 00:00:00 2001 From: lolwww Date: Fri, 28 Jun 2019 00:02:52 +0300 Subject: [PATCH 5/6] Fix indents for pep8 --- zaza/openstack/charm_tests/cinder_backup_swift/setup.py | 4 +++- zaza/openstack/charm_tests/cinder_backup_swift/tests.py | 7 ++++--- zaza/openstack/utilities/openstack.py | 8 +++++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/zaza/openstack/charm_tests/cinder_backup_swift/setup.py b/zaza/openstack/charm_tests/cinder_backup_swift/setup.py index 394d9c5..8451556 100644 --- a/zaza/openstack/charm_tests/cinder_backup_swift/setup.py +++ b/zaza/openstack/charm_tests/cinder_backup_swift/setup.py @@ -17,6 +17,7 @@ import zaza.model as zaza_model import zaza.openstack.charm_tests.test_utils + def configure_cinder_backup(): """Configure cinder-backup-swift.""" keystone_ip = zaza_model.get_app_ips( @@ -40,6 +41,7 @@ def configure_cinder_backup(): zaza_model.wait_for_application_states() _singleton = zaza.openstack.charm_tests.test_utils.OpenStackBaseTest() _singleton.setUpClass() - with _singleton.config_change(cinder_backup_swift_conf, cinder_backup_swift_conf): + with _singleton.config_change(cinder_backup_swift_conf, + cinder_backup_swift_conf): # wait for configuration to be applied then return pass diff --git a/zaza/openstack/charm_tests/cinder_backup_swift/tests.py b/zaza/openstack/charm_tests/cinder_backup_swift/tests.py index 9cc058c..45e4660 100644 --- a/zaza/openstack/charm_tests/cinder_backup_swift/tests.py +++ b/zaza/openstack/charm_tests/cinder_backup_swift/tests.py @@ -45,13 +45,14 @@ class CinderBackupSwiftTest(test_utils.OpenStackBaseTest): volume_backup = openstack_utils.create_volume_backup( self.cinder_client, volume.id) + + # Check if backup was created via Swift record = openstack_utils.get_volume_backup_metadata( self.cinder_client, volume_backup.id ) - - #Check if backup was created via Swift - assert record['backup_service'] == 'cinder.backup.drivers.swift.SwiftBackupDriver' + swift_driver = 'cinder.backup.drivers.swift.SwiftBackupDriver' + assert record['backup_service'] == swift_driver # Delete volume backup logging.info('Deleting volume backup') diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 33ef570..1339ce2 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -1692,6 +1692,7 @@ def delete_image(glance, img_id): def delete_volume(cinder, vol_id): """Delete the given volume from cinder. + :param cinder: Authenticated cinderclient :type cinder: cinderclient.Client :param vol_id: unique name or id for the openstack resource @@ -1702,6 +1703,7 @@ def delete_volume(cinder, vol_id): def delete_volume_backup(cinder, vol_backup_id): """Delete the given volume from cinder. + :param cinder: Authenticated cinderclient :type cinder: cinderclient.Client :param vol_backup_id: unique name or id for the openstack resource @@ -1710,6 +1712,7 @@ def delete_volume_backup(cinder, vol_backup_id): delete_resource(cinder.backups, vol_backup_id, msg="deleting cinder volume backup") + def upload_image_to_glance(glance, local_path, image_name, disk_format='qcow2', visibility='public', container_format='bare'): """Upload the given image to glance and apply the given label. @@ -1791,6 +1794,7 @@ def create_image(glance, image_url, image_name, image_cache_dir=None, tags=[]): def create_volume(cinder, size, name=None, image=None): """Create cinder volume. + :param cinder: Authenticated cinderclient :type cinder: cinder.Client :param size: Size of the volume @@ -1819,6 +1823,7 @@ def create_volume(cinder, size, name=None, image=None): def create_volume_backup(cinder, volume_id, name=None): """Create cinder volume backup. + :param cinder: Authenticated cinderclient :type cinder: cinder.Client :param volume_id: the source volume's id for backup @@ -1843,7 +1848,8 @@ def create_volume_backup(cinder, volume_id, name=None): def get_volume_backup_metadata(cinder, backup_id): - """Get cinder volume backup record + """Get cinder volume backup record. + :param cinder: Authenticated cinderclient :type cinder: cinder.Client :param backup_id: the source backup id From 824a943f426bb3629f06caf7f48c831313cba4f4 Mon Sep 17 00:00:00 2001 From: lolwww Date: Fri, 28 Jun 2019 21:40:23 +0300 Subject: [PATCH 6/6] Add wait for status in cinder-backup-swift test --- zaza/openstack/charm_tests/cinder_backup_swift/setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/zaza/openstack/charm_tests/cinder_backup_swift/setup.py b/zaza/openstack/charm_tests/cinder_backup_swift/setup.py index 8451556..d84ad2e 100644 --- a/zaza/openstack/charm_tests/cinder_backup_swift/setup.py +++ b/zaza/openstack/charm_tests/cinder_backup_swift/setup.py @@ -38,6 +38,7 @@ def configure_cinder_backup(): } juju_service = 'cinder-backup-swift' zaza_model.set_application_config(juju_service, cinder_backup_swift_conf) + zaza_model.wait_for_agent_status() zaza_model.wait_for_application_states() _singleton = zaza.openstack.charm_tests.test_utils.OpenStackBaseTest() _singleton.setUpClass()