X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=functest%2Fopnfv_tests%2Fopenstack%2Ftempest%2Ftempest.py;h=f30bbc552d333bd14cf66568c30d725bf1e8a07d;hb=59cf95974b2b9c0271c1ff9c9604b960c4bcfa26;hp=ac69357a80f37a34d17271cc62b99d4d242e4176;hpb=8b912cec489a96178fcac5667c03e20850149c3a;p=functest.git diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py index ac69357a8..f30bbc552 100644 --- a/functest/opnfv_tests/openstack/tempest/tempest.py +++ b/functest/opnfv_tests/openstack/tempest/tempest.py @@ -31,16 +31,39 @@ from functest.utils import env LOGGER = logging.getLogger(__name__) -class TempestCommon(singlevm.VmReady1): +class TempestCommon(singlevm.VmReady2): # pylint: disable=too-many-instance-attributes """TempestCommon testcases implementation class.""" visibility = 'public' + shared_network = True + filename_alt = '/home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img' def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = 'tempest' super(TempestCommon, self).__init__(**kwargs) + assert self.orig_cloud + assert self.cloud + assert self.project + if self.orig_cloud.get_role("admin"): + role_name = "admin" + elif self.orig_cloud.get_role("Admin"): + role_name = "Admin" + else: + raise Exception("Cannot detect neither admin nor Admin") + self.orig_cloud.grant_role( + role_name, user=self.project.user.id, + project=self.project.project.id, + domain=self.project.domain.id) + environ = dict( + os.environ, + OS_USERNAME=self.project.user.name, + OS_PROJECT_NAME=self.project.project.name, + OS_PROJECT_ID=self.project.project.id, + OS_PASSWORD=self.project.password) + conf_utils.create_rally_deployment(environ=environ) + conf_utils.create_verifier() self.verifier_id = conf_utils.get_verifier_id() self.verifier_repo_dir = conf_utils.get_verifier_repo_dir( self.verifier_id) @@ -55,6 +78,40 @@ class TempestCommon(singlevm.VmReady1): self.conf_file = None self.image_alt = None self.flavor_alt = None + self.services = [] + try: + self.services = kwargs['run']['args']['services'] + except Exception: # pylint: disable=broad-except + pass + self.neutron_extensions = [] + try: + self.neutron_extensions = kwargs['run']['args'][ + 'neutron_extensions'] + except Exception: # pylint: disable=broad-except + pass + + def check_services(self): + """Check the mandatory services.""" + for service in self.services: + try: + self.cloud.search_services(service)[0] + except Exception: # pylint: disable=broad-except + self.is_skipped = True + break + + def check_extensions(self): + """Check the mandatory network extensions.""" + extensions = self.cloud.get_network_extensions() + for network_extension in self.neutron_extensions: + if network_extension not in extensions: + LOGGER.warning( + "Cannot find Neutron extension: %s", network_extension) + self.is_skipped = True + break + + def check_requirements(self): + self.check_services() + self.check_extensions() @staticmethod def read_file(filename): @@ -77,10 +134,10 @@ class TempestCommon(singlevm.VmReady1): stdout=subprocess.PIPE, stderr=subprocess.STDOUT) for line in proc.stdout: + LOGGER.info(line.rstrip()) new_line = line.replace(' ', '').split('|') if 'Tests' in new_line: break - LOGGER.info(line) if 'Testscount' in new_line: result['num_tests'] = int(new_line[2]) elif 'Success' in new_line: @@ -131,19 +188,15 @@ class TempestCommon(singlevm.VmReady1): result_file = open(self.list, 'w') black_tests = [] try: - installer_type = env.get('INSTALLER_TYPE') deploy_scenario = env.get('DEPLOY_SCENARIO') - if bool(installer_type) * bool(deploy_scenario): - # if INSTALLER_TYPE and DEPLOY_SCENARIO are set we read the - # file + if bool(deploy_scenario): + # if DEPLOY_SCENARIO is set we read the file black_list_file = open(conf_utils.TEMPEST_BLACKLIST) black_list_yaml = yaml.safe_load(black_list_file) black_list_file.close() for item in black_list_yaml: scenarios = item['scenarios'] - installers = item['installers'] - if (deploy_scenario in scenarios and - installer_type in installers): + if deploy_scenario in scenarios: tests = item['tests'] for test in tests: black_tests.append(test) @@ -169,32 +222,31 @@ class TempestCommon(singlevm.VmReady1): f_stdout = open( os.path.join(self.res_dir, "tempest.log"), 'w+') - f_stderr = open( - os.path.join(self.res_dir, - "tempest-error.log"), 'w+') proc = subprocess.Popen( cmd, stdout=subprocess.PIPE, - stderr=f_stderr, + stderr=subprocess.STDOUT, bufsize=1) with proc.stdout: for line in iter(proc.stdout.readline, b''): if re.search(r"\} tempest\.", line): - LOGGER.info(line.replace('\n', '')) + LOGGER.info(line.rstrip()) elif re.search(r'(?=\(UUID=(.*)\))', line): self.verification_id = re.search( r'(?=\(UUID=(.*)\))', line).group(1) - LOGGER.info('Verification UUID: %s', self.verification_id) f_stdout.write(line) proc.wait() - f_stdout.close() - f_stderr.close() if self.verification_id is None: raise Exception('Verification UUID not found') + LOGGER.info('Verification UUID: %s', self.verification_id) + + shutil.copy( + "{}/tempest.log".format(self.deployment_dir), + "{}/tempest.debug.log".format(self.res_dir)) def parse_verifier_result(self): """Parse and save test results.""" @@ -212,7 +264,7 @@ class TempestCommon(singlevm.VmReady1): return with open(os.path.join(self.res_dir, - "tempest-error.log"), 'r') as logfile: + "tempest.log"), 'r') as logfile: output = logfile.read() success_testcases = [] @@ -254,13 +306,76 @@ class TempestCommon(singlevm.VmReady1): """Set image name as tempest img_name_regex""" rconfig = configparser.RawConfigParser() rconfig.read(rally_conf) - if not rconfig.has_section('tempest'): - rconfig.add_section('tempest') - rconfig.set('tempest', 'img_name_regex', '^{}$'.format( + if not rconfig.has_section('openstack'): + rconfig.add_section('openstack') + rconfig.set('openstack', 'img_name_regex', '^{}$'.format( self.image.name)) with open(rally_conf, 'wb') as config_file: rconfig.write(config_file) + def update_default_role(self, rally_conf='/etc/rally/rally.conf'): + """Detect and update the default role if required""" + role = self.get_default_role(self.cloud) + if not role: + return + rconfig = configparser.RawConfigParser() + rconfig.read(rally_conf) + if not rconfig.has_section('openstack'): + rconfig.add_section('openstack') + rconfig.set('openstack', 'swift_operator_role', role.name) + with open(rally_conf, 'wb') as config_file: + rconfig.write(config_file) + + def update_rally_logs(self, rally_conf='/etc/rally/rally.conf'): + """Print rally logs in res dir""" + if not os.path.exists(self.res_dir): + os.makedirs(self.res_dir) + rconfig = configparser.RawConfigParser() + rconfig.read(rally_conf) + rconfig.set('DEFAULT', 'log-file', 'rally.log') + rconfig.set('DEFAULT', 'log_dir', self.res_dir) + with open(rally_conf, 'wb') as config_file: + rconfig.write(config_file) + + @staticmethod + def clean_rally_conf(rally_conf='/etc/rally/rally.conf'): + """Clean Rally config""" + rconfig = configparser.RawConfigParser() + rconfig.read(rally_conf) + if rconfig.has_option('openstack', 'img_name_regex'): + rconfig.remove_option('openstack', 'img_name_regex') + if rconfig.has_option('openstack', 'swift_operator_role'): + rconfig.remove_option('openstack', 'swift_operator_role') + if rconfig.has_option('DEFAULT', 'log-file'): + rconfig.remove_option('DEFAULT', 'log-file') + if rconfig.has_option('DEFAULT', 'log_dir'): + rconfig.remove_option('DEFAULT', 'log_dir') + with open(rally_conf, 'wb') as config_file: + rconfig.write(config_file) + + def update_scenario_section(self): + """Update scenario section in tempest.conf""" + rconfig = configparser.RawConfigParser() + rconfig.read(self.conf_file) + filename = getattr( + config.CONF, '{}_image'.format(self.case_name), self.filename) + if not rconfig.has_section('scenario'): + rconfig.add_section('scenario') + rconfig.set('scenario', 'img_file', os.path.basename(filename)) + rconfig.set('scenario', 'img_dir', os.path.dirname(filename)) + rconfig.set('scenario', 'img_disk_format', getattr( + config.CONF, '{}_image_format'.format(self.case_name), + self.image_format)) + extra_properties = self.extra_properties.copy() + extra_properties.update( + getattr(config.CONF, '{}_extra_properties'.format( + self.case_name), {})) + rconfig.set( + 'scenario', 'img_properties', + conf_utils.convert_dict_to_ini(extra_properties)) + with open(self.conf_file, 'wb') as config_file: + rconfig.write(config_file) + def configure(self, **kwargs): # pylint: disable=unused-argument """ Create all openstack resources for tempest-based testcases and write @@ -270,19 +385,20 @@ class TempestCommon(singlevm.VmReady1): os.makedirs(self.res_dir) compute_cnt = len(self.cloud.list_hypervisors()) - self.image_alt = self.publish_image( - '{}-img_alt_{}'.format(self.case_name, self.guid)) + self.image_alt = self.publish_image_alt() self.flavor_alt = self.create_flavor_alt() LOGGER.debug("flavor: %s", self.flavor_alt) self.conf_file = conf_utils.configure_verifier(self.deployment_dir) conf_utils.configure_tempest_update_params( - self.conf_file, network_name=self.network.id, + self.conf_file, network_name=self.network.name, image_id=self.image.id, flavor_id=self.flavor.id, compute_cnt=compute_cnt, image_alt_id=self.image_alt.id, - flavor_alt_id=self.flavor_alt.id) + flavor_alt_id=self.flavor_alt.id, + domain_name=self.cloud.auth.get("project_domain_name", "Default")) + self.update_scenario_section() self.backup_tempest_config(self.conf_file, self.res_dir) def run(self, **kwargs): @@ -290,7 +406,12 @@ class TempestCommon(singlevm.VmReady1): try: assert super(TempestCommon, self).run( **kwargs) == testcase.TestCase.EX_OK + if not os.path.exists(self.res_dir): + os.makedirs(self.res_dir) self.update_rally_regex() + self.update_default_role() + self.update_rally_logs() + shutil.copy("/etc/rally/rally.conf", self.res_dir) self.configure(**kwargs) self.generate_test_list(**kwargs) self.apply_tempest_blacklist() @@ -309,8 +430,9 @@ class TempestCommon(singlevm.VmReady1): """ Cleanup all OpenStack objects. Should be called on completion. """ - super(TempestCommon, self).clean() + self.clean_rally_conf() if self.image_alt: self.cloud.delete_image(self.image_alt) if self.flavor_alt: self.orig_cloud.delete_flavor(self.flavor_alt.id) + super(TempestCommon, self).clean()