184eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 284eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold# Use of this source code is governed by a BSD-style license that can be 384eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold# found in the LICENSE file. 484eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 584eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold"""Module for discovering Chrome OS test images and payloads.""" 684eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 7bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosaimport logging 81318001bd349930e1a2a152324100583a841a892Gilad Arnoldimport re 984eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 10bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosaimport common 11bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosafrom autotest_lib.client.common_lib import global_config 1267dbe59a00e09c5357fd3667487d2ee58dc30993Chris Sosafrom autotest_lib.utils import external_packages 13481fbbf599f4b4491f7b071b777b8b7408b6a901Chris Sosa 1467dbe59a00e09c5357fd3667487d2ee58dc30993Chris Sosafrom autotest_lib.site_utils.autoupdate import import_common 1567dbe59a00e09c5357fd3667487d2ee58dc30993Chris Sosadevserver = import_common.download_and_import('devserver', 1667dbe59a00e09c5357fd3667487d2ee58dc30993Chris Sosa external_packages.DevServerRepo()) 17dc41cfe6cb678d92c63b2607101442de845baaedAlex Millerfrom devserver import gsutil_util 18bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa 1984eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 2084eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold# A string indicating a zip-file boundary within a URI path. This string must 2184eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold# end with a '/', in order for standard basename code to work correctly for 2284eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold# zip-encapsulated paths. 2384eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad ArnoldZIPFILE_BOUNDARY = '//' 24b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris SosaARCHIVE_URL_FORMAT = '%(archive_prefix)s/%(version)s' 2584eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 2684eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 2784eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnoldclass TestImageError(BaseException): 28bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa """Raised on any error in this module.""" 2984eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold pass 3084eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 3184eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 32728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosaclass NotSingleItem(Exception): 33728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosa """Raised when we want a single item but got multiple.""" 34728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosa 35728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosa 36b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosadef get_default_archive_url(board, build_version): 37b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa """Returns the default archive_url for the given board and build_version . 38fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosa 39b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa @param board: the platform/board name 40b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa @param build_version: the full build version i.e. R27-3823.0.0-a2. 41fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosa """ 42bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa archive_base = global_config.global_config.get_config_value( 43bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa 'CROS', 'image_storage_server') 44bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa archive_base = archive_base.rstrip('/') # Remove any trailing /'s. 451bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa 461bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa # TODO(garnold) adjustment to -he variant board names; should be removed 471bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa # once we switch to using artifacts from gs://chromeos-images/ 481bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa # (see chromium-os:38222) 49bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa board = re.sub('-he$', '_he', board) 50b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa archive_prefix = archive_base + '/%s-release' % board 51bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa return ARCHIVE_URL_FORMAT % dict( 52b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa archive_prefix=archive_prefix, version=build_version) 53b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa 54b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa 55b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosadef get_archive_url_from_prefix(archive_prefix, build_version): 56b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa """Returns the gs archive_url given a particular archive_prefix. 57b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa 58b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa @param archive_prefix: Use the archive_prefix as the base of your URL 59b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa 60b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa construction (instead of config + board-release) e.g. 61b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa gs://my_location/my_super_awesome_directory. 62b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa @param build_version: the full build version i.e. R27-3823.0.0-a2. 63b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa """ 64b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa return ARCHIVE_URL_FORMAT % dict( 65b86d2667b0bff0c43e3e26d5d46af6cd0df45c3dChris Sosa archive_prefix=archive_prefix, version=build_version) 66bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa 67bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa 681bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosadef gs_ls(pattern, archive_url, single): 6984eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold """Returns a list of URIs that match a given pattern. 7084eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 711bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa @param pattern: a regexp pattern to match (feeds into re.match). 721bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa @param archive_url: the gs uri where to search (see ARCHIVE_URL_FORMAT). 731bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa @param single: if true, expect a single match and return it. 7484eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 751bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa @return A list of URIs (possibly an empty list). 7684eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 7784eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold """ 781bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa try: 791bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa logging.debug('Searching for pattern %s from url %s', pattern, 801bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa archive_url) 811bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa uri_list = gsutil_util.GetGSNamesWithWait( 82728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosa pattern, archive_url, err_str=__name__, timeout=1) 831bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa # Convert to the format our clients expect (full archive path). 84fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosa if uri_list: 85728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosa if not single or (single and len(uri_list) == 1): 86728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosa return ['/'.join([archive_url, u]) for u in uri_list] 87728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosa else: 88728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosa raise NotSingleItem() 89fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosa 90fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosa return [] 911bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa except gsutil_util.PatternNotSpecific as e: 921bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa raise TestImageError(str(e)) 931bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa except gsutil_util.GSUtilError: 941bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa return [] 9584eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 9684eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 97fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosadef find_payload_uri(archive_url, delta=False, single=False): 9884eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold """Finds test payloads corresponding to a given board/release. 9984eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 100fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosa @param archive_url: Archive_url directory to find the payload. 10184eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold @param delta: if true, seek delta payloads to the given release 10284eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold @param single: if true, expect a single match and return it, otherwise 10384eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold None 10484eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 10584eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold @return A (possibly empty) list of URIs, or a single (possibly None) URI if 10684eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold |single| is True. 10784eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 10884eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold @raise TestImageError if an error has occurred. 10984eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 11084eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold """ 111bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa if delta: 112728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosa pattern = '*_delta_*' 113bc69deaf8ce5fb74646f0ff5d32a3773c5c3fbd1Chris Sosa else: 114728736163fe2ec04c8eb93b27bf4070e5dad1f05Chris Sosa pattern = '*_full_*' 11584eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 1161bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa payload_uri_list = gs_ls(pattern, archive_url, single) 117641c929a4205a630d9065332c7a30c5ef6c30cd3Chris Sosa if not payload_uri_list: 118641c929a4205a630d9065332c7a30c5ef6c30cd3Chris Sosa return None if single else [] 119641c929a4205a630d9065332c7a30c5ef6c30cd3Chris Sosa 1201bf41c4ff52e8a3ea1a99fa7331a1c77349c9f22Chris Sosa return payload_uri_list[0] if single else payload_uri_list 12184eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 12284eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 123fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosadef find_image_uri(archive_url): 12484eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold """Returns a URI to a test image. 12584eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 126fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosa @param archive_url: archive_url directory to find the payload. 12784eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 12884eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold @return A URI to the desired image if found, None otherwise. It will most 12984eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold likely be a file inside an image archive (image.zip), in which case 13084eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold we'll be using ZIPFILE_BOUNDARY ('//') to denote a zip-encapsulated 13184eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold file, for example: 13284eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold gs://chromeos-image-archive/.../image.zip//chromiumos_test_image.bin 13384eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 13484eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold @raise TestImageError if an error has occurred. 13584eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold 13684eb60cb5d66d6052407ebae4f1aa38000c9cbcfGilad Arnold """ 137641c929a4205a630d9065332c7a30c5ef6c30cd3Chris Sosa image_archive = gs_ls('image.zip', archive_url, single=True) 138641c929a4205a630d9065332c7a30c5ef6c30cd3Chris Sosa if not image_archive: 139641c929a4205a630d9065332c7a30c5ef6c30cd3Chris Sosa return None 140641c929a4205a630d9065332c7a30c5ef6c30cd3Chris Sosa 141641c929a4205a630d9065332c7a30c5ef6c30cd3Chris Sosa return (image_archive[0] + ZIPFILE_BOUNDARY + 'chromiumos_test_image.bin') 142