Kevin Cheng | 5272ca7 | 2016-01-11 11:55:31 -0800 | [diff] [blame] | 1 | # 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 | import json |
Xixuan Wu | 2ddf1b6 | 2019-11-18 10:45:17 -0800 | [diff] [blame] | 6 | import logging |
Kevin Cheng | 5272ca7 | 2016-01-11 11:55:31 -0800 | [diff] [blame] | 7 | import urllib2 |
| 8 | |
Xixuan Wu | 2ddf1b6 | 2019-11-18 10:45:17 -0800 | [diff] [blame] | 9 | from autotest_lib.client.common_lib import global_config |
| 10 | |
Kevin Cheng | 5272ca7 | 2016-01-11 11:55:31 -0800 | [diff] [blame] | 11 | # HWID info types to request. |
| 12 | HWID_INFO_LABEL = 'dutlabel' |
| 13 | HWID_INFO_BOM = 'bom' |
| 14 | HWID_INFO_SKU = 'sku' |
| 15 | HWID_INFO_TYPES = [HWID_INFO_BOM, HWID_INFO_SKU, HWID_INFO_LABEL] |
| 16 | |
| 17 | # HWID url vars. |
| 18 | HWID_VERSION = 'v1' |
| 19 | HWID_BASE_URL = 'https://www.googleapis.com/chromeoshwid' |
Clark Chung | 690c37e | 2019-11-20 11:31:08 +0800 | [diff] [blame] | 20 | CHROMEOS_HWID_SERVER_URL = "https://chromeos-hwid.appspot.com/api/chromeoshwid" |
Kevin Cheng | 5272ca7 | 2016-01-11 11:55:31 -0800 | [diff] [blame] | 21 | URL_FORMAT_STRING='%(base_url)s/%(version)s/%(info_type)s/%(hwid)s/?key=%(key)s' |
| 22 | |
Kevin Cheng | 80ad573 | 2016-03-31 16:01:56 -0700 | [diff] [blame] | 23 | # Key file name to use when we don't want hwid labels. |
| 24 | KEY_FILENAME_NO_HWID = 'no_hwid_labels' |
Kevin Cheng | 5272ca7 | 2016-01-11 11:55:31 -0800 | [diff] [blame] | 25 | |
| 26 | class HwIdException(Exception): |
| 27 | """Raised whenever anything fails in the hwid info request.""" |
| 28 | |
| 29 | |
| 30 | def 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 Cheng | 80ad573 | 2016-03-31 16:01:56 -0700 | [diff] [blame] | 43 | # 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 Cheng | 5272ca7 | 2016-01-11 11:55:31 -0800 | [diff] [blame] | 48 | 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 Wu | 2ddf1b6 | 2019-11-18 10:45:17 -0800 | [diff] [blame] | 54 | 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 Cheng | 5272ca7 | 2016-01-11 11:55:31 -0800 | [diff] [blame] | 60 | 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 Cheng | 80ad573 | 2016-03-31 16:01:56 -0700 | [diff] [blame] | 67 | 'hwid': urllib2.quote(hwid), |
Kevin Cheng | 5272ca7 | 2016-01-11 11:55:31 -0800 | [diff] [blame] | 68 | 'key': key} |
Xixuan Wu | 2ddf1b6 | 2019-11-18 10:45:17 -0800 | [diff] [blame] | 69 | return _fetch_hwid_response(url_format_dict) |
Kevin Cheng | 80ad573 | 2016-03-31 16:01:56 -0700 | [diff] [blame] | 70 | |
| 71 | |
| 72 | def 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 Wu | 2ddf1b6 | 2019-11-18 10:45:17 -0800 | [diff] [blame] | 86 | |
| 87 | |
| 88 | def _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 | |
| 121 | def _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 Chung | 690c37e | 2019-11-20 11:31:08 +0800 | [diff] [blame] | 143 | return hwid_info_dict |