blob: e237d59aab6fb782eb68e2ee9a9837b57f57d8a4 [file] [log] [blame]
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +01001#!/usr/bin/env python3 -u
2
3""" lava_helper.py:
4
Matthew Hartfb6fd362020-03-04 21:03:59 +00005 Generate custom defined LAVA definitions rendered from Jinja2 templates.
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +01006 It can also parse the yaml output of LAVA and verify the test outcome """
7
8from __future__ import print_function
9
10__copyright__ = """
11/*
Xinyu Zhang33633322021-05-20 09:08:57 +080012 * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010013 *
14 * SPDX-License-Identifier: BSD-3-Clause
15 *
16 */
17 """
Karl Zhang08681e62020-10-30 13:56:03 +080018
19__author__ = "tf-m@lists.trustedfirmware.org"
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010020__project__ = "Trusted Firmware-M Open CI"
Xinyu Zhang06286a92021-07-22 14:00:51 +080021__version__ = "1.4.0"
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010022
23import os
24import sys
Matthew Hartfb6fd362020-03-04 21:03:59 +000025import shutil
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010026import argparse
27from copy import deepcopy
28from collections import OrderedDict
29from jinja2 import Environment, FileSystemLoader
30from lava_helper_configs import *
31
32try:
33 from tfm_ci_pylib.utils import save_json, load_json, sort_dict,\
Minos Galanakisea421232019-06-20 17:11:28 +010034 load_yaml, test, print_test
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010035 from tfm_ci_pylib.lava_rpc_connector import LAVA_RPC_connector
36except ImportError:
37 dir_path = os.path.dirname(os.path.realpath(__file__))
38 sys.path.append(os.path.join(dir_path, "../"))
39 from tfm_ci_pylib.utils import save_json, load_json, sort_dict,\
Minos Galanakisea421232019-06-20 17:11:28 +010040 load_yaml, test, print_test
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010041 from tfm_ci_pylib.lava_rpc_connector import LAVA_RPC_connector
42
43
44def sort_lavagen_config(cfg):
45 """ Create a constact dictionary object. This method is tailored for
46 the complicated configuration structure of this module """
47
48 res = OrderedDict()
49 if sorted(lavagen_config_sort_order) == sorted(cfg.keys()):
50 item_list = sorted(cfg.keys(),
51 key=lambda x: lavagen_config_sort_order.index(x))
52 else:
53 item_list = sorted(cfg.keys(), key=len)
54 for k in item_list:
55 v = cfg[k]
56 if isinstance(v, dict):
57 res[k] = sort_lavagen_config(v)
58 elif isinstance(v, list) and isinstance(v[0], dict):
59 res[k] = [sort_dict(e, lava_gen_monitor_sort_order) for e in v]
60 else:
61 res[k] = v
62 return res
63
64
65def save_config(cfg_f, cfg_obj):
66 """ Export configuration to json file """
67 save_json(cfg_f, sort_lavagen_config(cfg_obj))
68
69
70def print_configs():
71 """ Print supported configurations """
72
73 print("%(pad)s Built-in configurations: %(pad)s" % {"pad": "*" * 10})
74 for k in lava_gen_config_map.keys():
75 print("\t * %s" % k)
76
77
Matthew Hartfb6fd362020-03-04 21:03:59 +000078def get_artifact_url(artifact_store_url, params, filename):
Fathi Boudracaa90bd2020-12-04 22:00:14 +010079 url = "{}/{}/artifact/build-ci-all/{}_{}_Config{}_{}_{}/bin/{}/{}".format(
Matthew Hartfb6fd362020-03-04 21:03:59 +000080 artifact_store_url,
81 params['build_no'],
82 params['platform'],
83 params['compiler'],
84 params['name'],
85 params['build_type'],
86 params['boot_type'],
87 params['platform'],
88 filename,
89 )
Fathi Boudracaa90bd2020-12-04 22:00:14 +010090 return url
Matthew Hartfb6fd362020-03-04 21:03:59 +000091
92def get_recovery_url(recovery_store_url, build_no, recovery):
93 return("{}/{}/artifact/{}".format(
94 recovery_store_url,
95 build_no,
96 recovery
97 ))
98
99def get_job_name(name, params, job):
100 return("{}_{}_{}_{}_{}_{}_{}_{}".format(
101 name,
102 job,
103 params['platform'],
104 params['build_no'],
105 params['compiler'],
106 params['build_type'],
107 params['boot_type'],
108 params['name'],
109 ))
110
111def generate_test_definitions(config, work_dir, user_args):
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100112 """ Get a dictionary configuration, and an existing jinja2 template
113 and generate a LAVA compatbile yaml definition """
114
115 template_loader = FileSystemLoader(searchpath=work_dir)
116 template_env = Environment(loader=template_loader)
Matthew Hartfb6fd362020-03-04 21:03:59 +0000117 recovery_store_url = "{}/job/{}".format(
118 user_args.jenkins_url,
119 user_args.jenkins_job
120 )
121 build_no = user_args.build_no
122 artifact_store_url = recovery_store_url
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100123 template_file = config.pop("templ")
124
Matthew Hartfb6fd362020-03-04 21:03:59 +0000125 definitions = {}
126
127 for platform, recovery in config['platforms'].items():
128 recovery_image_url = get_recovery_url(
129 recovery_store_url,
130 build_no,
131 recovery)
132 for compiler in config['compilers']:
133 for build_type in config['build_types']:
134 for boot_type in config['boot_types']:
135 for test_name, test_dict in config['tests'].items():
136 params = {
137 "device_type": config['device_type'],
138 "job_timeout": config['job_timeout'],
139 "action_timeout": config['action_timeout'],
140 "monitor_timeout": config['monitor_timeout'],
141 "poweroff_timeout": config['poweroff_timeout'],
142 'compiler': compiler,
143 'build_type': build_type,
144 'build_no': build_no,
145 'boot_type': boot_type,
146 'name': test_name,
147 'test': test_dict,
148 'platform': platform,
149 'recovery_image_url': recovery_image_url,
150 }
151 params.update({
152 'firmware_url': get_artifact_url(
153 artifact_store_url,
154 params,
155 test_dict['binaries']['firmware']
156 ),
157 'bootloader_url': get_artifact_url(
158 artifact_store_url,
159 params,
160 test_dict['binaries']['bootloader']
161 )
162 })
163 params.update({
164 'job_name': get_job_name(
165 config['job_name'],
166 params,
167 user_args.jenkins_job,
168 )
169 })
170
171 definition = template_env.get_template(template_file).render(params)
172 definitions.update({params['job_name']: definition})
173 return definitions
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100174
175
176def generate_lava_job_defs(user_args, config):
177 """ Create a LAVA test job definition file """
178
179 # Evaluate current directory
180 if user_args.work_dir:
181 work_dir = os.path.abspath(user_args.work_dir)
182 else:
183 work_dir = os.path.abspath(os.path.dirname(__file__))
184
185 # If a single platform is requested and it exists in the platform
186 if user_args.platform and user_args.platform in config["platforms"]:
187 # Only test this platform
188 platform = user_args.platform
189 config["platforms"] = {platform: config["platforms"][platform]}
190
191 # Generate the ouptut definition
Matthew Hartfb6fd362020-03-04 21:03:59 +0000192 definitions = generate_test_definitions(config, work_dir, user_args)
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100193
194 # Write it into a file
Matthew Hartfb6fd362020-03-04 21:03:59 +0000195 out_dir = os.path.abspath(user_args.lava_def_output)
196 if os.path.exists(out_dir):
197 shutil.rmtree(out_dir)
198 os.makedirs(out_dir)
199 for name, definition in definitions.items():
200 out_file = os.path.join(out_dir, "{}{}".format(name, ".yaml"))
201 with open(out_file, "w") as F:
202 F.write(definition)
203 print("Definition created at %s" % out_file)
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100204
205
206def test_map_from_config(lvg_cfg=tfm_mps2_sse_200):
207 """ Extract all required information from a lavagen config map
208 and generate a map of required tests, indexed by test name """
209
210 test_map = {}
211 suffix_l = []
212 for p in lvg_cfg["platforms"]:
213 for c in lvg_cfg["compilers"]:
214 for bd in lvg_cfg["build_types"]:
215 for bt in lvg_cfg["boot_types"]:
216 suffix_l.append("%s_%s_%s_%s_%s" % (p, c, "%s", bd, bt))
217
218 for test_cfg_name, tst in lvg_cfg["tests"].items():
219 for monitor in tst["monitors"]:
220 for suffix in suffix_l:
221 key = (monitor["name"] + "_" + suffix % test_cfg_name).lower()
222 # print (monitor['required'])
223 test_map[key] = monitor['required']
224
225 return deepcopy(test_map)
226
227
228def test_lava_results(user_args, config):
229 """ Uses input of a test config dictionary and a LAVA summary Files
230 and determines if the test is a successful or not """
231
232 # Parse command line arguments to override config
233 result_raw = load_yaml(user_args.lava_results)
234
235 test_map = test_map_from_config(config)
236 t_dict = {k: {} for k in test_map}
237
238 # Return true if test is contained in test_groups
239 def test_filter(x):
240 return x["metadata"]['definition'] in test_map
241
242 # Create a dictionary with common keys as the test map and test results
243 # {test_suite: {test_name: pass/fail}}
244 def format_results(x):
245 t_dict[x["metadata"]["definition"]].update({x["metadata"]["case"]:
246 x["metadata"]["result"]})
247
248 # Remove all irelevant entries from data
249 test_results = list(filter(test_filter, result_raw))
250
251 # Call the formatter
252 list(map(format_results, test_results))
253
Minos Galanakisea421232019-06-20 17:11:28 +0100254 # Remove the ignored commits if requested
255 if user_args.ignore_configs:
256 print(user_args.ignore_configs)
257 for cfg in user_args.ignore_configs:
258 try:
259 print("Rejecting config: ", cfg)
260 t_dict.pop(cfg)
261 except KeyError as e:
262 print("Warning! Rejected config %s not found"
263 " in LAVA results" % cfg)
264
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100265 # We need to check that each of the tests contained in the test_map exist
266 # AND that they have a passed status
267 t_sum = 0
Minos Galanakisea421232019-06-20 17:11:28 +0100268
269 with open("lava_job.url", "r") as F:
270 job_url = F.read().strip()
271
272 out_rep = {"report": {},
273 "_metadata_": {"job_url": job_url}}
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100274 for k, v in t_dict.items():
275 try:
Minos Galanakisea421232019-06-20 17:11:28 +0100276 out_rep["report"][k] = test(test_map[k],
277 v,
278 pass_text=["pass"],
279 error_on_failed=False,
280 test_name=k,
281 summary=user_args.lava_summary)
282 t_sum += int(out_rep["report"][k]["success"])
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100283 # Status can be None if a test did't fully run/complete
284 except TypeError as E:
285 t_sum = 1
Minos Galanakisea421232019-06-20 17:11:28 +0100286 print("\n")
287 sl = [x["name"] for x in out_rep["report"].values()
288 if x["success"] is True]
289 fl = [x["name"] for x in out_rep["report"].values()
290 if x["success"] is False]
291
292 if sl:
293 print_test(t_list=sl, status="passed", tname="Tests")
294 if fl:
295 print_test(t_list=fl, status="failed", tname="Tests")
296
297 # Generate the output report is requested
298 if user_args.output_report:
299 save_json(user_args.output_report, out_rep)
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100300
301 # Every single of the tests need to have passed for group to succeed
302 if t_sum != len(t_dict):
303 print("Group Testing FAILED!")
Minos Galanakisea421232019-06-20 17:11:28 +0100304 if user_args.eif:
305 sys.exit(1)
306 else:
307 print("Group Testing PASS!")
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100308
309
310def test_lava_dispatch_credentials(user_args):
311 """ Will validate if provided token/credentials are valid. It will return
312 a valid connection or exit program if not"""
313
314 # Collect the authentication tokens
315 try:
316 if user_args.token_from_env:
317 usr = os.environ['LAVA_USER']
318 secret = os.environ['LAVA_TOKEN']
Xinyu Zhang33633322021-05-20 09:08:57 +0800319 elif user_args.lava_user and user_args.lava_token:
320 usr = user_args.lava_user
321 secret = user_args.lava_token
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100322
323 # Do not submit job without complete credentials
324 if not len(usr) or not len(secret):
325 raise Exception("Credentials not set")
326
327 lava = LAVA_RPC_connector(usr,
328 secret,
329 user_args.lava_url,
330 user_args.lava_rpc)
331
332 # Test the credentials againist the backend
333 if not lava.test_credentials():
334 raise Exception("Server rejected user authentication")
335 except Exception as e:
336 print("Credential validation failed with : %s" % e)
Xinyu Zhang33633322021-05-20 09:08:57 +0800337 print("Did you set set --lava_user, --lava_token?")
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100338 sys.exit(1)
339 return lava
340
341
342def lava_dispatch(user_args):
343 """ Submit a job to LAVA backend, block untill it is completed, and
344 fetch the results files if successful. If not, calls sys exit with 1
345 return code """
346
347 lava = test_lava_dispatch_credentials(user_args)
348 job_id, job_url = lava.submit_job(user_args.dispatch)
Minos Galanakisea421232019-06-20 17:11:28 +0100349
350 # The reason of failure will be reported to user by LAVA_RPC_connector
351 if job_id is None and job_url is None:
352 sys.exit(1)
353 else:
354 print("Job submitted at: " + job_url)
355
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100356 with open("lava_job.id", "w") as F:
357 F.write(str(job_id))
358 print("Job id %s stored at lava_job.id file." % job_id)
Minos Galanakisea421232019-06-20 17:11:28 +0100359 with open("lava_job.url", "w") as F:
360 F.write(str(job_url))
361 print("Job url %s stored at lava_job.url file." % job_id)
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100362
363 # Wait for the job to complete
364 status = lava.block_wait_for_job(job_id, int(user_args.dispatch_timeout))
365 print("Job %s returned with status: %s" % (job_id, status))
366 if status == "Complete":
367 lava.get_job_results(job_id, user_args.lava_job_results)
368 print("Job results exported at: %s" % user_args.lava_job_results)
369 sys.exit(0)
370 sys.exit(1)
371
372
373def dispatch_cancel(user_args):
374 """ Sends a cancell request for user provided job id (dispatch_cancel)"""
375 lava = test_lava_dispatch_credentials(user_args)
376 id = user_args.dispatch_cancel
377 result = lava.cancel_job(id)
378 print("Request to cancell job: %s returned with status %s" % (id, result))
379
380
381def load_config_overrides(user_args):
382 """ Load a configuration from multiple locations and override it with
383 user provided arguemnts """
384
385 if user_args.config_file:
386 print("Loading config from file %s" % user_args.config_file)
387 try:
388 config = load_json(user_args.config_file)
389 except Exception:
390 print("Failed to load config from: %s ." % user_args.config_file)
391 sys.exit(1)
392 else:
393 print("Using built-in config: %s" % user_args.config_key)
394 try:
395 config = lava_gen_config_map[user_args.config_key]
396 except KeyError:
397 print("No template found for config: %s" % user_args.config_key)
398 sys.exit(1)
399
400 config["build_no"] = user_args.build_no
401
Minos Galanakisea421232019-06-20 17:11:28 +0100402 # Override with command line provided URL/Job Name
403 if user_args.jenkins_url:
404 _over_d = {"jenkins_url": user_args.jenkins_url,
405 "jenkins_job": "%(jenkins_job)s"}
406 config["recovery_store_url"] = config["recovery_store_url"] % _over_d
407 config["artifact_store_url"] = config["artifact_store_url"] % _over_d
408
409 if user_args.jenkins_job:
410 _over_d = {"jenkins_job": user_args.jenkins_job}
411 config["recovery_store_url"] = config["recovery_store_url"] % _over_d
412 config["artifact_store_url"] = config["artifact_store_url"] % _over_d
413
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100414 # Add the template folder
415 config["templ"] = os.path.join(user_args.template_dir, config["templ"])
416 return config
417
418
419def main(user_args):
420 """ Main logic, forked according to task arguments """
421
422 # If a configuration listing is requested
423 if user_args.ls_config:
424 print_configs()
425 return
426 elif user_args.cconfig:
427 config_key = user_args.cconfig
428 if config_key in lava_gen_config_map.keys():
429 config_file = "lava_job_gen_cfg_%s.json" % config_key
430 save_config(config_file, lava_gen_config_map[config_key])
431 print("Configuration exported at %s" % config_file)
432 return
Minos Galanakisea421232019-06-20 17:11:28 +0100433 if user_args.dispatch is not None or user_args.dispatch_cancel is not None:
434 pass
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100435 else:
436 config = load_config_overrides(user_args)
437
438 # Configuration is assumed fixed at this point
439 if user_args.lava_results:
440 print("Evaluating File", user_args.lava_results)
441 test_lava_results(user_args, config)
442 elif user_args.dispatch:
443 lava_dispatch(user_args)
444 elif user_args.dispatch_cancel:
445 dispatch_cancel(user_args)
446 elif user_args.create_definition:
447 print("Generating Lava")
448 generate_lava_job_defs(user_args, config)
449 else:
450 print("Nothing to do, please select a task")
451
452
453def get_cmd_args():
454 """ Parse command line arguments """
455
456 # Parse command line arguments to override config
457 parser = argparse.ArgumentParser(description="Lava Helper")
458
459 def_g = parser.add_argument_group('Create LAVA Definition')
460 disp_g = parser.add_argument_group('Dispatch LAVA job')
461 parse_g = parser.add_argument_group('Parse LAVA results')
462 config_g = parser.add_argument_group('Configuration handling')
463 over_g = parser.add_argument_group('Overrides')
464
465 # Configuration control
466 config_g.add_argument("-cn", "--config-name",
467 dest="config_key",
468 action="store",
469 default="tfm_mps2_sse_200",
470 help="Select built-in configuration by name")
471 config_g.add_argument("-cf", "--config-file",
472 dest="config_file",
473 action="store",
474 help="Load config from external file in JSON format")
475 config_g.add_argument("-te", "--task-config-export",
476 dest="cconfig",
477 action="store",
478 help="Export a json file with the current config "
479 "parameters")
480 config_g.add_argument("-tl", "--task-config-list",
481 dest="ls_config",
482 action="store_true",
483 default=False,
484 help="List built-in configurations")
485
486 def_g.add_argument("-tc", "--task-create-definition",
487 dest="create_definition",
488 action="store_true",
489 default=False,
490 help="Used in conjunction with --config parameters. "
491 "A LAVA compatible job definition will be created")
492 def_g.add_argument("-cb", "--create-definition-build-no",
493 dest="build_no",
494 action="store",
495 default="lastSuccessfulBuild",
496 help="JENKINGS Build number selector. "
497 "Default: lastSuccessfulBuild")
Matthew Hartfb6fd362020-03-04 21:03:59 +0000498 def_g.add_argument("-co", "--create-definition-output-dir",
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100499 dest="lava_def_output",
500 action="store",
Matthew Hartfb6fd362020-03-04 21:03:59 +0000501 default="job_results",
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100502 help="Set LAVA compatible .yaml output file")
503
504 # Parameter override commands
505 over_g.add_argument("-ow", "--override-work-path",
506 dest="work_dir",
507 action="store",
508 help="Working Directory (absolute path)")
509 over_g.add_argument("-ot", "--override-template-dir",
510 dest="template_dir",
511 action="store",
512 default="jinja2_templates",
513 help="Set directory where Jinja2 templates are stored")
514 over_g.add_argument("-op", "--override-platform",
515 dest="platform",
516 action="store",
517 help="Override platform.Only the provided one "
Minos Galanakisea421232019-06-20 17:11:28 +0100518 "will be tested")
519 over_g.add_argument("-ou", "--override-jenkins-url",
520 dest="jenkins_url",
521 action="store",
Minos Galanakis44074242019-10-14 09:59:11 +0100522 help="Override %%(jenkins_url)s params in config if "
Minos Galanakisea421232019-06-20 17:11:28 +0100523 "present. Sets the jenkings address including "
524 "port")
525 over_g.add_argument("-oj", "--override-jenkins-job",
526 dest="jenkins_job",
527 action="store",
Minos Galanakis44074242019-10-14 09:59:11 +0100528 help="Override %%(jenkins_job)s params in config if "
Minos Galanakisea421232019-06-20 17:11:28 +0100529 "present. Sets the jenkings job name")
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100530 parse_g.add_argument("-tp", "--task-lava-parse",
531 dest="lava_results",
532 action="store",
533 help="Parse provided yaml file, using a configuration"
534 " as reference to determine the outpcome"
535 " of testing")
536 parse_g.add_argument("-ls", "--lava-parse-summary",
537 dest="lava_summary",
Minos Galanakisea421232019-06-20 17:11:28 +0100538 default=False,
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100539 action="store_true",
540 help="Print full test summary")
Minos Galanakisea421232019-06-20 17:11:28 +0100541 parse_g.add_argument("-or", "--output-report",
542 dest="output_report",
543 action="store",
544 help="Print full test summary")
545 parser.add_argument("-ef", "--error-if-failed",
546 dest="eif",
547 action="store_true",
548 help="If set will change the script exit code if one "
549 "or more tests fail")
550 parser.add_argument('-ic', '--ignore-configs',
551 dest="ignore_configs",
552 nargs='+',
553 help="Pass a space separated list of build"
554 "configurations which will get ignored when"
555 "evaluation LAVA results")
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100556
557 # Lava job control commands
558 disp_g.add_argument("-td", "--task-dispatch",
559 dest="dispatch",
560 action="store",
561 help="Submit yaml file defined job to backend, and "
562 "wait for it to complete. \nRequires:"
563 " --lava_url --lava_token_usr/pass/--"
564 "lava_token_from_environ arguments, with optional"
565 "\n--lava_rpc_prefix\n--lava-job-results\n"
566 "parameters. \nIf not set they get RPC2 and "
567 "lava_job_results.yaml default values.\n"
568 "The number job id will be stored at lava_job.id")
569 disp_g.add_argument("-dc", "--dispatch-cancel",
570 dest="dispatch_cancel",
571 action="store",
572 help="Send a cancell request for job with provided id")
573 disp_g.add_argument("-dt", "--dispatch-timeout",
574 dest="dispatch_timeout",
575 default="3600",
576 action="store",
577 help="Maximum Time to block for job"
578 " submission to complete")
579 disp_g.add_argument("-dl", "--dispatch-lava-url",
580 dest="lava_url",
581 action="store",
582 help="Sets the lava hostname during job dispatch")
583 disp_g.add_argument("-dr", "--dispatch-lava-rpc-prefix",
584 dest="lava_rpc",
585 action="store",
586 default="RPC2",
587 help="Application prefix on Backend"
588 "(i.e www.domain.com/APP)\n"
589 "By default set to RPC2")
590 disp_g.add_argument("-du", "--dispatch-lava_token_usr",
Xinyu Zhang33633322021-05-20 09:08:57 +0800591 dest="lava_user",
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100592 action="store",
593 help="Lava user submitting the job")
594 disp_g.add_argument("-ds", "--dispatch-lava_token_secret",
Xinyu Zhang33633322021-05-20 09:08:57 +0800595 dest="lava_token",
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100596 action="store",
597 help="Hash token used to authenticate"
598 "user during job submission")
599 disp_g.add_argument("-de", "--dispatch-lava_token_from_environ",
600 dest="token_from_env",
601 action="store_true",
602 help="If set dispatcher will use the enviroment"
603 "stored $LAVA_USER, $LAVA_TOKEN for credentials")
604 disp_g.add_argument("-df", "--dispatch-lava-job-results-file",
605 dest="lava_job_results",
606 action="store",
607 default="lava_job_results.yaml",
608 help="Name of the job results file after job is "
609 "complete. Default: lava_job_results.yaml")
610 return parser.parse_args()
611
612
613if __name__ == "__main__":
614 main(get_cmd_args())