blob: 93fb29d20517e557912425f9b5d2e8d8eb302c7b [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2017 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Switcher for ChromeOS prebuilt"""
from __future__ import annotations
import argparse
import logging
import os
import sys
import typing
from bisect_kit import bisector_cli
from bisect_kit import cli
from bisect_kit import common
from bisect_kit import configure
from bisect_kit import core
from bisect_kit import cros_lab_util
from bisect_kit import cros_util
from bisect_kit import errors
logger = logging.getLogger(__name__)
def create_argument_parser():
parents = [common.create_session_optional_parser()]
parser = argparse.ArgumentParser(description=__doc__, parents=parents)
cli.patching_argparser_exit(parser)
parser.add_argument(
'--rich_result',
action='store_true',
help='Instead of mere exit code, output detailed information in json',
)
parser.add_argument(
'--dut',
type=cli.argtype_notempty,
metavar='DUT',
default=configure.get('DUT', ''),
)
parser.add_argument(
'version',
nargs='?',
type=cros_util.argtype_cros_version,
metavar='CROS_VERSION',
default=configure.get('CROS_VERSION', ''),
help='ChromeOS version number, short (10162.0.0) or full (R64-10162.0.0)',
)
parser.add_argument(
'--board',
metavar='BOARD',
default=configure.get('BOARD', ''),
help='ChromeOS board name',
)
parser.add_argument(
'--clobber-stateful',
'--clobber_stateful',
action='store_true',
help='Clobber stateful partition when performing update',
)
parser.add_argument(
'--no-disable-rootfs-verification',
'--no_disable_rootfs_verification',
dest='disable_rootfs_verification',
action='store_false',
help="Don't disable rootfs verification after update is completed",
)
parser.add_argument(
'--default_chromeos_root',
type=cli.argtype_dir_path,
default=configure.get(
'DEFAULT_CHROMEOS_ROOT', os.path.expanduser('~/chromiumos')
),
help='Default chromeos tree to run "cros flash" (default: %(default)s)',
)
return parser
def switch(opts):
if opts.session:
states = core.BisectStates.from_bisector_class(
'ChromeOSVersionDomain', opts.session
)
if states.load_states():
cros_util.SnapshotStore.init_with_state(states)
# TODO(kcwu): clear cache of cros flash
image_info = cros_util.search_image(opts.board, opts.version)
if not image_info:
raise errors.ExecutionFatalError(
'no images available for %s %s' % (opts.board, opts.version)
)
cros_util.provision_image_with_retry(
opts.default_chromeos_root,
opts.dut,
opts.board,
image_info,
version=opts.version,
clobber_stateful=opts.clobber_stateful,
disable_rootfs_verification=opts.disable_rootfs_verification,
repair_callback=cros_lab_util.repair,
force_reboot_callback=cros_lab_util.reboot_via_servo,
)
def parse_args(args):
parser = create_argument_parser()
return parser.parse_args(args)
def inner_main(opts):
if cros_lab_util.is_satlab_dut(opts.dut):
cros_lab_util.write_satlab_ssh_config(opts.dut)
if not cros_util.is_good_dut(opts.dut):
logger.error('%r is not a good DUT', opts.dut)
if not cros_lab_util.repair(opts.dut):
raise errors.BrokenDutException('%r is not a good DUT' % opts.dut)
if not opts.board:
opts.board = cros_util.query_dut_board(opts.dut)
cros_util.prepare_chroot(opts.default_chromeos_root)
try:
switch(opts)
finally:
# No matter switching succeeded or not, DUT must be in good state.
# switch() already tried repairing if possible, no repair here.
if not cros_util.is_good_dut(opts.dut):
raise errors.BrokenDutException('%r is not a good DUT' % opts.dut)
logger.info('done')
def switch_main(args: typing.Optional[tuple[str]]):
opts = parse_args(args)
common.config_logging(opts)
inner_main(opts)
def main(args: typing.Optional[tuple[str]] = None) -> int:
return bisector_cli.switch_main_wrapper(switch_main, args)
if __name__ == '__main__':
sys.exit(main())