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 re | 11 import re |
11 import optparse | 12 import optparse |
12 import os | 13 import os |
| 14 import shutil |
13 import sys | 15 import sys |
14 | 16 |
15 import cbuildbot_comm | 17 import cbuildbot_comm |
16 from cbuildbot_config import config | 18 from cbuildbot_config import config |
17 | 19 |
18 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) | 20 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) |
19 from cros_build_lib import Die, Info, RunCommand, Warning | 21 from cros_build_lib import Die, Info, RunCommand, Warning |
20 | 22 |
21 _DEFAULT_RETRIES = 3 | 23 _DEFAULT_RETRIES = 3 |
| 24 ARCHIVE_BASE = '/var/www/archive' |
| 25 ARCHIVE_COUNT = 10 |
22 | 26 |
23 # ======================== Utility functions ================================ | 27 # ======================== Utility functions ================================ |
24 | 28 |
25 def MakeDir(path, parents=False): | 29 def MakeDir(path, parents=False): |
26 """Basic wrapper around os.mkdirs. | 30 """Basic wrapper around os.mkdirs. |
27 | 31 |
28 Keyword arguments: | 32 Keyword arguments: |
29 path -- Path to create. | 33 path -- Path to create. |
30 parents -- Follow mkdir -p logic. | 34 parents -- Follow mkdir -p logic. |
31 | 35 |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 '--vdisk_size=%s' % vdisk_size, | 322 '--vdisk_size=%s' % vdisk_size, |
319 '--statefulfs_size=%s' % statefulfs_size, | 323 '--statefulfs_size=%s' % statefulfs_size, |
320 ], cwd=cwd, enter_chroot=True) | 324 ], cwd=cwd, enter_chroot=True) |
321 | 325 |
322 | 326 |
323 def _RunUnitTests(buildroot): | 327 def _RunUnitTests(buildroot): |
324 cwd = os.path.join(buildroot, 'src', 'scripts') | 328 cwd = os.path.join(buildroot, 'src', 'scripts') |
325 RunCommand(['./cros_run_unit_tests'], cwd=cwd, enter_chroot=True) | 329 RunCommand(['./cros_run_unit_tests'], cwd=cwd, enter_chroot=True) |
326 | 330 |
327 | 331 |
328 def _RunSmokeSuite(buildroot): | 332 def _RunSmokeSuite(buildroot, results_dir): |
| 333 results_dir_in_chroot = os.path.join(buildroot, 'chroot', |
| 334 results_dir.lstrip('/')) |
| 335 if os.path.exists(results_dir_in_chroot): |
| 336 shutil.rmtree(results_dir_in_chroot) |
| 337 |
329 cwd = os.path.join(buildroot, 'src', 'scripts') | 338 cwd = os.path.join(buildroot, 'src', 'scripts') |
330 RunCommand(['bin/cros_run_vm_test', | 339 RunCommand(['bin/cros_run_vm_test', |
331 '--no_graphics', | 340 '--no_graphics', |
332 '--test_case=suite_Smoke', | 341 '--test_case=suite_Smoke', |
| 342 '--results_dir_root=%s' % results_dir, |
333 ], cwd=cwd, error_ok=False) | 343 ], cwd=cwd, error_ok=False) |
334 | 344 |
335 | 345 |
336 def _UprevPackages(buildroot, tracking_branch, revisionfile, board): | 346 def _UprevPackages(buildroot, tracking_branch, revisionfile, board): |
337 """Uprevs a package based on given revisionfile. | 347 """Uprevs a package based on given revisionfile. |
338 | 348 |
339 If revisionfile is set to None or does not resolve to an actual file, this | 349 If revisionfile is set to None or does not resolve to an actual file, this |
340 function will uprev all packages. | 350 function will uprev all packages. |
341 | 351 |
342 Keyword arguments: | 352 Keyword arguments: |
(...skipping 28 matching lines...) Expand all Loading... |
371 def _UprevPush(buildroot, tracking_branch, board): | 381 def _UprevPush(buildroot, tracking_branch, board): |
372 """Pushes uprev changes to the main line.""" | 382 """Pushes uprev changes to the main line.""" |
373 cwd = os.path.join(buildroot, 'src', 'scripts') | 383 cwd = os.path.join(buildroot, 'src', 'scripts') |
374 RunCommand(['./cros_mark_as_stable', '--srcroot=..', | 384 RunCommand(['./cros_mark_as_stable', '--srcroot=..', |
375 '--board=%s' % board, | 385 '--board=%s' % board, |
376 '--tracking_branch="%s"' % tracking_branch, | 386 '--tracking_branch="%s"' % tracking_branch, |
377 '--push_options="--bypass-hooks -f"', 'push'], | 387 '--push_options="--bypass-hooks -f"', 'push'], |
378 cwd=cwd) | 388 cwd=cwd) |
379 | 389 |
380 | 390 |
| 391 def _ArchiveTestResults(buildroot, board, archive_dir, test_results_dir): |
| 392 """Archives the test results into the www dir for later use. |
| 393 |
| 394 Takes the results from the test_results_dir and dumps them into the archive |
| 395 dir specified. This also archives the last qemu image. |
| 396 |
| 397 board: Board to find the qemu image. |
| 398 archive_dir: Path from ARCHIVE_BASE to store image. |
| 399 test_results_dir: Path from buildroot/chroot to find test results. This must |
| 400 a subdir of /tmp. |
| 401 """ |
| 402 test_results_dir = test_results_dir.lstrip('/') |
| 403 if not os.path.exists(ARCHIVE_BASE): |
| 404 os.makedirs(ARCHIVE_BASE) |
| 405 else: |
| 406 dir_entries = os.listdir(ARCHIVE_BASE) |
| 407 if len(dir_entries) >= ARCHIVE_COUNT: |
| 408 oldest_dirs = heapq.nsmallest((len(dir_entries) - ARCHIVE_COUNT) + 1, |
| 409 [filename for filename in dir_entries], |
| 410 key=lambda fn: os.stat(fn).st_mtime) |
| 411 Info('Removing archive dirs %s' % oldest_dirs) |
| 412 for oldest_dir in oldest_dirs: |
| 413 shutil.rmtree(os.path.join(ARCHIVE_BASE, oldest_dir)) |
| 414 |
| 415 archive_target = os.path.join(ARCHIVE_BASE, str(archive_dir)) |
| 416 if os.path.exists(archive_target): |
| 417 shutil.rmtree(archive_target) |
| 418 |
| 419 results_path = os.path.join(buildroot, 'chroot', test_results_dir) |
| 420 RunCommand(['sudo', 'chmod', '-R', '+r', results_path]) |
| 421 try: |
| 422 shutil.copytree(results_path, archive_target) |
| 423 except: |
| 424 Warning('Some files could not be copied') |
| 425 |
| 426 image_name = 'chromiumos_qemu_image.bin' |
| 427 image_path = os.path.join(buildroot, 'src', 'build', 'images', board, |
| 428 'latest', image_name) |
| 429 RunCommand(['gzip', '-f', image_path]) |
| 430 shutil.copyfile(image_path + '.gz', os.path.join(archive_target, |
| 431 image_name + '.gz')) |
| 432 |
| 433 |
| 434 |
381 def _GetConfig(config_name): | 435 def _GetConfig(config_name): |
382 """Gets the configuration for the build""" | 436 """Gets the configuration for the build""" |
383 default = config['default'] | 437 default = config['default'] |
384 buildconfig = {} | 438 buildconfig = {} |
385 if not config.has_key(config_name): | 439 if not config.has_key(config_name): |
386 Warning('Non-existent configuration specified.') | 440 Warning('Non-existent configuration specified.') |
387 Warning('Please specify one of:') | 441 Warning('Please specify one of:') |
388 config_names = config.keys() | 442 config_names = config.keys() |
389 config_names.sort() | 443 config_names.sort() |
390 for name in config_names: | 444 for name in config_names: |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 | 510 |
457 _EnableLocalAccount(buildroot) | 511 _EnableLocalAccount(buildroot) |
458 _Build(buildroot) | 512 _Build(buildroot) |
459 if buildconfig['unittests']: | 513 if buildconfig['unittests']: |
460 _RunUnitTests(buildroot) | 514 _RunUnitTests(buildroot) |
461 | 515 |
462 _BuildImage(buildroot) | 516 _BuildImage(buildroot) |
463 | 517 |
464 if buildconfig['smoke_bvt']: | 518 if buildconfig['smoke_bvt']: |
465 _BuildVMImageForTesting(buildroot) | 519 _BuildVMImageForTesting(buildroot) |
466 _RunSmokeSuite(buildroot) | 520 test_results_dir = '/tmp/run_remote_tests.%s' % options.buildnumber |
| 521 try: |
| 522 _RunSmokeSuite(buildroot, test_results_dir) |
| 523 finally: |
| 524 _ArchiveTestResults(buildroot, buildconfig['board'], |
| 525 archive_dir=options.buildnumber, |
| 526 test_results_dir=test_results_dir) |
467 | 527 |
468 if buildconfig['uprev']: | 528 if buildconfig['uprev']: |
469 # Don't push changes for developers. | 529 # Don't push changes for developers. |
470 if not options.debug: | 530 if not options.debug: |
471 if buildconfig['master']: | 531 if buildconfig['master']: |
472 # Master bot needs to check if the other slaves completed. | 532 # Master bot needs to check if the other slaves completed. |
473 if cbuildbot_comm.HaveSlavesCompleted(config): | 533 if cbuildbot_comm.HaveSlavesCompleted(config): |
474 _UprevPush(buildroot, tracking_branch, buildconfig['board']) | 534 _UprevPush(buildroot, tracking_branch, buildconfig['board']) |
475 else: | 535 else: |
476 Die('CBUILDBOT - One of the slaves has failed!!!') | 536 Die('CBUILDBOT - One of the slaves has failed!!!') |
477 | 537 |
478 else: | 538 else: |
479 # Publish my status to the master if its expecting it. | 539 # Publish my status to the master if its expecting it. |
480 if buildconfig['important']: | 540 if buildconfig['important']: |
481 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) | 541 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) |
482 | 542 |
483 except: | 543 except: |
484 # Send failure to master bot. | 544 # Send failure to master bot. |
485 if not buildconfig['master'] and buildconfig['important']: | 545 if not buildconfig['master'] and buildconfig['important']: |
486 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) | 546 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) |
487 | 547 |
488 raise | 548 raise |
489 | 549 |
490 | 550 |
491 if __name__ == '__main__': | 551 if __name__ == '__main__': |
492 main() | 552 main() |
OLD | NEW |