summaryrefslogtreecommitdiffstats
path: root/dovetail/run.py
diff options
context:
space:
mode:
Diffstat (limited to 'dovetail/run.py')
-rwxr-xr-xdovetail/run.py357
1 files changed, 165 insertions, 192 deletions
diff --git a/dovetail/run.py b/dovetail/run.py
index 1537fb6b..c5281918 100755
--- a/dovetail/run.py
+++ b/dovetail/run.py
@@ -11,135 +11,75 @@
import copy
+from datetime import datetime
+import json
import os
import time
import uuid
import click
-from container import Container
+from dovetail.container import Container
from dovetail import constants
-from parser import Parser
-from report import BottlenecksChecker, FunctestChecker, YardstickChecker
-from report import BottlenecksCrawler, FunctestCrawler, YardstickCrawler
-from report import Report
-from test_runner import DockerRunner, ShellRunner
-from testcase import Testcase
-from testcase import Testsuite
-from utils.dovetail_config import DovetailConfig as dt_cfg
-import utils.dovetail_logger as dt_logger
-import utils.dovetail_utils as dt_utils
+from dovetail.parser import Parser
+import dovetail.report as dt_report
+import dovetail.test_runner as dt_test_runner
+import dovetail.testcase as dt_testcase
+from dovetail.utils.dovetail_config import DovetailConfig as dt_cfg
+import dovetail.utils.dovetail_logger as dt_logger
+import dovetail.utils.dovetail_utils as dt_utils
-
-def load_testsuite(testsuite):
- Testsuite.load()
- return Testsuite.get(testsuite)
+EXIT_RUN_FAILED = 2
-def load_testcase():
- Testcase.load()
+def load_testsuite(testsuite):
+ dt_testcase.Testsuite.load()
+ return dt_testcase.Testsuite.get(testsuite)
-def run_test(testsuite, testarea, logger, kwargs):
- testcase_list = Testcase.get_testcase_list(testsuite, testarea)
+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 = Testcase.get(testcase_name)
- if testcase is None:
- logger.error('Test case {} is not defined in testcase folder, '
- 'skipping.'.format(testcase_name))
- continue
+ testcase = dt_testcase.Testcase.get(testcase_name)
run_testcase = True
- # if testcase.exceed_max_retry_times():
- # run_testcase = False
-
- # if testcase.script_result_acquired():
- # run_testcase = False
-
+ tc_start_time = datetime.fromtimestamp(
+ time.time()).strftime('%Y-%m-%d %H:%M:%S')
if run_testcase:
testcase.run()
-
- stop_on_fail = check_tc_result(testcase, logger)
- try:
- if (not stop_on_fail or stop_on_fail['criteria'] == "FAIL") \
- and kwargs['stop']:
- return "stop_on_fail"
- except KeyError as e:
- logger.error("There is no key {}.".format(e))
+ 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
- return duration
-
-
-def check_tc_result(testcase, logger):
- result_dir = dt_cfg.dovetail_config['result_dir']
- validate_type = testcase.validate_type()
- functest_result = dt_cfg.dovetail_config['functest']['result']['file_path']
- dovetail_result = os.path.join(result_dir,
- dt_cfg.dovetail_config['result_file'])
- if dt_cfg.dovetail_config['report_dest'].startswith("http"):
- if dt_utils.store_db_results(dt_cfg.dovetail_config['report_dest'],
- dt_cfg.dovetail_config['build_tag'],
- testcase.name(), dovetail_result,
- logger):
- logger.info("Results have been pushed to database and stored "
- "with local file {}.".format(dovetail_result))
- else:
- logger.error("Failed to push results to database.")
- if dt_cfg.dovetail_config['report_dest'] == "file":
- if validate_type.lower() == 'yardstick':
- result_file = os.path.join(result_dir, testcase.name() + '.out')
- elif validate_type.lower() == 'functest':
- result_file = os.path.join(result_dir, functest_result)
- elif validate_type.lower() == 'bottlenecks':
- result_file = os.path.join(result_dir, testcase.name() + '.out')
- else:
- logger.error("Don't support {} now.".format(validate_type))
- return
- if os.path.isfile(result_file):
- logger.info(
- "Results have been stored with file {}.".format(result_file))
- else:
- logger.error(
- "Failed to store results with file {}.".format(result_file))
- result = Report.get_result(testcase)
- Report.check_result(testcase, result)
- return result
-
-
-def validate_input(input_dict, check_dict, logger):
- func_tag = input_dict['functest_tag']
- yard_tag = input_dict['yardstick_tag']
- # bott_tag = input_dict['bott_tag']
- valid_functest_tags = check_dict['valid_functest_tags']
- valid_yardstick_tags = check_dict['valid_yardstick_tags']
- if func_tag is not None and func_tag not in valid_functest_tags:
- logger.error("The input option 'functest_tag' can't be '{}', "
- "valid values are {}.".format(func_tag,
- valid_functest_tags))
- raise SystemExit(1)
- if yard_tag is not None and yard_tag not in valid_yardstick_tags:
- logger.error("The input option 'yardstick_tag' can't be '{}', "
- "valid values are {}.".format(yard_tag,
- valid_yardstick_tags))
- raise SystemExit(1)
- # if bott_tag is not None and bott_tag not in valid_tag:
- # logger.error("The input option 'bott_tag' can't be {}, "
- # "valid values are {}.".format(bott_tag, valid_tag))
- # raise SystemExit(1)
-
- # for 'report' option
- report = input_dict['report']
- if report:
- if report != "default":
- if not (report.startswith("http") or report == "file"):
- logger.error("Report type can't be {}, valid types are 'file' "
- "and 'http'.".format(input_dict['report']))
- raise SystemExit(1)
+ report.generate(testcase_list, duration)
+ if report_flag:
+ report.save_logs()
+ return
def filter_config(input_dict, logger):
@@ -168,7 +108,7 @@ def filter_config(input_dict, logger):
break
except KeyError as e:
logger.exception('KeyError {}.'.format(e))
- raise SystemExit(1)
+ raise SystemExit(EXIT_RUN_FAILED)
if not configs:
return None
return configs
@@ -177,54 +117,62 @@ def filter_config(input_dict, logger):
def create_logs():
Container.create_log()
Parser.create_log()
- Report.create_log()
- FunctestCrawler.create_log()
- YardstickCrawler.create_log()
- BottlenecksCrawler.create_log()
- FunctestChecker.create_log()
- YardstickChecker.create_log()
- BottlenecksChecker.create_log()
- Testcase.create_log()
- Testsuite.create_log()
- DockerRunner.create_log()
- ShellRunner.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 = 'sudo rm -rf %s/*' % (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(1)
+ 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"]
+ 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
- result_path = os.path.join(dovetail_home, 'results')
- dt_cfg.dovetail_config['result_dir'] = result_path
+ dt_cfg.dovetail_config['result_dir'] = os.path.join(dovetail_home,
+ 'results')
dt_cfg.dovetail_config['images_dir'] = os.path.join(dovetail_home,
'images')
- pre_config_path = os.path.join(dovetail_home, 'pre_config')
- patch_set_path = os.path.join(dovetail_home, 'patch')
- dt_cfg.dovetail_config['config_dir'] = pre_config_path
- dt_cfg.dovetail_config['patch_dir'] = patch_set_path
+ 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):
- pre_config_path = dt_cfg.dovetail_config['config_dir']
- if not os.path.isdir(pre_config_path):
- os.makedirs(pre_config_path)
- cmd = 'sudo cp -r %s/* %s' % (constants.USERCONF_PATH, pre_config_path)
+ 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)
@@ -232,90 +180,115 @@ 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 = 'sudo cp -r %s/* %s' % (constants.PATCH_PATH, 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)
-# env_init can source some env variable used in dovetail, such as
-# when https+credential used, OS_CACERT
-def env_init(logger):
- openrc = os.path.join(dt_cfg.dovetail_config['config_dir'],
- dt_cfg.dovetail_config['env_file'])
- if not os.path.isfile(openrc):
- logger.error("File {} does not exist.".format(openrc))
- dt_utils.source_env(openrc)
+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 check_hosts_file(logger):
- hosts_file = os.path.join(dt_cfg.dovetail_config['config_dir'],
- 'hosts.yaml')
- if not os.path.isfile(hosts_file):
- logger.warn("There is no hosts file {}, may be some issues with "
- "domain name resolution.".format(hosts_file))
+
+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())
+ 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()
- if kwargs['debug']:
- os.environ['DEBUG'] = 'true'
+ 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']))
- env_init(logger)
+ parse_cli(logger, **kwargs)
+ update_deploy_scenario(logger, **kwargs)
copy_userconfig_files(logger)
copy_patch_files(logger)
dt_utils.check_docker_version(logger)
- dt_utils.get_openstack_endpoint(logger)
- validate_input(kwargs, dt_cfg.dovetail_config['validate_input'], logger)
- check_hosts_file(logger)
- configs = filter_config(kwargs, logger)
- if configs is not None:
- dt_cfg.update_config(configs)
+ testcase_list = get_testcase_list(logger, **kwargs)
- if kwargs['report']:
- if(kwargs['report'].endswith('/')):
- kwargs['report'] = kwargs['report'][0:kwargs['report'].rfind('/')]
- if(kwargs['report'] == "default"):
- host_ip = os.popen(
- "/sbin/ip route|awk '/default/ { print $3 }'").read().rstrip()
- kwargs['report'] = "http://" + host_ip + ":8000/api/v1/results"
- dt_cfg.dovetail_config['report_dest'] = kwargs['report']
- dt_cfg.update_cmds()
-
- if kwargs['offline']:
- dt_cfg.dovetail_config['offline'] = True
- else:
- dt_cfg.dovetail_config['offline'] = False
+ 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')
- dt_utils.get_hardware_info(logger)
+ if not testcase_list:
+ raise SystemExit(EXIT_RUN_FAILED)
- origin_testarea = kwargs['testarea']
- testsuite_validation = False
- if kwargs['testsuite'] in dt_cfg.dovetail_config['testsuite_supported']:
- testsuite_validation = True
- testarea_validation, testarea = Testcase.check_testarea(origin_testarea)
- if testsuite_validation and testarea_validation:
- testsuite_yaml = load_testsuite(kwargs['testsuite'])
- load_testcase()
- duration = run_test(testsuite_yaml, testarea, logger, kwargs)
- if (dt_cfg.dovetail_config['report_dest'] == "file" and
- duration != "stop_on_fail"):
- Report.generate(testsuite_yaml, testarea, duration)
- if (dt_cfg.dovetail_config['report_dest'].startswith("http") and
- duration != "stop_on_fail"):
- Report.save_logs()
- else:
- logger.error('Invalid input commands, testsuite {} testarea {}'
- .format(kwargs['testsuite'], origin_testarea))
+ run_test(testcase_list, kwargs['report'], logger)
dt_cfg.load_config_files(constants.CONF_PATH)
@@ -324,7 +297,7 @@ 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 k, v in value.items():
+ for _, v in value.items():
flags = v['flags']
v.pop('flags')
v.pop('path', None)
@@ -332,7 +305,7 @@ if dovetail_config['cli']['options'] is not None:
if dovetail_config['cli']['arguments'] is not None:
for key, value in dovetail_config['cli']['arguments'].items():
if value is not None:
- for k, v in value.items():
+ for _, v in value.items():
flags = v['flags']
v.pop('flags')
v.pop('path', None)