Merge "Consider criteria as exit condition in odl test"
[functest.git] / functest / opnfv_tests / Controllers / ODL / OpenDaylightTesting.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2016 Orange and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 import argparse
11 import errno
12 import fileinput
13 import os
14 import re
15 import sys
16 import urlparse
17
18 from robot.api import ExecutionResult, ResultVisitor
19 from robot.errors import RobotError
20 import robot.run
21 from robot.utils.robottime import timestamp_to_secs
22
23 from functest.core import TestCasesBase
24 import functest.utils.functest_logger as ft_logger
25 import functest.utils.openstack_utils as op_utils
26 import functest.utils.functest_constants as ft_constants
27
28
29 class ODLResultVisitor(ResultVisitor):
30
31     def __init__(self):
32         self._data = []
33
34     def visit_test(self, test):
35         output = {}
36         output['name'] = test.name
37         output['parent'] = test.parent.name
38         output['status'] = test.status
39         output['startime'] = test.starttime
40         output['endtime'] = test.endtime
41         output['critical'] = test.critical
42         output['text'] = test.message
43         output['elapsedtime'] = test.elapsedtime
44         self._data.append(output)
45
46     def get_data(self):
47         return self._data
48
49
50 class ODLTestCases(TestCasesBase.TestCasesBase):
51
52     repos = ft_constants.REPOS_DIR
53     odl_test_repo = os.path.join(repos, "odl_test")
54     neutron_suite_dir = os.path.join(odl_test_repo,
55                                      "csit/suites/openstack/neutron")
56     basic_suite_dir = os.path.join(odl_test_repo,
57                                    "csit/suites/integration/basic")
58     res_dir = os.path.join(ft_constants.FUNCTEST_RESULTS_DIR, "odl")
59
60     logger = ft_logger.Logger("opendaylight").getLogger()
61
62     def __init__(self):
63         self.case_name = "odl"
64
65     @classmethod
66     def set_robotframework_vars(cls, odlusername="admin", odlpassword="admin"):
67         odl_variables_files = os.path.join(cls.odl_test_repo,
68                                            'csit/variables/Variables.py')
69         try:
70             for line in fileinput.input(odl_variables_files,
71                                         inplace=True):
72                 print re.sub("AUTH = .*",
73                              ("AUTH = [u'" + odlusername + "', u'" +
74                               odlpassword + "']"),
75                              line.rstrip())
76             return True
77         except Exception as e:
78             cls.logger.error("Cannot set ODL creds: %s" % str(e))
79             return False
80
81     def parse_results(self):
82         output_dir = os.path.join(self.res_dir, 'output.xml')
83         result = ExecutionResult(output_dir)
84         visitor = ODLResultVisitor()
85         result.visit(visitor)
86         self.criteria = result.suite.status
87         self.start_time = timestamp_to_secs(result.suite.starttime)
88         self.stop_time = timestamp_to_secs(result.suite.endtime)
89         self.details = {}
90         self.details['description'] = result.suite.name
91         self.details['tests'] = visitor.get_data()
92         return self.criteria
93
94     def main(self, **kwargs):
95         dirs = [self.basic_suite_dir, self.neutron_suite_dir]
96         try:
97             odlusername = kwargs['odlusername']
98             odlpassword = kwargs['odlpassword']
99             variables = ['KEYSTONE:' + kwargs['keystoneip'],
100                          'NEUTRON:' + kwargs['neutronip'],
101                          'OSUSERNAME:"' + kwargs['osusername'] + '"',
102                          'OSTENANTNAME:"' + kwargs['ostenantname'] + '"',
103                          'OSPASSWORD:"' + kwargs['ospassword'] + '"',
104                          'ODL_SYSTEM_IP:' + kwargs['odlip'],
105                          'PORT:' + kwargs['odlwebport'],
106                          'RESTCONFPORT:' + kwargs['odlrestconfport']]
107         except KeyError as e:
108             self.logger.error("Cannot run ODL testcases. Please check "
109                               "%s" % str(e))
110             return self.EX_RUN_ERROR
111         if self.set_robotframework_vars(odlusername, odlpassword):
112             try:
113                 os.makedirs(self.res_dir)
114             except OSError as e:
115                 if e.errno != errno.EEXIST:
116                     self.logger.exception(
117                         "Cannot create {}".format(self.res_dir))
118                     return self.EX_RUN_ERROR
119             stdout_file = os.path.join(self.res_dir, 'stdout.txt')
120             output_dir = os.path.join(self.res_dir, 'output.xml')
121             with open(stdout_file, 'w+') as stdout:
122                 robot.run(*dirs, variable=variables,
123                           output=output_dir,
124                           log='NONE',
125                           report='NONE',
126                           stdout=stdout)
127                 stdout.seek(0, 0)
128                 self.logger.info("\n" + stdout.read())
129             self.logger.info("ODL results were successfully generated")
130             try:
131                 test_res = self.parse_results()
132                 self.logger.info("ODL results were successfully parsed")
133                 if test_res is not "PASS":
134                     return self.EX_RUN_ERROR
135             except RobotError as e:
136                 self.logger.error("Run tests before publishing: %s" %
137                                   e.message)
138                 return self.EX_RUN_ERROR
139             try:
140                 os.remove(stdout_file)
141             except OSError:
142                 self.logger.warning("Cannot remove {}".format(stdout_file))
143             return self.EX_OK
144         else:
145             return self.EX_RUN_ERROR
146
147     def run(self):
148         try:
149             kclient = op_utils.get_keystone_client()
150             keystone_url = kclient.service_catalog.url_for(
151                 service_type='identity', endpoint_type='publicURL')
152             neutron_url = kclient.service_catalog.url_for(
153                 service_type='network', endpoint_type='publicURL')
154             kwargs = {'keystoneip': urlparse.urlparse(keystone_url).hostname}
155             kwargs['neutronip'] = urlparse.urlparse(neutron_url).hostname
156             kwargs['odlip'] = kwargs['neutronip']
157             kwargs['odlwebport'] = '8080'
158             kwargs['odlrestconfport'] = '8181'
159             kwargs['odlusername'] = 'admin'
160             kwargs['odlpassword'] = 'admin'
161
162             installer_type = ft_constants.CI_INSTALLER_TYPE
163             kwargs['osusername'] = ft_constants.OS_USERNAME
164             kwargs['ostenantname'] = ft_constants.OS_TENANT_NAME
165             kwargs['ospassword'] = ft_constants.OS_PASSWORD
166
167             if installer_type == 'fuel':
168                 kwargs['odlwebport'] = '8282'
169             elif installer_type == 'apex':
170                 if ft_constants.SDN_CONTROLLER_IP is None:
171                     return self.EX_RUN_ERROR
172                 kwargs['odlip'] = ft_constants.SDN_CONTROLLER_IP
173                 kwargs['odlwebport'] = '8181'
174             elif installer_type == 'joid':
175                 if ft_constants.SDN_CONTROLLER is None:
176                     return self.EX_RUN_ERROR
177                 kwargs['odlip'] = ft_constants.SDN_CONTROLLER
178             elif installer_type == 'compass':
179                 kwargs['odlwebport'] = '8181'
180             else:
181                 if ft_constants.SDN_CONTROLLER_IP is None:
182                     return self.EX_RUN_ERROR
183                 kwargs['odlip'] = ft_constants.SDN_CONTROLLER_IP
184         except KeyError as e:
185             self.logger.error("Cannot run ODL testcases. "
186                               "Please check env var: "
187                               "%s" % str(e))
188             return self.EX_RUN_ERROR
189         except Exception:
190             self.logger.exception("Cannot run ODL testcases.")
191             return self.EX_RUN_ERROR
192
193         return self.main(**kwargs)
194
195
196 if __name__ == '__main__':
197     parser = argparse.ArgumentParser()
198     parser.add_argument('-k', '--keystoneip',
199                         help='Keystone IP',
200                         default='127.0.0.1')
201     parser.add_argument('-n', '--neutronip',
202                         help='Neutron IP',
203                         default='127.0.0.1')
204     parser.add_argument('-a', '--osusername',
205                         help='Username for OpenStack',
206                         default='admin')
207     parser.add_argument('-b', '--ostenantname',
208                         help='Tenantname for OpenStack',
209                         default='admin')
210     parser.add_argument('-c', '--ospassword',
211                         help='Password for OpenStack',
212                         default='admin')
213     parser.add_argument('-o', '--odlip',
214                         help='OpenDaylight IP',
215                         default='127.0.0.1')
216     parser.add_argument('-w', '--odlwebport',
217                         help='OpenDaylight Web Portal Port',
218                         default='8080')
219     parser.add_argument('-r', '--odlrestconfport',
220                         help='OpenDaylight RESTConf Port',
221                         default='8181')
222     parser.add_argument('-d', '--odlusername',
223                         help='Username for ODL',
224                         default='admin')
225     parser.add_argument('-e', '--odlpassword',
226                         help='Password for ODL',
227                         default='admin')
228     parser.add_argument('-p', '--pushtodb',
229                         help='Push results to DB',
230                         action='store_true')
231
232     args = vars(parser.parse_args())
233     odl = ODLTestCases()
234     try:
235         result = odl.main(**args)
236         if result != TestCasesBase.TestCasesBase.EX_OK:
237             sys.exit(result)
238         if args['pushtodb']:
239             sys.exit(odl.push_to_db())
240     except Exception:
241         sys.exit(TestCasesBase.TestCasesBase.EX_RUN_ERROR)