215 lines
7.1 KiB
Python
215 lines
7.1 KiB
Python
# 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
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.client.common_lib import global_config
|
|
from autotest_lib.server.cros.dynamic_suite import frontend_wrappers
|
|
|
|
|
|
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)
|
|
_ANDROID_VERSION_MAP = AFE.get_stable_version_map(AFE.ANDROID_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 get_labels(host, prefix=None):
|
|
"""Get labels of a host with name started with given prefix.
|
|
|
|
@param prefix: Prefix of label names, if None, return all labels.
|
|
|
|
@returns List of labels that match the prefix or if prefix is None, all
|
|
labels.
|
|
"""
|
|
if not prefix:
|
|
return host._afe_host.labels
|
|
|
|
return [label for label in host._afe_host.labels
|
|
if label.startswith(prefix)]
|
|
|
|
|
|
def clear_version_labels(host):
|
|
"""Clear version labels for a given host.
|
|
|
|
@param host: Host whose version labels to clear.
|
|
"""
|
|
host._afe_host.labels = [label for label in host._afe_host.labels
|
|
if not label.startswith(host.VERSION_PREFIX)]
|
|
if not _host_in_lab(host):
|
|
return
|
|
|
|
host_list = [host.hostname]
|
|
labels = AFE.get_labels(
|
|
name__startswith=host.VERSION_PREFIX,
|
|
host__hostname=host.hostname)
|
|
|
|
for label in labels:
|
|
label.remove_hosts(hosts=host_list)
|
|
|
|
|
|
def add_version_label(host, image_name):
|
|
"""Add version labels to a host.
|
|
|
|
@param host: Host to add the version label for.
|
|
@param image_name: Name of the build version to add to the host.
|
|
"""
|
|
label = '%s:%s' % (host.VERSION_PREFIX, image_name)
|
|
host._afe_host.labels.append(label)
|
|
if not _host_in_lab(host):
|
|
return
|
|
AFE.run('label_add_hosts', id=label, hosts=[host.hostname])
|
|
|
|
|
|
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(board):
|
|
"""Retrieve the stable firmware version for a given board.
|
|
|
|
@param board: Board to lookup.
|
|
|
|
@returns A version of firmware to be installed via
|
|
`chromeos-firmwareupdate` from a repair build.
|
|
"""
|
|
return _FIRMWARE_VERSION_MAP.get_version(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 get_stable_android_version(board):
|
|
"""Retrieve the stable Android version a given board.
|
|
|
|
@param board: Board to lookup.
|
|
|
|
@returns Stable version of Android for the given board.
|
|
"""
|
|
return _ANDROID_VERSION_MAP.get_version(board)
|
|
|
|
|
|
def get_host_attribute(host, attribute, use_local_value=True):
|
|
"""Looks up the value of host attribute for the host.
|
|
|
|
@param host: A Host object to lookup for attribute value.
|
|
@param attribute: Name of the host attribute.
|
|
@param use_local_value: Boolean to indicate if the local value or AFE value
|
|
should be retrieved.
|
|
|
|
@returns value for the given attribute or None if not found.
|
|
"""
|
|
local_value = host._afe_host.attributes.get(attribute)
|
|
if not _host_in_lab(host) or use_local_value:
|
|
return local_value
|
|
|
|
hosts = AFE.get_hosts(hostname=host.hostname)
|
|
if hosts and attribute in hosts[0].attributes:
|
|
return hosts[0].attributes[attribute]
|
|
else:
|
|
return local_value
|
|
|
|
|
|
def _clear_host_attributes_before_provision(host, info):
|
|
"""Clear host attributes before provision, e.g., job_repo_url.
|
|
|
|
@param host: A Host object to clear attributes before provision.
|
|
@param info: A HostInfo to update the attributes in.
|
|
"""
|
|
attributes = host.get_attributes_to_clear_before_provision()
|
|
if not attributes:
|
|
return
|
|
|
|
for key in attributes:
|
|
info.attributes.pop(key, None)
|
|
|
|
|
|
def update_host_attribute(host, attribute, value):
|
|
"""Updates the host attribute with given value.
|
|
|
|
@param host: A Host object to update attribute value.
|
|
@param attribute: Name of the host attribute.
|
|
@param value: Value for the host attribute.
|
|
|
|
@raises AutoservError: If we failed to update the attribute.
|
|
"""
|
|
host._afe_host.attributes[attribute] = value
|
|
if not _host_in_lab(host):
|
|
return
|
|
|
|
AFE.set_host_attribute(attribute, value, hostname=host.hostname)
|
|
info = host.host_info_store.get(force_refresh=True)
|
|
if info.attributes.get(attribute) != value:
|
|
raise error.AutoservError(
|
|
'Failed to update host attribute `%s` with %s, host %s' %
|
|
(attribute, value, host.hostname))
|
|
|
|
|
|
def machine_install_and_update_labels(host, *args, **dargs):
|
|
"""Calls machine_install and updates the version labels on a host.
|
|
|
|
@param host: Host object to run machine_install on.
|
|
@param *args: Args list to pass to machine_install.
|
|
@param **dargs: dargs dict to pass to machine_install.
|
|
"""
|
|
info = host.host_info_store.get()
|
|
info.clear_version_labels()
|
|
_clear_host_attributes_before_provision(host, info)
|
|
host.host_info_store.commit(info)
|
|
# If ENABLE_DEVSERVER_TRIGGER_AUTO_UPDATE is enabled and the host is a
|
|
# CrosHost, devserver will be used to trigger auto-update.
|
|
if host.support_devserver_provision:
|
|
image_name, host_attributes = host.machine_install_by_devserver(
|
|
*args, **dargs)
|
|
else:
|
|
image_name, host_attributes = host.machine_install(*args, **dargs)
|
|
|
|
info = host.host_info_store.get()
|
|
info.attributes.update(host_attributes)
|
|
info.set_version_label(host.VERSION_PREFIX, image_name)
|
|
host.host_info_store.commit(info)
|