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