blob: 8bea5b37cd2222f6d3e8f28f656db7ce4903c4f7 [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
Chris Sosa1dc96132012-05-11 15:40:50 -070021import datetime
22import multiprocessing
Chris Sosa1dc96132012-05-11 15:40:50 -070023import os
24import sys
Chris Sosa1dc96132012-05-11 15:40:50 -070025
Don Garrett88b8d782014-05-13 17:30:55 -070026from chromite.cbuildbot import constants
27from chromite.cbuildbot import portage_utilities
David James6450a0a2012-12-04 07:59:53 -080028from chromite.lib import binpkg
Mike Frysinger86509232014-05-24 13:18:37 -040029from chromite.lib import commandline
Chris Sosa1dc96132012-05-11 15:40:50 -070030from chromite.lib import cros_build_lib
David James97d95872012-11-16 15:09:56 -080031from chromite.lib import git
Brian Harring7904b482012-08-08 02:54:12 -070032from chromite.lib import gs
Brian Harringaf019fb2012-05-10 15:06:13 -070033from chromite.lib import osutils
David James6450a0a2012-12-04 07:59:53 -080034from chromite.lib import parallel
Mike Frysinger8e727a32013-01-16 16:57:53 -050035from chromite.lib import toolchain
Chris Sosa1dc96132012-05-11 15:40:50 -070036
David James015af872012-06-19 15:24:36 -070037# How many times to retry uploads.
38_RETRIES = 10
39
40# Multiplier for how long to sleep (in seconds) between retries; will delay
41# (1*sleep) the first time, then (2*sleep), continuing via attempt * sleep.
42_SLEEP_TIME = 60
43
David James8c846492011-01-25 17:07:29 -080044_HOST_PACKAGES_PATH = 'chroot/var/lib/portage/pkgs'
David James05bcb2b2011-02-09 09:25:47 -080045_CATEGORIES_PATH = 'chroot/etc/portage/categories'
David James615e5b52011-06-03 11:10:15 -070046_PYM_PATH = 'chroot/usr/lib/portage/pym'
David James4058b0d2011-12-08 21:24:50 -080047_HOST_ARCH = 'amd64'
David James8c846492011-01-25 17:07:29 -080048_BOARD_PATH = 'chroot/build/%(board)s'
David James4058b0d2011-12-08 21:24:50 -080049_REL_BOARD_PATH = 'board/%(target)s/%(version)s'
50_REL_HOST_PATH = 'host/%(host_arch)s/%(target)s/%(version)s'
David James8c846492011-01-25 17:07:29 -080051# Private overlays to look at for builds to filter
52# relative to build path
53_PRIVATE_OVERLAY_DIR = 'src/private-overlays'
Scott Zawalskiab1bed32011-03-16 15:24:24 -070054_GOOGLESTORAGE_ACL_FILE = 'googlestorage_acl.xml'
David James3753d942014-04-23 10:55:48 -070055_BINHOST_BASE_URL = 'gs://chromeos-prebuilt'
David James8c846492011-01-25 17:07:29 -080056_PREBUILT_BASE_DIR = 'src/third_party/chromiumos-overlay/chromeos/config/'
57# Created in the event of new host targets becoming available
58_PREBUILT_MAKE_CONF = {'amd64': os.path.join(_PREBUILT_BASE_DIR,
59 'make.conf.amd64-host')}
60_BINHOST_CONF_DIR = 'src/third_party/chromiumos-overlay/chromeos/binhost'
61
62
David James4058b0d2011-12-08 21:24:50 -080063class BuildTarget(object):
64 """A board/variant/profile tuple."""
65
66 def __init__(self, board_variant, profile=None):
67 self.board_variant = board_variant
68 self.board, _, self.variant = board_variant.partition('_')
69 self.profile = profile
70
71 def __str__(self):
72 if self.profile:
73 return '%s_%s' % (self.board_variant, self.profile)
74 else:
75 return self.board_variant
76
77 def __eq__(self, other):
78 return str(other) == str(self)
79
80 def __hash__(self):
81 return hash(str(self))
82
83
David James8c846492011-01-25 17:07:29 -080084def UpdateLocalFile(filename, value, key='PORTAGE_BINHOST'):
85 """Update the key in file with the value passed.
Mike Frysinger1a736a82013-12-12 01:50:59 -050086
David James8c846492011-01-25 17:07:29 -080087 File format:
88 key="value"
89 Note quotes are added automatically
90
91 Args:
92 filename: Name of file to modify.
93 value: Value to write with the key.
94 key: The variable key to update. (Default: PORTAGE_BINHOST)
95 """
96 if os.path.exists(filename):
97 file_fh = open(filename)
98 else:
99 file_fh = open(filename, 'w+')
100 file_lines = []
101 found = False
102 keyval_str = '%(key)s=%(value)s'
103 for line in file_fh:
104 # Strip newlines from end of line. We already add newlines below.
105 line = line.rstrip("\n")
106
107 if len(line.split('=')) != 2:
108 # Skip any line that doesn't fit key=val.
109 file_lines.append(line)
110 continue
111
112 file_var, file_val = line.split('=')
113 if file_var == key:
114 found = True
David James20b2b6f2011-11-18 15:11:58 -0800115 print 'Updating %s=%s to %s="%s"' % (file_var, file_val, key, value)
David James8c846492011-01-25 17:07:29 -0800116 value = '"%s"' % value
117 file_lines.append(keyval_str % {'key': key, 'value': value})
118 else:
119 file_lines.append(keyval_str % {'key': file_var, 'value': file_val})
120
121 if not found:
Brian Harring2a014302012-05-12 00:53:33 -0700122 value = '"%s"' % value
David James8c846492011-01-25 17:07:29 -0800123 file_lines.append(keyval_str % {'key': key, 'value': value})
124
125 file_fh.close()
126 # write out new file
Brian Harringaf019fb2012-05-10 15:06:13 -0700127 osutils.WriteFile(filename, '\n'.join(file_lines) + '\n')
David James8c846492011-01-25 17:07:29 -0800128
129
Mike Frysinger5b34d732013-01-17 15:11:58 -0500130def RevGitFile(filename, data, retries=5, dryrun=False):
David James8c846492011-01-25 17:07:29 -0800131 """Update and push the git file.
132
Mike Frysinger5b34d732013-01-17 15:11:58 -0500133 Args:
134 filename: file to modify that is in a git repo already
135 data: A dict of key/values to update in |filename|
136 retries: The number of times to retry before giving up, default: 5
Matt Tennante8179042013-10-01 15:47:32 -0700137 dryrun: If True, do not actually commit the change.
David James8c846492011-01-25 17:07:29 -0800138 """
139 prebuilt_branch = 'prebuilt_branch'
David James1b6e67a2011-05-19 21:32:38 -0700140 cwd = os.path.abspath(os.path.dirname(filename))
David James97d95872012-11-16 15:09:56 -0800141 commit = git.RunGit(cwd, ['rev-parse', 'HEAD']).output.rstrip()
Mike Frysinger5b34d732013-01-17 15:11:58 -0500142 description = '%s: updating %s' % (os.path.basename(filename),
143 ', '.join(data.keys()))
144 # UpdateLocalFile will print out the keys/values for us.
145 print 'Revving git file %s' % filename
David James66009462012-03-25 10:08:38 -0700146
David James8c846492011-01-25 17:07:29 -0800147 try:
David James97d95872012-11-16 15:09:56 -0800148 git.CreatePushBranch(prebuilt_branch, cwd)
Mike Frysinger5b34d732013-01-17 15:11:58 -0500149 for key, value in data.iteritems():
150 UpdateLocalFile(filename, value, key)
David James97d95872012-11-16 15:09:56 -0800151 git.RunGit(cwd, ['add', filename])
152 git.RunGit(cwd, ['commit', '-m', description])
153 git.PushWithRetry(prebuilt_branch, cwd, dryrun=dryrun, retries=retries)
David James8c846492011-01-25 17:07:29 -0800154 finally:
David James67d73252013-09-19 17:33:12 -0700155 git.RunGit(cwd, ['checkout', commit])
David James8c846492011-01-25 17:07:29 -0800156
157
158def GetVersion():
159 """Get the version to put in LATEST and update the git version with."""
Mike Frysinger0b92cfe2012-12-13 02:13:45 -0500160 return datetime.datetime.now().strftime('%Y.%m.%d.%H%M%S')
David James8c846492011-01-25 17:07:29 -0800161
162
David James015af872012-06-19 15:24:36 -0700163def _GsUpload(local_file, remote_file, acl):
David James8c846492011-01-25 17:07:29 -0800164 """Upload to GS bucket.
165
166 Args:
Matt Tennante8179042013-10-01 15:47:32 -0700167 local_file: The local file to be uploaded.
168 remote_file: The remote location to upload to.
169 acl: The ACL to use for uploading the file.
David James8c846492011-01-25 17:07:29 -0800170
171 Returns:
172 Return the arg tuple of two if the upload failed
173 """
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700174 CANNED_ACLS = ['public-read', 'private', 'bucket-owner-read',
175 'authenticated-read', 'bucket-owner-full-control',
176 'public-read-write']
David James9374aac2013-10-08 16:00:17 -0700177 gs_context = gs.GSContext(retries=_RETRIES, sleep=_SLEEP_TIME)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700178 if acl in CANNED_ACLS:
David James9374aac2013-10-08 16:00:17 -0700179 gs_context.Copy(local_file, remote_file, acl=acl)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700180 else:
181 # For private uploads we assume that the overlay board is set up properly
David James015af872012-06-19 15:24:36 -0700182 # and a googlestore_acl.xml is present. Otherwise, this script errors.
David James9374aac2013-10-08 16:00:17 -0700183 gs_context.Copy(local_file, remote_file, acl='private')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700184 # Apply the passed in ACL xml file to the uploaded object.
David James9374aac2013-10-08 16:00:17 -0700185 gs_context.SetACL(remote_file, acl=acl)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700186
Mike Frysingercc838832014-05-24 13:10:30 -0400187
David Jamesfd0b0852011-02-23 11:15:36 -0800188def RemoteUpload(acl, files, pool=10):
David James8c846492011-01-25 17:07:29 -0800189 """Upload to google storage.
190
191 Create a pool of process and call _GsUpload with the proper arguments.
192
193 Args:
David Jamesfd0b0852011-02-23 11:15:36 -0800194 acl: The canned acl used for uploading. acl can be one of: "public-read",
195 "public-read-write", "authenticated-read", "bucket-owner-read",
196 "bucket-owner-full-control", or "private".
David James8c846492011-01-25 17:07:29 -0800197 files: dictionary with keys to local files and values to remote path.
198 pool: integer of maximum proesses to have at the same time.
199
200 Returns:
201 Return a set of tuple arguments of the failed uploads
202 """
David James015af872012-06-19 15:24:36 -0700203 tasks = [[key, value, acl] for key, value in files.iteritems()]
David James6450a0a2012-12-04 07:59:53 -0800204 parallel.RunTasksInProcessPool(_GsUpload, tasks, pool)
David James8c846492011-01-25 17:07:29 -0800205
206
207def GenerateUploadDict(base_local_path, base_remote_path, pkgs):
208 """Build a dictionary of local remote file key pairs to upload.
209
210 Args:
211 base_local_path: The base path to the files on the local hard drive.
Matt Tennante8179042013-10-01 15:47:32 -0700212 base_remote_path: The base path to the remote paths.
David James8c846492011-01-25 17:07:29 -0800213 pkgs: The packages to upload.
214
215 Returns:
216 Returns a dictionary of local_path/remote_path pairs
217 """
218 upload_files = {}
219 for pkg in pkgs:
220 suffix = pkg['CPV'] + '.tbz2'
221 local_path = os.path.join(base_local_path, suffix)
222 assert os.path.exists(local_path)
223 remote_path = '%s/%s' % (base_remote_path.rstrip('/'), suffix)
224 upload_files[local_path] = remote_path
225
226 return upload_files
227
Mike Frysingercc838832014-05-24 13:10:30 -0400228
Peter Mayo950e41a2014-02-06 21:07:33 +0000229def GetBoardOverlay(build_path, target):
David Jamese5867812012-10-19 12:02:20 -0700230 """Get the path to the board variant.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500231
David James8c846492011-01-25 17:07:29 -0800232 Args:
233 build_path: The path to the root of the build directory
David Jamese5867812012-10-19 12:02:20 -0700234 target: The target board as a BuildTarget object.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500235
David James8c846492011-01-25 17:07:29 -0800236 Returns:
David Jamese5867812012-10-19 12:02:20 -0700237 The last overlay configured for the given board as a string.
David James8c846492011-01-25 17:07:29 -0800238 """
David Jamese5867812012-10-19 12:02:20 -0700239 board = target.board_variant
240 overlays = portage_utilities.FindOverlays(constants.BOTH_OVERLAYS, board,
241 buildroot=build_path)
242 # We only care about the last entry.
243 return overlays[-1]
David James8c846492011-01-25 17:07:29 -0800244
245
246def DeterminePrebuiltConfFile(build_path, target):
247 """Determine the prebuilt.conf file that needs to be updated for prebuilts.
248
Mike Frysinger1a736a82013-12-12 01:50:59 -0500249 Args:
250 build_path: The path to the root of the build directory
251 target: String representation of the board. This includes host and board
252 targets
David James8c846492011-01-25 17:07:29 -0800253
Mike Frysinger1a736a82013-12-12 01:50:59 -0500254 Returns:
255 A string path to a prebuilt.conf file to be updated.
David James8c846492011-01-25 17:07:29 -0800256 """
David James4058b0d2011-12-08 21:24:50 -0800257 if _HOST_ARCH == target:
David James8c846492011-01-25 17:07:29 -0800258 # We are host.
259 # Without more examples of hosts this is a kludge for now.
260 # TODO(Scottz): as new host targets come online expand this to
261 # work more like boards.
Chris Sosa471532a2011-02-01 15:10:06 -0800262 make_path = _PREBUILT_MAKE_CONF[target]
David James8c846492011-01-25 17:07:29 -0800263 else:
264 # We are a board
Peter Mayo950e41a2014-02-06 21:07:33 +0000265 board = GetBoardOverlay(build_path, target)
David James8c846492011-01-25 17:07:29 -0800266 make_path = os.path.join(board, 'prebuilt.conf')
267
268 return make_path
269
270
271def UpdateBinhostConfFile(path, key, value):
272 """Update binhost config file file with key=value.
273
274 Args:
275 path: Filename to update.
276 key: Key to update.
277 value: New value for key.
278 """
279 cwd = os.path.dirname(os.path.abspath(path))
280 filename = os.path.basename(path)
Brian Harringaf019fb2012-05-10 15:06:13 -0700281 osutils.SafeMakedirs(cwd)
David Jamesf6e8fb72013-05-10 08:58:43 -0700282 if not git.GetCurrentBranch(cwd):
283 git.CreatePushBranch(constants.STABLE_EBUILD_BRANCH, cwd, sync=False)
Brian Harring22edb442012-05-11 23:55:18 -0700284 osutils.WriteFile(path, '', mode='a')
David James8c846492011-01-25 17:07:29 -0800285 UpdateLocalFile(path, value, key)
David James67d73252013-09-19 17:33:12 -0700286 git.RunGit(cwd, ['add', filename])
Mike Frysinger109cada2013-01-17 15:50:44 -0500287 description = '%s: updating %s' % (os.path.basename(filename), key)
David James67d73252013-09-19 17:33:12 -0700288 git.RunGit(cwd, ['commit', '-m', description])
David James8c846492011-01-25 17:07:29 -0800289
290
David Jamesce093af2011-02-23 15:21:58 -0800291def _GrabAllRemotePackageIndexes(binhost_urls):
David James05bcb2b2011-02-09 09:25:47 -0800292 """Grab all of the packages files associated with a list of binhost_urls.
293
David James05bcb2b2011-02-09 09:25:47 -0800294 Args:
295 binhost_urls: The URLs for the directories containing the Packages files we
296 want to grab.
David James05bcb2b2011-02-09 09:25:47 -0800297
298 Returns:
299 A list of PackageIndex objects.
300 """
301 pkg_indexes = []
302 for url in binhost_urls:
David James32faafe2012-06-08 14:25:03 -0700303 pkg_index = binpkg.GrabRemotePackageIndex(url)
David James05bcb2b2011-02-09 09:25:47 -0800304 if pkg_index:
305 pkg_indexes.append(pkg_index)
David James05bcb2b2011-02-09 09:25:47 -0800306 return pkg_indexes
307
308
David Jamesc0f158a2011-02-22 16:07:29 -0800309class PrebuiltUploader(object):
310 """Synchronize host and board prebuilts."""
David James8c846492011-01-25 17:07:29 -0800311
Mike Frysinger86509232014-05-24 13:18:37 -0400312 def __init__(self, upload_location, acl, binhost_base_url, pkg_indexes,
313 build_path, packages, skip_upload, binhost_conf_dir, dryrun,
314 target, slave_targets):
David Jamesc0f158a2011-02-22 16:07:29 -0800315 """Constructor for prebuilt uploader object.
David James8c846492011-01-25 17:07:29 -0800316
David Jamesc0f158a2011-02-22 16:07:29 -0800317 This object can upload host or prebuilt files to Google Storage.
David James8c846492011-01-25 17:07:29 -0800318
David Jamesc0f158a2011-02-22 16:07:29 -0800319 Args:
320 upload_location: The upload location.
David Jamesfd0b0852011-02-23 11:15:36 -0800321 acl: The canned acl used for uploading to Google Storage. acl can be one
322 of: "public-read", "public-read-write", "authenticated-read",
Matt Tennante8179042013-10-01 15:47:32 -0700323 "bucket-owner-read", "bucket-owner-full-control", "project-private",
324 or "private" (see "gsutil help acls"). If we are not uploading to
325 Google Storage, this parameter is unused.
David Jamesfd0b0852011-02-23 11:15:36 -0800326 binhost_base_url: The URL used for downloading the prebuilts.
David Jamesc0f158a2011-02-22 16:07:29 -0800327 pkg_indexes: Old uploaded prebuilts to compare against. Instead of
328 uploading duplicate files, we just link to the old files.
David James615e5b52011-06-03 11:10:15 -0700329 build_path: The path to the directory containing the chroot.
330 packages: Packages to upload.
David James32b0b2f2011-07-13 20:56:50 -0700331 skip_upload: Don't actually upload the tarballs.
332 binhost_conf_dir: Directory where to store binhost.conf files.
Mike Frysinger86509232014-05-24 13:18:37 -0400333 dryrun: Don't push or upload prebuilts.
David James4058b0d2011-12-08 21:24:50 -0800334 target: BuildTarget managed by this builder.
335 slave_targets: List of BuildTargets managed by slave builders.
David Jamesc0f158a2011-02-22 16:07:29 -0800336 """
337 self._upload_location = upload_location
David Jamesfd0b0852011-02-23 11:15:36 -0800338 self._acl = acl
David Jamesc0f158a2011-02-22 16:07:29 -0800339 self._binhost_base_url = binhost_base_url
340 self._pkg_indexes = pkg_indexes
David James615e5b52011-06-03 11:10:15 -0700341 self._build_path = build_path
342 self._packages = set(packages)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500343 self._found_packages = set()
David James8ece7ee2011-06-29 16:02:30 -0700344 self._skip_upload = skip_upload
David James32b0b2f2011-07-13 20:56:50 -0700345 self._binhost_conf_dir = binhost_conf_dir
Mike Frysinger86509232014-05-24 13:18:37 -0400346 self._dryrun = dryrun
David James4058b0d2011-12-08 21:24:50 -0800347 self._target = target
348 self._slave_targets = slave_targets
David James615e5b52011-06-03 11:10:15 -0700349
350 def _ShouldFilterPackage(self, pkg):
351 if not self._packages:
352 return False
353 pym_path = os.path.abspath(os.path.join(self._build_path, _PYM_PATH))
David James710b7dc2012-02-07 16:49:59 -0800354 sys.path.insert(0, pym_path)
Don Garrett25f309a2014-03-19 14:02:12 -0700355 # pylint: disable=F0401
David James615e5b52011-06-03 11:10:15 -0700356 import portage.versions
357 cat, pkgname = portage.versions.catpkgsplit(pkg['CPV'])[0:2]
358 cp = '%s/%s' % (cat, pkgname)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500359 self._found_packages.add(cp)
David James615e5b52011-06-03 11:10:15 -0700360 return pkgname not in self._packages and cp not in self._packages
David James8c846492011-01-25 17:07:29 -0800361
David Jamesc0f158a2011-02-22 16:07:29 -0800362 def _UploadPrebuilt(self, package_path, url_suffix):
363 """Upload host or board prebuilt files to Google Storage space.
David James8c846492011-01-25 17:07:29 -0800364
David Jamesc0f158a2011-02-22 16:07:29 -0800365 Args:
366 package_path: The path to the packages dir.
David Jamesce093af2011-02-23 15:21:58 -0800367 url_suffix: The remote subdirectory where we should upload the packages.
David Jamesc0f158a2011-02-22 16:07:29 -0800368 """
David Jamesc0f158a2011-02-22 16:07:29 -0800369 # Process Packages file, removing duplicates and filtered packages.
David James32faafe2012-06-08 14:25:03 -0700370 pkg_index = binpkg.GrabLocalPackageIndex(package_path)
David Jamesc0f158a2011-02-22 16:07:29 -0800371 pkg_index.SetUploadLocation(self._binhost_base_url, url_suffix)
David James615e5b52011-06-03 11:10:15 -0700372 pkg_index.RemoveFilteredPackages(self._ShouldFilterPackage)
David Jamesc0f158a2011-02-22 16:07:29 -0800373 uploads = pkg_index.ResolveDuplicateUploads(self._pkg_indexes)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500374 unmatched_pkgs = self._packages - self._found_packages
375 if unmatched_pkgs:
376 cros_build_lib.Warning('unable to match packages: %r' % unmatched_pkgs)
David James05bcb2b2011-02-09 09:25:47 -0800377
David Jamesc0f158a2011-02-22 16:07:29 -0800378 # Write Packages file.
379 tmp_packages_file = pkg_index.WriteToNamedTemporaryFile()
David James05bcb2b2011-02-09 09:25:47 -0800380
David Jamesc0f158a2011-02-22 16:07:29 -0800381 remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
David James015af872012-06-19 15:24:36 -0700382 assert remote_location.startswith('gs://')
David James05bcb2b2011-02-09 09:25:47 -0800383
David James015af872012-06-19 15:24:36 -0700384 # Build list of files to upload.
385 upload_files = GenerateUploadDict(package_path, remote_location, uploads)
386 remote_file = '%s/Packages' % remote_location.rstrip('/')
387 upload_files[tmp_packages_file.name] = remote_file
388
389 RemoteUpload(self._acl, upload_files)
David James8c846492011-01-25 17:07:29 -0800390
Mike Frysinger9e979b92012-11-29 02:55:09 -0500391 def _UploadSdkTarball(self, board_path, url_suffix, version, prepackaged,
392 toolchain_tarballs, toolchain_upload_path):
393 """Upload a tarball of the sdk at the specified path to Google Storage.
David James8fa34ea2011-04-15 13:00:20 -0700394
395 Args:
396 board_path: The path to the board dir.
397 url_suffix: The remote subdirectory where we should upload the packages.
Zdenek Behan5ad96c02011-06-23 01:04:06 +0200398 version: The version of the board.
Zdenek Behan62a57792012-08-31 15:09:08 +0200399 prepackaged: If given, a tarball that has been packaged outside of this
400 script and should be used.
Mike Frysinger9e979b92012-11-29 02:55:09 -0500401 toolchain_tarballs: List of toolchain tarballs to upload.
402 toolchain_upload_path: Path under the bucket to place toolchain tarballs.
David James8fa34ea2011-04-15 13:00:20 -0700403 """
404 remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
405 assert remote_location.startswith('gs://')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200406 boardname = os.path.basename(board_path.rstrip('/'))
407 # We do not upload non SDK board tarballs,
408 assert boardname == constants.CHROOT_BUILDER_BOARD
409 assert prepackaged is not None
Zdenek Behan62a57792012-08-31 15:09:08 +0200410
Zdenek Behan86c15e92012-10-13 00:55:47 +0200411 version_str = version[len('chroot-'):]
Mike Frysinger8e727a32013-01-16 16:57:53 -0500412 remote_tarfile = toolchain.GetSdkURL(
413 for_gsutil=True, suburl='cros-sdk-%s.tar.xz' % (version_str,))
Zdenek Behan86c15e92012-10-13 00:55:47 +0200414 # For SDK, also upload the manifest which is guaranteed to exist
415 # by the builderstage.
416 _GsUpload(prepackaged + '.Manifest', remote_tarfile + '.Manifest',
417 self._acl)
418 _GsUpload(prepackaged, remote_tarfile, self._acl)
419
Mike Frysinger9e979b92012-11-29 02:55:09 -0500420 # Post the toolchain tarballs too.
421 for tarball in toolchain_tarballs:
422 target, local_path = tarball.split(':')
423 suburl = toolchain_upload_path % {'target': target}
424 remote_path = toolchain.GetSdkURL(for_gsutil=True, suburl=suburl)
425 _GsUpload(local_path, remote_path, self._acl)
426
Zdenek Behan86c15e92012-10-13 00:55:47 +0200427 # Finally, also update the pointer to the latest SDK on which polling
428 # scripts rely.
David James4bc13702013-03-26 08:08:04 -0700429 with osutils.TempDir() as tmpdir:
Zdenek Behan86c15e92012-10-13 00:55:47 +0200430 pointerfile = os.path.join(tmpdir, 'cros-sdk-latest.conf')
Mike Frysinger8e727a32013-01-16 16:57:53 -0500431 remote_pointerfile = toolchain.GetSdkURL(for_gsutil=True,
432 suburl='cros-sdk-latest.conf')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200433 osutils.WriteFile(pointerfile, 'LATEST_SDK="%s"' % version_str)
434 _GsUpload(pointerfile, remote_pointerfile, self._acl)
Zdenek Behan33a34112012-09-10 21:07:51 +0200435
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700436 def _GetTargets(self):
437 """Retuns the list of targets to use."""
438 targets = self._slave_targets[:]
439 if self._target:
440 targets.append(self._target)
441
442 return targets
443
444 def SyncHostPrebuilts(self, version, key, git_sync, sync_binhost_conf):
David Jamesc0f158a2011-02-22 16:07:29 -0800445 """Synchronize host prebuilt files.
David James05bcb2b2011-02-09 09:25:47 -0800446
David Jamesc0f158a2011-02-22 16:07:29 -0800447 This function will sync both the standard host packages, plus the host
448 packages associated with all targets that have been "setup" with the
449 current host's chroot. For instance, if this host has been used to build
450 x86-generic, it will sync the host packages associated with
451 'i686-pc-linux-gnu'. If this host has also been used to build arm-generic,
452 it will also sync the host packages associated with
453 'armv7a-cros-linux-gnueabi'.
David James05bcb2b2011-02-09 09:25:47 -0800454
David Jamesc0f158a2011-02-22 16:07:29 -0800455 Args:
David Jamesc0f158a2011-02-22 16:07:29 -0800456 version: A unique string, intended to be included in the upload path,
457 which identifies the version number of the uploaded prebuilts.
458 key: The variable key to update in the git file.
459 git_sync: If set, update make.conf of target to reference the latest
460 prebuilt packages generated here.
461 sync_binhost_conf: If set, update binhost config file in
462 chromiumos-overlay for the host.
463 """
David Jamese2488642011-11-14 16:15:20 -0800464 # Slave boards are listed before the master board so that the master board
465 # takes priority (i.e. x86-generic preflight host prebuilts takes priority
466 # over preflight host prebuilts from other builders.)
467 binhost_urls = []
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700468 for target in self._GetTargets():
David James4058b0d2011-12-08 21:24:50 -0800469 url_suffix = _REL_HOST_PATH % {'version': version,
470 'host_arch': _HOST_ARCH,
471 'target': target}
David Jamese2488642011-11-14 16:15:20 -0800472 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David James05bcb2b2011-02-09 09:25:47 -0800473
Mike Frysinger86509232014-05-24 13:18:37 -0400474 if self._target == target and not self._skip_upload and not self._dryrun:
David Jamese2488642011-11-14 16:15:20 -0800475 # Upload prebuilts.
476 package_path = os.path.join(self._build_path, _HOST_PACKAGES_PATH)
477 self._UploadPrebuilt(package_path, packages_url_suffix)
David James8ece7ee2011-06-29 16:02:30 -0700478
David Jamese2488642011-11-14 16:15:20 -0800479 # Record URL where prebuilts were uploaded.
480 binhost_urls.append('%s/%s/' % (self._binhost_base_url.rstrip('/'),
481 packages_url_suffix.rstrip('/')))
482
David James20b2b6f2011-11-18 15:11:58 -0800483 binhost = ' '.join(binhost_urls)
David James8ece7ee2011-06-29 16:02:30 -0700484 if git_sync:
485 git_file = os.path.join(self._build_path,
David James4058b0d2011-12-08 21:24:50 -0800486 _PREBUILT_MAKE_CONF[_HOST_ARCH])
Mike Frysinger86509232014-05-24 13:18:37 -0400487 RevGitFile(git_file, {key: binhost}, dryrun=self._dryrun)
David James8ece7ee2011-06-29 16:02:30 -0700488 if sync_binhost_conf:
David James32b0b2f2011-07-13 20:56:50 -0700489 binhost_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James4058b0d2011-12-08 21:24:50 -0800490 'host', '%s-%s.conf' % (_HOST_ARCH, key))
David Jamese2488642011-11-14 16:15:20 -0800491 UpdateBinhostConfFile(binhost_conf, key, binhost)
David Jamesc0f158a2011-02-22 16:07:29 -0800492
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700493 def SyncBoardPrebuilts(self, version, key, git_sync, sync_binhost_conf,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500494 upload_board_tarball, prepackaged_board,
495 toolchain_tarballs, toolchain_upload_path):
David Jamesc0f158a2011-02-22 16:07:29 -0800496 """Synchronize board prebuilt files.
497
498 Args:
David Jamesc0f158a2011-02-22 16:07:29 -0800499 version: A unique string, intended to be included in the upload path,
500 which identifies the version number of the uploaded prebuilts.
501 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')
David James4058b0d2011-12-08 21:24:50 -0800515 url_suffix = _REL_BOARD_PATH % {'target': target, 'version': version}
David Jamese2488642011-11-14 16:15:20 -0800516 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David James8fa34ea2011-04-15 13:00:20 -0700517
Matt Tennante8179042013-10-01 15:47:32 -0700518 # Process the target board differently if it is the main --board.
Mike Frysinger86509232014-05-24 13:18:37 -0400519 if self._target == target and not self._skip_upload and not self._dryrun:
Matt Tennante8179042013-10-01 15:47:32 -0700520 # This strips "chroot" prefix because that is sometimes added as the
521 # --prepend-version argument (e.g. by chromiumos-sdk bot).
522 # TODO(build): Clean it up to be less hard-coded.
Mike Frysinger9e979b92012-11-29 02:55:09 -0500523 version_str = version[len('chroot-'):]
524
David Jamese2488642011-11-14 16:15:20 -0800525 # Upload board tarballs in the background.
526 if upload_board_tarball:
Mike Frysinger9e979b92012-11-29 02:55:09 -0500527 if toolchain_upload_path:
528 toolchain_upload_path %= {'version': version_str}
529 tar_process = multiprocessing.Process(
530 target=self._UploadSdkTarball,
531 args=(board_path, url_suffix, version, prepackaged_board,
532 toolchain_tarballs, toolchain_upload_path))
David Jamese2488642011-11-14 16:15:20 -0800533 tar_process.start()
David James8fa34ea2011-04-15 13:00:20 -0700534
David Jamese2488642011-11-14 16:15:20 -0800535 # Upload prebuilts.
536 self._UploadPrebuilt(package_path, packages_url_suffix)
David James8fa34ea2011-04-15 13:00:20 -0700537
David Jamese2488642011-11-14 16:15:20 -0800538 # Make sure we finished uploading the board tarballs.
539 if upload_board_tarball:
540 tar_process.join()
541 assert tar_process.exitcode == 0
542 # TODO(zbehan): This should be done cleaner.
Zdenek Behan33a34112012-09-10 21:07:51 +0200543 if target.board == constants.CHROOT_BUILDER_BOARD:
David Jamese2488642011-11-14 16:15:20 -0800544 sdk_conf = os.path.join(self._build_path, self._binhost_conf_dir,
Mike Frysinger5b34d732013-01-17 15:11:58 -0500545 'host/sdk_version.conf')
546 sdk_settings = {
Mike Frysinger9e979b92012-11-29 02:55:09 -0500547 'SDK_LATEST_VERSION': version_str,
548 'TC_PATH': toolchain_upload_path,
Mike Frysinger5b34d732013-01-17 15:11:58 -0500549 }
Mike Frysinger86509232014-05-24 13:18:37 -0400550 RevGitFile(sdk_conf, sdk_settings, dryrun=self._dryrun)
David Jamesc0f158a2011-02-22 16:07:29 -0800551
David Jamese2488642011-11-14 16:15:20 -0800552 # Record URL where prebuilts were uploaded.
553 url_value = '%s/%s/' % (self._binhost_base_url.rstrip('/'),
554 packages_url_suffix.rstrip('/'))
555
556 if git_sync:
David James4058b0d2011-12-08 21:24:50 -0800557 git_file = DeterminePrebuiltConfFile(self._build_path, target)
Mike Frysinger86509232014-05-24 13:18:37 -0400558 RevGitFile(git_file, {key: url_value}, dryrun=self._dryrun)
Matt Tennante8179042013-10-01 15:47:32 -0700559
David Jamese2488642011-11-14 16:15:20 -0800560 if sync_binhost_conf:
Matt Tennante8179042013-10-01 15:47:32 -0700561 # Update the binhost configuration file in git.
David Jamese2488642011-11-14 16:15:20 -0800562 binhost_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James4058b0d2011-12-08 21:24:50 -0800563 'target', '%s-%s.conf' % (target, key))
David Jamese2488642011-11-14 16:15:20 -0800564 UpdateBinhostConfFile(binhost_conf, key, url_value)
David James05bcb2b2011-02-09 09:25:47 -0800565
566
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700567def _AddSlaveBoard(_option, _opt_str, value, parser):
568 """Callback that adds a slave board to the list of slave targets."""
David James4058b0d2011-12-08 21:24:50 -0800569 parser.values.slave_targets.append(BuildTarget(value))
570
571
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700572def _AddSlaveProfile(_option, _opt_str, value, parser):
573 """Callback that adds a slave profile to the list of slave targets."""
David James4058b0d2011-12-08 21:24:50 -0800574 if not parser.values.slave_targets:
Mike Frysinger86509232014-05-24 13:18:37 -0400575 parser.error('Must specify --slave-board before --slave-profile')
David James4058b0d2011-12-08 21:24:50 -0800576 if parser.values.slave_targets[-1].profile is not None:
Mike Frysinger86509232014-05-24 13:18:37 -0400577 parser.error('Cannot specify --slave-profile twice for same board')
David James4058b0d2011-12-08 21:24:50 -0800578 parser.values.slave_targets[-1].profile = value
579
580
Mike Frysinger86509232014-05-24 13:18:37 -0400581def ParseOptions(argv):
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700582 """Returns options given by the user and the target specified.
583
Mike Frysinger86509232014-05-24 13:18:37 -0400584 Args:
585 argv: The args to parse.
586
Mike Frysinger1a736a82013-12-12 01:50:59 -0500587 Returns:
588 A tuple containing a parsed options object and BuildTarget.
589 The target instance is None if no board is specified.
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700590 """
Mike Frysinger86509232014-05-24 13:18:37 -0400591 parser = commandline.OptionParser()
David James8c846492011-01-25 17:07:29 -0800592 parser.add_option('-H', '--binhost-base-url', dest='binhost_base_url',
593 default=_BINHOST_BASE_URL,
594 help='Base URL to use for binhost in make.conf updates')
595 parser.add_option('', '--previous-binhost-url', action='append',
596 default=[], dest='previous_binhost_url',
597 help='Previous binhost URL')
598 parser.add_option('-b', '--board', dest='board', default=None,
599 help='Board type that was built on this machine')
Zdenek Behan62a57792012-08-31 15:09:08 +0200600 parser.add_option('-B', '--prepackaged-tarball', dest='prepackaged_tarball',
601 default=None,
602 help='Board tarball prebuilt outside of this script.')
Mike Frysinger9e979b92012-11-29 02:55:09 -0500603 parser.add_option('--toolchain-tarball', dest='toolchain_tarballs',
604 action='append', default=[],
605 help='Redistributable toolchain tarball.')
606 parser.add_option('--toolchain-upload-path', default='',
607 help='Path to place toolchain tarballs in the sdk tree.')
David James4058b0d2011-12-08 21:24:50 -0800608 parser.add_option('', '--profile', dest='profile', default=None,
609 help='Profile that was built on this machine')
610 parser.add_option('', '--slave-board', default=[], action='callback',
611 dest='slave_targets', type='string',
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700612 callback=_AddSlaveBoard,
David James4058b0d2011-12-08 21:24:50 -0800613 help='Board type that was built on a slave machine. To '
614 'add a profile to this board, use --slave-profile.')
615 parser.add_option('', '--slave-profile', action='callback', type='string',
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700616 callback=_AddSlaveProfile,
David James4058b0d2011-12-08 21:24:50 -0800617 help='Board profile that was built on a slave machine. '
618 'Applies to previous slave board.')
David James8c846492011-01-25 17:07:29 -0800619 parser.add_option('-p', '--build-path', dest='build_path',
David James05bcb2b2011-02-09 09:25:47 -0800620 help='Path to the directory containing the chroot')
David James615e5b52011-06-03 11:10:15 -0700621 parser.add_option('', '--packages', action='append',
622 default=[], dest='packages',
623 help='Only include the specified packages. '
624 '(Default is to include all packages.)')
David James8c846492011-01-25 17:07:29 -0800625 parser.add_option('-s', '--sync-host', dest='sync_host',
626 default=False, action='store_true',
627 help='Sync host prebuilts')
628 parser.add_option('-g', '--git-sync', dest='git_sync',
629 default=False, action='store_true',
David Jamese2488642011-11-14 16:15:20 -0800630 help='Enable git version sync (This commits to a repo.) '
631 'This is used by full builders to commit directly '
632 'to board overlays.')
David James8c846492011-01-25 17:07:29 -0800633 parser.add_option('-u', '--upload', dest='upload',
634 default=None,
635 help='Upload location')
636 parser.add_option('-V', '--prepend-version', dest='prepend_version',
637 default=None,
638 help='Add an identifier to the front of the version')
639 parser.add_option('-f', '--filters', dest='filters', action='store_true',
640 default=False,
641 help='Turn on filtering of private ebuild packages')
642 parser.add_option('-k', '--key', dest='key',
643 default='PORTAGE_BINHOST',
644 help='Key to update in make.conf / binhost.conf')
David James8ece7ee2011-06-29 16:02:30 -0700645 parser.add_option('', '--set-version', dest='set_version',
646 default=None,
647 help='Specify the version string')
David James8c846492011-01-25 17:07:29 -0800648 parser.add_option('', '--sync-binhost-conf', dest='sync_binhost_conf',
649 default=False, action='store_true',
David Jamese2488642011-11-14 16:15:20 -0800650 help='Update binhost.conf in chromiumos-overlay or '
651 'chromeos-overlay. Commit the changes, but don\'t '
652 'push them. This is used for preflight binhosts.')
David James32b0b2f2011-07-13 20:56:50 -0700653 parser.add_option('', '--binhost-conf-dir', dest='binhost_conf_dir',
654 default=_BINHOST_CONF_DIR,
655 help='Directory to commit binhost config with '
656 '--sync-binhost-conf.')
David Jamesfd0b0852011-02-23 11:15:36 -0800657 parser.add_option('-P', '--private', dest='private', action='store_true',
658 default=False, help='Mark gs:// uploads as private.')
David James8ece7ee2011-06-29 16:02:30 -0700659 parser.add_option('', '--skip-upload', dest='skip_upload',
660 action='store_true', default=False,
661 help='Skip upload step.')
David James8fa34ea2011-04-15 13:00:20 -0700662 parser.add_option('', '--upload-board-tarball', dest='upload_board_tarball',
663 action='store_true', default=False,
664 help='Upload board tarball to Google Storage.')
Mike Frysinger86509232014-05-24 13:18:37 -0400665 parser.add_option('-n', '--dry-run', dest='dryrun',
David James27fa7d12011-06-29 17:24:14 -0700666 action='store_true', default=False,
667 help='Don\'t push or upload prebuilts.')
David James8c846492011-01-25 17:07:29 -0800668
Mike Frysinger86509232014-05-24 13:18:37 -0400669 options, args = parser.parse_args(argv)
David James8c846492011-01-25 17:07:29 -0800670 if not options.build_path:
Mike Frysinger86509232014-05-24 13:18:37 -0400671 parser.error('you need provide a chroot path')
David James8ece7ee2011-06-29 16:02:30 -0700672 if not options.upload and not options.skip_upload:
Mike Frysinger86509232014-05-24 13:18:37 -0400673 parser.error('you need to provide an upload location using -u')
David James8ece7ee2011-06-29 16:02:30 -0700674 if not options.set_version and options.skip_upload:
Mike Frysinger86509232014-05-24 13:18:37 -0400675 parser.error('If you are using --skip-upload, you must specify a '
676 'version number using --set-version.')
David James9417f272011-05-26 13:24:47 -0700677 if args:
Mike Frysinger86509232014-05-24 13:18:37 -0400678 parser.error('invalid arguments passed to upload_prebuilts: %r' % args)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700679
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700680 target = None
681 if options.board:
682 target = BuildTarget(options.board, options.profile)
683
684 if target in options.slave_targets:
Mike Frysinger86509232014-05-24 13:18:37 -0400685 parser.error('--board/--profile must not also be a slave target.')
David Jamese2488642011-11-14 16:15:20 -0800686
David James4058b0d2011-12-08 21:24:50 -0800687 if len(set(options.slave_targets)) != len(options.slave_targets):
Mike Frysinger86509232014-05-24 13:18:37 -0400688 parser.error('--slave-boards must not have duplicates.')
David Jamese2488642011-11-14 16:15:20 -0800689
David James4058b0d2011-12-08 21:24:50 -0800690 if options.slave_targets and options.git_sync:
Mike Frysinger86509232014-05-24 13:18:37 -0400691 parser.error('--slave-boards is not compatible with --git-sync')
David Jamese2488642011-11-14 16:15:20 -0800692
David James8ece7ee2011-06-29 16:02:30 -0700693 if (options.upload_board_tarball and options.skip_upload and
694 options.board == 'amd64-host'):
Mike Frysinger86509232014-05-24 13:18:37 -0400695 parser.error('--skip-upload is not compatible with '
696 '--upload-board-tarball and --board=amd64-host')
David James8fa34ea2011-04-15 13:00:20 -0700697
David James8ece7ee2011-06-29 16:02:30 -0700698 if (options.upload_board_tarball and not options.skip_upload and
699 not options.upload.startswith('gs://')):
Mike Frysinger86509232014-05-24 13:18:37 -0400700 parser.error('--upload-board-tarball only works with gs:// URLs.\n'
701 '--upload must be a gs:// URL.')
David James8fa34ea2011-04-15 13:00:20 -0700702
Zdenek Behan86c15e92012-10-13 00:55:47 +0200703 if options.upload_board_tarball and options.prepackaged_tarball is None:
Mike Frysinger86509232014-05-24 13:18:37 -0400704 parser.error('--upload-board-tarball requires --prepackaged-tarball')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200705
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700706 if options.private:
707 if options.sync_host:
Mike Frysinger86509232014-05-24 13:18:37 -0400708 parser.error('--private and --sync-host/-s cannot be specified '
709 'together; we do not support private host prebuilts')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700710
David James8ece7ee2011-06-29 16:02:30 -0700711 if not options.upload or not options.upload.startswith('gs://'):
Mike Frysinger86509232014-05-24 13:18:37 -0400712 parser.error('--private is only valid for gs:// URLs; '
713 '--upload must be a gs:// URL.')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700714
715 if options.binhost_base_url != _BINHOST_BASE_URL:
Mike Frysinger86509232014-05-24 13:18:37 -0400716 parser.error('when using --private the --binhost-base-url '
717 'is automatically derived.')
David James27fa7d12011-06-29 17:24:14 -0700718
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700719 return options, target
David Jamesc0f158a2011-02-22 16:07:29 -0800720
Mike Frysingercc838832014-05-24 13:10:30 -0400721
Mike Frysinger86509232014-05-24 13:18:37 -0400722def main(argv):
David Jamesdb401072011-06-10 12:17:16 -0700723 # Set umask to a sane value so that files created as root are readable.
Mike Frysinger60ec1012013-10-21 00:11:10 -0400724 os.umask(0o22)
David Jamesdb401072011-06-10 12:17:16 -0700725
Mike Frysinger86509232014-05-24 13:18:37 -0400726 options, target = ParseOptions(argv)
David Jamesc0f158a2011-02-22 16:07:29 -0800727
David James05bcb2b2011-02-09 09:25:47 -0800728 # Calculate a list of Packages index files to compare against. Whenever we
729 # upload a package, we check to make sure it's not already stored in one of
730 # the packages files we uploaded. This list of packages files might contain
731 # both board and host packages.
David Jamesce093af2011-02-23 15:21:58 -0800732 pkg_indexes = _GrabAllRemotePackageIndexes(options.previous_binhost_url)
David James8c846492011-01-25 17:07:29 -0800733
David James8ece7ee2011-06-29 16:02:30 -0700734 if options.set_version:
735 version = options.set_version
736 else:
737 version = GetVersion()
Matt Tennante8179042013-10-01 15:47:32 -0700738
David Jamesc0f158a2011-02-22 16:07:29 -0800739 if options.prepend_version:
740 version = '%s-%s' % (options.prepend_version, version)
741
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700742 acl = 'public-read'
743 binhost_base_url = options.binhost_base_url
744
David Jamesadd21432013-05-21 10:04:07 -0700745 if options.private:
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700746 binhost_base_url = options.upload
David Jamesadd21432013-05-21 10:04:07 -0700747 if target:
Peter Mayo950e41a2014-02-06 21:07:33 +0000748 board_path = GetBoardOverlay(options.build_path, target)
David Jamesadd21432013-05-21 10:04:07 -0700749 acl = os.path.join(board_path, _GOOGLESTORAGE_ACL_FILE)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700750
751 uploader = PrebuiltUploader(options.upload, acl, binhost_base_url,
David James615e5b52011-06-03 11:10:15 -0700752 pkg_indexes, options.build_path,
David James27fa7d12011-06-29 17:24:14 -0700753 options.packages, options.skip_upload,
Mike Frysinger86509232014-05-24 13:18:37 -0400754 options.binhost_conf_dir, options.dryrun,
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700755 target, options.slave_targets)
David Jamesc0f158a2011-02-22 16:07:29 -0800756
David James8c846492011-01-25 17:07:29 -0800757 if options.sync_host:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700758 uploader.SyncHostPrebuilts(version, options.key, options.git_sync,
759 options.sync_binhost_conf)
David James8c846492011-01-25 17:07:29 -0800760
Chris Sosa62c8ff52012-06-04 15:03:12 -0700761 if options.board or options.slave_targets:
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700762 uploader.SyncBoardPrebuilts(version, options.key, options.git_sync,
763 options.sync_binhost_conf,
Zdenek Behan62a57792012-08-31 15:09:08 +0200764 options.upload_board_tarball,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500765 options.prepackaged_tarball,
766 options.toolchain_tarballs,
767 options.toolchain_upload_path)