blob: 9cfac639c8bf65117027438a24f1f9e302beb862 [file] [log] [blame]
David Jamesb619a782012-07-25 19:37:57 -07001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
David James8c846492011-01-25 17:07:29 -08002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Brian Harringaf019fb2012-05-10 15:06:13 -07005"""This script is used to upload host prebuilts as well as board BINHOSTS.
David James8c846492011-01-25 17:07:29 -08006
David James015af872012-06-19 15:24:36 -07007Prebuilts are uploaded using gsutil to Google Storage. After these prebuilts
8are successfully uploaded, a file is updated with the proper BINHOST version.
David James8c846492011-01-25 17:07:29 -08009
10To read more about prebuilts/binhost binary packages please refer to:
David James015af872012-06-19 15:24:36 -070011http://goto/chromeos-prebuilts
David James8c846492011-01-25 17:07:29 -080012
13Example of uploading prebuilt amd64 host files to Google Storage:
David Jamesc5cbd472012-06-19 16:25:45 -070014upload_prebuilts -p /b/cbuild/build -s -u gs://chromeos-prebuilt
David James8c846492011-01-25 17:07:29 -080015
16Example of uploading x86-dogfood binhosts to Google Storage:
David Jamesc5cbd472012-06-19 16:25:45 -070017upload_prebuilts -b x86-dogfood -p /b/cbuild/build/ -u gs://chromeos-prebuilt -g
David James8c846492011-01-25 17:07:29 -080018"""
19
Mike Frysingerff441bf2014-05-24 13:47:21 -040020from __future__ import print_function
21
Chris Sosa1dc96132012-05-11 15:40:50 -070022import datetime
Mike Frysinger540883b2014-05-24 13:46:16 -040023import functools
Chris Sosa1dc96132012-05-11 15:40:50 -070024import multiprocessing
Chris Sosa1dc96132012-05-11 15:40:50 -070025import os
26import sys
Mike Frysinger212e4292014-05-24 15:15:44 -040027import tempfile
Chris Sosa1dc96132012-05-11 15:40:50 -070028
Don Garrett88b8d782014-05-13 17:30:55 -070029from chromite.cbuildbot import constants
David James14e97772014-06-04 18:44:49 -070030from chromite.cbuildbot import commands
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
Alex Deymo075c2292014-09-04 18:31:50 -070038from chromite.lib import portage_util
Mike Frysinger8e727a32013-01-16 16:57:53 -050039from chromite.lib import toolchain
Chris Sosa1dc96132012-05-11 15:40:50 -070040
David James015af872012-06-19 15:24:36 -070041# How many times to retry uploads.
42_RETRIES = 10
43
44# Multiplier for how long to sleep (in seconds) between retries; will delay
45# (1*sleep) the first time, then (2*sleep), continuing via attempt * sleep.
46_SLEEP_TIME = 60
47
David James8c846492011-01-25 17:07:29 -080048_HOST_PACKAGES_PATH = 'chroot/var/lib/portage/pkgs'
David James05bcb2b2011-02-09 09:25:47 -080049_CATEGORIES_PATH = 'chroot/etc/portage/categories'
David James615e5b52011-06-03 11:10:15 -070050_PYM_PATH = 'chroot/usr/lib/portage/pym'
David James4058b0d2011-12-08 21:24:50 -080051_HOST_ARCH = 'amd64'
David James8c846492011-01-25 17:07:29 -080052_BOARD_PATH = 'chroot/build/%(board)s'
David James4058b0d2011-12-08 21:24:50 -080053_REL_BOARD_PATH = 'board/%(target)s/%(version)s'
54_REL_HOST_PATH = 'host/%(host_arch)s/%(target)s/%(version)s'
David James8c846492011-01-25 17:07:29 -080055# Private overlays to look at for builds to filter
56# relative to build path
57_PRIVATE_OVERLAY_DIR = 'src/private-overlays'
Gabe Black40169e62014-06-17 15:23:47 -070058_GOOGLESTORAGE_GSUTIL_FILE = 'googlestorage_acl.txt'
David James3753d942014-04-23 10:55:48 -070059_BINHOST_BASE_URL = 'gs://chromeos-prebuilt'
David James8c846492011-01-25 17:07:29 -080060_PREBUILT_BASE_DIR = 'src/third_party/chromiumos-overlay/chromeos/config/'
61# Created in the event of new host targets becoming available
62_PREBUILT_MAKE_CONF = {'amd64': os.path.join(_PREBUILT_BASE_DIR,
63 'make.conf.amd64-host')}
David James8c846492011-01-25 17:07:29 -080064
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')
Gabe Black40169e62014-06-17 15:23:47 -0700187 if acl.endswith('.xml'):
188 # Apply the passed in ACL xml file to the uploaded object.
189 gs_context.SetACL(remote_file, acl=acl)
190 else:
191 gs_context.ChangeACL(remote_file, acl_args_file=acl)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700192
Mike Frysingercc838832014-05-24 13:10:30 -0400193
Mike Frysinger540883b2014-05-24 13:46:16 -0400194def RemoteUpload(gs_context, acl, files, pool=10):
David James8c846492011-01-25 17:07:29 -0800195 """Upload to google storage.
196
197 Create a pool of process and call _GsUpload with the proper arguments.
198
199 Args:
Mike Frysinger540883b2014-05-24 13:46:16 -0400200 gs_context: A lib.gs.GSContext instance.
David Jamesfd0b0852011-02-23 11:15:36 -0800201 acl: The canned acl used for uploading. acl can be one of: "public-read",
202 "public-read-write", "authenticated-read", "bucket-owner-read",
203 "bucket-owner-full-control", or "private".
David James8c846492011-01-25 17:07:29 -0800204 files: dictionary with keys to local files and values to remote path.
205 pool: integer of maximum proesses to have at the same time.
206
207 Returns:
208 Return a set of tuple arguments of the failed uploads
209 """
Mike Frysinger540883b2014-05-24 13:46:16 -0400210 upload = functools.partial(_GsUpload, gs_context, acl)
211 tasks = [[key, value] for key, value in files.iteritems()]
212 parallel.RunTasksInProcessPool(upload, tasks, pool)
David James8c846492011-01-25 17:07:29 -0800213
214
215def GenerateUploadDict(base_local_path, base_remote_path, pkgs):
216 """Build a dictionary of local remote file key pairs to upload.
217
218 Args:
219 base_local_path: The base path to the files on the local hard drive.
Matt Tennante8179042013-10-01 15:47:32 -0700220 base_remote_path: The base path to the remote paths.
David James8c846492011-01-25 17:07:29 -0800221 pkgs: The packages to upload.
222
223 Returns:
224 Returns a dictionary of local_path/remote_path pairs
225 """
226 upload_files = {}
227 for pkg in pkgs:
228 suffix = pkg['CPV'] + '.tbz2'
229 local_path = os.path.join(base_local_path, suffix)
230 assert os.path.exists(local_path)
231 remote_path = '%s/%s' % (base_remote_path.rstrip('/'), suffix)
232 upload_files[local_path] = remote_path
233
234 return upload_files
235
Mike Frysingercc838832014-05-24 13:10:30 -0400236
Peter Mayo950e41a2014-02-06 21:07:33 +0000237def GetBoardOverlay(build_path, target):
David Jamese5867812012-10-19 12:02:20 -0700238 """Get the path to the board variant.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500239
David James8c846492011-01-25 17:07:29 -0800240 Args:
241 build_path: The path to the root of the build directory
David Jamese5867812012-10-19 12:02:20 -0700242 target: The target board as a BuildTarget object.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500243
David James8c846492011-01-25 17:07:29 -0800244 Returns:
David Jamese5867812012-10-19 12:02:20 -0700245 The last overlay configured for the given board as a string.
David James8c846492011-01-25 17:07:29 -0800246 """
David Jamese5867812012-10-19 12:02:20 -0700247 board = target.board_variant
Alex Deymo075c2292014-09-04 18:31:50 -0700248 overlays = portage_util.FindOverlays(constants.BOTH_OVERLAYS, board,
249 buildroot=build_path)
David Jamese5867812012-10-19 12:02:20 -0700250 # We only care about the last entry.
251 return overlays[-1]
David James8c846492011-01-25 17:07:29 -0800252
253
254def DeterminePrebuiltConfFile(build_path, target):
255 """Determine the prebuilt.conf file that needs to be updated for prebuilts.
256
Mike Frysinger1a736a82013-12-12 01:50:59 -0500257 Args:
258 build_path: The path to the root of the build directory
259 target: String representation of the board. This includes host and board
260 targets
David James8c846492011-01-25 17:07:29 -0800261
Mike Frysinger1a736a82013-12-12 01:50:59 -0500262 Returns:
263 A string path to a prebuilt.conf file to be updated.
David James8c846492011-01-25 17:07:29 -0800264 """
David James4058b0d2011-12-08 21:24:50 -0800265 if _HOST_ARCH == target:
David James8c846492011-01-25 17:07:29 -0800266 # We are host.
267 # Without more examples of hosts this is a kludge for now.
268 # TODO(Scottz): as new host targets come online expand this to
269 # work more like boards.
Chris Sosa471532a2011-02-01 15:10:06 -0800270 make_path = _PREBUILT_MAKE_CONF[target]
David James8c846492011-01-25 17:07:29 -0800271 else:
272 # We are a board
Peter Mayo950e41a2014-02-06 21:07:33 +0000273 board = GetBoardOverlay(build_path, target)
David James8c846492011-01-25 17:07:29 -0800274 make_path = os.path.join(board, 'prebuilt.conf')
275
276 return make_path
277
278
279def UpdateBinhostConfFile(path, key, value):
280 """Update binhost config file file with key=value.
281
282 Args:
283 path: Filename to update.
284 key: Key to update.
285 value: New value for key.
286 """
287 cwd = os.path.dirname(os.path.abspath(path))
288 filename = os.path.basename(path)
Brian Harringaf019fb2012-05-10 15:06:13 -0700289 osutils.SafeMakedirs(cwd)
David Jamesf6e8fb72013-05-10 08:58:43 -0700290 if not git.GetCurrentBranch(cwd):
291 git.CreatePushBranch(constants.STABLE_EBUILD_BRANCH, cwd, sync=False)
Brian Harring22edb442012-05-11 23:55:18 -0700292 osutils.WriteFile(path, '', mode='a')
David James8c846492011-01-25 17:07:29 -0800293 UpdateLocalFile(path, value, key)
David James67d73252013-09-19 17:33:12 -0700294 git.RunGit(cwd, ['add', filename])
Mike Frysinger109cada2013-01-17 15:50:44 -0500295 description = '%s: updating %s' % (os.path.basename(filename), key)
David James67d73252013-09-19 17:33:12 -0700296 git.RunGit(cwd, ['commit', '-m', description])
David James8c846492011-01-25 17:07:29 -0800297
298
Mike Frysinger212e4292014-05-24 15:15:44 -0400299def GenerateHtmlIndex(files, index, board, version):
300 """Given the list of |files|, generate an index.html at |index|.
301
302 Args:
303 files: The list of files to link to.
304 index: The path to the html index.
305 board: Name of the board this index is for.
306 version: Build version this index is for.
307 """
308 head = """<html>
309<head>
310 <title>Package Prebuilt Index: %(board)s / %(version)s</title>
311</head>
312<body>
313<h2>Package Prebuilt Index: %(board)s / %(version)s</h2>"""
314 head %= {
315 'board': board,
316 'version': version,
317 }
318
319 files = files + [
320 '.|Google Storage Index',
321 '..|',
322 ]
323 commands.GenerateHtmlIndex(index, files, head=head)
324
325
David Jamesce093af2011-02-23 15:21:58 -0800326def _GrabAllRemotePackageIndexes(binhost_urls):
David James05bcb2b2011-02-09 09:25:47 -0800327 """Grab all of the packages files associated with a list of binhost_urls.
328
David James05bcb2b2011-02-09 09:25:47 -0800329 Args:
330 binhost_urls: The URLs for the directories containing the Packages files we
331 want to grab.
David James05bcb2b2011-02-09 09:25:47 -0800332
333 Returns:
334 A list of PackageIndex objects.
335 """
336 pkg_indexes = []
337 for url in binhost_urls:
David James32faafe2012-06-08 14:25:03 -0700338 pkg_index = binpkg.GrabRemotePackageIndex(url)
David James05bcb2b2011-02-09 09:25:47 -0800339 if pkg_index:
340 pkg_indexes.append(pkg_index)
David James05bcb2b2011-02-09 09:25:47 -0800341 return pkg_indexes
342
343
David Jamesc0f158a2011-02-22 16:07:29 -0800344class PrebuiltUploader(object):
345 """Synchronize host and board prebuilts."""
David James8c846492011-01-25 17:07:29 -0800346
Mike Frysinger86509232014-05-24 13:18:37 -0400347 def __init__(self, upload_location, acl, binhost_base_url, pkg_indexes,
348 build_path, packages, skip_upload, binhost_conf_dir, dryrun,
Mike Frysinger8092a632014-05-24 13:25:46 -0400349 target, slave_targets, version):
David Jamesc0f158a2011-02-22 16:07:29 -0800350 """Constructor for prebuilt uploader object.
David James8c846492011-01-25 17:07:29 -0800351
David Jamesc0f158a2011-02-22 16:07:29 -0800352 This object can upload host or prebuilt files to Google Storage.
David James8c846492011-01-25 17:07:29 -0800353
David Jamesc0f158a2011-02-22 16:07:29 -0800354 Args:
355 upload_location: The upload location.
David Jamesfd0b0852011-02-23 11:15:36 -0800356 acl: The canned acl used for uploading to Google Storage. acl can be one
357 of: "public-read", "public-read-write", "authenticated-read",
Matt Tennante8179042013-10-01 15:47:32 -0700358 "bucket-owner-read", "bucket-owner-full-control", "project-private",
359 or "private" (see "gsutil help acls"). If we are not uploading to
360 Google Storage, this parameter is unused.
David Jamesfd0b0852011-02-23 11:15:36 -0800361 binhost_base_url: The URL used for downloading the prebuilts.
David Jamesc0f158a2011-02-22 16:07:29 -0800362 pkg_indexes: Old uploaded prebuilts to compare against. Instead of
363 uploading duplicate files, we just link to the old files.
David James615e5b52011-06-03 11:10:15 -0700364 build_path: The path to the directory containing the chroot.
365 packages: Packages to upload.
David James32b0b2f2011-07-13 20:56:50 -0700366 skip_upload: Don't actually upload the tarballs.
367 binhost_conf_dir: Directory where to store binhost.conf files.
Mike Frysinger86509232014-05-24 13:18:37 -0400368 dryrun: Don't push or upload prebuilts.
David James4058b0d2011-12-08 21:24:50 -0800369 target: BuildTarget managed by this builder.
370 slave_targets: List of BuildTargets managed by slave builders.
Mike Frysinger8092a632014-05-24 13:25:46 -0400371 version: A unique string, intended to be included in the upload path,
372 which identifies the version number of the uploaded prebuilts.
David Jamesc0f158a2011-02-22 16:07:29 -0800373 """
374 self._upload_location = upload_location
David Jamesfd0b0852011-02-23 11:15:36 -0800375 self._acl = acl
David Jamesc0f158a2011-02-22 16:07:29 -0800376 self._binhost_base_url = binhost_base_url
377 self._pkg_indexes = pkg_indexes
David James615e5b52011-06-03 11:10:15 -0700378 self._build_path = build_path
379 self._packages = set(packages)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500380 self._found_packages = set()
David James8ece7ee2011-06-29 16:02:30 -0700381 self._skip_upload = skip_upload
David James32b0b2f2011-07-13 20:56:50 -0700382 self._binhost_conf_dir = binhost_conf_dir
Mike Frysinger86509232014-05-24 13:18:37 -0400383 self._dryrun = dryrun
David James4058b0d2011-12-08 21:24:50 -0800384 self._target = target
385 self._slave_targets = slave_targets
Mike Frysinger8092a632014-05-24 13:25:46 -0400386 self._version = version
Mike Frysinger540883b2014-05-24 13:46:16 -0400387 self._gs_context = gs.GSContext(retries=_RETRIES, sleep=_SLEEP_TIME,
388 dry_run=self._dryrun)
389
390 def _Upload(self, local_file, remote_file):
391 """Wrapper around _GsUpload"""
392 _GsUpload(self._gs_context, self._acl, local_file, remote_file)
David James615e5b52011-06-03 11:10:15 -0700393
394 def _ShouldFilterPackage(self, pkg):
395 if not self._packages:
396 return False
397 pym_path = os.path.abspath(os.path.join(self._build_path, _PYM_PATH))
David James710b7dc2012-02-07 16:49:59 -0800398 sys.path.insert(0, pym_path)
Don Garrett25f309a2014-03-19 14:02:12 -0700399 # pylint: disable=F0401
David James615e5b52011-06-03 11:10:15 -0700400 import portage.versions
401 cat, pkgname = portage.versions.catpkgsplit(pkg['CPV'])[0:2]
402 cp = '%s/%s' % (cat, pkgname)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500403 self._found_packages.add(cp)
David James615e5b52011-06-03 11:10:15 -0700404 return pkgname not in self._packages and cp not in self._packages
David James8c846492011-01-25 17:07:29 -0800405
David Jamesc0f158a2011-02-22 16:07:29 -0800406 def _UploadPrebuilt(self, package_path, url_suffix):
407 """Upload host or board prebuilt files to Google Storage space.
David James8c846492011-01-25 17:07:29 -0800408
David Jamesc0f158a2011-02-22 16:07:29 -0800409 Args:
410 package_path: The path to the packages dir.
David Jamesce093af2011-02-23 15:21:58 -0800411 url_suffix: The remote subdirectory where we should upload the packages.
David Jamesc0f158a2011-02-22 16:07:29 -0800412 """
David Jamesc0f158a2011-02-22 16:07:29 -0800413 # Process Packages file, removing duplicates and filtered packages.
David James32faafe2012-06-08 14:25:03 -0700414 pkg_index = binpkg.GrabLocalPackageIndex(package_path)
David Jamesc0f158a2011-02-22 16:07:29 -0800415 pkg_index.SetUploadLocation(self._binhost_base_url, url_suffix)
David James615e5b52011-06-03 11:10:15 -0700416 pkg_index.RemoveFilteredPackages(self._ShouldFilterPackage)
David Jamesc0f158a2011-02-22 16:07:29 -0800417 uploads = pkg_index.ResolveDuplicateUploads(self._pkg_indexes)
Mike Frysingerf5f809a2013-02-12 13:47:37 -0500418 unmatched_pkgs = self._packages - self._found_packages
419 if unmatched_pkgs:
420 cros_build_lib.Warning('unable to match packages: %r' % unmatched_pkgs)
David James05bcb2b2011-02-09 09:25:47 -0800421
David Jamesc0f158a2011-02-22 16:07:29 -0800422 # Write Packages file.
423 tmp_packages_file = pkg_index.WriteToNamedTemporaryFile()
David James05bcb2b2011-02-09 09:25:47 -0800424
David Jamesc0f158a2011-02-22 16:07:29 -0800425 remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
David James015af872012-06-19 15:24:36 -0700426 assert remote_location.startswith('gs://')
David James05bcb2b2011-02-09 09:25:47 -0800427
David James015af872012-06-19 15:24:36 -0700428 # Build list of files to upload.
429 upload_files = GenerateUploadDict(package_path, remote_location, uploads)
430 remote_file = '%s/Packages' % remote_location.rstrip('/')
431 upload_files[tmp_packages_file.name] = remote_file
432
Mike Frysinger540883b2014-05-24 13:46:16 -0400433 RemoteUpload(self._gs_context, self._acl, upload_files)
David James8c846492011-01-25 17:07:29 -0800434
Mike Frysinger212e4292014-05-24 15:15:44 -0400435 with tempfile.NamedTemporaryFile(
436 prefix='chromite.upload_prebuilts.index.') as index:
437 GenerateHtmlIndex(
438 [x[len(remote_location) + 1:] for x in upload_files.values()],
439 index.name, self._target, self._version)
440 self._Upload(index.name, '%s/index.html' % remote_location.rstrip('/'))
441
442 link_name = 'Prebuilts[%s]: %s' % (self._target, self._version)
443 url = '%s%s/index.html' % (gs.PUBLIC_BASE_HTTPS_URL,
444 remote_location[len(gs.BASE_GS_URL):])
445 cros_build_lib.PrintBuildbotLink(link_name, url)
446
Mike Frysinger8092a632014-05-24 13:25:46 -0400447 def _UploadSdkTarball(self, board_path, url_suffix, prepackaged,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500448 toolchain_tarballs, toolchain_upload_path):
449 """Upload a tarball of the sdk at the specified path to Google Storage.
David James8fa34ea2011-04-15 13:00:20 -0700450
451 Args:
452 board_path: The path to the board dir.
453 url_suffix: The remote subdirectory where we should upload the packages.
Zdenek Behan62a57792012-08-31 15:09:08 +0200454 prepackaged: If given, a tarball that has been packaged outside of this
455 script and should be used.
Mike Frysinger9e979b92012-11-29 02:55:09 -0500456 toolchain_tarballs: List of toolchain tarballs to upload.
457 toolchain_upload_path: Path under the bucket to place toolchain tarballs.
David James8fa34ea2011-04-15 13:00:20 -0700458 """
459 remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
460 assert remote_location.startswith('gs://')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200461 boardname = os.path.basename(board_path.rstrip('/'))
462 # We do not upload non SDK board tarballs,
463 assert boardname == constants.CHROOT_BUILDER_BOARD
464 assert prepackaged is not None
Zdenek Behan62a57792012-08-31 15:09:08 +0200465
Mike Frysinger8092a632014-05-24 13:25:46 -0400466 version_str = self._version[len('chroot-'):]
Mike Frysinger8e727a32013-01-16 16:57:53 -0500467 remote_tarfile = toolchain.GetSdkURL(
468 for_gsutil=True, suburl='cros-sdk-%s.tar.xz' % (version_str,))
Zdenek Behan86c15e92012-10-13 00:55:47 +0200469 # For SDK, also upload the manifest which is guaranteed to exist
470 # by the builderstage.
Mike Frysinger540883b2014-05-24 13:46:16 -0400471 self._Upload(prepackaged + '.Manifest', remote_tarfile + '.Manifest')
472 self._Upload(prepackaged, remote_tarfile)
Zdenek Behan86c15e92012-10-13 00:55:47 +0200473
Mike Frysinger9e979b92012-11-29 02:55:09 -0500474 # Post the toolchain tarballs too.
475 for tarball in toolchain_tarballs:
476 target, local_path = tarball.split(':')
477 suburl = toolchain_upload_path % {'target': target}
478 remote_path = toolchain.GetSdkURL(for_gsutil=True, suburl=suburl)
Mike Frysinger540883b2014-05-24 13:46:16 -0400479 self._Upload(local_path, remote_path)
Mike Frysinger9e979b92012-11-29 02:55:09 -0500480
Zdenek Behan86c15e92012-10-13 00:55:47 +0200481 # Finally, also update the pointer to the latest SDK on which polling
482 # scripts rely.
David James4bc13702013-03-26 08:08:04 -0700483 with osutils.TempDir() as tmpdir:
Zdenek Behan86c15e92012-10-13 00:55:47 +0200484 pointerfile = os.path.join(tmpdir, 'cros-sdk-latest.conf')
Mike Frysinger8e727a32013-01-16 16:57:53 -0500485 remote_pointerfile = toolchain.GetSdkURL(for_gsutil=True,
486 suburl='cros-sdk-latest.conf')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200487 osutils.WriteFile(pointerfile, 'LATEST_SDK="%s"' % version_str)
Mike Frysinger540883b2014-05-24 13:46:16 -0400488 self._Upload(pointerfile, remote_pointerfile)
Zdenek Behan33a34112012-09-10 21:07:51 +0200489
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700490 def _GetTargets(self):
491 """Retuns the list of targets to use."""
492 targets = self._slave_targets[:]
493 if self._target:
494 targets.append(self._target)
495
496 return targets
497
Mike Frysinger8092a632014-05-24 13:25:46 -0400498 def SyncHostPrebuilts(self, key, git_sync, sync_binhost_conf):
David Jamesc0f158a2011-02-22 16:07:29 -0800499 """Synchronize host prebuilt files.
David James05bcb2b2011-02-09 09:25:47 -0800500
David Jamesc0f158a2011-02-22 16:07:29 -0800501 This function will sync both the standard host packages, plus the host
502 packages associated with all targets that have been "setup" with the
503 current host's chroot. For instance, if this host has been used to build
504 x86-generic, it will sync the host packages associated with
505 'i686-pc-linux-gnu'. If this host has also been used to build arm-generic,
506 it will also sync the host packages associated with
507 'armv7a-cros-linux-gnueabi'.
David James05bcb2b2011-02-09 09:25:47 -0800508
David Jamesc0f158a2011-02-22 16:07:29 -0800509 Args:
David Jamesc0f158a2011-02-22 16:07:29 -0800510 key: The variable key to update in the git file.
511 git_sync: If set, update make.conf of target to reference the latest
512 prebuilt packages generated here.
513 sync_binhost_conf: If set, update binhost config file in
514 chromiumos-overlay for the host.
515 """
David Jamese2488642011-11-14 16:15:20 -0800516 # Slave boards are listed before the master board so that the master board
517 # takes priority (i.e. x86-generic preflight host prebuilts takes priority
518 # over preflight host prebuilts from other builders.)
519 binhost_urls = []
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700520 for target in self._GetTargets():
Mike Frysinger8092a632014-05-24 13:25:46 -0400521 url_suffix = _REL_HOST_PATH % {'version': self._version,
David James4058b0d2011-12-08 21:24:50 -0800522 'host_arch': _HOST_ARCH,
523 'target': target}
David Jamese2488642011-11-14 16:15:20 -0800524 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David James05bcb2b2011-02-09 09:25:47 -0800525
Mike Frysinger540883b2014-05-24 13:46:16 -0400526 if self._target == target and not self._skip_upload:
David Jamese2488642011-11-14 16:15:20 -0800527 # Upload prebuilts.
528 package_path = os.path.join(self._build_path, _HOST_PACKAGES_PATH)
529 self._UploadPrebuilt(package_path, packages_url_suffix)
David James8ece7ee2011-06-29 16:02:30 -0700530
David Jamese2488642011-11-14 16:15:20 -0800531 # Record URL where prebuilts were uploaded.
532 binhost_urls.append('%s/%s/' % (self._binhost_base_url.rstrip('/'),
533 packages_url_suffix.rstrip('/')))
534
David James20b2b6f2011-11-18 15:11:58 -0800535 binhost = ' '.join(binhost_urls)
David James8ece7ee2011-06-29 16:02:30 -0700536 if git_sync:
537 git_file = os.path.join(self._build_path,
David James4058b0d2011-12-08 21:24:50 -0800538 _PREBUILT_MAKE_CONF[_HOST_ARCH])
Mike Frysinger86509232014-05-24 13:18:37 -0400539 RevGitFile(git_file, {key: binhost}, dryrun=self._dryrun)
David James8ece7ee2011-06-29 16:02:30 -0700540 if sync_binhost_conf:
David James32b0b2f2011-07-13 20:56:50 -0700541 binhost_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James4058b0d2011-12-08 21:24:50 -0800542 'host', '%s-%s.conf' % (_HOST_ARCH, key))
David Jamese2488642011-11-14 16:15:20 -0800543 UpdateBinhostConfFile(binhost_conf, key, binhost)
David Jamesc0f158a2011-02-22 16:07:29 -0800544
Mike Frysinger8092a632014-05-24 13:25:46 -0400545 def SyncBoardPrebuilts(self, key, git_sync, sync_binhost_conf,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500546 upload_board_tarball, prepackaged_board,
547 toolchain_tarballs, toolchain_upload_path):
David Jamesc0f158a2011-02-22 16:07:29 -0800548 """Synchronize board prebuilt files.
549
550 Args:
David Jamesc0f158a2011-02-22 16:07:29 -0800551 key: The variable key to update in the git file.
552 git_sync: If set, update make.conf of target to reference the latest
553 prebuilt packages generated here.
554 sync_binhost_conf: If set, update binhost config file in
555 chromiumos-overlay for the current board.
David James8fa34ea2011-04-15 13:00:20 -0700556 upload_board_tarball: Include a tarball of the board in our upload.
Zdenek Behan62a57792012-08-31 15:09:08 +0200557 prepackaged_board: A tarball of the board built outside of this script.
Mike Frysinger9e979b92012-11-29 02:55:09 -0500558 toolchain_tarballs: A list of toolchain tarballs to upload.
559 toolchain_upload_path: Path under the bucket to place toolchain tarballs.
David Jamesc0f158a2011-02-22 16:07:29 -0800560 """
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700561 for target in self._GetTargets():
David Jamese2488642011-11-14 16:15:20 -0800562 board_path = os.path.join(self._build_path,
David James4058b0d2011-12-08 21:24:50 -0800563 _BOARD_PATH % {'board': target.board_variant})
David Jamese2488642011-11-14 16:15:20 -0800564 package_path = os.path.join(board_path, 'packages')
Mike Frysinger8092a632014-05-24 13:25:46 -0400565 url_suffix = _REL_BOARD_PATH % {'target': target,
566 'version': self._version}
David Jamese2488642011-11-14 16:15:20 -0800567 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David James8fa34ea2011-04-15 13:00:20 -0700568
Matt Tennante8179042013-10-01 15:47:32 -0700569 # Process the target board differently if it is the main --board.
Mike Frysinger540883b2014-05-24 13:46:16 -0400570 if self._target == target and not self._skip_upload:
Matt Tennante8179042013-10-01 15:47:32 -0700571 # This strips "chroot" prefix because that is sometimes added as the
572 # --prepend-version argument (e.g. by chromiumos-sdk bot).
573 # TODO(build): Clean it up to be less hard-coded.
Mike Frysinger8092a632014-05-24 13:25:46 -0400574 version_str = self._version[len('chroot-'):]
Mike Frysinger9e979b92012-11-29 02:55:09 -0500575
David Jamese2488642011-11-14 16:15:20 -0800576 # Upload board tarballs in the background.
577 if upload_board_tarball:
Mike Frysinger9e979b92012-11-29 02:55:09 -0500578 if toolchain_upload_path:
579 toolchain_upload_path %= {'version': version_str}
580 tar_process = multiprocessing.Process(
581 target=self._UploadSdkTarball,
Mike Frysinger8092a632014-05-24 13:25:46 -0400582 args=(board_path, url_suffix, prepackaged_board,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500583 toolchain_tarballs, toolchain_upload_path))
David Jamese2488642011-11-14 16:15:20 -0800584 tar_process.start()
David James8fa34ea2011-04-15 13:00:20 -0700585
David Jamese2488642011-11-14 16:15:20 -0800586 # Upload prebuilts.
587 self._UploadPrebuilt(package_path, packages_url_suffix)
David James8fa34ea2011-04-15 13:00:20 -0700588
David Jamese2488642011-11-14 16:15:20 -0800589 # Make sure we finished uploading the board tarballs.
590 if upload_board_tarball:
591 tar_process.join()
592 assert tar_process.exitcode == 0
593 # TODO(zbehan): This should be done cleaner.
Zdenek Behan33a34112012-09-10 21:07:51 +0200594 if target.board == constants.CHROOT_BUILDER_BOARD:
David Jamese2488642011-11-14 16:15:20 -0800595 sdk_conf = os.path.join(self._build_path, self._binhost_conf_dir,
Mike Frysinger5b34d732013-01-17 15:11:58 -0500596 'host/sdk_version.conf')
597 sdk_settings = {
Mike Frysinger9e979b92012-11-29 02:55:09 -0500598 'SDK_LATEST_VERSION': version_str,
599 'TC_PATH': toolchain_upload_path,
Mike Frysinger5b34d732013-01-17 15:11:58 -0500600 }
Mike Frysinger86509232014-05-24 13:18:37 -0400601 RevGitFile(sdk_conf, sdk_settings, dryrun=self._dryrun)
David Jamesc0f158a2011-02-22 16:07:29 -0800602
David Jamese2488642011-11-14 16:15:20 -0800603 # Record URL where prebuilts were uploaded.
604 url_value = '%s/%s/' % (self._binhost_base_url.rstrip('/'),
605 packages_url_suffix.rstrip('/'))
606
607 if git_sync:
David James4058b0d2011-12-08 21:24:50 -0800608 git_file = DeterminePrebuiltConfFile(self._build_path, target)
Mike Frysinger86509232014-05-24 13:18:37 -0400609 RevGitFile(git_file, {key: url_value}, dryrun=self._dryrun)
Matt Tennante8179042013-10-01 15:47:32 -0700610
David Jamese2488642011-11-14 16:15:20 -0800611 if sync_binhost_conf:
Matt Tennante8179042013-10-01 15:47:32 -0700612 # Update the binhost configuration file in git.
David Jamese2488642011-11-14 16:15:20 -0800613 binhost_conf = os.path.join(self._build_path, self._binhost_conf_dir,
David James4058b0d2011-12-08 21:24:50 -0800614 'target', '%s-%s.conf' % (target, key))
David Jamese2488642011-11-14 16:15:20 -0800615 UpdateBinhostConfFile(binhost_conf, key, url_value)
David James05bcb2b2011-02-09 09:25:47 -0800616
617
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700618def _AddSlaveBoard(_option, _opt_str, value, parser):
619 """Callback that adds a slave board to the list of slave targets."""
David James4058b0d2011-12-08 21:24:50 -0800620 parser.values.slave_targets.append(BuildTarget(value))
621
622
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700623def _AddSlaveProfile(_option, _opt_str, value, parser):
624 """Callback that adds a slave profile to the list of slave targets."""
David James4058b0d2011-12-08 21:24:50 -0800625 if not parser.values.slave_targets:
Mike Frysinger86509232014-05-24 13:18:37 -0400626 parser.error('Must specify --slave-board before --slave-profile')
David James4058b0d2011-12-08 21:24:50 -0800627 if parser.values.slave_targets[-1].profile is not None:
Mike Frysinger86509232014-05-24 13:18:37 -0400628 parser.error('Cannot specify --slave-profile twice for same board')
David James4058b0d2011-12-08 21:24:50 -0800629 parser.values.slave_targets[-1].profile = value
630
631
Mike Frysinger86509232014-05-24 13:18:37 -0400632def ParseOptions(argv):
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700633 """Returns options given by the user and the target specified.
634
Mike Frysinger86509232014-05-24 13:18:37 -0400635 Args:
636 argv: The args to parse.
637
Mike Frysinger1a736a82013-12-12 01:50:59 -0500638 Returns:
639 A tuple containing a parsed options object and BuildTarget.
640 The target instance is None if no board is specified.
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700641 """
Mike Frysinger86509232014-05-24 13:18:37 -0400642 parser = commandline.OptionParser()
David James8c846492011-01-25 17:07:29 -0800643 parser.add_option('-H', '--binhost-base-url', dest='binhost_base_url',
644 default=_BINHOST_BASE_URL,
645 help='Base URL to use for binhost in make.conf updates')
646 parser.add_option('', '--previous-binhost-url', action='append',
647 default=[], dest='previous_binhost_url',
648 help='Previous binhost URL')
649 parser.add_option('-b', '--board', dest='board', default=None,
650 help='Board type that was built on this machine')
Zdenek Behan62a57792012-08-31 15:09:08 +0200651 parser.add_option('-B', '--prepackaged-tarball', dest='prepackaged_tarball',
652 default=None,
653 help='Board tarball prebuilt outside of this script.')
Mike Frysinger9e979b92012-11-29 02:55:09 -0500654 parser.add_option('--toolchain-tarball', dest='toolchain_tarballs',
655 action='append', default=[],
656 help='Redistributable toolchain tarball.')
657 parser.add_option('--toolchain-upload-path', default='',
658 help='Path to place toolchain tarballs in the sdk tree.')
David James4058b0d2011-12-08 21:24:50 -0800659 parser.add_option('', '--profile', dest='profile', default=None,
660 help='Profile that was built on this machine')
661 parser.add_option('', '--slave-board', default=[], action='callback',
662 dest='slave_targets', type='string',
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700663 callback=_AddSlaveBoard,
David James4058b0d2011-12-08 21:24:50 -0800664 help='Board type that was built on a slave machine. To '
665 'add a profile to this board, use --slave-profile.')
666 parser.add_option('', '--slave-profile', action='callback', type='string',
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700667 callback=_AddSlaveProfile,
David James4058b0d2011-12-08 21:24:50 -0800668 help='Board profile that was built on a slave machine. '
669 'Applies to previous slave board.')
David James8c846492011-01-25 17:07:29 -0800670 parser.add_option('-p', '--build-path', dest='build_path',
David James05bcb2b2011-02-09 09:25:47 -0800671 help='Path to the directory containing the chroot')
David James615e5b52011-06-03 11:10:15 -0700672 parser.add_option('', '--packages', action='append',
673 default=[], dest='packages',
674 help='Only include the specified packages. '
675 '(Default is to include all packages.)')
David James8c846492011-01-25 17:07:29 -0800676 parser.add_option('-s', '--sync-host', dest='sync_host',
677 default=False, action='store_true',
678 help='Sync host prebuilts')
679 parser.add_option('-g', '--git-sync', dest='git_sync',
680 default=False, action='store_true',
David Jamese2488642011-11-14 16:15:20 -0800681 help='Enable git version sync (This commits to a repo.) '
682 'This is used by full builders to commit directly '
683 'to board overlays.')
David James8c846492011-01-25 17:07:29 -0800684 parser.add_option('-u', '--upload', dest='upload',
685 default=None,
686 help='Upload location')
687 parser.add_option('-V', '--prepend-version', dest='prepend_version',
688 default=None,
689 help='Add an identifier to the front of the version')
690 parser.add_option('-f', '--filters', dest='filters', action='store_true',
691 default=False,
692 help='Turn on filtering of private ebuild packages')
693 parser.add_option('-k', '--key', dest='key',
694 default='PORTAGE_BINHOST',
695 help='Key to update in make.conf / binhost.conf')
David James8ece7ee2011-06-29 16:02:30 -0700696 parser.add_option('', '--set-version', dest='set_version',
697 default=None,
698 help='Specify the version string')
David James8c846492011-01-25 17:07:29 -0800699 parser.add_option('', '--sync-binhost-conf', dest='sync_binhost_conf',
700 default=False, action='store_true',
David Jamese2488642011-11-14 16:15:20 -0800701 help='Update binhost.conf in chromiumos-overlay or '
702 'chromeos-overlay. Commit the changes, but don\'t '
703 'push them. This is used for preflight binhosts.')
David James32b0b2f2011-07-13 20:56:50 -0700704 parser.add_option('', '--binhost-conf-dir', dest='binhost_conf_dir',
David James32b0b2f2011-07-13 20:56:50 -0700705 help='Directory to commit binhost config with '
706 '--sync-binhost-conf.')
David Jamesfd0b0852011-02-23 11:15:36 -0800707 parser.add_option('-P', '--private', dest='private', action='store_true',
708 default=False, help='Mark gs:// uploads as private.')
David James8ece7ee2011-06-29 16:02:30 -0700709 parser.add_option('', '--skip-upload', dest='skip_upload',
710 action='store_true', default=False,
711 help='Skip upload step.')
David James8fa34ea2011-04-15 13:00:20 -0700712 parser.add_option('', '--upload-board-tarball', dest='upload_board_tarball',
713 action='store_true', default=False,
714 help='Upload board tarball to Google Storage.')
Mike Frysinger86509232014-05-24 13:18:37 -0400715 parser.add_option('-n', '--dry-run', dest='dryrun',
David James27fa7d12011-06-29 17:24:14 -0700716 action='store_true', default=False,
717 help='Don\'t push or upload prebuilts.')
David James8c846492011-01-25 17:07:29 -0800718
Mike Frysinger86509232014-05-24 13:18:37 -0400719 options, args = parser.parse_args(argv)
David James8c846492011-01-25 17:07:29 -0800720 if not options.build_path:
Mike Frysinger86509232014-05-24 13:18:37 -0400721 parser.error('you need provide a chroot path')
David James8ece7ee2011-06-29 16:02:30 -0700722 if not options.upload and not options.skip_upload:
Mike Frysinger86509232014-05-24 13:18:37 -0400723 parser.error('you need to provide an upload location using -u')
David James8ece7ee2011-06-29 16:02:30 -0700724 if not options.set_version and options.skip_upload:
Mike Frysinger86509232014-05-24 13:18:37 -0400725 parser.error('If you are using --skip-upload, you must specify a '
726 'version number using --set-version.')
David James9417f272011-05-26 13:24:47 -0700727 if args:
Mike Frysinger86509232014-05-24 13:18:37 -0400728 parser.error('invalid arguments passed to upload_prebuilts: %r' % args)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700729
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700730 target = None
731 if options.board:
732 target = BuildTarget(options.board, options.profile)
733
734 if target in options.slave_targets:
Mike Frysinger86509232014-05-24 13:18:37 -0400735 parser.error('--board/--profile must not also be a slave target.')
David Jamese2488642011-11-14 16:15:20 -0800736
David James4058b0d2011-12-08 21:24:50 -0800737 if len(set(options.slave_targets)) != len(options.slave_targets):
Mike Frysinger86509232014-05-24 13:18:37 -0400738 parser.error('--slave-boards must not have duplicates.')
David Jamese2488642011-11-14 16:15:20 -0800739
David James4058b0d2011-12-08 21:24:50 -0800740 if options.slave_targets and options.git_sync:
Mike Frysinger86509232014-05-24 13:18:37 -0400741 parser.error('--slave-boards is not compatible with --git-sync')
David Jamese2488642011-11-14 16:15:20 -0800742
David James8ece7ee2011-06-29 16:02:30 -0700743 if (options.upload_board_tarball and options.skip_upload and
744 options.board == 'amd64-host'):
Mike Frysinger86509232014-05-24 13:18:37 -0400745 parser.error('--skip-upload is not compatible with '
746 '--upload-board-tarball and --board=amd64-host')
David James8fa34ea2011-04-15 13:00:20 -0700747
David James8ece7ee2011-06-29 16:02:30 -0700748 if (options.upload_board_tarball and not options.skip_upload and
749 not options.upload.startswith('gs://')):
Mike Frysinger86509232014-05-24 13:18:37 -0400750 parser.error('--upload-board-tarball only works with gs:// URLs.\n'
751 '--upload must be a gs:// URL.')
David James8fa34ea2011-04-15 13:00:20 -0700752
Zdenek Behan86c15e92012-10-13 00:55:47 +0200753 if options.upload_board_tarball and options.prepackaged_tarball is None:
Mike Frysinger86509232014-05-24 13:18:37 -0400754 parser.error('--upload-board-tarball requires --prepackaged-tarball')
Zdenek Behan86c15e92012-10-13 00:55:47 +0200755
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700756 if options.private:
757 if options.sync_host:
Mike Frysinger86509232014-05-24 13:18:37 -0400758 parser.error('--private and --sync-host/-s cannot be specified '
759 'together; we do not support private host prebuilts')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700760
David James8ece7ee2011-06-29 16:02:30 -0700761 if not options.upload or not options.upload.startswith('gs://'):
Mike Frysinger86509232014-05-24 13:18:37 -0400762 parser.error('--private is only valid for gs:// URLs; '
763 '--upload must be a gs:// URL.')
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700764
765 if options.binhost_base_url != _BINHOST_BASE_URL:
Mike Frysinger86509232014-05-24 13:18:37 -0400766 parser.error('when using --private the --binhost-base-url '
767 'is automatically derived.')
David James27fa7d12011-06-29 17:24:14 -0700768
David Jamesc31168e2014-06-05 14:40:05 -0700769 if options.sync_binhost_conf and not options.binhost_conf_dir:
770 parser.error('--sync-binhost-conf requires --binhost-conf-dir')
771
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700772 return options, target
David Jamesc0f158a2011-02-22 16:07:29 -0800773
Mike Frysingercc838832014-05-24 13:10:30 -0400774
Mike Frysinger86509232014-05-24 13:18:37 -0400775def main(argv):
David Jamesdb401072011-06-10 12:17:16 -0700776 # Set umask to a sane value so that files created as root are readable.
Mike Frysinger60ec1012013-10-21 00:11:10 -0400777 os.umask(0o22)
David Jamesdb401072011-06-10 12:17:16 -0700778
Mike Frysinger86509232014-05-24 13:18:37 -0400779 options, target = ParseOptions(argv)
David Jamesc0f158a2011-02-22 16:07:29 -0800780
David James05bcb2b2011-02-09 09:25:47 -0800781 # Calculate a list of Packages index files to compare against. Whenever we
782 # upload a package, we check to make sure it's not already stored in one of
783 # the packages files we uploaded. This list of packages files might contain
784 # both board and host packages.
David Jamesce093af2011-02-23 15:21:58 -0800785 pkg_indexes = _GrabAllRemotePackageIndexes(options.previous_binhost_url)
David James8c846492011-01-25 17:07:29 -0800786
David James8ece7ee2011-06-29 16:02:30 -0700787 if options.set_version:
788 version = options.set_version
789 else:
790 version = GetVersion()
Matt Tennante8179042013-10-01 15:47:32 -0700791
David Jamesc0f158a2011-02-22 16:07:29 -0800792 if options.prepend_version:
793 version = '%s-%s' % (options.prepend_version, version)
794
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700795 acl = 'public-read'
796 binhost_base_url = options.binhost_base_url
797
David Jamesadd21432013-05-21 10:04:07 -0700798 if options.private:
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700799 binhost_base_url = options.upload
David Jamesadd21432013-05-21 10:04:07 -0700800 if target:
Peter Mayo950e41a2014-02-06 21:07:33 +0000801 board_path = GetBoardOverlay(options.build_path, target)
Gabe Black40169e62014-06-17 15:23:47 -0700802 acl = os.path.join(board_path, _GOOGLESTORAGE_GSUTIL_FILE)
Scott Zawalskiab1bed32011-03-16 15:24:24 -0700803
804 uploader = PrebuiltUploader(options.upload, acl, binhost_base_url,
David James615e5b52011-06-03 11:10:15 -0700805 pkg_indexes, options.build_path,
David James27fa7d12011-06-29 17:24:14 -0700806 options.packages, options.skip_upload,
Mike Frysinger86509232014-05-24 13:18:37 -0400807 options.binhost_conf_dir, options.dryrun,
Mike Frysinger8092a632014-05-24 13:25:46 -0400808 target, options.slave_targets, version)
David Jamesc0f158a2011-02-22 16:07:29 -0800809
David James8c846492011-01-25 17:07:29 -0800810 if options.sync_host:
Mike Frysinger8092a632014-05-24 13:25:46 -0400811 uploader.SyncHostPrebuilts(options.key, options.git_sync,
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700812 options.sync_binhost_conf)
David James8c846492011-01-25 17:07:29 -0800813
Chris Sosa62c8ff52012-06-04 15:03:12 -0700814 if options.board or options.slave_targets:
Mike Frysinger8092a632014-05-24 13:25:46 -0400815 uploader.SyncBoardPrebuilts(options.key, options.git_sync,
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700816 options.sync_binhost_conf,
Zdenek Behan62a57792012-08-31 15:09:08 +0200817 options.upload_board_tarball,
Mike Frysinger9e979b92012-11-29 02:55:09 -0500818 options.prepackaged_tarball,
819 options.toolchain_tarballs,
820 options.toolchain_upload_path)