Package buildbot :: Package scripts :: Module logwatcher
[hide private]
[frames] | no frames]

Source Code for Module buildbot.scripts.logwatcher

 1   
 2  import os 
 3  from twisted.python.failure import Failure 
 4  from twisted.internet import defer, reactor, protocol, error 
 5  from twisted.protocols.basic import LineOnlyReceiver 
 6   
7 -class FakeTransport:
8 disconnecting = False
9
10 -class BuildmasterTimeoutError(Exception):
11 pass
12 -class BuildslaveTimeoutError(Exception):
13 pass
14 -class ReconfigError(Exception):
15 pass
16 -class BuildSlaveDetectedError(Exception):
17 pass
18
19 -class TailProcess(protocol.ProcessProtocol):
20 - def outReceived(self, data):
21 self.lw.dataReceived(data)
22 - def errReceived(self, data):
23 print "ERR: '%s'" % (data,)
24 25
26 -class LogWatcher(LineOnlyReceiver):
27 POLL_INTERVAL = 0.1 28 TIMEOUT_DELAY = 10.0 29 delimiter = os.linesep 30
31 - def __init__(self, logfile):
32 self.logfile = logfile 33 self.in_reconfig = False 34 self.transport = FakeTransport() 35 self.pp = TailProcess() 36 self.pp.lw = self 37 self.processtype = "buildmaster" 38 self.timer = None
39
40 - def start(self):
41 # return a Deferred that fires when the reconfig process has 42 # finished. It errbacks with TimeoutError if the finish line has not 43 # been seen within 10 seconds, and with ReconfigError if the error 44 # line was seen. If the logfile could not be opened, it errbacks with 45 # an IOError. 46 self.p = reactor.spawnProcess(self.pp, "/usr/bin/tail", 47 ("tail", "-f", "-n", "0", self.logfile), 48 env=os.environ, 49 ) 50 self.running = True 51 d = defer.maybeDeferred(self._start) 52 return d
53
54 - def _start(self):
55 self.d = defer.Deferred() 56 self.timer = reactor.callLater(self.TIMEOUT_DELAY, self.timeout) 57 return self.d
58
59 - def timeout(self):
60 self.timer = None 61 if self.processtype == "buildmaster": 62 e = BuildmasterTimeoutError() 63 else: 64 e = BuildslaveTimeoutError() 65 self.finished(Failure(e))
66
67 - def finished(self, results):
68 try: 69 self.p.signalProcess("KILL") 70 except error.ProcessExitedAlready: 71 pass 72 if self.timer: 73 self.timer.cancel() 74 self.timer = None 75 self.running = False 76 self.in_reconfig = False 77 self.d.callback(results)
78
79 - def lineReceived(self, line):
80 if not self.running: 81 return 82 if "Log opened." in line: 83 self.in_reconfig = True 84 if "loading configuration from" in line: 85 self.in_reconfig = True 86 if "Creating BuildSlave" in line: 87 self.processtype = "buildslave" 88 89 if self.in_reconfig: 90 print line 91 92 if "message from master: attached" in line: 93 return self.finished("buildslave") 94 if "I will keep using the previous config file" in line: 95 return self.finished(Failure(ReconfigError())) 96 if "configuration update complete" in line: 97 return self.finished("buildmaster")
98