Simran Basi | 5ace6f2 | 2016-01-06 17:30:44 -0800 | [diff] [blame] | 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 | |
Simran Basi | aa467ad | 2016-02-03 16:56:22 -0800 | [diff] [blame] | 5 | """Utility functions for AFE-based interactions. |
| 6 | |
| 7 | NOTE: 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 | """ |
Simran Basi | 5ace6f2 | 2016-01-06 17:30:44 -0800 | [diff] [blame] | 11 | |
| 12 | import common |
Gregory Nisbet | 7fe11c2 | 2019-11-22 11:06:06 -0800 | [diff] [blame] | 13 | import logging |
Gregory Nisbet | 8e2fbb2 | 2019-12-05 11:36:37 -0800 | [diff] [blame] | 14 | import traceback |
Sanika Kulkarni | 000fe8c | 2020-01-22 11:13:29 -0800 | [diff] [blame] | 15 | import urlparse |
| 16 | |
xixuan | 5dc64ea | 2016-05-20 17:27:51 -0700 | [diff] [blame] | 17 | from autotest_lib.client.common_lib import global_config |
Kirtika Ruchandani | fcc8aad | 2019-12-16 19:52:12 +0000 | [diff] [blame] | 18 | from autotest_lib.server.cros import autoupdater |
Rohit Makasana | df0a3a3 | 2017-06-30 13:55:18 -0700 | [diff] [blame] | 19 | from autotest_lib.server.cros import provision |
Simran Basi | 5ace6f2 | 2016-01-06 17:30:44 -0800 | [diff] [blame] | 20 | from autotest_lib.server.cros.dynamic_suite import frontend_wrappers |
Gregory Nisbet | 7fe11c2 | 2019-11-22 11:06:06 -0800 | [diff] [blame] | 21 | from autotest_lib.site_utils import stable_version_classify as sv |
Gregory Nisbet | 265a52c | 2019-12-10 20:38:42 -0800 | [diff] [blame] | 22 | from autotest_lib.server import site_utils as server_utils |
Sanika Kulkarni | 000fe8c | 2020-01-22 11:13:29 -0800 | [diff] [blame] | 23 | from autotest_lib.server.cros.dynamic_suite import constants as ds_constants |
| 24 | from autotest_lib.server.cros.dynamic_suite import tools |
| 25 | |
| 26 | from chromite.lib import auto_updater |
| 27 | from chromite.lib import remote_access |
Dan Shi | 8190eb8 | 2016-02-11 17:15:58 -0800 | [diff] [blame] | 28 | |
Simran Basi | 5ace6f2 | 2016-01-06 17:30:44 -0800 | [diff] [blame] | 29 | |
| 30 | AFE = frontend_wrappers.RetryingAFE(timeout_min=5, delay_sec=10) |
Richard Barnette | 260cbd0 | 2016-10-06 12:23:28 -0700 | [diff] [blame] | 31 | _CROS_VERSION_MAP = AFE.get_stable_version_map(AFE.CROS_IMAGE_TYPE) |
Richard Barnette | e50453e | 2016-10-10 16:43:44 -0700 | [diff] [blame] | 32 | _FIRMWARE_VERSION_MAP = AFE.get_stable_version_map(AFE.FIRMWARE_IMAGE_TYPE) |
Richard Barnette | 260cbd0 | 2016-10-06 12:23:28 -0700 | [diff] [blame] | 33 | _FAFT_VERSION_MAP = AFE.get_stable_version_map(AFE.FAFT_IMAGE_TYPE) |
Simran Basi | 5ace6f2 | 2016-01-06 17:30:44 -0800 | [diff] [blame] | 34 | |
xixuan | 5dc64ea | 2016-05-20 17:27:51 -0700 | [diff] [blame] | 35 | _CONFIG = global_config.global_config |
| 36 | ENABLE_DEVSERVER_TRIGGER_AUTO_UPDATE = _CONFIG.get_config_value( |
| 37 | 'CROS', 'enable_devserver_trigger_auto_update', type=bool, |
| 38 | default=False) |
| 39 | |
Simran Basi | 5ace6f2 | 2016-01-06 17:30:44 -0800 | [diff] [blame] | 40 | |
Richard Barnette | 260cbd0 | 2016-10-06 12:23:28 -0700 | [diff] [blame] | 41 | def _host_in_lab(host): |
Simran Basi | 5ace6f2 | 2016-01-06 17:30:44 -0800 | [diff] [blame] | 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 | """ |
Simran Basi | aa467ad | 2016-02-03 16:56:22 -0800 | [diff] [blame] | 53 | if not host.job or not host.job.in_lab: |
Simran Basi | 5ace6f2 | 2016-01-06 17:30:44 -0800 | [diff] [blame] | 54 | return False |
Kevin Cheng | 05ae2a4 | 2016-06-06 10:12:48 -0700 | [diff] [blame] | 55 | return host._afe_host |
Simran Basi | 5ace6f2 | 2016-01-06 17:30:44 -0800 | [diff] [blame] | 56 | |
| 57 | |
Gregory Nisbet | 265a52c | 2019-12-10 20:38:42 -0800 | [diff] [blame] | 58 | def _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 | |
| 66 | def _format_image_name(board, version): |
| 67 | return "%s-release/%s" % (board, version) |
| 68 | |
| 69 | |
Gregory Nisbet | 7fe11c2 | 2019-11-22 11:06:06 -0800 | [diff] [blame] | 70 | def 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) |
Gregory Nisbet | 265a52c | 2019-12-10 20:38:42 -0800 | [diff] [blame] | 73 | out = _format_image_name(board=info.board, version=info.cros_stable_version) |
| 74 | _log_image_name(out) |
| 75 | return out |
Gregory Nisbet | 7fe11c2 | 2019-11-22 11:06:06 -0800 | [diff] [blame] | 76 | logging.debug("get_stable_cros_image_name_v2: board %s from autotest frontend" % info.board) |
Gregory Nisbet | 9b9c761 | 2019-11-26 09:50:53 -0800 | [diff] [blame] | 77 | return get_stable_cros_image_name(info.board) |
Gregory Nisbet | 7fe11c2 | 2019-11-22 11:06:06 -0800 | [diff] [blame] | 78 | |
| 79 | |
Gregory Nisbet | 8e2fbb2 | 2019-12-05 11:36:37 -0800 | [diff] [blame] | 80 | def 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) |
Gregory Nisbet | 265a52c | 2019-12-10 20:38:42 -0800 | [diff] [blame] | 93 | out = _format_image_name(board=board, version=servo_version_from_hi) |
| 94 | _log_image_name(out) |
| 95 | return out |
Gregory Nisbet | 8e2fbb2 | 2019-12-05 11:36:37 -0800 | [diff] [blame] | 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 | |
Richard Barnette | 383ef9c | 2016-12-13 11:56:49 -0800 | [diff] [blame] | 107 | def get_stable_cros_image_name(board): |
| 108 | """Retrieve the Chrome OS stable image name for a given board. |
Simran Basi | beb2bb2 | 2016-02-03 15:25:48 -0800 | [diff] [blame] | 109 | |
| 110 | @param board: Board to lookup. |
Simran Basi | beb2bb2 | 2016-02-03 15:25:48 -0800 | [diff] [blame] | 111 | |
Richard Barnette | 383ef9c | 2016-12-13 11:56:49 -0800 | [diff] [blame] | 112 | @returns Name of a Chrome OS image to be installed in order to |
Richard Barnette | 260cbd0 | 2016-10-06 12:23:28 -0700 | [diff] [blame] | 113 | repair the given board. |
Simran Basi | beb2bb2 | 2016-02-03 15:25:48 -0800 | [diff] [blame] | 114 | """ |
Richard Barnette | 383ef9c | 2016-12-13 11:56:49 -0800 | [diff] [blame] | 115 | return _CROS_VERSION_MAP.get_image_name(board) |
Richard Barnette | 260cbd0 | 2016-10-06 12:23:28 -0700 | [diff] [blame] | 116 | |
| 117 | |
Gregory Nisbet | 7fe11c2 | 2019-11-22 11:06:06 -0800 | [diff] [blame] | 118 | def 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) |
Gregory Nisbet | 9b9c761 | 2019-11-26 09:50:53 -0800 | [diff] [blame] | 123 | return get_stable_firmware_version(info.model) |
Gregory Nisbet | 7fe11c2 | 2019-11-22 11:06:06 -0800 | [diff] [blame] | 124 | |
| 125 | |
Ningning Xia | 05af740 | 2018-02-13 18:19:10 -0800 | [diff] [blame] | 126 | def get_stable_firmware_version(model): |
| 127 | """Retrieve the stable firmware version for a given model. |
Richard Barnette | e50453e | 2016-10-10 16:43:44 -0700 | [diff] [blame] | 128 | |
Ningning Xia | 05af740 | 2018-02-13 18:19:10 -0800 | [diff] [blame] | 129 | @param model: Model to lookup. |
Richard Barnette | e50453e | 2016-10-10 16:43:44 -0700 | [diff] [blame] | 130 | |
| 131 | @returns A version of firmware to be installed via |
| 132 | `chromeos-firmwareupdate` from a repair build. |
| 133 | """ |
Ningning Xia | 05af740 | 2018-02-13 18:19:10 -0800 | [diff] [blame] | 134 | return _FIRMWARE_VERSION_MAP.get_version(model) |
Richard Barnette | e50453e | 2016-10-10 16:43:44 -0700 | [diff] [blame] | 135 | |
| 136 | |
Gregory Nisbet | 7fe11c2 | 2019-11-22 11:06:06 -0800 | [diff] [blame] | 137 | def 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 | |
Richard Barnette | 260cbd0 | 2016-10-06 12:23:28 -0700 | [diff] [blame] | 145 | def 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 | |
Xixuan Wu | f9e1161 | 2019-10-15 12:32:47 -0700 | [diff] [blame] | 156 | def clean_provision_labels(host): |
| 157 | """Clean provision-related labels. |
Dan Shi | 8190eb8 | 2016-02-11 17:15:58 -0800 | [diff] [blame] | 158 | |
Xixuan Wu | f9e1161 | 2019-10-15 12:32:47 -0700 | [diff] [blame] | 159 | @param host: Host object. |
Dan Shi | 8190eb8 | 2016-02-11 17:15:58 -0800 | [diff] [blame] | 160 | """ |
Xixuan Wu | f9e1161 | 2019-10-15 12:32:47 -0700 | [diff] [blame] | 161 | info = host.host_info_store.get() |
| 162 | info.clear_version_labels() |
Dan Shi | be3636a | 2016-02-14 22:48:01 -0800 | [diff] [blame] | 163 | attributes = host.get_attributes_to_clear_before_provision() |
Prathmesh Prabhu | 368abdf | 2017-02-14 11:23:47 -0800 | [diff] [blame] | 164 | for key in attributes: |
Xixuan Wu | f9e1161 | 2019-10-15 12:32:47 -0700 | [diff] [blame] | 165 | info.attributes.pop(key, None) |
| 166 | |
| 167 | host.host_info_store.commit(info) |
| 168 | |
| 169 | |
| 170 | def 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) |
Dan Shi | 8190eb8 | 2016-02-11 17:15:58 -0800 | [diff] [blame] | 184 | |
| 185 | |
Richard Barnette | 60e759e | 2018-07-21 20:56:59 -0700 | [diff] [blame] | 186 | def machine_install_and_update_labels(host, update_url, |
| 187 | use_quick_provision=False, |
Sanika Kulkarni | 000fe8c | 2020-01-22 11:13:29 -0800 | [diff] [blame] | 188 | with_cheets=False, staging_server=None): |
Richard Barnette | 044927e | 2018-07-21 20:50:39 -0700 | [diff] [blame] | 189 | """Install a build and update the version labels on a host. |
Dan Shi | be3636a | 2016-02-14 22:48:01 -0800 | [diff] [blame] | 190 | |
Richard Barnette | 044927e | 2018-07-21 20:50:39 -0700 | [diff] [blame] | 191 | @param host: Host object where the build is to be installed. |
Richard Barnette | 7101322 | 2018-05-05 19:00:45 +0000 | [diff] [blame] | 192 | @param update_url: URL of the build to install. |
Richard Barnette | 60e759e | 2018-07-21 20:56:59 -0700 | [diff] [blame] | 193 | @param use_quick_provision: If true, then attempt to use |
| 194 | quick-provision for the update. |
Richard Barnette | 7101322 | 2018-05-05 19:00:45 +0000 | [diff] [blame] | 195 | @param with_cheets: If true, installation is for a specific, custom |
| 196 | version of Android for a target running ARC. |
Sanika Kulkarni | 000fe8c | 2020-01-22 11:13:29 -0800 | [diff] [blame] | 197 | @param staging_server: Sever where images have been staged. Typically, |
| 198 | an instance of dev_server.ImageServer. |
Dan Shi | be3636a | 2016-02-14 22:48:01 -0800 | [diff] [blame] | 199 | """ |
Xixuan Wu | f9e1161 | 2019-10-15 12:32:47 -0700 | [diff] [blame] | 200 | clean_provision_labels(host) |
Sanika Kulkarni | 000fe8c | 2020-01-22 11:13:29 -0800 | [diff] [blame] | 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( |
Qijiang Fan | 31e0806 | 2020-01-16 17:48:10 +0000 | [diff] [blame] | 222 | update_url, host=host, use_quick_provision=use_quick_provision) |
Sanika Kulkarni | 000fe8c | 2020-01-22 11:13:29 -0800 | [diff] [blame] | 223 | image_name, host_attributes = updater.run_update() |
Richard Barnette | 7101322 | 2018-05-05 19:00:45 +0000 | [diff] [blame] | 224 | if with_cheets: |
Rohit Makasana | df0a3a3 | 2017-06-30 13:55:18 -0700 | [diff] [blame] | 225 | image_name += provision.CHEETS_SUFFIX |
Sanika Kulkarni | 000fe8c | 2020-01-22 11:13:29 -0800 | [diff] [blame] | 226 | add_provision_labels(host, host.VERSION_PREFIX, image_name, |
| 227 | host_attributes) |