diff options
Diffstat (limited to 'dovetail/report.py')
-rw-r--r-- | dovetail/report.py | 144 |
1 files changed, 114 insertions, 30 deletions
diff --git a/dovetail/report.py b/dovetail/report.py index 0d83831d..fa6a0ba4 100644 --- a/dovetail/report.py +++ b/dovetail/report.py @@ -13,6 +13,7 @@ import urllib2 import re import os import datetime +import tarfile from pbr import version @@ -25,7 +26,7 @@ from testcase import Testcase class Report(object): - results = {'functest': {}, 'yardstick': {}, 'shell': {}} + results = {'functest': {}, 'yardstick': {}, 'bottlenecks': {}, 'shell': {}} logger = None @@ -112,8 +113,8 @@ class Report(object): '|'.join(dt_cfg.dovetail_config['testarea_supported'])) area = pattern.findall(testcase['name']) if not area: - cls.logger.error("testcase %s not in supported testarea", - testcase['name']) + cls.logger.error("Test case {} not in supported testarea." + .format(testcase['name'])) return None area = area[0] testarea_scope.append(area) @@ -162,6 +163,17 @@ class Report(object): # cls.save(report_txt) return report_txt + @classmethod + def save_logs(cls): + logs_gz = "logs.tar.gz" + result_dir = dt_cfg.dovetail_config['result_dir'] + + with tarfile.open(os.path.join(result_dir, logs_gz), "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(result_dir, f)) + # save to disk as default @classmethod def save(cls, report): @@ -170,9 +182,9 @@ class Report(object): 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 %s', report_file_name) + cls.logger.info('Save report to {}'.format(report_file_name)) except Exception: - cls.logger.error('Failed to save: %s', report_file_name) + cls.logger.exception('Failed to save: {}'.format(report_file_name)) @classmethod def get_result(cls, testcase): @@ -180,7 +192,7 @@ class Report(object): type = testcase.validate_type() crawler = CrawlerFactory.create(type) if crawler is None: - cls.logger.error('crawler is None:%s', testcase.name()) + cls.logger.error('Crawler is None: {}'.format(testcase.name())) return None # if validate_testcase in cls.results[type]: @@ -191,12 +203,12 @@ class Report(object): if result is not None: cls.results[type][validate_testcase] = result # testcase.script_result_acquired(True) - cls.logger.debug('testcase: %s -> result acquired', - validate_testcase) + cls.logger.debug( + 'Test case: {} -> result acquired'.format(validate_testcase)) else: retry = testcase.increase_retry() - cls.logger.debug('testcase: %s -> result acquired retry:%d', - validate_testcase, retry) + cls.logger.debug('Test case: {} -> result acquired retry: {}' + .format(validate_testcase, retry)) return result @@ -206,7 +218,7 @@ class FunctestCrawler(object): def __init__(self): self.type = 'functest' - self.logger.debug('create crawler:%s', self.type) + self.logger.debug('Create crawler: {}'.format(self.type)) @classmethod def create_log(cls): @@ -234,14 +246,15 @@ class FunctestCrawler(object): os.path.join(dovetail_config['result_dir'], dovetail_config[self.type]['result']['file_path']) if not os.path.exists(file_path): - self.logger.info('result file not found: %s', 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 %s.", testcase_name) + self.logger.error( + "Wrong Functest test case {}.".format(testcase_name)) return None with open(file_path, 'r') as f: for jsonfile in f: @@ -264,7 +277,8 @@ class FunctestCrawler(object): "errors": error_case, "skipped": skipped_case} except KeyError as e: - self.logger.error("Key error, exception: %s", e) + self.logger.exception( + "Result data don't have key {}.".format(e)) return None except ValueError: continue @@ -273,20 +287,20 @@ class FunctestCrawler(object): 'timestop': timestop, 'duration': duration, 'details': details} - self.logger.debug('Results: %s', str(json_results)) + self.logger.debug('Results: {}'.format(str(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: %s", url) + self.logger.debug("Query to rest api: {}".format(url)) try: data = json.load(urllib2.urlopen(url)) return data['results'][0] except Exception as e: - self.logger.error("Cannot read content from the url: %s, " - "exception: %s", url, e) + self.logger.exception("Cannot read content from the url: {}, " + "exception: {}".format(url, e)) return None @@ -296,7 +310,7 @@ class YardstickCrawler(object): def __init__(self): self.type = 'yardstick' - self.logger.debug('create crawler:%s', self.type) + self.logger.debug('Create crawler: {}'.format(self.type)) @classmethod def create_log(cls): @@ -313,9 +327,9 @@ class YardstickCrawler(object): def crawl_from_file(self, testcase=None): file_path = os.path.join(dt_cfg.dovetail_config['result_dir'], - testcase.validate_testcase() + '.out') + testcase.name() + '.out') if not os.path.exists(file_path): - self.logger.info('result file not found: %s', file_path) + self.logger.error('Result file not found: {}'.format(file_path)) return None criteria = 'FAIL' with open(file_path, 'r') as f: @@ -327,9 +341,57 @@ class YardstickCrawler(object): if 1 == v: criteria = 'PASS' except KeyError as e: - self.logger.error('pass flag not found %s', e) + self.logger.exception( + 'Pass flag not found {}'.format(e)) json_results = {'criteria': criteria} - self.logger.debug('Results: %s', str(json_results)) + self.logger.debug('Results: {}'.format(str(json_results))) + return json_results + + def crawl_from_url(self, testcase=None): + return None + + +class BottlenecksCrawler(object): + + logger = None + + def __init__(self): + self.type = 'bottlenecks' + self.logger.debug('Create crawler: {}'.format(self.type)) + + @classmethod + def create_log(cls): + 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) + + 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') + 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: + data = json.loads(jsonfile) + try: + if 'PASS' == data["data_body"]["result"]: + criteria = 'PASS' + else: + criteria = 'FAIL' + break + 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): @@ -361,6 +423,7 @@ class CrawlerFactory(object): CRAWLER_MAP = {'functest': FunctestCrawler, 'yardstick': YardstickCrawler, + 'bottlenecks': BottlenecksCrawler, 'shell': ShellCrawler} @classmethod @@ -394,14 +457,16 @@ class FunctestChecker(object): sub_testcase = re.sub("\[.*?\]", "", sub_testcase) reg = sub_testcase + '[\s+\d+]' find_reg = re.compile(reg) - match = find_reg.findall(result) - if match: - return True + for tc in result: + match = find_reg.findall(tc) + if match: + return True reg = sub_testcase + '$' find_reg = re.compile(reg) - match = find_reg.findall(result) - if match: - return True + for tc in result: + match = find_reg.findall(tc) + if match: + return True return False def check(self, testcase, db_result): @@ -420,7 +485,7 @@ class FunctestChecker(object): testcase_passed = 'SKIP' for sub_testcase in sub_testcase_list: - self.logger.debug('check sub_testcase:%s', sub_testcase) + self.logger.debug('Check sub_testcase: {}'.format(sub_testcase)) try: if self.get_sub_testcase(sub_testcase, db_result['details']['errors']): @@ -463,6 +528,24 @@ class YardstickChecker(object): return +class BottlenecksChecker(object): + + logger = None + + @classmethod + def create_log(cls): + cls.logger = \ + dt_logger.Logger(__name__ + '.BottlenecksChecker').getLogger() + + @staticmethod + def check(testcase, result): + if not result: + testcase.passed('FAIL') + else: + testcase.passed(result['criteria']) + return + + class ShellChecker(object): @staticmethod @@ -477,6 +560,7 @@ class CheckerFactory(object): CHECKER_MAP = {'functest': FunctestChecker, 'yardstick': YardstickChecker, + 'bottlenecks': BottlenecksChecker, 'shell': ShellChecker} @classmethod |