Chromium Code Reviews| 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 | 28 |
| 29 # 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. | |
| 31 # We're planning on joining the two files soon and renaming the full binhost | |
| 32 # to FULL_BINHOST. | |
| 33 _FULL_BINHOST = 'PORTAGE_BINHOST' | |
| 34 _PREFLIGHT_BINHOST = 'PORTAGE_BINHOST' | |
| 35 | |
| 29 # ======================== Utility functions ================================ | 36 # ======================== Utility functions ================================ |
| 30 | 37 |
| 31 def MakeDir(path, parents=False): | 38 def MakeDir(path, parents=False): |
| 32 """Basic wrapper around os.mkdirs. | 39 """Basic wrapper around os.mkdirs. |
| 33 | 40 |
| 34 Keyword arguments: | 41 Keyword arguments: |
| 35 path -- Path to create. | 42 path -- Path to create. |
| 36 parents -- Follow mkdir -p logic. | 43 parents -- Follow mkdir -p logic. |
| 37 | 44 |
| 38 """ | 45 """ |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 """Performs a checkout without clobbering previous checkout.""" | 298 """Performs a checkout without clobbering previous checkout.""" |
| 292 RepoSync(buildroot, rw_checkout, retries) | 299 RepoSync(buildroot, rw_checkout, retries) |
| 293 | 300 |
| 294 | 301 |
| 295 def _MakeChroot(buildroot): | 302 def _MakeChroot(buildroot): |
| 296 """Wrapper around make_chroot.""" | 303 """Wrapper around make_chroot.""" |
| 297 cwd = os.path.join(buildroot, 'src', 'scripts') | 304 cwd = os.path.join(buildroot, 'src', 'scripts') |
| 298 RunCommand(['./make_chroot', '--fast'], cwd=cwd) | 305 RunCommand(['./make_chroot', '--fast'], cwd=cwd) |
| 299 | 306 |
| 300 | 307 |
| 308 def _GetPortageEnvVar(buildroot, board, envvar): | |
| 309 """Get a portage environment variable for the specified board, if any. | |
| 310 | |
| 311 buildroot: The root directory where the build occurs. Must be an absolute | |
| 312 path. | |
| 313 board: Board type that was built on this machine. E.g. x86-generic. | |
| 314 envvar: The environment variable to get. E.g. "PORTAGE_BINHOST". | |
| 315 | |
| 316 Returns: | |
| 317 The value of the environment variable, as a string. If no such variable | |
| 318 can be found, return the empty string. | |
| 319 """ | |
| 320 cwd = os.path.join(buildroot, 'src', 'scripts') | |
| 321 binhost = RunCommand(['portageq-%s' % board, 'envvar', envvar], | |
| 322 cwd=cwd, redirect_stdout=True, enter_chroot=True, | |
| 323 error_ok=True) | |
| 324 return binhost.rstrip('\n') | |
| 325 | |
| 326 | |
| 301 def _SetupBoard(buildroot, board='x86-generic'): | 327 def _SetupBoard(buildroot, board='x86-generic'): |
| 302 """Wrapper around setup_board.""" | 328 """Wrapper around setup_board.""" |
| 303 cwd = os.path.join(buildroot, 'src', 'scripts') | 329 cwd = os.path.join(buildroot, 'src', 'scripts') |
| 304 RunCommand(['./setup_board', '--fast', '--default', '--board=%s' % board], | 330 RunCommand(['./setup_board', '--fast', '--default', '--board=%s' % board], |
| 305 cwd=cwd, enter_chroot=True) | 331 cwd=cwd, enter_chroot=True) |
| 306 | 332 |
| 307 | 333 |
| 308 def _Build(buildroot): | 334 def _Build(buildroot): |
| 309 """Wrapper around build_packages.""" | 335 """Wrapper around build_packages.""" |
| 310 cwd = os.path.join(buildroot, 'src', 'scripts') | 336 cwd = os.path.join(buildroot, 'src', 'scripts') |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 489 paths = [private_overlay] | 515 paths = [private_overlay] |
| 490 elif overlays == 'public': | 516 elif overlays == 'public': |
| 491 paths = [public_overlay] | 517 paths = [public_overlay] |
| 492 elif overlays == 'both': | 518 elif overlays == 'both': |
| 493 paths = [public_overlay, private_overlay] | 519 paths = [public_overlay, private_overlay] |
| 494 else: | 520 else: |
| 495 Die('Incorrect overlay configuration: %s' % overlays) | 521 Die('Incorrect overlay configuration: %s' % overlays) |
| 496 return paths | 522 return paths |
| 497 | 523 |
| 498 | 524 |
| 525 def _UploadPrebuilts(buildroot, board, overlay_config): | |
| 526 """Upload prebuilts. | |
| 527 | |
| 528 Args: | |
| 529 buildroot: The root directory where the build occurs. | |
| 530 board: Board type that was built on this machine | |
| 531 overlay_config: A string describing which overlays you want. | |
| 532 'private': Just the private overlay. | |
| 533 'public': Just the public overlay. | |
| 534 'both': Both the public and private overlays. | |
| 535 """ | |
| 536 | |
| 537 cmd = ['%s/src/scripts/prebuilt.py' % buildroot, '--sync-binhost-conf', | |
|
sosa
2010/11/23 23:56:21
Can you put each of this long options on their own
davidjames
2010/11/24 00:29:23
Done.
| |
| 538 '--build-path', buildroot, '--board', board, | |
| 539 '--prepend-version', 'preflight', '--key', _PREFLIGHT_BINHOST] | |
| 540 if overlay_config == 'public': | |
| 541 cmd.extend(['--upload', 'gs://chromeos-prebuilt']) | |
| 542 else: | |
| 543 assert overlay_config in ('private', 'both') | |
| 544 cmd.extend(['--upload', 'chromeos-images:/var/www/prebuilt/', | |
| 545 '--binhost-base-url', 'http://chromeos-prebuilt']) | |
| 546 | |
| 547 RunCommand(cmd) | |
|
sosa
2010/11/23 23:56:21
Nit: Most other code sets cwd, is it possible to u
davidjames
2010/11/24 00:29:23
Done.
| |
| 548 | |
| 549 | |
| 499 def main(): | 550 def main(): |
| 500 # Parse options | 551 # Parse options |
| 501 usage = "usage: %prog [options] cbuildbot_config" | 552 usage = "usage: %prog [options] cbuildbot_config" |
| 502 parser = optparse.OptionParser(usage=usage) | 553 parser = optparse.OptionParser(usage=usage) |
| 503 parser.add_option('-r', '--buildroot', | 554 parser.add_option('-r', '--buildroot', |
| 504 help='root directory where build occurs', default=".") | 555 help='root directory where build occurs', default=".") |
| 505 parser.add_option('-n', '--buildnumber', | 556 parser.add_option('-n', '--buildnumber', |
| 506 help='build number', type='int', default=0) | 557 help='build number', type='int', default=0) |
| 507 parser.add_option('-f', '--revisionfile', | 558 parser.add_option('-f', '--revisionfile', |
| 508 help='file where new revisions are stored') | 559 help='file where new revisions are stored') |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 526 | 577 |
| 527 if len(args) >= 1: | 578 if len(args) >= 1: |
| 528 buildconfig = _GetConfig(args[-1]) | 579 buildconfig = _GetConfig(args[-1]) |
| 529 else: | 580 else: |
| 530 Warning('Missing configuration description') | 581 Warning('Missing configuration description') |
| 531 parser.print_usage() | 582 parser.print_usage() |
| 532 sys.exit(1) | 583 sys.exit(1) |
| 533 | 584 |
| 534 # Calculate list of overlay directories. | 585 # Calculate list of overlay directories. |
| 535 overlays = _ResolveOverlays(buildroot, buildconfig['overlays']) | 586 overlays = _ResolveOverlays(buildroot, buildconfig['overlays']) |
| 587 board = buildconfig['board'] | |
| 536 | 588 |
| 537 try: | 589 try: |
| 538 _PreFlightRinse(buildroot, buildconfig['board'], tracking_branch, overlays) | 590 _PreFlightRinse(buildroot, buildconfig['board'], tracking_branch, overlays) |
| 591 chroot_path = os.path.join(buildroot, 'chroot') | |
| 592 boardpath = os.path.join(chroot_path, 'build', board) | |
| 539 if options.clobber or not os.path.isdir(buildroot): | 593 if options.clobber or not os.path.isdir(buildroot): |
| 540 _FullCheckout(buildroot, tracking_branch, url=options.url) | 594 _FullCheckout(buildroot, tracking_branch, url=options.url) |
| 541 else: | 595 else: |
| 596 old_binhost = _GetPortageEnvVar(buildroot, board, _FULL_BINHOST) | |
| 542 _IncrementalCheckout(buildroot) | 597 _IncrementalCheckout(buildroot) |
| 598 new_binhost = _GetPortageEnvVar(buildroot, board, _FULL_BINHOST) | |
| 599 if old_binhost != new_binhost: | |
| 600 RunCommand(['sudo', 'rm', '-rf', boardpath]) | |
|
sosa
2010/11/23 23:56:21
Is sudo necessary? Is shutil.rmtree not sufficien
davidjames
2010/11/24 00:29:23
Yeah, it's necessary unfortunately. There are some
| |
| 543 | 601 |
| 544 # Check that all overlays can be found. | 602 # Check that all overlays can be found. |
| 545 for path in overlays: | 603 for path in overlays: |
| 546 assert ':' not in path, 'Overlay must not contain colons: %s' % path | 604 assert ':' not in path, 'Overlay must not contain colons: %s' % path |
| 547 if not os.path.isdir(path): | 605 if not os.path.isdir(path): |
| 548 Die('Missing overlay: %s' % path) | 606 Die('Missing overlay: %s' % path) |
| 549 | 607 |
| 550 chroot_path = os.path.join(buildroot, 'chroot') | |
| 551 if not os.path.isdir(chroot_path): | 608 if not os.path.isdir(chroot_path): |
| 552 _MakeChroot(buildroot) | 609 _MakeChroot(buildroot) |
| 553 | 610 |
| 554 boardpath = os.path.join(chroot_path, 'build', buildconfig['board']) | |
| 555 if not os.path.isdir(boardpath): | 611 if not os.path.isdir(boardpath): |
| 556 _SetupBoard(buildroot, board=buildconfig['board']) | 612 _SetupBoard(buildroot, board=buildconfig['board']) |
| 557 | 613 |
| 558 if buildconfig['uprev']: | 614 if buildconfig['uprev']: |
| 559 _UprevPackages(buildroot, tracking_branch, revisionfile, | 615 _UprevPackages(buildroot, tracking_branch, revisionfile, |
| 560 buildconfig['board'], overlays) | 616 buildconfig['board'], overlays) |
| 561 | 617 |
| 562 _EnableLocalAccount(buildroot) | 618 _EnableLocalAccount(buildroot) |
| 563 _Build(buildroot) | 619 _Build(buildroot) |
| 564 if buildconfig['unittests']: | 620 if buildconfig['unittests']: |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 575 _ArchiveTestResults(buildroot, buildconfig['board'], | 631 _ArchiveTestResults(buildroot, buildconfig['board'], |
| 576 archive_dir=options.buildnumber, | 632 archive_dir=options.buildnumber, |
| 577 test_results_dir=test_results_dir) | 633 test_results_dir=test_results_dir) |
| 578 | 634 |
| 579 if buildconfig['uprev']: | 635 if buildconfig['uprev']: |
| 580 # Don't push changes for developers. | 636 # Don't push changes for developers. |
| 581 if not options.debug: | 637 if not options.debug: |
| 582 if buildconfig['master']: | 638 if buildconfig['master']: |
| 583 # Master bot needs to check if the other slaves completed. | 639 # Master bot needs to check if the other slaves completed. |
| 584 if cbuildbot_comm.HaveSlavesCompleted(config): | 640 if cbuildbot_comm.HaveSlavesCompleted(config): |
| 641 _UploadPrebuilts(buildroot, board, buildconfig['overlays']) | |
| 585 _UprevPush(buildroot, tracking_branch, buildconfig['board'], | 642 _UprevPush(buildroot, tracking_branch, buildconfig['board'], |
| 586 overlays) | 643 overlays) |
| 587 else: | 644 else: |
| 588 Die('CBUILDBOT - One of the slaves has failed!!!') | 645 Die('CBUILDBOT - One of the slaves has failed!!!') |
| 589 | 646 |
| 590 else: | 647 else: |
| 591 # Publish my status to the master if its expecting it. | 648 # Publish my status to the master if its expecting it. |
| 592 if buildconfig['important']: | 649 if buildconfig['important']: |
| 593 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) | 650 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) |
|
sosa
2010/11/23 23:56:21
Scott has a if/else convention of a newline after
davidjames
2010/11/24 00:29:23
OK, added the newline back.
| |
| 594 | |
| 595 except: | 651 except: |
| 596 # Send failure to master bot. | 652 # Send failure to master bot. |
| 597 if not buildconfig['master'] and buildconfig['important']: | 653 if not buildconfig['master'] and buildconfig['important']: |
| 598 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) | 654 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) |
| 599 | 655 |
| 600 raise | 656 raise |
| 601 | 657 |
| 602 | 658 |
| 603 if __name__ == '__main__': | 659 if __name__ == '__main__': |
| 604 main() | 660 main() |
| OLD | NEW |