Merge "modify old naming Testcase_base to TestCase"
[functest.git] / functest / opnfv_tests / openstack / refstack_client / refstack_client.py
1 #!/usr/bin/env python
2
3 # matthew.lijun@huawei.com wangwulin@huawei.com
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 import argparse
9 import os
10 import re
11 import sys
12 import subprocess
13 import time
14
15 from functest.core import testcase
16 from functest.opnfv_tests.openstack.tempest import conf_utils
17 from functest.utils.constants import CONST
18 import functest.utils.functest_logger as ft_logger
19 import functest.utils.functest_utils as ft_utils
20 from tempest_conf import TempestConf
21
22 """ logging configuration """
23 logger = ft_logger.Logger("refstack_defcore").getLogger()
24
25
26 class RefstackClient(testcase.TestCase):
27
28     def __init__(self):
29         super(RefstackClient, self).__init__()
30         self.case_name = "refstack_defcore"
31         self.FUNCTEST_TEST = CONST.dir_functest_test
32         self.CONF_PATH = CONST.refstack_tempest_conf_path
33         self.DEFCORE_LIST = CONST.refstack_defcore_list
34         self.confpath = os.path.join(self.FUNCTEST_TEST,
35                                      self.CONF_PATH)
36         self.defcorelist = os.path.join(self.FUNCTEST_TEST,
37                                         self.DEFCORE_LIST)
38
39     def source_venv(self):
40
41         cmd = ("cd {0};"
42                ". .venv/bin/activate;"
43                "cd -;".format(CONST.dir_refstack_client))
44         ft_utils.execute_command(cmd)
45
46     def run_defcore(self, conf, testlist):
47         logger.debug("Generating test case list...")
48
49         cmd = ("cd {0};"
50                "./refstack-client test -c {1} -v --test-list {2};"
51                "cd -;".format(CONST.dir_refstack_client,
52                               conf,
53                               testlist))
54         ft_utils.execute_command(cmd)
55
56     def run_defcore_default(self):
57         logger.debug("Generating test case list...")
58
59         cmd = ("cd {0};"
60                "./refstack-client test -c {1} -v --test-list {2};"
61                "cd -;".format(CONST.dir_refstack_client,
62                               self.confpath,
63                               self.defcorelist))
64         logger.info("Starting Refstack_defcore test case: '%s'." % cmd)
65
66         header = ("Refstack environment:\n"
67                   "  SUT: %s\n  Scenario: %s\n  Node: %s\n  Date: %s\n" %
68                   (CONST.INSTALLER_TYPE,
69                    CONST.DEPLOY_SCENARIO,
70                    CONST.NODE_NAME,
71                    time.strftime("%a %b %d %H:%M:%S %Z %Y")))
72
73         f_stdout = open(
74             os.path.join(conf_utils.REFSTACK_RESULTS_DIR,
75                          "refstack.log"), 'w+')
76         f_env = open(os.path.join(conf_utils.REFSTACK_RESULTS_DIR,
77                                   "environment.log"), 'w+')
78         f_env.write(header)
79
80         p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
81                              stderr=subprocess.STDOUT, bufsize=1)
82
83         with p.stdout:
84             for line in iter(p.stdout.readline, b''):
85                 if 'Tests' in line:
86                     break
87                 if re.search("\} tempest\.", line):
88                     logger.info(line.replace('\n', ''))
89                 f_stdout.write(line)
90         p.wait()
91
92         f_stdout.close()
93         f_env.close()
94
95     def parse_refstack_result(self):
96         try:
97             with open(os.path.join(conf_utils.REFSTACK_RESULTS_DIR,
98                                    "refstack.log"), 'r') as logfile:
99                 output = logfile.read()
100
101             for match in re.findall("Ran: (\d+) tests in (\d+\.\d{4}) sec.",
102                                     output):
103                 num_tests = match[0]
104                 logger.info("Ran: %s tests in %s sec." % (num_tests, match[1]))
105             for match in re.findall("(- Passed: )(\d+)", output):
106                 num_success = match[1]
107                 logger.info("".join(match))
108             for match in re.findall("(- Skipped: )(\d+)", output):
109                 num_skipped = match[1]
110                 logger.info("".join(match))
111             for match in re.findall("(- Failed: )(\d+)", output):
112                 num_failures = match[1]
113                 logger.info("".join(match))
114             success_testcases = ""
115             for match in re.findall(r"\{0\}(.*?)[. ]*ok", output):
116                 success_testcases += match + ", "
117             failed_testcases = ""
118             for match in re.findall(r"\{0\}(.*?)[. ]*FAILED", output):
119                 failed_testcases += match + ", "
120             skipped_testcases = ""
121             for match in re.findall(r"\{0\}(.*?)[. ]*SKIPPED:", output):
122                 skipped_testcases += match + ", "
123
124             num_executed = int(num_tests) - int(num_skipped)
125             success_rate = 100 * int(num_success) / int(num_executed)
126
127             self.details = {"tests": int(num_tests),
128                             "failures": int(num_failures),
129                             "success": success_testcases,
130                             "errors": failed_testcases,
131                             "skipped": skipped_testcases}
132         except Exception:
133             success_rate = 0
134
135         self.criteria = ft_utils.check_success_rate(
136             self.case_name, success_rate)
137         logger.info("Testcase %s success_rate is %s%%, is marked as %s"
138                     % (self.case_name, success_rate, self.criteria))
139
140     def run(self):
141         '''used for functest command line,
142            functest testcase run refstack_defcore'''
143         self.start_time = time.time()
144
145         if not os.path.exists(conf_utils.REFSTACK_RESULTS_DIR):
146             os.makedirs(conf_utils.REFSTACK_RESULTS_DIR)
147
148         try:
149             tempestconf = TempestConf()
150             tempestconf.generate_tempestconf()
151             self.source_venv()
152             self.run_defcore_default()
153             self.parse_refstack_result()
154             res = testcase.TestCase.EX_OK
155         except Exception as e:
156             logger.error('Error with run: %s', e)
157             res = testcase.TestCase.EX_RUN_ERROR
158
159         self.stop_time = time.time()
160         return res
161
162     def _prep_test(self):
163         '''Check that the config file exists.'''
164         if not os.path.isfile(self.confpath):
165             logger.error("Conf file not valid: %s" % self.confpath)
166         if not os.path.isfile(self.testlist):
167             logger.error("testlist file not valid: %s" % self.testlist)
168
169     def main(self, **kwargs):
170         '''used for manually running,
171            python refstack_client.py -c <tempest_conf_path>
172            --testlist <testlist_path>
173            can generate a reference tempest.conf by
174            python tempest_conf.py
175         '''
176         try:
177             self.confpath = kwargs['config']
178             self.testlist = kwargs['testlist']
179         except KeyError as e:
180             logger.error("Cannot run refstack client. Please check "
181                          "%s", e)
182             return self.EX_RUN_ERROR
183         try:
184             self.source_venv()
185             self._prep_test()
186             self.run_defcore(self.confpath, self.testlist)
187             res = testcase.TestcaseBase.EX_OK
188         except Exception as e:
189             logger.error('Error with run: %s', e)
190             res = testcase.TestCase.EX_RUN_ERROR
191
192         return res
193
194
195 class RefstackClientParser(testcase.TestCase):
196
197     def __init__(self):
198         super(RefstackClientParser, self).__init__()
199         self.FUNCTEST_TEST = CONST.dir_functest_test
200         self.CONF_PATH = CONST.refstack_tempest_conf_path
201         self.DEFCORE_LIST = CONST.refstack_defcore_list
202         self.confpath = os.path.join(self.FUNCTEST_TEST,
203                                      self.CONF_PATH)
204         self.defcorelist = os.path.join(self.FUNCTEST_TEST,
205                                         self.DEFCORE_LIST)
206         self.parser = argparse.ArgumentParser()
207         self.parser.add_argument(
208             '-c', '--config',
209             help='the file path of tempest.conf',
210             default=self.confpath)
211         self.parser.add_argument(
212             '-t', '--testlist',
213             help='Specify the file path or URL of a test list text file. '
214                  'This test list will contain specific test cases that '
215                  'should be tested.',
216             default=self.defcorelist)
217
218     def parse_args(self, argv=[]):
219         return vars(self.parser.parse_args(argv))
220
221
222 if __name__ == '__main__':
223     refstackclient = RefstackClient()
224     parser = RefstackClientParser()
225     args = parser.parse_args(sys.argv[1:])
226     try:
227         result = refstackclient.main(**args)
228         if result != testcase.TestCase.EX_OK:
229             sys.exit(result)
230     except Exception:
231         sys.exit(testcase.TestCase.EX_RUN_ERROR)