jjb/lava: Parameterize repo URL and branch for test scripts
[lttng-ci.git] / scripts / system-tests / lava2-submit.py
CommitLineData
21fec189 1#!/usr/bin/python3
878b4840
JR
2# Copyright (C) 2016 - Francis Deslauriers <francis.deslauriers@efficios.com>
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17import argparse
878b4840
JR
18import json
19import os
20import random
9356eef7 21import re
878b4840
JR
22import sys
23import time
24import xmlrpc.client
6d3950a9
JR
25from urllib.parse import urljoin
26from urllib.request import urlretrieve
21fec189
JR
27import yaml
28from jinja2 import Environment, FileSystemLoader
878b4840 29
ef84c6ec
JR
30USERNAME = 'lava-jenkins'
31HOSTNAME = 'lava-master-02.internal.efficios.com'
0425e1dd 32OBJSTORE_URL = "https://obj.internal.efficios.com/lava/results/"
878b4840 33
cf1271bb
JR
34def parse_stable_version(stable_version_string):
35 # Get the major and minor version numbers from the lttng version string.
36 version_match = re.search('stable-(\d).(\d\d)', stable_version_string)
37
38 if version_match is not None:
39 major_version = int(version_match.group(1))
40 minor_version = int(version_match.group(2))
41 else:
42 # Setting to zero to make the comparison below easier.
43 major_version = 0
44 minor_version = 0
45 return major_version, minor_version
46
f5f36c68
FD
47
48class TestType:
21fec189 49 """ Enum like for test type """
f5f36c68 50
523e784d
FD
51 baremetal_tests = 1
52 kvm_tests = 2
878b4840 53 values = {
f5f36c68
FD
54 'baremetal-tests': baremetal_tests,
55 'kvm-tests': kvm_tests,
878b4840
JR
56 }
57
f5f36c68
FD
58
59class DeviceType:
21fec189 60 """ Enum like for device type """
f5f36c68 61
4cb5cc4f 62 x86 = 'x86'
f9a184a9 63 kvm = 'qemu'
f5f36c68
FD
64 values = {'kvm': kvm, 'x86': x86}
65
4cb5cc4f 66
878b4840
JR
67def get_job_bundle_content(server, job):
68 try:
69 bundle_sha = server.scheduler.job_status(str(job))['bundle_sha1']
70 bundle = server.dashboard.get(bundle_sha)
21fec189
JR
71 except xmlrpc.client.Fault as error:
72 print('Error while fetching results bundle', error.faultString)
73 raise error
878b4840
JR
74
75 return json.loads(bundle['content'])
76
f5f36c68 77
878b4840 78def check_job_all_test_cases_state_count(server, job):
21fec189
JR
79 """
80 Parse the results bundle to see the run-tests testcase
81 of the lttng-kernel-tests passed successfully
82 """
0425e1dd
JR
83 print("Testcase result:")
84 content = server.results.get_testjob_results_yaml(str(job))
c2f8bcb9 85 testcases = yaml.unsafe_load(content)
878b4840 86
21fec189
JR
87 passed_tests = 0
88 failed_tests = 0
0425e1dd
JR
89 for testcase in testcases:
90 if testcase['result'] != 'pass':
f5f36c68
FD
91 print(
92 "\tFAILED {}\n\t\t See http://{}{}".format(
93 testcase['name'], HOSTNAME, testcase['url']
94 )
95 )
21fec189 96 failed_tests += 1
0425e1dd 97 else:
21fec189 98 passed_tests += 1
878b4840
JR
99 return (passed_tests, failed_tests)
100
f5f36c68 101
878b4840 102def print_test_output(server, job):
21fec189
JR
103 """
104 Parse the attachment of the testcase to fetch the stdout of the test suite
105 """
0425e1dd 106 job_finished, log = server.scheduler.jobs.logs(str(job))
be7f51b6 107 logs = yaml.unsafe_load(log.data.decode('ascii'))
0425e1dd
JR
108 print_line = False
109 for line in logs:
110 if line['lvl'] != 'target':
111 continue
112 if line['msg'] == '<LAVA_SIGNAL_STARTTC run-tests>':
113 print('---- TEST SUITE OUTPUT BEGIN ----')
114 print_line = True
115 continue
116 if line['msg'] == '<LAVA_SIGNAL_ENDTC run-tests>':
117 print('----- TEST SUITE OUTPUT END -----')
d132001f
FD
118 print_line = False
119 continue
0425e1dd
JR
120 if print_line:
121 print("{} {}".format(line['dt'], line['msg']))
878b4840 122
f5f36c68
FD
123
124def get_vlttng_cmd(
9356eef7 125 lttng_version, lttng_tools_url, lttng_tools_commit, lttng_ust_url=None, lttng_ust_commit=None
f5f36c68 126):
21fec189
JR
127 """
128 Return vlttng cmd to be used in the job template for setup.
129 """
0dd62728
JR
130
131 major_version, minor_version = parse_stable_version(lttng_version)
132
f1d85a63
JR
133 urcu_profile = ""
134 if lttng_version == 'master' or (major_version >= 2 and minor_version >= 11):
135 urcu_profile = "urcu-master"
136 else:
137 urcu_profile = "urcu-stable-0.12"
878b4840 138
30989989
JR
139 # Starting with 2.14, babeltrace2 is the reader for testing.
140 if lttng_version == 'master' or (major_version >= 2 and minor_version >= 14):
141 babeltrace_profile = " --profile babeltrace2-stable-2.0 --profile babeltrace2-python"
cb59666e 142 babeltrace_overrides = " --override projects.babeltrace2.build-env.PYTHON=python3 --override projects.babeltrace2.build-env.PYTHON_CONFIG=python3-config -o projects.babeltrace2.configure+=--disable-man-pages"
30989989
JR
143 else:
144 babeltrace_profile = " --profile babeltrace-stable-1.5 --profile babeltrace-python"
a8160fec
JR
145 babeltrace_overrides = " --override projects.babeltrace.build-env.PYTHON=python3 --override projects.babeltrace.build-env.PYTHON_CONFIG=python3-config"
146
30989989 147
f5f36c68 148 vlttng_cmd = (
f1d85a63 149 'vlttng --jobs=$(nproc) --profile ' + urcu_profile
30989989 150 + babeltrace_profile
a8160fec 151 + babeltrace_overrides
30989989 152 + ' --profile lttng-tools-master'
f5f36c68
FD
153 ' --override projects.lttng-tools.source='
154 + lttng_tools_url
155 + ' --override projects.lttng-tools.checkout='
156 + lttng_tools_commit
157 + ' --profile lttng-tools-no-man-pages'
158 )
878b4840
JR
159
160 if lttng_ust_commit is not None:
f5f36c68
FD
161 vlttng_cmd += (
162 ' --profile lttng-ust-master '
163 ' --override projects.lttng-ust.source='
164 + lttng_ust_url
165 + ' --override projects.lttng-ust.checkout='
166 + lttng_ust_commit
167 + ' --profile lttng-ust-no-man-pages'
168 )
878b4840 169
9356eef7
FD
170
171 if lttng_version == 'master' or (major_version >= 2 and minor_version >= 11):
172 vlttng_cmd += (
173 ' --override projects.lttng-tools.configure+=--enable-test-sdt-uprobe'
174 )
175
888b31de 176 vlttng_path = '/tmp/virtenv'
c11ec858 177
4cb5cc4f 178 vlttng_cmd += ' ' + vlttng_path
878b4840 179
4cb5cc4f 180 return vlttng_cmd
878b4840 181
f5f36c68 182
878b4840 183def main():
559b83b3 184 send_retry_limit = 10
878b4840
JR
185 test_type = None
186 parser = argparse.ArgumentParser(description='Launch baremetal test using Lava')
187 parser.add_argument('-t', '--type', required=True)
9356eef7 188 parser.add_argument('-lv', '--lttng-version', required=True)
878b4840
JR
189 parser.add_argument('-j', '--jobname', required=True)
190 parser.add_argument('-k', '--kernel', required=True)
878b4840 191 parser.add_argument('-lm', '--lmodule', required=True)
eb5bdbeb 192 parser.add_argument('-tu', '--tools-url', required=True)
878b4840 193 parser.add_argument('-tc', '--tools-commit', required=True)
6b35e57c 194 parser.add_argument('-id', '--build-id', required=True)
eb5bdbeb 195 parser.add_argument('-uu', '--ust-url', required=False)
878b4840 196 parser.add_argument('-uc', '--ust-commit', required=False)
f23dc688 197 parser.add_argument('-d', '--debug', required=False, action='store_true')
6f3cac9a
KS
198 parser.add_argument(
199 '-r', '--rootfs-url', required=False,
200 default="https://obj.internal.efficios.com/lava/rootfs/rootfs_amd64_xenial_2018-12-05.tar.gz"
201 )
ef50ca2a
KS
202 parser.add_argument('--ci-repo', required=False, default='https://github.com/lttng/lttng-ci.git')
203 parser.add_argument('--ci-branch', required=False, default='master')
878b4840
JR
204 args = parser.parse_args()
205
206 if args.type not in TestType.values:
207 print('argument -t/--type {} unrecognized.'.format(args.type))
208 print('Possible values are:')
209 for k in TestType.values:
210 print('\t {}'.format(k))
211 return -1
878b4840
JR
212
213 lava_api_key = None
f23dc688
JR
214 if not args.debug:
215 try:
ef84c6ec 216 lava_api_key = os.environ['LAVA2_JENKINS_TOKEN']
21fec189 217 except Exception as error:
f5f36c68
FD
218 print(
219 'LAVA2_JENKINS_TOKEN not found in the environment variable. Exiting...',
220 error,
221 )
f23dc688 222 return -1
878b4840 223
4cb5cc4f 224 jinja_loader = FileSystemLoader(os.path.dirname(os.path.realpath(__file__)))
f5f36c68 225 jinja_env = Environment(loader=jinja_loader, trim_blocks=True, lstrip_blocks=True)
4cb5cc4f 226 jinja_template = jinja_env.get_template('template_lava_job.jinja2')
4cb5cc4f
JR
227
228 test_type = TestType.values[args.type]
229
523e784d 230 if test_type is TestType.baremetal_tests:
4cb5cc4f 231 device_type = DeviceType.x86
878b4840 232 else:
4cb5cc4f 233 device_type = DeviceType.kvm
e640b6d8
JR
234
235 vlttng_path = '/tmp/virtenv'
4cb5cc4f 236
f5f36c68 237 vlttng_cmd = get_vlttng_cmd(
9356eef7 238 args.lttng_version, args.tools_url, args.tools_commit, args.ust_url, args.ust_commit
f5f36c68 239 )
4cb5cc4f 240
cf1271bb
JR
241 if args.lttng_version == "master":
242 lttng_version_string = "master"
7ce9e417
JR
243 elif args.lttng_version == "canary":
244 lttng_version_string = "2.10"
cf1271bb
JR
245 else:
246 major, minor = parse_stable_version(args.lttng_version)
247 lttng_version_string = str(major) + "." + str(minor)
248
249
4cb5cc4f
JR
250 context = dict()
251 context['DeviceType'] = DeviceType
252 context['TestType'] = TestType
253
254 context['job_name'] = args.jobname
255 context['test_type'] = test_type
4cb5cc4f
JR
256 context['random_seed'] = random.randint(0, 1000000)
257 context['device_type'] = device_type
258
259 context['vlttng_cmd'] = vlttng_cmd
260 context['vlttng_path'] = vlttng_path
cf1271bb 261 context['lttng_version_string'] = lttng_version_string
4cb5cc4f
JR
262
263 context['kernel_url'] = args.kernel
6f3cac9a 264 context['nfsrootfs_url'] = args.rootfs_url
4cb5cc4f 265 context['lttng_modules_url'] = args.lmodule
6b35e57c 266 context['jenkins_build_id'] = args.build_id
4cb5cc4f
JR
267
268 context['kprobe_round_nb'] = 10
269
ef50ca2a
KS
270 context['ci_repo'] = args.ci_repo
271 context['ci_branch'] = args.ci_branch
272
ef84c6ec
JR
273 render = jinja_template.render(context)
274
ef84c6ec
JR
275 print('Job to be submitted:')
276
277 print(render)
878b4840 278
f23dc688 279 if args.debug:
f23dc688
JR
280 return 0
281
f5f36c68
FD
282 server = xmlrpc.client.ServerProxy(
283 'http://%s:%s@%s/RPC2' % (USERNAME, lava_api_key, HOSTNAME)
284 )
878b4840 285
559b83b3 286 for attempt in range(1, send_retry_limit + 1):
21fec189
JR
287 try:
288 jobid = server.scheduler.submit_job(render)
289 except xmlrpc.client.ProtocolError as error:
f5f36c68
FD
290 print(
291 'Protocol error on submit, sleeping and retrying. Attempt #{}'.format(
292 attempt
293 )
294 )
21fec189
JR
295 time.sleep(5)
296 continue
297 else:
298 break
559b83b3
JR
299 # Early exit when the maximum number of retry is reached.
300 if attempt == send_retry_limit:
301 print(
302 'Protocol error on submit, maximum number of retry reached ({})'.format(
303 attempt
304 )
305 )
306 return -1
878b4840
JR
307
308 print('Lava jobid:{}'.format(jobid))
f5f36c68
FD
309 print(
310 'Lava job URL: http://lava-master-02.internal.efficios.com/scheduler/job/{}'.format(
311 jobid
312 )
313 )
878b4840 314
f5f36c68 315 # Check the status of the job every 30 seconds
0425e1dd
JR
316 jobstatus = server.scheduler.job_state(jobid)['job_state']
317 running = False
21fec189 318 while jobstatus in ['Submitted', 'Scheduling', 'Scheduled', 'Running']:
0425e1dd 319 if not running and jobstatus == 'Running':
878b4840 320 print('Job started running')
0425e1dd 321 running = True
878b4840 322 time.sleep(30)
26cbe60b
JR
323 try:
324 jobstatus = server.scheduler.job_state(jobid)['job_state']
21fec189
JR
325 except xmlrpc.client.ProtocolError as error:
326 print('Protocol error, retrying')
327 continue
878b4840 328 print('Job ended with {} status.'.format(jobstatus))
0425e1dd
JR
329
330 if jobstatus != 'Finished':
878b4840 331 return -1
878b4840 332
0425e1dd
JR
333 if test_type is TestType.kvm_tests or test_type is TestType.baremetal_tests:
334 print_test_output(server, jobid)
0425e1dd 335
21fec189 336 passed, failed = check_job_all_test_cases_state_count(server, jobid)
0425e1dd
JR
337 print('With {} passed and {} failed Lava test cases.'.format(passed, failed))
338
21fec189 339 if failed != 0:
0425e1dd 340 return -1
878b4840 341
21fec189
JR
342 return 0
343
f5f36c68 344
878b4840
JR
345if __name__ == "__main__":
346 sys.exit(main())
This page took 0.044833 seconds and 4 git commands to generate.