LAVA: Upload results to obj.internal.efficios.com
[lttng-ci.git] / scripts / system-tests / lava-submit.py
CommitLineData
b3d73c46
FD
1#!/usr/bin/python
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
18import base64
19import json
20import os
78cb511c 21import random
b3d73c46
FD
22import sys
23import time
f42b2b7e 24import xmlrpc.client
6b35e57c
JR
25from urllib.parse import urljoin
26from urllib.request import urlretrieve
b3d73c46
FD
27from collections import OrderedDict
28from enum import Enum
29
30USERNAME = 'frdeso'
31HOSTNAME = 'lava-master.internal.efficios.com'
32SCP_PATH = 'scp://jenkins-lava@storage.internal.efficios.com'
6b35e57c 33OBJSTORE_URL = "https://obj.internal.efficios.com/lava/results/"
b3d73c46
FD
34
35class TestType(Enum):
1ac7fa2c
FD
36 baremetal_benchmarks=1
37 baremetal_tests=2
38 kvm_tests=3
a2243f89 39 kvm_fuzzing_tests=4
b3d73c46
FD
40
41def get_job_bundle_content(server, job):
534a243d
FD
42 try:
43 bundle_sha = server.scheduler.job_status(str(job))['bundle_sha1']
44 bundle = server.dashboard.get(bundle_sha)
f42b2b7e
FD
45 except xmlrpc.client.Fault as f:
46 print('Error while fetching results bundle', f.faultString)
5c0f342c 47 raise f
b3d73c46
FD
48
49 return json.loads(bundle['content'])
50
51# Parse the results bundle to see the run-tests testcase
52# of the lttng-kernel-tests passed successfully
53def check_job_all_test_cases_state_count(server, job):
54 content = get_job_bundle_content(server, job)
55
1d393f82
FD
56 # FIXME:Those tests are part of the boot actions and fail randomly but
57 # doesn't affect the behaviour of the tests. We should update our Lava
58 # installation and try to reproduce it. This error was encountered on
59 # Ubuntu 16.04.
60 tests_known_to_fail=['mount', 'df', 'ls', 'ip', 'wait_for_test_image_prompt']
61
b3d73c46
FD
62 passed_tests=0
63 failed_tests=0
64 for run in content['test_runs']:
65 for result in run['test_results']:
3e7245a4 66 if 'test_case_id' in result :
b3d73c46
FD
67 if result['result'] in 'pass':
68 passed_tests+=1
1d393f82 69 elif result['test_case_id'] in tests_known_to_fail:
3e7245a4 70 pass
b3d73c46
FD
71 else:
72 failed_tests+=1
73 return (passed_tests, failed_tests)
74
104ed94b
FD
75# Get the benchmark results from the lava bundle
76# save them as CSV files localy
6b35e57c 77def fetch_benchmark_results(build_id):
70e85c98 78 testcases = ['processed_results_close.csv',
c863d7ca 79 'processed_results_ioctl.csv',
70e85c98 80 'processed_results_open_efault.csv',
6ebb7306 81 'processed_results_open_enoent.csv',
dff1609b 82 'processed_results_dup_close.csv',
0ca122b6 83 'processed_results_raw_syscall_getpid.csv',
dff1609b 84 'processed_results_lttng_test_filter.csv']
6b35e57c
JR
85 for testcase in testcases:
86 url = urljoin(OBJSTORE_URL, "{:s}/{:s}".format(build_id, testcase))
87 urlretrieve(url, case)
104ed94b 88
b3d73c46
FD
89# Parse the attachment of the testcase to fetch the stdout of the test suite
90def print_test_output(server, job):
91 content = get_job_bundle_content(server, job)
92 found = False
93
94 for run in content['test_runs']:
95 if run['test_id'] in 'lttng-kernel-test':
96 for attachment in run['attachments']:
97 if attachment['pathname'] in 'stdout.log':
98
99 # Decode the base64 file and split on newlines to iterate
100 # on list
6d7f7c11
FD
101 testoutput = str(base64.b64decode(bytes(attachment['content'], encoding='UTF-8')))
102
103 testoutput = testoutput.replace('\\n', '\n')
b3d73c46
FD
104
105 # Create a generator to iterate on the lines and keeping
106 # the state of the iterator across the two loops.
6d7f7c11 107 testoutput_iter = iter(testoutput.split('\n'))
b3d73c46
FD
108 for line in testoutput_iter:
109
110 # Find the header of the test case and start printing
111 # from there
112 if 'LAVA_SIGNAL_STARTTC run-tests' in line:
b3d73c46
FD
113 print('---- TEST SUITE OUTPUT BEGIN ----')
114 for line in testoutput_iter:
115 if 'LAVA_SIGNAL_ENDTC run-tests' not in line:
116 print(line)
117 else:
118 # Print until we reach the end of the
119 # section
120 break
121
b3d73c46
FD
122 print('----- TEST SUITE OUTPUT END -----')
123 break
124
dc9700c9 125def create_new_job(name, build_device):
b3d73c46
FD
126 job = OrderedDict({
127 'health_check': False,
128 'job_name': name,
10ca6e3a 129 'device_type': build_device,
dc9700c9 130 'tags': [ ],
10ca6e3a 131 'timeout': 7200,
b3d73c46
FD
132 'actions': []
133 })
dc9700c9
FD
134 if build_device in 'x86':
135 job['tags'].append('dev-sda1')
136
b3d73c46
FD
137 return job
138
139def get_boot_cmd():
140 command = OrderedDict({
141 'command': 'boot_image'
142 })
143 return command
144
dc9700c9 145def get_config_cmd(build_device):
b3d73c46
FD
146 packages=['bsdtar', 'psmisc', 'wget', 'python3', 'python3-pip', \
147 'libglib2.0-dev', 'libffi-dev', 'elfutils', 'libdw-dev', \
e1504b01 148 'libelf-dev', 'libmount-dev', 'libxml2', 'libpfm4-dev', \
30b89c1f 149 'libnuma-dev', 'python3-dev', 'swig', 'stress']
b3d73c46
FD
150 command = OrderedDict({
151 'command': 'lava_command_run',
152 'parameters': {
153 'commands': [
b3d73c46
FD
154 'cat /etc/resolv.conf',
155 'echo nameserver 172.18.0.12 > /etc/resolv.conf',
dc9700c9 156 'groupadd tracing'
38cfd62c
FD
157 ],
158 'timeout':300
b3d73c46
FD
159 }
160 })
dc9700c9
FD
161 if build_device in 'x86':
162 command['parameters']['commands'].extend([
163 'mount /dev/sda1 /tmp',
164 'rm -rf /tmp/*'])
165
166 command['parameters']['commands'].extend([
167 'depmod -a',
168 'locale-gen en_US.UTF-8',
169 'apt-get update',
819f0b86 170 'apt-get upgrade',
dc9700c9
FD
171 'apt-get install -y {}'.format(' '.join(packages))
172 ])
b3d73c46
FD
173 return command
174
6b35e57c 175def get_baremetal_benchmarks_cmd(build_id):
b3d73c46
FD
176 command = OrderedDict({
177 'command': 'lava_test_shell',
178 'parameters': {
179 'testdef_repos': [
180 {
181 'git-repo': 'https://github.com/lttng/lttng-ci.git',
182 'revision': 'master',
6b35e57c
JR
183 'testdef': 'lava/system-tests/failing-close.yml',
184 'parameters': { 'JENKINS_BUILD_ID': build_id }
b3d73c46 185 },
c863d7ca
FD
186 {
187 'git-repo': 'https://github.com/lttng/lttng-ci.git',
188 'revision': 'master',
6b35e57c
JR
189 'testdef': 'lava/system-tests/failing-ioctl.yml',
190 'parameters': { 'JENKINS_BUILD_ID': build_id }
c863d7ca 191 },
b3d73c46
FD
192 {
193 'git-repo': 'https://github.com/lttng/lttng-ci.git',
194 'revision': 'master',
6b35e57c
JR
195 'testdef': 'lava/system-tests/failing-open-efault.yml',
196 'parameters': { 'JENKINS_BUILD_ID': build_id }
b3d73c46
FD
197 },
198 {
199 'git-repo': 'https://github.com/lttng/lttng-ci.git',
200 'revision': 'master',
6b35e57c
JR
201 'testdef': 'lava/system-tests/success-dup-close.yml',
202 'parameters': { 'JENKINS_BUILD_ID': build_id }
dff1609b 203 },
0ca122b6
FD
204 {
205 'git-repo': 'https://github.com/lttng/lttng-ci.git',
206 'revision': 'master',
6b35e57c
JR
207 'testdef': 'lava/system-tests/raw-syscall-getpid.yml',
208 'parameters': { 'JENKINS_BUILD_ID': build_id }
0ca122b6 209 },
6ebb7306
FD
210 {
211 'git-repo': 'https://github.com/lttng/lttng-ci.git',
212 'revision': 'master',
6b35e57c
JR
213 'testdef': 'lava/system-tests/failing-open-enoent.yml',
214 'parameters': { 'JENKINS_BUILD_ID': build_id }
6ebb7306 215 },
dff1609b
FD
216 {
217 'git-repo': 'https://github.com/lttng/lttng-ci.git',
218 'revision': 'master',
6b35e57c
JR
219 'testdef': 'lava/system-tests/lttng-test-filter.yml',
220 'parameters': { 'JENKINS_BUILD_ID': build_id }
1ac7fa2c
FD
221 }
222 ],
10ca6e3a 223 'timeout': 7200
1ac7fa2c
FD
224 }
225 })
226 return command
227
6b35e57c 228def get_baremetal_tests_cmd(build_id):
1ac7fa2c
FD
229 command = OrderedDict({
230 'command': 'lava_test_shell',
231 'parameters': {
232 'testdef_repos': [
f3d4ee9f
FD
233 {
234 'git-repo': 'https://github.com/lttng/lttng-ci.git',
235 'revision': 'master',
6b35e57c
JR
236 'testdef': 'lava/system-tests/perf-tests.yml',
237 'parameters': { 'JENKINS_BUILD_ID': build_id }
b3d73c46
FD
238 }
239 ],
10ca6e3a 240 'timeout': 3600
b3d73c46
FD
241 }
242 })
243 return command
244
6b35e57c 245def get_kvm_tests_cmd(build_id):
b3d73c46
FD
246 command = OrderedDict({
247 'command': 'lava_test_shell',
248 'parameters': {
249 'testdef_repos': [
250 {
251 'git-repo': 'https://github.com/lttng/lttng-ci.git',
252 'revision': 'master',
6b35e57c
JR
253 'testdef': 'lava/system-tests/kernel-tests.yml',
254 'parameters': { 'JENKINS_BUILD_ID': build_id }
ee02050f
FD
255 },
256 {
257 'git-repo': 'https://github.com/lttng/lttng-ci.git',
258 'revision': 'master',
6b35e57c
JR
259 'testdef': 'lava/system-tests/destructive-tests.yml',
260 'parameters': { 'JENKINS_BUILD_ID': build_id }
9d9c173f
FD
261 }
262 ],
958065a8 263 'timeout': 7200
9d9c173f
FD
264 }
265 })
266 return command
6dffa64f
FD
267
268def get_kprobes_generate_data_cmd():
78cb511c 269 random_seed = random.randint(0, 1000000)
6dffa64f
FD
270 command = OrderedDict({
271 'command': 'lava_test_shell',
272 'parameters': {
273 'testdef_repos': [
274 {
275 'git-repo': 'https://github.com/lttng/lttng-ci.git',
276 'revision': 'master',
78cb511c
FD
277 'testdef': 'lava/system-tests/kprobe-fuzzing-generate-data.yml',
278 'parameters': { 'RANDOM_SEED': str(random_seed) }
6dffa64f
FD
279 }
280 ],
281 'timeout': 60
282 }
283 })
284 return command
285
c5b4a212 286def get_kprobes_test_cmd(round_nb):
9d9c173f
FD
287 command = OrderedDict({
288 'command': 'lava_test_shell',
289 'parameters': {
290 'testdef_repos': [
30b89c1f
FD
291 {
292 'git-repo': 'https://github.com/lttng/lttng-ci.git',
293 'revision': 'master',
c5b4a212
FD
294 'testdef': 'lava/system-tests/kprobe-fuzzing-tests.yml',
295 'parameters': { 'ROUND_NB': str(round_nb) }
b3d73c46 296 }
c5b4a212
FD
297 ],
298 'timeout': 1000
b3d73c46
FD
299 }
300 })
301 return command
302
303def get_results_cmd(stream_name):
304 command = OrderedDict({
305 'command': 'submit_results',
306 'parameters': {
307 'server': 'http://lava-master.internal.efficios.com/RPC2/'
308 }
309 })
310 command['parameters']['stream']='/anonymous/'+stream_name+'/'
311 return command
312
35b46f08 313def get_deploy_cmd_kvm(jenkins_job, kernel_path, lttng_modules_path):
dc9700c9
FD
314 command = OrderedDict({
315 'command': 'deploy_kernel',
316 'metadata': {},
317 'parameters': {
318 'customize': {},
319 'kernel': None,
819f0b86
FD
320 'target_type': 'ubuntu',
321 'rootfs': 'file:///var/lib/lava-server/default/media/images/xenial.img.gz',
322 'login_prompt': 'kvm02 login:',
323 'username': 'root'
dc9700c9
FD
324 }
325 })
326
dc9700c9
FD
327 command['parameters']['customize'][SCP_PATH+lttng_modules_path]=['rootfs:/','archive']
328 command['parameters']['kernel'] = str(SCP_PATH+kernel_path)
329 command['metadata']['jenkins_jobname'] = jenkins_job
330
331 return command
332
35b46f08 333def get_deploy_cmd_x86(jenkins_job, kernel_path, lttng_modules_path, nb_iter=None):
b3d73c46
FD
334 command = OrderedDict({
335 'command': 'deploy_kernel',
336 'metadata': {},
337 'parameters': {
338 'overlays': [],
339 'kernel': None,
340 'nfsrootfs': str(SCP_PATH+'/storage/jenkins-lava/rootfs/rootfs_amd64_trusty_2016-02-23-1134.tar.gz'),
341 'target_type': 'ubuntu'
342 }
343 })
344
b3d73c46
FD
345 command['parameters']['overlays'].append( str(SCP_PATH+lttng_modules_path))
346 command['parameters']['kernel'] = str(SCP_PATH+kernel_path)
dc9700c9 347 command['metadata']['jenkins_jobname'] = jenkins_job
b3d73c46
FD
348 if nb_iter is not None:
349 command['metadata']['nb_iterations'] = nb_iter
350
351 return command
352
353
dc9700c9 354def get_env_setup_cmd(build_device, lttng_tools_commit, lttng_ust_commit=None):
b3d73c46
FD
355 command = OrderedDict({
356 'command': 'lava_command_run',
357 'parameters': {
358 'commands': [
819f0b86 359 'pip3 install --upgrade pip',
46fb8afa 360 'hash -r',
b3d73c46
FD
361 'pip3 install vlttng',
362 ],
10ca6e3a 363 'timeout': 3600
b3d73c46
FD
364 }
365 })
366
4418be37 367 vlttng_cmd = 'vlttng --jobs=$(nproc) --profile urcu-master' \
c6204172
FD
368 ' --override projects.babeltrace.build-env.PYTHON=python3' \
369 ' --override projects.babeltrace.build-env.PYTHON_CONFIG=python3-config' \
370 ' --profile babeltrace-stable-1.4' \
371 ' --profile babeltrace-python' \
b3d73c46
FD
372 ' --profile lttng-tools-master' \
373 ' --override projects.lttng-tools.checkout='+lttng_tools_commit + \
374 ' --profile lttng-tools-no-man-pages'
375
376 if lttng_ust_commit is not None:
377 vlttng_cmd += ' --profile lttng-ust-master ' \
378 ' --override projects.lttng-ust.checkout='+lttng_ust_commit+ \
379 ' --profile lttng-ust-no-man-pages'
380
dc9700c9
FD
381 virtenv_path = None
382 if build_device in 'kvm':
383 virtenv_path = '/root/virtenv'
384 else:
385 virtenv_path = '/tmp/virtenv'
386
387 vlttng_cmd += ' '+virtenv_path
b3d73c46
FD
388
389 command['parameters']['commands'].append(vlttng_cmd)
dc9700c9
FD
390 command['parameters']['commands'].append('ln -s '+virtenv_path+' /root/lttngvenv')
391 command['parameters']['commands'].append('sync')
392
b3d73c46
FD
393 return command
394
395def main():
396 test_type = None
397 parser = argparse.ArgumentParser(description='Launch baremetal test using Lava')
398 parser.add_argument('-t', '--type', required=True)
399 parser.add_argument('-j', '--jobname', required=True)
400 parser.add_argument('-k', '--kernel', required=True)
b3d73c46 401 parser.add_argument('-lm', '--lmodule', required=True)
b3d73c46 402 parser.add_argument('-tc', '--tools-commit', required=True)
6b35e57c 403 parser.add_argument('-id', '--build-id', required=True)
b3d73c46
FD
404 parser.add_argument('-uc', '--ust-commit', required=False)
405 args = parser.parse_args()
406
1ac7fa2c
FD
407 if args.type in 'baremetal-benchmarks':
408 test_type = TestType.baremetal_benchmarks
409 elif args.type in 'baremetal-tests':
410 test_type = TestType.baremetal_tests
411 elif args.type in 'kvm-tests':
412 test_type = TestType.kvm_tests
a2243f89
FD
413 elif args.type in 'kvm-fuzzing-tests':
414 test_type = TestType.kvm_fuzzing_tests
b3d73c46
FD
415 else:
416 print('argument -t/--type {} unrecognized. Exiting...'.format(args.type))
417 return -1
418
8cef2adf
FD
419 lava_api_key = None
420 try:
30003819 421 lava_api_key = os.environ['LAVA_JENKINS_TOKEN']
f42b2b7e 422 except Exception as e:
30003819 423 print('LAVA_JENKINS_TOKEN not found in the environment variable. Exiting...', e )
8cef2adf
FD
424 return -1
425
1ac7fa2c 426 if test_type is TestType.baremetal_benchmarks:
dc9700c9 427 j = create_new_job(args.jobname, build_device='x86')
35b46f08 428 j['actions'].append(get_deploy_cmd_x86(args.jobname, args.kernel, args.lmodule))
1ac7fa2c
FD
429 elif test_type is TestType.baremetal_tests:
430 j = create_new_job(args.jobname, build_device='x86')
35b46f08 431 j['actions'].append(get_deploy_cmd_x86(args.jobname, args.kernel, args.lmodule))
a2243f89 432 elif test_type is TestType.kvm_tests or test_type is TestType.kvm_fuzzing_tests:
dc9700c9 433 j = create_new_job(args.jobname, build_device='kvm')
35b46f08 434 j['actions'].append(get_deploy_cmd_kvm(args.jobname, args.kernel, args.lmodule))
dc9700c9
FD
435
436 j['actions'].append(get_boot_cmd())
437
1ac7fa2c 438 if test_type is TestType.baremetal_benchmarks:
dc9700c9
FD
439 j['actions'].append(get_config_cmd('x86'))
440 j['actions'].append(get_env_setup_cmd('x86', args.tools_commit))
6b35e57c 441 j['actions'].append(get_baremetal_benchmarks_cmd(args.build_id))
b3d73c46 442 j['actions'].append(get_results_cmd(stream_name='benchmark-kernel'))
1ac7fa2c
FD
443 elif test_type is TestType.baremetal_tests:
444 if args.ust_commit is None:
445 print('Tests runs need -uc/--ust-commit options. Exiting...')
446 return -1
447 j['actions'].append(get_config_cmd('x86'))
448 j['actions'].append(get_env_setup_cmd('x86', args.tools_commit, args.ust_commit))
6b35e57c 449 j['actions'].append(get_baremetal_tests_cmd(args.build_id))
1ac7fa2c
FD
450 j['actions'].append(get_results_cmd(stream_name='tests-kernel'))
451 elif test_type is TestType.kvm_tests:
b3d73c46
FD
452 if args.ust_commit is None:
453 print('Tests runs need -uc/--ust-commit options. Exiting...')
454 return -1
dc9700c9
FD
455 j['actions'].append(get_config_cmd('kvm'))
456 j['actions'].append(get_env_setup_cmd('kvm', args.tools_commit, args.ust_commit))
6b35e57c 457 j['actions'].append(get_kvm_tests_cmd(args.build_id))
a2243f89
FD
458 j['actions'].append(get_results_cmd(stream_name='tests-kernel'))
459 elif test_type is TestType.kvm_fuzzing_tests:
460 if args.ust_commit is None:
461 print('Tests runs need -uc/--ust-commit options. Exiting...')
462 return -1
463 j['actions'].append(get_config_cmd('kvm'))
6dffa64f 464 j['actions'].append(get_kprobes_generate_data_cmd())
c5b4a212
FD
465 for i in range(10):
466 j['actions'].append(get_kprobes_test_cmd(round_nb=i))
b3d73c46
FD
467 j['actions'].append(get_results_cmd(stream_name='tests-kernel'))
468 else:
469 assert False, 'Unknown test type'
470
f42b2b7e 471 server = xmlrpc.client.ServerProxy('http://%s:%s@%s/RPC2' % (USERNAME, lava_api_key, HOSTNAME))
b3d73c46
FD
472
473 jobid = server.scheduler.submit_job(json.dumps(j))
474
21e89f7e 475 print('Lava jobid:{}'.format(jobid))
0467dff8 476 print('Lava job URL: http://lava-master.internal.efficios.com/scheduler/job/{}/log_file'.format(jobid))
21e89f7e 477
b3d73c46
FD
478 #Check the status of the job every 30 seconds
479 jobstatus = server.scheduler.job_status(jobid)['job_status']
d9997fe4 480 not_running = False
b3d73c46 481 while jobstatus in 'Submitted' or jobstatus in 'Running':
d9997fe4
FD
482 if not_running is False and jobstatus in 'Running':
483 print('Job started running')
484 not_running = True
b3d73c46
FD
485 time.sleep(30)
486 jobstatus = server.scheduler.job_status(jobid)['job_status']
487
534a243d 488 if test_type is TestType.kvm_tests or test_type is TestType.baremetal_tests:
b3d73c46 489 print_test_output(server, jobid)
104ed94b 490 elif test_type is TestType.baremetal_benchmarks:
6b35e57c 491 fetch_benchmark_results(args.build_id)
b3d73c46 492
d1b69f4d
FD
493 print('Job ended with {} status.'.format(jobstatus))
494 if jobstatus not in 'Complete':
495 return -1
496 else:
73c1d4bc 497 passed, failed=check_job_all_test_cases_state_count(server, jobid)
d1b69f4d
FD
498 print('With {} passed and {} failed Lava test cases.'.format(passed, failed))
499
73c1d4bc
FD
500 if failed == 0:
501 return 0
502 else:
503 return -1
b3d73c46
FD
504
505if __name__ == "__main__":
506 sys.exit(main())
This page took 0.048601 seconds and 4 git commands to generate.