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 |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 """Pushes uprev changes to the main line.""" | 399 """Pushes uprev changes to the main line.""" |
400 cwd = os.path.join(buildroot, 'src', 'scripts') | 400 cwd = os.path.join(buildroot, 'src', 'scripts') |
401 RunCommand(['./cros_mark_as_stable', '--srcroot=..', | 401 RunCommand(['./cros_mark_as_stable', '--srcroot=..', |
402 '--board=%s' % board, | 402 '--board=%s' % board, |
403 '--overlays=%s' % ':'.join(overlays), | 403 '--overlays=%s' % ':'.join(overlays), |
404 '--tracking_branch=%s' % tracking_branch, | 404 '--tracking_branch=%s' % tracking_branch, |
405 '--push_options=--bypass-hooks -f', 'push'], | 405 '--push_options=--bypass-hooks -f', 'push'], |
406 cwd=cwd) | 406 cwd=cwd) |
407 | 407 |
408 | 408 |
409 def _ArchiveTestResults(buildroot, board, archive_dir, test_results_dir): | 409 def _ArchiveTestResults(buildroot, board, test_results_dir, |
410 """Archives the test results into the www dir for later use. | 410 gsutil, archive_dir, acl): |
| 411 """Archives the test results into Google Storage |
411 | 412 |
412 Takes the results from the test_results_dir and dumps them into the archive | 413 Takes the results from the test_results_dir and the last qemu image and |
413 dir specified. This also archives the last qemu image. | 414 uploads them to Google Storage. |
414 | 415 |
415 board: Board to find the qemu image. | 416 Arguments: |
416 archive_dir: Path from ARCHIVE_BASE to store image. | 417 buildroot: Root directory where build occurs |
417 test_results_dir: Path from buildroot/chroot to find test results. This must | 418 board: Board to find the qemu image. |
418 a subdir of /tmp. | 419 test_results_dir: Path from buildroot/chroot to find test results. |
| 420 This must a subdir of /tmp. |
| 421 gsutil: Location of gsutil |
| 422 archive_dir: Google Storage path to store the archive |
| 423 acl: ACL to set on archive in Google Storage |
419 """ | 424 """ |
| 425 num_gsutil_retries = 5 |
420 test_results_dir = test_results_dir.lstrip('/') | 426 test_results_dir = test_results_dir.lstrip('/') |
421 if not os.path.exists(ARCHIVE_BASE): | |
422 os.makedirs(ARCHIVE_BASE) | |
423 else: | |
424 dir_entries = os.listdir(ARCHIVE_BASE) | |
425 if len(dir_entries) >= ARCHIVE_COUNT: | |
426 oldest_dirs = heapq.nsmallest((len(dir_entries) - ARCHIVE_COUNT) + 1, | |
427 [os.path.join(ARCHIVE_BASE, filename) for filename in dir_entries], | |
428 key=lambda fn: os.stat(fn).st_mtime) | |
429 Info('Removing archive dirs %s' % oldest_dirs) | |
430 for oldest_dir in oldest_dirs: | |
431 shutil.rmtree(os.path.join(ARCHIVE_BASE, oldest_dir)) | |
432 | |
433 archive_target = os.path.join(ARCHIVE_BASE, str(archive_dir)) | |
434 if os.path.exists(archive_target): | |
435 shutil.rmtree(archive_target) | |
436 | |
437 results_path = os.path.join(buildroot, 'chroot', test_results_dir) | 427 results_path = os.path.join(buildroot, 'chroot', test_results_dir) |
438 RunCommand(['sudo', 'chmod', '-R', '+r', results_path]) | 428 RunCommand(['sudo', 'chmod', '-R', '+r', results_path]) |
439 try: | 429 try: |
440 shutil.copytree(results_path, archive_target) | 430 # gsutil has the ability to resume an upload when the command is retried |
441 except: | 431 RunCommand([gsutil, 'cp', '-R', results_path, archive_dir], |
442 Warning('Some files could not be copied') | 432 num_retries=num_gsutil_retries) |
| 433 RunCommand([gsutil, 'setacl', acl, archive_dir]) |
443 | 434 |
444 image_name = 'chromiumos_qemu_image.bin' | 435 image_name = 'chromiumos_qemu_image.bin' |
445 image_path = os.path.join(buildroot, 'src', 'build', 'images', board, | 436 image_path = os.path.join(buildroot, 'src', 'build', 'images', board, |
446 'latest', image_name) | 437 'latest', image_name) |
447 RunCommand(['gzip', '-f', '--fast', image_path]) | 438 RunCommand(['gzip', '-f', '--fast', image_path]) |
448 shutil.copyfile(image_path + '.gz', os.path.join(archive_target, | 439 RunCommand([gsutil, 'cp', image_path + '.gz', archive_dir], |
449 image_name + '.gz')) | 440 num_retries=num_gsutil_retries) |
450 | 441 except Exception, e: |
| 442 Warning('Could not archive test results (error=%s)' % str(e)) |
451 | 443 |
452 | 444 |
453 def _GetConfig(config_name): | 445 def _GetConfig(config_name): |
454 """Gets the configuration for the build""" | 446 """Gets the configuration for the build""" |
455 default = config['default'] | 447 default = config['default'] |
456 buildconfig = {} | 448 buildconfig = {} |
457 if not config.has_key(config_name): | 449 if not config.has_key(config_name): |
458 Warning('Non-existent configuration specified.') | 450 Warning('Non-existent configuration specified.') |
459 Warning('Please specify one of:') | 451 Warning('Please specify one of:') |
460 config_names = config.keys() | 452 config_names = config.keys() |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 default=False, | 502 default=False, |
511 help='Clobbers an old checkout before syncing') | 503 help='Clobbers an old checkout before syncing') |
512 parser.add_option('--debug', action='store_true', dest='debug', | 504 parser.add_option('--debug', action='store_true', dest='debug', |
513 default=False, | 505 default=False, |
514 help='Override some options to run as a developer.') | 506 help='Override some options to run as a developer.') |
515 parser.add_option('-t', '--tracking-branch', dest='tracking_branch', | 507 parser.add_option('-t', '--tracking-branch', dest='tracking_branch', |
516 default='cros/master', help='Run the buildbot on a branch') | 508 default='cros/master', help='Run the buildbot on a branch') |
517 parser.add_option('-u', '--url', dest='url', | 509 parser.add_option('-u', '--url', dest='url', |
518 default='http://git.chromium.org/git/manifest', | 510 default='http://git.chromium.org/git/manifest', |
519 help='Run the buildbot on internal manifest') | 511 help='Run the buildbot on internal manifest') |
| 512 parser.add_option('-g', '--gsutil', default='', help='Location of gsutil') |
| 513 parser.add_option('-c', '--gsutil_archive', default='', |
| 514 help='Datastore archive location') |
| 515 parser.add_option('-a', '--acl', default='private', |
| 516 help='ACL to set on GSD archives') |
520 | 517 |
521 (options, args) = parser.parse_args() | 518 (options, args) = parser.parse_args() |
522 | 519 |
523 buildroot = os.path.abspath(options.buildroot) | 520 buildroot = os.path.abspath(options.buildroot) |
524 revisionfile = options.revisionfile | 521 revisionfile = options.revisionfile |
525 tracking_branch = options.tracking_branch | 522 tracking_branch = options.tracking_branch |
526 | 523 |
527 if len(args) >= 1: | 524 if len(args) >= 1: |
528 buildconfig = _GetConfig(args[-1]) | 525 buildconfig = _GetConfig(args[-1]) |
529 else: | 526 else: |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 _RunUnitTests(buildroot) | 562 _RunUnitTests(buildroot) |
566 | 563 |
567 _BuildImage(buildroot) | 564 _BuildImage(buildroot) |
568 | 565 |
569 if buildconfig['smoke_bvt']: | 566 if buildconfig['smoke_bvt']: |
570 _BuildVMImageForTesting(buildroot) | 567 _BuildVMImageForTesting(buildroot) |
571 test_results_dir = '/tmp/run_remote_tests.%s' % options.buildnumber | 568 test_results_dir = '/tmp/run_remote_tests.%s' % options.buildnumber |
572 try: | 569 try: |
573 _RunSmokeSuite(buildroot, test_results_dir) | 570 _RunSmokeSuite(buildroot, test_results_dir) |
574 finally: | 571 finally: |
575 _ArchiveTestResults(buildroot, buildconfig['board'], | 572 if not options.debug: |
576 archive_dir=options.buildnumber, | 573 archive_full_path=os.path.join(options.gsutil_archive, |
577 test_results_dir=test_results_dir) | 574 str(options.buildnumber)) |
| 575 _ArchiveTestResults(buildroot, buildconfig['board'], |
| 576 test_results_dir=test_results_dir, |
| 577 gsutil=options.gsutil, |
| 578 archive_dir=archive_full_path, |
| 579 acl=options.acl) |
578 | 580 |
579 if buildconfig['uprev']: | 581 if buildconfig['uprev']: |
580 # Don't push changes for developers. | 582 # Don't push changes for developers. |
581 if not options.debug: | 583 if not options.debug: |
582 if buildconfig['master']: | 584 if buildconfig['master']: |
583 # Master bot needs to check if the other slaves completed. | 585 # Master bot needs to check if the other slaves completed. |
584 if cbuildbot_comm.HaveSlavesCompleted(config): | 586 if cbuildbot_comm.HaveSlavesCompleted(config): |
585 _UprevPush(buildroot, tracking_branch, buildconfig['board'], | 587 _UprevPush(buildroot, tracking_branch, buildconfig['board'], |
586 overlays) | 588 overlays) |
587 else: | 589 else: |
588 Die('CBUILDBOT - One of the slaves has failed!!!') | 590 Die('CBUILDBOT - One of the slaves has failed!!!') |
589 | 591 |
590 else: | 592 else: |
591 # Publish my status to the master if its expecting it. | 593 # Publish my status to the master if its expecting it. |
592 if buildconfig['important']: | 594 if buildconfig['important']: |
593 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) | 595 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) |
594 | 596 |
595 except: | 597 except: |
596 # Send failure to master bot. | 598 # Send failure to master bot. |
597 if not buildconfig['master'] and buildconfig['important']: | 599 if not buildconfig['master'] and buildconfig['important']: |
598 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) | 600 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) |
599 | 601 |
600 raise | 602 raise |
601 | 603 |
602 | 604 |
603 if __name__ == '__main__': | 605 if __name__ == '__main__': |
604 main() | 606 main() |
OLD | NEW |