From be1706cb76d6cc2f7d7b20bbf3d69e63f21e8cd1 Mon Sep 17 00:00:00 2001 From: Nobuto Murata Date: Fri, 21 May 2021 15:19:28 +0900 Subject: [PATCH 1/2] Functional testing for glance external S3 backend Set up Ceph-Radosgw in the same model as an external S3 backend for Glance: - create an S3 user in Radosgw - create an S3 bucket for Glance - inject those parameters into Glance charm configurations as an external S3 backend - upload an image to the S3 backend via Glance, and check the size of the image in the S3 bucket directly Co-authored-by: Connor Chamberlain --- zaza/openstack/charm_tests/glance/setup.py | 59 ++++++++++++++++++++++ zaza/openstack/charm_tests/glance/tests.py | 56 +++++++++++++++++++- 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/zaza/openstack/charm_tests/glance/setup.py b/zaza/openstack/charm_tests/glance/setup.py index 6686d70..32f7d4e 100644 --- a/zaza/openstack/charm_tests/glance/setup.py +++ b/zaza/openstack/charm_tests/glance/setup.py @@ -14,7 +14,11 @@ """Code for configuring glance.""" +import json import logging + +import boto3 +import zaza.model as model import zaza.openstack.utilities.openstack as openstack_utils import zaza.utilities.deployment_env as deployment_env @@ -161,3 +165,58 @@ def add_lts_image(glance_client=None, image_name=None, release=None, glance_client=glance_client, image_name=image_name, properties=properties) + + +def configure_external_s3_backend(): + """Set up Ceph-radosgw as an external S3 backend for Glance.""" + logging.info("Creating a test S3 user and credentials for Glance") + username, displayname = "zaza-glance-test", "Zaza Glance Test User" + cmd = "radosgw-admin user create --uid='{}' --display-name='{}'".format( + username, displayname + ) + results = model.run_on_leader("ceph-mon", cmd) + stdout = json.loads(results["stdout"]) + keys = stdout["keys"][0] + access_key, secret_key = keys["access_key"], keys["secret_key"] + + logging.info("Getting S3 endpoint URL of Radosgw from Keystone") + keystone_auth = openstack_utils.get_overcloud_auth() + keystone_client = openstack_utils.get_keystone_client(keystone_auth) + endpoint_url = keystone_client.session.get_endpoint( + service_type="s3", + interface="public", + region="RegionOne", + ) + + logging.info("Creating a test S3 bucketfor Glance") + bucket_name = "zaza-glance-s3-test" + s3_client = boto3.client( + "s3", + endpoint_url=endpoint_url, + aws_access_key_id=access_key, + aws_secret_access_key=secret_key, + ) + s3_client.create_bucket(Bucket=bucket_name) + + logging.info("Updating Glance configs with S3 endpoint infomation") + model.set_application_config( + "glance", + { + "s3-store-host": endpoint_url, + "s3-store-access-key": access_key, + "s3-store-secret-key": secret_key, + "s3-store-bucket": bucket_name, + }, + ) + model.wait_for_agent_status() + + logging.info("Waiting for units to reach target states") + model.wait_for_application_states( + states={ + "glance": { + "workload-status": "active", + "workload-status-message": "Unit is ready", + } + } + ) + model.block_until_all_units_idle() diff --git a/zaza/openstack/charm_tests/glance/tests.py b/zaza/openstack/charm_tests/glance/tests.py index 5d45338..799e69a 100644 --- a/zaza/openstack/charm_tests/glance/tests.py +++ b/zaza/openstack/charm_tests/glance/tests.py @@ -18,8 +18,10 @@ import logging -import zaza.openstack.utilities.openstack as openstack_utils +import boto3 +import zaza.model as model import zaza.openstack.charm_tests.test_utils as test_utils +import zaza.openstack.utilities.openstack as openstack_utils class GlanceTest(test_utils.OpenStackBaseTest): @@ -142,3 +144,55 @@ class GlanceCephRGWBackendTest(test_utils.OpenStackBaseTest): 'image size {}'.format(image['size'], total_bytes)) self.assertEqual(image['size'], total_bytes) openstack_utils.delete_image(self.glance_client, image['id']) + + +class GlanceExternalS3Test(test_utils.OpenStackBaseTest): + """Encapsulate glance tests using an external S3 backend.""" + + @classmethod + def setUpClass(cls): + """Run class setup for running glance tests with S3 backend.""" + super(GlanceExternalS3Test, cls).setUpClass() + cls.glance_client = openstack_utils.get_glance_session_client( + cls.keystone_session + ) + + configs = model.get_application_config("glance") + cls.s3_store_host = configs["s3-store-host"]["value"] + cls.s3_store_access_key = configs["s3-store-access-key"]["value"] + cls.s3_store_secret_key = configs["s3-store-secret-key"]["value"] + cls.s3_store_bucket = configs["s3-store-bucket"]["value"] + + def test_100_create_delete_image(self): + """Create an image and do a simple validation of it. + + Validate the size of the image in both Glance API and actual S3 bucket. + """ + image_name = "zaza-s3-test-image" + openstack_utils.create_image( + glance=self.glance_client, + image_url=openstack_utils.find_cirros_image(arch="x86_64"), + image_name=image_name, + backend="s3", + ) + images = openstack_utils.get_images_by_name( + self.glance_client, image_name + ) + self.assertEqual(len(images), 1) + image = images[0] + + s3_client = boto3.client( + "s3", + endpoint_url=self.s3_store_host, + aws_access_key_id=self.s3_store_access_key, + aws_secret_access_key=self.s3_store_secret_key, + ) + response = s3_client.head_object( + Bucket=self.s3_store_bucket, Key=image["id"] + ) + logging.info( + "Checking glance image size {} matches S3 object's ContentLength " + "{}".format(image["size"], response["ContentLength"]) + ) + self.assertEqual(image["size"], response["ContentLength"]) + openstack_utils.delete_image(self.glance_client, image["id"]) From 2e7d52b9cda5ca4a2ca07f45ddf6f9ad4396c0b5 Mon Sep 17 00:00:00 2001 From: Nobuto Murata Date: Fri, 28 May 2021 22:12:51 +0900 Subject: [PATCH 2/2] fix typo --- zaza/openstack/charm_tests/glance/setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zaza/openstack/charm_tests/glance/setup.py b/zaza/openstack/charm_tests/glance/setup.py index 32f7d4e..367c980 100644 --- a/zaza/openstack/charm_tests/glance/setup.py +++ b/zaza/openstack/charm_tests/glance/setup.py @@ -188,7 +188,7 @@ def configure_external_s3_backend(): region="RegionOne", ) - logging.info("Creating a test S3 bucketfor Glance") + logging.info("Creating a test S3 bucket for Glance") bucket_name = "zaza-glance-s3-test" s3_client = boto3.client( "s3", @@ -198,7 +198,7 @@ def configure_external_s3_backend(): ) s3_client.create_bucket(Bucket=bucket_name) - logging.info("Updating Glance configs with S3 endpoint infomation") + logging.info("Updating Glance configs with S3 endpoint information") model.set_application_config( "glance", {