Home | History | Annotate | Download | only in skylab_suite
      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