site_utils.py revision 0c1a37dd9b1237fe8d43c7f911ce601104806339
1a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi# Copyright (c) 2013 The Chromium Authors. All rights reserved. 2a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi# Use of this source code is governed by a BSD-style license that can be 3a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi# found in the LICENSE file. 4a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 5dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller 63cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnetteimport httplib 73cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnetteimport json 8a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shiimport logging 935d661e09666d315325f8942d06949ca7283666fMK Ryuimport os 10023afc65f9377db51ff6122977a9f529a32422d3beepsimport random 11dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Millerimport re 123cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnetteimport time 13bef578d9163c6574d626e8b98298c59a5ab79221Paul Drewsimport urllib2 14a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 153cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnetteimport common 16023afc65f9377db51ff6122977a9f529a32422d3beepsfrom autotest_lib.client.common_lib import base_utils 17023afc65f9377db51ff6122977a9f529a32422d3beepsfrom autotest_lib.client.common_lib import error 18023afc65f9377db51ff6122977a9f529a32422d3beepsfrom autotest_lib.client.common_lib import global_config 190c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryufrom autotest_lib.client.common_lib import host_queue_entry_states 20a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shifrom autotest_lib.server.cros.dynamic_suite import constants 217e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shifrom autotest_lib.server.cros.dynamic_suite import job_status 22a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 23a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 24dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller_SHERIFF_JS = global_config.global_config.get_config_value( 25dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller 'NOTIFICATIONS', 'sheriffs', default='') 263197b39f82eb92afff33c7d44b805afe120c7627Fang Deng_LAB_SHERIFF_JS = global_config.global_config.get_config_value( 273197b39f82eb92afff33c7d44b805afe120c7627Fang Deng 'NOTIFICATIONS', 'lab_sheriffs', default='') 28dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller_CHROMIUM_BUILD_URL = global_config.global_config.get_config_value( 29dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller 'NOTIFICATIONS', 'chromium_build_url', default='') 30dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller 313cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard BarnetteLAB_GOOD_STATES = ('open', 'throttled') 323cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 333cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 34abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnetteclass TestLabException(Exception): 35abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette """Exception raised when the Test Lab blocks a test or suite.""" 363cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette pass 373cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 383cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 393cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnetteclass ParseBuildNameException(Exception): 403cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette """Raised when ParseBuildName() cannot parse a build name.""" 413cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette pass 423cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 433cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 443cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnettedef ParseBuildName(name): 453cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette """Format a build name, given board, type, milestone, and manifest num. 463cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 47b7d2116ad62dd09c52791c8f27dfa61b9df186b9Simran Basi @param name: a build name, e.g. 'x86-alex-release/R20-2015.0.0' or a 48b7d2116ad62dd09c52791c8f27dfa61b9df186b9Simran Basi relative build name, e.g. 'x86-alex-release/LATEST' 493cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 503cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette @return board: board the manifest is for, e.g. x86-alex. 513cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette @return type: one of 'release', 'factory', or 'firmware' 523cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette @return milestone: (numeric) milestone the manifest was associated with. 53b7d2116ad62dd09c52791c8f27dfa61b9df186b9Simran Basi Will be None for relative build names. 54b7d2116ad62dd09c52791c8f27dfa61b9df186b9Simran Basi @return manifest: manifest number, e.g. '2015.0.0'. 55b7d2116ad62dd09c52791c8f27dfa61b9df186b9Simran Basi Will be None for relative build names. 563cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 573cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette """ 58f8f648e049ca2f8777fa55c0ea9c4f886efecea9Simran Basi match = re.match(r'(trybot-)?(?P<board>[\w-]+)-(?P<type>\w+)/' 59f8f648e049ca2f8777fa55c0ea9c4f886efecea9Simran Basi r'(R(?P<milestone>\d+)-(?P<manifest>[\d.ab-]+)|LATEST)', 60f8f648e049ca2f8777fa55c0ea9c4f886efecea9Simran Basi name) 61f8f648e049ca2f8777fa55c0ea9c4f886efecea9Simran Basi if match and len(match.groups()) >= 5: 62b7d2116ad62dd09c52791c8f27dfa61b9df186b9Simran Basi return (match.group('board'), match.group('type'), 63b7d2116ad62dd09c52791c8f27dfa61b9df186b9Simran Basi match.group('milestone'), match.group('manifest')) 643cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette raise ParseBuildNameException('%s is a malformed build name.' % name) 653cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 66dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller 67a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shidef get_label_from_afe(hostname, label_prefix, afe): 68a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi """Retrieve a host's specific label from the AFE. 69a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 70a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi Looks for a host label that has the form <label_prefix>:<value> 71a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi and returns the "<value>" part of the label. None is returned 72a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi if there is not a label matching the pattern 73a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 74a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi @param hostname: hostname of given DUT. 75a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi @param label_prefix: prefix of label to be matched, e.g., |board:| 76a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi @param afe: afe instance. 77a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi @returns the label that matches the prefix or 'None' 78a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 79a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi """ 80a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi labels = afe.get_labels(name__startswith=label_prefix, 81a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi host__hostname__in=[hostname]) 82a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi if labels and len(labels) == 1: 83a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi return labels[0].name.split(label_prefix, 1)[1] 84a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 85a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 86a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shidef get_board_from_afe(hostname, afe): 87a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi """Retrieve given host's board from its labels in the AFE. 88a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 89a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi Looks for a host label of the form "board:<board>", and 90a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi returns the "<board>" part of the label. `None` is returned 91a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi if there is not a single, unique label matching the pattern. 92a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 93a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi @param hostname: hostname of given DUT. 94a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi @param afe: afe instance. 95a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi @returns board from label, or `None`. 96a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 97a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi """ 98a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi return get_label_from_afe(hostname, constants.BOARD_PREFIX, afe) 99a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 100a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 101a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shidef get_build_from_afe(hostname, afe): 102a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi """Retrieve the current build for given host from the AFE. 103a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 104a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi Looks through the host's labels in the AFE to determine its build. 105a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 106a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi @param hostname: hostname of given DUT. 107a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi @param afe: afe instance. 108a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi @returns The current build or None if it could not find it or if there 109a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi were multiple build labels assigned to this host. 110a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 111a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi """ 112a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi return get_label_from_afe(hostname, constants.VERSION_PREFIX, afe) 113a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 114a1ecd5c903928f359cd6cbcff5c986652e109599Dan Shi 1153197b39f82eb92afff33c7d44b805afe120c7627Fang Dengdef get_sheriffs(lab_only=False): 116dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller """ 117dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller Polls the javascript file that holds the identity of the sheriff and 118dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller parses it's output to return a list of chromium sheriff email addresses. 119dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller The javascript file can contain the ldap of more than one sheriff, eg: 120dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller document.write('sheriff_one, sheriff_two'). 121dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller 1223197b39f82eb92afff33c7d44b805afe120c7627Fang Deng @param lab_only: if True, only pulls lab sheriff. 1233197b39f82eb92afff33c7d44b805afe120c7627Fang Deng @return: A list of chroium.org sheriff email addresses to cc on the bug. 1243197b39f82eb92afff33c7d44b805afe120c7627Fang Deng An empty list if failed to parse the javascript. 125dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller """ 126dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller sheriff_ids = [] 1273197b39f82eb92afff33c7d44b805afe120c7627Fang Deng sheriff_js_list = _LAB_SHERIFF_JS.split(',') 1283197b39f82eb92afff33c7d44b805afe120c7627Fang Deng if not lab_only: 1293197b39f82eb92afff33c7d44b805afe120c7627Fang Deng sheriff_js_list.extend(_SHERIFF_JS.split(',')) 1303197b39f82eb92afff33c7d44b805afe120c7627Fang Deng 1313197b39f82eb92afff33c7d44b805afe120c7627Fang Deng for sheriff_js in sheriff_js_list: 132dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller try: 133dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller url_content = base_utils.urlopen('%s%s'% ( 134dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller _CHROMIUM_BUILD_URL, sheriff_js)).read() 135dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller except (ValueError, IOError) as e: 1364efdf03d1057f9d38e043b7c2affe842109805d2beeps logging.warning('could not parse sheriff from url %s%s: %s', 1374efdf03d1057f9d38e043b7c2affe842109805d2beeps _CHROMIUM_BUILD_URL, sheriff_js, str(e)) 138bef578d9163c6574d626e8b98298c59a5ab79221Paul Drews except (urllib2.URLError, httplib.HTTPException) as e: 139bef578d9163c6574d626e8b98298c59a5ab79221Paul Drews logging.warning('unexpected error reading from url "%s%s": %s', 140bef578d9163c6574d626e8b98298c59a5ab79221Paul Drews _CHROMIUM_BUILD_URL, sheriff_js, str(e)) 141dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller else: 142dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller ldaps = re.search(r"document.write\('(.*)'\)", url_content) 143dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller if not ldaps: 1444efdf03d1057f9d38e043b7c2affe842109805d2beeps logging.warning('Could not retrieve sheriff ldaps for: %s', 1454efdf03d1057f9d38e043b7c2affe842109805d2beeps url_content) 146dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller continue 147dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller sheriff_ids += ['%s@chromium.org' % alias.replace(' ', '') 148dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller for alias in ldaps.group(1).split(',')] 149dadc2c21c0b0b904067ea6400e179a187c0247d4Alex Miller return sheriff_ids 15046dadc9439355f72d394dcc4700902001bd797ffbeeps 15146dadc9439355f72d394dcc4700902001bd797ffbeeps 15246dadc9439355f72d394dcc4700902001bd797ffbeepsdef remote_wget(source_url, dest_path, ssh_cmd): 15346dadc9439355f72d394dcc4700902001bd797ffbeeps """wget source_url from localhost to dest_path on remote host using ssh. 15446dadc9439355f72d394dcc4700902001bd797ffbeeps 15546dadc9439355f72d394dcc4700902001bd797ffbeeps @param source_url: The complete url of the source of the package to send. 15646dadc9439355f72d394dcc4700902001bd797ffbeeps @param dest_path: The path on the remote host's file system where we would 15746dadc9439355f72d394dcc4700902001bd797ffbeeps like to store the package. 15846dadc9439355f72d394dcc4700902001bd797ffbeeps @param ssh_cmd: The ssh command to use in performing the remote wget. 15946dadc9439355f72d394dcc4700902001bd797ffbeeps """ 16046dadc9439355f72d394dcc4700902001bd797ffbeeps wget_cmd = ("wget -O - %s | %s 'cat >%s'" % 16146dadc9439355f72d394dcc4700902001bd797ffbeeps (source_url, ssh_cmd, dest_path)) 16246dadc9439355f72d394dcc4700902001bd797ffbeeps base_utils.run(wget_cmd) 16346dadc9439355f72d394dcc4700902001bd797ffbeeps 1643cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 165266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette_MAX_LAB_STATUS_ATTEMPTS = 5 166266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnettedef _get_lab_status(status_url): 1673cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette """Grabs the current lab status and message. 1683cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 169266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette @returns The JSON object obtained from the given URL. 170266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette 1713cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette """ 1723cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette retry_waittime = 1 173266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette for _ in range(_MAX_LAB_STATUS_ATTEMPTS): 1743cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette try: 1753cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette response = urllib2.urlopen(status_url) 1763cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette except IOError as e: 177266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette logging.debug('Error occurred when grabbing the lab status: %s.', 1783cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette e) 1793cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette time.sleep(retry_waittime) 1803cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette continue 1813cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette # Check for successful response code. 1823cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette if response.getcode() == 200: 183266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette return json.load(response) 1843cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette time.sleep(retry_waittime) 185266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette return None 1863cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 1873cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 188abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnettedef _decode_lab_status(lab_status, build): 189266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette """Decode lab status, and report exceptions as needed. 1903cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 191abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette Take a deserialized JSON object from the lab status page, and 192abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette interpret it to determine the actual lab status. Raise 193266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette exceptions as required to report when the lab is down. 1943cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 195abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette @param build: build name that we want to check the status of. 1963cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 197abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette @raises TestLabException Raised if a request to test for the given 198abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette status and build should be blocked. 1993cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette """ 2003cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette # First check if the lab is up. 201266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette if not lab_status['general_state'] in LAB_GOOD_STATES: 202abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette raise TestLabException('Chromium OS Test Lab is closed: ' 203abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette '%s.' % lab_status['message']) 2043cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette 205abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette # Check if the build we wish to use is disabled. 2063cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette # Lab messages should be in the format of: 207abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette # Lab is 'status' [regex ...] (comment) 208abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette # If the build name matches any regex, it will be blocked. 209abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette build_exceptions = re.search('\[(.*)\]', lab_status['message']) 210ae43721d4a11c6ecd2d502bba73b185b05bfce29Prashanth Balasubramanian if not build_exceptions or not build: 211abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette return 212abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette for build_pattern in build_exceptions.group(1).split(): 213abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette if re.search(build_pattern, build): 214abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette raise TestLabException('Chromium OS Test Lab is closed: ' 215abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette '%s matches %s.' % ( 216abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette build, build_pattern)) 2173cbd76b06c383d8bc3e4ba959659a0bd04180761J. Richard Barnette return 218266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette 219266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette 22094234cb747dc067b159789a4b63f21b23d706922Dan Shidef is_in_lab(): 22194234cb747dc067b159789a4b63f21b23d706922Dan Shi """Check if current Autotest instance is in lab 22294234cb747dc067b159789a4b63f21b23d706922Dan Shi 22394234cb747dc067b159789a4b63f21b23d706922Dan Shi @return: True if the Autotest instance is in lab. 22494234cb747dc067b159789a4b63f21b23d706922Dan Shi """ 22594234cb747dc067b159789a4b63f21b23d706922Dan Shi test_server_name = global_config.global_config.get_config_value( 22694234cb747dc067b159789a4b63f21b23d706922Dan Shi 'SERVER', 'hostname') 22794234cb747dc067b159789a4b63f21b23d706922Dan Shi return test_server_name.startswith('cautotest') 22894234cb747dc067b159789a4b63f21b23d706922Dan Shi 22994234cb747dc067b159789a4b63f21b23d706922Dan Shi 230abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnettedef check_lab_status(build): 231abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette """Check if the lab status allows us to schedule for a build. 232266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette 233abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette Checks if the lab is down, or if testing for the requested build 234abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette should be blocked. 235266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette 236abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette @param build: Name of the build to be scheduled for testing. 237266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette 238abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette @raises TestLabException Raised if a request to test for the given 239abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette status and build should be blocked. 240266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette 241266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette """ 242266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette # Ensure we are trying to schedule on the actual lab. 24394234cb747dc067b159789a4b63f21b23d706922Dan Shi if not is_in_lab(): 244266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette return 245266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette 246266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette # Download the lab status from its home on the web. 247266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette status_url = global_config.global_config.get_config_value( 248266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette 'CROS', 'lab_status_url') 249266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette json_status = _get_lab_status(status_url) 250266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette if json_status is None: 251266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette # We go ahead and say the lab is open if we can't get the status. 25204be2bd5e4666a5c253e9c30ab20555e04286032Ilja H. Friedel logging.warning('Could not get a status from %s', status_url) 253266da2a226391a7153df264d54dcb54635df7bfcJ. Richard Barnette return 254abbe09600d73d77af92157027a20661c035be01eJ. Richard Barnette _decode_lab_status(json_status, build) 255023afc65f9377db51ff6122977a9f529a32422d3beeps 256023afc65f9377db51ff6122977a9f529a32422d3beeps 257023afc65f9377db51ff6122977a9f529a32422d3beepsdef lock_host_with_labels(afe, lock_manager, labels): 258023afc65f9377db51ff6122977a9f529a32422d3beeps """Lookup and lock one host that matches the list of input labels. 259023afc65f9377db51ff6122977a9f529a32422d3beeps 260023afc65f9377db51ff6122977a9f529a32422d3beeps @param afe: An instance of the afe class, as defined in server.frontend. 261023afc65f9377db51ff6122977a9f529a32422d3beeps @param lock_manager: A lock manager capable of locking hosts, eg the 262023afc65f9377db51ff6122977a9f529a32422d3beeps one defined in server.cros.host_lock_manager. 263023afc65f9377db51ff6122977a9f529a32422d3beeps @param labels: A list of labels to look for on hosts. 264023afc65f9377db51ff6122977a9f529a32422d3beeps 265023afc65f9377db51ff6122977a9f529a32422d3beeps @return: The hostname of a host matching all labels, and locked through the 266023afc65f9377db51ff6122977a9f529a32422d3beeps lock_manager. The hostname will be as specified in the database the afe 267023afc65f9377db51ff6122977a9f529a32422d3beeps object is associated with, i.e if it exists in afe_hosts with a .cros 268023afc65f9377db51ff6122977a9f529a32422d3beeps suffix, the hostname returned will contain a .cros suffix. 269023afc65f9377db51ff6122977a9f529a32422d3beeps 270023afc65f9377db51ff6122977a9f529a32422d3beeps @raises: error.NoEligibleHostException: If no hosts matching the list of 271023afc65f9377db51ff6122977a9f529a32422d3beeps input labels are available. 272023afc65f9377db51ff6122977a9f529a32422d3beeps @raises: error.TestError: If unable to lock a host matching the labels. 273023afc65f9377db51ff6122977a9f529a32422d3beeps """ 274023afc65f9377db51ff6122977a9f529a32422d3beeps potential_hosts = afe.get_hosts(multiple_labels=labels) 275023afc65f9377db51ff6122977a9f529a32422d3beeps if not potential_hosts: 276023afc65f9377db51ff6122977a9f529a32422d3beeps raise error.NoEligibleHostException( 277023afc65f9377db51ff6122977a9f529a32422d3beeps 'No devices found with labels %s.' % labels) 278023afc65f9377db51ff6122977a9f529a32422d3beeps 279023afc65f9377db51ff6122977a9f529a32422d3beeps # This prevents errors where a fault might seem repeatable 280023afc65f9377db51ff6122977a9f529a32422d3beeps # because we lock, say, the same packet capturer for each test run. 281023afc65f9377db51ff6122977a9f529a32422d3beeps random.shuffle(potential_hosts) 282023afc65f9377db51ff6122977a9f529a32422d3beeps for host in potential_hosts: 283023afc65f9377db51ff6122977a9f529a32422d3beeps if lock_manager.lock([host.hostname]): 284023afc65f9377db51ff6122977a9f529a32422d3beeps logging.info('Locked device %s with labels %s.', 285023afc65f9377db51ff6122977a9f529a32422d3beeps host.hostname, labels) 286023afc65f9377db51ff6122977a9f529a32422d3beeps return host.hostname 287023afc65f9377db51ff6122977a9f529a32422d3beeps else: 288023afc65f9377db51ff6122977a9f529a32422d3beeps logging.info('Unable to lock device %s with labels %s.', 289023afc65f9377db51ff6122977a9f529a32422d3beeps host.hostname, labels) 290023afc65f9377db51ff6122977a9f529a32422d3beeps 291023afc65f9377db51ff6122977a9f529a32422d3beeps raise error.TestError('Could not lock a device with labels %s' % labels) 2927e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi 2937e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi 2947e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shidef get_test_views_from_tko(suite_job_id, tko): 2957e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi """Get test name and result for given suite job ID. 2967e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi 2977e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi @param suite_job_id: ID of suite job. 2987e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi @param tko: an instance of TKO as defined in server/frontend.py. 2997e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi @return: A dictionary of test status keyed by test name, e.g., 3007e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi {'dummy_Fail.Error': 'ERROR', 'dummy_Fail.NAError': 'TEST_NA'} 3017e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi @raise: Exception when there is no test view found. 3027e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi 3037e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi """ 3047e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi views = tko.run('get_detailed_test_views', afe_job_id=suite_job_id) 3057e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi relevant_views = filter(job_status.view_is_relevant, views) 3067e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi if not relevant_views: 3077e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi raise Exception('Failed to retrieve job results.') 3087e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi 3097e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi test_views = {} 3107e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi for view in relevant_views: 3117e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi test_views[view['test_name']] = view['status'] 3127e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi 3137e04fa8cf1f07512f52870cf4bffd9f8b0801088Dan Shi return test_views 31435d661e09666d315325f8942d06949ca7283666fMK Ryu 31535d661e09666d315325f8942d06949ca7283666fMK Ryu 31635d661e09666d315325f8942d06949ca7283666fMK Ryudef parse_simple_config(config_file): 31735d661e09666d315325f8942d06949ca7283666fMK Ryu """Get paths by parsing a simple config file. 31835d661e09666d315325f8942d06949ca7283666fMK Ryu 31935d661e09666d315325f8942d06949ca7283666fMK Ryu Each line of the config file is a path for a file or directory. 32035d661e09666d315325f8942d06949ca7283666fMK Ryu Ignore an empty line and a line starting with a hash character ('#'). 32135d661e09666d315325f8942d06949ca7283666fMK Ryu One example of this kind of simple config file is 32235d661e09666d315325f8942d06949ca7283666fMK Ryu client/common_lib/logs_to_collect. 32335d661e09666d315325f8942d06949ca7283666fMK Ryu 32435d661e09666d315325f8942d06949ca7283666fMK Ryu @param config_file: Config file path 32535d661e09666d315325f8942d06949ca7283666fMK Ryu @return: A list of directory strings 32635d661e09666d315325f8942d06949ca7283666fMK Ryu """ 32735d661e09666d315325f8942d06949ca7283666fMK Ryu dirs = [] 32835d661e09666d315325f8942d06949ca7283666fMK Ryu for l in open(config_file): 32935d661e09666d315325f8942d06949ca7283666fMK Ryu l = l.strip() 33035d661e09666d315325f8942d06949ca7283666fMK Ryu if l and not l.startswith('#'): 33135d661e09666d315325f8942d06949ca7283666fMK Ryu dirs.append(l) 33235d661e09666d315325f8942d06949ca7283666fMK Ryu return dirs 33335d661e09666d315325f8942d06949ca7283666fMK Ryu 33435d661e09666d315325f8942d06949ca7283666fMK Ryu 33535d661e09666d315325f8942d06949ca7283666fMK Ryudef concat_path_except_last(base, sub): 33635d661e09666d315325f8942d06949ca7283666fMK Ryu """Concatenate two paths but exclude last entry. 33735d661e09666d315325f8942d06949ca7283666fMK Ryu 33835d661e09666d315325f8942d06949ca7283666fMK Ryu Take two paths as parameters and return a path string in which 33935d661e09666d315325f8942d06949ca7283666fMK Ryu the second path becomes under the first path. 34035d661e09666d315325f8942d06949ca7283666fMK Ryu In addition, remove the last path entry from the concatenated path. 34135d661e09666d315325f8942d06949ca7283666fMK Ryu This works even when two paths are absolute paths. 34235d661e09666d315325f8942d06949ca7283666fMK Ryu 34335d661e09666d315325f8942d06949ca7283666fMK Ryu e.g., /usr/local/autotest/results/ + /var/log/ = 34435d661e09666d315325f8942d06949ca7283666fMK Ryu /usr/local/autotest/results/var 34535d661e09666d315325f8942d06949ca7283666fMK Ryu 34635d661e09666d315325f8942d06949ca7283666fMK Ryu e.g., /usr/local/autotest/results/ + /var/log/syslog = 34735d661e09666d315325f8942d06949ca7283666fMK Ryu /usr/local/autotest/results/var/log 34835d661e09666d315325f8942d06949ca7283666fMK Ryu 34935d661e09666d315325f8942d06949ca7283666fMK Ryu @param base: Beginning path 35035d661e09666d315325f8942d06949ca7283666fMK Ryu @param sub: The path that is concatenated to base 35135d661e09666d315325f8942d06949ca7283666fMK Ryu @return: Concatenated path string 35235d661e09666d315325f8942d06949ca7283666fMK Ryu """ 35335d661e09666d315325f8942d06949ca7283666fMK Ryu dirname = os.path.dirname(sub.rstrip('/')) 35435d661e09666d315325f8942d06949ca7283666fMK Ryu return os.path.join(base, dirname.strip('/')) 355c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 356c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 357c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryudef get_data_key(prefix, suite, build, board): 358c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu """ 359c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu Constructs a key string from parameters. 360c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 361c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu @param prefix: Prefix for the generating key. 362c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu @param suite: a suite name. e.g., bvt-cq, bvt-inline, dummy 363c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu @param build: The build string. This string should have a consistent 364c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu format eg: x86-mario-release/R26-3570.0.0. If the format of this 365c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu string changes such that we can't determine build_type or branch 366c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu we give up and use the parametes we're sure of instead (suite, 367c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu board). eg: 368c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 1. build = x86-alex-pgo-release/R26-3570.0.0 369c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu branch = 26 370c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu build_type = pgo-release 371c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 2. build = lumpy-paladin/R28-3993.0.0-rc5 372c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu branch = 28 373c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu build_type = paladin 374c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu @param board: The board that this suite ran on. 375c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu @return: The key string used for a dictionary. 376c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu """ 377c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu try: 378c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu _board, build_type, branch = ParseBuildName(build)[:3] 379c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu except ParseBuildNameException as e: 380c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu logging.error(str(e)) 381c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu branch = 'Unknown' 382c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu build_type = 'Unknown' 383c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu else: 384c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu embedded_str = re.search(r'x86-\w+-(.*)', _board) 385c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu if embedded_str: 386c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu build_type = embedded_str.group(1) + '-' + build_type 387c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 388c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu data_key_dict = { 389c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 'prefix': prefix, 390c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 'board': board, 391c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 'branch': branch, 392c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 'build_type': build_type, 393c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu 'suite': suite, 394c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu } 395c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu return ('%(prefix)s.%(board)s.%(build_type)s.%(branch)s.%(suite)s' 396c9c0c3ff2e8800bfad3f0c79fe5879be0ec78489MK Ryu % data_key_dict) 39783184356b60f4352e46e69488d54222032d426c0MK Ryu 39883184356b60f4352e46e69488d54222032d426c0MK Ryu 3992d0a364b21297418bef4d7f32acee8831e4eeefeMK Ryudef setup_logging(logfile=None, prefix=False): 40083184356b60f4352e46e69488d54222032d426c0MK Ryu """Setup basic logging with all logging info stripped. 40183184356b60f4352e46e69488d54222032d426c0MK Ryu 40283184356b60f4352e46e69488d54222032d426c0MK Ryu Calls to logging will only show the message. No severity is logged. 40383184356b60f4352e46e69488d54222032d426c0MK Ryu 40483184356b60f4352e46e69488d54222032d426c0MK Ryu @param logfile: If specified dump output to a file as well. 4052d0a364b21297418bef4d7f32acee8831e4eeefeMK Ryu @param prefix: Flag for log prefix. Set to True to add prefix to log 4062d0a364b21297418bef4d7f32acee8831e4eeefeMK Ryu entries to include timestamp and log level. Default is False. 40783184356b60f4352e46e69488d54222032d426c0MK Ryu """ 40883184356b60f4352e46e69488d54222032d426c0MK Ryu # Remove all existing handlers. client/common_lib/logging_config adds 40983184356b60f4352e46e69488d54222032d426c0MK Ryu # a StreamHandler to logger when modules are imported, e.g., 41083184356b60f4352e46e69488d54222032d426c0MK Ryu # autotest_lib.client.bin.utils. A new StreamHandler will be added here to 41183184356b60f4352e46e69488d54222032d426c0MK Ryu # log only messages, not severity. 41283184356b60f4352e46e69488d54222032d426c0MK Ryu logging.getLogger().handlers = [] 41383184356b60f4352e46e69488d54222032d426c0MK Ryu 4142d0a364b21297418bef4d7f32acee8831e4eeefeMK Ryu if prefix: 4152d0a364b21297418bef4d7f32acee8831e4eeefeMK Ryu log_format = '%(asctime)s %(levelname)-5s| %(message)s' 4162d0a364b21297418bef4d7f32acee8831e4eeefeMK Ryu else: 4172d0a364b21297418bef4d7f32acee8831e4eeefeMK Ryu log_format = '%(message)s' 4182d0a364b21297418bef4d7f32acee8831e4eeefeMK Ryu 41983184356b60f4352e46e69488d54222032d426c0MK Ryu screen_handler = logging.StreamHandler() 4202d0a364b21297418bef4d7f32acee8831e4eeefeMK Ryu screen_handler.setFormatter(logging.Formatter(log_format)) 42183184356b60f4352e46e69488d54222032d426c0MK Ryu logging.getLogger().addHandler(screen_handler) 42283184356b60f4352e46e69488d54222032d426c0MK Ryu logging.getLogger().setLevel(logging.INFO) 42383184356b60f4352e46e69488d54222032d426c0MK Ryu if logfile: 42483184356b60f4352e46e69488d54222032d426c0MK Ryu file_handler = logging.FileHandler(logfile) 4252d0a364b21297418bef4d7f32acee8831e4eeefeMK Ryu file_handler.setFormatter(logging.Formatter(log_format)) 42683184356b60f4352e46e69488d54222032d426c0MK Ryu file_handler.setLevel(logging.DEBUG) 42783184356b60f4352e46e69488d54222032d426c0MK Ryu logging.getLogger().addHandler(file_handler) 4288c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramanian 4298c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramanian 4308c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramaniandef is_shard(): 4318c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramanian """Determines if this instance is running as a shard. 4328c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramanian 4338c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramanian Reads the global_config value shard_hostname in the section SHARD. 4348c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramanian 4358c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramanian @return True, if shard_hostname is set, False otherwise. 4368c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramanian """ 4378c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramanian hostname = global_config.global_config.get_config_value( 4388c98ac10beaa08bfb975c412b0b3bda23178763aPrashanth Balasubramanian 'SHARD', 'shard_hostname', default=None) 4390c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu return bool(hostname) 4400c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4410c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4420c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryudef get_special_task_status(is_complete, success, is_active): 4430c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu """Get the status of a special task. 4440c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4450c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu Emulate a host queue entry status for a special task 4460c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu Although SpecialTasks are not HostQueueEntries, it is helpful to 4470c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu the user to present similar statuses. 4480c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4490c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param is_complete Boolean if the task is completed. 4500c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param success Boolean if the task succeeded. 4510c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param is_active Boolean if the task is active. 4520c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4530c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @return The status of a special task. 4540c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu """ 4550c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu if is_complete: 4560c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu if success: 4570c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu return host_queue_entry_states.Status.COMPLETED 4580c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu return host_queue_entry_states.Status.FAILED 4590c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu if is_active: 4600c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu return host_queue_entry_states.Status.RUNNING 4610c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu return host_queue_entry_states.Status.QUEUED 4620c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4630c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4640c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryudef get_special_task_exec_path(hostname, task_id, task_name, time_requested): 4650c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu """Get the execution path of the SpecialTask. 4660c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4670c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu This method returns different paths depending on where a 4680c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu the task ran: 4690c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu * Master: hosts/hostname/task_id-task_type 4700c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu * Shard: Master_path/time_created 4710c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu This is to work around the fact that a shard can fail independent 4720c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu of the master, and be replaced by another shard that has the same 4730c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu hosts. Without the time_created stamp the logs of the tasks running 4740c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu on the second shard will clobber the logs from the first in google 4750c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu storage, because task ids are not globally unique. 4760c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4770c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param hostname Hostname 4780c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param task_id Special task id 4790c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param task_name Special task name (e.g., Verify, Repair, etc) 4800c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param time_requested Special task requested time. 4810c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4820c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @return An execution path for the task. 4830c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu """ 4840c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu results_path = 'hosts/%s/%s-%s' % (hostname, task_id, task_name.lower()) 4850c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4860c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # If we do this on the master it will break backward compatibility, 4870c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # as there are tasks that currently don't have timestamps. If a host 4880c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # or job has been sent to a shard, the rpc for that host/job will 4890c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # be redirected to the shard, so this global_config check will happen 4900c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # on the shard the logs are on. 4910c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu if not is_shard(): 4920c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu return results_path 4930c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 4940c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # Generate a uid to disambiguate special task result directories 4950c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # in case this shard fails. The simplest uid is the job_id, however 4960c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # in rare cases tasks do not have jobs associated with them (eg: 4970c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # frontend verify), so just use the creation timestamp. The clocks 4980c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # between a shard and master should always be in sync. Any discrepancies 4990c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # will be brought to our attention in the form of job timeouts. 5000c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu uid = time_requested.strftime('%Y%d%m%H%M%S') 5010c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 5020c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # TODO: This is a hack, however it is the easiest way to achieve 5030c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # correctness. There is currently some debate over the future of 5040c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # tasks in our infrastructure and refactoring everything right 5050c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu # now isn't worth the time. 5060c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu return '%s/%s' % (results_path, uid) 5070c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 5080c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 5090c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryudef get_job_tag(id, owner): 5100c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu """Returns a string tag for a job. 5110c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 5120c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param id Job id 5130c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param owner Job owner 5140c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 5150c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu """ 5160c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu return '%s-%s' % (id, owner) 5170c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 5180c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 5190c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryudef get_hqe_exec_path(tag, execution_subdir): 5200c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu """Returns a execution path to a HQE's results. 5210c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 5220c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param tag Tag string for a job associated with a HQE. 5230c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu @param execution_subdir Execution sub-directory string of a HQE. 5240c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu 5250c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu """ 5260c1a37dd9b1237fe8d43c7f911ce601104806339MK Ryu return os.path.join(tag, execution_subdir) 527