blob: 22533352fddee29ae0e9227b46e53fd51eb86d48 [file] [log] [blame]
Kevin Cheng5272ca72016-01-11 11:55:31 -08001# 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
5import json
Xixuan Wu2ddf1b62019-11-18 10:45:17 -08006import logging
Kevin Cheng5272ca72016-01-11 11:55:31 -08007import urllib2
8
Xixuan Wu2ddf1b62019-11-18 10:45:17 -08009from autotest_lib.client.common_lib import global_config
10
Kevin Cheng5272ca72016-01-11 11:55:31 -080011# HWID info types to request.
12HWID_INFO_LABEL = 'dutlabel'
13HWID_INFO_BOM = 'bom'
14HWID_INFO_SKU = 'sku'
15HWID_INFO_TYPES = [HWID_INFO_BOM, HWID_INFO_SKU, HWID_INFO_LABEL]
16
17# HWID url vars.
18HWID_VERSION = 'v1'
19HWID_BASE_URL = 'https://www.googleapis.com/chromeoshwid'
Clark Chung690c37e2019-11-20 11:31:08 +080020CHROMEOS_HWID_SERVER_URL = "https://chromeos-hwid.appspot.com/api/chromeoshwid"
Kevin Cheng5272ca72016-01-11 11:55:31 -080021URL_FORMAT_STRING='%(base_url)s/%(version)s/%(info_type)s/%(hwid)s/?key=%(key)s'
22
Kevin Cheng80ad5732016-03-31 16:01:56 -070023# Key file name to use when we don't want hwid labels.
24KEY_FILENAME_NO_HWID = 'no_hwid_labels'
Kevin Cheng5272ca72016-01-11 11:55:31 -080025
26class HwIdException(Exception):
27 """Raised whenever anything fails in the hwid info request."""
28
29
30def get_hwid_info(hwid, info_type, key_file):
31 """Given a hwid and info type, return a dict of the requested info.
32
33 @param hwid: hwid to use for the query.
34 @param info_type: String of info type requested.
35 @param key_file: Filename that holds the key for authentication.
36
37 @return: A dict of the info.
38
39 @raises HwIdException: If hwid/info_type/key_file is invalid or there's an
40 error anywhere related to getting the raw hwid info
41 or decoding it.
42 """
Kevin Cheng80ad5732016-03-31 16:01:56 -070043 # There are situations we don't want to call out to the hwid service, we use
44 # the key_file name as the indicator for that.
45 if key_file == KEY_FILENAME_NO_HWID:
46 return {}
47
Kevin Cheng5272ca72016-01-11 11:55:31 -080048 if not isinstance(hwid, str):
49 raise ValueError('hwid is not a string.')
50
51 if info_type not in HWID_INFO_TYPES:
52 raise ValueError('invalid info type: "%s".' % info_type)
53
Xixuan Wu2ddf1b62019-11-18 10:45:17 -080054 hwid_info_dict = _try_hwid_v1(hwid, info_type)
55 if hwid_info_dict is not None:
56 return hwid_info_dict
57 else:
58 logging.debug("Switch back to use old endpoint")
59
Kevin Cheng5272ca72016-01-11 11:55:31 -080060 key = None
61 with open(key_file) as f:
62 key = f.read().strip()
63
64 url_format_dict = {'base_url': HWID_BASE_URL,
65 'version': HWID_VERSION,
66 'info_type': info_type,
Kevin Cheng80ad5732016-03-31 16:01:56 -070067 'hwid': urllib2.quote(hwid),
Kevin Cheng5272ca72016-01-11 11:55:31 -080068 'key': key}
Xixuan Wu2ddf1b62019-11-18 10:45:17 -080069 return _fetch_hwid_response(url_format_dict)
Kevin Cheng80ad5732016-03-31 16:01:56 -070070
71
72def get_all_possible_dut_labels(key_file):
73 """Return all possible labels that can be supplied by dutlabels.
74
75 We can send a dummy key to the service to retrieve all the possible
76 labels the service will provide under the dutlabel api call. We need
77 this in order to track which labels we can remove if they're not detected
78 on a dut anymore.
79
80 @param key_file: Filename that holds the key for authentication.
81
82 @return: A list of all possible labels.
83 """
84 return get_hwid_info('dummy_hwid', HWID_INFO_LABEL, key_file).get(
85 'possible_labels', [])
Xixuan Wu2ddf1b62019-11-18 10:45:17 -080086
87
88def _try_hwid_v1(hwid, info_type):
89 """Try chromeos-hwid endpoints for fetching hwid info.
90
91 @param hwid: a string hardware ID.
92 @param info_type: String of info type requested.
93
94 @return a dict of hwid info.
95 """
96 key_file_path = global_config.global_config.get_config_value(
97 'CROS', 'NEW_HWID_KEY', type=str, default="")
98 if key_file_path == "":
99 return None
100
101 key = None
102 with open(key_file_path) as f:
103 key = f.read().strip()
104
105 if key is None:
106 return None
107
108 url_format_dict = {'base_url': CHROMEOS_HWID_SERVER_URL,
109 'version': HWID_VERSION,
110 'info_type': info_type,
111 'hwid': urllib2.quote(hwid),
112 'key': key}
113
114 try:
115 return _fetch_hwid_response(url_format_dict)
116 except Exception as e:
117 logging.debug("fail to call new HWID endpoint: %s", str(e))
118 return None
119
120
121def _fetch_hwid_response(req_parameter_dict):
122 """Fetch and parse hwid response.
123
124 @param req_parameter_dict: A dict of url parameters.
125
126 @return a dict of hwid info.
127 """
128 url_request = URL_FORMAT_STRING % req_parameter_dict
129 try:
130 page_contents = urllib2.urlopen(url_request)
131 except (urllib2.URLError, urllib2.HTTPError) as e:
132 # TODO(kevcheng): Might need to scrub out key from exception message.
133 raise HwIdException('error retrieving raw hwid info: %s' % e)
134
135 try:
136 hwid_info_dict = json.load(page_contents)
137 except ValueError as e:
138 raise HwIdException('error decoding hwid info: %s - "%s"' %
139 (e, page_contents.getvalue()))
140 finally:
141 page_contents.close()
142
Clark Chung690c37e2019-11-20 11:31:08 +0800143 return hwid_info_dict