| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 | |
| 7 """ Repeatedly launch the build master in an infinite loop, updating the source | |
| 8 between launches. This script is intended to be run at boot time. """ | |
| 9 | |
| 10 | |
| 11 import os | |
| 12 import socket | |
| 13 import subprocess | |
| 14 import sys | |
| 15 import time | |
| 16 | |
| 17 BUILDBOT_PATH = os.path.realpath(os.path.join(os.path.dirname(__file__), | |
| 18 os.pardir)) | |
| 19 sys.path.append(os.path.join(BUILDBOT_PATH, 'site_config')) | |
| 20 sys.path.append(os.path.join(BUILDBOT_PATH, 'third_party', 'chromium_buildbot', | |
| 21 'site_config')) | |
| 22 | |
| 23 import config_private | |
| 24 | |
| 25 | |
| 26 # File where the PID of the running master is stored | |
| 27 PID_FILE = 'twistd.pid' | |
| 28 | |
| 29 # Maximum time (in seconds) to wait for PID_FILE to be written after the master | |
| 30 # is launched. If PID_FILE is not written by then, we assume an error occurred. | |
| 31 PID_TIMEOUT = 10.0 | |
| 32 | |
| 33 | |
| 34 def _SyncSources(): | |
| 35 """ Run 'gclient sync' on the buildbot sources. """ | |
| 36 path_to_gclient = os.path.join(BUILDBOT_PATH, 'third_party', 'depot_tools', | |
| 37 'gclient.py') | |
| 38 cmd = ['python', path_to_gclient, 'sync'] | |
| 39 if not subprocess.call(cmd) == 0: | |
| 40 # Don't throw an exception or quit, since we want to keep the master running | |
| 41 print 'WARNING: Failed to update sources.' | |
| 42 | |
| 43 | |
| 44 def _LaunchMaster(): | |
| 45 """ Launch the build master and return its PID. """ | |
| 46 # Make sure the master is stopped. | |
| 47 subprocess.call(['make', 'stop']) | |
| 48 | |
| 49 # Launch the master | |
| 50 cmd = ['make', 'start'] | |
| 51 if not os.environ.get('TESTING_MASTER'): | |
| 52 for master in config_private.Master.valid_masters: | |
| 53 if socket.getfqdn() == master.master_fqdn: | |
| 54 master_name = master.__name__ | |
| 55 print 'Using master %s' % master_name | |
| 56 os.environ['TESTING_MASTER'] = master_name | |
| 57 break | |
| 58 else: | |
| 59 print 'Could not find a matching production master. Using default.' | |
| 60 subprocess.call(cmd) | |
| 61 | |
| 62 # Wait for the pid file to be written, then use it to obtain the master's pid | |
| 63 pid_file = None | |
| 64 start_time = time.time() | |
| 65 while not pid_file: | |
| 66 try: | |
| 67 pid_file = open(PID_FILE) | |
| 68 except Exception: | |
| 69 if time.time() - start_time > PID_TIMEOUT: | |
| 70 raise Exception('Failed to launch master.') | |
| 71 time.sleep(1) | |
| 72 pid = str(pid_file.read()).rstrip() | |
| 73 pid_file.close() | |
| 74 return pid | |
| 75 | |
| 76 | |
| 77 # TODO(borenet): Share this code with launch_slaves.py. | |
| 78 def IsRunning(pid): | |
| 79 """ Determine whether a process with the given PID is running. | |
| 80 | |
| 81 pid: string; the PID to test. If pid is None, return False. | |
| 82 """ | |
| 83 if pid is None: | |
| 84 return False | |
| 85 if os.name == 'nt': | |
| 86 cmd = ['tasklist', '/FI', '"PID eq %s"' % pid] | |
| 87 output = subprocess.check_output(cmd, stdout=subprocess.PIPE, | |
| 88 stderr=subprocess.STDOUT) | |
| 89 is_running = pid in output | |
| 90 else: | |
| 91 cmd = ['cat', '/proc/%s/stat' % pid] | |
| 92 is_running = subprocess.call(cmd, stdout=subprocess.PIPE, | |
| 93 stderr=subprocess.STDOUT) == 0 | |
| 94 return is_running | |
| 95 | |
| 96 | |
| 97 def _BlockUntilFinished(pid): | |
| 98 """ Blocks until the given process has finished. | |
| 99 | |
| 100 pid: PID of the process to wait for | |
| 101 """ | |
| 102 while IsRunning(pid): | |
| 103 time.sleep(1) | |
| 104 | |
| 105 | |
| 106 def _UpdateAndRunMaster(): | |
| 107 """ Update the buildbot sources and run the build master, blocking until it | |
| 108 finishes. """ | |
| 109 _SyncSources() | |
| 110 pid = _LaunchMaster() | |
| 111 print 'Launched build master with PID: %s' % pid | |
| 112 _BlockUntilFinished(pid) | |
| 113 print 'Master process has finished.' | |
| 114 | |
| 115 | |
| 116 def main(): | |
| 117 """ Alternately sync the buildbot source and launch the build master. """ | |
| 118 loop = '--noloop' not in sys.argv | |
| 119 master_path = os.path.join(BUILDBOT_PATH, 'master') | |
| 120 os.chdir(master_path) | |
| 121 _UpdateAndRunMaster() | |
| 122 while loop: | |
| 123 print 'Restarting the build master.' | |
| 124 _UpdateAndRunMaster() | |
| 125 | |
| 126 if '__main__' == __name__: | |
| 127 sys.exit(main()) | |
| OLD | NEW |