# Copyright 2016 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Utility functions for AFE-based interactions. NOTE: This module should only be used in the context of a running test. Any utilities that require accessing the AFE, should do so by creating their own instance of the AFE client and interact with it directly. """ import common import logging import traceback import urlparse from autotest_lib.client.common_lib import global_config from autotest_lib.server.cros import autoupdater from autotest_lib.server.cros import provision from autotest_lib.server.cros.dynamic_suite import frontend_wrappers from autotest_lib.site_utils import stable_version_classify as sv from autotest_lib.server import site_utils as server_utils from autotest_lib.server.cros.dynamic_suite import constants as ds_constants from autotest_lib.server.cros.dynamic_suite import tools from chromite.lib import auto_updater from chromite.lib import remote_access AFE = frontend_wrappers.RetryingAFE(timeout_min=5, delay_sec=10) _CROS_VERSION_MAP = AFE.get_stable_version_map(AFE.CROS_IMAGE_TYPE) _FIRMWARE_VERSION_MAP = AFE.get_stable_version_map(AFE.FIRMWARE_IMAGE_TYPE) _FAFT_VERSION_MAP = AFE.get_stable_version_map(AFE.FAFT_IMAGE_TYPE) _CONFIG = global_config.global_config ENABLE_DEVSERVER_TRIGGER_AUTO_UPDATE = _CONFIG.get_config_value( 'CROS', 'enable_devserver_trigger_auto_update', type=bool, default=False) def _host_in_lab(host): """Check if the host is in the lab and an object the AFE knows. This check ensures that autoserv and the host's current job is running inside a fully Autotest instance, aka a lab environment. If this is the case it then verifies the host is registed with the configured AFE instance. @param host: Host object to verify. @returns The host model object. """ if not host.job or not host.job.in_lab: return False return host._afe_host def _log_image_name(image_name): try: logging.debug("_log_image_name: image (%s)", image_name) server_utils.ParseBuildName(name=image_name) except Exception: logging.error(traceback.format_exc()) def _format_image_name(board, version): return "%s-release/%s" % (board, version) def get_stable_cros_image_name_v2(info, _config_override=None): if sv.classify_board(info.board, _config_override=_config_override) == sv.FROM_HOST_CONFIG: logging.debug("get_stable_cros_image_name_v2: board %s from host_info_store" % info.board) out = _format_image_name(board=info.board, version=info.cros_stable_version) _log_image_name(out) return out logging.debug("get_stable_cros_image_name_v2: board %s from autotest frontend" % info.board) return get_stable_cros_image_name(info.board) def get_stable_servo_cros_image_name_v2(servo_version_from_hi, board, _config_override=None): """ @param servo_version_from_hi (string or None) : the stable version image name taken from the host info store. A value of None means that that the host_info_store does not exist or ultimately not contain a servo_stable_version field. @param board (string) : the board of the labstation or servo v3 that we're getting the stable version of """ logging.debug("get_stable_servo_cros_image_name_v2: servo_version_from_hi (%s) board (%s)" % (servo_version_from_hi, board)) if sv.classify_board(board, _config_override=_config_override) != sv.FROM_HOST_CONFIG: logging.debug("get_stable_servo_cros_image_name_v2: servo version for board (%s) from afe" % board) return get_stable_cros_image_name(board) if servo_version_from_hi is not None: logging.debug("get_stable_servo_cros_image_name_v2: servo version (%s) from host_info_store" % servo_version_from_hi) out = _format_image_name(board=board, version=servo_version_from_hi) _log_image_name(out) return out logging.debug("get_stable_servo_cros_image_name_v2: no servo version provided. board is (%s)" % board) logging.debug("get_stable_servo_cros_image_name_v2: falling back to afe if possible") out = None # get_stable_cros_image_name uses the AFE as the source of truth. try: out = get_stable_cros_image_name(board) except Exception: logging.error("get_stable_servo_cros_image_name_v2: error falling back to AFE (%s)" % traceback.format_exc()) return out def get_stable_cros_image_name(board): """Retrieve the Chrome OS stable image name for a given board. @param board: Board to lookup. @returns Name of a Chrome OS image to be installed in order to repair the given board. """ return _CROS_VERSION_MAP.get_image_name(board) def get_stable_firmware_version_v2(info, _config_override=None): if sv.classify_model(info.model, _config_override=_config_override) == sv.FROM_HOST_CONFIG: logging.debug("get_stable_firmware_version_v2: model %s from host_info_store" % info.model) return info.firmware_stable_version logging.debug("get_stable_cros_image_name_v2: model %s from autotest frontend" % info.model) return get_stable_firmware_version(info.model) def get_stable_firmware_version(model): """Retrieve the stable firmware version for a given model. @param model: Model to lookup. @returns A version of firmware to be installed via `chromeos-firmwareupdate` from a repair build. """ return _FIRMWARE_VERSION_MAP.get_version(model) def get_stable_faft_version_v2(info, _config_override=None): if sv.classify_board(info.board, _config_override=_config_override) == sv.FROM_HOST_CONFIG: logging.debug("get_stable_faft_version_v2: model %s from host_info_store" % info.model) return info.faft_stable_version logging.debug("get_stable_faft_version_v2: model %s from autotest frontend" % info.model) return get_stable_faft_version(info.board) def get_stable_faft_version(board): """Retrieve the stable firmware version for FAFT DUTs. @param board: Board to lookup. @returns A version of firmware to be installed in order to repair firmware on a DUT used for FAFT testing. """ return _FAFT_VERSION_MAP.get_version(board) def clean_provision_labels(host): """Clean provision-related labels. @param host: Host object. """ info = host.host_info_store.get() info.clear_version_labels() attributes = host.get_attributes_to_clear_before_provision() for key in attributes: info.attributes.pop(key, None) host.host_info_store.commit(info) def add_provision_labels(host, version_prefix, image_name, provision_attributes={}): """Add provision labels for host. @param host: Host object. @param version_prefix: a string version prefix, e.g. "cros-version:" @param image_name: a string image name, e.g. peppy-release/R70-11011.0.0. @param provision_attributes: a map, including attributes for provisioning, e.g. {"job_repo_url": "http://..."} """ info = host.host_info_store.get() info.attributes.update(provision_attributes) info.set_version_label(version_prefix, image_name) host.host_info_store.commit(info) def machine_install_and_update_labels(host, update_url, use_quick_provision=False, with_cheets=False, staging_server=None): """Install a build and update the version labels on a host. @param host: Host object where the build is to be installed. @param update_url: URL of the build to install. @param use_quick_provision: If true, then attempt to use quick-provision for the update. @param with_cheets: If true, installation is for a specific, custom version of Android for a target running ARC. @param staging_server: Sever where images have been staged. Typically, an instance of dev_server.ImageServer. """ clean_provision_labels(host) # TODO(crbug.com/1049346): The try-except block exists to catch failures in # chromite auto_updater that may occur due to autotest/chromite version # mismatch. This should be removed once that bug is resolved. try: # Get image_name in the format -release/Rxx-12345.0.0 from the # update_url. image_name = '/'.join(urlparse.urlparse(update_url).path.split('/')[-2:]) with remote_access.ChromiumOSDeviceHandler(host.ip) as device: updater = auto_updater.ChromiumOSUpdater( device, build_name=None, payload_dir=image_name, staging_server=staging_server.url()) updater.CheckPayloads() updater.PreparePayloadPropsFile() updater.RunUpdate() repo_url = tools.get_package_url(staging_server.url(), image_name) host_attributes = {ds_constants.JOB_REPO_URL: repo_url} except Exception as e: logging.warning( "Chromite auto_updater has failed with the exception: %s", e) logging.debug("Attempting to provision with quick provision.") updater = autoupdater.ChromiumOSUpdater( update_url, host=host, use_quick_provision=use_quick_provision) image_name, host_attributes = updater.run_update() if with_cheets: image_name += provision.CHEETS_SUFFIX add_provision_labels(host, host.VERSION_PREFIX, image_name, host_attributes)