diff --git a/releasenotes/notes/remove-input-scenarios-functionality-01308e6d4307f580.yaml b/releasenotes/notes/remove-input-scenarios-functionality-01308e6d4307f580.yaml new file mode 100644 index 0000000000..4ee883f605 --- /dev/null +++ b/releasenotes/notes/remove-input-scenarios-functionality-01308e6d4307f580.yaml @@ -0,0 +1,11 @@ +--- +upgrade: + - The input scenarios functionality no longer exists in tempest. This caused + a large number of issues for limited benefit and was only used by a single + test, test_server_basic_ops. If you were using this functionality you'll + now have to do it manually with a script and/or tempest workspaces +deprecations: + - All the options in the input-scenario group are now deprecated. These were + only used in tree by the now removed input scenarios functionality in + test_server_basic_ops. They were only deprecated because there could be + external consumers via plugins. They will be removed during the Ocata cycle. diff --git a/tempest/config.py b/tempest/config.py index a9cf5379bc..b3d409f79c 100644 --- a/tempest/config.py +++ b/tempest/config.py @@ -1035,23 +1035,28 @@ specify .* as the regex. input_scenario_group = cfg.OptGroup(name="input-scenario", title="Filters and values for" - " input scenarios") + " input scenarios[DEPRECATED]") + InputScenarioGroup = [ cfg.StrOpt('image_regex', default='^cirros-0.3.1-x86_64-uec$', - help="Matching images become parameters for scenario tests"), + help="Matching images become parameters for scenario tests", + deprecated_for_removal=True), cfg.StrOpt('flavor_regex', default='^m1.nano$', - help="Matching flavors become parameters for scenario tests"), + help="Matching flavors become parameters for scenario tests", + deprecated_for_removal=True), cfg.StrOpt('non_ssh_image_regex', default='^.*[Ww]in.*$', help="SSH verification in tests is skipped" - "for matching images"), + "for matching images", + deprecated_for_removal=True), cfg.StrOpt('ssh_user_regex', default="[[\"^.*[Cc]irros.*$\", \"cirros\"]]", help="List of user mapped to regex " - "to matching image names."), + "to matching image names.", + deprecated_for_removal=True), ] diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py index a9f2dff3f7..91669d050f 100644 --- a/tempest/scenario/test_server_basic_ops.py +++ b/tempest/scenario/test_server_basic_ops.py @@ -20,15 +20,12 @@ from oslo_log import log as logging from tempest import config from tempest import exceptions from tempest.scenario import manager -from tempest.scenario import utils as test_utils from tempest import test CONF = config.CONF LOG = logging.getLogger(__name__) -load_tests = test_utils.load_tests_input_scenario_utils - class TestServerBasicOps(manager.ScenarioTest): @@ -47,27 +44,10 @@ class TestServerBasicOps(manager.ScenarioTest): def setUp(self): super(TestServerBasicOps, self).setUp() - # Setup image and flavor the test instance - # Support both configured and injected values - if not hasattr(self, 'image_ref'): - self.image_ref = CONF.compute.image_ref - if not hasattr(self, 'flavor_ref'): - self.flavor_ref = CONF.compute.flavor_ref - self.image_utils = test_utils.ImageUtils(self.manager) - if not self.image_utils.is_flavor_enough(self.flavor_ref, - self.image_ref): - raise self.skipException( - '{image} does not fit in {flavor}'.format( - image=self.image_ref, flavor=self.flavor_ref - ) - ) - self.run_ssh = CONF.validation.run_validation and \ - self.image_utils.is_sshable_image(self.image_ref) - self.ssh_user = self.image_utils.ssh_user(self.image_ref) - LOG.debug('Starting test for i:{image}, f:{flavor}. ' - 'Run ssh: {ssh}, user: {ssh_user}'.format( - image=self.image_ref, flavor=self.flavor_ref, - ssh=self.run_ssh, ssh_user=self.ssh_user)) + self.image_ref = CONF.compute.image_ref + self.flavor_ref = CONF.compute.flavor_ref + self.run_ssh = CONF.validation.run_validation + self.ssh_user = CONF.validation.image_ssh_user def verify_ssh(self, keypair): if self.run_ssh: diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py deleted file mode 100644 index c7ba659366..0000000000 --- a/tempest/scenario/utils.py +++ /dev/null @@ -1,185 +0,0 @@ -# Copyright 2013 Hewlett-Packard, Ltd. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import re -import string -import unicodedata - -from oslo_serialization import jsonutils as json -import testscenarios -import testtools - -from tempest import clients -from tempest.common import credentials_factory as credentials -from tempest import config -from tempest.lib.common.utils import misc -from tempest.lib import exceptions as exc_lib - -CONF = config.CONF - - -class ImageUtils(object): - - default_ssh_user = 'root' - - def __init__(self, os): - # Load configuration items - self.ssh_users = json.loads(CONF.input_scenario.ssh_user_regex) - self.non_ssh_image_pattern = \ - CONF.input_scenario.non_ssh_image_regex - # Setup clients - self.compute_images_client = os.compute_images_client - self.flavors_client = os.flavors_client - - def ssh_user(self, image_id): - _image = self.compute_images_client.show_image(image_id)['image'] - for regex, user in self.ssh_users: - # First match wins - if re.match(regex, _image['name']) is not None: - return user - else: - return self.default_ssh_user - - def _is_sshable_image(self, image): - return not re.search(pattern=self.non_ssh_image_pattern, - string=str(image['name'])) - - def is_sshable_image(self, image_id): - _image = self.compute_images_client.show_image(image_id)['image'] - return self._is_sshable_image(_image) - - def _is_flavor_enough(self, flavor, image): - return image['minDisk'] <= flavor['disk'] - - def is_flavor_enough(self, flavor_id, image_id): - _image = self.compute_images_client.show_image(image_id)['image'] - _flavor = self.flavors_client.show_flavor(flavor_id)['flavor'] - return self._is_flavor_enough(_flavor, _image) - - -@misc.singleton -class InputScenarioUtils(object): - - """Example usage: - - import testscenarios - (...) - load_tests = testscenarios.load_tests_apply_scenarios - - - class TestInputScenario(manager.ScenarioTest): - - scenario_utils = utils.InputScenarioUtils() - scenario_flavor = scenario_utils.scenario_flavors - scenario_image = scenario_utils.scenario_images - scenarios = testscenarios.multiply_scenarios(scenario_image, - scenario_flavor) - - def test_create_server_metadata(self): - name = rand_name('instance') - self.servers_client.create_server(name=name, - flavorRef=self.flavor_ref, - imageRef=self.image_ref) - """ - validchars = "-_.{ascii}{digit}".format(ascii=string.ascii_letters, - digit=string.digits) - - def __init__(self): - network_resources = { - 'network': False, - 'router': False, - 'subnet': False, - 'dhcp': False, - } - self.cred_provider = credentials.get_credentials_provider( - name='InputScenarioUtils', - identity_version=CONF.identity.auth_version, - network_resources=network_resources) - os = clients.Manager( - self.cred_provider.get_primary_creds().credentials) - self.compute_images_client = os.compute_images_client - self.flavors_client = os.flavors_client - self.image_pattern = CONF.input_scenario.image_regex - self.flavor_pattern = CONF.input_scenario.flavor_regex - - def _normalize_name(self, name): - nname = unicodedata.normalize('NFKD', name).encode('ASCII', 'ignore') - nname = ''.join(c for c in nname if c in self.validchars) - return nname - - def clear_creds(self): - self.cred_provider.clear_creds() - - @property - def scenario_images(self): - """:return: a scenario with name and uuid of images""" - if not CONF.service_available.glance: - return [] - if not hasattr(self, '_scenario_images'): - try: - images = self.compute_images_client.list_images()['images'] - self._scenario_images = [ - (self._normalize_name(i['name']), dict(image_ref=i['id'])) - for i in images if re.search(self.image_pattern, - str(i['name'])) - ] - except Exception: - self._scenario_images = [] - return self._scenario_images - - @property - def scenario_flavors(self): - """:return: a scenario with name and uuid of flavors""" - if not hasattr(self, '_scenario_flavors'): - try: - flavors = self.flavors_client.list_flavors()['flavors'] - self._scenario_flavors = [ - (self._normalize_name(f['name']), dict(flavor_ref=f['id'])) - for f in flavors if re.search(self.flavor_pattern, - str(f['name'])) - ] - except Exception: - self._scenario_flavors = [] - return self._scenario_flavors - - -def load_tests_input_scenario_utils(*args): - """Wrapper for testscenarios to set the scenarios - - The purpose is to avoid running a getattr on the CONF object at import. - """ - - if getattr(args[0], 'suiteClass', None) is not None: - loader, standard_tests, pattern = args - else: - standard_tests, module, loader = args - output = None - scenario_utils = None - try: - scenario_utils = InputScenarioUtils() - scenario_flavor = scenario_utils.scenario_flavors - scenario_image = scenario_utils.scenario_images - except (exc_lib.InvalidCredentials, TypeError): - output = standard_tests - finally: - if scenario_utils: - scenario_utils.clear_creds() - if output is not None: - return output - for test in testtools.iterate_tests(standard_tests): - setattr(test, 'scenarios', testscenarios.multiply_scenarios( - scenario_image, - scenario_flavor)) - return testscenarios.load_tests_apply_scenarios(*args)