Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: bin/cbuildbot.py

Issue 4442001: Add more error checking to preflight queue. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/crosutils.git
Patch Set: Quotes Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | bin/cbuildbot_config.py » ('j') | bin/cbuildbot_unittest.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 repo_name = revision_tuple[0].replace('.git', '') 174 repo_name = revision_tuple[0].replace('.git', '')
175 # Might not have entry if no matching ebuild. 175 # Might not have entry if no matching ebuild.
176 if repo_dictionary.has_key(repo_name): 176 if repo_dictionary.has_key(repo_name):
177 # May be many corresponding packages to a given git repo e.g. kernel). 177 # May be many corresponding packages to a given git repo e.g. kernel).
178 for package in repo_dictionary[repo_name]: 178 for package in repo_dictionary[repo_name]:
179 revisions[package] = revision_tuple[1] 179 revisions[package] = revision_tuple[1]
180 180
181 return revisions.items() 181 return revisions.items()
182 182
183 183
184 def _UprevFromRevisionList(buildroot, tracking_branch, revision_list, board): 184 def _UprevFromRevisionList(buildroot, tracking_branch, revision_list, board,
185 overlays):
185 """Uprevs based on revision list.""" 186 """Uprevs based on revision list."""
186 if not revision_list: 187 if not revision_list:
187 Info('No packages found to uprev') 188 Info('No packages found to uprev')
188 return 189 return
189 190
190 package_str = '' 191 packages = []
191 for package, revision in revision_list: 192 for package, revision in revision_list:
192 package_str += package + ' ' 193 assert ':' not in package, 'Invalid package name: %s' % package
scottz-goog 2010/11/10 23:48:14 Why is this being added? Have their been cases whe
davidjames 2010/11/11 02:23:24 Nope. Dianders just suggested I add the check.
193 194 packages.append(package)
194 package_str = package_str.strip()
195 195
196 cwd = os.path.join(buildroot, 'src', 'scripts') 196 cwd = os.path.join(buildroot, 'src', 'scripts')
197 # TODO(davidjames): --foo="bar baz" only works here because we're using
198 # enter_chroot.
199 RunCommand(['./cros_mark_as_stable', 197 RunCommand(['./cros_mark_as_stable',
200 '--board=%s' % board, 198 '--board=%s' % board,
201 '--tracking_branch="%s"' % tracking_branch, 199 '--tracking_branch=%s' % tracking_branch,
202 '--packages="%s"' % package_str, 200 '--overlays=%s' % ':'.join(overlays),
201 '--packages=%s' % ':'.join(packages),
203 'commit'], 202 'commit'],
204 cwd=cwd, enter_chroot=True) 203 cwd=cwd, enter_chroot=True)
205 204
206 205
207 def _UprevAllPackages(buildroot, tracking_branch, board): 206 def _UprevAllPackages(buildroot, tracking_branch, board, overlays):
208 """Uprevs all packages that have been updated since last uprev.""" 207 """Uprevs all packages that have been updated since last uprev."""
209 cwd = os.path.join(buildroot, 'src', 'scripts') 208 cwd = os.path.join(buildroot, 'src', 'scripts')
210 # TODO(davidjames): --foo="bar baz" only works here because we're using
211 # enter_chroot.
212 RunCommand(['./cros_mark_as_stable', '--all', 209 RunCommand(['./cros_mark_as_stable', '--all',
213 '--board=%s' % board, 210 '--board=%s' % board,
214 '--tracking_branch="%s"' % tracking_branch, 'commit'], 211 '--overlays=%s' % ':'.join(overlays),
212 '--tracking_branch=%s' % tracking_branch, 'commit'],
215 cwd=cwd, enter_chroot=True) 213 cwd=cwd, enter_chroot=True)
216 214
217 215
218 def _GetVMConstants(buildroot): 216 def _GetVMConstants(buildroot):
219 """Returns minimum (vdisk_size, statefulfs_size) recommended for VM's.""" 217 """Returns minimum (vdisk_size, statefulfs_size) recommended for VM's."""
220 cwd = os.path.join(buildroot, 'src', 'scripts', 'lib') 218 cwd = os.path.join(buildroot, 'src', 'scripts', 'lib')
221 source_cmd = 'source %s/cros_vm_constants.sh' % cwd 219 source_cmd = 'source %s/cros_vm_constants.sh' % cwd
222 vdisk_size = RunCommand([ 220 vdisk_size = RunCommand([
223 '/bin/bash', '-c', '%s && echo $MIN_VDISK_SIZE_FULL' % source_cmd], 221 '/bin/bash', '-c', '%s && echo $MIN_VDISK_SIZE_FULL' % source_cmd],
224 redirect_stdout=True) 222 redirect_stdout=True)
225 statefulfs_size = RunCommand([ 223 statefulfs_size = RunCommand([
226 '/bin/bash', '-c', '%s && echo $MIN_STATEFUL_FS_SIZE_FULL' % source_cmd], 224 '/bin/bash', '-c', '%s && echo $MIN_STATEFUL_FS_SIZE_FULL' % source_cmd],
227 redirect_stdout=True) 225 redirect_stdout=True)
228 return (vdisk_size.strip(), statefulfs_size.strip()) 226 return (vdisk_size.strip(), statefulfs_size.strip())
229 227
230 228
231 def _GitCleanup(buildroot, board, tracking_branch): 229 def _GitCleanup(buildroot, board, tracking_branch, overlays):
232 """Clean up git branch after previous uprev attempt.""" 230 """Clean up git branch after previous uprev attempt."""
233 cwd = os.path.join(buildroot, 'src', 'scripts') 231 cwd = os.path.join(buildroot, 'src', 'scripts')
234 if os.path.exists(cwd): 232 if os.path.exists(cwd):
235 RunCommand(['./cros_mark_as_stable', '--srcroot=..', 233 RunCommand(['./cros_mark_as_stable', '--srcroot=..',
236 '--board=%s' % board, 234 '--board=%s' % board,
235 '--overlays=%s' % ':'.join(overlays),
237 '--tracking_branch=%s' % tracking_branch, 'clean'], 236 '--tracking_branch=%s' % tracking_branch, 'clean'],
238 cwd=cwd, error_ok=True) 237 cwd=cwd, error_ok=True)
239 238
240 239
241 def _CleanUpMountPoints(buildroot): 240 def _CleanUpMountPoints(buildroot):
242 """Cleans up any stale mount points from previous runs.""" 241 """Cleans up any stale mount points from previous runs."""
243 mount_output = RunCommand(['mount'], redirect_stdout=True) 242 mount_output = RunCommand(['mount'], redirect_stdout=True)
244 mount_pts_in_buildroot = RunCommand(['grep', buildroot], input=mount_output, 243 mount_pts_in_buildroot = RunCommand(['grep', buildroot], input=mount_output,
245 redirect_stdout=True, error_ok=True) 244 redirect_stdout=True, error_ok=True)
246 245
247 for mount_pt_str in mount_pts_in_buildroot.splitlines(): 246 for mount_pt_str in mount_pts_in_buildroot.splitlines():
248 mount_pt = mount_pt_str.rpartition(' type ')[0].partition(' on ')[2] 247 mount_pt = mount_pt_str.rpartition(' type ')[0].partition(' on ')[2]
249 RunCommand(['sudo', 'umount', '-l', mount_pt], error_ok=True) 248 RunCommand(['sudo', 'umount', '-l', mount_pt], error_ok=True)
250 249
251 250
252 def _WipeOldOutput(buildroot): 251 def _WipeOldOutput(buildroot):
253 """Wipes out build output directories.""" 252 """Wipes out build output directories."""
254 RunCommand(['rm', '-rf', 'src/build/images'], cwd=buildroot) 253 RunCommand(['rm', '-rf', 'src/build/images'], cwd=buildroot)
255 254
256 255
257 # =========================== Main Commands =================================== 256 # =========================== Main Commands ===================================
258 257
259 258
260 def _PreFlightRinse(buildroot, board, tracking_branch): 259 def _PreFlightRinse(buildroot, board, tracking_branch, overlays):
261 """Cleans up any leftover state from previous runs.""" 260 """Cleans up any leftover state from previous runs."""
262 _GitCleanup(buildroot, board, tracking_branch) 261 _GitCleanup(buildroot, board, tracking_branch, overlays)
263 _CleanUpMountPoints(buildroot) 262 _CleanUpMountPoints(buildroot)
264 RunCommand(['sudo', 'killall', 'kvm'], error_ok=True) 263 RunCommand(['sudo', 'killall', 'kvm'], error_ok=True)
265 264
266 265
267 def _FullCheckout(buildroot, tracking_branch, rw_checkout=True, 266 def _FullCheckout(buildroot, tracking_branch, rw_checkout=True,
268 retries=_DEFAULT_RETRIES, 267 retries=_DEFAULT_RETRIES,
269 url='http://git.chromium.org/git/manifest'): 268 url='http://git.chromium.org/git/manifest'):
270 """Performs a full checkout and clobbers any previous checkouts.""" 269 """Performs a full checkout and clobbers any previous checkouts."""
271 RunCommand(['sudo', 'rm', '-rf', buildroot]) 270 RunCommand(['sudo', 'rm', '-rf', buildroot])
272 MakeDir(buildroot, parents=True) 271 MakeDir(buildroot, parents=True)
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 shutil.rmtree(results_dir_in_chroot) 339 shutil.rmtree(results_dir_in_chroot)
341 340
342 cwd = os.path.join(buildroot, 'src', 'scripts') 341 cwd = os.path.join(buildroot, 'src', 'scripts')
343 RunCommand(['bin/cros_run_vm_test', 342 RunCommand(['bin/cros_run_vm_test',
344 '--no_graphics', 343 '--no_graphics',
345 '--test_case=suite_Smoke', 344 '--test_case=suite_Smoke',
346 '--results_dir_root=%s' % results_dir, 345 '--results_dir_root=%s' % results_dir,
347 ], cwd=cwd, error_ok=False) 346 ], cwd=cwd, error_ok=False)
348 347
349 348
350 def _UprevPackages(buildroot, tracking_branch, revisionfile, board): 349 def _UprevPackages(buildroot, tracking_branch, revisionfile, board, overlays):
351 """Uprevs a package based on given revisionfile. 350 """Uprevs a package based on given revisionfile.
352 351
353 If revisionfile is set to None or does not resolve to an actual file, this 352 If revisionfile is set to None or does not resolve to an actual file, this
354 function will uprev all packages. 353 function will uprev all packages.
355 354
356 Keyword arguments: 355 Keyword arguments:
357 revisionfile -- string specifying a file that contains a list of revisions to 356 revisionfile -- string specifying a file that contains a list of revisions to
358 uprev. 357 uprev.
359 """ 358 """
360 # Purposefully set to None as it means Force Build was pressed. 359 # Purposefully set to None as it means Force Build was pressed.
361 revisions = 'None' 360 revisions = 'None'
362 if (revisionfile): 361 if (revisionfile):
363 try: 362 try:
364 rev_file = open(revisionfile) 363 rev_file = open(revisionfile)
365 revisions = rev_file.read() 364 revisions = rev_file.read()
366 rev_file.close() 365 rev_file.close()
367 except Exception, e: 366 except Exception, e:
368 Warning('Error reading %s, revving all' % revisionfile) 367 Warning('Error reading %s, revving all' % revisionfile)
369 revisions = 'None' 368 revisions = 'None'
370 369
371 revisions = revisions.strip() 370 revisions = revisions.strip()
372 371
373 # TODO(sosa): Un-comment once we close individual trees. 372 # TODO(sosa): Un-comment once we close individual trees.
374 # revisions == "None" indicates a Force Build. 373 # revisions == "None" indicates a Force Build.
375 #if revisions != 'None': 374 #if revisions != 'None':
376 # print >> sys.stderr, 'CBUILDBOT Revision list found %s' % revisions 375 # print >> sys.stderr, 'CBUILDBOT Revision list found %s' % revisions
377 # revision_list = _ParseRevisionString(revisions, 376 # revision_list = _ParseRevisionString(revisions,
378 # _CreateRepoDictionary(buildroot, board)) 377 # _CreateRepoDictionary(buildroot, board))
379 # _UprevFromRevisionList(buildroot, tracking_branch, revision_list, board) 378 # _UprevFromRevisionList(buildroot, tracking_branch, revision_list, board,
379 # overlays)
380 #else: 380 #else:
381 Info('CBUILDBOT Revving all') 381 Info('CBUILDBOT Revving all')
382 _UprevAllPackages(buildroot, tracking_branch, board) 382 _UprevAllPackages(buildroot, tracking_branch, board, overlays)
383 383
384 384
385 def _UprevPush(buildroot, tracking_branch, board, overlays): 385 def _UprevPush(buildroot, tracking_branch, board, overlays):
386 """Pushes uprev changes to the main line.""" 386 """Pushes uprev changes to the main line."""
387 cwd = os.path.join(buildroot, 'src', 'scripts') 387 cwd = os.path.join(buildroot, 'src', 'scripts')
388 public_overlay = '%s/src/third_party/chromiumos-overlay' % buildroot
389 private_overlay = '%s/src/private-overlays/chromeos-overlay' % buildroot
390 if overlays == 'private':
391 overlays = [private_overlay]
392 elif overlays == 'public':
393 overlays = [public_overlay]
394 else:
395 overlays = [public_overlay, private_overlay]
396 RunCommand(['./cros_mark_as_stable', '--srcroot=..', 388 RunCommand(['./cros_mark_as_stable', '--srcroot=..',
397 '--board=%s' % board, 389 '--board=%s' % board,
398 '--overlays=%s' % " ".join(overlays), 390 '--overlays=%s' % ':'.join(overlays),
399 '--tracking_branch=%s' % tracking_branch, 391 '--tracking_branch=%s' % tracking_branch,
400 '--push_options=--bypass-hooks -f', 'push'], 392 '--push_options=--bypass-hooks -f', 'push'],
401 cwd=cwd) 393 cwd=cwd)
402 394
403 395
404 def _ArchiveTestResults(buildroot, board, archive_dir, test_results_dir): 396 def _ArchiveTestResults(buildroot, board, archive_dir, test_results_dir):
405 """Archives the test results into the www dir for later use. 397 """Archives the test results into the www dir for later use.
406 398
407 Takes the results from the test_results_dir and dumps them into the archive 399 Takes the results from the test_results_dir and dumps them into the archive
408 dir specified. This also archives the last qemu image. 400 dir specified. This also archives the last qemu image.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 452
461 buildconfig = config[config_name] 453 buildconfig = config[config_name]
462 454
463 for key in default.iterkeys(): 455 for key in default.iterkeys():
464 if not buildconfig.has_key(key): 456 if not buildconfig.has_key(key):
465 buildconfig[key] = default[key] 457 buildconfig[key] = default[key]
466 458
467 return buildconfig 459 return buildconfig
468 460
469 461
462 def ResolveOverlays(overlays):
463 """Return the list of overlays to use for a given buildbot.
464
scottz-goog 2010/11/10 23:48:14 I know this file doesn't have proper docstrings an
davidjames 2010/11/11 02:23:24 Done.
465 overlays: A string describing which overlays you want.
466 'private': Just the private overlay.
467 'public': Just the public overlay.
468 'both': Both the public and private overlays.
469 """
scottz-goog 2010/11/10 23:48:14 Align indent.
davidjames 2010/11/11 02:23:24 Done.
470 public_overlay = '%s/src/third_party/chromiumos-overlay' % buildroot
471 private_overlay = '%s/src/private-overlays/chromeos-overlay' % buildroot
472 if overlays == 'private':
473 dirs = [private_overlay]
474 elif overlays == 'public':
475 dirs = [public_overlay]
476 elif overlays == 'both':
477 dirs = [public_overlay, private_overlay]
478 else:
479 Die('Incorrect overlay configuration: %s' % overlays)
480 for dir in dirs:
481 assert ':' not in dir, 'Overlay must not contain colons: %s' % dir
scottz-goog 2010/11/10 23:48:14 Why again are we doing this asssertion? Can you pl
davidjames 2010/11/11 02:23:24 It's very unlikely that it'll contain colons. Just
482 if not os.path.exists(dir):
483 Die('Missing overlay: %s' % dir)
484 return dirs
485
486
470 def main(): 487 def main():
471 # Parse options 488 # Parse options
472 usage = "usage: %prog [options] cbuildbot_config" 489 usage = "usage: %prog [options] cbuildbot_config"
473 parser = optparse.OptionParser(usage=usage) 490 parser = optparse.OptionParser(usage=usage)
474 parser.add_option('-r', '--buildroot', 491 parser.add_option('-r', '--buildroot',
475 help='root directory where build occurs', default=".") 492 help='root directory where build occurs', default=".")
476 parser.add_option('-n', '--buildnumber', 493 parser.add_option('-n', '--buildnumber',
477 help='build number', type='int', default=0) 494 help='build number', type='int', default=0)
478 parser.add_option('-f', '--revisionfile', 495 parser.add_option('-f', '--revisionfile',
479 help='file where new revisions are stored') 496 help='file where new revisions are stored')
(...skipping 15 matching lines...) Expand all
495 revisionfile = options.revisionfile 512 revisionfile = options.revisionfile
496 tracking_branch = options.tracking_branch 513 tracking_branch = options.tracking_branch
497 514
498 if len(args) >= 1: 515 if len(args) >= 1:
499 buildconfig = _GetConfig(args[-1]) 516 buildconfig = _GetConfig(args[-1])
500 else: 517 else:
501 Warning('Missing configuration description') 518 Warning('Missing configuration description')
502 parser.print_usage() 519 parser.print_usage()
503 sys.exit(1) 520 sys.exit(1)
504 521
522 # Calculate list of overlay directories.
523 overlays = ResolveOverlays(buildconfig['overlays'])
524
505 try: 525 try:
506 _PreFlightRinse(buildroot, buildconfig['board'], tracking_branch) 526 _PreFlightRinse(buildroot, buildconfig['board'], tracking_branch, overlays)
507 if options.clobber or not os.path.isdir(buildroot): 527 if options.clobber or not os.path.isdir(buildroot):
508 _FullCheckout(buildroot, tracking_branch, url=options.url) 528 _FullCheckout(buildroot, tracking_branch, url=options.url)
509 else: 529 else:
510 _IncrementalCheckout(buildroot) 530 _IncrementalCheckout(buildroot)
511 531
512 chroot_path = os.path.join(buildroot, 'chroot') 532 chroot_path = os.path.join(buildroot, 'chroot')
513 if not os.path.isdir(chroot_path): 533 if not os.path.isdir(chroot_path):
514 _MakeChroot(buildroot) 534 _MakeChroot(buildroot)
515 535
516 boardpath = os.path.join(chroot_path, 'build', buildconfig['board']) 536 boardpath = os.path.join(chroot_path, 'build', buildconfig['board'])
517 if not os.path.isdir(boardpath): 537 if not os.path.isdir(boardpath):
518 _SetupBoard(buildroot, board=buildconfig['board']) 538 _SetupBoard(buildroot, board=buildconfig['board'])
519 539
520 if buildconfig['uprev']: 540 if buildconfig['uprev']:
521 _UprevPackages(buildroot, tracking_branch, revisionfile, 541 _UprevPackages(buildroot, tracking_branch, revisionfile,
522 board=buildconfig['board']) 542 buildconfig['board'], overlays)
523 543
524 _EnableLocalAccount(buildroot) 544 _EnableLocalAccount(buildroot)
525 _Build(buildroot) 545 _Build(buildroot)
526 if buildconfig['unittests']: 546 if buildconfig['unittests']:
527 _RunUnitTests(buildroot) 547 _RunUnitTests(buildroot)
528 548
529 _BuildImage(buildroot) 549 _BuildImage(buildroot)
530 550
531 if buildconfig['smoke_bvt']: 551 if buildconfig['smoke_bvt']:
532 _BuildVMImageForTesting(buildroot) 552 _BuildVMImageForTesting(buildroot)
533 test_results_dir = '/tmp/run_remote_tests.%s' % options.buildnumber 553 test_results_dir = '/tmp/run_remote_tests.%s' % options.buildnumber
534 try: 554 try:
535 _RunSmokeSuite(buildroot, test_results_dir) 555 _RunSmokeSuite(buildroot, test_results_dir)
536 finally: 556 finally:
537 _ArchiveTestResults(buildroot, buildconfig['board'], 557 _ArchiveTestResults(buildroot, buildconfig['board'],
538 archive_dir=options.buildnumber, 558 archive_dir=options.buildnumber,
539 test_results_dir=test_results_dir) 559 test_results_dir=test_results_dir)
540 560
541 if buildconfig['uprev']: 561 if buildconfig['uprev']:
542 # Don't push changes for developers. 562 # Don't push changes for developers.
543 if not options.debug: 563 if not options.debug:
544 if buildconfig['master']: 564 if buildconfig['master']:
545 # Master bot needs to check if the other slaves completed. 565 # Master bot needs to check if the other slaves completed.
546 if cbuildbot_comm.HaveSlavesCompleted(config): 566 if cbuildbot_comm.HaveSlavesCompleted(config):
547 _UprevPush(buildroot, tracking_branch, buildconfig['board'], 567 _UprevPush(buildroot, tracking_branch, buildconfig['board'],
548 buildconfig['overlays']) 568 overlays)
549 else: 569 else:
550 Die('CBUILDBOT - One of the slaves has failed!!!') 570 Die('CBUILDBOT - One of the slaves has failed!!!')
551 571
552 else: 572 else:
553 # Publish my status to the master if its expecting it. 573 # Publish my status to the master if its expecting it.
554 if buildconfig['important']: 574 if buildconfig['important']:
555 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) 575 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE)
556 576
557 except: 577 except:
558 # Send failure to master bot. 578 # Send failure to master bot.
559 if not buildconfig['master'] and buildconfig['important']: 579 if not buildconfig['master'] and buildconfig['important']:
560 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) 580 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED)
561 581
562 raise 582 raise
563 583
564 584
565 if __name__ == '__main__': 585 if __name__ == '__main__':
566 main() 586 main()
OLDNEW
« no previous file with comments | « no previous file | bin/cbuildbot_config.py » ('j') | bin/cbuildbot_unittest.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698