OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """CBuildbot is wrapper around the build process used by the pre-flight queue""" | 7 """CBuildbot is wrapper around the build process used by the pre-flight queue""" |
8 | 8 |
9 import errno | 9 import errno |
10 import heapq | 10 import heapq |
11 import re | 11 import re |
12 import optparse | 12 import optparse |
13 import os | 13 import os |
14 import shutil | 14 import shutil |
15 import sys | 15 import sys |
16 | 16 |
17 import cbuildbot_comm | 17 import cbuildbot_comm |
18 from cbuildbot_config import config | 18 from cbuildbot_config import config |
19 | 19 |
20 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) | 20 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) |
21 from cros_build_lib import (Die, Info, ReinterpretPathForChroot, RunCommand, | 21 from cros_build_lib import (Die, Info, ReinterpretPathForChroot, RunCommand, |
22 Warning) | 22 Warning) |
23 | 23 |
24 _DEFAULT_RETRIES = 3 | 24 _DEFAULT_RETRIES = 3 |
25 _PACKAGE_FILE = '%(buildroot)s/src/scripts/cbuildbot_package.list' | 25 _PACKAGE_FILE = '%(buildroot)s/src/scripts/cbuildbot_package.list' |
26 ARCHIVE_BASE = '/var/www/archive' | 26 ARCHIVE_BASE = '/var/www/archive' |
27 ARCHIVE_COUNT = 10 | 27 ARCHIVE_COUNT = 10 |
| 28 PUBLIC_OVERLAY = '%(buildroot)s/src/third_party/chromiumos-overlay' |
| 29 PRIVATE_OVERLAY = '%(buildroot)s/src/private-overlays/chromeos-overlay' |
28 | 30 |
29 # Currently, both the full buildbot and the preflight buildbot store their | 31 # Currently, both the full buildbot and the preflight buildbot store their |
30 # data in a variable named PORTAGE_BINHOST, but they're in different files. | 32 # data in a variable named PORTAGE_BINHOST, but they're in different files. |
31 # We're planning on joining the two files soon and renaming the full binhost | 33 # We're planning on joining the two files soon and renaming the full binhost |
32 # to FULL_BINHOST. | 34 # to FULL_BINHOST. |
33 _FULL_BINHOST = 'PORTAGE_BINHOST' | 35 _FULL_BINHOST = 'PORTAGE_BINHOST' |
34 _PREFLIGHT_BINHOST = 'PORTAGE_BINHOST' | 36 _PREFLIGHT_BINHOST = 'PORTAGE_BINHOST' |
35 | 37 |
36 # ======================== Utility functions ================================ | 38 # ======================== Utility functions ================================ |
37 | 39 |
| 40 def _PrintFile(path): |
| 41 """Prints out the contents of a file to stderr.""" |
| 42 file_handle = open(path) |
| 43 print >> sys.stderr, file_handle.read() |
| 44 file_handle.close() |
| 45 sys.stderr.flush() |
| 46 |
| 47 |
38 def MakeDir(path, parents=False): | 48 def MakeDir(path, parents=False): |
39 """Basic wrapper around os.mkdirs. | 49 """Basic wrapper around os.mkdirs. |
40 | 50 |
41 Keyword arguments: | 51 Keyword arguments: |
42 path -- Path to create. | 52 path -- Path to create. |
43 parents -- Follow mkdir -p logic. | 53 parents -- Follow mkdir -p logic. |
44 | 54 |
45 """ | 55 """ |
46 try: | 56 try: |
47 os.makedirs(path) | 57 os.makedirs(path) |
(...skipping 21 matching lines...) Expand all Loading... |
69 RunCommand(['repo', '--trace', 'sync'], cwd=buildroot) | 79 RunCommand(['repo', '--trace', 'sync'], cwd=buildroot) |
70 retries = 0 | 80 retries = 0 |
71 except: | 81 except: |
72 retries -= 1 | 82 retries -= 1 |
73 if retries > 0: | 83 if retries > 0: |
74 Warning('CBUILDBOT -- Repo Sync Failed, retrying') | 84 Warning('CBUILDBOT -- Repo Sync Failed, retrying') |
75 else: | 85 else: |
76 Warning('CBUILDBOT -- Retries exhausted') | 86 Warning('CBUILDBOT -- Retries exhausted') |
77 raise | 87 raise |
78 | 88 |
79 # Output manifest | |
80 RunCommand(['repo', 'manifest', '-r', '-o', '-'], cwd=buildroot) | |
81 | |
82 # =========================== Command Helpers ================================= | 89 # =========================== Command Helpers ================================= |
83 | 90 |
84 def _GetAllGitRepos(buildroot, debug=False): | 91 def _GetAllGitRepos(buildroot, debug=False): |
85 """Returns a list of tuples containing [git_repo, src_path].""" | 92 """Returns a list of tuples containing [git_repo, src_path].""" |
86 manifest_tuples = [] | 93 manifest_tuples = [] |
87 # Gets all the git repos from a full repo manifest. | 94 # Gets all the git repos from a full repo manifest. |
88 repo_cmd = "repo manifest -o -".split() | 95 repo_cmd = "repo manifest -o -".split() |
89 output = RunCommand(repo_cmd, cwd=buildroot, redirect_stdout=True, | 96 output = RunCommand(repo_cmd, cwd=buildroot, redirect_stdout=True, |
90 redirect_stderr=True, print_cmd=debug) | 97 redirect_stderr=True, print_cmd=debug) |
91 | 98 |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 for mount_pt_str in mount_pts_in_buildroot.splitlines(): | 278 for mount_pt_str in mount_pts_in_buildroot.splitlines(): |
272 mount_pt = mount_pt_str.rpartition(' type ')[0].partition(' on ')[2] | 279 mount_pt = mount_pt_str.rpartition(' type ')[0].partition(' on ')[2] |
273 RunCommand(['sudo', 'umount', '-l', mount_pt], error_ok=True) | 280 RunCommand(['sudo', 'umount', '-l', mount_pt], error_ok=True) |
274 | 281 |
275 | 282 |
276 def _WipeOldOutput(buildroot): | 283 def _WipeOldOutput(buildroot): |
277 """Wipes out build output directories.""" | 284 """Wipes out build output directories.""" |
278 RunCommand(['rm', '-rf', 'src/build/images'], cwd=buildroot) | 285 RunCommand(['rm', '-rf', 'src/build/images'], cwd=buildroot) |
279 | 286 |
280 | 287 |
| 288 def _GetChromeOSVersion(buildroot): |
| 289 """Returns the tuple version of the Chrome OS version of the buildroot.""" |
| 290 cwd = os.path.join(buildroot, 'src', 'scripts') |
| 291 version_cmd = './chromeos_version.sh' |
| 292 output = RunCommand(version_cmd, cwd=cwd, redirect_stdout=True, |
| 293 redirect_stderr=True) |
| 294 version_re = re.compile('\s+CHROMEOS_VERSION_STRING=' |
| 295 '(\d+)\.(\d+)\.(\d+)\.(\w+)') |
| 296 for line in output.splitlines(): |
| 297 match = version_re.match(line) |
| 298 if match: |
| 299 return match.group(1), match.group(2), match.group(3), match.group(4) |
| 300 |
| 301 raise Exception('Chrome OS version not found.') |
| 302 |
| 303 |
| 304 def _GetManifestPath(buildroot): |
| 305 """Returns the relative path that a manifest should be saved into.""" |
| 306 version_tuple = _GetChromeOSVersion(buildroot) |
| 307 (major, minor, branch, patch) = version_tuple |
| 308 relative_path = os.path.join('.'.join([major, minor]), |
| 309 '%s.xml' % '.'.join(version_tuple)) |
| 310 return relative_path |
| 311 |
| 312 |
281 # =========================== Main Commands =================================== | 313 # =========================== Main Commands =================================== |
282 | 314 |
283 | 315 |
284 def _PreFlightRinse(buildroot, board, tracking_branch, overlays): | 316 def _PreFlightRinse(buildroot, board, tracking_branch, overlays): |
285 """Cleans up any leftover state from previous runs.""" | 317 """Cleans up any leftover state from previous runs.""" |
286 _GitCleanup(buildroot, board, tracking_branch, overlays) | 318 _GitCleanup(buildroot, board, tracking_branch, overlays) |
287 _CleanUpMountPoints(buildroot) | 319 _CleanUpMountPoints(buildroot) |
288 RunCommand(['sudo', 'killall', 'kvm'], error_ok=True) | 320 RunCommand(['sudo', 'killall', 'kvm'], error_ok=True) |
289 | 321 |
290 | 322 |
291 def _FullCheckout(buildroot, tracking_branch, | 323 def _FullCheckout(buildroot, tracking_branch, |
292 retries=_DEFAULT_RETRIES, | 324 retries=_DEFAULT_RETRIES, |
293 url='http://git.chromium.org/git/manifest'): | 325 url='http://git.chromium.org/git/manifest'): |
294 """Performs a full checkout and clobbers any previous checkouts.""" | 326 """Performs a full checkout and clobbers any previous checkouts.""" |
295 RunCommand(['sudo', 'rm', '-rf', buildroot]) | 327 RunCommand(['sudo', 'rm', '-rf', buildroot]) |
296 MakeDir(buildroot, parents=True) | 328 MakeDir(buildroot, parents=True) |
297 branch = tracking_branch.split('/'); | 329 branch = tracking_branch.split('/'); |
298 RunCommand(['repo', 'init', '-u', | 330 RunCommand(['repo', 'init', '-u', |
299 url, '-b', | 331 url, '-b', |
300 '%s' % branch[-1]], cwd=buildroot, input='\n\ny\n') | 332 '%s' % branch[-1]], cwd=buildroot, input='\n\ny\n') |
301 RepoSync(buildroot, retries) | 333 RepoSync(buildroot, retries) |
302 | 334 |
303 | 335 |
304 def _IncrementalCheckout(buildroot, retries=_DEFAULT_RETRIES): | 336 def _IncrementalCheckout(buildroot, retries=_DEFAULT_RETRIES): |
305 """Performs a checkout without clobbering previous checkout.""" | 337 """Performs a checkout without clobbering previous checkout.""" |
306 RepoSync(buildroot, retries) | 338 RepoSync(buildroot, retries) |
307 | 339 |
308 | 340 |
| 341 def _DumpManifest(buildroot, url): |
| 342 """Stores the manifest in the public | private overlay depending on url.""" |
| 343 public_overlay = PUBLIC_OVERLAY % {'buildroot': buildroot} |
| 344 private_overlay = PRIVATE_OVERLAY % {'buildroot': buildroot} |
| 345 if url.endswith('manifest-internal'): |
| 346 overlay = PRIVATE_OVERLAY % {'buildroot': buildroot} |
| 347 else: |
| 348 overlay = PUBLIC_OVERLAY % {'buildroot': buildroot} |
| 349 |
| 350 # Generate paths for manifests. |
| 351 relative_path = _GetManifestPath(buildroot) |
| 352 manifest_path = os.path.join(overlay, 'manifests', relative_path) |
| 353 symlink_path = os.path.join(overlay, 'manifests', 'LATEST') |
| 354 if not os.path.isdir(os.path.dirname(manifest_path)): |
| 355 os.makedirs(os.path.dirname(manifest_path)) |
| 356 |
| 357 # Dump the manifest and create a symlink to it. |
| 358 RunCommand(['repo', 'manifest', '-r', '-o', manifest_path], cwd=buildroot) |
| 359 if os.path.exists(symlink_path): |
| 360 os.unlink(symlink_path) |
| 361 |
| 362 os.symlink(relative_path, symlink_path) |
| 363 |
| 364 # Add it to git and print it to stderr. |
| 365 RunCommand(['git', 'add', os.path.join('manifests', relative_path)], |
| 366 cwd=overlay) |
| 367 RunCommand(['git', 'add', os.path.join('manifests', 'LATEST')], cwd=overlay) |
| 368 _PrintFile(manifest_path) |
| 369 |
| 370 |
309 def _MakeChroot(buildroot): | 371 def _MakeChroot(buildroot): |
310 """Wrapper around make_chroot.""" | 372 """Wrapper around make_chroot.""" |
311 cwd = os.path.join(buildroot, 'src', 'scripts') | 373 cwd = os.path.join(buildroot, 'src', 'scripts') |
312 RunCommand(['./make_chroot', '--fast'], cwd=cwd) | 374 RunCommand(['./make_chroot', '--fast'], cwd=cwd) |
313 | 375 |
314 | 376 |
315 def _GetPortageEnvVar(buildroot, board, envvar): | 377 def _GetPortageEnvVar(buildroot, board, envvar): |
316 """Get a portage environment variable for the specified board, if any. | 378 """Get a portage environment variable for the specified board, if any. |
317 | 379 |
318 buildroot: The root directory where the build occurs. Must be an absolute | 380 buildroot: The root directory where the build occurs. Must be an absolute |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 """Return the list of overlays to use for a given buildbot. | 582 """Return the list of overlays to use for a given buildbot. |
521 | 583 |
522 Args: | 584 Args: |
523 buildroot: The root directory where the build occurs. Must be an absolute | 585 buildroot: The root directory where the build occurs. Must be an absolute |
524 path. | 586 path. |
525 overlays: A string describing which overlays you want. | 587 overlays: A string describing which overlays you want. |
526 'private': Just the private overlay. | 588 'private': Just the private overlay. |
527 'public': Just the public overlay. | 589 'public': Just the public overlay. |
528 'both': Both the public and private overlays. | 590 'both': Both the public and private overlays. |
529 """ | 591 """ |
530 public_overlay = '%s/src/third_party/chromiumos-overlay' % buildroot | 592 public_overlay = PUBLIC_OVERLAY % {'buildroot': buildroot} |
531 private_overlay = '%s/src/private-overlays/chromeos-overlay' % buildroot | 593 private_overlay = PRIVATE_OVERLAY % {'buildroot': buildroot} |
532 if overlays == 'private': | 594 if overlays == 'private': |
533 paths = [private_overlay] | 595 paths = [private_overlay] |
534 elif overlays == 'public': | 596 elif overlays == 'public': |
535 paths = [public_overlay] | 597 paths = [public_overlay] |
536 elif overlays == 'both': | 598 elif overlays == 'both': |
537 paths = [public_overlay, private_overlay] | 599 paths = [public_overlay, private_overlay] |
538 else: | 600 else: |
539 Info('No overlays found.') | 601 Info('No overlays found.') |
540 paths = [] | 602 paths = [] |
541 return paths | 603 return paths |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 _IncrementalCheckout(buildroot) | 712 _IncrementalCheckout(buildroot) |
651 | 713 |
652 new_binhost = _GetPortageEnvVar(buildroot, board, _FULL_BINHOST) | 714 new_binhost = _GetPortageEnvVar(buildroot, board, _FULL_BINHOST) |
653 emptytree = (old_binhost and old_binhost != new_binhost) | 715 emptytree = (old_binhost and old_binhost != new_binhost) |
654 | 716 |
655 # Check that all overlays can be found. | 717 # Check that all overlays can be found. |
656 for path in rev_overlays: | 718 for path in rev_overlays: |
657 if not os.path.isdir(path): | 719 if not os.path.isdir(path): |
658 Die('Missing overlay: %s' % path) | 720 Die('Missing overlay: %s' % path) |
659 | 721 |
| 722 _DumpManifest(buildroot, options.url) |
| 723 |
660 if not os.path.isdir(chroot_path): | 724 if not os.path.isdir(chroot_path): |
661 _MakeChroot(buildroot) | 725 _MakeChroot(buildroot) |
662 | 726 |
663 if not os.path.isdir(boardpath): | 727 if not os.path.isdir(boardpath): |
664 _SetupBoard(buildroot, board=buildconfig['board']) | 728 _SetupBoard(buildroot, board=buildconfig['board']) |
665 | 729 |
666 # Perform uprev. If chrome_uprev is set, rev Chrome ebuilds. | 730 # Perform uprev. If chrome_uprev is set, rev Chrome ebuilds. |
667 if options.chrome_rev: | 731 if options.chrome_rev: |
668 chrome_atom_to_build = _MarkChromeAsStable(buildroot, tracking_branch, | 732 chrome_atom_to_build = _MarkChromeAsStable(buildroot, tracking_branch, |
669 options.chrome_rev) | 733 options.chrome_rev) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 except: | 784 except: |
721 # Send failure to master bot. | 785 # Send failure to master bot. |
722 if not buildconfig['master'] and buildconfig['important']: | 786 if not buildconfig['master'] and buildconfig['important']: |
723 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) | 787 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) |
724 | 788 |
725 raise | 789 raise |
726 | 790 |
727 | 791 |
728 if __name__ == '__main__': | 792 if __name__ == '__main__': |
729 main() | 793 main() |
OLD | NEW |