blob: 40730265f82aafa72da7d55217e8ca3218a9df16 [file] [log] [blame]
Simran Basi5ace6f22016-01-06 17:30:44 -08001# 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 Basiaa467ad2016-02-03 16:56:22 -08005"""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"""
Simran Basi5ace6f22016-01-06 17:30:44 -080011
12import common
Dan Shi8190eb82016-02-11 17:15:58 -080013from autotest_lib.client.common_lib import error
Kevin Cheng84a71ba2016-07-14 11:03:57 -070014from autotest_lib.server.cros import provision
15from autotest_lib.server.cros.dynamic_suite import constants
xixuan5dc64ea2016-05-20 17:27:51 -070016from autotest_lib.client.common_lib import global_config
Simran Basi5ace6f22016-01-06 17:30:44 -080017from autotest_lib.server.cros.dynamic_suite import frontend_wrappers
Dan Shi8190eb82016-02-11 17:15:58 -080018
Simran Basi5ace6f22016-01-06 17:30:44 -080019
20AFE = frontend_wrappers.RetryingAFE(timeout_min=5, delay_sec=10)
21
xixuan5dc64ea2016-05-20 17:27:51 -070022_CONFIG = global_config.global_config
23ENABLE_DEVSERVER_TRIGGER_AUTO_UPDATE = _CONFIG.get_config_value(
24 'CROS', 'enable_devserver_trigger_auto_update', type=bool,
25 default=False)
26
Simran Basi5ace6f22016-01-06 17:30:44 -080027
28def host_in_lab(host):
29 """Check if the host is in the lab and an object the AFE knows.
30
31 This check ensures that autoserv and the host's current job is running
32 inside a fully Autotest instance, aka a lab environment. If this is the
33 case it then verifies the host is registed with the configured AFE
34 instance.
35
36 @param host: Host object to verify.
37
38 @returns The host model object.
39 """
Simran Basiaa467ad2016-02-03 16:56:22 -080040 if not host.job or not host.job.in_lab:
Simran Basi5ace6f22016-01-06 17:30:44 -080041 return False
Kevin Cheng05ae2a42016-06-06 10:12:48 -070042 return host._afe_host
Simran Basi5ace6f22016-01-06 17:30:44 -080043
44
Kevin Cheng84a71ba2016-07-14 11:03:57 -070045def get_labels(host, prefix=None):
46 """Get labels of a host with name started with given prefix.
Simran Basi5ace6f22016-01-06 17:30:44 -080047
Kevin Cheng84a71ba2016-07-14 11:03:57 -070048 @param prefix: Prefix of label names, if None, return all labels.
49
50 @returns List of labels that match the prefix or if prefix is None, all
51 labels.
52 """
53 if not prefix:
54 return host._afe_host.labels
55
56 return [label for label in host._afe_host.labels
57 if label.startswith(prefix)]
58
59
60def get_build(host):
61 """Retrieve the current build for a given host stored inside host._afe_host.
62
63 Looks through a host's labels in host._afe_host.labels to determine
64 its build.
Simran Basi5ace6f22016-01-06 17:30:44 -080065
Dan Shib3b6db32016-02-03 14:54:05 -080066 @param host: Host object to get build.
Simran Basi5ace6f22016-01-06 17:30:44 -080067
68 @returns The current build or None if it could not find it or if there
69 were multiple build labels assigned to the host.
70 """
Kevin Cheng84a71ba2016-07-14 11:03:57 -070071 for label_prefix in [provision.CROS_VERSION_PREFIX,
72 provision.ANDROID_BUILD_VERSION_PREFIX,
73 provision.TESTBED_BUILD_VERSION_PREFIX]:
74 full_label_prefix = label_prefix + ':'
75 build_labels = get_labels(host, full_label_prefix)
76 if build_labels:
77 return build_labels[0][len(full_label_prefix):]
78 return None
79
80
81def get_boards(host):
82 """Retrieve all boards for a given host stored inside host._afe_host.
83
84 @param host: Host object to get board.
85
86 @returns List of all boards.
87 """
88 return [board[len(constants.BOARD_PREFIX):]
89 for board in get_labels(host, constants.BOARD_PREFIX)]
Simran Basi5ace6f22016-01-06 17:30:44 -080090
91
Simran Basibeb2bb22016-02-03 15:25:48 -080092def get_board(host):
Kevin Cheng84a71ba2016-07-14 11:03:57 -070093 """Retrieve the board for a given host stored inside host._afe_host.
Simran Basibeb2bb22016-02-03 15:25:48 -080094
95 @param host: Host object to get board.
96
97 @returns The current board or None if it could not find it.
98 """
Kevin Cheng84a71ba2016-07-14 11:03:57 -070099 boards = get_boards(host)
100 if not boards:
Simran Basibeb2bb22016-02-03 15:25:48 -0800101 return None
Kevin Cheng84a71ba2016-07-14 11:03:57 -0700102 return boards[0]
103
Simran Basibeb2bb22016-02-03 15:25:48 -0800104
105
Simran Basi5ace6f22016-01-06 17:30:44 -0800106def clear_version_labels(host):
107 """Clear version labels for a given host.
108
109 @param host: Host whose version labels to clear.
110 """
111 if not host_in_lab(host):
112 return
113
114 host_list = [host.hostname]
115 labels = AFE.get_labels(
116 name__startswith=host.VERSION_PREFIX,
117 host__hostname=host.hostname)
118
119 for label in labels:
120 label.remove_hosts(hosts=host_list)
121
122
123def add_version_label(host, image_name):
124 """Add version labels to a host.
125
126 @param host: Host to add the version label for.
127 @param image_name: Name of the build version to add to the host.
128 """
129 if not host_in_lab(host):
130 return
131 label = '%s:%s' % (host.VERSION_PREFIX, image_name)
132 AFE.run('label_add_hosts', id=label, hosts=[host.hostname])
133
134
Simran Basibeb2bb22016-02-03 15:25:48 -0800135def get_stable_version(board, android=False):
136 """Retrieves a board's stable version from the AFE.
137
138 @param board: Board to lookup.
139 @param android: If True, indicates we are looking up a Android/Brillo-based
140 board. There is no default version that works for all
141 Android/Brillo boards. If False, we are looking up a Chrome
142 OS based board.
143
144 @returns Stable version of the given board.
145 """
146 return AFE.run('get_stable_version', board=board, android=android)
Dan Shi8190eb82016-02-11 17:15:58 -0800147
148
Dan Shie4256c82016-02-18 00:23:49 -0800149def lookup_job_repo_url(host):
Dan Shi8190eb82016-02-11 17:15:58 -0800150 """Looks up the job_repo_url for the host.
151
Dan Shie4256c82016-02-18 00:23:49 -0800152 The method is kept for backwards compatibility with test
153 autoupdate_EndToEndTest in existing builds. It should not be used for new
154 code.
155 TODO(dshi): Update autoupdate_EndToEndTest to use get_host_attribute after
156 lab is updated. After R50 is in stable channel, this method can be removed.
157
158 @param host: A Host object to lookup for job_repo_url.
159
160 @returns Host attribute `job_repo_url` of the given host.
161 """
162 return get_host_attribute(host, host.job_repo_url_attribute)
163
164
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700165def get_host_attribute(host, attribute, use_local_value=True):
Dan Shie4256c82016-02-18 00:23:49 -0800166 """Looks up the value of host attribute for the host.
167
Dan Shibe3636a2016-02-14 22:48:01 -0800168 @param host: A Host object to lookup for attribute value.
169 @param attribute: Name of the host attribute.
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700170 @param use_local_value: Boolean to indicate if the local value or AFE value
171 should be retrieved.
Dan Shi8190eb82016-02-11 17:15:58 -0800172
Dan Shibe3636a2016-02-14 22:48:01 -0800173 @returns value for the given attribute or None if not found.
Dan Shi8190eb82016-02-11 17:15:58 -0800174 """
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700175 local_value = host._afe_host.attributes.get(attribute)
176 if not host_in_lab(host) or use_local_value:
Dan Shibe3636a2016-02-14 22:48:01 -0800177 return local_value
178
Dan Shi8190eb82016-02-11 17:15:58 -0800179 hosts = AFE.get_hosts(hostname=host.hostname)
Dan Shibe3636a2016-02-14 22:48:01 -0800180 if hosts and attribute in hosts[0].attributes:
181 return hosts[0].attributes[attribute]
Dan Shi8190eb82016-02-11 17:15:58 -0800182 else:
Dan Shibe3636a2016-02-14 22:48:01 -0800183 return local_value
Dan Shi8190eb82016-02-11 17:15:58 -0800184
185
Dan Shibe3636a2016-02-14 22:48:01 -0800186def clear_host_attributes_before_provision(host):
Dan Shie4256c82016-02-18 00:23:49 -0800187 """Clear host attributes before provision, e.g., job_repo_url.
Dan Shi8190eb82016-02-11 17:15:58 -0800188
Dan Shibe3636a2016-02-14 22:48:01 -0800189 @param host: A Host object to clear attributes before provision.
Dan Shi8190eb82016-02-11 17:15:58 -0800190 """
Dan Shibe3636a2016-02-14 22:48:01 -0800191 attributes = host.get_attributes_to_clear_before_provision()
192 for attribute in attributes:
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700193 host._afe_host.attributes.pop(attribute, None)
Dan Shi8190eb82016-02-11 17:15:58 -0800194 if not host_in_lab(host):
195 return
Dan Shibe3636a2016-02-14 22:48:01 -0800196
197 for attribute in attributes:
198 update_host_attribute(host, attribute, None)
Dan Shi8190eb82016-02-11 17:15:58 -0800199
200
Dan Shibe3636a2016-02-14 22:48:01 -0800201def update_host_attribute(host, attribute, value):
202 """Updates the host attribute with given value.
Dan Shi8190eb82016-02-11 17:15:58 -0800203
Dan Shibe3636a2016-02-14 22:48:01 -0800204 @param host: A Host object to update attribute value.
205 @param attribute: Name of the host attribute.
206 @param value: Value for the host attribute.
Dan Shi8190eb82016-02-11 17:15:58 -0800207
Dan Shie4256c82016-02-18 00:23:49 -0800208 @raises AutoservError: If we failed to update the attribute.
Dan Shi8190eb82016-02-11 17:15:58 -0800209 """
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700210 host._afe_host.attributes[attribute] = value
Dan Shi8190eb82016-02-11 17:15:58 -0800211 if not host_in_lab(host):
212 return
213
Dan Shibe3636a2016-02-14 22:48:01 -0800214 AFE.set_host_attribute(attribute, value, hostname=host.hostname)
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700215 if get_host_attribute(host, attribute, use_local_value=False) != value:
Dan Shibe3636a2016-02-14 22:48:01 -0800216 raise error.AutoservError(
217 'Failed to update host attribute `%s` with %s, host %s' %
218 (attribute, value, host.hostname))
219
220
221def machine_install_and_update_labels(host, *args, **dargs):
222 """Calls machine_install and updates the version labels on a host.
223
224 @param host: Host object to run machine_install on.
225 @param *args: Args list to pass to machine_install.
226 @param **dargs: dargs dict to pass to machine_install.
227 """
228 clear_version_labels(host)
229 clear_host_attributes_before_provision(host)
xixuan5dc64ea2016-05-20 17:27:51 -0700230 if not ENABLE_DEVSERVER_TRIGGER_AUTO_UPDATE:
231 image_name, host_attributes = host.machine_install(*args, **dargs)
232 else:
233 image_name, host_attributes = host.machine_install_by_devserver(
234 *args, **dargs)
Dan Shibe3636a2016-02-14 22:48:01 -0800235 add_version_label(host, image_name)
236 for attribute, value in host_attributes.items():
237 update_host_attribute(host, attribute, value)
Dan Shi6450e142016-03-11 11:52:20 -0800238
239
Kevin Cheng212880e2016-06-28 12:09:01 -0700240def get_os(host):
Kevin Cheng84a71ba2016-07-14 11:03:57 -0700241 """Retrieve the os for a given host stored inside host._afe_host.
Kevin Cheng212880e2016-06-28 12:09:01 -0700242
243 @param host: Host object to get board.
244
245 @returns The os or None if it could not find it.
246 """
Kevin Cheng84a71ba2016-07-14 11:03:57 -0700247 full_os_prefix = constants.OS_PREFIX + ':'
248 os_labels = get_labels(host, full_os_prefix)
249 if not os_labels:
Kevin Cheng212880e2016-06-28 12:09:01 -0700250 return None
Kevin Cheng84a71ba2016-07-14 11:03:57 -0700251 return os_labels[0][len(full_os_prefix):]