diff options
Diffstat (limited to 'dovetail/report.py')
-rw-r--r-- | dovetail/report.py | 536 |
1 files changed, 361 insertions, 175 deletions
diff --git a/dovetail/report.py b/dovetail/report.py index 9d0517b4..ed3f942b 100644 --- a/dovetail/report.py +++ b/dovetail/report.py @@ -1,33 +1,37 @@ #!/usr/bin/env python + +# +# Copyright (c) 2017 grakiss.wanglei@huawei.com and others. # -# grakiss.wanglei@huawei.com # 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 # + from __future__ import division +import collections +import hashlib import json -import urllib2 import re import os import datetime import tarfile import time -from pbr import version +import dovetail.utils.dovetail_logger as dt_logger -import utils.dovetail_logger as dt_logger - -from utils.dovetail_config import DovetailConfig as dt_cfg -import utils.dovetail_utils as dt_utils -from testcase import Testcase +from dovetail.utils.dovetail_config import DovetailConfig as dt_cfg +import dovetail.utils.dovetail_utils as dt_utils +from dovetail.testcase import Testcase class Report(object): - results = {'functest': {}, 'yardstick': {}, 'bottlenecks': {}, 'shell': {}} + results = {'functest': {}, 'yardstick': {}, 'functest-k8s': {}, + 'bottlenecks': {}, 'shell': {}, 'onap-vtp': {}, + 'onap-vvp': {}} logger = None @@ -35,27 +39,77 @@ class Report(object): def create_log(cls): cls.logger = dt_logger.Logger(__name__ + '.Report').getLogger() + def check_tc_result(self, testcase): + result_path = dt_cfg.dovetail_config['result_dir'] + check_results_files = dt_utils.get_value_from_dict( + 'report.check_results_files', testcase.testcase) + if not check_results_files: + self.logger.error("Failed to get 'check_results_files' from config" + " file of test case {}".format(testcase.name())) + self.check_result(testcase) + return None + result_files = [] + for check_results_file in check_results_files: + result_file = os.path.join(result_path, check_results_file) + if not os.path.isfile(result_file): + self.logger.error( + 'Failed to store results with file {}.'. + format(result_file)) + self.check_result(testcase) + return None + else: + result_files.append(result_file) + self.logger.info( + 'Results have been stored with files: {}.'.format(result_files)) + result = self.get_result(testcase, result_files) + self.check_result(testcase, result) + return result + @staticmethod - def check_result(testcase, db_result): + def check_result(testcase, db_result=None): checker = CheckerFactory.create(testcase.validate_type()) if checker is not None: checker.check(testcase, db_result) - @classmethod - def generate_json(cls, testsuite_yaml, testarea, duration): + @staticmethod + def get_checksum(vnf_type): + if vnf_type == 'tosca': + path = os.path.join(dt_cfg.dovetail_config['config_dir'], + os.getenv('CSAR_FILE')) + elif vnf_type == 'heat': + path = os.path.join( + dt_cfg.dovetail_config['config_dir'], + '{}.zip'.format(os.getenv('VNF_ARCHIVE_NAME'))) + + checksum = hashlib.sha256() + + if os.path.isfile(path): + with open(path, 'rb') as f: + for chunk in iter(lambda: f.read(4096), b''): + checksum.update(chunk) + + return checksum.hexdigest() + + def generate_json(self, testcase_list, duration): report_obj = {} - report_obj['version'] = \ - version.VersionInfo('dovetail').version_string() - report_obj['testsuite'] = testsuite_yaml['name'] - # TO DO: once dashboard url settled, adjust accordingly - report_obj['dashboard'] = None + # egeokun: using a hardcoded string instead of pbr version for + # versioning the result file. The version of the results.json is + # logically independent of the release of Dovetail. + report_obj['version'] = dt_cfg.dovetail_config.get('version') report_obj['build_tag'] = dt_cfg.dovetail_config['build_tag'] - report_obj['upload_date'] =\ - datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC") + report_obj['test_date'] =\ + datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC') report_obj['duration'] = duration + vnf_type = dt_cfg.dovetail_config.get('vnf_type') + if vnf_type: + report_obj['vnf_type'] = vnf_type + report_obj['vnf_checksum'] = self.get_checksum(vnf_type) + else: + report_obj['validation'] = os.getenv('validation') report_obj['testcases_list'] = [] - testcase_list = Testcase.get_testcase_list(testsuite_yaml, testarea) + if not testcase_list: + return report_obj for testcase_name in testcase_list: testcase = Testcase.get(testcase_name) testcase_inreport = {} @@ -64,11 +118,22 @@ class Report(object): testcase_inreport['result'] = 'Undefined' testcase_inreport['objective'] = '' testcase_inreport['sub_testcase'] = [] + testcase_inreport['mandatory'] = False + testcase_inreport['portal_key_file'] = '' report_obj['testcases_list'].append(testcase_inreport) continue testcase_inreport['result'] = testcase.passed() testcase_inreport['objective'] = testcase.objective() + try: + vnf_type = testcase.vnf_type() + except Exception: + vnf_type = None + if vnf_type: + report_obj['vnf_type'] = vnf_type + report_obj['vnf_checksum'] = self.get_checksum(vnf_type) + testcase_inreport['mandatory'] = testcase.is_mandatory + testcase_inreport['portal_key_file'] = testcase.portal_key_file() testcase_inreport['sub_testcase'] = [] if testcase.sub_testcase() is not None: for sub_test in testcase.sub_testcase(): @@ -77,45 +142,33 @@ class Report(object): 'result': testcase.sub_testcase_passed(sub_test) }) report_obj['testcases_list'].append(testcase_inreport) - cls.logger.debug(json.dumps(report_obj)) return report_obj - @classmethod - def generate(cls, testsuite_yaml, testarea, duration): - report_data = cls.generate_json(testsuite_yaml, testarea, duration) + def generate(self, testcase_list, duration): + report_data = self.generate_json(testcase_list, duration) + self.save_json_results(report_data) + report_txt = '' report_txt += '\n\nDovetail Report\n' report_txt += 'Version: %s\n' % report_data['version'] - report_txt += 'TestSuite: %s\n' % report_data['testsuite'] - report_txt += 'Result Dashboard: %s\n' % report_data['dashboard'] report_txt += 'Build Tag: %s\n' % report_data['build_tag'] - report_txt += 'Upload Date: %s\n' % report_data['upload_date'] - if report_data['duration'] == 0: - report_txt += 'Duration: %s\n\n' % 'N/A' - else: - report_txt += 'Duration: %.2f s\n\n' % report_data['duration'] + report_txt += 'Test Date: %s\n' % report_data['test_date'] + report_txt += 'Duration: %.2f s\n\n' % report_data['duration'] total_num = 0 pass_num = 0 - sub_report = {} + sub_report = collections.OrderedDict() testcase_num = {} testcase_passnum = {} - for area in dt_cfg.dovetail_config['testarea_supported']: - sub_report[area] = '' - testcase_num[area] = 0 - testcase_passnum[area] = 0 testarea_scope = [] for testcase in report_data['testcases_list']: - pattern = re.compile( - '|'.join(dt_cfg.dovetail_config['testarea_supported'])) - area = pattern.findall(testcase['name']) - if not area: - cls.logger.error("Test case {} not in supported testarea." - .format(testcase['name'])) - return None - area = area[0] - testarea_scope.append(area) + area = testcase['name'].split('.')[1] + if area not in testarea_scope: + testarea_scope.append(area) + sub_report[area] = '' + testcase_num[area] = 0 + testcase_passnum[area] = 0 sub_report[area] += '-%-25s %s\n' %\ (testcase['name'], testcase['result']) if 'sub_testcase' in testcase: @@ -135,21 +188,13 @@ class Report(object): pass_rate = pass_num / total_num report_txt += 'Pass Rate: %.2f%% (%s/%s)\n' %\ (pass_rate * 100, pass_num, total_num) - report_txt += 'Assessed test areas:\n' else: report_txt += \ - 'no testcase or all testcases are skipped in this testsuite' + 'no testcase or all testcases are skipped in this testsuite\n' for key in sub_report: if testcase_num[key] != 0: pass_rate = testcase_passnum[key] / testcase_num[key] - report_txt += '-%-25s pass %.2f%%\n' %\ - (key + ' results:', pass_rate * 100) - elif key in testarea_scope: - report_txt += '-%-25s all skipped\n' % key - for key in sub_report: - if testcase_num[key] != 0: - pass_rate = testcase_passnum[key] / testcase_num[key] report_txt += '%-25s pass rate %.2f%%\n' %\ (key + ':', pass_rate * 100) report_txt += sub_report[key] @@ -157,65 +202,62 @@ class Report(object): report_txt += '%-25s all skipped\n' % key report_txt += sub_report[key] - cls.logger.info(report_txt) - # cls.save(report_txt) + self.logger.info(report_txt) return report_txt - @classmethod - def save_logs(cls): + def save_json_results(self, results): + result_file = os.path.join(dt_cfg.dovetail_config['result_dir'], + dt_cfg.dovetail_config['result_file']) + + try: + with open(result_file, 'w') as f: + f.write(json.dumps(results) + '\n') + except Exception as e: + self.logger.exception('Failed to add result to file {}, ' + 'exception: {}'.format(result_file, e)) + + @staticmethod + def save_logs(): file_suffix = time.strftime('%Y%m%d_%H%M', time.localtime()) - logs_gz = "logs_{}.tar.gz".format(file_suffix) + logs_gz = 'logs_{}.tar.gz'.format(file_suffix) result_dir = dt_cfg.dovetail_config['result_dir'] cwd = os.getcwd() os.chdir(os.path.join(result_dir, '..')) tar_file = os.path.join(result_dir, '..', logs_gz) - with tarfile.open(tar_file, "w:gz") as f_out: + with tarfile.open(tar_file, 'w:gz') as f_out: files = os.listdir(result_dir) for f in files: if f not in ['workspace']: f_out.add(os.path.join('results', f)) os.chdir(cwd) - # save to disk as default - @classmethod - def save(cls, report): - report_file_name = dt_cfg.dovetail_config['report_file'] - try: - with open(os.path.join(dt_cfg.dovetail_config['result_dir'], - report_file_name), 'w') as report_file: - report_file.write(report) - cls.logger.info('Save report to {}'.format(report_file_name)) - except Exception: - cls.logger.exception('Failed to save: {}'.format(report_file_name)) - - @classmethod - def get_result(cls, testcase): + def get_result(self, testcase, check_results_files): validate_testcase = testcase.validate_testcase() type = testcase.validate_type() crawler = CrawlerFactory.create(type) if crawler is None: - cls.logger.error('Crawler is None: {}'.format(testcase.name())) + self.logger.error('Crawler is None: {}'.format(testcase.name())) return None - # if validate_testcase in cls.results[type]: - # return cls.results[type][validate_testcase] - - result = crawler.crawl(testcase) + result = crawler.crawl(testcase, check_results_files) if result is not None: - cls.results[type][validate_testcase] = result - # testcase.script_result_acquired(True) - cls.logger.debug( + self.results[type][validate_testcase] = result + self.logger.debug( 'Test case: {} -> result acquired'.format(validate_testcase)) else: retry = testcase.increase_retry() - cls.logger.debug('Test case: {} -> result acquired retry: {}' - .format(validate_testcase, retry)) + self.logger.debug('Test case: {} -> result acquired retry: {}' + .format(validate_testcase, retry)) return result -class FunctestCrawler(object): +class Crawler(object): + pass + + +class FunctestCrawler(Crawler): logger = None @@ -228,15 +270,10 @@ class FunctestCrawler(object): cls.logger = \ dt_logger.Logger(__name__ + '.FunctestCrawler').getLogger() - def crawl(self, testcase=None): - report_dest = dt_cfg.dovetail_config['report_dest'] - if report_dest.lower() == 'file': - return self.crawl_from_file(testcase) - - if report_dest.lower().startswith('http'): - return self.crawl_from_url(testcase) + def crawl(self, testcase, file_paths): + return self.crawl_from_file(testcase, file_paths[0]) - def crawl_from_file(self, testcase=None): + def crawl_from_file(self, testcase, file_path): dovetail_config = dt_cfg.dovetail_config criteria = 'FAIL' details = {} @@ -245,26 +282,18 @@ class FunctestCrawler(object): duration = 0 testcase_name = testcase.validate_testcase() build_tag = '%s-%s' % (dovetail_config['build_tag'], testcase.name()) - file_path = \ - os.path.join(dovetail_config['result_dir'], - dovetail_config[self.type]['result']['file_path']) if not os.path.exists(file_path): self.logger.error('Result file not found: {}'.format(file_path)) return None - if testcase_name in dt_cfg.dovetail_config['functest_testcase']: - complex_testcase = False - elif testcase_name in dt_cfg.dovetail_config['functest_testsuite']: - complex_testcase = True - else: - self.logger.error( - "Wrong Functest test case {}.".format(testcase_name)) - return None + + sub_testcase_list = testcase.sub_testcase() + complex_testcase = True if sub_testcase_list else False + with open(file_path, 'r') as f: for jsonfile in f: try: data = json.loads(jsonfile) - if (testcase_name == data['case_name'] or - data['project_name'] == "sdnvpn") and \ + if testcase_name == data['case_name'] and \ build_tag == data['build_tag']: criteria = data['criteria'] timestart = data['start_date'] @@ -272,16 +301,10 @@ class FunctestCrawler(object): duration = dt_utils.get_duration(timestart, timestop, self.logger) if complex_testcase: - tests = data['details']['tests'] - failed_num = data['details']['failures'] - success_case = data['details']['success'] - error_case = data['details']['errors'] - skipped_case = data['details']['skipped'] - details = {"tests": tests, - "failures": failed_num, - "success": success_case, - "errors": error_case, - "skipped": skipped_case} + if testcase_name == 'rally_full': + details = self.get_rally_details(data) + else: + details = self.get_details(data) except KeyError as e: self.logger.exception( "Result data don't have key {}.".format(e)) @@ -293,24 +316,56 @@ class FunctestCrawler(object): 'timestop': timestop, 'duration': duration, 'details': details} - self.logger.debug('Results: {}'.format(str(json_results))) + testcase.set_results(json_results) return json_results - def crawl_from_url(self, testcase=None): - url = "%s?case=%s&last=1" % \ - (dt_cfg.dovetail_config['report_dest'], - testcase.validate_testcase()) - self.logger.debug("Query to rest api: {}".format(url)) + def get_details(self, data): try: - data = json.load(urllib2.urlopen(url)) - return data['results'][0] + t_details = data['details'] + details = { + 'tests': t_details['tests_number'], + 'failures': t_details['failures_number'], + 'success': t_details['success'], + 'errors': t_details['failures'], + 'skipped': t_details['skipped'] + } + return details except Exception as e: - self.logger.exception("Cannot read content from the url: {}, " - "exception: {}".format(url, e)) + self.logger.exception("Failed to get details, {}.".format(e)) return None + def get_rally_details(self, data): + try: + t_details = data['details']['modules'][0]['details'] + tests = len(t_details['success']) + len(t_details['failures']) + details = { + 'tests': tests, + 'failures': len(t_details['failures']), + 'success': t_details['success'], + 'errors': t_details['failures'], + 'skipped': [] + } + return details + except Exception as e: + self.logger.exception("Failed to get details, {}.".format(e)) + return None + + +class FunctestK8sCrawler(FunctestCrawler): + + logger = None + + def __init__(self): + self.type = 'functest-k8s' + self.logger.debug('Create crawler: {}'.format(self.type)) + + @classmethod + def create_log(cls): + cls.logger = \ + dt_logger.Logger(__name__ + '.FunctestK8sCrawler').getLogger() + -class YardstickCrawler(object): +class YardstickCrawler(Crawler): logger = None @@ -323,17 +378,10 @@ class YardstickCrawler(object): cls.logger = \ dt_logger.Logger(__name__ + '.YardstickCrawler').getLogger() - def crawl(self, testcase=None): - report_dest = dt_cfg.dovetail_config['report_dest'] - if report_dest.lower() == 'file': - return self.crawl_from_file(testcase) + def crawl(self, testcase, file_paths): + return self.crawl_from_file(testcase, file_paths[0]) - if report_dest.lower().startswith('http'): - return self.crawl_from_url(testcase) - - def crawl_from_file(self, testcase=None): - file_path = os.path.join(dt_cfg.dovetail_config['result_dir'], - testcase.name() + '.out') + def crawl_from_file(self, testcase, file_path): if not os.path.exists(file_path): self.logger.error('Result file not found: {}'.format(file_path)) return None @@ -342,7 +390,8 @@ class YardstickCrawler(object): for jsonfile in f: data = json.loads(jsonfile) try: - criteria = data['result']['criteria'] + criteria = dt_utils.get_value_from_dict('result.criteria', + data) if criteria == 'PASS': valid_tc = testcase.validate_testcase() details = data['result']['testcases'][valid_tc] @@ -352,14 +401,12 @@ class YardstickCrawler(object): except KeyError as e: self.logger.exception('Pass flag not found {}'.format(e)) json_results = {'criteria': criteria} - self.logger.debug('Results: {}'.format(str(json_results))) - return json_results - def crawl_from_url(self, testcase=None): - return None + testcase.set_results(json_results) + return json_results -class BottlenecksCrawler(object): +class BottlenecksCrawler(Crawler): logger = None @@ -372,17 +419,10 @@ class BottlenecksCrawler(object): cls.logger = \ dt_logger.Logger(__name__ + '.BottlenecksCrawler').getLogger() - def crawl(self, testcase=None): - report_dest = dt_cfg.dovetail_config['report_dest'] - if report_dest.lower() == 'file': - return self.crawl_from_file(testcase) + def crawl(self, testcase, file_paths): + return self.crawl_from_file(testcase, file_paths[0]) - if report_dest.lower().startswith('http'): - return self.crawl_from_url(testcase) - - def crawl_from_file(self, testcase=None): - file_path = os.path.join(dt_cfg.dovetail_config['result_dir'], - testcase.name() + '.out') + def crawl_from_file(self, testcase, file_path): if not os.path.exists(file_path): self.logger.error('Result file not found: {}'.format(file_path)) return None @@ -391,7 +431,7 @@ class BottlenecksCrawler(object): for jsonfile in f: data = json.loads(jsonfile) try: - if 'PASS' == data["data_body"]["result"]: + if 'PASS' == data['data_body']['result']: criteria = 'PASS' else: criteria = 'FAIL' @@ -399,24 +439,20 @@ class BottlenecksCrawler(object): except KeyError as e: self.logger.exception('Pass flag not found {}'.format(e)) json_results = {'criteria': criteria} - self.logger.debug('Results: {}'.format(str(json_results))) - return json_results - def crawl_from_url(self, testcase=None): - return None + testcase.set_results(json_results) + return json_results -class ShellCrawler(object): +class ShellCrawler(Crawler): def __init__(self): self.type = 'shell' - def crawl(self, testcase=None): - return self.crawl_from_file(testcase) + def crawl(self, testcase, file_paths): + return self.crawl_from_file(testcase, file_paths[0]) - def crawl_from_file(self, testcase=None): - file_path = os.path.join(dt_cfg.dovetail_config['result_dir'], - testcase.name()) + '.out' + def crawl_from_file(self, testcase, file_path): if not os.path.exists(file_path): return None try: @@ -427,12 +463,108 @@ class ShellCrawler(object): return None +class OnapVtpCrawler(Crawler): + + logger = None + + def __init__(self): + self.type = 'onap-vtp' + self.logger.debug('Create crawler: {}'.format(self.type)) + + @classmethod + def create_log(cls): + cls.logger = dt_logger.Logger(__name__ + '.OnapVtpCrawler').getLogger() + + def crawl(self, testcase, file_paths): + return self.crawl_from_file(testcase, file_paths[0]) + + # The pass result looks like + # { + # "results": [ + # {"property": "results", "value": "{value=SUCCESS}"}, + # {"property": "build_tag", "value": "test"}, + # {"property": "criteria", "value": "PASS"} + # ] + # } + # The fail result looks like + # { + # "results": [ + # {"property": "results", "value": "{value=file doesn't exists}"}, + # {"property": "build_tag", "value": "test"}, + # {"property": "criteria", "value": "FAILED"} + # ] + # } + def crawl_from_file(self, testcase, file_path): + if not os.path.exists(file_path): + self.logger.error('Result file not found: {}'.format(file_path)) + return None + criteria = 'FAIL' + with open(file_path, 'r') as f: + for jsonfile in f: + try: + data = json.loads(jsonfile) + for item in data['results']: + if 'criteria' == item['property']: + if 'PASS' == item['value']: + criteria = 'PASS' + break + else: + self.logger.error('There is no property criteria.') + except KeyError as e: + self.logger.exception('Pass flag not found {}'.format(e)) + except ValueError: + continue + json_results = {'criteria': criteria} + + testcase.set_results(json_results) + return json_results + + +class OnapVvpCrawler(Crawler): + + logger = None + + def __init__(self): + self.type = 'onap-vvp' + self.logger.debug('Create crawler: {}'.format(self.type)) + + @classmethod + def create_log(cls): + cls.logger = dt_logger.Logger(__name__ + '.OnapVvpCrawler').getLogger() + + def crawl(self, testcase, file_paths): + return self.crawl_from_file(testcase, file_paths[0]) + + def crawl_from_file(self, testcase, file_path): + if not os.path.exists(file_path): + self.logger.error('Result file not found: {}'.format(file_path)) + return None + criteria = 'FAIL' + with open(file_path, 'r') as f: + try: + data = json.load(f) + criteria = data['outcome'] + except KeyError as e: + self.logger.exception('Outcome field not found {}'.format(e)) + except ValueError: + self.logger.exception('Result file has invalid format') + json_results = {'criteria': criteria} + + testcase.set_results(json_results) + return json_results + + class CrawlerFactory(object): - CRAWLER_MAP = {'functest': FunctestCrawler, - 'yardstick': YardstickCrawler, - 'bottlenecks': BottlenecksCrawler, - 'shell': ShellCrawler} + CRAWLER_MAP = { + 'functest': FunctestCrawler, + 'yardstick': YardstickCrawler, + 'bottlenecks': BottlenecksCrawler, + 'shell': ShellCrawler, + 'functest-k8s': FunctestK8sCrawler, + 'onap-vtp': OnapVtpCrawler, + 'onap-vvp': OnapVvpCrawler + } @classmethod def create(cls, type): @@ -462,8 +594,8 @@ class FunctestChecker(object): def get_sub_testcase(sub_testcase, result): if not result: return False - sub_testcase = re.sub("\[.*?\]", "", sub_testcase) - reg = sub_testcase + '[\s+\d+]' + sub_testcase = re.sub(r"\[.*?\]", "", sub_testcase) + reg = sub_testcase + r'[\s+\d+]' find_reg = re.compile(reg) for tc in result: match = find_reg.findall(tc) @@ -475,6 +607,12 @@ class FunctestChecker(object): match = find_reg.findall(tc) if match: return True + reg = sub_testcase.rsplit('.', 1)[0] + '$' + find_reg = re.compile(reg) + for tc in result: + match = find_reg.findall(tc) + if match: + return True return False def check(self, testcase, db_result): @@ -493,7 +631,6 @@ class FunctestChecker(object): testcase_passed = 'PASS' for sub_testcase in sub_testcase_list: - self.logger.debug('Check sub_testcase: {}'.format(sub_testcase)) try: if self.get_sub_testcase(sub_testcase, db_result['details']['success']): @@ -512,6 +649,16 @@ class FunctestChecker(object): testcase.passed(testcase_passed) +class FunctestK8sChecker(FunctestChecker): + + logger = None + + @classmethod + def create_log(cls): + cls.logger = \ + dt_logger.Logger(__name__ + '.FunctestK8sChecker').getLogger() + + class YardstickChecker(object): logger = None @@ -558,12 +705,51 @@ class ShellChecker(object): testcase.passed(False) +class OnapVtpChecker(object): + + logger = None + + @classmethod + def create_log(cls): + cls.logger = dt_logger.Logger(__name__ + '.OnapVtpChecker').getLogger() + + @staticmethod + def check(testcase, result): + if not result: + testcase.passed('FAIL') + else: + testcase.passed(result['criteria']) + return + + +class OnapVvpChecker(object): + + logger = None + + @classmethod + def create_log(cls): + cls.logger = dt_logger.Logger(__name__ + '.OnapVvpChecker').getLogger() + + @staticmethod + def check(testcase, result): + if not result: + testcase.passed('FAIL') + else: + testcase.passed(result['criteria']) + return + + class CheckerFactory(object): - CHECKER_MAP = {'functest': FunctestChecker, - 'yardstick': YardstickChecker, - 'bottlenecks': BottlenecksChecker, - 'shell': ShellChecker} + CHECKER_MAP = { + 'functest': FunctestChecker, + 'yardstick': YardstickChecker, + 'bottlenecks': BottlenecksChecker, + 'shell': ShellChecker, + 'functest-k8s': FunctestK8sChecker, + 'onap-vtp': OnapVtpChecker, + 'onap-vvp': OnapVvpChecker + } @classmethod def create(cls, type): |