1# Copyright 2016 The Chromium 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"""Utility functions for AFE-based interactions. 6 7NOTE: This module should only be used in the context of a running test. Any 8 utilities that require accessing the AFE, should do so by creating 9 their own instance of the AFE client and interact with it directly. 10""" 11 12import common 13import logging 14import traceback 15import urlparse 16 17from autotest_lib.client.common_lib import global_config 18from autotest_lib.server.cros import autoupdater 19from autotest_lib.server.cros import provision 20from autotest_lib.server.cros.dynamic_suite import frontend_wrappers 21from autotest_lib.site_utils import stable_version_classify as sv 22from autotest_lib.server import site_utils as server_utils 23from autotest_lib.server.cros.dynamic_suite import constants as ds_constants 24from autotest_lib.server.cros.dynamic_suite import tools 25 26from chromite.lib import auto_updater 27from chromite.lib import remote_access 28 29 30AFE = frontend_wrappers.RetryingAFE(timeout_min=5, delay_sec=10) 31_CROS_VERSION_MAP = AFE.get_stable_version_map(AFE.CROS_IMAGE_TYPE) 32_FIRMWARE_VERSION_MAP = AFE.get_stable_version_map(AFE.FIRMWARE_IMAGE_TYPE) 33_FAFT_VERSION_MAP = AFE.get_stable_version_map(AFE.FAFT_IMAGE_TYPE) 34 35_CONFIG = global_config.global_config 36ENABLE_DEVSERVER_TRIGGER_AUTO_UPDATE = _CONFIG.get_config_value( 37 'CROS', 'enable_devserver_trigger_auto_update', type=bool, 38 default=False) 39 40 41def _host_in_lab(host): 42 """Check if the host is in the lab and an object the AFE knows. 43 44 This check ensures that autoserv and the host's current job is running 45 inside a fully Autotest instance, aka a lab environment. If this is the 46 case it then verifies the host is registed with the configured AFE 47 instance. 48 49 @param host: Host object to verify. 50 51 @returns The host model object. 52 """ 53 if not host.job or not host.job.in_lab: 54 return False 55 return host._afe_host 56 57 58def _log_image_name(image_name): 59 try: 60 logging.debug("_log_image_name: image (%s)", image_name) 61 server_utils.ParseBuildName(name=image_name) 62 except Exception: 63 logging.error(traceback.format_exc()) 64 65 66def _format_image_name(board, version): 67 return "%s-release/%s" % (board, version) 68 69 70def get_stable_cros_image_name_v2(info, _config_override=None): 71 if sv.classify_board(info.board, _config_override=_config_override) == sv.FROM_HOST_CONFIG: 72 logging.debug("get_stable_cros_image_name_v2: board %s from host_info_store" % info.board) 73 out = _format_image_name(board=info.board, version=info.cros_stable_version) 74 _log_image_name(out) 75 return out 76 logging.debug("get_stable_cros_image_name_v2: board %s from autotest frontend" % info.board) 77 return get_stable_cros_image_name(info.board) 78 79 80def get_stable_servo_cros_image_name_v2(servo_version_from_hi, board, _config_override=None): 81 """ 82 @param servo_version_from_hi (string or None) : the stable version image name taken from the host info store. 83 A value of None means that that the host_info_store does not exist or 84 ultimately not contain a servo_stable_version field. 85 @param board (string) : the board of the labstation or servo v3 that we're getting the stable version of 86 """ 87 logging.debug("get_stable_servo_cros_image_name_v2: servo_version_from_hi (%s) board (%s)" % (servo_version_from_hi, board)) 88 if sv.classify_board(board, _config_override=_config_override) != sv.FROM_HOST_CONFIG: 89 logging.debug("get_stable_servo_cros_image_name_v2: servo version for board (%s) from afe" % board) 90 return get_stable_cros_image_name(board) 91 if servo_version_from_hi is not None: 92 logging.debug("get_stable_servo_cros_image_name_v2: servo version (%s) from host_info_store" % servo_version_from_hi) 93 out = _format_image_name(board=board, version=servo_version_from_hi) 94 _log_image_name(out) 95 return out 96 logging.debug("get_stable_servo_cros_image_name_v2: no servo version provided. board is (%s)" % board) 97 logging.debug("get_stable_servo_cros_image_name_v2: falling back to afe if possible") 98 out = None 99 # get_stable_cros_image_name uses the AFE as the source of truth. 100 try: 101 out = get_stable_cros_image_name(board) 102 except Exception: 103 logging.error("get_stable_servo_cros_image_name_v2: error falling back to AFE (%s)" % traceback.format_exc()) 104 return out 105 106 107def get_stable_cros_image_name(board): 108 """Retrieve the Chrome OS stable image name for a given board. 109 110 @param board: Board to lookup. 111 112 @returns Name of a Chrome OS image to be installed in order to 113 repair the given board. 114 """ 115 return _CROS_VERSION_MAP.get_image_name(board) 116 117 118def get_stable_firmware_version_v2(info, _config_override=None): 119 if sv.classify_model(info.model, _config_override=_config_override) == sv.FROM_HOST_CONFIG: 120 logging.debug("get_stable_firmware_version_v2: model %s from host_info_store" % info.model) 121 return info.firmware_stable_version 122 logging.debug("get_stable_cros_image_name_v2: model %s from autotest frontend" % info.model) 123 return get_stable_firmware_version(info.model) 124 125 126def get_stable_firmware_version(model): 127 """Retrieve the stable firmware version for a given model. 128 129 @param model: Model to lookup. 130 131 @returns A version of firmware to be installed via 132 `chromeos-firmwareupdate` from a repair build. 133 """ 134 return _FIRMWARE_VERSION_MAP.get_version(model) 135 136 137def get_stable_faft_version_v2(info, _config_override=None): 138 if sv.classify_board(info.board, _config_override=_config_override) == sv.FROM_HOST_CONFIG: 139 logging.debug("get_stable_faft_version_v2: model %s from host_info_store" % info.model) 140 return info.faft_stable_version 141 logging.debug("get_stable_faft_version_v2: model %s from autotest frontend" % info.model) 142 return get_stable_faft_version(info.board) 143 144 145def get_stable_faft_version(board): 146 """Retrieve the stable firmware version for FAFT DUTs. 147 148 @param board: Board to lookup. 149 150 @returns A version of firmware to be installed in order to 151 repair firmware on a DUT used for FAFT testing. 152 """ 153 return _FAFT_VERSION_MAP.get_version(board) 154 155 156def clean_provision_labels(host): 157 """Clean provision-related labels. 158 159 @param host: Host object. 160 """ 161 info = host.host_info_store.get() 162 info.clear_version_labels() 163 attributes = host.get_attributes_to_clear_before_provision() 164 for key in attributes: 165 info.attributes.pop(key, None) 166 167 host.host_info_store.commit(info) 168 169 170def add_provision_labels(host, version_prefix, image_name, 171 provision_attributes={}): 172 """Add provision labels for host. 173 174 @param host: Host object. 175 @param version_prefix: a string version prefix, e.g. "cros-version:" 176 @param image_name: a string image name, e.g. peppy-release/R70-11011.0.0. 177 @param provision_attributes: a map, including attributes for provisioning, 178 e.g. {"job_repo_url": "http://..."} 179 """ 180 info = host.host_info_store.get() 181 info.attributes.update(provision_attributes) 182 info.set_version_label(version_prefix, image_name) 183 host.host_info_store.commit(info) 184 185 186def machine_install_and_update_labels(host, update_url, 187 use_quick_provision=False, 188 with_cheets=False, staging_server=None): 189 """Install a build and update the version labels on a host. 190 191 @param host: Host object where the build is to be installed. 192 @param update_url: URL of the build to install. 193 @param use_quick_provision: If true, then attempt to use 194 quick-provision for the update. 195 @param with_cheets: If true, installation is for a specific, custom 196 version of Android for a target running ARC. 197 @param staging_server: Sever where images have been staged. Typically, 198 an instance of dev_server.ImageServer. 199 """ 200 clean_provision_labels(host) 201 # TODO(crbug.com/1049346): The try-except block exists to catch failures in 202 # chromite auto_updater that may occur due to autotest/chromite version 203 # mismatch. This should be removed once that bug is resolved. 204 try: 205 # Get image_name in the format <board>-release/Rxx-12345.0.0 from the 206 # update_url. 207 image_name = '/'.join(urlparse.urlparse(update_url).path.split('/')[-2:]) 208 with remote_access.ChromiumOSDeviceHandler(host.ip) as device: 209 updater = auto_updater.ChromiumOSUpdater( 210 device, build_name=None, payload_dir=image_name, 211 staging_server=staging_server.url()) 212 updater.CheckPayloads() 213 updater.PreparePayloadPropsFile() 214 updater.RunUpdate() 215 repo_url = tools.get_package_url(staging_server.url(), image_name) 216 host_attributes = {ds_constants.JOB_REPO_URL: repo_url} 217 except Exception as e: 218 logging.warning( 219 "Chromite auto_updater has failed with the exception: %s", e) 220 logging.debug("Attempting to provision with quick provision.") 221 updater = autoupdater.ChromiumOSUpdater( 222 update_url, host=host, use_quick_provision=use_quick_provision) 223 image_name, host_attributes = updater.run_update() 224 if with_cheets: 225 image_name += provision.CHEETS_SUFFIX 226 add_provision_labels(host, host.VERSION_PREFIX, image_name, 227 host_attributes) 228