blob: abbdb30bb0c5f6b69715d1bc02d4305fef14d5b5 [file] [log] [blame]
Gilad Arnold84eb60c2012-11-05 23:46:10 -08001# Copyright (c) 2012 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"""Module for discovering Chrome OS test images and payloads."""
6
Chris Sosabc69dea2013-02-22 16:09:40 -08007import logging
Gilad Arnold13180012013-01-24 17:58:21 -08008import re
Gilad Arnold84eb60c2012-11-05 23:46:10 -08009import subprocess
10
Chris Sosabc69dea2013-02-22 16:09:40 -080011import common
12from autotest_lib.client.common_lib import global_config
13
Gilad Arnold84eb60c2012-11-05 23:46:10 -080014
15# A string indicating a zip-file boundary within a URI path. This string must
16# end with a '/', in order for standard basename code to work correctly for
17# zip-encapsulated paths.
18ZIPFILE_BOUNDARY = '//'
Chris Sosabc69dea2013-02-22 16:09:40 -080019ARCHIVE_URL_FORMAT = '%(archive_base)s/%(board)s-release/%(branch)s-%(release)s'
Gilad Arnold84eb60c2012-11-05 23:46:10 -080020
21
22class TestImageError(BaseException):
Chris Sosabc69dea2013-02-22 16:09:40 -080023 """Raised on any error in this module."""
Gilad Arnold84eb60c2012-11-05 23:46:10 -080024 pass
25
26
Chris Sosabc69dea2013-02-22 16:09:40 -080027def _get_archive_url(board, branch, release):
28 """Returns the gs archive_url for the respective arguments."""
29 # TODO(garnold) adjustment to -he variant board names; should be removed
30 # once we switch to using artifacts from gs://chromeos-images/
31 # (see chromium-os:38222)
32 archive_base = global_config.global_config.get_config_value(
33 'CROS', 'image_storage_server')
34 archive_base = archive_base.rstrip('/') # Remove any trailing /'s.
35 board = re.sub('-he$', '_he', board)
36 return ARCHIVE_URL_FORMAT % dict(
37 archive_base=archive_base, board=board, branch=branch,
38 release=release)
39
40
Gilad Arnold84eb60c2012-11-05 23:46:10 -080041def gs_ls(uri_pattern):
42 """Returns a list of URIs that match a given pattern.
43
44 @param uri_pattern: a GS URI pattern, may contain wildcards
45
46 @return A list of URIs matching the given pattern.
47
48 """
49 gs_cmd = ['gsutil', 'ls', uri_pattern]
Chris Sosabc69dea2013-02-22 16:09:40 -080050 logging.debug(' '.join(gs_cmd))
Gilad Arnold84eb60c2012-11-05 23:46:10 -080051 output = subprocess.Popen(gs_cmd, stdout=subprocess.PIPE,
52 stderr=subprocess.PIPE).stdout
53 return [path.rstrip() for path in output if path]
54
55
56def find_payload_uri(board, release, branch, delta=False,
Chris Sosabc69dea2013-02-22 16:09:40 -080057 single=False, archive_url=None):
Gilad Arnold84eb60c2012-11-05 23:46:10 -080058 """Finds test payloads corresponding to a given board/release.
59
60 @param board: the platform name (string)
61 @param release: the release version (string), without milestone and
62 attempt/build counters
63 @param branch: the release's branch name
64 @param delta: if true, seek delta payloads to the given release
65 @param single: if true, expect a single match and return it, otherwise
66 None
Chris Sosabc69dea2013-02-22 16:09:40 -080067 @param archive_url: Optional archive_url directory to find the payload.
Gilad Arnold84eb60c2012-11-05 23:46:10 -080068
69 @return A (possibly empty) list of URIs, or a single (possibly None) URI if
70 |single| is True.
71
72 @raise TestImageError if an error has occurred.
73
74 """
Chris Sosabc69dea2013-02-22 16:09:40 -080075 if not archive_url:
76 archive_url = _get_archive_url(board, branch, release)
Gilad Arnold13180012013-01-24 17:58:21 -080077
Chris Sosabc69dea2013-02-22 16:09:40 -080078 if delta:
79 gs_ls_search = (archive_url + '/chromeos_*_%s-%s*_%s_delta_dev.bin' %
80 (branch, release, board))
81 else:
82 gs_ls_search = (archive_url + '/chromeos_%s-%s*_%s_full_dev.bin' %
83 (branch, release, board))
84
85 payload_uri_list = gs_ls(gs_ls_search)
Gilad Arnold84eb60c2012-11-05 23:46:10 -080086
87 if single:
88 payload_uri_list_len = len(payload_uri_list)
89 if payload_uri_list_len == 0:
90 return None
91 elif payload_uri_list_len != 1:
92 raise TestImageError('unexpected number of results (%d instead '
93 'of 1)' % payload_uri_list_len)
94 return payload_uri_list[0]
95
96 return payload_uri_list
97
98
Chris Sosabc69dea2013-02-22 16:09:40 -080099def find_image_uri(board, release, branch, archive_url=None):
Gilad Arnold84eb60c2012-11-05 23:46:10 -0800100 """Returns a URI to a test image.
101
102 @param board: the platform name (string)
103 @param release: the release version (string), without milestone and
104 attempt/build counters
105 @param branch: the release's branch name
Chris Sosabc69dea2013-02-22 16:09:40 -0800106 @param archive_url: Optional archive_url directory to find the payload.
Gilad Arnold84eb60c2012-11-05 23:46:10 -0800107
108 @return A URI to the desired image if found, None otherwise. It will most
109 likely be a file inside an image archive (image.zip), in which case
110 we'll be using ZIPFILE_BOUNDARY ('//') to denote a zip-encapsulated
111 file, for example:
112 gs://chromeos-image-archive/.../image.zip//chromiumos_test_image.bin
113
114 @raise TestImageError if an error has occurred.
115
116 """
Chris Sosabc69dea2013-02-22 16:09:40 -0800117 if not archive_url:
118 archive_url = _get_archive_url(board, branch, release)
Gilad Arnold13180012013-01-24 17:58:21 -0800119
Chris Sosabc69dea2013-02-22 16:09:40 -0800120 gs_ls_search = archive_url + '/image.zip'
121 image_archive_uri_list = gs_ls(gs_ls_search)
Gilad Arnold84eb60c2012-11-05 23:46:10 -0800122
123 image_archive_uri_list_len = len(image_archive_uri_list)
124 if image_archive_uri_list_len == 0:
125 return None
126 elif image_archive_uri_list_len != 1:
127 raise TestImageError('unexpected number of results (%d > 1)' %
128 image_archive_uri_list_len)
129
130 return (image_archive_uri_list[0] + ZIPFILE_BOUNDARY +
131 'chromiumos_test_image.bin')