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