1 # Copyright 2018 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 """Parse & Validate CLI arguments for run_suite_skylab.py.""" 6 7 from __future__ import absolute_import 8 from __future__ import division 9 from __future__ import print_function 10 11 import argparse 12 import ast 13 import sys 14 15 from lucifer import autotest 16 from skylab_suite import cros_suite 17 from skylab_suite import swarming_lib 18 19 20 def make_parser(): 21 """Make ArgumentParser instance for run_suite_skylab.py.""" 22 parser = argparse.ArgumentParser(prog='run_suite_skylab', 23 description="Run a test suite in Skylab.") 24 25 # Suite-related parameters. 26 parser.add_argument('--board', required=True) 27 parser.add_argument( 28 '--model', default=None, 29 help=('The device model to run tests against. For non-unified ' 30 'builds, model and board are synonymous, but board is more ' 31 'accurate in some cases. Only pass this option if your build ' 32 'is a unified build.')) 33 # Allow customized pool label temporarily for crbug.com/913623. 34 parser.add_argument( 35 '--pool', default='suites', 36 help=('Specify the pool of DUTs to run this suite. Default: suites. ' 37 'If you want no pool, you can specify it with --pool="". ' 38 'USE WITH CARE.')) 39 parser.add_argument( 40 '--suite_name', required=True, 41 help='Specify the suite to run.') 42 parser.add_argument( 43 '--build', required=True, 44 help='Specify the build to run the suite with.') 45 parser.add_argument( 46 '--cheets_build', default=None, 47 help='ChromeOS Android build to be installed on dut.') 48 parser.add_argument( 49 '--firmware_rw_build', default=None, 50 help='Firmware build to be installed in dut RW firmware.') 51 parser.add_argument( 52 '--firmware_ro_build', default=None, 53 help='Firmware build to be installed in dut RO firmware.') 54 parser.add_argument( 55 '--test_source_build', default=None, 56 help=('Build that contains the test code. It can be the value ' 57 'of arguments "--build", "--firmware_rw_build" or ' 58 '"--firmware_ro_build". Default is to use test code from ' 59 'the "--build" version (CrOS image)')) 60 parser.add_argument( 61 '--priority', type=int, 62 default=swarming_lib.SKYLAB_HWTEST_PRIORITIES_MAP['Default'], 63 choices=[value for name, value in 64 swarming_lib.SORTED_SKYLAB_HWTEST_PRIORITY], 65 help=('The priority to run the suite. A high value means this suite ' 66 'will be executed in a low priority, e.g. being delayed to ' 67 'execute. Each numerical value represents: '+ ', '.join([ 68 '(%s: %d)' % (name, value) for name, value in 69 swarming_lib.SORTED_SKYLAB_HWTEST_PRIORITY]))) 70 parser.add_argument( 71 "--suite_args", type=ast.literal_eval, default=None, 72 action="store", 73 help="A dict of args passed to the suite control file.") 74 parser.add_argument( 75 "--job_keyvals", type=ast.literal_eval, default={}, 76 action="store", 77 help="A dict of job keyvals to be passed to child jobs.") 78 parser.add_argument( 79 "--minimum_duts", type=int, default=1, action="store", 80 help="A minimum required numbers of DUTs to run this suite.") 81 parser.add_argument( 82 '--quota_account', default=None, action='store', 83 help=("Quota account to be used for this suite's jobs, if applicable. " 84 "Only relevant for jobs running in a quota scheduler pool " 85 "(e.g. quota-metered).")) 86 parser.add_argument( 87 '--swarming_auth_json', default=swarming_lib.DEFAULT_SERVICE_ACCOUNT, 88 action='store', help="Path to swarming service account json creds. " 89 "Specify '' to omit. Otherwise, defaults to bot's default creds.") 90 91 # TODO(ayatane): Make sure no callers pass --use_fallback before removing. 92 parser.add_argument( 93 "--use_fallback", action="store_true", help='Deprecated') 94 95 # Swarming-related parameters. 96 parser.add_argument( 97 '--execution_timeout_seconds', type=int, default=30, 98 help='Seconds to allow a task to complete, once execution beings.') 99 100 # logic-related parameters. 101 parser.add_argument( 102 '--create_and_return', action='store_true', 103 help='Create the child jobs of a suite, then finish immediately.') 104 parser.add_argument( 105 '--suite_id', default=None, 106 help='A suite ID, wait for whose child tests to finish.') 107 parser.add_argument( 108 '--test_retry', default=False, action='store_true', 109 help='Enable test-level retry.') 110 parser.add_argument( 111 '--max_retries', default=0, type=int, action='store', 112 help='Maximum retries allowed at suite level. No retry if it is 0.') 113 parser.add_argument( 114 '--timeout_mins', default=90, type=int, action='store', 115 help='Maximum minutes to wait for a suite to finish.') 116 parser.add_argument( 117 '--passed_mins', default=0, type=int, action='store', 118 help='The minutes that this suite already runs for.') 119 parser.add_argument( 120 '--run_prod_code', action='store_true', default=False, 121 help='Run the test code that lives in prod aka the test ' 122 'code currently on the lab servers.') 123 parser.add_argument( 124 '--dry_run', action='store_true', 125 help=('Used for kicking off a run of suite with fake commands.')) 126 parser.add_argument( 127 '--pre_check', action='store_true', 128 help=('Used for checking whether a same suite is already kicked off' 129 'to Skylab.')) 130 parser.add_argument( 131 '--do_nothing', action='store_true', 132 help=('Used for monitoring purposes, to measure no-op swarming proxy ' 133 'latency or create a dummy run_suite_skylab run.')) 134 135 # Abort-related parameters. 136 parser.add_argument( 137 '--abort_limit', default=sys.maxint, type=int, action='store', 138 help=('Only abort first N parent tasks which fulfill the search ' 139 'requirements.')) 140 parser.add_argument( 141 '--suite_task_ids', nargs='*', default=[], 142 help=('Specify the parent swarming task id to abort.')) 143 144 return parser 145 146 147 def verify_and_clean_options(options): 148 """Validate options.""" 149 if options.suite_args is None: 150 options.suite_args = {} 151 152 return True 153 154 155 def parse_suite_spec(options): 156 """Parse options to suite_spec.""" 157 suite_common = autotest.load('server.cros.dynamic_suite.suite_common') 158 builds = suite_common.make_builds_from_options(options) 159 return cros_suite.SuiteSpec( 160 builds=builds, 161 suite_name=options.suite_name, 162 suite_file_name=suite_common.canonicalize_suite_name( 163 options.suite_name), 164 test_source_build=suite_common.get_test_source_build( 165 builds, test_source_build=options.test_source_build), 166 suite_args=options.suite_args, 167 priority=options.priority, 168 board=options.board, 169 model=options.model, 170 pool=options.pool, 171 job_keyvals=options.job_keyvals, 172 minimum_duts=options.minimum_duts, 173 timeout_mins=options.timeout_mins, 174 quota_account=options.quota_account, 175 ) 176