| # Copyright 2018 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Parse & Validate CLI arguments for run_suite_skylab.py.""" |
| |
| from __future__ import absolute_import |
| from __future__ import division |
| from __future__ import print_function |
| |
| import argparse |
| import ast |
| import sys |
| |
| from lucifer import autotest |
| from skylab_suite import cros_suite |
| from skylab_suite import swarming_lib |
| |
| |
| def make_parser(): |
| """Make ArgumentParser instance for run_suite_skylab.py.""" |
| parser = argparse.ArgumentParser(prog='run_suite_skylab', |
| description="Run a test suite in Skylab.") |
| |
| # Suite-related parameters. |
| parser.add_argument('--board', required=True) |
| parser.add_argument( |
| '--model', default=None, |
| help=('The device model to run tests against. For non-unified ' |
| 'builds, model and board are synonymous, but board is more ' |
| 'accurate in some cases. Only pass this option if your build ' |
| 'is a unified build.')) |
| # Allow customized pool label temporarily for crbug.com/913623. |
| parser.add_argument( |
| '--pool', default='suites', |
| help=('Specify the pool of DUTs to run this suite. Default: suites. ' |
| 'If you want no pool, you can specify it with --pool="". ' |
| 'USE WITH CARE.')) |
| parser.add_argument( |
| '--suite_name', required=True, |
| help='Specify the suite to run.') |
| parser.add_argument( |
| '--build', required=True, |
| help='Specify the build to run the suite with.') |
| parser.add_argument( |
| '--cheets_build', default=None, |
| help='ChromeOS Android build to be installed on dut.') |
| parser.add_argument( |
| '--firmware_rw_build', default=None, |
| help='Firmware build to be installed in dut RW firmware.') |
| parser.add_argument( |
| '--firmware_ro_build', default=None, |
| help='Firmware build to be installed in dut RO firmware.') |
| parser.add_argument( |
| '--test_source_build', default=None, |
| help=('Build that contains the test code. It can be the value ' |
| 'of arguments "--build", "--firmware_rw_build" or ' |
| '"--firmware_ro_build". Default is to use test code from ' |
| 'the "--build" version (CrOS image)')) |
| parser.add_argument( |
| '--priority', type=int, |
| default=swarming_lib.SKYLAB_HWTEST_PRIORITIES_MAP['Default'], |
| choices=[value for name, value in |
| swarming_lib.SORTED_SKYLAB_HWTEST_PRIORITY], |
| help=('The priority to run the suite. A high value means this suite ' |
| 'will be executed in a low priority, e.g. being delayed to ' |
| 'execute. Each numerical value represents: '+ ', '.join([ |
| '(%s: %d)' % (name, value) for name, value in |
| swarming_lib.SORTED_SKYLAB_HWTEST_PRIORITY]))) |
| parser.add_argument( |
| "--suite_args", type=ast.literal_eval, default=None, |
| action="store", |
| help="A dict of args passed to the suite control file.") |
| parser.add_argument( |
| "--job_keyvals", type=ast.literal_eval, default={}, |
| action="store", |
| help="A dict of job keyvals to be passed to child jobs.") |
| parser.add_argument( |
| "--minimum_duts", type=int, default=1, action="store", |
| help="A minimum required numbers of DUTs to run this suite.") |
| parser.add_argument( |
| '--quota_account', default=None, action='store', |
| help=("Quota account to be used for this suite's jobs, if applicable. " |
| "Only relevant for jobs running in a quota scheduler pool " |
| "(e.g. quota-metered).")) |
| parser.add_argument( |
| '--swarming_auth_json', default=swarming_lib.DEFAULT_SERVICE_ACCOUNT, |
| action='store', help="Path to swarming service account json creds. " |
| "Specify '' to omit. Otherwise, defaults to bot's default creds.") |
| |
| # TODO(ayatane): Make sure no callers pass --use_fallback before removing. |
| parser.add_argument( |
| "--use_fallback", action="store_true", help='Deprecated') |
| |
| # Swarming-related parameters. |
| parser.add_argument( |
| '--execution_timeout_seconds', type=int, default=30, |
| help='Seconds to allow a task to complete, once execution beings.') |
| |
| # logic-related parameters. |
| parser.add_argument( |
| '--create_and_return', action='store_true', |
| help='Create the child jobs of a suite, then finish immediately.') |
| parser.add_argument( |
| '--suite_id', default=None, |
| help='A suite ID, wait for whose child tests to finish.') |
| parser.add_argument( |
| '--test_retry', default=False, action='store_true', |
| help='Enable test-level retry.') |
| parser.add_argument( |
| '--max_retries', default=0, type=int, action='store', |
| help='Maximum retries allowed at suite level. No retry if it is 0.') |
| parser.add_argument( |
| '--timeout_mins', default=90, type=int, action='store', |
| help='Maximum minutes to wait for a suite to finish.') |
| parser.add_argument( |
| '--passed_mins', default=0, type=int, action='store', |
| help='The minutes that this suite already runs for.') |
| parser.add_argument( |
| '--run_prod_code', action='store_true', default=False, |
| help='Run the test code that lives in prod aka the test ' |
| 'code currently on the lab servers.') |
| parser.add_argument( |
| '--dry_run', action='store_true', |
| help=('Used for kicking off a run of suite with fake commands.')) |
| parser.add_argument( |
| '--pre_check', action='store_true', |
| help=('Used for checking whether a same suite is already kicked off' |
| 'to Skylab.')) |
| parser.add_argument( |
| '--do_nothing', action='store_true', |
| help=('Used for monitoring purposes, to measure no-op swarming proxy ' |
| 'latency or create a dummy run_suite_skylab run.')) |
| |
| # Abort-related parameters. |
| parser.add_argument( |
| '--abort_limit', default=sys.maxint, type=int, action='store', |
| help=('Only abort first N parent tasks which fulfill the search ' |
| 'requirements.')) |
| parser.add_argument( |
| '--suite_task_ids', nargs='*', default=[], |
| help=('Specify the parent swarming task id to abort.')) |
| |
| return parser |
| |
| |
| def verify_and_clean_options(options): |
| """Validate options.""" |
| if options.suite_args is None: |
| options.suite_args = {} |
| |
| return True |
| |
| |
| def parse_suite_spec(options): |
| """Parse options to suite_spec.""" |
| suite_common = autotest.load('server.cros.dynamic_suite.suite_common') |
| builds = suite_common.make_builds_from_options(options) |
| return cros_suite.SuiteSpec( |
| builds=builds, |
| suite_name=options.suite_name, |
| suite_file_name=suite_common.canonicalize_suite_name( |
| options.suite_name), |
| test_source_build=suite_common.get_test_source_build( |
| builds, test_source_build=options.test_source_build), |
| suite_args=options.suite_args, |
| priority=options.priority, |
| board=options.board, |
| model=options.model, |
| pool=options.pool, |
| job_keyvals=options.job_keyvals, |
| minimum_duts=options.minimum_duts, |
| timeout_mins=options.timeout_mins, |
| quota_account=options.quota_account, |
| ) |