• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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