blob: 64d5e9ece8dffaa16ea97c7d37e008e12dce84b3 [file] [log] [blame]
David James8c846492011-01-25 17:07:29 -08001#!/usr/bin/python
David Jamesb619a782012-07-25 19:37:57 -07002# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
David James8c846492011-01-25 17:07:29 -08003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
Brian Harringaf019fb2012-05-10 15:06:13 -07006"""This script is used to upload host prebuilts as well as board BINHOSTS.
David James8c846492011-01-25 17:07:29 -08007
David James015af872012-06-19 15:24:36 -07008Prebuilts are uploaded using gsutil to Google Storage. After these prebuilts
9are successfully uploaded, a file is updated with the proper BINHOST version.
David James8c846492011-01-25 17:07:29 -080010
11To read more about prebuilts/binhost binary packages please refer to:
David James015af872012-06-19 15:24:36 -070012http://goto/chromeos-prebuilts
David James8c846492011-01-25 17:07:29 -080013
14Example of uploading prebuilt amd64 host files to Google Storage:
David Jamesc5cbd472012-06-19 16:25:45 -070015upload_prebuilts -p /b/cbuild/build -s -u gs://chromeos-prebuilt
David James8c846492011-01-25 17:07:29 -080016
17Example of uploading x86-dogfood binhosts to Google Storage:
David Jamesc5cbd472012-06-19 16:25:45 -070018upload_prebuilts -b x86-dogfood -p /b/cbuild/build/ -u gs://chromeos-prebuilt -g
David James8c846492011-01-25 17:07:29 -080019"""
20
Mike Frysingerff441bf2014-05-24 13:47:21 -040021from __future__ import print_function
22
Chris Sosa1dc96132012-05-11 15:40:50 -070023import datetime
24import multiprocessing
Chris Sosa1dc96132012-05-11 15:40:50 -070025import os
26import sys
Chris Sosa1dc96132012-05-11 15:40:50 -070027
Don Garrett88b8d782014-05-13 17:30:55 -070028from chromite.cbuildbot import constants
29from chromite.cbuildbot import portage_utilities
David James6450a0a2012-12-04 07:59:53 -080030from chromite.lib import binpkg
Mike Frysinger86509232014-05-24 13:18:37 -040031from chromite.lib import commandline
Chris Sosa1dc96132012-05-11 15:40:50 -070032from chromite.lib import cros_build_lib
David James97d95872012-11-16 15:09:56 -080033from chromite.lib import git
Brian Harring7904b482012-08-08 02:54:12 -070034from chromite.lib import gs
Brian Harringaf019fb2012-05-10 15:06:13 -070035from chromite.lib import osutils
David James6450a0a2012-12-04 07:59:53 -080036from chromite.lib import parallel
Mike Frysinger8e727a32013-01-16 16:57:53 -050037from chromite.lib import toolchain
Chris Sosa1dc96132012-05-11 15:40:50 -070038
David James015af872012-06-19 15:24:36 -070039# How many times to retry uploads.
40_RETRIES = 10
41
42# Multiplier for how long to sleep (in seconds) between retries; will delay
43# (1*sleep) the first time, then (2*sleep), continuing via attempt * sleep.
44_SLEEP_TIME = 60
45
David James8c846492011-01-25 17:07:29 -080046_HOST_PACKAGES_PATH = 'chroot/var/lib/portage/pkgs'
David James05bcb2b2011-02-09 09:25:47 -080047_CATEGORIES_PATH = 'chroot/etc/portage/categories'
David James615e5b52011-06-03 11:10:15 -070048_PYM_PATH = 'chroot/usr/lib/portage/pym'
David James4058b0d2011-12-08 21:24:50 -080049_HOST_ARCH = 'amd64'
David James8c846492011-01-25 17:07:29 -080050_BOARD_PATH = 'chroot/build/%(board)s'
David James4058b0d2011-12-08 21:24:50 -080051_REL_BOARD_PATH = 'board/%(target)s/%(version)s'
52_REL_HOST_PATH = 'host/%(host_arch)s/%(target)s/%(version)s'
David James8c846492011-01-25 17:07:29 -080053# Private overlays to look at for builds to filter
54# relative to build path
55_PRIVATE_OVERLAY_DIR = 'src/private-overlays'
Scott Zawalskiab1bed32011-03-16 15:24:24 -070056_GOOGLESTORAGE_ACL_FILE = 'googlestorage_acl.xml'
David James3753d942014-04-23 10:55:48 -070057_BINHOST_BASE_URL = 'gs://chromeos-prebuilt'
David James8c846492011-01-25 17:07:29 -080058_PREBUILT_BASE_DIR = 'src/third_party/chromiumos-overlay/chromeos/config/'
59# Created in the event of new host targets becoming available
60_PREBUILT_MAKE_CONF = {'amd64': os.path.join(_PREBUILT_BASE_DIR,
61 'make.conf.amd64-host')}
62_BINHOST_CONF_DIR = 'src/third_party/chromiumos-overlay/chromeos/binhost'
63
64
David James4058b0d2011-12-08 21:24:50 -080065class BuildTarget(object):
66 """A board/variant/profile tuple."""
67
68 def __init__(self, board_variant, profile=None):
69 self.board_variant = board_variant
70 self.board, _, self.variant = board_variant.partition('_')
71 self.profile = profile
72
73 def __str__(self):
74 if self.profile:
75 return '%s_%s' % (self.board_variant, self.profile)
76 else:
77 return self.board_variant
78
79 def __eq__(self, other):
80 return str(other) == str(self)
81
82 def __hash__(self):
83 return hash(str(self))
84
85
David James8c846492011-01-25 17:07:29 -080086def UpdateLocalFile(filename, value, key='PORTAGE_BINHOST'):
87 """Update the key in file with the value passed.
Mike Frysinger1a736a82013-12-12 01:50:59 -050088
David James8c846492011-01-25 17:07:29 -080089 File format:
90 key="value"
91 Note quotes are added automatically
92
93 Args:
94 filename: Name of file to modify.
95 value: Value to write with the key.
96 key: The variable key to update. (Default: PORTAGE_BINHOST)
97 """
98 if os.path.exists(filename):
99 file_fh = open(filename)
100 else:
101 file_fh = open(filename, 'w+')
102 file_lines = []
103 found = False
104 keyval_str = '%(key)s=%(value)s'
105 for line in file_fh:
106 # Strip newlines from end of line. We already add newlines below.
107 line = line.rstrip("\n")
108
109 if len(line.split('=')) != 2:
110 # Skip any line that doesn't fit key=val.
111 file_lines.append(line)
112 continue
113
114 file_var, file_val = line.split('=')
115 if file_var == key:
116 found = True
Mike Frysingerff441bf2014-05-24 13:47:21 -0400117 print('Updating %s=%s to %s="%s"' % (file_var, file_val, key, value))
David James8c846492011-01-25 17:07:29 -0800118 value = '"%s"' % value
119 file_lines.append(keyval_str % {'key': key, 'value': value})
120 else:
121 file_lines.append(keyval_str % {'key': file_var, 'value': file_val})
122
123 if not found:
Brian Harring2a014302012-05-12 00:53:33 -0700124 value = '"%s"' % value
David James8c846492011-01-25 17:07:29 -0800125 file_lines.append(keyval_str % {'key': key, 'value': value})
126
127 file_fh.close()
128 # write out new file
Brian Harringaf019fb2012-05-10 15:06:13 -0700129 osutils.WriteFile(filename, '\n'.join(file_lines) + '\n')
David James8c846492011-01-25 17:07:29 -0800130
131
Mike Frysinger5b34d732013-01-17 15:11:58 -0500132def RevGitFile(filename, data, retries=5, dryrun=False):
David James8c846492011-01-25 17:07:29 -0800133 """Update and push the git file.
134
Mike Frysinger5b34d732013-01-17 15:11:58 -0500135 Args:
136 filename: file to modify that is in a git repo already
137 data: A dict of key/values to update in |filename|
138 retries: The number of times to retry before giving up, default: 5
Matt Tennante8179042013-10-01 15:47:32 -0700139 dryrun: If True, do not actually commit the change.
David James8c846492011-01-25 17:07:29 -0800140 """
141 prebuilt_branch = 'prebuilt_branch'
David James1b6e67a2011-05-19 21:32:38 -0700142 cwd = os.path.abspath(os.path.dirname(filename))
David James97d95872012-11-16 15:09:56 -0800143 commit = git.RunGit(cwd, ['rev-parse', 'HEAD']).output.rstrip()
Mike Frysinger5b34d732013-01-17 15:11:58 -0500144 description = '%s: updating %s' % (os.path.basename(filename),
145 ', '.join(data.keys()))
146 # UpdateLocalFile will print out the keys/values for us.
Mike Frysingerff441bf2014-05-24 13:47:21 -0400147 print('Revving git file %s' % filename)
David James66009462012-03-25 10:08:38 -0700148
David James8c846492011-01-25 17:07:29 -0800149 try:
David James97d95872012-11-16 15:09:56 -0800150 git.CreatePushBranch(prebuilt_branch, cwd)
Mike Frysinger5b34d732013-01-17 15:11:58 -0500151 for key, value in data.iteritems():
152 UpdateLocalFile(filename, value, key)
David James97d95872012-11-16 15:09:56 -0800153 git.RunGit(cwd, ['add', filename])
154 git.RunGit(cwd, ['commit', '-m', description])
155 git.PushWithRetry(prebuilt_branch, cwd, dryrun=dryrun, retries=retries)
David James8c846492011-01-25 17:07:29 -0800156 finally:
David James67d73252013-09-19 17:33:12 -0700157 git.RunGit(cwd, ['checkout', commit])
David James8c846492011-01-25 17:07:29 -0800158
159
160def GetVersion():
161 """Get the version to put in LATEST and update the git version with."""
Mike Frysinger0b92cfe2012-12-13 02:13:45 -0500162 return datetime.datetime.now().strftime('%Y.%m.%d.%H%M%S')
David James8c846492011-01-25 17:07:29 -0800163
164
David James015af872012-06-19 15:24:36 -0700165def _GsUpload(local_file, remote_file, acl):
David James8c846492011-01-25 17:07:29 -0800166 """Upload to GS bucket.
167
168 Args:
Matt Tennante8179042013-10-01 15:47:32 -0700169 local_file: The local file to be uploaded.
170 remote_file: The remote location to upload to.
171 acl: The ACL to use for uploading the file.
David James8c846492011-01-25 17:07:29 -0800172
173 Returns:
174 Return the arg tuple of two if the upload failed
175 """
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700176 CANNED_ACLS = ['public-read', 'private', 'bucket-owner-read',
177 'authenticated-read', 'bucket-owner-full-control',
178 'public-read-write']
David James9374aac2013-10-08 16:00:17 -0700179 gs_context = gs.GSContext(retries=_RETRIES, sleep=_SLEEP_TIME)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700180 if acl in CANNED_ACLS:
David James9374aac2013-10-08 16:00:17 -0700181 gs_context.Copy(local_file, remote_file, acl=acl)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700182 else:
183 # For private uploads we assume that the overlay board is set up properly
David James015af872012-06-19 15:24:36 -0700184 # and a googlestore_acl.xml is present. Otherwise, this script errors.
David James9374aac2013-10-08 16:00:17 -0700185 gs_context.Copy(local_file, remote_file, acl='private')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700186 # Apply the passed in ACL xml file to the uploaded object.
David James9374aac2013-10-08 16:00:17 -0700187 gs_context.SetACL(remote_file, acl=acl)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700188
Mike Frysingercc838832014-05-24 13:10:30 -0400189
David Jamesfd0b0852011-02-23 11:15:36 -0800190def RemoteUpload(acl, files, pool=10):
David James8c846492011-01-25 17:07:29 -0800191 """Upload to google storage.
192
193 Create a pool of process and call _GsUpload with the proper arguments.
194
195 Args:
David Jamesfd0b0852011-02-23 11:15:36 -0800196 acl: The canned acl used for uploading. acl can be one of: "public-read",
197 "public-read-write", "authenticated-read", "bucket-owner-read",
198 "bucket-owner-full-control", or "private".
David James8c846492011-01-25 17:07:29 -0800199 files: dictionary with keys to local files and values to remote path.
200 pool: integer of maximum proesses to have at the same time.
201
202 Returns:
203 Return a set of tuple arguments of the failed uploads
204 """
David James015af872012-06-19 15:24:36 -0700205 tasks = [[key, value, acl] for key, value in files.iteritems()]
David James6450a0a2012-12-04 07:59:53 -0800206 parallel.RunTasksInProcessPool(_GsUpload, tasks, pool)
David James8c846492011-01-25 17:07:29 -0800207
208
209def GenerateUploadDict(base_local_path, base_remote_path, pkgs):
210 """Build a dictionary of local remote file key pairs to upload.
211
212 Args:
213 base_local_path: The base path to the files on the local hard drive.
Matt Tennante8179042013-10-01 15:47:32 -0700214 base_remote_path: The base path to the remote paths.
David James8c846492011-01-25 17:07:29 -0800215 pkgs: The packages to upload.
216
217 Returns:
218 Returns a dictionary of local_path/remote_path pairs
219 """
220 upload_files = {}
221 for pkg in pkgs:
222 suffix = pkg['CPV'] + '.tbz2'
223 local_path = os.path.join(base_local_path, suffix)
224 assert os.path.exists(local_path)
225 remote_path = '%s/%s' % (base_remote_path.rstrip('/'), suffix)
226 upload_files[local_path] = remote_path
227
228 return upload_files
229
Mike Frysingercc838832014-05-24 13:10:30 -0400230
Peter Mayo950e41a2014-02-06 21:07:33 +0000231def GetBoardOverlay(build_path, target):
David Jamese5867812012-10-19 12:02:20 -0700232 """Get the path to the board variant.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500233
David James8c846492011-01-25 17:07:29 -0800234 Args:
235 build_path: The path to the root of the build directory
David Jamese5867812012-10-19 12:02:20 -0700236 target: The target board as a BuildTarget object.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500237
David James8c846492011-01-25 17:07:29 -0800238 Returns:
David Jamese5867812012-10-19 12:02:20 -0700239 The last overlay configured for the given board as a string.
David James8c846492011-01-25 17:07:29 -0800240 """
David Jamese5867812012-10-19 12:02:20 -0700241 board = target.board_variant
242 overlays = portage_utilities.FindOverlays(constants.BOTH_OVERLAYS, board,
243 buildroot=build_path)
244 # We only care about the last entry.
245 return overlays[-1]
David James8c846492011-01-25 17:07:29 -0800246
247
248def DeterminePrebuiltConfFile(build_path, target):
249 """Determine the prebuilt.conf file that needs to be updated for prebuilts.
250
Mike Frysinger1a736a82013-12-12 01:50:59 -0500251 Args:
252 build_path: The path to the root of the build directory
253 target: String representation of the board. This includes host and board
254 targets
David James8c846492011-01-25 17:07:29 -0800255
Mike Frysinger1a736a82013-12-12 01:50:59 -0500256 Returns:
257 A string path to a prebuilt.conf file to be updated.
David James8c846492011-01-25 17:07:29 -0800258 """
David James4058b0d2011-12-08 21:24:50 -0800259 if _HOST_ARCH == target:
David James8c846492011-01-25 17:07:29 -0800260 # We are host.
261 # Without more examples of hosts this is a kludge for now.
262 # TODO(Scottz): as new host targets come online expand this to
263 # work more like boards.
Chris Sosa471532a2011-02-01 15:10:06 -0800264 make_path = _PREBUILT_MAKE_CONF[target]
David James8c846492011-01-25 17:07:29 -0800265 else:
266 # We are a board
Peter Mayo950e41a2014-02-06 21:07:33 +0000267 board = GetBoardOverlay(build_path, target)
David James8c846492011-01-25 17:07:29 -0800268 make_path = os.path.join(board, 'prebuilt.conf')
269
270 return make_path
271
272
273def UpdateBinhostConfFile(path, key, value):
274 """Update binhost config file file with key=value.
275
276 Args:
277 path: Filename to update.
278 key: Key to update.
279 value: New value for key.
280 """
281 cwd = os.path.dirname(os.path.abspath(path))
282 filename = os.path.basename(path)
Brian Harringaf019fb2012-05-10 15:06:13 -0700283 osutils.SafeMakedirs(cwd)
David Jamesf6e8fb72013-05-10 08:58:43 -0700284 if not git.GetCurrentBranch(cwd):
285 git.CreatePushBranch(constants.STABLE_EBUILD_BRANCH, cwd, sync=False)
Brian Harring22edb442012-05-11 23:55:18 -0700286 osutils.WriteFile(path, '', mode='a')
David James8c846492011-01-25 17:07:29 -0800287 UpdateLocalFile(path, value, key)
David James67d73252013-09-19 17:33:12 -0700288 git.RunGit(cwd, ['add', filename])
Mike Frysinger109cada2013-01-17 15:50:44 -0500289 description = '%s: updating %s' % (os.path.basename(filename), key)
David James67d73252013-09-19 17:33:12 -0700290 git.RunGit(cwd, ['commit', '-m', description])
David James8c846492011-01-25 17:07:29 -0800291
292
David Jamesce093af2011-02-23 15:21:58 -0800293def _GrabAllRemotePackageIndexes(binhost_urls):
David James05bcb2b2011-02-09 09:25:47 -0800294 """Grab all of the packages files associated with a list of binhost_urls.
295
David James05bcb2b2011-02-09 09:25:47 -0800296 Args:
297 binhost_urls: The URLs for the directories containing the Packages files we
298 want to grab.
David James05bcb2b2011-02-09 09:25:47 -0800299
300 Returns:
301 A list of PackageIndex objects.
302 """
303 pkg_indexes = []
304 for url in binhost_urls:
David James32faafe2012-06-08 14:25:03 -0700305 pkg_index = binpkg.GrabRemotePackageIndex(url)
David James05bcb2b2011-02-09 09:25:47 -0800306 if pkg_index:
307 pkg_indexes.append(pkg_index)
David James05bcb2b2011-02-09 09:25:47 -0800308 return pkg_indexes
309
310
David Jamesc0f158a2011-02-22 16:07:29 -0800311class PrebuiltUploader(object):
312 """Synchronize host and board prebuilts."""
David James8c846492011-01-25 17:07:29 -0800313
Mike Frysinger86509232014-05-24 13:18:37 -0400314 def __init__(self, upload_location, acl, binhost_base_url, pkg_indexes,
315 build_path, packages, skip_upload, binhost_conf_dir, dryrun,
Mike Frysinger8092a632014-05-24 13:25:46 -0400316 target, slave_targets, version):
David Jamesc0f158a2011-02-22 16:07:29 -0800317 """Constructor for prebuilt uploader object.
David James8c846492011-01-25 17:07:29 -0800318
David Jamesc0f158a2011-02-22 16:07:29 -0800319 This object can upload host or prebuilt files to Google Storage.
David James8c846492011-01-25 17:07:29 -0800320
David Jamesc0f158a2011-02-22 16:07:29 -0800321 Args:
322 upload_location: The upload location.
David Jamesfd0b0852011-02-23 11:15:36 -0800323 acl: The canned acl used for uploading to Google Storage. acl can be one
324 of: "public-read", "public-read-write", "authenticated-read",
Matt Tennante8179042013-10-01 15:47:32 -0700325 "bucket-owner-read", "bucket-owner-full-control", "project-private",
326 or "private" (see "gsutil help acls"). If we are not uploading to
327 Google Storage, this parameter is unused.
David Jamesfd0b0852011-02-23 11:15:36 -0800328 binhost_base_url: The URL used for downloading the prebuilts.
David Jamesc0f158a2011-02-22 16:07:29 -0800329 pkg_indexes: Old uploaded prebuilts to compare against. Instead of
330 uploading duplicate files, we just link to the old files.
David James615e5b52011-06-03 11:10:15 -0700331 build_path: The path to the directory containing the chroot.
332 packages: Packages to upload.
David James32b0b2f2011-07-13 20:56:50 -0700333 skip_upload: Don't actually upload the tarballs.
334 binhost_conf_dir: Directory where to store binhost.conf files.
Mike Frysinger86509232014-05-24 13:18:37 -0400335 dryrun: Don't push or upload prebuilts.
David James4058b0d2011-12-08 21:24:50 -0800336 target: BuildTarget managed by this builder.
337 slave_targets: List of BuildTargets managed by slave builders.
Mike Frysinger8092a632014-05-24 13:25:46 -0400338 version: A unique string, intended to be included in the upload path,
339 which identifies the version number of the uploaded prebuilts.
David Jamesc0f158a2011-02-22 16:07:29 -0800340 """
341 self._upload_location = upload_location
David Jamesfd0b0852011-02-23 11:15:36 -0800342 self._acl = acl
David Jamesc0f158a2011-02-22 16:07:29 -0800343 self._binhost_base_url = binhost_base_url
344 self._pkg_indexes = pkg_indexes
David James615e5b52011-06-03 11:10:15 -0700345 self._build_path = build_path
346 self._packages = set(packages)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500347 self._found_packages = set()
David James8ece7ee2011-06-29 16:02:30 -0700348 self._skip_upload = skip_upload
David James32b0b2f2011-07-13 20:56:50 -0700349 self._binhost_conf_dir = binhost_conf_dir
Mike Frysinger86509232014-05-24 13:18:37 -0400350 self._dryrun = dryrun
David James4058b0d2011-12-08 21:24:50 -0800351 self._target = target
352 self._slave_targets = slave_targets
Mike Frysinger8092a632014-05-24 13:25:46 -0400353 self._version = version
David James615e5b52011-06-03 11:10:15 -0700354
355 def _ShouldFilterPackage(self, pkg):
356 if not self._packages:
357 return False
358 pym_path = os.path.abspath(os.path.join(self._build_path, _PYM_PATH))
David James710b7dc2012-02-07 16:49:59 -0800359 sys.path.insert(0, pym_path)
Don Garrett25f309a2014-03-19 14:02:12 -0700360 # pylint: disable=F0401
David James615e5b52011-06-03 11:10:15 -0700361 import portage.versions
362 cat, pkgname = portage.versions.catpkgsplit(pkg['CPV'])[0:2]
363 cp = '%s/%s' % (cat, pkgname)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500364 self._found_packages.add(cp)
David James615e5b52011-06-03 11:10:15 -0700365 return pkgname not in self._packages and cp not in self._packages
David James8c846492011-01-25 17:07:29 -0800366
David Jamesc0f158a2011-02-22 16:07:29 -0800367 def _UploadPrebuilt(self, package_path, url_suffix):
368 """Upload host or board prebuilt files to Google Storage space.
David James8c846492011-01-25 17:07:29 -0800369
David Jamesc0f158a2011-02-22 16:07:29 -0800370 Args:
371 package_path: The path to the packages dir.
David Jamesce093af2011-02-23 15:21:58 -0800372 url_suffix: The remote subdirectory where we should upload the packages.
David Jamesc0f158a2011-02-22 16:07:29 -0800373 """
David Jamesc0f158a2011-02-22 16:07:29 -0800374 # Process Packages file, removing duplicates and filtered packages.
David James32faafe2012-06-08 14:25:03 -0700375 pkg_index = binpkg.GrabLocalPackageIndex(package_path)
David Jamesc0f158a2011-02-22 16:07:29 -0800376 pkg_index.SetUploadLocation(self._binhost_base_url, url_suffix)
David James615e5b52011-06-03 11:10:15 -0700377 pkg_index.RemoveFilteredPackages(self._ShouldFilterPackage)
David Jamesc0f158a2011-02-22 16:07:29 -0800378 uploads = pkg_index.ResolveDuplicateUploads(self._pkg_indexes)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500379 unmatched_pkgs = self._packages - self._found_packages
380 if unmatched_pkgs:
381 cros_build_lib.Warning('unable to match packages: %r' % unmatched_pkgs)
David James05bcb2b2011-02-09 09:25:47 -0800382
David Jamesc0f158a2011-02-22 16:07:29 -0800383 # Write Packages file.
384 tmp_packages_file = pkg_index.WriteToNamedTemporaryFile()
David James05bcb2b2011-02-09 09:25:47 -0800385
David Jamesc0f158a2011-02-22 16:07:29 -0800386 remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
David James015af872012-06-19 15:24:36 -0700387 assert remote_location.startswith('gs://')
David James05bcb2b2011-02-09 09:25:47 -0800388
David James015af872012-06-19 15:24:36 -0700389 # Build list of files to upload.
390 upload_files = GenerateUploadDict(package_path, remote_location, uploads)
391 remote_file = '%s/Packages' % remote_location.rstrip('/')
392 upload_files[tmp_packages_file.name] = remote_file
393
394 RemoteUpload(self._acl, upload_files)
David James8c846492011-01-25 17:07:29 -0800395
Mike Frysinger8092a632014-05-24 13:25:46 -0400396 def _UploadSdkTarball(self, board_path, url_suffix, prepackaged,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500397 toolchain_tarballs, toolchain_upload_path):
398 """Upload a tarball of the sdk at the specified path to Google Storage.
David James8fa34ea2011-04-15 13:00:20 -0700399
400 Args:
401 board_path: The path to the board dir.
402 url_suffix: The remote subdirectory where we should upload the packages.
Zdenek Behan62a57792012-08-31 15:09:08 +0200403 prepackaged: If given, a tarball that has been packaged outside of this
404 script and should be used.
Mike Frysinger9e979b92012-11-29 02:55:09 -0500405 toolchain_tarballs: List of toolchain tarballs to upload.
406 toolchain_upload_path: Path under the bucket to place toolchain tarballs.
David James8fa34ea2011-04-15 13:00:20 -0700407 """
408 remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
409 assert remote_location.startswith('gs://')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200410 boardname = os.path.basename(board_path.rstrip('/'))
411 # We do not upload non SDK board tarballs,
412 assert boardname == constants.CHROOT_BUILDER_BOARD
413 assert prepackaged is not None
Zdenek Behan62a57792012-08-31 15:09:08 +0200414
Mike Frysinger8092a632014-05-24 13:25:46 -0400415 version_str = self._version[len('chroot-'):]
Mike Frysinger8e727a32013-01-16 16:57:53 -0500416 remote_tarfile = toolchain.GetSdkURL(
417 for_gsutil=True, suburl='cros-sdk-%s.tar.xz' % (version_str,))
Zdenek Behan86c15e92012-10-13 00:55:47 +0200418 # For SDK, also upload the manifest which is guaranteed to exist
419 # by the builderstage.
420 _GsUpload(prepackaged + '.Manifest', remote_tarfile + '.Manifest',
421 self._acl)
422 _GsUpload(prepackaged, remote_tarfile, self._acl)
423
Mike Frysinger9e979b92012-11-29 02:55:09 -0500424 # Post the toolchain tarballs too.
425 for tarball in toolchain_tarballs:
426 target, local_path = tarball.split(':')
427 suburl = toolchain_upload_path % {'target': target}
428 remote_path = toolchain.GetSdkURL(for_gsutil=True, suburl=suburl)
429 _GsUpload(local_path, remote_path, self._acl)
430
Zdenek Behan86c15e92012-10-13 00:55:47 +0200431 # Finally, also update the pointer to the latest SDK on which polling
432 # scripts rely.
David James4bc13702013-03-26 08:08:04 -0700433 with osutils.TempDir() as tmpdir:
Zdenek Behan86c15e92012-10-13 00:55:47 +0200434 pointerfile = os.path.join(tmpdir, 'cros-sdk-latest.conf')
Mike Frysinger8e727a32013-01-16 16:57:53 -0500435 remote_pointerfile = toolchain.GetSdkURL(for_gsutil=True,
436 suburl='cros-sdk-latest.conf')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200437 osutils.WriteFile(pointerfile, 'LATEST_SDK="%s"' % version_str)
438 _GsUpload(pointerfile, remote_pointerfile, self._acl)
Zdenek Behan33a34112012-09-10 21:07:51 +0200439
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700440 def _GetTargets(self):
441 """Retuns the list of targets to use."""
442 targets = self._slave_targets[:]
443 if self._target:
444 targets.append(self._target)
445
446 return targets
447
Mike Frysinger8092a632014-05-24 13:25:46 -0400448 def SyncHostPrebuilts(self, key, git_sync, sync_binhost_conf):
David Jamesc0f158a2011-02-22 16:07:29 -0800449 """Synchronize host prebuilt files.
David James05bcb2b2011-02-09 09:25:47 -0800450
David Jamesc0f158a2011-02-22 16:07:29 -0800451 This function will sync both the standard host packages, plus the host
452 packages associated with all targets that have been "setup" with the
453 current host's chroot. For instance, if this host has been used to build
454 x86-generic, it will sync the host packages associated with
455 'i686-pc-linux-gnu'. If this host has also been used to build arm-generic,
456 it will also sync the host packages associated with
457 'armv7a-cros-linux-gnueabi'.
David James05bcb2b2011-02-09 09:25:47 -0800458
David Jamesc0f158a2011-02-22 16:07:29 -0800459 Args:
David Jamesc0f158a2011-02-22 16:07:29 -0800460 key: The variable key to update in the git file.
461 git_sync: If set, update make.conf of target to reference the latest
462 prebuilt packages generated here.
463 sync_binhost_conf: If set, update binhost config file in
464 chromiumos-overlay for the host.
465 """
David Jamese2488642011-11-14 16:15:20 -0800466 # Slave boards are listed before the master board so that the master board
467 # takes priority (i.e. x86-generic preflight host prebuilts takes priority
468 # over preflight host prebuilts from other builders.)
469 binhost_urls = []
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700470 for target in self._GetTargets():
Mike Frysinger8092a632014-05-24 13:25:46 -0400471 url_suffix = _REL_HOST_PATH % {'version': self._version,
David James4058b0d2011-12-08 21:24:50 -0800472 'host_arch': _HOST_ARCH,
473 'target': target}
David Jamese2488642011-11-14 16:15:20 -0800474 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David James05bcb2b2011-02-09 09:25:47 -0800475
Mike Frysinger86509232014-05-24 13:18:37 -0400476 if self._target == target and not self._skip_upload and not self._dryrun:
David Jamese2488642011-11-14 16:15:20 -0800477 # Upload prebuilts.
478 package_path = os.path.join(self._build_path, _HOST_PACKAGES_PATH)
479 self._UploadPrebuilt(package_path, packages_url_suffix)
David James8ece7ee2011-06-29 16:02:30 -0700480
David Jamese2488642011-11-14 16:15:20 -0800481 # Record URL where prebuilts were uploaded.
482 binhost_urls.append('%s/%s/' % (self._binhost_base_url.rstrip('/'),
483 packages_url_suffix.rstrip('/')))
484
David James20b2b6f2011-11-18 15:11:58 -0800485 binhost = ' '.join(binhost_urls)
David James8ece7ee2011-06-29 16:02:30 -0700486 if git_sync:
487 git_file = os.path.join(self._build_path,
David James4058b0d2011-12-08 21:24:50 -0800488 _PREBUILT_MAKE_CONF[_HOST_ARCH])
Mike Frysinger86509232014-05-24 13:18:37 -0400489 RevGitFile(git_file, {key: binhost}, dryrun=self._dryrun)
David James8ece7ee2011-06-29 16:02:30 -0700490 if sync_binhost_conf:
David James32b0b2f2011-07-13 20:56:50 -0700491 binhost_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James4058b0d2011-12-08 21:24:50 -0800492 'host', '%s-%s.conf' % (_HOST_ARCH, key))
David Jamese2488642011-11-14 16:15:20 -0800493 UpdateBinhostConfFile(binhost_conf, key, binhost)
David Jamesc0f158a2011-02-22 16:07:29 -0800494
Mike Frysinger8092a632014-05-24 13:25:46 -0400495 def SyncBoardPrebuilts(self, key, git_sync, sync_binhost_conf,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500496 upload_board_tarball, prepackaged_board,
497 toolchain_tarballs, toolchain_upload_path):
David Jamesc0f158a2011-02-22 16:07:29 -0800498 """Synchronize board prebuilt files.
499
500 Args:
David Jamesc0f158a2011-02-22 16:07:29 -0800501 key: The variable key to update in the git file.
502 git_sync: If set, update make.conf of target to reference the latest
503 prebuilt packages generated here.
504 sync_binhost_conf: If set, update binhost config file in
505 chromiumos-overlay for the current board.
David James8fa34ea2011-04-15 13:00:20 -0700506 upload_board_tarball: Include a tarball of the board in our upload.
Zdenek Behan62a57792012-08-31 15:09:08 +0200507 prepackaged_board: A tarball of the board built outside of this script.
Mike Frysinger9e979b92012-11-29 02:55:09 -0500508 toolchain_tarballs: A list of toolchain tarballs to upload.
509 toolchain_upload_path: Path under the bucket to place toolchain tarballs.
David Jamesc0f158a2011-02-22 16:07:29 -0800510 """
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700511 for target in self._GetTargets():
David Jamese2488642011-11-14 16:15:20 -0800512 board_path = os.path.join(self._build_path,
David James4058b0d2011-12-08 21:24:50 -0800513 _BOARD_PATH % {'board': target.board_variant})
David Jamese2488642011-11-14 16:15:20 -0800514 package_path = os.path.join(board_path, 'packages')
Mike Frysinger8092a632014-05-24 13:25:46 -0400515 url_suffix = _REL_BOARD_PATH % {'target': target,
516 'version': self._version}
David Jamese2488642011-11-14 16:15:20 -0800517 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David James8fa34ea2011-04-15 13:00:20 -0700518
Matt Tennante8179042013-10-01 15:47:32 -0700519 # Process the target board differently if it is the main --board.
Mike Frysinger86509232014-05-24 13:18:37 -0400520 if self._target == target and not self._skip_upload and not self._dryrun:
Matt Tennante8179042013-10-01 15:47:32 -0700521 # This strips "chroot" prefix because that is sometimes added as the
522 # --prepend-version argument (e.g. by chromiumos-sdk bot).
523 # TODO(build): Clean it up to be less hard-coded.
Mike Frysinger8092a632014-05-24 13:25:46 -0400524 version_str = self._version[len('chroot-'):]
Mike Frysinger9e979b92012-11-29 02:55:09 -0500525
David Jamese2488642011-11-14 16:15:20 -0800526 # Upload board tarballs in the background.
527 if upload_board_tarball:
Mike Frysinger9e979b92012-11-29 02:55:09 -0500528 if toolchain_upload_path:
529 toolchain_upload_path %= {'version': version_str}
530 tar_process = multiprocessing.Process(
531 target=self._UploadSdkTarball,
Mike Frysinger8092a632014-05-24 13:25:46 -0400532 args=(board_path, url_suffix, prepackaged_board,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500533 toolchain_tarballs, toolchain_upload_path))
David Jamese2488642011-11-14 16:15:20 -0800534 tar_process.start()
David James8fa34ea2011-04-15 13:00:20 -0700535
David Jamese2488642011-11-14 16:15:20 -0800536 # Upload prebuilts.
537 self._UploadPrebuilt(package_path, packages_url_suffix)
David James8fa34ea2011-04-15 13:00:20 -0700538
David Jamese2488642011-11-14 16:15:20 -0800539 # Make sure we finished uploading the board tarballs.
540 if upload_board_tarball:
541 tar_process.join()
542 assert tar_process.exitcode == 0
543 # TODO(zbehan): This should be done cleaner.
Zdenek Behan33a34112012-09-10 21:07:51 +0200544 if target.board == constants.CHROOT_BUILDER_BOARD:
David Jamese2488642011-11-14 16:15:20 -0800545 sdk_conf = os.path.join(self._build_path, self._binhost_conf_dir,
Mike Frysinger5b34d732013-01-17 15:11:58 -0500546 'host/sdk_version.conf')
547 sdk_settings = {
Mike Frysinger9e979b92012-11-29 02:55:09 -0500548 'SDK_LATEST_VERSION': version_str,
549 'TC_PATH': toolchain_upload_path,
Mike Frysinger5b34d732013-01-17 15:11:58 -0500550 }
Mike Frysinger86509232014-05-24 13:18:37 -0400551 RevGitFile(sdk_conf, sdk_settings, dryrun=self._dryrun)
David Jamesc0f158a2011-02-22 16:07:29 -0800552
David Jamese2488642011-11-14 16:15:20 -0800553 # Record URL where prebuilts were uploaded.
554 url_value = '%s/%s/' % (self._binhost_base_url.rstrip('/'),
555 packages_url_suffix.rstrip('/'))
556
557 if git_sync:
David James4058b0d2011-12-08 21:24:50 -0800558 git_file = DeterminePrebuiltConfFile(self._build_path, target)
Mike Frysinger86509232014-05-24 13:18:37 -0400559 RevGitFile(git_file, {key: url_value}, dryrun=self._dryrun)
Matt Tennante8179042013-10-01 15:47:32 -0700560
David Jamese2488642011-11-14 16:15:20 -0800561 if sync_binhost_conf:
Matt Tennante8179042013-10-01 15:47:32 -0700562 # Update the binhost configuration file in git.
David Jamese2488642011-11-14 16:15:20 -0800563 binhost_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James4058b0d2011-12-08 21:24:50 -0800564 'target', '%s-%s.conf' % (target, key))
David Jamese2488642011-11-14 16:15:20 -0800565 UpdateBinhostConfFile(binhost_conf, key, url_value)
David James05bcb2b2011-02-09 09:25:47 -0800566
567
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700568def _AddSlaveBoard(_option, _opt_str, value, parser):
569 """Callback that adds a slave board to the list of slave targets."""
David James4058b0d2011-12-08 21:24:50 -0800570 parser.values.slave_targets.append(BuildTarget(value))
571
572
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700573def _AddSlaveProfile(_option, _opt_str, value, parser):
574 """Callback that adds a slave profile to the list of slave targets."""
David James4058b0d2011-12-08 21:24:50 -0800575 if not parser.values.slave_targets:
Mike Frysinger86509232014-05-24 13:18:37 -0400576 parser.error('Must specify --slave-board before --slave-profile')
David James4058b0d2011-12-08 21:24:50 -0800577 if parser.values.slave_targets[-1].profile is not None:
Mike Frysinger86509232014-05-24 13:18:37 -0400578 parser.error('Cannot specify --slave-profile twice for same board')
David James4058b0d2011-12-08 21:24:50 -0800579 parser.values.slave_targets[-1].profile = value
580
581
Mike Frysinger86509232014-05-24 13:18:37 -0400582def ParseOptions(argv):
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700583 """Returns options given by the user and the target specified.
584
Mike Frysinger86509232014-05-24 13:18:37 -0400585 Args:
586 argv: The args to parse.
587
Mike Frysinger1a736a82013-12-12 01:50:59 -0500588 Returns:
589 A tuple containing a parsed options object and BuildTarget.
590 The target instance is None if no board is specified.
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700591 """
Mike Frysinger86509232014-05-24 13:18:37 -0400592 parser = commandline.OptionParser()
David James8c846492011-01-25 17:07:29 -0800593 parser.add_option('-H', '--binhost-base-url', dest='binhost_base_url',
594 default=_BINHOST_BASE_URL,
595 help='Base URL to use for binhost in make.conf updates')
596 parser.add_option('', '--previous-binhost-url', action='append',
597 default=[], dest='previous_binhost_url',
598 help='Previous binhost URL')
599 parser.add_option('-b', '--board', dest='board', default=None,
600 help='Board type that was built on this machine')
Zdenek Behan62a57792012-08-31 15:09:08 +0200601 parser.add_option('-B', '--prepackaged-tarball', dest='prepackaged_tarball',
602 default=None,
603 help='Board tarball prebuilt outside of this script.')
Mike Frysinger9e979b92012-11-29 02:55:09 -0500604 parser.add_option('--toolchain-tarball', dest='toolchain_tarballs',
605 action='append', default=[],
606 help='Redistributable toolchain tarball.')
607 parser.add_option('--toolchain-upload-path', default='',
608 help='Path to place toolchain tarballs in the sdk tree.')
David James4058b0d2011-12-08 21:24:50 -0800609 parser.add_option('', '--profile', dest='profile', default=None,
610 help='Profile that was built on this machine')
611 parser.add_option('', '--slave-board', default=[], action='callback',
612 dest='slave_targets', type='string',
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700613 callback=_AddSlaveBoard,
David James4058b0d2011-12-08 21:24:50 -0800614 help='Board type that was built on a slave machine. To '
615 'add a profile to this board, use --slave-profile.')
616 parser.add_option('', '--slave-profile', action='callback', type='string',
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700617 callback=_AddSlaveProfile,
David James4058b0d2011-12-08 21:24:50 -0800618 help='Board profile that was built on a slave machine. '
619 'Applies to previous slave board.')
David James8c846492011-01-25 17:07:29 -0800620 parser.add_option('-p', '--build-path', dest='build_path',
David James05bcb2b2011-02-09 09:25:47 -0800621 help='Path to the directory containing the chroot')
David James615e5b52011-06-03 11:10:15 -0700622 parser.add_option('', '--packages', action='append',
623 default=[], dest='packages',
624 help='Only include the specified packages. '
625 '(Default is to include all packages.)')
David James8c846492011-01-25 17:07:29 -0800626 parser.add_option('-s', '--sync-host', dest='sync_host',
627 default=False, action='store_true',
628 help='Sync host prebuilts')
629 parser.add_option('-g', '--git-sync', dest='git_sync',
630 default=False, action='store_true',
David Jamese2488642011-11-14 16:15:20 -0800631 help='Enable git version sync (This commits to a repo.) '
632 'This is used by full builders to commit directly '
633 'to board overlays.')
David James8c846492011-01-25 17:07:29 -0800634 parser.add_option('-u', '--upload', dest='upload',
635 default=None,
636 help='Upload location')
637 parser.add_option('-V', '--prepend-version', dest='prepend_version',
638 default=None,
639 help='Add an identifier to the front of the version')
640 parser.add_option('-f', '--filters', dest='filters', action='store_true',
641 default=False,
642 help='Turn on filtering of private ebuild packages')
643 parser.add_option('-k', '--key', dest='key',
644 default='PORTAGE_BINHOST',
645 help='Key to update in make.conf / binhost.conf')
David James8ece7ee2011-06-29 16:02:30 -0700646 parser.add_option('', '--set-version', dest='set_version',
647 default=None,
648 help='Specify the version string')
David James8c846492011-01-25 17:07:29 -0800649 parser.add_option('', '--sync-binhost-conf', dest='sync_binhost_conf',
650 default=False, action='store_true',
David Jamese2488642011-11-14 16:15:20 -0800651 help='Update binhost.conf in chromiumos-overlay or '
652 'chromeos-overlay. Commit the changes, but don\'t '
653 'push them. This is used for preflight binhosts.')
David James32b0b2f2011-07-13 20:56:50 -0700654 parser.add_option('', '--binhost-conf-dir', dest='binhost_conf_dir',
655 default=_BINHOST_CONF_DIR,
656 help='Directory to commit binhost config with '
657 '--sync-binhost-conf.')
David Jamesfd0b0852011-02-23 11:15:36 -0800658 parser.add_option('-P', '--private', dest='private', action='store_true',
659 default=False, help='Mark gs:// uploads as private.')
David James8ece7ee2011-06-29 16:02:30 -0700660 parser.add_option('', '--skip-upload', dest='skip_upload',
661 action='store_true', default=False,
662 help='Skip upload step.')
David James8fa34ea2011-04-15 13:00:20 -0700663 parser.add_option('', '--upload-board-tarball', dest='upload_board_tarball',
664 action='store_true', default=False,
665 help='Upload board tarball to Google Storage.')
Mike Frysinger86509232014-05-24 13:18:37 -0400666 parser.add_option('-n', '--dry-run', dest='dryrun',
David James27fa7d12011-06-29 17:24:14 -0700667 action='store_true', default=False,
668 help='Don\'t push or upload prebuilts.')
David James8c846492011-01-25 17:07:29 -0800669
Mike Frysinger86509232014-05-24 13:18:37 -0400670 options, args = parser.parse_args(argv)
David James8c846492011-01-25 17:07:29 -0800671 if not options.build_path:
Mike Frysinger86509232014-05-24 13:18:37 -0400672 parser.error('you need provide a chroot path')
David James8ece7ee2011-06-29 16:02:30 -0700673 if not options.upload and not options.skip_upload:
Mike Frysinger86509232014-05-24 13:18:37 -0400674 parser.error('you need to provide an upload location using -u')
David James8ece7ee2011-06-29 16:02:30 -0700675 if not options.set_version and options.skip_upload:
Mike Frysinger86509232014-05-24 13:18:37 -0400676 parser.error('If you are using --skip-upload, you must specify a '
677 'version number using --set-version.')
David James9417f272011-05-26 13:24:47 -0700678 if args:
Mike Frysinger86509232014-05-24 13:18:37 -0400679 parser.error('invalid arguments passed to upload_prebuilts: %r' % args)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700680
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700681 target = None
682 if options.board:
683 target = BuildTarget(options.board, options.profile)
684
685 if target in options.slave_targets:
Mike Frysinger86509232014-05-24 13:18:37 -0400686 parser.error('--board/--profile must not also be a slave target.')
David Jamese2488642011-11-14 16:15:20 -0800687
David James4058b0d2011-12-08 21:24:50 -0800688 if len(set(options.slave_targets)) != len(options.slave_targets):
Mike Frysinger86509232014-05-24 13:18:37 -0400689 parser.error('--slave-boards must not have duplicates.')
David Jamese2488642011-11-14 16:15:20 -0800690
David James4058b0d2011-12-08 21:24:50 -0800691 if options.slave_targets and options.git_sync:
Mike Frysinger86509232014-05-24 13:18:37 -0400692 parser.error('--slave-boards is not compatible with --git-sync')
David Jamese2488642011-11-14 16:15:20 -0800693
David James8ece7ee2011-06-29 16:02:30 -0700694 if (options.upload_board_tarball and options.skip_upload and
695 options.board == 'amd64-host'):
Mike Frysinger86509232014-05-24 13:18:37 -0400696 parser.error('--skip-upload is not compatible with '
697 '--upload-board-tarball and --board=amd64-host')
David James8fa34ea2011-04-15 13:00:20 -0700698
David James8ece7ee2011-06-29 16:02:30 -0700699 if (options.upload_board_tarball and not options.skip_upload and
700 not options.upload.startswith('gs://')):
Mike Frysinger86509232014-05-24 13:18:37 -0400701 parser.error('--upload-board-tarball only works with gs:// URLs.\n'
702 '--upload must be a gs:// URL.')
David James8fa34ea2011-04-15 13:00:20 -0700703
Zdenek Behan86c15e92012-10-13 00:55:47 +0200704 if options.upload_board_tarball and options.prepackaged_tarball is None:
Mike Frysinger86509232014-05-24 13:18:37 -0400705 parser.error('--upload-board-tarball requires --prepackaged-tarball')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200706
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700707 if options.private:
708 if options.sync_host:
Mike Frysinger86509232014-05-24 13:18:37 -0400709 parser.error('--private and --sync-host/-s cannot be specified '
710 'together; we do not support private host prebuilts')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700711
David James8ece7ee2011-06-29 16:02:30 -0700712 if not options.upload or not options.upload.startswith('gs://'):
Mike Frysinger86509232014-05-24 13:18:37 -0400713 parser.error('--private is only valid for gs:// URLs; '
714 '--upload must be a gs:// URL.')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700715
716 if options.binhost_base_url != _BINHOST_BASE_URL:
Mike Frysinger86509232014-05-24 13:18:37 -0400717 parser.error('when using --private the --binhost-base-url '
718 'is automatically derived.')
David James27fa7d12011-06-29 17:24:14 -0700719
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700720 return options, target
David Jamesc0f158a2011-02-22 16:07:29 -0800721
Mike Frysingercc838832014-05-24 13:10:30 -0400722
Mike Frysinger86509232014-05-24 13:18:37 -0400723def main(argv):
David Jamesdb401072011-06-10 12:17:16 -0700724 # Set umask to a sane value so that files created as root are readable.
Mike Frysinger60ec1012013-10-21 00:11:10 -0400725 os.umask(0o22)
David Jamesdb401072011-06-10 12:17:16 -0700726
Mike Frysinger86509232014-05-24 13:18:37 -0400727 options, target = ParseOptions(argv)
David Jamesc0f158a2011-02-22 16:07:29 -0800728
David James05bcb2b2011-02-09 09:25:47 -0800729 # Calculate a list of Packages index files to compare against. Whenever we
730 # upload a package, we check to make sure it's not already stored in one of
731 # the packages files we uploaded. This list of packages files might contain
732 # both board and host packages.
David Jamesce093af2011-02-23 15:21:58 -0800733 pkg_indexes = _GrabAllRemotePackageIndexes(options.previous_binhost_url)
David James8c846492011-01-25 17:07:29 -0800734
David James8ece7ee2011-06-29 16:02:30 -0700735 if options.set_version:
736 version = options.set_version
737 else:
738 version = GetVersion()
Matt Tennante8179042013-10-01 15:47:32 -0700739
David Jamesc0f158a2011-02-22 16:07:29 -0800740 if options.prepend_version:
741 version = '%s-%s' % (options.prepend_version, version)
742
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700743 acl = 'public-read'
744 binhost_base_url = options.binhost_base_url
745
David Jamesadd21432013-05-21 10:04:07 -0700746 if options.private:
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700747 binhost_base_url = options.upload
David Jamesadd21432013-05-21 10:04:07 -0700748 if target:
Peter Mayo950e41a2014-02-06 21:07:33 +0000749 board_path = GetBoardOverlay(options.build_path, target)
David Jamesadd21432013-05-21 10:04:07 -0700750 acl = os.path.join(board_path, _GOOGLESTORAGE_ACL_FILE)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700751
752 uploader = PrebuiltUploader(options.upload, acl, binhost_base_url,
David James615e5b52011-06-03 11:10:15 -0700753 pkg_indexes, options.build_path,
David James27fa7d12011-06-29 17:24:14 -0700754 options.packages, options.skip_upload,
Mike Frysinger86509232014-05-24 13:18:37 -0400755 options.binhost_conf_dir, options.dryrun,
Mike Frysinger8092a632014-05-24 13:25:46 -0400756 target, options.slave_targets, version)
David Jamesc0f158a2011-02-22 16:07:29 -0800757
David James8c846492011-01-25 17:07:29 -0800758 if options.sync_host:
Mike Frysinger8092a632014-05-24 13:25:46 -0400759 uploader.SyncHostPrebuilts(options.key, options.git_sync,
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700760 options.sync_binhost_conf)
David James8c846492011-01-25 17:07:29 -0800761
Chris Sosa62c8ff52012-06-04 15:03:12 -0700762 if options.board or options.slave_targets:
Mike Frysinger8092a632014-05-24 13:25:46 -0400763 uploader.SyncBoardPrebuilts(options.key, options.git_sync,
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700764 options.sync_binhost_conf,
Zdenek Behan62a57792012-08-31 15:09:08 +0200765 options.upload_board_tarball,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500766 options.prepackaged_tarball,
767 options.toolchain_tarballs,
768 options.toolchain_upload_path)