Add onaptests_bench into integration project repository
[integration.git] / test / onaptests_bench / src / onaptests_bench / launcher.py
1 #!/usr/bin/env python3
2
3 # ============LICENSE_START=======================================================
4 #  Copyright (C) 2022 Orange, Ltd.
5 # ================================================================================
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 #      http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 # SPDX-License-Identifier: Apache-2.0
19 # ============LICENSE_END=========================================================
20 #
21 # Launch basic_* tests in parallel and report results
22 # the possible basic tests are:
23 # - basic_onboarding
24 # - basic_vm
25 # - basic_network
26 # - basic_cnf
27 # - ...
28
29 # Dependencies:
30 #     See requirements.txt
31 #     The dashboard is based on bulma framework
32 #
33 # Environment:
34 #
35 # Example usage:
36 #       python launcher.py
37 #               -t <test>
38 #               -s <nb simultaneous occurences>
39 #               -d <duration>
40 #               -r <reporting path>
41 #
42 # the summary html page will be generated where the script is launched
43 """
44 Check ONAP certificates
45 """
46 import argparse
47 import logging
48 import os
49 import sys
50 import random
51 import string
52 import time
53 import docker  # pylint: disable=import-error
54
55 import onaptests_bench.reporting as Reporting
56
57 HOMEPATH = os.environ.get("HOME", "/home/ubuntu")
58
59 sys.path.append(f"{HOMEPATH}/onaptests_bench/src/onaptests_bench")
60
61 # Logger
62 LOG_LEVEL = 'INFO'
63 logging.basicConfig()
64 LOGGER = logging.getLogger("onaptests_bench")
65 LOGGER.setLevel(LOG_LEVEL)
66 TEST_LIST = ['basic_onboard', 'basic_vm', 'basic_vm_macro',
67              'basic_network', 'basic_cnf']
68 DEFAULT_TEST = TEST_LIST[0]
69 DEFAULT_SIMU_TESTS = 5
70 DEFAULT_TEST_DURATION = 180 # duration in minutes
71 RESULT_PATH = "/tmp"
72 ONAPTEST_BENCH_WAIT_TIMER = 40
73 ONAPTESTS_SETTINGS = ("/usr/lib/python3.8/site-packages/onaptests" +
74                       "/configuration/settings.py")
75
76 CLUSTER_IP = "127.0.0.1"
77
78 # Get arguments
79 PARSER = argparse.ArgumentParser()
80 PARSER.add_argument(
81     '-t',
82     '--test',
83     choices=TEST_LIST,
84     help=('Select your test (basic_onboard, basic_vm, basic_network, basic_cnf).' +
85           'If not set, basic_onboarding is considered'),
86     default=DEFAULT_TEST)
87 PARSER.add_argument(
88     '-s',
89     '--simu',
90     type=int,
91     help='Number of simultaneous tests',
92     default=DEFAULT_SIMU_TESTS)
93 PARSER.add_argument(
94     '-d',
95     '--duration',
96     type=int,
97     help='Test duration (in minutes)',
98     default=DEFAULT_TEST_DURATION)
99 PARSER.add_argument(
100     '-r',
101     '--reporting',
102     help='Result directory',
103     default=RESULT_PATH)
104 PARSER.add_argument(
105     '-i',
106     '--ip',
107     help='Cluster IP',
108     default=CLUSTER_IP)
109
110 ARGS = PARSER.parse_args()
111
112 def prepare_test_config():
113     """Check the test execution.
114        We supposed that basic_vm tests are already available in /tmp/xtesting
115        If not the tests cannot be executed."""
116     LOGGER.info("Prepare the test, verify that the test can be run")
117
118 def get_container_name():
119     """Set Container name."""
120     result_str = ''.join(random.choice(string.ascii_letters) for i in range(8))
121     container_name = ARGS.test + "_" + result_str
122     return container_name
123
124 def clean_test_device(docker_client, test):
125     """Clean test resources."""
126     container_list = docker_client.containers.list(
127         all=True,
128         filters={'label':'test='+test})
129     LOGGER.info("Containers cleanup before: %s containers", len(container_list))
130
131     for container in container_list:
132         container.stop()
133         container.remove()
134
135 def retrieve_onap_ip():
136     """Retrieve ONAP IP from /etc/hosts"""
137     filepath = '/etc/hosts'
138     with open(filepath) as fp_config:
139         line = fp_config.readline()
140         while line:
141             line = fp_config.readline()
142             if "so.api.simpledemo.onap.org" in line:
143                 onap_ip = line.split()[0]
144                 return onap_ip
145     return None
146
147 def execute_test(serie_number, test_number,
148                  docker_client):
149     """Execute one test."""
150     LOGGER.info("Execute test n° %s", test_number + 1)
151
152     volume_reporting = (ARGS.reporting + '/serie' + str(serie_number) +
153                         '/test' + str(test_number + 1))
154     if ARGS.ip == CLUSTER_IP:
155         onap_ip = retrieve_onap_ip()
156     else:
157         onap_ip = ARGS.ip
158
159     this_container = docker_client.containers.run(
160         "nexus3.onap.org:10003/onap/xtesting-smoke-usecases-pythonsdk:master",
161         command="run_tests -t " + ARGS.test,
162         name=get_container_name(),
163         labels={"test":ARGS.test},
164         stdout=True,
165         stderr=True,
166         stream=False,
167         detach=True,
168         extra_hosts={'portal.api.simpledemo.onap.org':onap_ip,
169                      'vid.api.simpledemo.onap.org':onap_ip,
170                      'sdc.api.fe.simpledemo.onap.org':onap_ip,
171                      'sdc.api.be.simpledemo.onap.org':onap_ip,
172                      'aai.api.sparky.simpledemo.onap.org':onap_ip,
173                      'so.api.simpledemo.onap.org':onap_ip,
174                      'sdnc.api.simpledemo.onap.org':onap_ip,
175                      'sdc.workflow.plugin.simpledemo.onap.org':onap_ip,
176                      'sdc.dcae.plugin.simpledemo.onap.org':onap_ip,
177                      'msb.api.simpledemo.onap.org':onap_ip},
178         volumes={'/tmp/xtesting/smoke-usecases/' + ARGS.test + '/env':{'bind': '/var/lib/xtesting/conf/env_file', 'mode': 'rw'},  # pylint: disable=line-too-long
179                  f'{HOMEPATH}/.config/openstack/clouds.yaml':{'bind': '/root/.config/openstack/clouds.yaml', 'mode': 'rw'},  # pylint: disable=line-too-long
180                  volume_reporting:{'bind':'/var/lib/xtesting/results', 'mode': 'rw'},
181                  f'{HOMEPATH}/.kube/config':{'bind':'/root/.kube/config', 'mode': 'rw'},
182                  os.path.dirname(os.path.abspath(__file__)) + '/artifacts/settings.py':{'bind': ONAPTESTS_SETTINGS, 'mode': 'rw'}})  # pylint: disable=line-too-long
183
184     return this_container
185
186 def launch_test_serie(serie_number,
187                       docker_client, serie_containers):
188     """Launch a serie of n tests."""
189     for test_number in range(ARGS.simu):
190         container = execute_test(serie_number, test_number,
191                                  docker_client)
192         serie_containers.append(container)
193     return serie_containers
194
195 def get_terminated_serie_status(running_containers):
196     """Check if the dockers in the list are terminated and get exit codes"""
197     LOGGER.info("check terminated dockers")
198     exit_codes = []
199     exit_codes.clear()
200
201     for container in running_containers:
202         try:
203             # wait for the container to finish within a certain time
204             result = container.wait(timeout=60*ONAPTEST_BENCH_WAIT_TIMER)
205             exit_code = result["StatusCode"]
206         except Exception as timeout:  # pylint: disable=broad-except
207             #if the container didn't finish in the allocated time
208             # raise timeout exception and sto the container
209             LOGGER.error(timeout)
210             LOGGER.error("docker not terminating in allocated time")
211             container.stop()
212             exit_code = -1
213         LOGGER.info("exit code : %s", str(exit_code))
214         exit_codes.append(exit_code)
215     return exit_codes
216
217 def generate_report():
218     """Build reporting."""
219     LOGGER.info("Generate the report")
220     test = Reporting.OnaptestBenchReporting(
221         nb_simultaneous_tests=ARGS.simu,
222         duration=ARGS.duration,
223         res_dir_path=ARGS.reporting,
224         reporting_dir=ARGS.reporting)
225     test.generate_reporting()
226
227 def main():
228     """Entry point"""
229     # ***************************************************************************
230     # ***************************************************************************
231     # start of the test
232     # ***************************************************************************
233     # ***************************************************************************
234     test_client = docker.from_env()
235     serie_containers = []
236     exit_codes = []
237
238     prepare_test_config()
239
240     t_end = time.time() + 60 * float(ARGS.duration)
241
242     # clean previous container no longer used to avoid saturation
243
244
245     LOGGER.info("****************************")
246     LOGGER.info("Launch the tests")
247     LOGGER.info("Testcase: %s", ARGS.test)
248     LOGGER.info("Number of simultaneous tests : %s", ARGS.simu)
249     LOGGER.info("Test duration : %s m", ARGS.duration)
250     LOGGER.info("Reporting path : %s", ARGS.reporting)
251     LOGGER.info("****************************")
252
253     try:
254         # keep on launching series until we reached the duration expected by the tester
255         serie_number = 1
256         while time.time() < t_end:
257             clean_test_device(test_client, ARGS.test)
258             LOGGER.info("Serie : %s", str(serie_number))
259             serie_containers.clear()
260             # launch the serie
261             serie_containers = launch_test_serie(
262                 serie_number,
263                 test_client,
264                 serie_containers)
265             LOGGER.info("Containers of serie %s created", str(serie_number))
266             exit_codes = get_terminated_serie_status(serie_containers)
267             LOGGER.info("Serie terminated")
268             LOGGER.debug(exit_codes)
269             remaining_time = int(t_end - time.time())
270             if remaining_time > 0:
271                 LOGGER.info("%s s remaining, restart a serie...", remaining_time)
272             serie_number += 1
273
274     except Exception as error:  # pylint: disable=broad-except
275         LOGGER.error(error)
276         LOGGER.error(">>>> Onaptests_bench FAIL")
277         LOGGER.error("do you have the correct env file?")
278         LOGGER.error("do you have the correctcluster IP?")
279         sys.exit(1)
280
281     else:
282         LOGGER.info(">>>> Onaptests_bench successfully executed")
283
284     finally:
285         generate_report()