Merge "Refactor TempestCommon to simplify subclasses"
[functest.git] / functest / opnfv_tests / sdn / odl / odl.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 """Define classes required to run ODL suites.
11
12 It has been designed for any context. But helpers are given for
13 running test suites in OPNFV environment.
14
15 Example:
16         $ python odl.py
17 """
18
19 from __future__ import division
20
21 import argparse
22 import fileinput
23 import logging
24 import os
25 import re
26 import sys
27
28 from six.moves import urllib
29 from snaps.openstack.utils import keystone_utils
30
31 from functest.opnfv_tests.openstack.snaps import snaps_utils
32 from functest.utils import config
33 from functest.utils import env
34 from xtesting.core import robotframework
35
36 __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
37
38
39 class ODLTests(robotframework.RobotFramework):
40     """ODL test runner."""
41
42     odl_test_repo = getattr(config.CONF, 'dir_repo_odl_test')
43     neutron_suite_dir = os.path.join(
44         odl_test_repo, "csit/suites/openstack/neutron")
45     basic_suite_dir = os.path.join(
46         odl_test_repo, "csit/suites/integration/basic")
47     default_suites = [basic_suite_dir, neutron_suite_dir]
48     odl_variables_file = os.path.join(
49         odl_test_repo, 'csit/variables/Variables.robot')
50     __logger = logging.getLogger(__name__)
51
52     def __init__(self, **kwargs):
53         super(ODLTests, self).__init__(**kwargs)
54         self.res_dir = os.path.join(
55             getattr(config.CONF, 'dir_results'), 'odl')
56         self.xml_file = os.path.join(self.res_dir, 'output.xml')
57
58     @classmethod
59     def set_robotframework_vars(cls, odlusername="admin", odlpassword="admin"):
60         """Set credentials in csit/variables/Variables.robot.
61
62         Returns:
63             True if credentials are set.
64             False otherwise.
65         """
66
67         try:
68             for line in fileinput.input(cls.odl_variables_file,
69                                         inplace=True):
70                 print(re.sub("@{AUTH}.*",
71                              "@{{AUTH}}           {}    {}".format(
72                                  odlusername, odlpassword),
73                              line.rstrip()))
74             return True
75         except Exception:  # pylint: disable=broad-except
76             cls.__logger.exception("Cannot set ODL creds:")
77             return False
78
79     def run_suites(self, suites=None, **kwargs):
80         """Run the test suites
81
82         It has been designed to be called in any context.
83         It requires the following keyword arguments:
84
85            * odlusername,
86            * odlpassword,
87            * osauthurl,
88            * neutronurl,
89            * osusername,
90            * osprojectname,
91            * ospassword,
92            * odlip,
93            * odlwebport,
94            * odlrestconfport.
95
96         Here are the steps:
97            * set all RobotFramework_variables,
98            * create the output directories if required,
99            * get the results in output.xml,
100            * delete temporary files.
101
102         Args:
103             kwargs: Arbitrary keyword arguments.
104
105         Returns:
106             EX_OK if all suites ran well.
107             EX_RUN_ERROR otherwise.
108         """
109         try:
110             if not suites:
111                 suites = self.default_suites
112             odlusername = kwargs['odlusername']
113             odlpassword = kwargs['odlpassword']
114             osauthurl = kwargs['osauthurl']
115             keystoneurl = "{}://{}".format(
116                 urllib.parse.urlparse(osauthurl).scheme,
117                 urllib.parse.urlparse(osauthurl).netloc)
118             variable = ['KEYSTONEURL:' + keystoneurl,
119                         'NEUTRONURL:' + kwargs['neutronurl'],
120                         'OS_AUTH_URL:"' + osauthurl + '"',
121                         'OSUSERNAME:"' + kwargs['osusername'] + '"',
122                         ('OSUSERDOMAINNAME:"' +
123                          kwargs['osuserdomainname'] + '"'),
124                         'OSTENANTNAME:"' + kwargs['osprojectname'] + '"',
125                         ('OSPROJECTDOMAINNAME:"' +
126                          kwargs['osprojectdomainname'] + '"'),
127                         'OSPASSWORD:"' + kwargs['ospassword'] + '"',
128                         'ODL_SYSTEM_IP:' + kwargs['odlip'],
129                         'PORT:' + kwargs['odlwebport'],
130                         'RESTCONFPORT:' + kwargs['odlrestconfport']]
131         except KeyError:
132             self.__logger.exception("Cannot run ODL testcases. Please check")
133             return self.EX_RUN_ERROR
134         if not os.path.isfile(self.odl_variables_file):
135             self.__logger.info("Skip writting ODL creds")
136         else:
137             if not self.set_robotframework_vars(odlusername, odlpassword):
138                 return self.EX_RUN_ERROR
139         return super(ODLTests, self).run(variable=variable, suites=suites)
140
141     def run(self, **kwargs):
142         """Run suites in OPNFV environment
143
144         It basically checks env vars to call main() with the keywords
145         required.
146
147         Args:
148             kwargs: Arbitrary keyword arguments.
149
150         Returns:
151             EX_OK if all suites ran well.
152             EX_RUN_ERROR otherwise.
153         """
154         try:
155             suites = self.default_suites
156             try:
157                 suites = kwargs["suites"]
158             except KeyError:
159                 pass
160             snaps_creds = snaps_utils.get_credentials()
161             kwargs = {'neutronurl': keystone_utils.get_endpoint(
162                 snaps_creds, 'network')}
163             kwargs['odlip'] = urllib.parse.urlparse(
164                 kwargs['neutronurl']).hostname
165             kwargs['odlwebport'] = '8080'
166             kwargs['odlrestconfport'] = '8181'
167             kwargs['odlusername'] = 'admin'
168             kwargs['odlpassword'] = 'admin'
169             installer_type = env.get('INSTALLER_TYPE')
170             kwargs['osusername'] = os.environ['OS_USERNAME']
171             kwargs['osuserdomainname'] = os.environ.get(
172                 'OS_USER_DOMAIN_NAME', 'Default')
173             kwargs['osprojectname'] = os.environ['OS_PROJECT_NAME']
174             kwargs['osprojectdomainname'] = os.environ.get(
175                 'OS_PROJECT_DOMAIN_NAME', 'Default')
176             kwargs['osauthurl'] = os.environ['OS_AUTH_URL']
177             kwargs['ospassword'] = os.environ['OS_PASSWORD']
178             if installer_type == 'fuel':
179                 kwargs['odlwebport'] = '8181'
180                 kwargs['odlrestconfport'] = '8282'
181             elif installer_type == 'apex' or installer_type == 'netvirt':
182                 kwargs['odlip'] = env.get('SDN_CONTROLLER_IP')
183                 kwargs['odlwebport'] = '8081'
184                 kwargs['odlrestconfport'] = '8081'
185             elif installer_type == 'compass':
186                 kwargs['odlip'] = env.get('SDN_CONTROLLER_IP')
187                 kwargs['odlrestconfport'] = '8080'
188             elif installer_type == 'daisy':
189                 kwargs['odlip'] = env.get('SDN_CONTROLLER_IP')
190                 kwargs['odlwebport'] = '8181'
191                 kwargs['odlrestconfport'] = '8087'
192             else:
193                 kwargs['odlip'] = env.get('SDN_CONTROLLER_IP')
194             assert kwargs['odlip']
195         except KeyError as ex:
196             self.__logger.error("Cannot run ODL testcases. "
197                                 "Please check env var: "
198                                 "%s", str(ex))
199             return self.EX_RUN_ERROR
200         except Exception:  # pylint: disable=broad-except
201             self.__logger.exception("Cannot run ODL testcases.")
202             return self.EX_RUN_ERROR
203
204         return self.run_suites(suites, **kwargs)
205
206
207 class ODLParser(object):  # pylint: disable=too-few-public-methods
208     """Parser to run ODL test suites."""
209
210     def __init__(self):
211         self.parser = argparse.ArgumentParser()
212         self.parser.add_argument(
213             '-n', '--neutronurl', help='Neutron Endpoint',
214             default='http://127.0.0.1:9696')
215         self.parser.add_argument(
216             '-k', '--osauthurl', help='OS_AUTH_URL as defined by OpenStack',
217             default='http://127.0.0.1:5000/v3')
218         self.parser.add_argument(
219             '-a', '--osusername', help='Username for OpenStack',
220             default='admin')
221         self.parser.add_argument(
222             '-f', '--osuserdomainname', help='User domain name for OpenStack',
223             default='Default')
224         self.parser.add_argument(
225             '-b', '--osprojectname', help='Projet name for OpenStack',
226             default='admin')
227         self.parser.add_argument(
228             '-g', '--osprojectdomainname',
229             help='Project domain name for OpenStack',
230             default='Default')
231         self.parser.add_argument(
232             '-c', '--ospassword', help='Password for OpenStack',
233             default='admin')
234         self.parser.add_argument(
235             '-o', '--odlip', help='OpenDaylight IP',
236             default='127.0.0.1')
237         self.parser.add_argument(
238             '-w', '--odlwebport', help='OpenDaylight Web Portal Port',
239             default='8080')
240         self.parser.add_argument(
241             '-r', '--odlrestconfport', help='OpenDaylight RESTConf Port',
242             default='8181')
243         self.parser.add_argument(
244             '-d', '--odlusername', help='Username for ODL',
245             default='admin')
246         self.parser.add_argument(
247             '-e', '--odlpassword', help='Password for ODL',
248             default='admin')
249         self.parser.add_argument(
250             '-p', '--pushtodb', help='Push results to DB',
251             action='store_true')
252
253     def parse_args(self, argv=None):
254         """Parse arguments.
255
256         It can call sys.exit if arguments are incorrect.
257
258         Returns:
259             the arguments from cmdline
260         """
261         if not argv:
262             argv = []
263         return vars(self.parser.parse_args(argv))
264
265
266 def main():
267     """Entry point"""
268     logging.basicConfig()
269     odl = ODLTests()
270     parser = ODLParser()
271     args = parser.parse_args(sys.argv[1:])
272     try:
273         result = odl.run_suites(ODLTests.default_suites, **args)
274         if result != robotframework.RobotFramework.EX_OK:
275             return result
276         if args['pushtodb']:
277             return odl.push_to_db()
278         return result
279     except Exception:  # pylint: disable=broad-except
280         return robotframework.RobotFramework.EX_RUN_ERROR