You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
4.9 KiB
134 lines
4.9 KiB
#!/usr/bin/python2
|
|
#
|
|
# Copyright 2019 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.
|
|
"""
|
|
Call `cros_config` from the DUT while respecting new fallback commands.
|
|
|
|
When `cros_config` is called on a non-Unibuild DUT, the usual config
|
|
files (and thus behavior) are not available, so it resorts to plan B.
|
|
The following file's kCommandMap contains a list of fallback commands:
|
|
platform2/chromeos-config/libcros_config/cros_config_fallback.cc
|
|
If the requested cros_config path/property are mapped to a fallback
|
|
command, then that command is called, and its results is returned.
|
|
That behavior is all native to cros_config.
|
|
|
|
Let's say you define a new fallback command in cros_config_fallback.cc:
|
|
`cros_config /foo bar` --> `mosys baz quux`
|
|
You then call `cros_config /foo bar` during an Autotest test.
|
|
But, alas! Your test breaks on non-Unibuild boards during qual tests!
|
|
Why? Your new fallback needs to get promoted from ToT to Canary to Dev
|
|
to Beta to Stable. In contrast, Autotest is typically run from whatever
|
|
version is available: often ToT.
|
|
So, ToT Autotest runs `cros_config /foo bar` on a DUT with a Dev image.
|
|
`cros_config` looks for a fallback command, but cannot find the new one.
|
|
It returns the empty string and an error code of 1, and your test fails.
|
|
|
|
This file serves to replicate the fallbacks in cros_config_fallback.cc,
|
|
so that you don't have to wait for your new fallbacks to get promoted.
|
|
|
|
"""
|
|
|
|
import logging
|
|
|
|
import common
|
|
from autotest_lib.client.common_lib import error
|
|
|
|
FALLBACKS = {
|
|
'/firmware image-name': 'mosys platform model',
|
|
'/ name': 'mosys platform model',
|
|
'/ brand-code': 'mosys platform brand',
|
|
'/identity sku-id': 'mosys platform sku',
|
|
'/identity platform-name': 'mosys platform name'
|
|
}
|
|
|
|
|
|
def get_fallback(cros_config_args):
|
|
"""
|
|
Get the fallback command for a cros_config command, if one exists.
|
|
NOTE: Does not strip trailing newlines.
|
|
|
|
@param cros_config_args: '$path $property', as used by cros_config
|
|
@return: The fallback command if one exists, else empty string
|
|
|
|
@type cros_config_args: string
|
|
@rtype: string | None
|
|
|
|
"""
|
|
return FALLBACKS.get(cros_config_args)
|
|
|
|
|
|
def call_cros_config_with_fallback(cros_config_args, run, **run_kwargs):
|
|
"""
|
|
Try to call cros_config via a supplied run function.
|
|
If it fails, and a fallback command exists, call its fallback.
|
|
In order to replicate the behavior of the real cros_config, we
|
|
(attempt to) strip exactly one trailing \n from the fallback result.
|
|
|
|
@param cros_config_args: '$path $property', as used by cros_config
|
|
@param run: A function which passes a command to the DUT, and
|
|
returns a client.common_lib.utils.CmdResult object.
|
|
@param **run_kwargs: Any kwargs to be passed into run()
|
|
@return: The CmdResult of either cros_config or its fallback,
|
|
whichever ran more recently.
|
|
|
|
@type cros_config: string
|
|
@type run: func(string, **kwargs) -> CmdResult
|
|
@rtype: client.common_lib.utils.CmdResult
|
|
|
|
@raises CmdError or CmdTimeoutError if either:
|
|
1. cros_config raised one, and there was no fallback, or
|
|
2. the fallback command raised one
|
|
|
|
"""
|
|
cros_config_cmd = 'cros_config %s' % cros_config_args
|
|
fallback_cmd = get_fallback(cros_config_args)
|
|
try:
|
|
result = run(cros_config_cmd, **run_kwargs)
|
|
except error.CmdError as e:
|
|
if fallback_cmd:
|
|
logging.debug('<%s> raised an error.', cros_config_cmd)
|
|
result = e.result_obj
|
|
else:
|
|
raise
|
|
else:
|
|
if result.exit_status:
|
|
logging.debug('<%s> returned with an exit code.', cros_config_cmd)
|
|
else:
|
|
return result
|
|
if fallback_cmd:
|
|
logging.debug('Trying fallback cmd: <%s>', fallback_cmd)
|
|
result = run(fallback_cmd, **run_kwargs)
|
|
if result.stdout and result.stdout[-1] == '\n':
|
|
result.stdout = result.stdout[:-1]
|
|
else:
|
|
logging.debug('No fallback command found for <%s>.', cros_config_cmd)
|
|
return result
|
|
|
|
|
|
def call_cros_config_get_output(cros_config_args, run, **run_kwargs):
|
|
"""
|
|
Get the stdout from cros_config (or its fallback).
|
|
|
|
@param cros_config_args: '$path $property', as used by cros_config
|
|
@param run: A function which passes a command to the DUT, and
|
|
returns a client.common_lib.utils.CmdResult object.
|
|
@param **run_kwargs: Any kwargs to be passed into run()
|
|
@return: The string stdout of either cros_config or its fallback,
|
|
or empty string in the case of error.
|
|
|
|
@type cros_config: string
|
|
@type run: func(string, **kwargs) -> CmdResult
|
|
@rtype: string
|
|
|
|
"""
|
|
try:
|
|
result = call_cros_config_with_fallback(cros_config_args, run,
|
|
**run_kwargs)
|
|
except error.CmdError:
|
|
return ''
|
|
if result.exit_status:
|
|
return ''
|
|
return result.stdout
|