From 362eabd829721ca2536e57b54e954f75b4cd03a5 Mon Sep 17 00:00:00 2001 From: jh629g Date: Fri, 13 Dec 2019 22:46:34 -0600 Subject: [PATCH] Refactor to remove resource leaks Resource leaks occur when resources error out when creating in openstack. This also includes a general refactor. Change-Id: I2c3c3fad0a484cf3b5edf172d00b8465ba7d70f7 --- ranger_tempest_plugin/config.py | 2 +- ranger_tempest_plugin/services/fms_client.py | 8 +- ranger_tempest_plugin/tests/api/cms_base.py | 18 +- ranger_tempest_plugin/tests/api/fms_base.py | 2 + .../tests/api/test_customers.py | 37 +- .../tests/api/test_flavors.py | 209 ++-- .../tests/api/test_images.py | 980 +++++++++--------- 7 files changed, 614 insertions(+), 642 deletions(-) mode change 100755 => 100644 ranger_tempest_plugin/tests/api/test_images.py diff --git a/ranger_tempest_plugin/config.py b/ranger_tempest_plugin/config.py index a673a91..ac248bc 100755 --- a/ranger_tempest_plugin/config.py +++ b/ranger_tempest_plugin/config.py @@ -60,7 +60,7 @@ ORM_GROUP_OPTIONS = [ cfg.StrOpt("alt_region_available", default=False, help="Alt region for ranger tempest testing"), - cfg.StrOpt("region_alt", + cfg.StrOpt("alt_region", default='', help="Provide alternate region for creating" "resources with multiple regions"), diff --git a/ranger_tempest_plugin/services/fms_client.py b/ranger_tempest_plugin/services/fms_client.py index 149105d..6b3087a 100755 --- a/ranger_tempest_plugin/services/fms_client.py +++ b/ranger_tempest_plugin/services/fms_client.py @@ -97,21 +97,21 @@ class FmsClient(base_client.RangerClientBase): flavor_id) return self.get_request(uri, schema.get_extra_specs) - def add_flvr_tenants(self, flavor_id, tenant_body): + def add_flavor_tenants(self, flavor_id, tenant_body): uri = '%s/%s/orm/flavors/%s/tenants/' % (self.fms_url, self.version, flavor_id) post_body = json.dumps(tenant_body) return self.post_request(uri, post_body, schema.add_tenant) - def add_flvr_regions(self, flavor_id, region_body): + def add_flavor_regions(self, flavor_id, region_body): uri = '%s/%s/orm/flavors/%s/regions' % (self.fms_url, self.version, flavor_id) post_body = json.dumps(region_body) return self.post_request(uri, post_body, schema.add_region) - def delete_flvr_region(self, flavor_id, region_id): + def delete_flavor_region(self, flavor_id, region_id): uri = '%s/%s/orm/flavors/%s/regions/%s' % (self.fms_url, self.version, flavor_id, region_id) @@ -142,7 +142,7 @@ class FmsClient(base_client.RangerClientBase): flavor_id, para) return self.delete_request(uri, schema.delete_extra_specs) - def delete_flvr_tenant(self, flavor_id, tenant): + def delete_flavor_tenant(self, flavor_id, tenant): uri = '%s/%s/orm/flavors/%s/tenants/%s' % (self.fms_url, self.version, flavor_id, tenant) diff --git a/ranger_tempest_plugin/tests/api/cms_base.py b/ranger_tempest_plugin/tests/api/cms_base.py index 0484864..faa2ffa 100755 --- a/ranger_tempest_plugin/tests/api/cms_base.py +++ b/ranger_tempest_plugin/tests/api/cms_base.py @@ -77,7 +77,7 @@ class CmsBaseOrmTest(base.BaseOrmTest): @classmethod def _get_customer_params(cls, quota=None, enabled=True, region_users=True, default_users=True): - region, user, metadata, payload = {}, {}, {}, {} + region, user, metadata, customer = {}, {}, {}, {} cust_name = data_utils.rand_name('ormTempestCms') if not quota: quota = cls._get_quota() @@ -90,14 +90,14 @@ class CmsBaseOrmTest(base.BaseOrmTest): regions = [region] metadata['my_server_name'] = cust_name metadata['ocx_cust'] = str(random.randint(0, 999999999)) - payload["description"] = cust_name - payload["enabled"] = True if enabled else False - payload["name"] = cust_name - payload['metadata'] = metadata - payload["regions"] = regions - payload["defaultQuotas"] = [quota] - payload['users'] = [user] if default_users else [] - return payload + customer["description"] = cust_name + customer["enabled"] = True if enabled else False + customer["name"] = cust_name + customer['metadata'] = metadata + customer["regions"] = regions + customer["defaultQuotas"] = [quota] + customer['users'] = [user] if default_users else [] + return customer @classmethod def _get_bare_customer_params(cls): diff --git a/ranger_tempest_plugin/tests/api/fms_base.py b/ranger_tempest_plugin/tests/api/fms_base.py index d3b0e89..2719613 100755 --- a/ranger_tempest_plugin/tests/api/fms_base.py +++ b/ranger_tempest_plugin/tests/api/fms_base.py @@ -15,6 +15,7 @@ import random import time +import uuid from oslo_log import log as logging from ranger_tempest_plugin.tests.api import base @@ -49,6 +50,7 @@ class FmsBaseOrmTest(base.BaseOrmTest): swap = random.randint(1, 40) * 1024 vcpus = random.randint(2, 40) disk = random.randint(2, 102) + post_body['id'] = uuid.uuid4().hex post_body["description"] = \ "orm-plugin-BaseORMTest-flavor" post_body["series"] = random.choice(CONF.ranger.flavor_series) diff --git a/ranger_tempest_plugin/tests/api/test_customers.py b/ranger_tempest_plugin/tests/api/test_customers.py index 57b9869..5eb359b 100755 --- a/ranger_tempest_plugin/tests/api/test_customers.py +++ b/ranger_tempest_plugin/tests/api/test_customers.py @@ -19,7 +19,6 @@ import uuid from ranger_tempest_plugin.data_utils import data_utils from ranger_tempest_plugin.tests.api import cms_base from tempest import config -from tempest import test from tempest.lib import decorators from tempest.lib import exceptions @@ -36,14 +35,15 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): cls._create_cust_validate_creation_on_dcp_and_lcp( **cls.setup_customer) + cls.addClassResourceCleanup( + cls._del_cust_validate_deletion_on_dcp_and_lcp, + cls.setup_customer_id) + cls.bare_customer = cls._get_bare_customer_params() cls.bare_customer_id = \ cls._create_cust_validate_creation_on_dcp_and_lcp( **cls.bare_customer) - cls.addClassResourceCleanup( - cls._del_cust_validate_deletion_on_dcp_and_lcp, - cls.setup_customer_id) cls.addClassResourceCleanup( cls._del_cust_validate_deletion_on_dcp_and_lcp, cls.bare_customer_id) @@ -58,15 +58,15 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): def _create_region(self, status='functional'): region_name = data_utils.rand_name() + self.addCleanup( + self.os_admin.rms_client.delete_region, + region_name) _, region = self.os_admin.rms_client.create_region( **{ 'region_id': region_name, 'status': status, } ) - test.addClassResourceCleanup( - self.os_admin.rms_client.delete_region, - region_name) return region def _create_customer(self, post_body): @@ -140,7 +140,7 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): post_body = self._get_customer_params(enabled=False) test_customer_id = self._create_cust_validate_creation_on_dcp_and_lcp( **post_body) - test.addClassResourceCleanup( + self.addCleanup( self._del_cust_validate_deletion_on_dcp_and_lcp, test_customer_id) @@ -160,9 +160,10 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): region_users=False) test_customer_id = self._create_cust_validate_creation_on_dcp_and_lcp( **post_body) - test.addClassResourceCleanup( + self.addCleanup( self._del_cust_validate_deletion_on_dcp_and_lcp, test_customer_id) + _, body = self.client.get_customer(test_customer_id) self.assertFalse(body['users']) self.assertFalse(body["regions"][0]['users']) @@ -186,7 +187,7 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): default_user_id = post_body["users"][0]["id"] test_customer_id = self._create_cust_validate_creation_on_dcp_and_lcp( **post_body) - test.addClassResourceCleanup( + self.addCleanup( self._del_cust_validate_deletion_on_dcp_and_lcp, test_customer_id) _, body = self.client.get_customer(test_customer_id) @@ -212,7 +213,7 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): default_user_id = post_body["users"][0]["id"] test_customer_id = self._create_cust_validate_creation_on_dcp_and_lcp( **post_body) - test.addClassResourceCleanup( + self.addCleanup( self._del_cust_validate_deletion_on_dcp_and_lcp, test_customer_id) _, body = self.client.get_customer(test_customer_id) @@ -242,7 +243,7 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): default_users=False) test_customer_id = self._create_cust_validate_creation_on_dcp_and_lcp( **post_body) - test.addClassResourceCleanup( + self.addCleanup( self._del_cust_validate_deletion_on_dcp_and_lcp, test_customer_id) _, body = self.client.get_customer(test_customer_id) @@ -268,7 +269,7 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): region_user_id = post_body["regions"][0]["users"][0]["id"] test_customer_id = self._create_cust_validate_creation_on_dcp_and_lcp( **post_body) - test.addResourceCleanup( + self.addCleanup( self._del_cust_validate_deletion_on_dcp_and_lcp, test_customer_id) _, body = self.client.get_customer(test_customer_id) @@ -288,7 +289,7 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): post_body = self._get_customer_params() test_customer_id = self._create_cust_validate_creation_on_dcp_and_lcp( **post_body) - test.addClassResourceCleanup( + self.addCleanup( self._del_cust_validate_deletion_on_dcp_and_lcp, test_customer_id) @@ -341,7 +342,7 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): region_name = post_body["regions"][0]["name"] test_customer_id = self._create_cust_validate_creation_on_dcp_and_lcp( **post_body) - test.addClassResourceCleanup( + self.addCleanup( self._del_cust_validate_deletion_on_dcp_and_lcp, test_customer_id) _, customer = self.client.get_customer(test_customer_id) @@ -358,7 +359,7 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): test_cust_name = post_body['name'] _, body = self.client.create_customer(**post_body) test_customer_id = body['customer']['id'] - test.addClassResourceCleanup( + self.addCleanup( self._del_cust_validate_deletion_on_dcp_and_lcp, test_customer_id) self._wait_for_status(test_customer_id, 'Success') @@ -414,7 +415,7 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): resp, body = self.client.create_customer(**cust_body) self.assertIn('id', body['customer']) test_customer_id = body['customer']['id'] - test.addClassResourceCleanup( + self.addCleanup( self._delete_customer, test_customer_id, region_name) @@ -434,7 +435,7 @@ class TestTempestCms(cms_base.CmsBaseOrmTest): resp, body = self.client.create_customer(**cust_body) self.assertIn('id', body['customer']) test_customer_id = body['customer']['id'] - test.addClassResourceCleanup( + self.addCleanup( self._delete_customer, test_customer_id, region_name) diff --git a/ranger_tempest_plugin/tests/api/test_flavors.py b/ranger_tempest_plugin/tests/api/test_flavors.py index 2bb2965..708c320 100755 --- a/ranger_tempest_plugin/tests/api/test_flavors.py +++ b/ranger_tempest_plugin/tests/api/test_flavors.py @@ -14,7 +14,6 @@ # under the License. import json -import uuid from ranger_tempest_plugin import data_utils as orm_data_utils from ranger_tempest_plugin.tests.api import fms_base @@ -84,21 +83,18 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): return group_id def _data_setup(self, post_body): - flavor = self._create_flv_and_validate_creation_on_dcp_and_lcp( - **post_body) self.addCleanup( self._del_flv_and_validate_deletion_on_dcp_and_lcp, - flavor["id"]) + post_body['id']) + flavor = self._create_flv_and_validate_creation_on_dcp_and_lcp( + **post_body) return flavor def _exec_tags_function(self, flavor_id, req_json, action, para): - if action == 'add': _, body = self.client.add_tags(flavor_id, req_json) - elif action == 'update': _, body = self.client.update_tags(flavor_id, req_json) - elif action == 'delete': _, body = self.client.delete_tags(flavor_id, para) @@ -107,10 +103,8 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): def _exec_ex_spec_function(self, flavor_id, es_body, action, para): if action == 'add': _, body = self.client.add_extra_specs(flavor_id, es_body) - elif action == 'update': _, body = self.client.update_extra_specs(flavor_id, es_body) - elif action == 'delete': _, body = self.client.delete_extra_specs(flavor_id, para) @@ -136,39 +130,37 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): def _assert_create_flavor(self, public=False): post_body = self._get_flavor_params(public=public) visibility = "private" if not public else "public" - # call client create_flavor and wait till status equals 'Success' - _, body = self.client.create_flavor(**post_body) - test_flvr_id = body["flavor"]['id'] - self._wait_for_flavor_status_on_dcp(test_flvr_id, 'Success') - # add flavor to tempest cleanup - self.addCleanup( - self._del_flv_and_validate_deletion_on_dcp_and_lcp, - test_flvr_id) + # call client create_flavor and wait till status equals 'Success' + body = self._data_setup(post_body) + test_flavor_id = body['id'] + self._wait_for_flavor_status_on_dcp(test_flavor_id, 'Success') # verify flavor record created successfully - flavor = self._get_flavor_details(test_flvr_id) + flavor = self._get_flavor_details(test_flavor_id) self.assertEqual(flavor["visibility"], visibility) self.assertEqual(flavor["regions"][0]["name"], CONF.identity.region) self.assertEqual(flavor["status"], "Success") def _create_region(self, status='functional'): region_name = data_utils.rand_name() + self.addCleanup( + self.os_admin.rms_client.delete_region, + region_name) _, region = self.os_admin.rms_client.create_region( **{ 'region_id': region_name, 'status': status, } ) - self.addCleanup( - self.os_admin.rms_client.delete_region, - region_name) return region - def _delete_flavor(self, flvr_id): + def _delete_flavor(self, flavor_id): # delete the data and do get_flavor to ensure 404-NotFound response - self._del_flv_and_validate_deletion_on_dcp_and_lcp(flvr_id) - self.assertRaises(exceptions.NotFound, self.client.get_flavor, flvr_id) + self._del_flv_and_validate_deletion_on_dcp_and_lcp(flavor_id) + self.assertRaises(exceptions.NotFound, + self.client.get_flavor, + flavor_id) @decorators.idempotent_id('2a4481cd-acce-4a5d-af7c-940222a6238b') def test_get_flavor(self): @@ -209,7 +201,7 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): alias_filter, contains_filter, startswith_filter, series_filter, tenant_filter]: _, body = self.client.list_flavors(list_filter) - flavor_ids = [flvr["id"] for flvr in body["flavors"]] + flavor_ids = [flavor["id"] for flavor in body["flavors"]] self.assertIn(self.flavor_id, flavor_ids) @decorators.idempotent_id('7b9d1f91-a8a4-458d-aaad-a98b5bf033b4') @@ -221,7 +213,7 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): self._assert_create_flavor(public=True) @decorators.idempotent_id('4cad10ce-67d2-4633-b347-2c16783a31b9') - def test_add_flvr_tags(self): + def test_add_flavor_tags(self): # test add_tags command with two sets of key:values add_tag_body = {"tags": {"aa": "bb", "cc": "dd"}} self._exec_tags_function(self.flavor_id, add_tag_body, 'add', None) @@ -233,20 +225,17 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): self.assertDictEqual(add_tag_body.get("tags"), subset) @decorators.idempotent_id('db8e5c0f-0041-45d4-9939-e079296123d8') - def test_replace_flvr_tags(self): + def test_replace_flavor_tags(self): # test replace_tags command replace_tag_body = {"tags": {"ee": "ff", "gg": "hh"}} self._exec_tags_function(self.flavor_id, replace_tag_body, 'update', None) - self.addCleanup( - self._restore_default_tags, - self.flavor_id) _, tag_body = self.client.get_tags(self.flavor_id) self.assertDictEqual(replace_tag_body.get("tags"), tag_body.get("tags")) @decorators.idempotent_id('e0a0eca6-e120-45ab-a1a4-f5b95fdf97f1') - def test_delete_flvr_tag(self): + def test_delete_flavor_tag(self): # test delete_tag command - delete a tag from tags body delete_tag_key = "a" self._exec_tags_function(self.flavor_id, None, 'delete', @@ -257,7 +246,7 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): self.assertIsNone(tag_present) @decorators.idempotent_id('9c511020-53ed-4139-8c53-451cb0ea8c75') - def test_delete_all_flvr_tags(self): + def test_delete_all_flavor_tags(self): # ensure there is at least a tag _, tag_body = self.client.get_tags(self.flavor_id) self.assertTrue(True if tag_body.get("tags") else False) @@ -265,40 +254,37 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): # test delete_all_tags command - run get_tag again and confirm # that the tag dict is now empty self._exec_tags_function(self.flavor_id, None, 'delete', None) - self.addCleanup( - self._restore_default_tags, - self.flavor_id) _, tag_body = self.client.get_tags(self.flavor_id) # assert that tag_body contains nothing self.assertFalse(tag_body["tags"]) @decorators.idempotent_id('ec74d68f-b42a-41a8-9685-ff5eca25ea0c') - def test_add_delete_flvr_region(self): + def test_add_delete_flavor_region(self): # setup data to add region post_body = self._get_flavor_params(set_region=False) flavor = self._data_setup(post_body) - test_flvr_id = flavor['id'] + test_flavor_id = flavor['id'] post_region_body = '{"regions": [{"name": "%s"}]}' % (self.region_id) post_region_body = json.loads(post_region_body) - _, body = self.client.add_flvr_regions(test_flvr_id, - post_region_body) - self._wait_for_flavor_status_on_dcp(test_flvr_id, 'Success') - _, body = self.client.get_flavor(test_flvr_id) + _, body = self.client.add_flavor_regions(test_flavor_id, + post_region_body) + self._wait_for_flavor_status_on_dcp(test_flavor_id, 'Success') + _, body = self.client.get_flavor(test_flavor_id) self.assertEqual(body["flavor"]["regions"][0]["name"], post_region_body["regions"][0]["name"]) # remove added region and then check to confirm flavor status - _, body = self.client.delete_flvr_region(test_flvr_id, - self.region_id) + _, body = self.client.delete_flavor_region(test_flavor_id, + self.region_id) # flavor status must show 'no regions' when it has no region assigned - self._wait_for_flavor_status_on_dcp(test_flvr_id, 'no regions') + self._wait_for_flavor_status_on_dcp(test_flavor_id, 'no regions') # flavor region is now empty after the lone region was removed - _, body = self.client.get_flavor(test_flvr_id) + _, body = self.client.get_flavor(test_flavor_id) self.assertTrue(len(body["flavor"]["regions"]) == 0) @decorators.idempotent_id('71404409-5d95-472c-8dac-b49a1c0c4b37') - def test_add_flvr_extra_specs(self): + def test_add_flavor_extra_specs(self): # get extra specs before the add _, es_body = self.client.get_extra_specs(self.flavor_id) es_expected = es_body.get("os_extra_specs") @@ -313,7 +299,7 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): self.assertDictEqual(es_expected, extra_specs.get("os_extra_specs")) @decorators.idempotent_id('043948fd-125b-4d96-bf40-42464066a7e1') - def test_update_flvr_extra_specs(self): + def test_update_flavor_extra_specs(self): # add custom extra spec using update_extra_spec replace_es_body = {"os_extra_specs": {"z": "zebra", "x": "xray"}} self._exec_ex_spec_function( @@ -321,19 +307,17 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): replace_es_body, 'update', None) - self.addCleanup( - self._restore_custom_es, - self.flavor_id) # assert extra specs update results match expected - _, flvr_ex_specs = self.client.get_extra_specs(self.flavor_id) + _, flavor_ex_specs = self.client.get_extra_specs(self.flavor_id) es_expected = replace_es_body.get("os_extra_specs") es_expected.update(self.dflt_ex_specs) - self.assertDictEqual(es_expected, flvr_ex_specs.get("os_extra_specs")) + self.assertDictEqual(es_expected, + flavor_ex_specs.get("os_extra_specs")) @decorators.idempotent_id('df83e2cd-d202-4b2f-8459-391a73067ec5') - def test_delete_flvr_extra_spec(self): + def test_delete_flavor_extra_spec(self): # get extra specs before the delete _, es_body = self.client.get_extra_specs(self.flavor_id) @@ -344,53 +328,51 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): # assert extra specs update results match expected es_body["os_extra_specs"].pop(delete_es_key_h) - _, flvr_ex_specs = self.client.get_extra_specs(self.flavor_id) + _, flavor_ex_specs = self.client.get_extra_specs(self.flavor_id) self.assertDictEqual(es_body["os_extra_specs"], - flvr_ex_specs.get("os_extra_specs")) + flavor_ex_specs.get("os_extra_specs")) @decorators.idempotent_id('e3fc7ce3-c8fe-4805-8ad3-7be2c94fe7ad') - def test_delete_all_flvr_extra_specs(self): + def test_delete_all_flavor_extra_specs(self): # run delete ALL extra specs - note that this will only # delete custom extra specs, NOT the default extra specs self._exec_ex_spec_function(self.flavor_id, None, 'delete', None) - self.addCleanup( - self._restore_custom_es, - self.flavor_id) - _, flvr_ex_specs = self.client.get_extra_specs(self.flavor_id) + _, flavor_ex_specs = self.client.get_extra_specs(self.flavor_id) # assert that flavor extra specs now contains only # the default extra specs self.assertDictEqual(self.dflt_ex_specs, - flvr_ex_specs.get("os_extra_specs")) + flavor_ex_specs.get("os_extra_specs")) @decorators.idempotent_id('187195b5-adfb-4c73-a2f5-42117021f5f2') - def test_add_delete_flvr_tenant(self): + def test_add_delete_flavor_tenant(self): # setup data for test case post_body = self._get_flavor_params() flavor = self._data_setup(post_body) - test_flvr_id = flavor['id'] + test_flavor_id = flavor['id'] - # check that flavor contains one tenant before testing add_flvr_tenant - flavor = self._get_flavor_details(test_flvr_id) + # check that flavor contains one tenant before testing adding tenant + flavor = self._get_flavor_details(test_flavor_id) self.assertEqual(len(flavor["tenants"]), 1) self.assertEqual(flavor["tenants"][0], self.tenant_id) - # test add_flvr_tenant by adding one more tenant + # test add_flavor_tenant by adding one more tenant post_tenant_body = '{"tenants": ["%s"]}' % (self.alt_tenant_id) post_tenant_body = json.loads(post_tenant_body) - _, body = self.client.add_flvr_tenants(test_flvr_id, post_tenant_body) - self._wait_for_flavor_status_on_dcp(test_flvr_id, 'Success') + _, body = self.client.add_flavor_tenants(test_flavor_id, + post_tenant_body) + self._wait_for_flavor_status_on_dcp(test_flavor_id, 'Success') # get flavor on same flavor id and confirm we have two tenants now - flavor = self._get_flavor_details(test_flvr_id) + flavor = self._get_flavor_details(test_flavor_id) self.assertEqual(len(flavor["tenants"]), 2) self.assertIn(self.alt_tenant_id, flavor["tenants"]) # delete one tenant, then wait until status = 'Success' - _, body = self.client.delete_flvr_tenant(test_flvr_id, - self.alt_tenant_id) - self._wait_for_flavor_status_on_dcp(test_flvr_id, 'Success') + _, body = self.client.delete_flavor_tenant(test_flavor_id, + self.alt_tenant_id) + self._wait_for_flavor_status_on_dcp(test_flavor_id, 'Success') # get flavor to confirm flavor["tenants"] now shows one tenant only - flavor = self._get_flavor_details(test_flvr_id) + flavor = self._get_flavor_details(test_flavor_id) self.assertEqual(len(flavor["tenants"]), 1) self.assertEqual(flavor["tenants"][0], self.tenant_id) @@ -398,16 +380,16 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): def test_delete_flavor(self): # setup data for test case post_body = self._get_flavor_params() - flavor = self._create_flv_and_validate_creation_on_dcp_and_lcp( - **post_body) - test_flvr_id = flavor['id'] - - # delete the data and do get_flavor to ensure 404-NotFound response self.addCleanup( self._del_flv_and_validate_deletion_on_dcp_and_lcp, - test_flvr_id) + post_body['id']) + flavor = self._create_flv_and_validate_creation_on_dcp_and_lcp( + **post_body) + test_flavor_id = flavor['id'] + + # delete the data and do get_flavor to ensure 404-NotFound response self.assertRaises(exceptions.NotFound, self.client.get_flavor, - test_flvr_id) + test_flavor_id) @decorators.idempotent_id('2a1240d8-ae30-4c37-b99f-af961a5e16cb') def test_create_flavor_with_swap_and_ephemeral(self): @@ -419,9 +401,9 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): post_body['ephemeral'] = ephemeral post_body['swap'] = swap flavor = self._data_setup(post_body) - test_flvr_id = flavor['id'] + test_flavor_id = flavor['id'] # verify flavor record created successfully - flavor_details = self._get_flavor_details(test_flvr_id) + flavor_details = self._get_flavor_details(test_flavor_id) self.assertEqual(flavor_details['status'], 'Success') self.assertEqual(flavor_details['swap'], swap) self.assertEqual(flavor_details['ephemeral'], ephemeral) @@ -458,35 +440,28 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): disk = '0' post_body['disk'] = disk flavor = self._data_setup(post_body) - test_flvr_id = flavor['id'] - flavor_details = self._get_flavor_details(test_flvr_id) + test_flavor_id = flavor['id'] + flavor_details = self._get_flavor_details(test_flavor_id) self.assertEqual(flavor_details["status"], "Success") self.assertEqual(flavor_details["disk"], disk) @decorators.idempotent_id('997ca03c-4176-4632-a0c9-7e943b03306c') def test_create_flavor_with_region_group(self): # create region group - _, body = self.rms_client.create_region_group( - **orm_data_utils.rand_region_group([CONF.identity.region]) - ) - group_id = body['group']['id'] - self.addCleanup( - self.rms_client.delete_region_group, - group_id) - + group_id = self._create_region_group() post_body = self._get_flavor_params() region_group = {'name': group_id, 'type': 'group'} post_body['regions'] = [region_group] flavor = self._data_setup(post_body) - test_flvr_id = flavor['id'] + test_flavor_id = flavor['id'] - flavor_details = self._get_flavor_details(test_flvr_id) + flavor_details = self._get_flavor_details(test_flavor_id) self.assertEqual(flavor_details['status'], 'Success') self.assertEqual(flavor['regions'][0]['name'], CONF.identity.region) @decorators.idempotent_id('ea2a618e-bd53-460b-bde5-01ea20b417c9') def test_create_flavor_with_two_regions(self): - region_alt = CONF.ranger.region_alt + region_alt = CONF.ranger.alt_region if not region_alt: raise exceptions.InvalidConfiguration( 'Provide region_alt in ranger block in configuration file') @@ -495,15 +470,15 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): {'name': region_alt} ) flavor = self._data_setup(post_body) - test_flvr_id = flavor['id'] - flavor_details = self._get_flavor_details(test_flvr_id) + test_flavor_id = flavor['id'] + flavor_details = self._get_flavor_details(test_flavor_id) self.assertEqual(flavor_details['status'], 'Success') self.assertEqual(flavor['regions'][0]['name'], CONF.identity.region) self.assertEqual(flavor['regions'][1]['name'], region_alt) @decorators.idempotent_id('06c81b29-85b6-4edf-ab89-3877c49e23bc') def test_create_flavor_with_single_and_group_region(self): - region_alt = CONF.ranger.region_alt + region_alt = CONF.ranger.alt_region if not region_alt: raise exceptions.InvalidConfiguration( 'Provide region_alt in ranger block in configuration file') @@ -520,8 +495,7 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): } ] flavor = self._data_setup(post_body) - test_flvr_id = flavor['id'] - flavor_details = self._get_flavor_details(test_flvr_id) + flavor_details = self._get_flavor_details(flavor['id']) self.assertEqual(flavor_details['status'], 'Success') self.assertEqual(flavor['regions'][0]['name'], CONF.identity.region) self.assertEqual(flavor['regions'][1]['name'], region_alt) @@ -529,12 +503,10 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): @decorators.idempotent_id('997ca03c-4176-4632-a0c9-7e943b03306d') def test_create_flavor_with_uuid(self): post_body = self._get_flavor_params() - uuid_ = uuid.uuid4().hex - post_body['id'] = uuid_ flavor = self._data_setup(post_body) - flavor_details = self._get_flavor_details(uuid_) + flavor_details = self._get_flavor_details(post_body['id']) self.assertEqual(flavor_details['status'], 'Success') - self.assertEqual(flavor['id'], uuid_) + self.assertEqual(flavor['id'], post_body['id']) @decorators.idempotent_id('37f1909f-3ba2-403c-ba0c-0a11b869d6a1') def test_flavor_while_region_down(self): @@ -545,7 +517,7 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): post_body = self._get_flavor_params() post_body['regions'][0]['name'] = region['name'] self.assertRaises(exceptions.BadRequest, - self.client.create_flavor, **post_body) + self._data_setup, post_body) @decorators.idempotent_id('1c6a24d3-345e-46d4-aaa0-127b7fc8a42d') def test_flavor_while_region_building(self): @@ -554,16 +526,16 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): post_body = self._get_flavor_params() post_body['regions'][0]['name'] = region['name'] - _, body = self.client.create_flavor(**post_body) - - self.assertIn('id', body['flavor']) - test_flvr_id = body['flavor']['id'] self.addCleanup( self._delete_flavor, - test_flvr_id) + post_body['id']) + body = self._data_setup(post_body) - flavor = self._get_flavor_details(test_flvr_id) - self.assertEqual(flavor['id'], test_flvr_id) + self.assertIn('id', body) + test_flavor_id = body['id'] + + flavor = self._get_flavor_details(test_flavor_id) + self.assertEqual(flavor['id'], test_flavor_id) self.assertEqual(flavor['status'], 'Error') @decorators.idempotent_id('e17dab64-c900-4a19-a7a2-96a0bf4af0f8') @@ -573,13 +545,10 @@ class TestTempestFms(fms_base.FmsBaseOrmTest): post_body = self._get_flavor_params() post_body['regions'][0]['name'] = region['name'] - _, body = self.client.create_flavor(**post_body) - self.assertIn('id', body['flavor']) - test_flvr_id = body['flavor']['id'] - self.addCleanup( - self._delete_flavor, - test_flvr_id) + body = self._data_setup(post_body) + self.assertIn('id', body) + test_flavor_id = body['id'] - flavor = self._get_flavor_details(test_flvr_id) - self.assertEqual(flavor['id'], test_flvr_id) + flavor = self._get_flavor_details(test_flavor_id) + self.assertEqual(flavor['id'], test_flavor_id) self.assertEqual(flavor['status'], 'Error') diff --git a/ranger_tempest_plugin/tests/api/test_images.py b/ranger_tempest_plugin/tests/api/test_images.py old mode 100755 new mode 100644 index a67010d..24350b9 --- a/ranger_tempest_plugin/tests/api/test_images.py +++ b/ranger_tempest_plugin/tests/api/test_images.py @@ -1,490 +1,490 @@ -# Copyright 2016 AT&T Corp -# 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. - -import uuid - -from ranger_tempest_plugin.data_utils import data_utils -from ranger_tempest_plugin.tests.api import ims_base -from tempest import config - -from tempest.lib import decorators -from tempest.lib import exceptions - -CONF = config.CONF - - -class TestTempestIms(ims_base.ImsBaseOrmTest): - - @classmethod - def setup_credentials(cls): - cls.set_network_resources() - super(TestTempestIms, cls).setup_credentials() - - @classmethod - def setup_clients(cls): - super(TestTempestIms, cls).setup_clients() - - @classmethod - def resource_setup(cls): - # setup public image for tempest testing - cls.image_params_public = \ - cls._get_image_params(set_private=False) - cls.image_params_private = \ - cls._get_image_params(set_enabled=False) - - cls.addClassResourceCleanup( - cls._del_img_validate_deletion_on_dcp_and_lcp, - cls.image_params_public['id']) - cls.addClassResourceCleanup( - cls._del_img_validate_deletion_on_dcp_and_lcp, - cls.image_params_private['id']) - - # setup public image for tempest testing - cls.public_image = \ - cls._create_img_and_validate_creation_on_dcp_and_lcp( - **cls.image_params_public) - - # setup private image for tempest testing - cls.private_image = \ - cls._create_img_and_validate_creation_on_dcp_and_lcp( - **cls.image_params_private) - - super(TestTempestIms, cls).resource_setup() - - def _data_setup(self, post_body): - self.addCleanup( - self._del_img_validate_deletion_on_dcp_and_lcp, - post_body["id"]) - image = self._create_img_and_validate_creation_on_dcp_and_lcp( - **post_body) - # only check for Success image status if "regions" is not empty - if image["regions"]: - self._wait_for_image_status_on_dcp(image["id"], 'Success') - - return image - - def _delete_image(self, id_): - """Try to delete from from dcp only""" - # delete the data and do get_image to ensure 404-NotFound response - self._del_img_validate_deletion_on_dcp_and_lcp(id_) - self.assertRaises(exceptions.NotFound, self.client.get_image, id_) - - def _create_region(self, status='functional'): - region_name = data_utils.rand_name() - self.addCleanup( - self.os_admin.rms_client.delete_region, - region_name) - - _, region = self.os_admin.rms_client.create_region( - **{ - 'region_id': region_name, - 'status': status, - } - ) - - return region - - @decorators.idempotent_id('2b1bb28b-4151-4e75-ae1b-d21089c3418c') - def test_get_image(self): - """Execute 'get_image' using the following options: - - - get image by id (using cust_id parameter) - - get image by name (using cust_name parameter) - """ - - # execute get_image using image ID and iamge_name - for identifier in [self.public_image['id'], self.public_image['name']]: - _, body = self.client.get_image(identifier) - self.assertIn(self.public_image['id'], body['image']['id']) - - @decorators.idempotent_id('6072c438-1e45-4c0b-97a6-e5127bd33d90') - def test_list_images_with_filters(self): - """This function executes 'list customer' with all available filters: - - - no filter (i.e. list all images) - - filter by region - - filter by customer - - filter by visibility (public/private) - """ - - # define the list customer filters to be used for this test - no_filter = None - customer_filter = "?customer=%s" % self.tenant_id - region_filter = "?region=%s" % self.region_id - public_filter = "?visibility=public" - private_filter = "?visibility=private" - - # list public images - _, body = self.client.list_images(public_filter) - image_ids = [img['id'] for img in body['images']] - self.assertIn(self.public_image['id'], image_ids) - - # list private images - _, body = self.client.list_images(private_filter) - image_ids = [img['id'] for img in body['images']] - self.assertIn(self.private_image['id'], image_ids) - - # execute list_customers with the rest of the filters - for list_filter in [no_filter, region_filter, - customer_filter]: - _, body = self.client.list_images(list_filter) - images = [image['id'] for image in body['images']] - self.assertIn(self.private_image['id'], images) - - @decorators.idempotent_id('4435fef4-49a9-435b-8463-cf8a1e0b7cd8') - def test_disable_image(self): - # disable self.public_image and check if request is successful - self.client.enabled_image(self.public_image['id'], False) - self._wait_for_image_status_on_dcp(self.public_image['id'], 'Success') - _, body = self.client.get_image(self.public_image['id']) - image = body["image"] - - # assert that the image["enabled"] value is 'False' - self.assertTrue(not image['enabled']) - - @decorators.idempotent_id('f32a13e3-6f38-423b-a616-09c8d4e1c277') - def test_enable_image(self): - # enable self.private_image and check if request is successful - self.client.enabled_image(self.private_image['id'], True) - self._wait_for_image_status_on_dcp(self.private_image['id'], 'Success') - _, body = self.client.get_image(self.private_image['id']) - image = body["image"] - - # assert that the image["enabled"] value is 'True' - self.assertTrue(image['enabled']) - - @decorators.idempotent_id('cb9e3022-00d7-4a21-bdb2-67d3cd15a4f8') - def test_add_delete_image_region(self): - # skip region assignment in data setup - post_body = self._get_image_params(set_region=False) - image = self._data_setup(post_body) - test_image_id = image['id'] - - # add region to image then check to confirm image status = "Success" - self.client.add_region_to_image(test_image_id, self.region_id) - # image status must show 'Success' when assigned to a region - self._wait_for_image_status_on_dcp(test_image_id, 'Success') - - # check that region is successfully added - _, body = self.client.get_image(test_image_id) - image = body["image"] - self.assertEqual(image["regions"][0]["name"], self.region_id) - - # delete the region then check to confirm image status = "no regions" - _, body = self.client.delete_region_from_image(test_image_id, - self.region_id) - self._wait_for_image_status_on_dcp(test_image_id, 'no regions') - - # image region array should be empty after the region was removed - _, body = self.client.get_image(test_image_id) - image = body["image"] - self.assertFalse(image["regions"]) - - @decorators.idempotent_id('0ee68189-66a8-4213-ad68-bc12991c174a') - def test_add_delete_image_tenant(self): - # add alt tenant to self.private_image & check if status = "Success" - self.client.add_customer_to_image(self.private_image['id'], - self.alt_tenant_id) - self._wait_for_image_status_on_dcp(self.private_image['id'], - 'Success') - - # check that alt tenant successfully added to image tenants array - _, body = self.client.get_image(self.private_image['id']) - image = body["image"] - self.assertEqual(len(image["customers"]), 2) - self.assertIn(self.alt_tenant_id, image['customers']) - - # now delete alt_tenant_id and ensure operation is successful - _, body = self.client.delete_customer_from_image( - self.private_image['id'], - self.alt_tenant_id) - self._wait_for_image_status_on_dcp(self.private_image['id'], 'Success') - - # image region array should no longer contain alt tenant - _, body = self.client.get_image(self.private_image['id']) - image = body["image"] - self.assertNotIn(self.alt_tenant_id, image['customers']) - - @decorators.idempotent_id('bac99348-6b13-4b30-958b-3c039b27eda3') - def test_update_image_tenant(self): - # replace current tenant in self.private_image with alt tenant - self.client.update_customer(self.private_image['id'], - self.alt_tenant_id) - self._wait_for_image_status_on_dcp(self.private_image['id'], 'Success') - - # check that image tenants array contains only alt tenant - _, body = self.client.get_image(self.private_image['id']) - image = body["image"] - self.assertEqual(len(image["customers"]), 1) - self.assertIn(self.alt_tenant_id, image['customers']) - - @decorators.idempotent_id('0331e02a-ab52-4341-b676-a02462244277') - def test_create_image(self): - post_body = self._get_image_params() - self.addCleanup( - self._del_img_validate_deletion_on_dcp_and_lcp, - post_body["id"]) - # call client create_IMAGE and wait till status equals 'Success' - _, body = self.client.create_image(**post_body) - image = body["image"] - test_image_id = image["id"] - self._wait_for_image_status_on_dcp(test_image_id, 'Success') - - # verify image record created successfully - _, body = self.client.get_image(test_image_id) - image = body["image"] - self.assertEqual(image["regions"][0]["name"], CONF.identity.region) - - @decorators.idempotent_id('01160918-e217-401d-a6a0-e7992ab76e41') - def test_update_image(self): - region = {} - post_body = self._get_image_params(set_region=False) - image = self._data_setup(post_body) - test_image_id = image['id'] - - # setup region and change 'enabled', 'customers' properties - region["name"] = self.region_id - region["type"] = "single" - region["checksum"] = "7297321c2fa6424417a548c85edd6e98" - region["virtual_size"] = "None" - region["size"] = "38797312" - post_body["regions"] = [region] - post_body["enabled"] = False - post_body["customers"] = [self.alt_tenant_id] - # empty tags list - post_body["tags"] = [] - - _, body = self.client.update_image(test_image_id, para=None, - **post_body) - self._wait_for_image_status_on_dcp(test_image_id, 'Success') - # verify image record updated successfully - _, body = self.client.get_image(test_image_id) - image = body["image"] - self.assertEqual(image["regions"][0]["name"], CONF.identity.region) - self.assertIn(self.alt_tenant_id, image['customers']) - self.assertFalse(image['enabled']) - self.assertFalse(image['tags']) - - @decorators.idempotent_id('23e2e7e2-5b19-4c66-b35c-7c686a986627') - def test_delete_image(self): - # setup data for test case - post_body = self._get_image_params() - image = self._create_img_and_validate_creation_on_dcp_and_lcp( - **post_body) - test_image_id = image['id'] - - # delete the data and do get_image to ensure 404-NotFound response - self._del_img_validate_deletion_on_dcp_and_lcp(test_image_id) - self.assertRaises(exceptions.NotFound, self.client.get_image, - test_image_id) - - @decorators.idempotent_id('e642fa39-1b69-4d17-8bd1-aee90ea042a3') - def test_image_while_region_down(self): - # create region with status down - region = self._create_region(status='down') - - # create image within that newly created region - post_body = self._get_image_params() - post_body['regions'][0]['name'] = region['name'] - - # TODO(JH629G): Determine if flavor resource deletion is necessary here - - self.assertRaises(exceptions.BadRequest, - self.client.create_image, **post_body) - - @decorators.idempotent_id('a1fee342-3000-41a6-97f9-b33fd2734e4d') - def test_image_while_region_building(self): - # create region with status building - region = self._create_region(status='building') - - # create image within that newly created region - post_body = self._get_image_params() - post_body['regions'][0]['name'] = region['name'] - _, body = self.client.create_image(**post_body) - self.assertIn('id', body['image']) - test_image_id = body['image']['id'] - - # add image to tempest cleanup - self.addCleanup( - self._del_img_validate_deletion_on_dcp_and_lcp, - test_image_id) - - _, body = self.client.get_image(test_image_id) - # since region is building it will give error - # Notification to ORD failed - _, body = self.client.get_image(test_image_id) - self.assertEqual(body['image']['id'], test_image_id) - self.assertEqual(body['image']['status'], 'error') - - @decorators.idempotent_id('b967ce58-5d24-4af2-8416-a336772c8087') - def test_image_while_region_maintenance(self): - # create region with status maintenance - region = self._create_region(status='maintenance') - - # create image within that newly created region - post_body = self._get_image_params() - post_body['regions'][0]['name'] = region['name'] - _, body = self.client.create_image(**post_body) - self.assertIn('id', body['image']) - test_image_id = body['image']['id'] - - # add image to tempest cleanup - self.addCleanup( - self._del_img_validate_deletion_on_dcp_and_lcp, - test_image_id) - _, body = self.client.get_image(test_image_id) - # since region is maintenance it will give error - # Notification to ORD failed - self.assertEqual(body['image']['id'], test_image_id) - self.assertEqual(body['image']['status'], 'Error') - - @decorators.idempotent_id('eae7ca20-5383-4579-9f73-0138b8b3ec85') - def test_list_public_images(self): - """List images with visibility = 'public'""" - # set_private = False to create image with visibility = 'public' - post_body = self._get_image_params(set_private=False) - image = self._data_setup(post_body) - test_image_id = image['id'] - # confirm image visibility is set to "public" after image is created - self.assertEqual(image["visibility"], "public") - filter_public_images = "?visibility=%s" % image["visibility"] - - # list all public images and check if test_image_id is in the list - _, body = self.client.list_images(filter_public_images) - image_ids = [img['id'] for img in body['images']] - self.assertIn(test_image_id, image_ids) - - @decorators.idempotent_id('dc321d60-f3bd-477c-b7bf-1594626f0a12') - def test_list_private_images(self): - """List images with visibility = 'private' """ - # image data created with visibility = private set by default - post_body = self._get_image_params() - image = self._data_setup(post_body) - test_image_id = image['id'] - # confirm image visibility is set to "private" after image is created - self.assertEqual(image["visibility"], "private") - filter_private_images = "?visibility=%s" % image["visibility"] - - # list all public images and check if test_image_id is in the list - _, body = self.client.list_images(filter_private_images) - image_ids = [img['id'] for img in body['images']] - self.assertIn(test_image_id, image_ids) - - @decorators.idempotent_id('59887b26-8e73-4781-87a4-3b505ece0021') - def test_create_image_protected_true(self): - post_body = self._get_image_params() - # set Protected True - post_body['protected'] = True - # call client create_IMAGE and wait till status equals 'Success' - _, body = self.client.create_image(**post_body) - image = body["image"] - test_image_id = image["id"] - self._wait_for_image_status_on_dcp(test_image_id, 'Success') - - # add image to temepst cleanup - self.addCleanup( - self._del_img_validate_deletion_on_dcp_and_lcp, - test_image_id) - # verify image record created successfully - _, body = self.client.get_image(test_image_id) - image = body["image"] - self.assertEqual(image["regions"][0]["name"], CONF.identity.region) - - @decorators.idempotent_id('56cd1de0-3908-41d5-af98-45ad95463817') - def test_create_image_with_tags_properties(self): - post_body = self._get_image_params() - # set tags and properties - tags = ["brocade", "vyatta", "vCEImage", "mediumImage"] - properties = { - "Application-Name": "Vyatta", - "Application-Type": "VCE", - "Application-Vendor": "Brocade", - "Application-Version": "3.5.R5.att-V6.0", - "hw_vif_model": "VirtualVmxnet3", - "OS": "Debian", - "OS-Version": "7", - "Post-Processing-Networking": "None", - "Post-Processing-Tools": "None", - "vmware-adaptertype": "ide", - "vmware-disktype": "sparse" - } - post_body["tags"] = tags - post_body["properties"] = properties - - # call client create_IMAGE and wait till status equals 'Success' - _, body = self.client.create_image(**post_body) - image = body["image"] - test_image_id = image["id"] - self._wait_for_image_status_on_dcp(test_image_id, 'Success') - - # add image to tempest cleanup - self.addCleanup( - self._del_img_validate_deletion_on_dcp_and_lcp, - test_image_id) - # verify image record created successfully - _, body = self.client.get_image(test_image_id) - image = body["image"] - self.assertListEqual(image["regions"][0]["tags"], tags) - self.assertDictEqual(image["regions"][0]["properties"], properties) - - @decorators.idempotent_id('67aa7014-4dbb-4d66-bc7b-1a95a57494f8') - def test_create_image_with_uuid(self): - post_body = self._get_image_params() - # set uuid - post_body['id'] = uuid.uuid4().hex - - # add image to tempest cleanup - self.addCleanup( - self._del_img_validate_deletion_on_dcp_and_lcp, - post_body['id']) - - # call client create_IMAGE and wait till status equals 'Success' - _, body = self.client.create_image(**post_body) - image = body["image"] - - self._wait_for_image_status_on_dcp(post_body['id'], 'Success') - - # verify image record created successfully - _, body = self.client.get_image(post_body['id']) - image = body["image"] - self.assertEqual(image["regions"][0]["id"], post_body['id']) - - @decorators.idempotent_id('ae1223b5-cb75-442b-82eb-488969acc978') - def test_create_image_with_region_group(self): - post_body = self._get_image_params() - # region group - region_group = {"name": "NCLargetest", "type": "group"} - # update region_group to regions - post_body["regions"].append(region_group) - # add image to tempest cleanup - self.addCleanup( - self._del_img_validate_deletion_on_dcp_and_lcp, - post_body["id"]) - - # call client create_IMAGE and wait till status equals 'Success' - _, body = self.client.create_image(**post_body) - image = body["image"] - test_image_id = image["id"] - self._wait_for_image_status_on_dcp(test_image_id, 'Success') - - # verify image record created successfully - _, body = self.client.get_image(test_image_id) - image = body["image"] - # Aggregate Status - self.assertEqual(image["status"], 'Success') - # Region Status - self.assertEqual(image["regions"][1]["status"], 'Success') - # region group - self.assertDictEqual(image["regions"][1]["name"], "NCLargetest") +# Copyright 2016 AT&T Corp +# 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 ranger_tempest_plugin.data_utils import data_utils +from ranger_tempest_plugin.tests.api import ims_base +from tempest import config + +from tempest.lib import decorators +from tempest.lib import exceptions + +CONF = config.CONF + + +class TestTempestIms(ims_base.ImsBaseOrmTest): + + @classmethod + def setup_credentials(cls): + cls.set_network_resources() + super(TestTempestIms, cls).setup_credentials() + + @classmethod + def setup_clients(cls): + super(TestTempestIms, cls).setup_clients() + + @classmethod + def resource_setup(cls): + # setup public image for tempest testing + cls.image_params_public = \ + cls._get_image_params(set_private=False) + cls.image_params_private = \ + cls._get_image_params(set_enabled=False) + + cls.addClassResourceCleanup( + cls._del_img_validate_deletion_on_dcp_and_lcp, + cls.image_params_public['id']) + cls.addClassResourceCleanup( + cls._del_img_validate_deletion_on_dcp_and_lcp, + cls.image_params_private['id']) + + # setup public image for tempest testing + cls.public_image = \ + cls._create_img_and_validate_creation_on_dcp_and_lcp( + **cls.image_params_public) + + # setup private image for tempest testing + cls.private_image = \ + cls._create_img_and_validate_creation_on_dcp_and_lcp( + **cls.image_params_private) + + super(TestTempestIms, cls).resource_setup() + + def _data_setup(self, post_body): + self.addCleanup( + self._del_img_validate_deletion_on_dcp_and_lcp, + post_body['id']) + image = self._create_img_and_validate_creation_on_dcp_and_lcp( + **post_body) + # only check for Success image status if "regions" is not empty + if image["regions"]: + self._wait_for_image_status_on_dcp(image['id'], 'Success') + + return image + + def _delete_image(self, id_): + """Try to delete from from dcp only""" + # delete the data and do get_image to ensure 404-NotFound response + self._del_img_validate_deletion_on_dcp_and_lcp(id_) + self.assertRaises(exceptions.NotFound, self.client.get_image, id_) + + def _create_region(self, status='functional'): + region_name = data_utils.rand_name() + self.addCleanup( + self.os_admin.rms_client.delete_region, + region_name) + + _, region = self.os_admin.rms_client.create_region( + **{ + 'region_id': region_name, + 'status': status, + } + ) + + return region + + @decorators.idempotent_id('2b1bb28b-4151-4e75-ae1b-d21089c3418c') + def test_get_image(self): + """Execute 'get_image' using the following options: + + - get image by id (using cust_id parameter) + - get image by name (using cust_name parameter) + """ + + # execute get_image using image ID and iamge_name + for identifier in [self.public_image['id'], self.public_image['name']]: + _, body = self.client.get_image(identifier) + self.assertIn(self.public_image['id'], body['image']['id']) + + @decorators.idempotent_id('6072c438-1e45-4c0b-97a6-e5127bd33d90') + def test_list_images_with_filters(self): + """This function executes 'list customer' with all available filters: + + - no filter (i.e. list all images) + - filter by region + - filter by customer + - filter by visibility (public/private) + """ + + # define the list customer filters to be used for this test + no_filter = None + customer_filter = "?customer=%s" % self.tenant_id + region_filter = "?region=%s" % self.region_id + public_filter = "?visibility=public" + private_filter = "?visibility=private" + + # list public images + _, body = self.client.list_images(public_filter) + image_ids = [img['id'] for img in body['images']] + self.assertIn(self.public_image['id'], image_ids) + + # list private images + _, body = self.client.list_images(private_filter) + image_ids = [img['id'] for img in body['images']] + self.assertIn(self.private_image['id'], image_ids) + + # execute list_customers with the rest of the filters + for list_filter in [no_filter, region_filter, + customer_filter]: + _, body = self.client.list_images(list_filter) + images = [image['id'] for image in body['images']] + self.assertIn(self.private_image['id'], images) + + @decorators.idempotent_id('4435fef4-49a9-435b-8463-cf8a1e0b7cd8') + def test_disable_image(self): + # disable self.public_image and check if request is successful + self.client.enabled_image(self.public_image['id'], False) + self._wait_for_image_status_on_dcp(self.public_image['id'], 'Success') + _, body = self.client.get_image(self.public_image['id']) + image = body["image"] + + # assert that the image["enabled"] value is 'False' + self.assertTrue(not image['enabled']) + + @decorators.idempotent_id('f32a13e3-6f38-423b-a616-09c8d4e1c277') + def test_enable_image(self): + # enable self.private_image and check if request is successful + self.client.enabled_image(self.private_image['id'], True) + self._wait_for_image_status_on_dcp(self.private_image['id'], 'Success') + _, body = self.client.get_image(self.private_image['id']) + image = body["image"] + + # assert that the image["enabled"] value is 'True' + self.assertTrue(image['enabled']) + + @decorators.idempotent_id('cb9e3022-00d7-4a21-bdb2-67d3cd15a4f8') + def test_add_delete_image_region(self): + # skip region assignment in data setup + post_body = self._get_image_params(set_region=False) + image = self._data_setup(post_body) + + # add region to image then check to confirm image status = "Success" + self.client.add_region_to_image(image['id'], self.region_id) + # image status must show 'Success' when assigned to a region + self._wait_for_image_status_on_dcp(image['id'], 'Success') + + # check that region is successfully added + _, body = self.client.get_image(image['id']) + image = body["image"] + self.assertEqual(image["regions"][0]["name"], self.region_id) + + # delete the region then check to confirm image status = "no regions" + _, body = self.client.delete_region_from_image(image['id'], + self.region_id) + self._wait_for_image_status_on_dcp(image['id'], 'no regions') + + # image region array should be empty after the region was removed + _, body = self.client.get_image(image['id']) + image = body["image"] + self.assertFalse(image["regions"]) + + @decorators.idempotent_id('0ee68189-66a8-4213-ad68-bc12991c174a') + def test_add_delete_image_tenant(self): + # add alt tenant to self.private_image & check if status = "Success" + self.client.add_customer_to_image(self.private_image['id'], + self.alt_tenant_id) + self._wait_for_image_status_on_dcp(self.private_image['id'], + 'Success') + + # check that alt tenant successfully added to image tenants array + _, body = self.client.get_image(self.private_image['id']) + image = body["image"] + self.assertEqual(len(image["customers"]), 2) + self.assertIn(self.alt_tenant_id, image['customers']) + + # now delete alt_tenant_id and ensure operation is successful + _, body = self.client.delete_customer_from_image( + self.private_image['id'], + self.alt_tenant_id) + self._wait_for_image_status_on_dcp(self.private_image['id'], 'Success') + + # image region array should no longer contain alt tenant + _, body = self.client.get_image(self.private_image['id']) + image = body["image"] + self.assertNotIn(self.alt_tenant_id, image['customers']) + + @decorators.idempotent_id('bac99348-6b13-4b30-958b-3c039b27eda3') + def test_update_image_tenant(self): + # replace current tenant in self.private_image with alt tenant + self.client.update_customer(self.private_image['id'], + self.alt_tenant_id) + self._wait_for_image_status_on_dcp(self.private_image['id'], 'Success') + + # check that image tenants array contains only alt tenant + _, body = self.client.get_image(self.private_image['id']) + image = body["image"] + self.assertEqual(len(image["customers"]), 1) + self.assertIn(self.alt_tenant_id, image['customers']) + + @decorators.idempotent_id('0331e02a-ab52-4341-b676-a02462244277') + def test_create_image(self): + post_body = self._get_image_params() + self.addCleanup( + self._del_img_validate_deletion_on_dcp_and_lcp, + post_body['id']) + # call client create_IMAGE and wait till status equals 'Success' + _, body = self.client.create_image(**post_body) + image = body["image"] + self._wait_for_image_status_on_dcp(image['id'], 'Success') + + # verify image record created successfully + _, body = self.client.get_image(image['id']) + image = body["image"] + self.assertEqual(image["regions"][0]["name"], CONF.identity.region) + + @decorators.idempotent_id('01160918-e217-401d-a6a0-e7992ab76e41') + def test_update_image(self): + region = {} + + # define data used to update image + post_body = self._get_image_params(set_region=False) + + # create image that will be updated + image = self._data_setup(post_body) + + # setup region, change properties for update data + region["name"] = self.region_id + region["type"] = "single" + region["checksum"] = "7297321c2fa6424417a548c85edd6e98" + region["virtual_size"] = "None" + region["size"] = "38797312" + post_body["regions"] = [region] + post_body["enabled"] = False + post_body["customers"] = [self.alt_tenant_id] + # empty tags list + post_body["tags"] = [] + + _, body = self.client.update_image(image['id'], para=None, + **post_body) + self._wait_for_image_status_on_dcp(image['id'], 'Success') + # verify image record updated successfully + _, body = self.client.get_image(image['id']) + image = body["image"] + self.assertEqual(image["regions"][0]["name"], CONF.identity.region) + self.assertIn(self.alt_tenant_id, image['customers']) + self.assertFalse(image['enabled']) + self.assertFalse(image['tags']) + + @decorators.idempotent_id('23e2e7e2-5b19-4c66-b35c-7c686a986627') + def test_delete_image(self): + # setup data for test case + post_body = self._get_image_params() + image = self._create_img_and_validate_creation_on_dcp_and_lcp( + **post_body) + + # delete the data and do get_image to ensure 404-NotFound response + self._del_img_validate_deletion_on_dcp_and_lcp(image['id']) + self.assertRaises(exceptions.NotFound, self.client.get_image, + image['id']) + + @decorators.idempotent_id('e642fa39-1b69-4d17-8bd1-aee90ea042a3') + def test_image_while_region_down(self): + # create region with status down + region = self._create_region(status='down') + + # create image within that newly created region + post_body = self._get_image_params() + post_body['regions'][0]['name'] = region['name'] + + self.assertRaises(exceptions.BadRequest, + self.client.create_image, **post_body) + + @decorators.idempotent_id('a1fee342-3000-41a6-97f9-b33fd2734e4d') + def test_image_while_region_building(self): + # create region with status building + region = self._create_region(status='building') + + # create image within that newly created region + post_body = self._get_image_params() + post_body['regions'][0]['name'] = region['name'] + + # add image to tempest cleanup + self.addCleanup( + self._del_img_validate_deletion_on_dcp_and_lcp, + post_body["id"]) + + _, body = self.client.create_image(**post_body) + self.assertIn('id', body['image']) + image = body['image'] + _, body = self.client.get_image(image['id']) + # since region is building it will send error + # notification to ORD + _, body = self.client.get_image(image['id']) + self.assertEqual(body['image']['id'], image['id']) + self.assertEqual(body['image']['status'], 'error') + + @decorators.idempotent_id('b967ce58-5d24-4af2-8416-a336772c8087') + def test_image_while_region_maintenance(self): + # create region with status maintenance + region = self._create_region(status='maintenance') + + # get image params and add region to them + post_body = self._get_image_params() + post_body['regions'][0]['name'] = region['name'] + + # add image to tempest cleanup + self.addCleanup( + self._del_img_validate_deletion_on_dcp_and_lcp, + post_body['id']) + + _, body = self.client.create_image(**post_body) + self.assertIn('id', body['image']) + image = body['image'] + + _, body = self.client.get_image(image['id']) + # since region is maintenance it will give error + # Notification to ORD failed + self.assertEqual(body['image']['id'], image['id']) + self.assertEqual(body['image']['status'], 'Error') + + @decorators.idempotent_id('eae7ca20-5383-4579-9f73-0138b8b3ec85') + def test_list_public_images(self): + """List images with visibility = 'public'""" + # set_private = False to create image with visibility = 'public' + post_body = self._get_image_params(set_private=False) + image = self._data_setup(post_body) + test_image_id = image['id'] + # confirm image visibility is set to "public" after image is created + self.assertEqual(image["visibility"], "public") + filter_public_images = "?visibility=%s" % image["visibility"] + + # list all public images and check if test_image_id is in the list + _, body = self.client.list_images(filter_public_images) + image_ids = [img['id'] for img in body['images']] + self.assertIn(test_image_id, image_ids) + + @decorators.idempotent_id('dc321d60-f3bd-477c-b7bf-1594626f0a12') + def test_list_private_images(self): + """List images with visibility = 'private' """ + # image data created with visibility = private set by default + post_body = self._get_image_params() + image = self._data_setup(post_body) + # confirm image visibility is set to "private" after image is created + self.assertEqual(image["visibility"], "private") + filter_private_images = "?visibility=%s" % image["visibility"] + + # list all public images and check if image id is in the list + _, body = self.client.list_images(filter_private_images) + image_ids = [img['id'] for img in body['images']] + self.assertIn(image['id'], image_ids) + + @decorators.idempotent_id('59887b26-8e73-4781-87a4-3b505ece0021') + def test_create_image_protected_true(self): + post_body = self._get_image_params() + # set Protected True + post_body['protected'] = True + + # add image to temepst cleanup + self.addCleanup( + self._del_img_validate_deletion_on_dcp_and_lcp, + post_body['id']) + + # call client create_IMAGE and wait till status equals 'Success' + _, body = self.client.create_image(**post_body) + image = body["image"] + self._wait_for_image_status_on_dcp(image['id'], 'Success') + + # verify image record created successfully + _, body = self.client.get_image(image['id']) + image = body["image"] + self.assertEqual(image["regions"][0]["name"], CONF.identity.region) + + @decorators.idempotent_id('56cd1de0-3908-41d5-af98-45ad95463817') + def test_create_image_with_tags_properties(self): + post_body = self._get_image_params() + # set tags and properties + tags = ["brocade", "vyatta", "vCEImage", "mediumImage"] + properties = { + "Application-Name": "Vyatta", + "Application-Type": "VCE", + "Application-Vendor": "Brocade", + "Application-Version": "3.5.R5.att-V6.0", + "hw_vif_model": "VirtualVmxnet3", + "OS": "Debian", + "OS-Version": "7", + "Post-Processing-Networking": "None", + "Post-Processing-Tools": "None", + "vmware-adaptertype": "ide", + "vmware-disktype": "sparse" + } + post_body["tags"] = tags + post_body["properties"] = properties + + # add image to tempest cleanup + self.addCleanup( + self._del_img_validate_deletion_on_dcp_and_lcp, + post_body['id']) + + # call client create_IMAGE and wait till status equals 'Success' + _, body = self.client.create_image(**post_body) + image = body["image"] + self._wait_for_image_status_on_dcp(image['id'], 'Success') + + # verify image record created successfully + _, body = self.client.get_image(image['id']) + image = body["image"] + self.assertListEqual(image["regions"][0]["tags"], tags) + self.assertDictEqual(image["regions"][0]["properties"], properties) + + @decorators.idempotent_id('67aa7014-4dbb-4d66-bc7b-1a95a57494f8') + def test_create_image_with_uuid(self): + post_body = self._get_image_params() + + # add image to tempest cleanup + self.addCleanup( + self._del_img_validate_deletion_on_dcp_and_lcp, + post_body['id']) + + # call client create_IMAGE and wait till status equals 'Success' + _, body = self.client.create_image(**post_body) + image = body["image"] + + self._wait_for_image_status_on_dcp(image['id'], 'Success') + + # verify image record created successfully + _, body = self.client.get_image(image['id']) + image = body["image"] + self.assertEqual(image["regions"][0]['id'], post_body['id']) + + @decorators.idempotent_id('ae1223b5-cb75-442b-82eb-488969acc978') + def test_create_image_with_region_group(self): + + # grab image details needed for image build + post_body = self._get_image_params() + # define a region group + region_group = {"name": "NCLargetest", "type": "group"} + # add region_group to regions in image + post_body["regions"].append(region_group) + + # add image to tempest cleanup + self.addCleanup( + self._del_img_validate_deletion_on_dcp_and_lcp, + post_body['id']) + + # call client create_IMAGE and wait till status equals 'Success' + _, body = self.client.create_image(**post_body) + + # set object to built image and wait until it is ready for use + image = body["image"] + self._wait_for_image_status_on_dcp(image['id'], 'Success') + + # verify image record created successfully + _, body = self.client.get_image(image['id']) + image = body["image"] + # Aggregate Status + self.assertEqual(image["status"], 'Success') + # Region Status + self.assertEqual(image["regions"][1]["status"], 'Success') + # region group + self.assertDictEqual(image["regions"][1]["name"], "NCLargetest")