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, | |
538 '--sync-binhost-conf', | |
539 '--build-path', buildroot, | |
540 '--board', board, | |
541 '--prepend-version', 'preflight', | |
542 '--key', _PREFLIGHT_BINHOST] | |
diandersAtChromium
2010/11/24 01:30:31
Still a little curious why this is done through Ru
scottz
2010/11/29 17:56:39
Agreed on both, if we want to convert to importing
davidjames
2010/11/29 21:18:55
Which of the following do you mean?
1. os.path.j
| |
543 if overlay_config == 'public': | |
544 cmd.extend(['--upload', 'gs://chromeos-prebuilt']) | |
545 else: | |
546 assert overlay_config in ('private', 'both') | |
547 cmd.extend(['--upload', 'chromeos-images:/var/www/prebuilt/', | |
548 '--binhost-base-url', 'http://chromeos-prebuilt']) | |
549 | |
550 RunCommand(cmd, cwd='%s/src/scripts' % buildroot) | |
551 | |
552 | |
499 def main(): | 553 def main(): |
500 # Parse options | 554 # Parse options |
501 usage = "usage: %prog [options] cbuildbot_config" | 555 usage = "usage: %prog [options] cbuildbot_config" |
502 parser = optparse.OptionParser(usage=usage) | 556 parser = optparse.OptionParser(usage=usage) |
503 parser.add_option('-r', '--buildroot', | 557 parser.add_option('-r', '--buildroot', |
504 help='root directory where build occurs', default=".") | 558 help='root directory where build occurs', default=".") |
505 parser.add_option('-n', '--buildnumber', | 559 parser.add_option('-n', '--buildnumber', |
506 help='build number', type='int', default=0) | 560 help='build number', type='int', default=0) |
507 parser.add_option('-f', '--revisionfile', | 561 parser.add_option('-f', '--revisionfile', |
508 help='file where new revisions are stored') | 562 help='file where new revisions are stored') |
(...skipping 17 matching lines...) Expand all Loading... | |
526 | 580 |
527 if len(args) >= 1: | 581 if len(args) >= 1: |
528 buildconfig = _GetConfig(args[-1]) | 582 buildconfig = _GetConfig(args[-1]) |
529 else: | 583 else: |
530 Warning('Missing configuration description') | 584 Warning('Missing configuration description') |
531 parser.print_usage() | 585 parser.print_usage() |
532 sys.exit(1) | 586 sys.exit(1) |
533 | 587 |
534 # Calculate list of overlay directories. | 588 # Calculate list of overlay directories. |
535 overlays = _ResolveOverlays(buildroot, buildconfig['overlays']) | 589 overlays = _ResolveOverlays(buildroot, buildconfig['overlays']) |
590 board = buildconfig['board'] | |
diandersAtChromium
2010/11/24 01:30:31
Curious about whether these two lines should be in
davidjames
2010/11/29 21:18:55
Done.
| |
536 | 591 |
537 try: | 592 try: |
538 _PreFlightRinse(buildroot, buildconfig['board'], tracking_branch, overlays) | 593 _PreFlightRinse(buildroot, buildconfig['board'], tracking_branch, overlays) |
594 chroot_path = os.path.join(buildroot, 'chroot') | |
595 boardpath = os.path.join(chroot_path, 'build', board) | |
539 if options.clobber or not os.path.isdir(buildroot): | 596 if options.clobber or not os.path.isdir(buildroot): |
540 _FullCheckout(buildroot, tracking_branch, url=options.url) | 597 _FullCheckout(buildroot, tracking_branch, url=options.url) |
541 else: | 598 else: |
599 old_binhost = _GetPortageEnvVar(buildroot, board, _FULL_BINHOST) | |
542 _IncrementalCheckout(buildroot) | 600 _IncrementalCheckout(buildroot) |
601 new_binhost = _GetPortageEnvVar(buildroot, board, _FULL_BINHOST) | |
602 if old_binhost != new_binhost: | |
603 RunCommand(['sudo', 'rm', '-rf', boardpath]) | |
543 | 604 |
544 # Check that all overlays can be found. | 605 # Check that all overlays can be found. |
545 for path in overlays: | 606 for path in overlays: |
546 assert ':' not in path, 'Overlay must not contain colons: %s' % path | 607 assert ':' not in path, 'Overlay must not contain colons: %s' % path |
547 if not os.path.isdir(path): | 608 if not os.path.isdir(path): |
548 Die('Missing overlay: %s' % path) | 609 Die('Missing overlay: %s' % path) |
549 | 610 |
550 chroot_path = os.path.join(buildroot, 'chroot') | |
551 if not os.path.isdir(chroot_path): | 611 if not os.path.isdir(chroot_path): |
552 _MakeChroot(buildroot) | 612 _MakeChroot(buildroot) |
553 | 613 |
554 boardpath = os.path.join(chroot_path, 'build', buildconfig['board']) | |
555 if not os.path.isdir(boardpath): | 614 if not os.path.isdir(boardpath): |
556 _SetupBoard(buildroot, board=buildconfig['board']) | 615 _SetupBoard(buildroot, board=buildconfig['board']) |
557 | 616 |
558 if buildconfig['uprev']: | 617 if buildconfig['uprev']: |
559 _UprevPackages(buildroot, tracking_branch, revisionfile, | 618 _UprevPackages(buildroot, tracking_branch, revisionfile, |
560 buildconfig['board'], overlays) | 619 buildconfig['board'], overlays) |
561 | 620 |
562 _EnableLocalAccount(buildroot) | 621 _EnableLocalAccount(buildroot) |
563 _Build(buildroot) | 622 _Build(buildroot) |
564 if buildconfig['unittests']: | 623 if buildconfig['unittests']: |
(...skipping 10 matching lines...) Expand all Loading... | |
575 _ArchiveTestResults(buildroot, buildconfig['board'], | 634 _ArchiveTestResults(buildroot, buildconfig['board'], |
576 archive_dir=options.buildnumber, | 635 archive_dir=options.buildnumber, |
577 test_results_dir=test_results_dir) | 636 test_results_dir=test_results_dir) |
578 | 637 |
579 if buildconfig['uprev']: | 638 if buildconfig['uprev']: |
580 # Don't push changes for developers. | 639 # Don't push changes for developers. |
581 if not options.debug: | 640 if not options.debug: |
582 if buildconfig['master']: | 641 if buildconfig['master']: |
583 # Master bot needs to check if the other slaves completed. | 642 # Master bot needs to check if the other slaves completed. |
584 if cbuildbot_comm.HaveSlavesCompleted(config): | 643 if cbuildbot_comm.HaveSlavesCompleted(config): |
644 _UploadPrebuilts(buildroot, board, buildconfig['overlays']) | |
585 _UprevPush(buildroot, tracking_branch, buildconfig['board'], | 645 _UprevPush(buildroot, tracking_branch, buildconfig['board'], |
586 overlays) | 646 overlays) |
587 else: | 647 else: |
588 Die('CBUILDBOT - One of the slaves has failed!!!') | 648 Die('CBUILDBOT - One of the slaves has failed!!!') |
589 | 649 |
590 else: | 650 else: |
591 # Publish my status to the master if its expecting it. | 651 # Publish my status to the master if its expecting it. |
592 if buildconfig['important']: | 652 if buildconfig['important']: |
593 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) | 653 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) |
594 | 654 |
595 except: | 655 except: |
596 # Send failure to master bot. | 656 # Send failure to master bot. |
597 if not buildconfig['master'] and buildconfig['important']: | 657 if not buildconfig['master'] and buildconfig['important']: |
598 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) | 658 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) |
599 | 659 |
600 raise | 660 raise |
601 | 661 |
602 | 662 |
603 if __name__ == '__main__': | 663 if __name__ == '__main__': |
604 main() | 664 main() |
OLD | NEW |