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