blob: f6997bd18754eb5db024eb0f9ada06d628094b1b [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 """
Kevin Cheng4ce67612016-07-29 13:34:17 -0700111 host._afe_host.labels = [label for label in host._afe_host.labels
112 if not label.startswith(host.VERSION_PREFIX)]
Simran Basi5ace6f22016-01-06 17:30:44 -0800113 if not host_in_lab(host):
114 return
115
116 host_list = [host.hostname]
117 labels = AFE.get_labels(
118 name__startswith=host.VERSION_PREFIX,
119 host__hostname=host.hostname)
120
121 for label in labels:
122 label.remove_hosts(hosts=host_list)
123
124
125def add_version_label(host, image_name):
126 """Add version labels to a host.
127
128 @param host: Host to add the version label for.
129 @param image_name: Name of the build version to add to the host.
130 """
Kevin Cheng4ce67612016-07-29 13:34:17 -0700131 label = '%s:%s' % (host.VERSION_PREFIX, image_name)
132 host._afe_host.labels.append(label)
Simran Basi5ace6f22016-01-06 17:30:44 -0800133 if not host_in_lab(host):
134 return
Simran Basi5ace6f22016-01-06 17:30:44 -0800135 AFE.run('label_add_hosts', id=label, hosts=[host.hostname])
136
137
Simran Basibeb2bb22016-02-03 15:25:48 -0800138def get_stable_version(board, android=False):
139 """Retrieves a board's stable version from the AFE.
140
141 @param board: Board to lookup.
142 @param android: If True, indicates we are looking up a Android/Brillo-based
143 board. There is no default version that works for all
144 Android/Brillo boards. If False, we are looking up a Chrome
145 OS based board.
146
147 @returns Stable version of the given board.
148 """
149 return AFE.run('get_stable_version', board=board, android=android)
Dan Shi8190eb82016-02-11 17:15:58 -0800150
151
Dan Shie4256c82016-02-18 00:23:49 -0800152def lookup_job_repo_url(host):
Dan Shi8190eb82016-02-11 17:15:58 -0800153 """Looks up the job_repo_url for the host.
154
Dan Shie4256c82016-02-18 00:23:49 -0800155 The method is kept for backwards compatibility with test
156 autoupdate_EndToEndTest in existing builds. It should not be used for new
157 code.
158 TODO(dshi): Update autoupdate_EndToEndTest to use get_host_attribute after
159 lab is updated. After R50 is in stable channel, this method can be removed.
160
161 @param host: A Host object to lookup for job_repo_url.
162
163 @returns Host attribute `job_repo_url` of the given host.
164 """
165 return get_host_attribute(host, host.job_repo_url_attribute)
166
167
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700168def get_host_attribute(host, attribute, use_local_value=True):
Dan Shie4256c82016-02-18 00:23:49 -0800169 """Looks up the value of host attribute for the host.
170
Dan Shibe3636a2016-02-14 22:48:01 -0800171 @param host: A Host object to lookup for attribute value.
172 @param attribute: Name of the host attribute.
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700173 @param use_local_value: Boolean to indicate if the local value or AFE value
174 should be retrieved.
Dan Shi8190eb82016-02-11 17:15:58 -0800175
Dan Shibe3636a2016-02-14 22:48:01 -0800176 @returns value for the given attribute or None if not found.
Dan Shi8190eb82016-02-11 17:15:58 -0800177 """
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700178 local_value = host._afe_host.attributes.get(attribute)
179 if not host_in_lab(host) or use_local_value:
Dan Shibe3636a2016-02-14 22:48:01 -0800180 return local_value
181
Dan Shi8190eb82016-02-11 17:15:58 -0800182 hosts = AFE.get_hosts(hostname=host.hostname)
Dan Shibe3636a2016-02-14 22:48:01 -0800183 if hosts and attribute in hosts[0].attributes:
184 return hosts[0].attributes[attribute]
Dan Shi8190eb82016-02-11 17:15:58 -0800185 else:
Dan Shibe3636a2016-02-14 22:48:01 -0800186 return local_value
Dan Shi8190eb82016-02-11 17:15:58 -0800187
188
Dan Shibe3636a2016-02-14 22:48:01 -0800189def clear_host_attributes_before_provision(host):
Dan Shie4256c82016-02-18 00:23:49 -0800190 """Clear host attributes before provision, e.g., job_repo_url.
Dan Shi8190eb82016-02-11 17:15:58 -0800191
Dan Shibe3636a2016-02-14 22:48:01 -0800192 @param host: A Host object to clear attributes before provision.
Dan Shi8190eb82016-02-11 17:15:58 -0800193 """
Dan Shibe3636a2016-02-14 22:48:01 -0800194 attributes = host.get_attributes_to_clear_before_provision()
195 for attribute in attributes:
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700196 host._afe_host.attributes.pop(attribute, None)
Dan Shi8190eb82016-02-11 17:15:58 -0800197 if not host_in_lab(host):
198 return
Dan Shibe3636a2016-02-14 22:48:01 -0800199
200 for attribute in attributes:
201 update_host_attribute(host, attribute, None)
Dan Shi8190eb82016-02-11 17:15:58 -0800202
203
Dan Shibe3636a2016-02-14 22:48:01 -0800204def update_host_attribute(host, attribute, value):
205 """Updates the host attribute with given value.
Dan Shi8190eb82016-02-11 17:15:58 -0800206
Dan Shibe3636a2016-02-14 22:48:01 -0800207 @param host: A Host object to update attribute value.
208 @param attribute: Name of the host attribute.
209 @param value: Value for the host attribute.
Dan Shi8190eb82016-02-11 17:15:58 -0800210
Dan Shie4256c82016-02-18 00:23:49 -0800211 @raises AutoservError: If we failed to update the attribute.
Dan Shi8190eb82016-02-11 17:15:58 -0800212 """
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700213 host._afe_host.attributes[attribute] = value
Dan Shi8190eb82016-02-11 17:15:58 -0800214 if not host_in_lab(host):
215 return
216
Dan Shibe3636a2016-02-14 22:48:01 -0800217 AFE.set_host_attribute(attribute, value, hostname=host.hostname)
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700218 if get_host_attribute(host, attribute, use_local_value=False) != value:
Dan Shibe3636a2016-02-14 22:48:01 -0800219 raise error.AutoservError(
220 'Failed to update host attribute `%s` with %s, host %s' %
221 (attribute, value, host.hostname))
222
223
224def machine_install_and_update_labels(host, *args, **dargs):
225 """Calls machine_install and updates the version labels on a host.
226
227 @param host: Host object to run machine_install on.
228 @param *args: Args list to pass to machine_install.
229 @param **dargs: dargs dict to pass to machine_install.
230 """
231 clear_version_labels(host)
232 clear_host_attributes_before_provision(host)
xixuan5dc64ea2016-05-20 17:27:51 -0700233 if not ENABLE_DEVSERVER_TRIGGER_AUTO_UPDATE:
234 image_name, host_attributes = host.machine_install(*args, **dargs)
235 else:
236 image_name, host_attributes = host.machine_install_by_devserver(
237 *args, **dargs)
Dan Shibe3636a2016-02-14 22:48:01 -0800238 add_version_label(host, image_name)
239 for attribute, value in host_attributes.items():
240 update_host_attribute(host, attribute, value)
Dan Shi6450e142016-03-11 11:52:20 -0800241
242
Kevin Cheng212880e2016-06-28 12:09:01 -0700243def get_os(host):
Kevin Cheng84a71ba2016-07-14 11:03:57 -0700244 """Retrieve the os for a given host stored inside host._afe_host.
Kevin Cheng212880e2016-06-28 12:09:01 -0700245
246 @param host: Host object to get board.
247
248 @returns The os or None if it could not find it.
249 """
Kevin Cheng84a71ba2016-07-14 11:03:57 -0700250 full_os_prefix = constants.OS_PREFIX + ':'
251 os_labels = get_labels(host, full_os_prefix)
252 if not os_labels:
Kevin Cheng212880e2016-06-28 12:09:01 -0700253 return None
Kevin Cheng84a71ba2016-07-14 11:03:57 -0700254 return os_labels[0][len(full_os_prefix):]