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 |