blob: 28ff0d2d7c8c9b21c119ab4458b58b9a3f218bb6 [file] [log] [blame]
Kevin Chenga2619dc2016-03-28 11:42:08 -07001# Copyright 2016 The Chromium OS 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"""This class defines the CrosHost Label class."""
6
C Shapiro05dd3222017-09-22 10:42:33 -06007import collections
Kevin Chenga2619dc2016-03-28 11:42:08 -07008import logging
Kevin Chenga2619dc2016-03-28 11:42:08 -07009import re
10
11import common
12
13from autotest_lib.client.bin import utils
Kevin Cheng80ad5732016-03-31 16:01:56 -070014from autotest_lib.client.common_lib import global_config
Kevin Chenga2619dc2016-03-28 11:42:08 -070015from autotest_lib.client.cros.audio import cras_utils
Kevin Chenga2619dc2016-03-28 11:42:08 -070016from autotest_lib.server.cros.dynamic_suite import constants as ds_constants
17from autotest_lib.server.hosts import base_label
18from autotest_lib.server.hosts import common_label
Garry Wang11b5e872020-03-11 15:14:08 -070019from autotest_lib.server.hosts import servo_constants
Kevin Cheng80ad5732016-03-31 16:01:56 -070020from autotest_lib.site_utils import hwid_lib
Kevin Chenga2619dc2016-03-28 11:42:08 -070021
22# pylint: disable=missing-docstring
C Shapiro05dd3222017-09-22 10:42:33 -060023LsbOutput = collections.namedtuple('LsbOutput', ['unibuild', 'board'])
24
Gregory Nisbetfb68a1f2019-08-22 10:27:33 -070025# fallback values if we can't contact the HWID server
26HWID_LABELS_FALLBACK = ['sku', 'phase', 'touchscreen', 'touchpad', 'variant', 'stylus']
27
Eshwar Narayan871a2c02020-02-06 11:15:24 -080028# Repair and Deploy taskName
29REPAIR_TASK_NAME = 'repair'
30DEPLOY_TASK_NAME = 'deploy'
31
Gregory Nisbetfb68a1f2019-08-22 10:27:33 -070032
C Shapiro05dd3222017-09-22 10:42:33 -060033def _parse_lsb_output(host):
Allen Lia0c7afc2019-02-26 15:50:06 -080034 """Parses the LSB output and returns key data points for labeling.
C Shapiro05dd3222017-09-22 10:42:33 -060035
Allen Lia0c7afc2019-02-26 15:50:06 -080036 @param host: Host that the command will be executed against
37 @returns: LsbOutput with the result of parsing the /etc/lsb-release output
38 """
39 release_info = utils.parse_cmd_output('cat /etc/lsb-release',
40 run_method=host.run)
C Shapiro05dd3222017-09-22 10:42:33 -060041
Allen Lia0c7afc2019-02-26 15:50:06 -080042 unibuild = release_info.get('CHROMEOS_RELEASE_UNIBUILD') == '1'
43 return LsbOutput(unibuild, release_info['CHROMEOS_RELEASE_BOARD'])
C Shapiro05dd3222017-09-22 10:42:33 -060044
Kevin Chenga2619dc2016-03-28 11:42:08 -070045
C Shapirobe0ff8d2019-06-14 10:41:43 -060046class DeviceSkuLabel(base_label.StringPrefixLabel):
47 """Determine the correct device_sku label for the device."""
48
49 _NAME = ds_constants.DEVICE_SKU_LABEL
50
51 def generate_labels(self, host):
52 device_sku = host.host_info_store.get().device_sku
53 if device_sku:
54 return [device_sku]
55
56 mosys_cmd = 'mosys platform sku'
57 result = host.run(command=mosys_cmd, ignore_status=True)
58 if result.exit_status == 0:
59 return [result.stdout.strip()]
60
61 return []
62
Eshwar Narayan871a2c02020-02-06 11:15:24 -080063 def update_for_task(self, task_name):
64 # This label is stored in the lab config, so only deploy tasks update it
65 # or when no task name is mentioned.
66 return task_name in (DEPLOY_TASK_NAME, '')
67
C Shapirobe0ff8d2019-06-14 10:41:43 -060068
Ned Nguyene0a619d2019-07-01 15:50:23 -060069class BrandCodeLabel(base_label.StringPrefixLabel):
70 """Determine the correct brand_code (aka RLZ-code) for the device."""
71
72 _NAME = ds_constants.BRAND_CODE_LABEL
73
74 def generate_labels(self, host):
75 brand_code = host.host_info_store.get().brand_code
76 if brand_code:
77 return [brand_code]
78
Greg Edelston7cea0c42019-11-26 15:17:22 -070079 cros_config_cmd = 'cros_config / brand-code'
80 result = host.run(command=cros_config_cmd, ignore_status=True)
Ned Nguyene0a619d2019-07-01 15:50:23 -060081 if result.exit_status == 0:
82 return [result.stdout.strip()]
83
84 return []
85
86
Shijin Abrahamc09587d2020-02-14 20:46:55 -080087class BluetoothPeerLabel(base_label.StringPrefixLabel):
88 """Return the Bluetooth peer labels.
89
90 working_bluetooth_btpeer label is applied if a Raspberry Pi Bluetooth peer
91 is detected.There can be up to 4 Bluetooth peers. Labels
92 working_bluetooth_btpeer:[1-4] will be assigned depending on the number of
93 peers present.
94
95 """
96
97 _NAME = 'working_bluetooth_btpeer'
98
99 def exists(self, host):
100 return len(host._btpeer_host_list) > 0
101
102 def generate_labels(self, host):
103 labels_list = []
104 count = 1
105
106 for (btpeer, btpeer_host) in \
107 zip(host.btpeer_list, host._btpeer_host_list):
108 try:
109 # Initialize one device type to make sure the peer is working
110 bt_hid_device = btpeer.get_bluetooth_hid_mouse()
111 if bt_hid_device.CheckSerialConnection():
112 labels_list.append(str(count))
113 count += 1
114 except Exception as e:
115 logging.error('Error with initializing bt_hid_mouse on '
116 'btpeer %s %s', btpeer_host.hostname, e)
117
118 logging.info('Bluetooth Peer labels are %s', labels_list)
119 return labels_list
120
121 def update_for_task(self, task_name):
Shijin Abraham76bc1db2020-03-06 10:52:10 -0800122 # This label is stored in the state config, so only repair tasks update
123 # it or when no task name is mentioned.
124 return task_name in (REPAIR_TASK_NAME, '')
Shijin Abrahamc09587d2020-02-14 20:46:55 -0800125
Kevin Chenga2619dc2016-03-28 11:42:08 -0700126
Mary Ruthven935ebad2018-06-13 16:13:20 -0700127class Cr50Label(base_label.StringPrefixLabel):
Mary Ruthven6c462642019-09-17 19:13:36 -0700128 """Label indicating the cr50 image type."""
Mary Ruthven935ebad2018-06-13 16:13:20 -0700129
130 _NAME = 'cr50'
131
132 def __init__(self):
133 self.ver = None
134
Mary Ruthven935ebad2018-06-13 16:13:20 -0700135 def exists(self, host):
136 # Make sure the gsctool version command runs ok
137 self.ver = host.run('gsctool -a -f', ignore_status=True)
138 return self.ver.exit_status == 0
139
Mary Ruthven6c462642019-09-17 19:13:36 -0700140 def _get_version(self, region):
141 """Get the version number of the given region"""
142 return re.search(region + ' (\d+\.\d+\.\d+)', self.ver.stdout).group(1)
Mary Ruthven935ebad2018-06-13 16:13:20 -0700143
144 def generate_labels(self, host):
145 # Check the major version to determine prePVT vs PVT
Mary Ruthven6c462642019-09-17 19:13:36 -0700146 version = self._get_version('RW')
147 major_version = int(version.split('.')[1])
Mary Ruthven935ebad2018-06-13 16:13:20 -0700148 # PVT images have a odd major version prePVT have even
Mary Ruthven6c462642019-09-17 19:13:36 -0700149 return ['pvt' if (major_version % 2) else 'prepvt']
150
Xixuan Wu61b2b262020-03-06 10:09:55 -0800151 def update_for_task(self, task_name):
152 # This label is stored in the state config, so only repair tasks update
153 # it or when no task name is mentioned.
154 return task_name in (REPAIR_TASK_NAME, '')
155
Mary Ruthven6c462642019-09-17 19:13:36 -0700156
157class Cr50RWKeyidLabel(Cr50Label):
158 """Label indicating the cr50 RW version."""
159 _REGION = 'RW'
160 _NAME = 'cr50-rw-keyid'
161
162 def _get_keyid_info(self, region):
163 """Get the keyid of the given region."""
164 match = re.search('keyids:.*%s (\S+)' % region, self.ver.stdout)
165 keyid = match.group(1).rstrip(',')
166 is_prod = int(keyid, 16) & (1 << 2)
167 return [keyid, 'prod' if is_prod else 'dev']
168
169 def generate_labels(self, host):
170 """Get the key type."""
171 return self._get_keyid_info(self._REGION)
172
173
174class Cr50ROKeyidLabel(Cr50RWKeyidLabel):
175 """Label indicating the RO key type."""
176 _REGION = 'RO'
177 _NAME = 'cr50-ro-keyid'
178
179
Kevin Chenga2619dc2016-03-28 11:42:08 -0700180class ChameleonLabel(base_label.BaseLabel):
181 """Determine if a Chameleon is connected to this host."""
182
183 _NAME = 'chameleon'
184
185 def exists(self, host):
Xixuan Wu7afb54f2019-09-17 11:45:20 -0700186 # See crbug.com/1004500#2 for details.
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800187 has_chameleon = host._chameleon_host is not None
Gregory Nisbetb2f6d792019-09-11 14:30:47 -0700188 # TODO(crbug.com/995900) -- debug why chameleon label is flipping
189 try:
190 logging.info("has_chameleon %s", has_chameleon)
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800191 logging.info("_chameleon_host %s",
192 getattr(host, "_chameleon_host", "NO_ATTRIBUTE"))
193 logging.info("chameleon %s",
194 getattr(host, "chameleon", "NO_ATTRIBUTE"))
Gregory Nisbetb2f6d792019-09-11 14:30:47 -0700195 except:
196 pass
197 return has_chameleon
198
Eshwar Narayan871a2c02020-02-06 11:15:24 -0800199 def update_for_task(self, task_name):
200 # This label is stored in the state config, so only repair tasks update
201 # it or when no task name is mentioned.
202 return task_name in (REPAIR_TASK_NAME, '')
Kevin Chenga2619dc2016-03-28 11:42:08 -0700203
204
205class ChameleonConnectionLabel(base_label.StringPrefixLabel):
206 """Return the Chameleon connection label."""
207
208 _NAME = 'chameleon'
209
210 def exists(self, host):
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800211 return host._chameleon_host is not None
Joseph Hwangeac44312016-08-31 12:08:38 +0800212
Kevin Chenga2619dc2016-03-28 11:42:08 -0700213 def generate_labels(self, host):
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800214 return [host.chameleon.get_label()]
Kevin Chenga2619dc2016-03-28 11:42:08 -0700215
Eshwar Narayan871a2c02020-02-06 11:15:24 -0800216 def update_for_task(self, task_name):
217 # This label is stored in the lab config, so only deploy tasks update it
218 # or when no task name is mentioned.
219 return task_name in (DEPLOY_TASK_NAME, '')
220
Kevin Chenga2619dc2016-03-28 11:42:08 -0700221
Joseph Hwangeac44312016-08-31 12:08:38 +0800222class ChameleonPeripheralsLabel(base_label.StringPrefixLabel):
223 """Return the Chameleon peripherals labels.
224
225 The 'chameleon:bt_hid' label is applied if the bluetooth
226 classic hid device, i.e, RN-42 emulation kit, is detected.
227
228 Any peripherals plugged into the chameleon board would be
229 detected and applied proper labels in this class.
230 """
231
232 _NAME = 'chameleon'
233
234 def exists(self, host):
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800235 return host._chameleon_host is not None
Joseph Hwangeac44312016-08-31 12:08:38 +0800236
237 def generate_labels(self, host):
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800238 labels = []
239 try:
240 bt_hid_device = host.chameleon.get_bluetooth_hid_mouse()
241 if bt_hid_device.CheckSerialConnection():
242 labels.append('bt_hid')
243 except:
244 logging.error('Error with initializing bt_hid_mouse')
howardchung83e55272019-08-08 14:08:05 +0800245
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800246 try:
247 ble_hid_device = host.chameleon.get_ble_mouse()
248 if ble_hid_device.CheckSerialConnection():
249 labels.append('bt_ble_hid')
250 except:
251 logging.error('Error with initializing ble_hid_mouse')
howardchung83e55272019-08-08 14:08:05 +0800252
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800253 try:
254 bt_a2dp_sink = host.chameleon.get_bluetooth_a2dp_sink()
255 if bt_a2dp_sink.CheckSerialConnection():
256 labels.append('bt_a2dp_sink')
257 except:
258 logging.error('Error with initializing bt_a2dp_sink')
howardchung83e55272019-08-08 14:08:05 +0800259
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800260 try:
Joseph Hwang94044ea2020-01-03 14:47:43 +0800261 bt_audio_device = host.chameleon.get_bluetooth_audio()
262 if bt_audio_device.IsDetected():
263 labels.append('bt_audio')
264 except:
265 logging.error('Error in detecting bt_audio')
266
267 try:
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800268 bt_base_device = host.chameleon.get_bluetooth_base()
269 if bt_base_device.IsDetected():
270 labels.append('bt_base')
271 except:
272 logging.error('Error in detecting bt_base')
howardchung83e55272019-08-08 14:08:05 +0800273
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800274 if labels != []:
275 labels.append('bt_peer')
Joseph Hwang89e779c2019-12-24 16:05:56 +0800276
Shijin Abraham783a7dd2020-02-14 15:36:11 -0800277 logging.info('Chameleon Bluetooth labels are %s', labels)
278 return labels
Shijin Abrahamff61ac32019-05-20 12:35:44 -0700279
Eshwar Narayan871a2c02020-02-06 11:15:24 -0800280 def update_for_task(self, task_name):
281 # This label is stored in the lab config, so only deploy tasks update it
282 # or when no task name is mentioned.
283 return task_name in (DEPLOY_TASK_NAME, '')
Joseph Hwangeac44312016-08-31 12:08:38 +0800284
285
Kevin Chenga2619dc2016-03-28 11:42:08 -0700286class AudioLoopbackDongleLabel(base_label.BaseLabel):
287 """Return the label if an audio loopback dongle is plugged in."""
288
289 _NAME = 'audio_loopback_dongle'
290
291 def exists(self, host):
Gregory Nisbete280ea22019-08-16 17:50:03 -0700292 # Based on crbug.com/991285, AudioLoopbackDongle sometimes flips.
293 # Ensure that AudioLoopbackDongle.exists returns True
294 # forever, after it returns True *once*.
295 if self._cached_exists(host):
296 # If the current state is True, return it, don't run the command on
297 # the DUT and potentially flip the state.
298 return True
299 # If the current state is not True, run the command on
300 # the DUT. The new state will be set to whatever the command
301 # produces.
302 return self._host_run_exists(host)
303
304 def _cached_exists(self, host):
305 """Get the state of AudioLoopbackDongle in the data store"""
306 info = host.host_info_store.get()
307 for label in info.labels:
308 if label.startswith(self._NAME):
309 return True
310 return False
311
312 def _host_run_exists(self, host):
313 """Detect presence of audio_loopback_dongle by physically
314 running a command on the DUT."""
Kevin Chenga2619dc2016-03-28 11:42:08 -0700315 nodes_info = host.run(command=cras_utils.get_cras_nodes_cmd(),
316 ignore_status=True).stdout
317 if (cras_utils.node_type_is_plugged('HEADPHONE', nodes_info) and
318 cras_utils.node_type_is_plugged('MIC', nodes_info)):
Otabek Kasimovcefc0d12020-02-07 17:13:52 -0800319 return True
Kevin Chenga2619dc2016-03-28 11:42:08 -0700320 return False
321
Eshwar Narayan871a2c02020-02-06 11:15:24 -0800322 def update_for_task(self, task_name):
323 # This label is stored in the state config, so only repair tasks update
324 # it or when no task name is mentioned.
325 return task_name in (REPAIR_TASK_NAME, '')
326
Kevin Chenga2619dc2016-03-28 11:42:08 -0700327
Kevin Chenga2619dc2016-03-28 11:42:08 -0700328class ServoLabel(base_label.BaseLabel):
Otabek Kasimov7267a7a2020-03-04 11:18:45 -0800329 # class will be removed as part of decommission the old servo label
330 # "not_connected" and "wrong_config" will be part of ServoHost
Otabek Kasimovcefc0d12020-02-07 17:13:52 -0800331 """
332 Label servo is applying if a servo is present.
333 Label servo_state present always.
334 """
Kevin Chenga2619dc2016-03-28 11:42:08 -0700335
Otabek Kasimovcefc0d12020-02-07 17:13:52 -0800336 _NAME_OLD = 'servo'
Garry Wang11b5e872020-03-11 15:14:08 -0700337 _NAME = servo_constants.SERVO_STATE_LABEL_PREFIX
Otabek Kasimovcefc0d12020-02-07 17:13:52 -0800338
339 def get(self, host):
Otabek Kasimov7267a7a2020-03-04 11:18:45 -0800340 state = self._get_state(host)
341 servo_state = self._NAME + ':' + state
Garry Wang11b5e872020-03-11 15:14:08 -0700342 if state == servo_constants.SERVO_STATE_NOT_CONNECTED:
Otabek Kasimov7267a7a2020-03-04 11:18:45 -0800343 return [servo_state]
344 return [self._NAME_OLD, servo_state]
Otabek Kasimovcefc0d12020-02-07 17:13:52 -0800345
346 def get_all_labels(self):
347 return set([self._NAME]), set([self._NAME_OLD])
Kevin Chenga2619dc2016-03-28 11:42:08 -0700348
349 def exists(self, host):
Otabek Kasimov7267a7a2020-03-04 11:18:45 -0800350 pass
Gregory Nisbet8b008f82019-08-20 13:06:19 -0700351
Otabek Kasimov7267a7a2020-03-04 11:18:45 -0800352 def _get_state(self, host):
353 # Based on crbug.com/995900, Servo sometimes flips.
354 # Ensure that labels has servo or servo_state label
355 # forever, after it returns state *once*.
356 state = self._cached_servo_state_status(host)
357 if state:
358 # If status exist we do not need to run anything
359 return state
360
361 # by last changes this point should not reached now
362 # only till not all DUTs have servo_state label
363 servo_label = self._cached_servo_label(host)
364 if servo_label:
Garry Wang11b5e872020-03-11 15:14:08 -0700365 return servo_constants.SERVO_STATE_WORKING
366 return servo_constants.SERVO_STATE_NOT_CONNECTED
Otabek Kasimov7267a7a2020-03-04 11:18:45 -0800367
368 def _cached_servo_state_status(self, host):
Gregory Nisbet8b008f82019-08-20 13:06:19 -0700369 """Get the state of Servo in the data store"""
370 info = host.host_info_store.get()
Otabek Kasimov7267a7a2020-03-04 11:18:45 -0800371 # First try to find targeted label
Gregory Nisbet8b008f82019-08-20 13:06:19 -0700372 for label in info.labels:
Otabek Kasimov7267a7a2020-03-04 11:18:45 -0800373 if label.startswith(self._NAME):
374 suffix_length = len(self._NAME) + 1
375 return label[suffix_length:]
376 return ''
377
378 def _cached_servo_label(self, host):
379 """Get the state of Servo in the data store"""
380 info = host.host_info_store.get()
381 # First try to find targeted label
382 for label in info.labels:
383 if label is not None and label.strip() == self._NAME_OLD:
Gregory Nisbet8b008f82019-08-20 13:06:19 -0700384 return True
385 return False
386
Eshwar Narayan871a2c02020-02-06 11:15:24 -0800387 def update_for_task(self, task_name):
388 # This label is stored in the state config, so only repair tasks update
389 # it or when no task name is mentioned.
390 return task_name in (REPAIR_TASK_NAME, '')
391
Kevin Chenga2619dc2016-03-28 11:42:08 -0700392
Otabek Kasimov43185912020-03-11 16:01:52 -0700393class ServoTypeLabel(base_label.StringPrefixLabel):
Otabek Kasimove7565282020-04-14 13:26:12 -0700394 _NAME = servo_constants.SERVO_TYPE_LABEL_PREFIX
Otabek Kasimov43185912020-03-11 16:01:52 -0700395
396 def generate_labels(self, host):
397 info = host.host_info_store.get()
398
399 servo_type = self._get_from_labels(info)
400 if servo_type != '':
Otabek Kasimov1b67c002020-04-15 13:27:38 -0700401 logging.info("Using servo_type: %s from cache!", servo_type)
Otabek Kasimov43185912020-03-11 16:01:52 -0700402 return [servo_type]
403
404 if host.servo is not None:
405 try:
406 servo_type = host.servo.get_servo_version()
407 if servo_type != '':
408 return [servo_type]
Otabek Kasimov1b67c002020-04-15 13:27:38 -0700409 logging.warning('Cannot collect servo_type from servo'
410 ' by `dut-control servo_type`! Please file a bug'
411 ' and inform infra team as we are not expected '
412 ' to reach this point.')
Otabek Kasimov43185912020-03-11 16:01:52 -0700413 except Exception as e:
414 # We don't want fail the label and break DUTs here just
415 # because of servo issue.
416 logging.error("Failed to update servo_type, %s", str(e))
417 return []
418
419 def _get_from_labels(self, info):
420 prefix = self._NAME + ':'
421 for label in info.labels:
422 if label.startswith(prefix):
423 suffix_length = len(prefix)
424 return label[suffix_length:]
425 return ''
426
427 def update_for_task(self, task_name):
428 # This label is stored in the lab config,
429 # only deploy and repair tasks update it
430 # or when no task name is mentioned.
431 # use REPAIR_TASK_NAME till restore value for all DUTs
432 return task_name in (REPAIR_TASK_NAME, DEPLOY_TASK_NAME, '')
433
434
Xixuan Wu78569d02019-09-15 16:08:25 -0700435def _parse_hwid_labels(hwid_info_list):
436 if len(hwid_info_list) == 0:
437 return hwid_info_list
438
439 res = []
440 # See crbug.com/997816#c7 for details of two potential formats of returns
441 # from HWID server.
442 if isinstance(hwid_info_list[0], dict):
443 # Format of hwid_info:
444 # [{u'name': u'sku', u'value': u'xxx'}, ..., ]
445 for hwid_info in hwid_info_list:
446 value = hwid_info.get('value', '')
447 name = hwid_info.get('name', '')
448 # There should always be a name but just in case there is not.
449 if name:
450 new_label = name if not value else '%s:%s' % (name, value)
451 res.append(new_label)
452 else:
453 # Format of hwid_info:
454 # [<DUTLabel name: 'sku' value: u'xxx'>, ..., ]
455 for hwid_info in hwid_info_list:
456 new_label = str(hwid_info)
457 logging.info('processing hwid label: %s', new_label)
458 res.append(new_label)
459
460 return res
461
462
Kevin Cheng80ad5732016-03-31 16:01:56 -0700463class HWIDLabel(base_label.StringLabel):
464 """Return all the labels generated from the hwid."""
465
466 # We leave out _NAME because hwid_lib will generate everything for us.
467
468 def __init__(self):
469 # Grab the key file needed to access the hwid service.
470 self.key_file = global_config.global_config.get_config_value(
471 'CROS', 'HWID_KEY', type=str)
472
473
Gregory Nisbetfb68a1f2019-08-22 10:27:33 -0700474 @staticmethod
475 def _merge_hwid_label_lists(new, old):
476 """merge a list of old and new values for hwid_labels.
477 preferring new values if available
478
479 @returns: list of labels"""
480 # TODO(gregorynisbet): what is the appropriate way to merge
481 # old and new information?
482 retained = set(x for x in old)
483 for label in new:
484 key, sep, value = label.partition(':')
485 # If we have a key-value key such as variant:aaa,
486 # then we remove all the old labels with the same key.
487 if sep:
488 retained = set(x for x in retained if (not x.startswith(key + ':')))
489 return list(sorted(retained.union(new)))
490
491
492 def _hwid_label_names(self):
493 """get the labels that hwid_lib controls.
494
495 @returns: hwid_labels
496 """
497 all_hwid_labels, _ = self.get_all_labels()
498 # If and only if get_all_labels was unsuccessful,
499 # it will return a falsey value.
Gregory Nisbetbfd120f2019-09-04 14:49:46 -0700500 out = all_hwid_labels or HWID_LABELS_FALLBACK
501
502 # TODO(gregorynisbet): remove this
503 # TODO(crbug.com/999785)
504 if "sku" not in out:
505 logging.info("sku-less label names %s", out)
506
507 return out
Gregory Nisbetfb68a1f2019-08-22 10:27:33 -0700508
509
510 def _old_label_values(self, host):
511 """get the hwid_lib labels on previous run
512
513 @returns: hwid_labels"""
514 out = []
515 info = host.host_info_store.get()
516 for hwid_label in self._hwid_label_names():
517 for label in info.labels:
518 # NOTE: we want *all* the labels starting
519 # with this prefix.
520 if label.startswith(hwid_label):
521 out.append(label)
522 return out
523
524
Kevin Cheng80ad5732016-03-31 16:01:56 -0700525 def generate_labels(self, host):
Gregory Nisbetfb68a1f2019-08-22 10:27:33 -0700526 # use previous values as default
527 old_hwid_labels = self._old_label_values(host)
Xixuan Wue63f8352019-09-13 15:18:03 -0700528 logging.info("old_hwid_labels: %r", old_hwid_labels)
Kevin Cheng80ad5732016-03-31 16:01:56 -0700529 hwid = host.run_output('crossystem hwid').strip()
Gregory Nisbetfb68a1f2019-08-22 10:27:33 -0700530 hwid_info_list = []
531 try:
532 hwid_info_response = hwid_lib.get_hwid_info(
533 hwid=hwid,
534 info_type=hwid_lib.HWID_INFO_LABEL,
535 key_file=self.key_file,
536 )
Xixuan Wue63f8352019-09-13 15:18:03 -0700537 logging.info("hwid_info_response: %r", hwid_info_response)
Gregory Nisbetfb68a1f2019-08-22 10:27:33 -0700538 hwid_info_list = hwid_info_response.get('labels', [])
539 except hwid_lib.HwIdException as e:
540 logging.info("HwIdException: %s", e)
Kevin Cheng80ad5732016-03-31 16:01:56 -0700541
Xixuan Wu78569d02019-09-15 16:08:25 -0700542 new_hwid_labels = _parse_hwid_labels(hwid_info_list)
543 logging.info("new HWID labels: %r", new_hwid_labels)
Gregory Nisbetbfd120f2019-09-04 14:49:46 -0700544
Gregory Nisbetfb68a1f2019-08-22 10:27:33 -0700545 return HWIDLabel._merge_hwid_label_lists(
546 old=old_hwid_labels,
Xixuan Wu78569d02019-09-15 16:08:25 -0700547 new=new_hwid_labels,
Gregory Nisbetfb68a1f2019-08-22 10:27:33 -0700548 )
Kevin Cheng80ad5732016-03-31 16:01:56 -0700549
550
551 def get_all_labels(self):
552 """We need to try all labels as a prefix and as standalone.
553
554 We don't know for sure which labels are prefix labels and which are
555 standalone so we try all of them as both.
556 """
557 all_hwid_labels = []
558 try:
559 all_hwid_labels = hwid_lib.get_all_possible_dut_labels(
560 self.key_file)
561 except IOError:
562 logging.error('Can not open key file: %s', self.key_file)
563 except hwid_lib.HwIdException as e:
564 logging.error('hwid service: %s', e)
565 return all_hwid_labels, all_hwid_labels
566
567
Kevin Chenga2619dc2016-03-28 11:42:08 -0700568CROS_LABELS = [
Eshwar Narayanf46904c2020-02-11 17:57:31 -0800569 AudioLoopbackDongleLabel(), #STATECONFIG
Shijin Abraham76bc1db2020-03-06 10:52:10 -0800570 BluetoothPeerLabel(), #STATECONFIG
Eshwar Narayanf46904c2020-02-11 17:57:31 -0800571 ChameleonConnectionLabel(), #LABCONFIG
572 ChameleonLabel(), #STATECONFIG
573 ChameleonPeripheralsLabel(), #LABCONFIG
Kevin Chenga2619dc2016-03-28 11:42:08 -0700574 common_label.OSLabel(),
Eshwar Narayanf46904c2020-02-11 17:57:31 -0800575 DeviceSkuLabel(), #LABCONFIG
Kevin Cheng80ad5732016-03-31 16:01:56 -0700576 HWIDLabel(),
Eshwar Narayanf46904c2020-02-11 17:57:31 -0800577 ServoLabel(), #STATECONFIG
Otabek Kasimov43185912020-03-11 16:01:52 -0700578 ServoTypeLabel(), #LABCONFIG
Xixuan Wu457b4ac2020-03-02 14:39:08 -0800579 # Temporarily add back as there's no way to reference cr50 configs.
580 # See crbug.com/1057145 for the root cause.
581 # See crbug.com/1057719 for future tracking.
582 Cr50Label(),
583 Cr50ROKeyidLabel(),
Kevin Chenga2619dc2016-03-28 11:42:08 -0700584]
Garry Wange4b6d6e2019-06-17 17:08:46 -0700585
586LABSTATION_LABELS = [
Garry Wange4b6d6e2019-06-17 17:08:46 -0700587 common_label.OSLabel(),
588]