#!/usr/bin/env python ############################################################################## # Copyright (c) 2017 grakiss.wanglei@huawei.com and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## import copy from datetime import datetime import json import os import time import uuid import click from container import Container from dovetail import constants from parser import Parser import report as dt_report import test_runner as dt_test_runner import testcase as dt_testcase from utils.dovetail_config import DovetailConfig as dt_cfg import utils.dovetail_logger as dt_logger import utils.dovetail_utils as dt_utils EXIT_RUN_FAILED = 2 def load_testsuite(testsuite): dt_testcase.Testsuite.load() return dt_testcase.Testsuite.get(testsuite) def run_test(testcase_list, report_flag, logger): report = dt_report.Report() duration = 0 if not testcase_list: logger.warning('No test case will be executed.') return start_time = time.time() for testcase_name in testcase_list: logger.info('>>[testcase]: {}'.format(testcase_name)) testcase = dt_testcase.Testcase.get(testcase_name) run_testcase = True tc_start_time = datetime.fromtimestamp( time.time()).strftime('%Y-%m-%d %H:%M:%S') if run_testcase: testcase.run() tc_stop_time = datetime.fromtimestamp( time.time()).strftime('%Y-%m-%d %H:%M:%S') result = report.check_tc_result(testcase) if os.getenv('OPNFV_CI') == 'true': dt_utils.push_results_to_db(case_name=testcase_name, start_date=tc_start_time, stop_date=tc_stop_time, details=result, logger=logger) if dt_cfg.dovetail_config['stop']: try: if (not result or result['criteria'] == 'FAIL'): logger.info('Stop because {} failed'.format(testcase_name)) return except KeyError as e: logger.error('There is no key {}.'.format(e)) logger.info('Stop because {} failed'.format(testcase_name)) return end_time = time.time() duration = end_time - start_time report.generate(testcase_list, duration) if report_flag: report.save_logs() return def filter_config(input_dict, logger): cli_dict = dt_cfg.dovetail_config['cli'] configs = {} for key in cli_dict: if not cli_dict[key]: continue try: cli_config = cli_dict[key]['config'] if cli_config is None: continue except KeyError: continue for key, value in input_dict.items(): for config_key, config_value in cli_config.items(): value_dict = {} value_dict['value'] = value try: value_dict['path'] = config_value['path'] if key == config_key: configs[key] = value_dict break if key.upper() == config_key: configs[key.upper()] = value_dict break except KeyError as e: logger.exception('KeyError {}.'.format(e)) raise SystemExit(EXIT_RUN_FAILED) if not configs: return None return configs def create_logs(): Container.create_log() Parser.create_log() dt_report.Report.create_log() dt_report.FunctestCrawler.create_log() dt_report.FunctestK8sCrawler.create_log() dt_report.YardstickCrawler.create_log() dt_report.BottlenecksCrawler.create_log() dt_report.OnapVtpCrawler.create_log() dt_report.OnapVvpCrawler.create_log() dt_report.FunctestChecker.create_log() dt_report.FunctestK8sChecker.create_log() dt_report.YardstickChecker.create_log() dt_report.BottlenecksChecker.create_log() dt_report.OnapVtpChecker.create_log() dt_report.OnapVvpChecker.create_log() dt_testcase.Testcase.create_log() dt_testcase.Testsuite.create_log() dt_test_runner.DockerRunner.create_log() dt_test_runner.ShellRunner.create_log() def clean_results_dir(): result_path = dt_cfg.dovetail_config['result_dir'] if os.path.exists(result_path): if os.path.isdir(result_path): cmd = 'rm -rf %s/*' % (result_path) dt_utils.exec_cmd(cmd, exit_on_error=False, exec_msg_on=False) else: print('result_dir in dovetail_config.yml is not a directory.') raise SystemExit(EXIT_RUN_FAILED) def get_result_path(): try: dovetail_home = os.environ['DOVETAIL_HOME'] except Exception: print("ERROR: mandatory env variable 'DOVETAIL_HOME' is not found, " "please set in env_config.sh and source this file before " "running.") return None dt_cfg.dovetail_config['result_dir'] = os.path.join(dovetail_home, 'results') dt_cfg.dovetail_config['images_dir'] = os.path.join(dovetail_home, 'images') dt_cfg.dovetail_config['config_dir'] = os.path.join(dovetail_home, 'pre_config') dt_cfg.dovetail_config['patch_dir'] = os.path.join(dovetail_home, 'patches') dt_cfg.dovetail_config['userconfig_dir'] = os.path.join(dovetail_home, 'userconfig') return dovetail_home def copy_userconfig_files(logger): userconfig_path = dt_cfg.dovetail_config['userconfig_dir'] if not os.path.isdir(userconfig_path): os.makedirs(userconfig_path) cmd = 'cp -r %s/* %s' % (constants.USERCONF_PATH, userconfig_path) dt_utils.exec_cmd(cmd, logger, exit_on_error=False) def copy_patch_files(logger): patch_set_path = dt_cfg.dovetail_config['patch_dir'] if not os.path.isdir(patch_set_path): os.makedirs(patch_set_path) cmd = 'cp -a -r %s/* %s' % (constants.PATCH_PATH, patch_set_path) dt_utils.exec_cmd(cmd, logger, exit_on_error=False) def update_deploy_scenario(logger, **kwargs): if 'deploy_scenario' in kwargs and kwargs['deploy_scenario'] is not None: os.environ['DEPLOY_SCENARIO'] = kwargs['deploy_scenario'] logger.info('DEPLOY_SCENARIO : %s', os.environ['DEPLOY_SCENARIO']) def parse_cli(logger=None, **kwargs): configs = filter_config(kwargs, logger) if configs is not None: dt_cfg.update_config(configs) dt_cfg.dovetail_config['offline'] = kwargs['offline'] dt_cfg.dovetail_config['noclean'] = kwargs['no_clean'] dt_cfg.dovetail_config['stop'] = kwargs['stop'] dt_cfg.dovetail_config['mandatory'] = kwargs['mandatory'] dt_cfg.dovetail_config['optional'] = kwargs['optional'] if kwargs['no_api_validation']: dt_cfg.dovetail_config['no_api_validation'] = True logger.warning('Strict API response validation DISABLED.') else: dt_cfg.dovetail_config['no_api_validation'] = False def check_testcase_list(testcase_list, logger=None): if testcase_list: for tc in testcase_list: if tc not in dt_testcase.Testcase.testcase_list: logger.error('Test case {} is not defined.'.format(tc)) return None return testcase_list logger.error('There is no test case to be executed.') return None def get_testcase_list(logger=None, **kwargs): dt_testcase.Testcase.load() testcase_list = kwargs['testcase'] # If specify 'testcase' on the CLI, ignore 'testsuite' and 'testarea'. In # this case, all test cases are marked as mandatory=false in the result # file because there is no testsuite to relate to. # If 'testcase' is not specified on the CLI, check the combination of # 'testsuite' and 'testarea' if testcase_list: return check_testcase_list(testcase_list, logger) testsuite_validation = False testsuite = kwargs['testsuite'] if testsuite in dt_cfg.dovetail_config['testsuite_supported']: testsuite_validation = True origin_testarea = kwargs['testarea'] testarea_validation, testarea = dt_testcase.Testcase.check_testarea( origin_testarea) if testsuite_validation and testarea_validation: testsuite_yaml = load_testsuite(testsuite) dt_cfg.dovetail_config['version'] = dt_utils.get_value_from_dict( 'version', testsuite_yaml) dt_cfg.dovetail_config['vnf_type'] = dt_utils.get_value_from_dict( 'vnf_type', testsuite_yaml) testcase_list = dt_testcase.Testcase.get_testcases_for_testsuite( testsuite_yaml, testarea) return check_testcase_list(testcase_list, logger) elif not testsuite_validation: logger.error('Test suite {} is not defined.'.format(testsuite)) else: logger.error('Test area {} is not defined.'.format(origin_testarea)) return None def main(*args, **kwargs): """Dovetail compliance test entry!""" build_tag = 'daily-master-%s' % str(uuid.uuid1()) dt_cfg.dovetail_config['build_tag'] = build_tag if not get_result_path(): return clean_results_dir() os.environ['DEBUG'] = 'true' if kwargs['debug'] else 'false' os.environ['OPNFV_CI'] = 'true' if kwargs['opnfv_ci'] else 'false' os.environ['validation'] = 'disabled' \ if kwargs['no_api_validation'] else 'enabled' create_logs() logger = dt_logger.Logger('run').getLogger() logger.info('================================================') logger.info('Dovetail compliance: {}!'.format(kwargs['testsuite'])) logger.info('================================================') logger.info('Build tag: {}'.format(dt_cfg.dovetail_config['build_tag'])) parse_cli(logger, **kwargs) update_deploy_scenario(logger, **kwargs) copy_userconfig_files(logger) copy_patch_files(logger) dt_utils.check_docker_version(logger) testcase_list = get_testcase_list(logger, **kwargs) dovetail_home = os.environ['DOVETAIL_HOME'] testcases_file = os.path.join(dovetail_home, 'results', 'testcases.json') with open(testcases_file, "w") as f: data = {'testsuite': kwargs['testsuite'], 'testcases': testcase_list} f.write(json.dumps(data) + '\n') if not testcase_list: raise SystemExit(EXIT_RUN_FAILED) run_test(testcase_list, kwargs['report'], logger) dt_cfg.load_config_files(constants.CONF_PATH) dovetail_config = copy.deepcopy(dt_cfg.dovetail_config) CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) if dovetail_config['cli']['options'] is not None: for key, value in dovetail_config['cli']['options'].items(): if value is not None: for _, v in value.items(): flags = v['flags'] v.pop('flags') v.pop('path', None) main = click.option(*flags, **v)(main) if dovetail_config['cli']['arguments'] is not None: for key, value in dovetail_config['cli']['arguments'].items(): if value is not None: for _, v in value.items(): flags = v['flags'] v.pop('flags') v.pop('path', None) main = click.argument(flags, **v)(main) main = click.command(context_settings=CONTEXT_SETTINGS)(main) if __name__ == '__main__': main()