From e32353a740a3aaa76031fe9c2372b11f88add1bb Mon Sep 17 00:00:00 2001 From: Juha Kosonen Date: Fri, 4 May 2018 16:30:44 +0300 Subject: [PATCH] Switch to Shade in rally Use Shade for managing OpenStack resources in rally. Change-Id: Ic8b7aaef6886f6ca4930b2ea463317b75ed8d3c9 Signed-off-by: Juha Kosonen --- functest/opnfv_tests/openstack/rally/rally.py | 155 +++++++------- functest/tests/unit/openstack/rally/test_rally.py | 240 ++++++++++++++-------- 2 files changed, 228 insertions(+), 167 deletions(-) diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py index 8048eddeb..8d1bfabb5 100644 --- a/functest/opnfv_tests/openstack/rally/rally.py +++ b/functest/opnfv_tests/openstack/rally/rally.py @@ -20,21 +20,16 @@ import subprocess import time import uuid +import os_client_config import pkg_resources import prettytable -from snaps.config.flavor import FlavorConfig -from snaps.config.image import ImageConfig -from snaps.config.network import NetworkConfig, SubnetConfig -from snaps.config.router import RouterConfig -from snaps.openstack.create_flavor import OpenStackFlavor -from snaps.openstack.utils import deploy_utils from xtesting.core import testcase from xtesting.energy import energy import yaml -from functest.opnfv_tests.openstack.snaps import snaps_utils from functest.opnfv_tests.openstack.tempest import conf_utils from functest.utils import config +from functest.utils import functest_utils from functest.utils import env LOGGER = logging.getLogger(__name__) @@ -51,14 +46,13 @@ class RallyBase(testcase.TestCase): GLANCE_IMAGE_PATH = os.path.join(getattr( config.CONF, 'dir_functest_images'), GLANCE_IMAGE_FILENAME) GLANCE_IMAGE_FORMAT = getattr(config.CONF, 'openstack_image_disk_format') - GLANCE_IMAGE_USERNAME = getattr(config.CONF, 'openstack_image_username') GLANCE_IMAGE_EXTRA_PROPERTIES = getattr( config.CONF, 'image_properties', {}) FLAVOR_NAME = getattr(config.CONF, 'rally_flavor_name') FLAVOR_ALT_NAME = getattr(config.CONF, 'rally_flavor_alt_name') FLAVOR_RAM = 512 FLAVOR_RAM_ALT = 1024 - FLAVOR_EXTRA_SPECS = getattr(config.CONF, 'flavor_extra_specs', None) + FLAVOR_EXTRA_SPECS = getattr(config.CONF, 'flavor_extra_specs', {}) if FLAVOR_EXTRA_SPECS: FLAVOR_RAM = 1024 FLAVOR_RAM_ALT = 2048 @@ -87,15 +81,14 @@ class RallyBase(testcase.TestCase): def __init__(self, **kwargs): """Initialize RallyBase object.""" super(RallyBase, self).__init__(**kwargs) - self.os_creds = kwargs.get('os_creds') or snaps_utils.get_credentials() + self.cloud = os_client_config.make_shade() self.guid = '-' + str(uuid.uuid4()) self.creators = [] self.mode = '' self.summary = [] self.scenario_dir = '' self.image_name = None - self.ext_net_name = None - self.priv_net_id = None + self.ext_net = None self.flavor_name = None self.flavor_alt_name = None self.smoke = None @@ -104,6 +97,12 @@ class RallyBase(testcase.TestCase): self.result = None self.details = None self.compute_cnt = 0 + self.image = None + self.flavor = None + self.flavor_alt = None + self.network = None + self.subnet = None + self.router = None def _build_task_args(self, test_file_name): """Build arguments for the Rally task.""" @@ -122,15 +121,13 @@ class RallyBase(testcase.TestCase): task_args['concurrency'] = self.CONCURRENCY task_args['smoke'] = self.smoke - ext_net = self.ext_net_name - if ext_net: - task_args['floating_network'] = str(ext_net) + if self.ext_net: + task_args['floating_network'] = str(self.ext_net.name) else: task_args['floating_network'] = '' - net_id = self.priv_net_id - if net_id: - task_args['netid'] = str(net_id) + if self.network: + task_args['netid'] = str(self.network.id) else: task_args['netid'] = '' @@ -421,6 +418,7 @@ class RallyBase(testcase.TestCase): def _prepare_env(self): """Create resources needed by test scenarios.""" + assert self.cloud LOGGER.debug('Validating the test name...') if self.test_name not in self.TESTS: raise Exception("Test name '%s' is invalid" % self.test_name) @@ -431,73 +429,69 @@ class RallyBase(testcase.TestCase): self.image_name = self.GLANCE_IMAGE_NAME + self.guid self.flavor_name = self.FLAVOR_NAME + self.guid self.flavor_alt_name = self.FLAVOR_ALT_NAME + self.guid - self.ext_net_name = snaps_utils.get_ext_net_name(self.os_creds) - self.compute_cnt = snaps_utils.get_active_compute_cnt(self.os_creds) + self.compute_cnt = len(self.cloud.list_hypervisors()) + self.ext_net = functest_utils.get_external_network(self.cloud) + if self.ext_net is None: + raise Exception("No external network found") LOGGER.debug("Creating image '%s'...", self.image_name) - image_creator = deploy_utils.create_image( - self.os_creds, ImageConfig( - name=self.image_name, - image_file=self.GLANCE_IMAGE_PATH, - img_format=self.GLANCE_IMAGE_FORMAT, - image_user=self.GLANCE_IMAGE_USERNAME, - public=True, - extra_properties=self.GLANCE_IMAGE_EXTRA_PROPERTIES)) - if image_creator is None: + self.image = self.cloud.create_image( + self.image_name, + filename=self.GLANCE_IMAGE_PATH, + disk_format=self.GLANCE_IMAGE_FORMAT, + meta=self.GLANCE_IMAGE_EXTRA_PROPERTIES, + is_public=True) + if self.image is None: raise Exception("Failed to create image") - self.creators.append(image_creator) LOGGER.debug("Creating network '%s'...", network_name) - - rally_network_type = getattr(config.CONF, 'rally_network_type', None) - rally_physical_network = getattr( - config.CONF, 'rally_physical_network', None) - rally_segmentation_id = getattr( - config.CONF, 'rally_segmentation_id', None) - - network_creator = deploy_utils.create_network( - self.os_creds, NetworkConfig( - name=network_name, - shared=True, - network_type=rally_network_type, - physical_network=rally_physical_network, - segmentation_id=rally_segmentation_id, - subnet_settings=[SubnetConfig( - name=subnet_name, - cidr=self.RALLY_PRIVATE_SUBNET_CIDR, - dns_nameservers=[env.get('NAMESERVER')])])) - if network_creator is None: + provider = {} + if hasattr(config.CONF, 'rally_network_type'): + provider["network_type"] = getattr( + config.CONF, 'rally_network_type') + if hasattr(config.CONF, 'rally_physical_network'): + provider["physical_network"] = getattr( + config.CONF, 'rally_physical_network') + if hasattr(config.CONF, 'rally_segmentation_id'): + provider["segmentation_id"] = getattr( + config.CONF, 'rally_segmentation_id') + + self.network = self.cloud.create_network( + network_name, shared=True, provider=provider) + if self.network is None: raise Exception("Failed to create private network") - self.priv_net_id = network_creator.get_network().id - self.creators.append(network_creator) + + self.subnet = self.cloud.create_subnet( + self.network.id, + subnet_name=subnet_name, + cidr=self.RALLY_PRIVATE_SUBNET_CIDR, + enable_dhcp=True, + dns_nameservers=[env.get('NAMESERVER')]) + if self.subnet is None: + raise Exception("Failed to create private subnet") LOGGER.debug("Creating router '%s'...", router_name) - router_creator = deploy_utils.create_router( - self.os_creds, RouterConfig( - name=router_name, - external_gateway=self.ext_net_name, - internal_subnets=[subnet_name])) - if router_creator is None: + self.router = self.cloud.create_router( + router_name, ext_gateway_net_id=self.ext_net.id) + if self.router is None: raise Exception("Failed to create router") - self.creators.append(router_creator) + self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id) LOGGER.debug("Creating flavor '%s'...", self.flavor_name) - flavor_creator = OpenStackFlavor( - self.os_creds, FlavorConfig( - name=self.flavor_name, ram=self.FLAVOR_RAM, disk=1, vcpus=1, - metadata=self.FLAVOR_EXTRA_SPECS)) - if flavor_creator is None or flavor_creator.create() is None: + self.flavor = self.cloud.create_flavor( + self.flavor_name, self.FLAVOR_RAM, 1, 1) + if self.flavor is None: raise Exception("Failed to create flavor") - self.creators.append(flavor_creator) + self.cloud.set_flavor_specs( + self.flavor.id, self.FLAVOR_EXTRA_SPECS) LOGGER.debug("Creating flavor '%s'...", self.flavor_alt_name) - flavor_alt_creator = OpenStackFlavor( - self.os_creds, FlavorConfig( - name=self.flavor_alt_name, ram=self.FLAVOR_RAM_ALT, disk=1, - vcpus=1, metadata=self.FLAVOR_EXTRA_SPECS)) - if flavor_alt_creator is None or flavor_alt_creator.create() is None: + self.flavor_alt = self.cloud.create_flavor( + self.flavor_alt_name, self.FLAVOR_RAM_ALT, 1, 1) + if self.flavor_alt is None: raise Exception("Failed to create flavor") - self.creators.append(flavor_alt_creator) + self.cloud.set_flavor_specs( + self.flavor_alt.id, self.FLAVOR_EXTRA_SPECS) def _run_tests(self): """Execute tests.""" @@ -563,12 +557,21 @@ class RallyBase(testcase.TestCase): self.details = payload def _clean_up(self): - """Cleanup all OpenStack objects. Should be called on completion.""" - for creator in reversed(self.creators): - try: - creator.clean() - except Exception as exc: # pylint: disable=broad-except - LOGGER.error('Unexpected error cleaning - %s', exc) + """Cleanup of OpenStack resources. Should be called on completion.""" + if self.flavor_alt: + self.cloud.delete_flavor(self.flavor_alt.id) + if self.flavor: + self.cloud.delete_flavor(self.flavor.id) + if self.router and self.subnet: + self.cloud.remove_router_interface(self.router, self.subnet.id) + if self.router: + self.cloud.delete_router(self.router.id) + if self.subnet: + self.cloud.delete_subnet(self.subnet.id) + if self.network: + self.cloud.delete_network(self.network.id) + if self.image: + self.cloud.delete_image(self.image.id) @energy.enable_recording def run(self, **kwargs): diff --git a/functest/tests/unit/openstack/rally/test_rally.py b/functest/tests/unit/openstack/rally/test_rally.py index 989ade090..970e5c4f4 100644 --- a/functest/tests/unit/openstack/rally/test_rally.py +++ b/functest/tests/unit/openstack/rally/test_rally.py @@ -13,7 +13,6 @@ import os import unittest import mock -from snaps.openstack.os_credentials import OSCreds from xtesting.core import testcase from functest.opnfv_tests.openstack.rally import rally @@ -22,14 +21,9 @@ from functest.opnfv_tests.openstack.rally import rally class OSRallyTesting(unittest.TestCase): # pylint: disable=too-many-public-methods def setUp(self): - os_creds = OSCreds( - username='user', password='pass', - auth_url='http://foo.com:5000/v3', project_name='bar') - with mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_credentials', - return_value=os_creds) as mock_get_creds: + with mock.patch('os_client_config.make_shade') as mock_make_shade: self.rally_base = rally.RallyBase() - self.assertTrue(mock_get_creds.called) + self.assertTrue(mock_make_shade.called) def test_build_task_args_missing_floating_network(self): os.environ['OS_AUTH_URL'] = '' @@ -270,94 +264,138 @@ class OSRallyTesting(unittest.TestCase): with self.assertRaises(Exception): self.rally_base._prepare_env() - @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_active_compute_cnt') - @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_ext_net_name', return_value='test_net_name') - @mock.patch('snaps.openstack.utils.deploy_utils.create_image', - return_value=None) - def test_prepare_env_image_missing( - self, mock_get_img, mock_get_net, mock_get_comp_cnt): + @mock.patch('functest.utils.functest_utils.get_external_network') + def test_prepare_env_image_missing(self, *args): + # pylint: disable=unused-argument self.rally_base.TESTS = ['test1', 'test2'] self.rally_base.test_name = 'test1' - with self.assertRaises(Exception): - self.rally_base._prepare_env() - mock_get_img.assert_called() - mock_get_net.assert_called() - mock_get_comp_cnt.assert_called() - - @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_active_compute_cnt') - @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_ext_net_name', return_value='test_net_name') - @mock.patch('snaps.openstack.utils.deploy_utils.create_image') - @mock.patch('snaps.openstack.utils.deploy_utils.create_network', - return_value=None) - def test_prepare_env_network_creation_failed( - self, mock_create_net, mock_get_img, mock_get_net, - mock_get_comp_cnt): + with mock.patch.object(self.rally_base.cloud, 'list_hypervisors'), \ + mock.patch.object(self.rally_base.cloud, 'create_image', + return_value=None): + with self.assertRaises(Exception): + self.rally_base._prepare_env() + + @mock.patch('functest.utils.functest_utils.get_external_network') + def test_prepare_env_network_creation_failed(self, *args): + # pylint: disable=unused-argument self.rally_base.TESTS = ['test1', 'test2'] self.rally_base.test_name = 'test1' - with self.assertRaises(Exception): - self.rally_base._prepare_env() - mock_create_net.assert_called() - mock_get_img.assert_called() - mock_get_net.assert_called() - mock_get_comp_cnt.assert_called() - - @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_active_compute_cnt') - @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_ext_net_name', return_value='test_net_name') - @mock.patch('snaps.openstack.utils.deploy_utils.create_image') - @mock.patch('snaps.openstack.utils.deploy_utils.create_network') - @mock.patch('snaps.openstack.utils.deploy_utils.create_router', - return_value=None) + with mock.patch.object(self.rally_base.cloud, + 'list_hypervisors') as mock_list_hyperv, \ + mock.patch.object(self.rally_base.cloud, + 'create_image') as mock_create_img, \ + mock.patch.object(self.rally_base.cloud, 'create_network', + return_value=None) as mock_create_net: + with self.assertRaises(Exception): + self.rally_base._prepare_env() + mock_create_net.assert_called() + mock_create_img.assert_called() + mock_list_hyperv.assert_called() + + @mock.patch('functest.utils.functest_utils.get_external_network') + def test_prepare_env_subnet_creation_failed(self, *args): + # pylint: disable=unused-argument + self.rally_base.TESTS = ['test1', 'test2'] + self.rally_base.test_name = 'test1' + with mock.patch.object(self.rally_base.cloud, + 'list_hypervisors') as mock_list_hyperv, \ + mock.patch.object(self.rally_base.cloud, + 'create_image') as mock_create_img, \ + mock.patch.object(self.rally_base.cloud, + 'create_network') as mock_create_net, \ + mock.patch.object(self.rally_base.cloud, 'create_subnet', + return_value=None) as mock_create_subnet: + with self.assertRaises(Exception): + self.rally_base._prepare_env() + mock_create_subnet.assert_called() + mock_create_net.assert_called() + mock_create_img.assert_called() + mock_list_hyperv.assert_called() + + @mock.patch('functest.utils.functest_utils.get_external_network') def test_prepare_env_router_creation_failed(self, *args): + # pylint: disable=unused-argument self.rally_base.TESTS = ['test1', 'test2'] self.rally_base.test_name = 'test1' - with self.assertRaises(Exception): - self.rally_base._prepare_env() - for func in args: - func.assert_called() - - @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_active_compute_cnt') - @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_ext_net_name', return_value='test_net_name') - @mock.patch('snaps.openstack.utils.deploy_utils.create_image') - @mock.patch('snaps.openstack.utils.deploy_utils.create_network') - @mock.patch('snaps.openstack.utils.deploy_utils.create_router') - @mock.patch('snaps.openstack.create_flavor.OpenStackFlavor.create', - return_value=None) - def test_prepare_env_flavor_creation_failed(self, mock_create_flavor, - *args): + with mock.patch.object(self.rally_base.cloud, + 'list_hypervisors') as mock_list_hyperv, \ + mock.patch.object(self.rally_base.cloud, + 'create_image') as mock_create_img, \ + mock.patch.object(self.rally_base.cloud, + 'create_network') as mock_create_net, \ + mock.patch.object(self.rally_base.cloud, + 'create_subnet') as mock_create_subnet, \ + mock.patch.object(self.rally_base.cloud, 'create_router', + return_value=None) as mock_create_router: + with self.assertRaises(Exception): + self.rally_base._prepare_env() + mock_create_router.assert_called() + mock_create_subnet.assert_called() + mock_create_net.assert_called() + mock_create_img.assert_called() + mock_list_hyperv.assert_called() + + @mock.patch('functest.utils.functest_utils.get_external_network') + def test_prepare_env_flavor_creation_failed(self, *args): + # pylint: disable=unused-argument self.rally_base.TESTS = ['test1', 'test2'] self.rally_base.test_name = 'test1' - with self.assertRaises(Exception): - self.rally_base._prepare_env() - for func in args: - func.assert_called() - mock_create_flavor.assert_called_once() - - @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_active_compute_cnt') - @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' - 'get_ext_net_name', return_value='test_net_name') - @mock.patch('snaps.openstack.utils.deploy_utils.create_image') - @mock.patch('snaps.openstack.utils.deploy_utils.create_network') - @mock.patch('snaps.openstack.utils.deploy_utils.create_router') - @mock.patch('snaps.openstack.create_flavor.OpenStackFlavor.create', - side_effect=[mock.Mock, None]) - def test_prepare_env_flavor_alt_creation_failed(self, mock_create_flavor, - *args): + with mock.patch.object(self.rally_base.cloud, + 'list_hypervisors') as mock_list_hyperv, \ + mock.patch.object(self.rally_base.cloud, + 'create_image') as mock_create_img, \ + mock.patch.object(self.rally_base.cloud, + 'create_network') as mock_create_net, \ + mock.patch.object(self.rally_base.cloud, + 'create_subnet') as mock_create_subnet, \ + mock.patch.object(self.rally_base.cloud, + 'add_router_interface') as mock_add_router_if, \ + mock.patch.object(self.rally_base.cloud, + 'create_router') as mock_create_router, \ + mock.patch.object(self.rally_base.cloud, 'create_flavor', + return_value=None) as mock_create_flavor: + with self.assertRaises(Exception): + self.rally_base._prepare_env() + mock_create_flavor.assert_called_once() + mock_add_router_if.assert_called() + mock_create_router.assert_called() + mock_create_subnet.assert_called() + mock_create_net.assert_called() + mock_create_img.assert_called() + mock_list_hyperv.assert_called() + + @mock.patch('functest.utils.functest_utils.get_external_network') + def test_prepare_env_flavor_alt_creation_failed(self, *args): + # pylint: disable=unused-argument self.rally_base.TESTS = ['test1', 'test2'] self.rally_base.test_name = 'test1' - with self.assertRaises(Exception): - self.rally_base._prepare_env() - for func in args: - func.assert_called() - self.assertEqual(mock_create_flavor.call_count, 2) + with mock.patch.object(self.rally_base.cloud, + 'list_hypervisors') as mock_list_hyperv, \ + mock.patch.object(self.rally_base.cloud, + 'create_image') as mock_create_img, \ + mock.patch.object(self.rally_base.cloud, + 'create_network') as mock_create_net, \ + mock.patch.object(self.rally_base.cloud, + 'create_subnet') as mock_create_subnet, \ + mock.patch.object(self.rally_base.cloud, + 'add_router_interface') as mock_add_router_if, \ + mock.patch.object(self.rally_base.cloud, + 'create_router') as mock_create_router, \ + mock.patch.object(self.rally_base.cloud, + 'set_flavor_specs') as mock_set_flavor_specs, \ + mock.patch.object(self.rally_base.cloud, 'create_flavor', + side_effect=[mock.Mock(), None]) \ + as mock_create_flavor: + with self.assertRaises(Exception): + self.rally_base._prepare_env() + self.assertEqual(mock_create_flavor.call_count, 2) + mock_set_flavor_specs.assert_called_once() + mock_add_router_if.assert_called() + mock_create_router.assert_called() + mock_create_subnet.assert_called() + mock_create_net.assert_called() + mock_create_img.assert_called() + mock_list_hyperv.assert_called() @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.' '_run_task') @@ -377,12 +415,32 @@ class OSRallyTesting(unittest.TestCase): mock_run_task.assert_any_call('test1') def test_clean_up_default(self): - creator1 = mock.Mock() - creator2 = mock.Mock() - self.rally_base.creators = [creator1, creator2] - self.rally_base._clean_up() - self.assertTrue(creator1.clean.called) - self.assertTrue(creator2.clean.called) + with mock.patch.object(self.rally_base.cloud, + 'delete_flavor') as mock_delete_flavor, \ + mock.patch.object(self.rally_base.cloud, + 'remove_router_interface') \ + as mock_remove_router_if, \ + mock.patch.object(self.rally_base.cloud, + 'delete_router') as mock_delete_router, \ + mock.patch.object(self.rally_base.cloud, + 'delete_subnet') as mock_delete_subnet, \ + mock.patch.object(self.rally_base.cloud, + 'delete_network') as mock_delete_net, \ + mock.patch.object(self.rally_base.cloud, + 'delete_image') as mock_delete_img: + self.rally_base.flavor_alt = mock.Mock() + self.rally_base.flavor = mock.Mock() + self.rally_base.router = mock.Mock() + self.rally_base.subnet = mock.Mock() + self.rally_base.network = mock.Mock() + self.rally_base.image = mock.Mock() + self.rally_base._clean_up() + self.assertEqual(mock_delete_flavor.call_count, 2) + mock_remove_router_if.assert_called() + mock_delete_router.assert_called() + mock_delete_subnet.assert_called() + mock_delete_net.assert_called() + mock_delete_img.assert_called() @mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.' 'create_rally_deployment') -- 2.16.6