OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 | 6 |
7 """ Launch multiple buildbot slave instances on a single machine. This script | 7 """ Launch multiple buildbot slave instances on a single machine. This script |
8 is intended to be run at boot time. """ | 8 is intended to be run at boot time. """ |
9 | 9 |
10 | 10 |
11 import multiprocessing | 11 import multiprocessing |
12 import os | 12 import os |
13 import shutil | 13 import shutil |
14 import socket | 14 import socket |
15 import subprocess | 15 import subprocess |
16 import sys | 16 import sys |
17 import time | 17 import time |
18 | 18 |
19 | 19 |
20 buildbot_path = os.path.abspath(os.path.join(os.path.dirname(__file__), | 20 buildbot_path = os.path.abspath(os.path.join(os.path.dirname(__file__), |
21 os.pardir)) | 21 os.pardir)) |
22 sys.path.append(os.path.join(buildbot_path, 'master')) | |
23 sys.path.append(os.path.join(buildbot_path, 'site_config')) | 22 sys.path.append(os.path.join(buildbot_path, 'site_config')) |
24 sys.path.append(os.path.join(buildbot_path, 'third_party', 'chromium_buildbot', | |
25 'scripts')) | |
26 sys.path.append(os.path.join(buildbot_path, 'third_party', 'chromium_buildbot', | |
27 'site_config')) | |
28 sys.path.append(os.path.join(buildbot_path, 'third_party', 'chromium_buildbot', | |
29 'third_party', 'buildbot_8_4p1')) | |
30 sys.path.append(os.path.join(buildbot_path, 'third_party', 'chromium_buildbot', | |
31 'third_party', 'jinja2')) | |
32 sys.path.append(os.path.join(buildbot_path, 'third_party', 'chromium_buildbot', | |
33 'third_party', 'twisted_8_1')) | |
34 | 23 |
35 | |
36 import config | |
37 import slave_hosts_cfg | 24 import slave_hosts_cfg |
38 import slaves_cfg | |
39 | 25 |
40 | 26 |
41 CHROME_INTERNAL = 'https://chrome-internal.googlesource.com/' | 27 CHROME_INTERNAL = 'https://chrome-internal.googlesource.com/' |
42 CHROME_SLAVE_DEPS_URL = CHROME_INTERNAL + 'chrome/tools/build/slave.DEPS' | 28 CHROME_SLAVE_DEPS_URL = CHROME_INTERNAL + 'chrome/tools/build/slave.DEPS' |
43 CHROME_SLAVE_INTERNAL_DEPS_URL = ( | 29 CHROME_SLAVE_INTERNAL_DEPS_URL = ( |
44 CHROME_INTERNAL + 'chrome/tools/build/internal.DEPS') | 30 CHROME_INTERNAL + 'chrome/tools/build/internal.DEPS') |
45 SKIA_URL = 'https://skia.googlesource.com/buildbot.git' | |
46 GCLIENT = 'gclient.bat' if os.name == 'nt' else 'gclient' | 31 GCLIENT = 'gclient.bat' if os.name == 'nt' else 'gclient' |
47 GIT = 'git.bat' if os.name == 'nt' else 'git' | |
48 NEW_MASTER_NAME = { | |
49 'Skia': 'Skia', | |
50 'AndroidSkia': 'SkiaAndroid', | |
51 'CompileSkia': 'SkiaCompile', | |
52 'FYISkia': 'SkiaFYI', | |
53 'PrivateSkia': 'SkiaInternal', | |
54 } | |
55 UPSTREAM_MASTER_PREFIX = 'client.skia' | |
56 | |
57 | 32 |
58 # How often we should check each buildslave's keepalive conditions, in seconds. | 33 # How often we should check each buildslave's keepalive conditions, in seconds. |
59 DEFAULT_POLL_INTERVAL = 60 | 34 PID_FILE = os.path.join('build', 'slave', 'twistd.pid') |
60 PID_FILE = os.path.join('buildbot', 'third_party', 'chromium_buildbot', 'slave', | 35 |
61 'twistd.pid') | |
62 # Maximum time (in seconds) to wait for PID_FILE to be written after the slave | 36 # Maximum time (in seconds) to wait for PID_FILE to be written after the slave |
63 # is launched. If PID_FILE is not written by then, we assume an error occurred. | 37 # is launched. If PID_FILE is not written by then, we assume an error occurred. |
64 PID_TIMEOUT = 60.0 | 38 PID_TIMEOUT = 60.0 |
65 | 39 |
66 | 40 |
67 | |
68 logger = None | 41 logger = None |
69 | 42 |
70 | 43 |
71 # TODO(borenet): Share this code with launch_master.py. | |
72 def IsRunning(pid): | 44 def IsRunning(pid): |
73 """ Determine whether a process with the given PID is running. | 45 """ Determine whether a process with the given PID is running. |
74 | 46 |
75 pid: string; the PID to test. If pid is None, return False. | 47 pid: string; the PID to test. If pid is None, return False. |
76 """ | 48 """ |
77 if pid is None: | 49 if pid is None: |
78 return False | 50 return False |
79 if os.name == 'nt': | 51 if os.name == 'nt': |
80 cmd = ['tasklist', '/FI', '"PID eq %s"' % pid] | 52 cmd = ['tasklist', '/FI', '"PID eq %s"' % pid] |
81 output = subprocess.check_output(cmd, stdout=subprocess.PIPE, | 53 output = subprocess.check_output(cmd, stdout=subprocess.PIPE, |
82 stderr=subprocess.STDOUT) | 54 stderr=subprocess.STDOUT) |
83 is_running = pid in output | 55 is_running = pid in output |
84 else: | 56 else: |
85 cmd = ['cat', '/proc/%s/stat' % pid] | 57 cmd = ['cat', '/proc/%s/stat' % pid] |
86 is_running = subprocess.call(cmd, stdout=subprocess.PIPE, | 58 is_running = subprocess.call(cmd, stdout=subprocess.PIPE, |
87 stderr=subprocess.STDOUT) == 0 | 59 stderr=subprocess.STDOUT) == 0 |
88 return is_running | 60 return is_running |
89 | 61 |
90 | 62 |
63 def _IsRunning(): | |
64 """Determine if the BuildSlave is running in CWD | |
65 | |
66 If so, return its PID. Otherwise, return None. | |
67 """ | |
68 if os.path.isfile(PID_FILE): | |
69 with open(PID_FILE) as f: | |
70 pid = str(f.read()).rstrip() | |
71 if IsRunning(pid): | |
72 return pid | |
73 return None | |
74 | |
75 | |
76 def _KillSlave(): | |
77 """Kill the BuildSlave running in CWD.""" | |
78 pid = _IsRunning() | |
79 if not pid: | |
80 print '_KillSlave: Slave not running.' | |
81 return | |
82 if os.name == 'nt': | |
83 cmd = ['taskkill', '/F', '/T', '/PID', str(pid)] | |
84 else: | |
85 cmd = ['make', 'stop'] | |
86 subprocess.check_call(cmd, cwd=os.path.join('buildbot', 'slave')) | |
87 | |
88 | |
91 class BuildSlaveManager(multiprocessing.Process): | 89 class BuildSlaveManager(multiprocessing.Process): |
92 """ Manager process for BuildSlaves. Periodically checks that any | 90 """Manager process for BuildSlaves.""" |
93 keepalive_conditions are met and kills or starts the slave accordingly. """ | |
94 | 91 |
95 def __init__(self, slavename, checkout_path, copies, copy_src_dir, | 92 def __init__(self, slavename, checkout_path, copies, copy_src_dir, |
96 master_name, keepalive_conditions, poll_interval): | 93 is_internal): |
97 """ Construct the BuildSlaveManager. | 94 """ Construct the BuildSlaveManager. |
98 | 95 |
99 slavename: string; the name of the slave to start. | 96 slavename: string; the name of the slave to start. |
100 checkout_path: string; the directory in which to launch the slave. | 97 checkout_path: string; the directory in which to launch the slave. |
101 copies: list of dictionaries; files to copy into the slave's source | 98 copies: list of dictionaries; files to copy into the slave's source |
102 checkout. | 99 checkout. |
103 copy_src_dir: string; directory in which the files to copy reside. | 100 copy_src_dir: string; directory in which the files to copy reside. |
104 master_name: string; name of the master to which this build slave connects. | 101 is_internal: bool; whether this buildslave uses internal code. |
105 This is NOT the hostname of the master, which is obtained from the | |
106 master class in config_private.py. | |
107 keepalive_conditions: list; commands which must succeed in order for the | |
108 slave to stay alive. | |
109 poll_interval: number; how often to verify the keepalive_conditions, in | |
110 seconds. | |
111 """ | 102 """ |
112 self._slavename = slavename | 103 self._slavename = slavename |
113 self._checkout_path = checkout_path | 104 self._checkout_path = checkout_path |
114 self._copies = copies | 105 self._copies = copies |
115 self._copy_src_dir = os.path.abspath(copy_src_dir) | 106 self._copy_src_dir = os.path.abspath(copy_src_dir) |
116 self._keepalive_conditions = keepalive_conditions | 107 self._is_internal = is_internal |
117 self._poll_interval = poll_interval | |
118 self._master_name = master_name | |
119 multiprocessing.Process.__init__(self) | 108 multiprocessing.Process.__init__(self) |
120 | 109 |
121 def _GClientConfig(self): | 110 def _GClientConfig(self): |
122 """Run 'gclient config'.""" | 111 """Run 'gclient config'.""" |
123 subprocess.check_call([GCLIENT, 'config', SKIA_URL]) | 112 config_url = (CHROME_SLAVE_INTERNAL_DEPS_URL if self._is_internal |
113 else CHROME_SLAVE_DEPS_URL) | |
114 cmd = [GCLIENT, 'config', config_url, '--deps-file', '.DEPS.git'] | |
115 print 'Running command: %s' % ' '.join(cmd) | |
116 subprocess.check_call(cmd) | |
124 | 117 |
125 def _SyncSources(self): | 118 def _SyncSources(self): |
126 """ Run 'gclient sync' on the buildbot sources. """ | 119 """ Run 'gclient sync' on the buildbot sources. """ |
127 # Check out or update the buildbot scripts | 120 # Check out or update the buildbot scripts |
128 self._GClientConfig() | 121 self._GClientConfig() |
129 subprocess.check_call([GCLIENT, 'sync', '-j1', '--force']) | 122 subprocess.check_call([GCLIENT, 'sync', '-j1', '--force']) |
130 | 123 |
131 if os.name == 'nt': | 124 if os.name == 'nt': |
132 os.environ['WIN_TOOLS_FORCE'] = '1' | 125 os.environ['WIN_TOOLS_FORCE'] = '1' |
133 subprocess.check_call([self.local_gclient]) | 126 subprocess.check_call([os.path.join(os.getcwd(), 'depot_tools', GCLIENT)]) |
134 del os.environ['WIN_TOOLS_FORCE'] | 127 del os.environ['WIN_TOOLS_FORCE'] |
135 | 128 |
136 # Perform Copies | 129 # Perform Copies |
137 if self._copies: | 130 if self._copies: |
138 for copy in self._copies: | 131 for copy in self._copies: |
139 src = os.path.join(self._copy_src_dir, os.path.normpath(copy['source'])) | 132 src = os.path.join(self._copy_src_dir, os.path.normpath(copy['source'])) |
140 dest = os.path.normpath(copy['destination']) | 133 dest = os.path.normpath(copy['destination']) |
141 print 'Copying %s to %s' % (src, dest) | 134 print 'Copying %s to %s' % (src, dest) |
142 shutil.copy(src, dest) | 135 shutil.copy(src, dest) |
143 | 136 |
144 @property | |
145 def master_host(self): | |
146 """Return the hostname of the master for this buildslave.""" | |
147 return config.Master.set_active_master(self._master_name).master_host | |
148 | |
149 @property | |
150 def slave_dir(self): | |
151 """Directory in which to launch the slave.""" | |
152 return os.path.join('buildbot', 'slave') | |
153 | |
154 @property | |
155 def local_gclient(self): | |
156 """Path to the local version of gclient within this slave's checkout.""" | |
157 return os.path.join(os.getcwd(), 'buildbot', 'third_party', 'depot_tools', | |
158 GCLIENT) | |
159 | |
160 def _LaunchSlave(self): | 137 def _LaunchSlave(self): |
161 """ Launch the BuildSlave. """ | 138 """ Launch the BuildSlave. """ |
162 self._KillSlave() | 139 _KillSlave() |
163 | 140 |
164 self._SyncSources() | 141 self._SyncSources() |
165 | 142 |
166 if os.name == 'nt': | 143 if os.name == 'nt': |
167 # We run different commands for the Windows shell | 144 # We run different commands for the Windows shell |
168 cmd = 'setlocal&&' | 145 cmd = 'setlocal&&' |
169 cmd += 'set TESTING_SLAVENAME=%s&&' % self._slavename | 146 cmd += 'set TESTING_SLAVENAME=%s&&' % self._slavename |
170 cmd += 'set TESTING_MASTER=%s&&' % self._master_name | |
171 if self.master_host: | |
172 cmd += 'set TESTING_MASTER_HOST=%s&&' % self.master_host | |
173 cmd += 'run_slave.bat' | 147 cmd += 'run_slave.bat' |
174 cmd += '&& endlocal' | 148 cmd += '&& endlocal' |
175 else: | 149 else: |
176 cmd = 'TESTING_SLAVENAME=%s ' % self._slavename | 150 cmd = 'TESTING_SLAVENAME=%s ' % self._slavename |
177 cmd += 'TESTING_MASTER=%s ' % self._master_name | |
178 if self.master_host: | |
179 cmd += 'TESTING_MASTER_HOST=%s ' % self.master_host | |
180 cmd += 'make start' | 151 cmd += 'make start' |
181 print 'Running cmd: %s' % cmd | 152 print 'Running cmd: %s' % cmd |
182 subprocess.check_call(cmd, shell=True, cwd=self.slave_dir) | 153 subprocess.check_call(cmd, shell=True, cwd=os.path.join('build', 'slave')) |
183 | 154 |
184 start_time = time.time() | 155 start_time = time.time() |
185 while not self._IsRunning(): | 156 while not _IsRunning(): |
186 if time.time() - start_time > PID_TIMEOUT: | 157 if time.time() - start_time > PID_TIMEOUT: |
187 raise Exception('Failed to launch %s' % self._slavename) | 158 raise Exception('Failed to launch %s' % self._slavename) |
188 time.sleep(1) | 159 time.sleep(1) |
189 | 160 |
190 def _IsRunning(self): | |
191 """ Determine if this BuildSlave is running. If so, return its PID, | |
192 otherwise, return None. """ | |
193 if os.path.isfile(PID_FILE): | |
194 with open(PID_FILE) as f: | |
195 pid = str(f.read()).rstrip() | |
196 if IsRunning(pid): | |
197 return pid | |
198 return None | |
199 | |
200 def _KillSlave(self): | |
201 """ Kill the BuildSlave. """ | |
202 pid = self._IsRunning() | |
203 if not pid: | |
204 print 'BuildSlaveManager._KillSlave: Slave not running.' | |
205 return | |
206 if os.name == 'nt': | |
207 cmd = ['taskkill', '/F', '/T', '/PID', str(pid)] | |
208 else: | |
209 cmd = ['make', 'stop'] | |
210 subprocess.check_call(cmd, cwd=os.path.join('buildbot', 'slave')) | |
211 | |
212 def run(self): | 161 def run(self): |
213 """ Run the BuildSlaveManager. This overrides multiprocessing.Process's | 162 """ Run the BuildSlaveManager. This overrides multiprocessing.Process's |
214 run() method. """ | 163 run() method. """ |
215 os.chdir(self._checkout_path) | 164 os.chdir(self._checkout_path) |
216 self._SyncSources() | 165 self._SyncSources() |
217 self._checkout_path = os.path.abspath(os.curdir) | 166 self._checkout_path = os.path.abspath(os.curdir) |
218 self._KillSlave() | 167 _KillSlave() |
219 while True: | 168 self._LaunchSlave() |
220 print 'Checking keepalive conditions for %s' % self._slavename | 169 print 'Successfully launched slave %s.' % self._slavename |
borenet
2014/10/17 18:04:18
We lose keepalive_conditions as part of this chang
rmistry
2014/10/17 18:19:21
Acknowledged.
| |
221 slave_can_run = True | |
222 for keepalive_condition in self._keepalive_conditions: | |
223 print 'Executing keepalive condition: %s' % keepalive_condition | |
224 proc = subprocess.Popen(keepalive_condition, stdout=subprocess.PIPE, | |
225 stderr=subprocess.STDOUT) | |
226 if proc.wait() != 0: | |
227 print 'Keepalive condition failed for %s: %s' % (self._slavename, | |
228 keepalive_condition) | |
229 print proc.communicate()[0] | |
230 slave_can_run = False | |
231 break | |
232 print proc.communicate()[0] | |
233 if not slave_can_run and self._IsRunning(): | |
234 self._KillSlave() | |
235 elif slave_can_run and not self._IsRunning(): | |
236 self._LaunchSlave() | |
237 print 'Successfully launched slave %s.' % self._slavename | |
238 time.sleep(self._poll_interval) | |
239 print 'Slave process for %s has finished.' % self._slavename | 170 print 'Slave process for %s has finished.' % self._slavename |
240 | 171 |
241 | 172 |
242 class ChromeBuildSlaveManager(BuildSlaveManager): | |
243 """BuildSlaveManager for slaves using Chromium build code.""" | |
244 | |
245 def _GClientConfig(self): | |
246 """Run 'gclient config'.""" | |
247 config_url = ( | |
248 CHROME_SLAVE_INTERNAL_DEPS_URL if self._master_name == 'SkiaInternal' | |
249 else CHROME_SLAVE_DEPS_URL) | |
250 cmd = [GCLIENT, 'config', config_url, '--deps-file', '.DEPS.git'] | |
251 print 'Running command: %s' % ' '.join(cmd) | |
252 subprocess.check_call(cmd) | |
253 | |
254 @property | |
255 def master_host(self): | |
256 """Return the hostname of the master for this buildslave.""" | |
257 return None # Just use the default. | |
258 | |
259 @property | |
260 def slave_dir(self): | |
261 """Directory from which to launch the buildslave.""" | |
262 return os.path.join('build', 'slave') | |
263 | |
264 @property | |
265 def local_gclient(self): | |
266 """Path to the local version of gclient within this slave's checkout.""" | |
267 return os.path.join(os.getcwd(), 'depot_tools', GCLIENT) | |
268 | |
269 | |
270 def ReadSlavesCfg(slaves_cfg_path): | 173 def ReadSlavesCfg(slaves_cfg_path): |
271 """Read the given slaves.cfg path and return the slaves dict.""" | 174 """Read the given slaves.cfg path and return the slaves dict.""" |
272 cfg = {} | 175 cfg = {} |
273 execfile(slaves_cfg_path, cfg) | 176 execfile(slaves_cfg_path, cfg) |
274 return cfg['slaves'] | 177 return cfg['slaves'] |
275 | 178 |
276 | 179 |
277 def RunSlave(slavename, slave_num, connects_to_new_master=False): | 180 def RunSlave(slavename, slave_num, is_internal): |
278 """ Launch a single slave, checking out the buildbot tree if necessary. | 181 """ Launch a single slave, checking out the buildbot tree if necessary. |
279 | 182 |
280 slavename: string indicating the hostname of the build slave to launch. | 183 slavename: string indicating the hostname of the build slave to launch. |
281 copies: dictionary with 'source' and 'destination' keys whose values are the | 184 copies: dictionary with 'source' and 'destination' keys whose values are the |
rmistry
2014/10/17 18:19:21
Can you replace copies with slave_num.
borenet
2014/10/17 18:39:26
Done.
| |
282 current location and destination location within the buildbot checkout of | 185 current location and destination location within the buildbot checkout of |
283 files to be copied. | 186 files to be copied. |
187 is_internal: bool; whether this slave uses internal code. | |
284 """ | 188 """ |
285 print 'Starting slave: %s%s' % ( | 189 print 'Starting slave: %s' % slavename |
286 slavename, ' (new)' if connects_to_new_master else '') | |
287 start_dir = os.path.realpath(os.curdir) | 190 start_dir = os.path.realpath(os.curdir) |
288 slave_dir = os.path.join(start_dir, slavename) | 191 slave_dir = os.path.join(start_dir, slavename) |
289 if connects_to_new_master and os.name == 'nt': | 192 if os.name == 'nt': |
290 slave_dir = os.path.join('c:\\', slave_num) | 193 slave_dir = os.path.join('c:\\', slave_num) |
291 copies = (slave_hosts_cfg.CHROMEBUILD_COPIES if connects_to_new_master | 194 copies = slave_hosts_cfg.CHROMEBUILD_COPIES |
292 else slave_hosts_cfg.DEFAULT_COPIES) | |
293 | 195 |
294 # Create the slave directory if needed | 196 # Create the slave directory if needed |
295 if not os.path.isdir(slave_dir): | 197 if not os.path.isdir(slave_dir): |
296 print 'Creating directory: %s' % slave_dir | 198 print 'Creating directory: %s' % slave_dir |
297 os.makedirs(slave_dir) | 199 os.makedirs(slave_dir) |
298 | 200 |
299 # Find the slave config dict and BuildSlaveManager type for this slave. | |
300 slave_cfg = {} | |
301 manager = (ChromeBuildSlaveManager if connects_to_new_master | |
302 else BuildSlaveManager) | |
303 for cfg in slaves_cfg.SLAVES: | |
304 if cfg['hostname'] == slavename: | |
305 slave_cfg = cfg | |
306 break | |
307 if not slave_cfg: | |
308 # Try looking at upstream masters. | |
309 upstream_masters_dir = os.path.join('third_party', | |
310 'chromium_buildbot_tot', | |
311 'masters') | |
312 for master_dir in os.listdir(upstream_masters_dir): | |
313 if master_dir.startswith('master.%s' % UPSTREAM_MASTER_PREFIX): | |
314 slaves_cfg_path = os.path.join( | |
315 upstream_masters_dir, master_dir, 'slaves.cfg') | |
316 for cfg in ReadSlavesCfg(slaves_cfg_path): | |
317 if cfg['hostname'] == slavename: | |
318 slave_cfg = cfg | |
319 break | |
320 if not slave_cfg: | |
321 raise Exception('No buildslave config found for %s!' % slavename) | |
322 | |
323 # Launch the buildslave. | 201 # Launch the buildslave. |
324 master_name = slave_cfg['master'] | 202 BuildSlaveManager(slavename, slave_dir, copies, os.pardir, is_internal |
325 if connects_to_new_master: | 203 ).start() |
326 master_name = NEW_MASTER_NAME[master_name] | |
327 manager(slavename, slave_dir, copies, os.pardir, master_name, | |
328 slave_cfg.get('keepalive_conditions', []), DEFAULT_POLL_INTERVAL | |
329 ).start() | |
330 | 204 |
331 | 205 |
332 class FileLogger: | 206 class FileLogger: |
333 """ Write stdout to a log file. """ | 207 """ Write stdout to a log file. """ |
334 def __init__(self, log_file_name): | 208 def __init__(self, log_file_name): |
335 # Open the log file. | 209 # Open the log file. |
336 self._logfile = open(log_file_name, 'w') | 210 self._logfile = open(log_file_name, 'w') |
337 self._stdout = sys.stdout | 211 self._stdout = sys.stdout |
338 sys.stdout = self | 212 sys.stdout = self |
339 | 213 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 if os.name == 'nt': | 266 if os.name == 'nt': |
393 os.environ['HOME'] = os.path.join('c:\\', 'Users', 'chrome-bot') | 267 os.environ['HOME'] = os.path.join('c:\\', 'Users', 'chrome-bot') |
394 | 268 |
395 # Sync the buildbot code. | 269 # Sync the buildbot code. |
396 subprocess.check_call([GCLIENT, 'sync', '--force', '-j1']) | 270 subprocess.check_call([GCLIENT, 'sync', '--force', '-j1']) |
397 | 271 |
398 # Obtain configuration information about this build slave host machine. | 272 # Obtain configuration information about this build slave host machine. |
399 slave_host = slave_hosts_cfg.get_slave_host_config(socket.gethostname()) | 273 slave_host = slave_hosts_cfg.get_slave_host_config(socket.gethostname()) |
400 slaves = slave_host.slaves | 274 slaves = slave_host.slaves |
401 print 'Attempting to launch build slaves:' | 275 print 'Attempting to launch build slaves:' |
402 for slavename, _, connects_to_new_master in slaves: | 276 for slavename, _, _ in slaves: |
403 print ' %s%s' % (slavename, | 277 print ' %s' % slavename |
404 (' (new master)' if connects_to_new_master else '')) | |
405 | 278 |
406 # Launch the build slaves | 279 # Launch the build slaves |
407 for slavename, slave_num, connects_to_new_master in slaves: | 280 for slavename, slave_num, is_internal in slaves: |
408 RunSlave(slavename, slave_num, connects_to_new_master) | 281 RunSlave(slavename, slave_num, is_internal) |
409 | 282 |
410 | 283 |
411 if '__main__' == __name__: | 284 if '__main__' == __name__: |
412 # Pipe all output to a log file. | 285 # Pipe all output to a log file. |
413 logfile = 'launch_slaves.log' | 286 logfile = 'launch_slaves.log' |
414 if os.path.isfile(logfile): | 287 if os.path.isfile(logfile): |
415 num = 1 | 288 num = 1 |
416 new_filename = logfile + '.' + str(num) | 289 new_filename = logfile + '.' + str(num) |
417 while os.path.isfile(new_filename): | 290 while os.path.isfile(new_filename): |
418 num += 1 | 291 num += 1 |
419 new_filename = logfile + '.' + str(num) | 292 new_filename = logfile + '.' + str(num) |
420 os.rename(logfile, new_filename) | 293 os.rename(logfile, new_filename) |
421 logger = FileLogger(logfile) | 294 logger = FileLogger(logfile) |
422 sys.exit(main()) | 295 sys.exit(main()) |
OLD | NEW |