Update linters and fix all new issues
[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().__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(
70                     "@{AUTH}.*",
71                     f"@{{AUTH}}           {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 = (f"{urllib.parse.urlparse(osauthurl).scheme}://"
115                            f"{urllib.parse.urlparse(osauthurl).netloc}")
116             variable = ['KEYSTONEURL:' + keystoneurl,
117                         'NEUTRONURL:' + kwargs['neutronurl'],
118                         'OS_AUTH_URL:"' + osauthurl + '"',
119                         'OSUSERNAME:"' + kwargs['osusername'] + '"',
120                         ('OSUSERDOMAINNAME:"' +
121                          kwargs['osuserdomainname'] + '"'),
122                         'OSTENANTNAME:"' + kwargs['osprojectname'] + '"',
123                         ('OSPROJECTDOMAINNAME:"' +
124                          kwargs['osprojectdomainname'] + '"'),
125                         'OSPASSWORD:"' + kwargs['ospassword'] + '"',
126                         'ODL_SYSTEM_IP:' + kwargs['odlip'],
127                         'PORT:' + kwargs['odlwebport'],
128                         'RESTCONFPORT:' + kwargs['odlrestconfport']]
129         except KeyError:
130             self.__logger.exception("Cannot run ODL testcases. Please check")
131             return self.EX_RUN_ERROR
132         if not os.path.isfile(self.odl_variables_file):
133             self.__logger.info("Skip writting ODL creds")
134         else:
135             if not self.set_robotframework_vars(odlusername, odlpassword):
136                 return self.EX_RUN_ERROR
137         return super().run(variable=variable, suites=suites)
138
139     def run(self, **kwargs):
140         """Run suites in OPNFV environment
141
142         It basically checks env vars to call main() with the keywords
143         required.
144
145         Args:
146             kwargs: Arbitrary keyword arguments.
147
148         Returns:
149             EX_OK if all suites ran well.
150             EX_RUN_ERROR otherwise.
151         """
152         try:
153             suites = self.default_suites
154             try:
155                 suites = kwargs["suites"]
156             except KeyError:
157                 pass
158             cloud = os_client_config.make_shade()
159             neutron_id = cloud.search_services('neutron')[0].id
160             endpoint = cloud.search_endpoints(
161                 filters={
162                     'interface': os.environ.get(
163                         'OS_INTERFACE', 'public').replace('URL', ''),
164                     'service_id': neutron_id})[0].url
165             kwargs = {'neutronurl': endpoint}
166             kwargs['odlip'] = env.get('SDN_CONTROLLER_IP')
167             kwargs['odlwebport'] = env.get('SDN_CONTROLLER_WEBPORT')
168             kwargs['odlrestconfport'] = env.get('SDN_CONTROLLER_RESTCONFPORT')
169             kwargs['odlusername'] = env.get('SDN_CONTROLLER_USER')
170             kwargs['odlpassword'] = env.get('SDN_CONTROLLER_PASSWORD')
171             kwargs['osusername'] = os.environ['OS_USERNAME']
172             kwargs['osuserdomainname'] = os.environ.get(
173                 'OS_USER_DOMAIN_NAME', 'Default')
174             kwargs['osprojectname'] = os.environ['OS_PROJECT_NAME']
175             kwargs['osprojectdomainname'] = os.environ.get(
176                 'OS_PROJECT_DOMAIN_NAME', 'Default')
177             kwargs['osauthurl'] = os.environ['OS_AUTH_URL']
178             kwargs['ospassword'] = os.environ['OS_PASSWORD']
179             assert kwargs['odlip']
180         except KeyError as ex:
181             self.__logger.error(
182                 "Cannot run ODL testcases. Please check env var: %s", str(ex))
183             return self.EX_RUN_ERROR
184         except Exception:  # pylint: disable=broad-except
185             self.__logger.exception("Cannot run ODL testcases.")
186             return self.EX_RUN_ERROR
187
188         return self.run_suites(suites, **kwargs)
189
190
191 class ODLParser():  # pylint: disable=too-few-public-methods
192     """Parser to run ODL test suites."""
193
194     def __init__(self):
195         self.parser = argparse.ArgumentParser()
196         self.parser.add_argument(
197             '-n', '--neutronurl', help='Neutron Endpoint',
198             default='http://127.0.0.1:9696')
199         self.parser.add_argument(
200             '-k', '--osauthurl', help='OS_AUTH_URL as defined by OpenStack',
201             default='http://127.0.0.1:5000/v3')
202         self.parser.add_argument(
203             '-a', '--osusername', help='Username for OpenStack',
204             default='admin')
205         self.parser.add_argument(
206             '-f', '--osuserdomainname', help='User domain name for OpenStack',
207             default='Default')
208         self.parser.add_argument(
209             '-b', '--osprojectname', help='Projet name for OpenStack',
210             default='admin')
211         self.parser.add_argument(
212             '-g', '--osprojectdomainname',
213             help='Project domain name for OpenStack',
214             default='Default')
215         self.parser.add_argument(
216             '-c', '--ospassword', help='Password for OpenStack',
217             default='admin')
218         self.parser.add_argument(
219             '-o', '--odlip', help='OpenDaylight IP',
220             default='127.0.0.1')
221         self.parser.add_argument(
222             '-w', '--odlwebport', help='OpenDaylight Web Portal Port',
223             default='8080')
224         self.parser.add_argument(
225             '-r', '--odlrestconfport', help='OpenDaylight RESTConf Port',
226             default='8181')
227         self.parser.add_argument(
228             '-d', '--odlusername', help='Username for ODL',
229             default='admin')
230         self.parser.add_argument(
231             '-e', '--odlpassword', help='Password for ODL',
232             default='admin')
233         self.parser.add_argument(
234             '-p', '--pushtodb', help='Push results to DB',
235             action='store_true')
236
237     def parse_args(self, argv=None):
238         """Parse arguments.
239
240         It can call sys.exit if arguments are incorrect.
241
242         Returns:
243             the arguments from cmdline
244         """
245         if not argv:
246             argv = []
247         return vars(self.parser.parse_args(argv))
248
249
250 def main():
251     """Entry point"""
252     logging.basicConfig()
253     odl = ODLTests()
254     parser = ODLParser()
255     args = parser.parse_args(sys.argv[1:])
256     try:
257         result = odl.run_suites(ODLTests.default_suites, **args)
258         if result != robotframework.RobotFramework.EX_OK:
259             return result
260         if args['pushtodb']:
261             return odl.push_to_db()
262         return result
263     except Exception:  # pylint: disable=broad-except
264         return robotframework.RobotFramework.EX_RUN_ERROR