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