Merge "Support for customized tempest case list"
[functest.git] / testcases / VIM / OpenStack / CI / libraries / run_tempest.py
1 #!/usr/bin/env python
2 #
3 # Description:
4 #    Runs tempest and pushes the results to the DB
5 #
6 # Authors:
7 #    morgan.richomme@orange.com
8 #    jose.lausuch@ericsson.com
9 #
10
11 import argparse
12 import json
13 import logging
14 import os
15 import re
16 import requests
17 import subprocess
18 import sys
19 import yaml
20
21 modes = ['full', 'smoke', 'baremetal', 'compute', 'data_processing',
22          'identity', 'image', 'network', 'object_storage', 'orchestration',
23          'telemetry', 'volume', 'custom']
24
25 """ tests configuration """
26 parser = argparse.ArgumentParser()
27 parser.add_argument("-d", "--debug", help="Debug mode",  action="store_true")
28 parser.add_argument("-m", "--mode", help="Tempest test mode [smoke, all]",
29                     default="smoke")
30 parser.add_argument("-r", "--report",
31                     help="Create json result file",
32                     action="store_true")
33
34 args = parser.parse_args()
35
36 """ logging configuration """
37 logger = logging.getLogger('run_tempest')
38 logger.setLevel(logging.DEBUG)
39
40 ch = logging.StreamHandler()
41 if args.debug:
42     ch.setLevel(logging.DEBUG)
43 else:
44     ch.setLevel(logging.INFO)
45
46 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
47 ch.setFormatter(formatter)
48 logger.addHandler(ch)
49
50 REPO_PATH=os.environ['repos_dir']+'/functest/'
51 if not os.path.exists(REPO_PATH):
52     logger.error("Functest repository directory not found '%s'" % REPO_PATH)
53     exit(-1)
54 sys.path.append(REPO_PATH + "testcases/")
55 import functest_utils
56
57 with open(REPO_PATH+"testcases/config_functest.yaml") as f:
58     functest_yaml = yaml.safe_load(f)
59 f.close()
60 TEST_DB = functest_yaml.get("results").get("test_db_url")
61
62 MODE = "smoke"
63
64
65 def get_info(file_result):
66     test_run = ""
67     duration = ""
68     test_failed = ""
69
70     p = subprocess.Popen('cat tempest.log',
71                          shell=True, stdout=subprocess.PIPE,
72                          stderr=subprocess.STDOUT)
73     for line in p.stdout.readlines():
74         # print line,
75         if (len(test_run) < 1):
76             test_run = re.findall("[0-9]*\.[0-9]*s", line)
77         if (len(duration) < 1):
78             duration = re.findall("[0-9]*\ tests", line)
79         regexp = r"(failures=[0-9]+)"
80         if (len(test_failed) < 1):
81             test_failed = re.findall(regexp, line)
82
83     retval = p.wait()
84
85     logger.debug("test_run:"+test_run)
86     logger.debug("duration:"+duration)
87
88
89 def push_results_to_db(payload, module, pod_name):
90
91     # TODO move DB creds into config file
92     url = TEST_DB + "/results"
93     installer = functest_utils.get_installer_type(logger)
94     git_version = functest_utils.get_git_branch(REPO_PATH)
95     logger.info("Pushing results to DB: '%s'." % url)
96
97     params = {"project_name": "functest", "case_name": "Tempest",
98               "pod_name": str(pod_name), 'installer': installer,
99               "version": git_version, 'details': payload}
100     headers = {'Content-Type': 'application/json'}
101
102     r = requests.post(url, data=json.dumps(params), headers=headers)
103     logger.debug(r)
104
105
106 def run_tempest(OPTION):
107     #
108     # the "main" function of the script which launches Rally to run Tempest
109     # :param option: tempest option (smoke, ..)
110     # :return: void
111     #
112     logger.info("Starting Tempest test suite: '%s'." % OPTION)
113     cmd_line = "rally verify start "+OPTION
114     logger.debug('Executing command : {}'.format(cmd_line))
115     subprocess.call(cmd_line, shell=True, stderr=subprocess.STDOUT)
116
117     cmd_line = "rally verify list"
118     logger.debug('Executing command : {}'.format(cmd_line))
119     cmd = os.popen(cmd_line)
120     output = (((cmd.read()).splitlines()[3]).replace(" ", "")).split("|")
121     # Format:
122     # | UUID | Deployment UUID | smoke | tests | failures | Created at |
123     # Duration | Status  |
124     num_tests = output[4]
125     num_failures = output[5]
126     time_start = output[6]
127     duration = output[7]
128     # Compute duration (lets assume it does not take more than 60 min)
129     dur_min=int(duration.split(':')[1])
130     dur_sec_float=float(duration.split(':')[2])
131     dur_sec_int=int(round(dur_sec_float,0))
132     dur_sec_int = dur_sec_int + 60 * dur_min
133
134     # Generate json results for DB
135     json_results = {"timestart": time_start, "duration": dur_sec_int,
136                     "tests": int(num_tests), "failures": int(num_failures)}
137     logger.info("Results: "+str(json_results))
138     pod_name = functest_utils.get_pod_name(logger)
139
140     # Push results in payload of testcase
141     if args.report:
142         logger.debug("Push result into DB")
143         push_results_to_db(json_results, MODE, pod_name)
144
145
146 def main():
147     global MODE
148     if not (args.mode):
149         MODE = "smoke"
150     elif not (args.mode in modes):
151         logger.error("Tempest mode not valid. Possible values are:\n"
152                      + str(modes))
153         exit(-1)
154     elif (args.mode == 'custom'):
155         MODE = "--tests-file "+REPO_PATH+"testcases/VIM/OpenStack/CI/custom_tests/test_list.txt"
156     else:
157         MODE = "--set "+args.mode
158
159     run_tempest(MODE)
160
161
162 if __name__ == '__main__':
163     main()