blob: 37c9197a70d5534aa73705a6acefcb5d8e599da5 [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
Mike Frysinger540883b2014-05-24 13:46:16 -040024import functools
Chris Sosa1dc96132012-05-11 15:40:50 -070025import multiprocessing
Chris Sosa1dc96132012-05-11 15:40:50 -070026import os
27import sys
Chris Sosa1dc96132012-05-11 15:40:50 -070028
Don Garrett88b8d782014-05-13 17:30:55 -070029from chromite.cbuildbot import constants
30from chromite.cbuildbot import portage_utilities
David James6450a0a2012-12-04 07:59:53 -080031from chromite.lib import binpkg
Mike Frysinger86509232014-05-24 13:18:37 -040032from chromite.lib import commandline
Chris Sosa1dc96132012-05-11 15:40:50 -070033from chromite.lib import cros_build_lib
David James97d95872012-11-16 15:09:56 -080034from chromite.lib import git
Brian Harring7904b482012-08-08 02:54:12 -070035from chromite.lib import gs
Brian Harringaf019fb2012-05-10 15:06:13 -070036from chromite.lib import osutils
David James6450a0a2012-12-04 07:59:53 -080037from chromite.lib import parallel
Mike Frysinger8e727a32013-01-16 16:57:53 -050038from chromite.lib import toolchain
Chris Sosa1dc96132012-05-11 15:40:50 -070039
David James015af872012-06-19 15:24:36 -070040# How many times to retry uploads.
41_RETRIES = 10
42
43# Multiplier for how long to sleep (in seconds) between retries; will delay
44# (1*sleep) the first time, then (2*sleep), continuing via attempt * sleep.
45_SLEEP_TIME = 60
46
David James8c846492011-01-25 17:07:29 -080047_HOST_PACKAGES_PATH = 'chroot/var/lib/portage/pkgs'
David James05bcb2b2011-02-09 09:25:47 -080048_CATEGORIES_PATH = 'chroot/etc/portage/categories'
David James615e5b52011-06-03 11:10:15 -070049_PYM_PATH = 'chroot/usr/lib/portage/pym'
David James4058b0d2011-12-08 21:24:50 -080050_HOST_ARCH = 'amd64'
David James8c846492011-01-25 17:07:29 -080051_BOARD_PATH = 'chroot/build/%(board)s'
David James4058b0d2011-12-08 21:24:50 -080052_REL_BOARD_PATH = 'board/%(target)s/%(version)s'
53_REL_HOST_PATH = 'host/%(host_arch)s/%(target)s/%(version)s'
David James8c846492011-01-25 17:07:29 -080054# Private overlays to look at for builds to filter
55# relative to build path
56_PRIVATE_OVERLAY_DIR = 'src/private-overlays'
Scott Zawalskiab1bed32011-03-16 15:24:24 -070057_GOOGLESTORAGE_ACL_FILE = 'googlestorage_acl.xml'
David James3753d942014-04-23 10:55:48 -070058_BINHOST_BASE_URL = 'gs://chromeos-prebuilt'
David James8c846492011-01-25 17:07:29 -080059_PREBUILT_BASE_DIR = 'src/third_party/chromiumos-overlay/chromeos/config/'
60# Created in the event of new host targets becoming available
61_PREBUILT_MAKE_CONF = {'amd64': os.path.join(_PREBUILT_BASE_DIR,
62 'make.conf.amd64-host')}
63_BINHOST_CONF_DIR = 'src/third_party/chromiumos-overlay/chromeos/binhost'
64
65
David James4058b0d2011-12-08 21:24:50 -080066class BuildTarget(object):
67 """A board/variant/profile tuple."""
68
69 def __init__(self, board_variant, profile=None):
70 self.board_variant = board_variant
71 self.board, _, self.variant = board_variant.partition('_')
72 self.profile = profile
73
74 def __str__(self):
75 if self.profile:
76 return '%s_%s' % (self.board_variant, self.profile)
77 else:
78 return self.board_variant
79
80 def __eq__(self, other):
81 return str(other) == str(self)
82
83 def __hash__(self):
84 return hash(str(self))
85
86
David James8c846492011-01-25 17:07:29 -080087def UpdateLocalFile(filename, value, key='PORTAGE_BINHOST'):
88 """Update the key in file with the value passed.
Mike Frysinger1a736a82013-12-12 01:50:59 -050089
David James8c846492011-01-25 17:07:29 -080090 File format:
91 key="value"
92 Note quotes are added automatically
93
94 Args:
95 filename: Name of file to modify.
96 value: Value to write with the key.
97 key: The variable key to update. (Default: PORTAGE_BINHOST)
98 """
99 if os.path.exists(filename):
100 file_fh = open(filename)
101 else:
102 file_fh = open(filename, 'w+')
103 file_lines = []
104 found = False
105 keyval_str = '%(key)s=%(value)s'
106 for line in file_fh:
107 # Strip newlines from end of line. We already add newlines below.
108 line = line.rstrip("\n")
109
110 if len(line.split('=')) != 2:
111 # Skip any line that doesn't fit key=val.
112 file_lines.append(line)
113 continue
114
115 file_var, file_val = line.split('=')
116 if file_var == key:
117 found = True
Mike Frysingerff441bf2014-05-24 13:47:21 -0400118 print('Updating %s=%s to %s="%s"' % (file_var, file_val, key, value))
David James8c846492011-01-25 17:07:29 -0800119 value = '"%s"' % value
120 file_lines.append(keyval_str % {'key': key, 'value': value})
121 else:
122 file_lines.append(keyval_str % {'key': file_var, 'value': file_val})
123
124 if not found:
Brian Harring2a014302012-05-12 00:53:33 -0700125 value = '"%s"' % value
David James8c846492011-01-25 17:07:29 -0800126 file_lines.append(keyval_str % {'key': key, 'value': value})
127
128 file_fh.close()
129 # write out new file
Brian Harringaf019fb2012-05-10 15:06:13 -0700130 osutils.WriteFile(filename, '\n'.join(file_lines) + '\n')
David James8c846492011-01-25 17:07:29 -0800131
132
Mike Frysinger5b34d732013-01-17 15:11:58 -0500133def RevGitFile(filename, data, retries=5, dryrun=False):
David James8c846492011-01-25 17:07:29 -0800134 """Update and push the git file.
135
Mike Frysinger5b34d732013-01-17 15:11:58 -0500136 Args:
137 filename: file to modify that is in a git repo already
138 data: A dict of key/values to update in |filename|
139 retries: The number of times to retry before giving up, default: 5
Matt Tennante8179042013-10-01 15:47:32 -0700140 dryrun: If True, do not actually commit the change.
David James8c846492011-01-25 17:07:29 -0800141 """
142 prebuilt_branch = 'prebuilt_branch'
David James1b6e67a2011-05-19 21:32:38 -0700143 cwd = os.path.abspath(os.path.dirname(filename))
David James97d95872012-11-16 15:09:56 -0800144 commit = git.RunGit(cwd, ['rev-parse', 'HEAD']).output.rstrip()
Mike Frysinger5b34d732013-01-17 15:11:58 -0500145 description = '%s: updating %s' % (os.path.basename(filename),
146 ', '.join(data.keys()))
147 # UpdateLocalFile will print out the keys/values for us.
Mike Frysingerff441bf2014-05-24 13:47:21 -0400148 print('Revving git file %s' % filename)
David James66009462012-03-25 10:08:38 -0700149
David James8c846492011-01-25 17:07:29 -0800150 try:
David James97d95872012-11-16 15:09:56 -0800151 git.CreatePushBranch(prebuilt_branch, cwd)
Mike Frysinger5b34d732013-01-17 15:11:58 -0500152 for key, value in data.iteritems():
153 UpdateLocalFile(filename, value, key)
David James97d95872012-11-16 15:09:56 -0800154 git.RunGit(cwd, ['add', filename])
155 git.RunGit(cwd, ['commit', '-m', description])
156 git.PushWithRetry(prebuilt_branch, cwd, dryrun=dryrun, retries=retries)
David James8c846492011-01-25 17:07:29 -0800157 finally:
David James67d73252013-09-19 17:33:12 -0700158 git.RunGit(cwd, ['checkout', commit])
David James8c846492011-01-25 17:07:29 -0800159
160
161def GetVersion():
162 """Get the version to put in LATEST and update the git version with."""
Mike Frysinger0b92cfe2012-12-13 02:13:45 -0500163 return datetime.datetime.now().strftime('%Y.%m.%d.%H%M%S')
David James8c846492011-01-25 17:07:29 -0800164
165
Mike Frysinger540883b2014-05-24 13:46:16 -0400166def _GsUpload(gs_context, acl, local_file, remote_file):
David James8c846492011-01-25 17:07:29 -0800167 """Upload to GS bucket.
168
169 Args:
Mike Frysinger540883b2014-05-24 13:46:16 -0400170 gs_context: A lib.gs.GSContext instance.
171 acl: The ACL to use for uploading the file.
Matt Tennante8179042013-10-01 15:47:32 -0700172 local_file: The local file to be uploaded.
173 remote_file: The remote location to upload to.
David James8c846492011-01-25 17:07:29 -0800174
175 Returns:
176 Return the arg tuple of two if the upload failed
177 """
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700178 CANNED_ACLS = ['public-read', 'private', 'bucket-owner-read',
179 'authenticated-read', 'bucket-owner-full-control',
180 'public-read-write']
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700181 if acl in CANNED_ACLS:
David James9374aac2013-10-08 16:00:17 -0700182 gs_context.Copy(local_file, remote_file, acl=acl)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700183 else:
184 # For private uploads we assume that the overlay board is set up properly
David James015af872012-06-19 15:24:36 -0700185 # and a googlestore_acl.xml is present. Otherwise, this script errors.
David James9374aac2013-10-08 16:00:17 -0700186 gs_context.Copy(local_file, remote_file, acl='private')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700187 # Apply the passed in ACL xml file to the uploaded object.
David James9374aac2013-10-08 16:00:17 -0700188 gs_context.SetACL(remote_file, acl=acl)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700189
Mike Frysingercc838832014-05-24 13:10:30 -0400190
Mike Frysinger540883b2014-05-24 13:46:16 -0400191def RemoteUpload(gs_context, acl, files, pool=10):
David James8c846492011-01-25 17:07:29 -0800192 """Upload to google storage.
193
194 Create a pool of process and call _GsUpload with the proper arguments.
195
196 Args:
Mike Frysinger540883b2014-05-24 13:46:16 -0400197 gs_context: A lib.gs.GSContext instance.
David Jamesfd0b0852011-02-23 11:15:36 -0800198 acl: The canned acl used for uploading. acl can be one of: "public-read",
199 "public-read-write", "authenticated-read", "bucket-owner-read",
200 "bucket-owner-full-control", or "private".
David James8c846492011-01-25 17:07:29 -0800201 files: dictionary with keys to local files and values to remote path.
202 pool: integer of maximum proesses to have at the same time.
203
204 Returns:
205 Return a set of tuple arguments of the failed uploads
206 """
Mike Frysinger540883b2014-05-24 13:46:16 -0400207 upload = functools.partial(_GsUpload, gs_context, acl)
208 tasks = [[key, value] for key, value in files.iteritems()]
209 parallel.RunTasksInProcessPool(upload, tasks, pool)
David James8c846492011-01-25 17:07:29 -0800210
211
212def GenerateUploadDict(base_local_path, base_remote_path, pkgs):
213 """Build a dictionary of local remote file key pairs to upload.
214
215 Args:
216 base_local_path: The base path to the files on the local hard drive.
Matt Tennante8179042013-10-01 15:47:32 -0700217 base_remote_path: The base path to the remote paths.
David James8c846492011-01-25 17:07:29 -0800218 pkgs: The packages to upload.
219
220 Returns:
221 Returns a dictionary of local_path/remote_path pairs
222 """
223 upload_files = {}
224 for pkg in pkgs:
225 suffix = pkg['CPV'] + '.tbz2'
226 local_path = os.path.join(base_local_path, suffix)
227 assert os.path.exists(local_path)
228 remote_path = '%s/%s' % (base_remote_path.rstrip('/'), suffix)
229 upload_files[local_path] = remote_path
230
231 return upload_files
232
Mike Frysingercc838832014-05-24 13:10:30 -0400233
Peter Mayo950e41a2014-02-06 21:07:33 +0000234def GetBoardOverlay(build_path, target):
David Jamese5867812012-10-19 12:02:20 -0700235 """Get the path to the board variant.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500236
David James8c846492011-01-25 17:07:29 -0800237 Args:
238 build_path: The path to the root of the build directory
David Jamese5867812012-10-19 12:02:20 -0700239 target: The target board as a BuildTarget object.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500240
David James8c846492011-01-25 17:07:29 -0800241 Returns:
David Jamese5867812012-10-19 12:02:20 -0700242 The last overlay configured for the given board as a string.
David James8c846492011-01-25 17:07:29 -0800243 """
David Jamese5867812012-10-19 12:02:20 -0700244 board = target.board_variant
245 overlays = portage_utilities.FindOverlays(constants.BOTH_OVERLAYS, board,
246 buildroot=build_path)
247 # We only care about the last entry.
248 return overlays[-1]
David James8c846492011-01-25 17:07:29 -0800249
250
251def DeterminePrebuiltConfFile(build_path, target):
252 """Determine the prebuilt.conf file that needs to be updated for prebuilts.
253
Mike Frysinger1a736a82013-12-12 01:50:59 -0500254 Args:
255 build_path: The path to the root of the build directory
256 target: String representation of the board. This includes host and board
257 targets
David James8c846492011-01-25 17:07:29 -0800258
Mike Frysinger1a736a82013-12-12 01:50:59 -0500259 Returns:
260 A string path to a prebuilt.conf file to be updated.
David James8c846492011-01-25 17:07:29 -0800261 """
David James4058b0d2011-12-08 21:24:50 -0800262 if _HOST_ARCH == target:
David James8c846492011-01-25 17:07:29 -0800263 # We are host.
264 # Without more examples of hosts this is a kludge for now.
265 # TODO(Scottz): as new host targets come online expand this to
266 # work more like boards.
Chris Sosa471532a2011-02-01 15:10:06 -0800267 make_path = _PREBUILT_MAKE_CONF[target]
David James8c846492011-01-25 17:07:29 -0800268 else:
269 # We are a board
Peter Mayo950e41a2014-02-06 21:07:33 +0000270 board = GetBoardOverlay(build_path, target)
David James8c846492011-01-25 17:07:29 -0800271 make_path = os.path.join(board, 'prebuilt.conf')
272
273 return make_path
274
275
276def UpdateBinhostConfFile(path, key, value):
277 """Update binhost config file file with key=value.
278
279 Args:
280 path: Filename to update.
281 key: Key to update.
282 value: New value for key.
283 """
284 cwd = os.path.dirname(os.path.abspath(path))
285 filename = os.path.basename(path)
Brian Harringaf019fb2012-05-10 15:06:13 -0700286 osutils.SafeMakedirs(cwd)
David Jamesf6e8fb72013-05-10 08:58:43 -0700287 if not git.GetCurrentBranch(cwd):
288 git.CreatePushBranch(constants.STABLE_EBUILD_BRANCH, cwd, sync=False)
Brian Harring22edb442012-05-11 23:55:18 -0700289 osutils.WriteFile(path, '', mode='a')
David James8c846492011-01-25 17:07:29 -0800290 UpdateLocalFile(path, value, key)
David James67d73252013-09-19 17:33:12 -0700291 git.RunGit(cwd, ['add', filename])
Mike Frysinger109cada2013-01-17 15:50:44 -0500292 description = '%s: updating %s' % (os.path.basename(filename), key)
David James67d73252013-09-19 17:33:12 -0700293 git.RunGit(cwd, ['commit', '-m', description])
David James8c846492011-01-25 17:07:29 -0800294
295
David Jamesce093af2011-02-23 15:21:58 -0800296def _GrabAllRemotePackageIndexes(binhost_urls):
David James05bcb2b2011-02-09 09:25:47 -0800297 """Grab all of the packages files associated with a list of binhost_urls.
298
David James05bcb2b2011-02-09 09:25:47 -0800299 Args:
300 binhost_urls: The URLs for the directories containing the Packages files we
301 want to grab.
David James05bcb2b2011-02-09 09:25:47 -0800302
303 Returns:
304 A list of PackageIndex objects.
305 """
306 pkg_indexes = []
307 for url in binhost_urls:
David James32faafe2012-06-08 14:25:03 -0700308 pkg_index = binpkg.GrabRemotePackageIndex(url)
David James05bcb2b2011-02-09 09:25:47 -0800309 if pkg_index:
310 pkg_indexes.append(pkg_index)
David James05bcb2b2011-02-09 09:25:47 -0800311 return pkg_indexes
312
313
David Jamesc0f158a2011-02-22 16:07:29 -0800314class PrebuiltUploader(object):
315 """Synchronize host and board prebuilts."""
David James8c846492011-01-25 17:07:29 -0800316
Mike Frysinger86509232014-05-24 13:18:37 -0400317 def __init__(self, upload_location, acl, binhost_base_url, pkg_indexes,
318 build_path, packages, skip_upload, binhost_conf_dir, dryrun,
Mike Frysinger8092a632014-05-24 13:25:46 -0400319 target, slave_targets, version):
David Jamesc0f158a2011-02-22 16:07:29 -0800320 """Constructor for prebuilt uploader object.
David James8c846492011-01-25 17:07:29 -0800321
David Jamesc0f158a2011-02-22 16:07:29 -0800322 This object can upload host or prebuilt files to Google Storage.
David James8c846492011-01-25 17:07:29 -0800323
David Jamesc0f158a2011-02-22 16:07:29 -0800324 Args:
325 upload_location: The upload location.
David Jamesfd0b0852011-02-23 11:15:36 -0800326 acl: The canned acl used for uploading to Google Storage. acl can be one
327 of: "public-read", "public-read-write", "authenticated-read",
Matt Tennante8179042013-10-01 15:47:32 -0700328 "bucket-owner-read", "bucket-owner-full-control", "project-private",
329 or "private" (see "gsutil help acls"). If we are not uploading to
330 Google Storage, this parameter is unused.
David Jamesfd0b0852011-02-23 11:15:36 -0800331 binhost_base_url: The URL used for downloading the prebuilts.
David Jamesc0f158a2011-02-22 16:07:29 -0800332 pkg_indexes: Old uploaded prebuilts to compare against. Instead of
333 uploading duplicate files, we just link to the old files.
David James615e5b52011-06-03 11:10:15 -0700334 build_path: The path to the directory containing the chroot.
335 packages: Packages to upload.
David James32b0b2f2011-07-13 20:56:50 -0700336 skip_upload: Don't actually upload the tarballs.
337 binhost_conf_dir: Directory where to store binhost.conf files.
Mike Frysinger86509232014-05-24 13:18:37 -0400338 dryrun: Don't push or upload prebuilts.
David James4058b0d2011-12-08 21:24:50 -0800339 target: BuildTarget managed by this builder.
340 slave_targets: List of BuildTargets managed by slave builders.
Mike Frysinger8092a632014-05-24 13:25:46 -0400341 version: A unique string, intended to be included in the upload path,
342 which identifies the version number of the uploaded prebuilts.
David Jamesc0f158a2011-02-22 16:07:29 -0800343 """
344 self._upload_location = upload_location
David Jamesfd0b0852011-02-23 11:15:36 -0800345 self._acl = acl
David Jamesc0f158a2011-02-22 16:07:29 -0800346 self._binhost_base_url = binhost_base_url
347 self._pkg_indexes = pkg_indexes
David James615e5b52011-06-03 11:10:15 -0700348 self._build_path = build_path
349 self._packages = set(packages)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500350 self._found_packages = set()
David James8ece7ee2011-06-29 16:02:30 -0700351 self._skip_upload = skip_upload
David James32b0b2f2011-07-13 20:56:50 -0700352 self._binhost_conf_dir = binhost_conf_dir
Mike Frysinger86509232014-05-24 13:18:37 -0400353 self._dryrun = dryrun
David James4058b0d2011-12-08 21:24:50 -0800354 self._target = target
355 self._slave_targets = slave_targets
Mike Frysinger8092a632014-05-24 13:25:46 -0400356 self._version = version
Mike Frysinger540883b2014-05-24 13:46:16 -0400357 self._gs_context = gs.GSContext(retries=_RETRIES, sleep=_SLEEP_TIME,
358 dry_run=self._dryrun)
359
360 def _Upload(self, local_file, remote_file):
361 """Wrapper around _GsUpload"""
362 _GsUpload(self._gs_context, self._acl, local_file, remote_file)
David James615e5b52011-06-03 11:10:15 -0700363
364 def _ShouldFilterPackage(self, pkg):
365 if not self._packages:
366 return False
367 pym_path = os.path.abspath(os.path.join(self._build_path, _PYM_PATH))
David James710b7dc2012-02-07 16:49:59 -0800368 sys.path.insert(0, pym_path)
Don Garrett25f309a2014-03-19 14:02:12 -0700369 # pylint: disable=F0401
David James615e5b52011-06-03 11:10:15 -0700370 import portage.versions
371 cat, pkgname = portage.versions.catpkgsplit(pkg['CPV'])[0:2]
372 cp = '%s/%s' % (cat, pkgname)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500373 self._found_packages.add(cp)
David James615e5b52011-06-03 11:10:15 -0700374 return pkgname not in self._packages and cp not in self._packages
David James8c846492011-01-25 17:07:29 -0800375
David Jamesc0f158a2011-02-22 16:07:29 -0800376 def _UploadPrebuilt(self, package_path, url_suffix):
377 """Upload host or board prebuilt files to Google Storage space.
David James8c846492011-01-25 17:07:29 -0800378
David Jamesc0f158a2011-02-22 16:07:29 -0800379 Args:
380 package_path: The path to the packages dir.
David Jamesce093af2011-02-23 15:21:58 -0800381 url_suffix: The remote subdirectory where we should upload the packages.
David Jamesc0f158a2011-02-22 16:07:29 -0800382 """
David Jamesc0f158a2011-02-22 16:07:29 -0800383 # Process Packages file, removing duplicates and filtered packages.
David James32faafe2012-06-08 14:25:03 -0700384 pkg_index = binpkg.GrabLocalPackageIndex(package_path)
David Jamesc0f158a2011-02-22 16:07:29 -0800385 pkg_index.SetUploadLocation(self._binhost_base_url, url_suffix)
David James615e5b52011-06-03 11:10:15 -0700386 pkg_index.RemoveFilteredPackages(self._ShouldFilterPackage)
David Jamesc0f158a2011-02-22 16:07:29 -0800387 uploads = pkg_index.ResolveDuplicateUploads(self._pkg_indexes)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500388 unmatched_pkgs = self._packages - self._found_packages
389 if unmatched_pkgs:
390 cros_build_lib.Warning('unable to match packages: %r' % unmatched_pkgs)
David James05bcb2b2011-02-09 09:25:47 -0800391
David Jamesc0f158a2011-02-22 16:07:29 -0800392 # Write Packages file.
393 tmp_packages_file = pkg_index.WriteToNamedTemporaryFile()
David James05bcb2b2011-02-09 09:25:47 -0800394
David Jamesc0f158a2011-02-22 16:07:29 -0800395 remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
David James015af872012-06-19 15:24:36 -0700396 assert remote_location.startswith('gs://')
David James05bcb2b2011-02-09 09:25:47 -0800397
David James015af872012-06-19 15:24:36 -0700398 # Build list of files to upload.
399 upload_files = GenerateUploadDict(package_path, remote_location, uploads)
400 remote_file = '%s/Packages' % remote_location.rstrip('/')
401 upload_files[tmp_packages_file.name] = remote_file
402
Mike Frysinger540883b2014-05-24 13:46:16 -0400403 RemoteUpload(self._gs_context, self._acl, upload_files)
David James8c846492011-01-25 17:07:29 -0800404
Mike Frysinger8092a632014-05-24 13:25:46 -0400405 def _UploadSdkTarball(self, board_path, url_suffix, prepackaged,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500406 toolchain_tarballs, toolchain_upload_path):
407 """Upload a tarball of the sdk at the specified path to Google Storage.
David James8fa34ea2011-04-15 13:00:20 -0700408
409 Args:
410 board_path: The path to the board dir.
411 url_suffix: The remote subdirectory where we should upload the packages.
Zdenek Behan62a57792012-08-31 15:09:08 +0200412 prepackaged: If given, a tarball that has been packaged outside of this
413 script and should be used.
Mike Frysinger9e979b92012-11-29 02:55:09 -0500414 toolchain_tarballs: List of toolchain tarballs to upload.
415 toolchain_upload_path: Path under the bucket to place toolchain tarballs.
David James8fa34ea2011-04-15 13:00:20 -0700416 """
417 remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
418 assert remote_location.startswith('gs://')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200419 boardname = os.path.basename(board_path.rstrip('/'))
420 # We do not upload non SDK board tarballs,
421 assert boardname == constants.CHROOT_BUILDER_BOARD
422 assert prepackaged is not None
Zdenek Behan62a57792012-08-31 15:09:08 +0200423
Mike Frysinger8092a632014-05-24 13:25:46 -0400424 version_str = self._version[len('chroot-'):]
Mike Frysinger8e727a32013-01-16 16:57:53 -0500425 remote_tarfile = toolchain.GetSdkURL(
426 for_gsutil=True, suburl='cros-sdk-%s.tar.xz' % (version_str,))
Zdenek Behan86c15e92012-10-13 00:55:47 +0200427 # For SDK, also upload the manifest which is guaranteed to exist
428 # by the builderstage.
Mike Frysinger540883b2014-05-24 13:46:16 -0400429 self._Upload(prepackaged + '.Manifest', remote_tarfile + '.Manifest')
430 self._Upload(prepackaged, remote_tarfile)
Zdenek Behan86c15e92012-10-13 00:55:47 +0200431
Mike Frysinger9e979b92012-11-29 02:55:09 -0500432 # Post the toolchain tarballs too.
433 for tarball in toolchain_tarballs:
434 target, local_path = tarball.split(':')
435 suburl = toolchain_upload_path % {'target': target}
436 remote_path = toolchain.GetSdkURL(for_gsutil=True, suburl=suburl)
Mike Frysinger540883b2014-05-24 13:46:16 -0400437 self._Upload(local_path, remote_path)
Mike Frysinger9e979b92012-11-29 02:55:09 -0500438
Zdenek Behan86c15e92012-10-13 00:55:47 +0200439 # Finally, also update the pointer to the latest SDK on which polling
440 # scripts rely.
David James4bc13702013-03-26 08:08:04 -0700441 with osutils.TempDir() as tmpdir:
Zdenek Behan86c15e92012-10-13 00:55:47 +0200442 pointerfile = os.path.join(tmpdir, 'cros-sdk-latest.conf')
Mike Frysinger8e727a32013-01-16 16:57:53 -0500443 remote_pointerfile = toolchain.GetSdkURL(for_gsutil=True,
444 suburl='cros-sdk-latest.conf')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200445 osutils.WriteFile(pointerfile, 'LATEST_SDK="%s"' % version_str)
Mike Frysinger540883b2014-05-24 13:46:16 -0400446 self._Upload(pointerfile, remote_pointerfile)
Zdenek Behan33a34112012-09-10 21:07:51 +0200447
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700448 def _GetTargets(self):
449 """Retuns the list of targets to use."""
450 targets = self._slave_targets[:]
451 if self._target:
452 targets.append(self._target)
453
454 return targets
455
Mike Frysinger8092a632014-05-24 13:25:46 -0400456 def SyncHostPrebuilts(self, key, git_sync, sync_binhost_conf):
David Jamesc0f158a2011-02-22 16:07:29 -0800457 """Synchronize host prebuilt files.
David James05bcb2b2011-02-09 09:25:47 -0800458
David Jamesc0f158a2011-02-22 16:07:29 -0800459 This function will sync both the standard host packages, plus the host
460 packages associated with all targets that have been "setup" with the
461 current host's chroot. For instance, if this host has been used to build
462 x86-generic, it will sync the host packages associated with
463 'i686-pc-linux-gnu'. If this host has also been used to build arm-generic,
464 it will also sync the host packages associated with
465 'armv7a-cros-linux-gnueabi'.
David James05bcb2b2011-02-09 09:25:47 -0800466
David Jamesc0f158a2011-02-22 16:07:29 -0800467 Args:
David Jamesc0f158a2011-02-22 16:07:29 -0800468 key: The variable key to update in the git file.
469 git_sync: If set, update make.conf of target to reference the latest
470 prebuilt packages generated here.
471 sync_binhost_conf: If set, update binhost config file in
472 chromiumos-overlay for the host.
473 """
David Jamese2488642011-11-14 16:15:20 -0800474 # Slave boards are listed before the master board so that the master board
475 # takes priority (i.e. x86-generic preflight host prebuilts takes priority
476 # over preflight host prebuilts from other builders.)
477 binhost_urls = []
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700478 for target in self._GetTargets():
Mike Frysinger8092a632014-05-24 13:25:46 -0400479 url_suffix = _REL_HOST_PATH % {'version': self._version,
David James4058b0d2011-12-08 21:24:50 -0800480 'host_arch': _HOST_ARCH,
481 'target': target}
David Jamese2488642011-11-14 16:15:20 -0800482 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David James05bcb2b2011-02-09 09:25:47 -0800483
Mike Frysinger540883b2014-05-24 13:46:16 -0400484 if self._target == target and not self._skip_upload:
David Jamese2488642011-11-14 16:15:20 -0800485 # Upload prebuilts.
486 package_path = os.path.join(self._build_path, _HOST_PACKAGES_PATH)
487 self._UploadPrebuilt(package_path, packages_url_suffix)
David James8ece7ee2011-06-29 16:02:30 -0700488
David Jamese2488642011-11-14 16:15:20 -0800489 # Record URL where prebuilts were uploaded.
490 binhost_urls.append('%s/%s/' % (self._binhost_base_url.rstrip('/'),
491 packages_url_suffix.rstrip('/')))
492
David James20b2b6f2011-11-18 15:11:58 -0800493 binhost = ' '.join(binhost_urls)
David James8ece7ee2011-06-29 16:02:30 -0700494 if git_sync:
495 git_file = os.path.join(self._build_path,
David James4058b0d2011-12-08 21:24:50 -0800496 _PREBUILT_MAKE_CONF[_HOST_ARCH])
Mike Frysinger86509232014-05-24 13:18:37 -0400497 RevGitFile(git_file, {key: binhost}, dryrun=self._dryrun)
David James8ece7ee2011-06-29 16:02:30 -0700498 if sync_binhost_conf:
David James32b0b2f2011-07-13 20:56:50 -0700499 binhost_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James4058b0d2011-12-08 21:24:50 -0800500 'host', '%s-%s.conf' % (_HOST_ARCH, key))
David Jamese2488642011-11-14 16:15:20 -0800501 UpdateBinhostConfFile(binhost_conf, key, binhost)
David Jamesc0f158a2011-02-22 16:07:29 -0800502
Mike Frysinger8092a632014-05-24 13:25:46 -0400503 def SyncBoardPrebuilts(self, key, git_sync, sync_binhost_conf,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500504 upload_board_tarball, prepackaged_board,
505 toolchain_tarballs, toolchain_upload_path):
David Jamesc0f158a2011-02-22 16:07:29 -0800506 """Synchronize board prebuilt files.
507
508 Args:
David Jamesc0f158a2011-02-22 16:07:29 -0800509 key: The variable key to update in the git file.
510 git_sync: If set, update make.conf of target to reference the latest
511 prebuilt packages generated here.
512 sync_binhost_conf: If set, update binhost config file in
513 chromiumos-overlay for the current board.
David James8fa34ea2011-04-15 13:00:20 -0700514 upload_board_tarball: Include a tarball of the board in our upload.
Zdenek Behan62a57792012-08-31 15:09:08 +0200515 prepackaged_board: A tarball of the board built outside of this script.
Mike Frysinger9e979b92012-11-29 02:55:09 -0500516 toolchain_tarballs: A list of toolchain tarballs to upload.
517 toolchain_upload_path: Path under the bucket to place toolchain tarballs.
David Jamesc0f158a2011-02-22 16:07:29 -0800518 """
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700519 for target in self._GetTargets():
David Jamese2488642011-11-14 16:15:20 -0800520 board_path = os.path.join(self._build_path,
David James4058b0d2011-12-08 21:24:50 -0800521 _BOARD_PATH % {'board': target.board_variant})
David Jamese2488642011-11-14 16:15:20 -0800522 package_path = os.path.join(board_path, 'packages')
Mike Frysinger8092a632014-05-24 13:25:46 -0400523 url_suffix = _REL_BOARD_PATH % {'target': target,
524 'version': self._version}
David Jamese2488642011-11-14 16:15:20 -0800525 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David James8fa34ea2011-04-15 13:00:20 -0700526
Matt Tennante8179042013-10-01 15:47:32 -0700527 # Process the target board differently if it is the main --board.
Mike Frysinger540883b2014-05-24 13:46:16 -0400528 if self._target == target and not self._skip_upload:
Matt Tennante8179042013-10-01 15:47:32 -0700529 # This strips "chroot" prefix because that is sometimes added as the
530 # --prepend-version argument (e.g. by chromiumos-sdk bot).
531 # TODO(build): Clean it up to be less hard-coded.
Mike Frysinger8092a632014-05-24 13:25:46 -0400532 version_str = self._version[len('chroot-'):]
Mike Frysinger9e979b92012-11-29 02:55:09 -0500533
David Jamese2488642011-11-14 16:15:20 -0800534 # Upload board tarballs in the background.
535 if upload_board_tarball:
Mike Frysinger9e979b92012-11-29 02:55:09 -0500536 if toolchain_upload_path:
537 toolchain_upload_path %= {'version': version_str}
538 tar_process = multiprocessing.Process(
539 target=self._UploadSdkTarball,
Mike Frysinger8092a632014-05-24 13:25:46 -0400540 args=(board_path, url_suffix, prepackaged_board,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500541 toolchain_tarballs, toolchain_upload_path))
David Jamese2488642011-11-14 16:15:20 -0800542 tar_process.start()
David James8fa34ea2011-04-15 13:00:20 -0700543
David Jamese2488642011-11-14 16:15:20 -0800544 # Upload prebuilts.
545 self._UploadPrebuilt(package_path, packages_url_suffix)
David James8fa34ea2011-04-15 13:00:20 -0700546
David Jamese2488642011-11-14 16:15:20 -0800547 # Make sure we finished uploading the board tarballs.
548 if upload_board_tarball:
549 tar_process.join()
550 assert tar_process.exitcode == 0
551 # TODO(zbehan): This should be done cleaner.
Zdenek Behan33a34112012-09-10 21:07:51 +0200552 if target.board == constants.CHROOT_BUILDER_BOARD:
David Jamese2488642011-11-14 16:15:20 -0800553 sdk_conf = os.path.join(self._build_path, self._binhost_conf_dir,
Mike Frysinger5b34d732013-01-17 15:11:58 -0500554 'host/sdk_version.conf')
555 sdk_settings = {
Mike Frysinger9e979b92012-11-29 02:55:09 -0500556 'SDK_LATEST_VERSION': version_str,
557 'TC_PATH': toolchain_upload_path,
Mike Frysinger5b34d732013-01-17 15:11:58 -0500558 }
Mike Frysinger86509232014-05-24 13:18:37 -0400559 RevGitFile(sdk_conf, sdk_settings, dryrun=self._dryrun)
David Jamesc0f158a2011-02-22 16:07:29 -0800560
David Jamese2488642011-11-14 16:15:20 -0800561 # Record URL where prebuilts were uploaded.
562 url_value = '%s/%s/' % (self._binhost_base_url.rstrip('/'),
563 packages_url_suffix.rstrip('/'))
564
565 if git_sync:
David James4058b0d2011-12-08 21:24:50 -0800566 git_file = DeterminePrebuiltConfFile(self._build_path, target)
Mike Frysinger86509232014-05-24 13:18:37 -0400567 RevGitFile(git_file, {key: url_value}, dryrun=self._dryrun)
Matt Tennante8179042013-10-01 15:47:32 -0700568
David Jamese2488642011-11-14 16:15:20 -0800569 if sync_binhost_conf:
Matt Tennante8179042013-10-01 15:47:32 -0700570 # Update the binhost configuration file in git.
David Jamese2488642011-11-14 16:15:20 -0800571 binhost_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James4058b0d2011-12-08 21:24:50 -0800572 'target', '%s-%s.conf' % (target, key))
David Jamese2488642011-11-14 16:15:20 -0800573 UpdateBinhostConfFile(binhost_conf, key, url_value)
David James05bcb2b2011-02-09 09:25:47 -0800574
575
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700576def _AddSlaveBoard(_option, _opt_str, value, parser):
577 """Callback that adds a slave board to the list of slave targets."""
David James4058b0d2011-12-08 21:24:50 -0800578 parser.values.slave_targets.append(BuildTarget(value))
579
580
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700581def _AddSlaveProfile(_option, _opt_str, value, parser):
582 """Callback that adds a slave profile to the list of slave targets."""
David James4058b0d2011-12-08 21:24:50 -0800583 if not parser.values.slave_targets:
Mike Frysinger86509232014-05-24 13:18:37 -0400584 parser.error('Must specify --slave-board before --slave-profile')
David James4058b0d2011-12-08 21:24:50 -0800585 if parser.values.slave_targets[-1].profile is not None:
Mike Frysinger86509232014-05-24 13:18:37 -0400586 parser.error('Cannot specify --slave-profile twice for same board')
David James4058b0d2011-12-08 21:24:50 -0800587 parser.values.slave_targets[-1].profile = value
588
589
Mike Frysinger86509232014-05-24 13:18:37 -0400590def ParseOptions(argv):
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700591 """Returns options given by the user and the target specified.
592
Mike Frysinger86509232014-05-24 13:18:37 -0400593 Args:
594 argv: The args to parse.
595
Mike Frysinger1a736a82013-12-12 01:50:59 -0500596 Returns:
597 A tuple containing a parsed options object and BuildTarget.
598 The target instance is None if no board is specified.
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700599 """
Mike Frysinger86509232014-05-24 13:18:37 -0400600 parser = commandline.OptionParser()
David James8c846492011-01-25 17:07:29 -0800601 parser.add_option('-H', '--binhost-base-url', dest='binhost_base_url',
602 default=_BINHOST_BASE_URL,
603 help='Base URL to use for binhost in make.conf updates')
604 parser.add_option('', '--previous-binhost-url', action='append',
605 default=[], dest='previous_binhost_url',
606 help='Previous binhost URL')
607 parser.add_option('-b', '--board', dest='board', default=None,
608 help='Board type that was built on this machine')
Zdenek Behan62a57792012-08-31 15:09:08 +0200609 parser.add_option('-B', '--prepackaged-tarball', dest='prepackaged_tarball',
610 default=None,
611 help='Board tarball prebuilt outside of this script.')
Mike Frysinger9e979b92012-11-29 02:55:09 -0500612 parser.add_option('--toolchain-tarball', dest='toolchain_tarballs',
613 action='append', default=[],
614 help='Redistributable toolchain tarball.')
615 parser.add_option('--toolchain-upload-path', default='',
616 help='Path to place toolchain tarballs in the sdk tree.')
David James4058b0d2011-12-08 21:24:50 -0800617 parser.add_option('', '--profile', dest='profile', default=None,
618 help='Profile that was built on this machine')
619 parser.add_option('', '--slave-board', default=[], action='callback',
620 dest='slave_targets', type='string',
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700621 callback=_AddSlaveBoard,
David James4058b0d2011-12-08 21:24:50 -0800622 help='Board type that was built on a slave machine. To '
623 'add a profile to this board, use --slave-profile.')
624 parser.add_option('', '--slave-profile', action='callback', type='string',
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700625 callback=_AddSlaveProfile,
David James4058b0d2011-12-08 21:24:50 -0800626 help='Board profile that was built on a slave machine. '
627 'Applies to previous slave board.')
David James8c846492011-01-25 17:07:29 -0800628 parser.add_option('-p', '--build-path', dest='build_path',
David James05bcb2b2011-02-09 09:25:47 -0800629 help='Path to the directory containing the chroot')
David James615e5b52011-06-03 11:10:15 -0700630 parser.add_option('', '--packages', action='append',
631 default=[], dest='packages',
632 help='Only include the specified packages. '
633 '(Default is to include all packages.)')
David James8c846492011-01-25 17:07:29 -0800634 parser.add_option('-s', '--sync-host', dest='sync_host',
635 default=False, action='store_true',
636 help='Sync host prebuilts')
637 parser.add_option('-g', '--git-sync', dest='git_sync',
638 default=False, action='store_true',
David Jamese2488642011-11-14 16:15:20 -0800639 help='Enable git version sync (This commits to a repo.) '
640 'This is used by full builders to commit directly '
641 'to board overlays.')
David James8c846492011-01-25 17:07:29 -0800642 parser.add_option('-u', '--upload', dest='upload',
643 default=None,
644 help='Upload location')
645 parser.add_option('-V', '--prepend-version', dest='prepend_version',
646 default=None,
647 help='Add an identifier to the front of the version')
648 parser.add_option('-f', '--filters', dest='filters', action='store_true',
649 default=False,
650 help='Turn on filtering of private ebuild packages')
651 parser.add_option('-k', '--key', dest='key',
652 default='PORTAGE_BINHOST',
653 help='Key to update in make.conf / binhost.conf')
David James8ece7ee2011-06-29 16:02:30 -0700654 parser.add_option('', '--set-version', dest='set_version',
655 default=None,
656 help='Specify the version string')
David James8c846492011-01-25 17:07:29 -0800657 parser.add_option('', '--sync-binhost-conf', dest='sync_binhost_conf',
658 default=False, action='store_true',
David Jamese2488642011-11-14 16:15:20 -0800659 help='Update binhost.conf in chromiumos-overlay or '
660 'chromeos-overlay. Commit the changes, but don\'t '
661 'push them. This is used for preflight binhosts.')
David James32b0b2f2011-07-13 20:56:50 -0700662 parser.add_option('', '--binhost-conf-dir', dest='binhost_conf_dir',
663 default=_BINHOST_CONF_DIR,
664 help='Directory to commit binhost config with '
665 '--sync-binhost-conf.')
David Jamesfd0b0852011-02-23 11:15:36 -0800666 parser.add_option('-P', '--private', dest='private', action='store_true',
667 default=False, help='Mark gs:// uploads as private.')
David James8ece7ee2011-06-29 16:02:30 -0700668 parser.add_option('', '--skip-upload', dest='skip_upload',
669 action='store_true', default=False,
670 help='Skip upload step.')
David James8fa34ea2011-04-15 13:00:20 -0700671 parser.add_option('', '--upload-board-tarball', dest='upload_board_tarball',
672 action='store_true', default=False,
673 help='Upload board tarball to Google Storage.')
Mike Frysinger86509232014-05-24 13:18:37 -0400674 parser.add_option('-n', '--dry-run', dest='dryrun',
David James27fa7d12011-06-29 17:24:14 -0700675 action='store_true', default=False,
676 help='Don\'t push or upload prebuilts.')
David James8c846492011-01-25 17:07:29 -0800677
Mike Frysinger86509232014-05-24 13:18:37 -0400678 options, args = parser.parse_args(argv)
David James8c846492011-01-25 17:07:29 -0800679 if not options.build_path:
Mike Frysinger86509232014-05-24 13:18:37 -0400680 parser.error('you need provide a chroot path')
David James8ece7ee2011-06-29 16:02:30 -0700681 if not options.upload and not options.skip_upload:
Mike Frysinger86509232014-05-24 13:18:37 -0400682 parser.error('you need to provide an upload location using -u')
David James8ece7ee2011-06-29 16:02:30 -0700683 if not options.set_version and options.skip_upload:
Mike Frysinger86509232014-05-24 13:18:37 -0400684 parser.error('If you are using --skip-upload, you must specify a '
685 'version number using --set-version.')
David James9417f272011-05-26 13:24:47 -0700686 if args:
Mike Frysinger86509232014-05-24 13:18:37 -0400687 parser.error('invalid arguments passed to upload_prebuilts: %r' % args)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700688
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700689 target = None
690 if options.board:
691 target = BuildTarget(options.board, options.profile)
692
693 if target in options.slave_targets:
Mike Frysinger86509232014-05-24 13:18:37 -0400694 parser.error('--board/--profile must not also be a slave target.')
David Jamese2488642011-11-14 16:15:20 -0800695
David James4058b0d2011-12-08 21:24:50 -0800696 if len(set(options.slave_targets)) != len(options.slave_targets):
Mike Frysinger86509232014-05-24 13:18:37 -0400697 parser.error('--slave-boards must not have duplicates.')
David Jamese2488642011-11-14 16:15:20 -0800698
David James4058b0d2011-12-08 21:24:50 -0800699 if options.slave_targets and options.git_sync:
Mike Frysinger86509232014-05-24 13:18:37 -0400700 parser.error('--slave-boards is not compatible with --git-sync')
David Jamese2488642011-11-14 16:15:20 -0800701
David James8ece7ee2011-06-29 16:02:30 -0700702 if (options.upload_board_tarball and options.skip_upload and
703 options.board == 'amd64-host'):
Mike Frysinger86509232014-05-24 13:18:37 -0400704 parser.error('--skip-upload is not compatible with '
705 '--upload-board-tarball and --board=amd64-host')
David James8fa34ea2011-04-15 13:00:20 -0700706
David James8ece7ee2011-06-29 16:02:30 -0700707 if (options.upload_board_tarball and not options.skip_upload and
708 not options.upload.startswith('gs://')):
Mike Frysinger86509232014-05-24 13:18:37 -0400709 parser.error('--upload-board-tarball only works with gs:// URLs.\n'
710 '--upload must be a gs:// URL.')
David James8fa34ea2011-04-15 13:00:20 -0700711
Zdenek Behan86c15e92012-10-13 00:55:47 +0200712 if options.upload_board_tarball and options.prepackaged_tarball is None:
Mike Frysinger86509232014-05-24 13:18:37 -0400713 parser.error('--upload-board-tarball requires --prepackaged-tarball')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200714
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700715 if options.private:
716 if options.sync_host:
Mike Frysinger86509232014-05-24 13:18:37 -0400717 parser.error('--private and --sync-host/-s cannot be specified '
718 'together; we do not support private host prebuilts')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700719
David James8ece7ee2011-06-29 16:02:30 -0700720 if not options.upload or not options.upload.startswith('gs://'):
Mike Frysinger86509232014-05-24 13:18:37 -0400721 parser.error('--private is only valid for gs:// URLs; '
722 '--upload must be a gs:// URL.')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700723
724 if options.binhost_base_url != _BINHOST_BASE_URL:
Mike Frysinger86509232014-05-24 13:18:37 -0400725 parser.error('when using --private the --binhost-base-url '
726 'is automatically derived.')
David James27fa7d12011-06-29 17:24:14 -0700727
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700728 return options, target
David Jamesc0f158a2011-02-22 16:07:29 -0800729
Mike Frysingercc838832014-05-24 13:10:30 -0400730
Mike Frysinger86509232014-05-24 13:18:37 -0400731def main(argv):
David Jamesdb401072011-06-10 12:17:16 -0700732 # Set umask to a sane value so that files created as root are readable.
Mike Frysinger60ec1012013-10-21 00:11:10 -0400733 os.umask(0o22)
David Jamesdb401072011-06-10 12:17:16 -0700734
Mike Frysinger86509232014-05-24 13:18:37 -0400735 options, target = ParseOptions(argv)
David Jamesc0f158a2011-02-22 16:07:29 -0800736
David James05bcb2b2011-02-09 09:25:47 -0800737 # Calculate a list of Packages index files to compare against. Whenever we
738 # upload a package, we check to make sure it's not already stored in one of
739 # the packages files we uploaded. This list of packages files might contain
740 # both board and host packages.
David Jamesce093af2011-02-23 15:21:58 -0800741 pkg_indexes = _GrabAllRemotePackageIndexes(options.previous_binhost_url)
David James8c846492011-01-25 17:07:29 -0800742
David James8ece7ee2011-06-29 16:02:30 -0700743 if options.set_version:
744 version = options.set_version
745 else:
746 version = GetVersion()
Matt Tennante8179042013-10-01 15:47:32 -0700747
David Jamesc0f158a2011-02-22 16:07:29 -0800748 if options.prepend_version:
749 version = '%s-%s' % (options.prepend_version, version)
750
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700751 acl = 'public-read'
752 binhost_base_url = options.binhost_base_url
753
David Jamesadd21432013-05-21 10:04:07 -0700754 if options.private:
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700755 binhost_base_url = options.upload
David Jamesadd21432013-05-21 10:04:07 -0700756 if target:
Peter Mayo950e41a2014-02-06 21:07:33 +0000757 board_path = GetBoardOverlay(options.build_path, target)
David Jamesadd21432013-05-21 10:04:07 -0700758 acl = os.path.join(board_path, _GOOGLESTORAGE_ACL_FILE)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700759
760 uploader = PrebuiltUploader(options.upload, acl, binhost_base_url,
David James615e5b52011-06-03 11:10:15 -0700761 pkg_indexes, options.build_path,
David James27fa7d12011-06-29 17:24:14 -0700762 options.packages, options.skip_upload,
Mike Frysinger86509232014-05-24 13:18:37 -0400763 options.binhost_conf_dir, options.dryrun,
Mike Frysinger8092a632014-05-24 13:25:46 -0400764 target, options.slave_targets, version)
David Jamesc0f158a2011-02-22 16:07:29 -0800765
David James8c846492011-01-25 17:07:29 -0800766 if options.sync_host:
Mike Frysinger8092a632014-05-24 13:25:46 -0400767 uploader.SyncHostPrebuilts(options.key, options.git_sync,
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700768 options.sync_binhost_conf)
David James8c846492011-01-25 17:07:29 -0800769
Chris Sosa62c8ff52012-06-04 15:03:12 -0700770 if options.board or options.slave_targets:
Mike Frysinger8092a632014-05-24 13:25:46 -0400771 uploader.SyncBoardPrebuilts(options.key, options.git_sync,
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700772 options.sync_binhost_conf,
Zdenek Behan62a57792012-08-31 15:09:08 +0200773 options.upload_board_tarball,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500774 options.prepackaged_tarball,
775 options.toolchain_tarballs,
776 options.toolchain_upload_path)