From 00328295738af0b5f6022f1c1eabe71ab83f24b1 Mon Sep 17 00:00:00 2001 From: warner Date: Fri, 24 Nov 2006 14:21:21 +0100 Subject: [PATCH] enhance 'buildbot sighup' to show all related twistd.log lines. Also rename it to 'buildbot reconfig'. This addresses half of SF#1517975 --- ChangeLog | 13 +++++++ buildbot/master.py | 2 + buildbot/scripts/reconfig.py | 93 ++++++++++++++++++++++++++++++++++++++++++++ buildbot/scripts/runner.py | 16 +++++++- docs/buildbot.texinfo | 8 +++- 5 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 buildbot/scripts/reconfig.py diff --git a/ChangeLog b/ChangeLog index 36aecbe..67e27db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ 2006-11-24 Brian Warner + * buildbot/scripts/runner.py (Options.subCommands): rename + 'buildbot sighup DIR' to 'buildbot reconfig DIR', but keep + 'sighup' as an alias. + * buildbot/scripts/reconfig.py (Reconfigurator): enhance the + reconfig command to follow twistd.log and print all of the lines + from the start of the config-file reload to its completion. This + should make it a lot easier to discover bugs in the config file. + Use --quiet to disable this behavior. This addresses half of + SF#1517975, the other half will be to add this same utility to + 'buildbot start' and 'buildbot restart'. + * docs/buildbot.texinfo (Loading the Config File): same + (Shutdown): same + * buildbot/interfaces.py (IBuilderControl.forceBuild): remove this method, it has been deprecated for a long time. Use IBuilderControl.requestBuild instead. diff --git a/buildbot/master.py b/buildbot/master.py index f0caa5d..2459543 100644 --- a/buildbot/master.py +++ b/buildbot/master.py @@ -625,6 +625,8 @@ class BuildMaster(service.MultiService, styles.Versioned): except: log.msg("error during loadConfig") log.err() + log.msg("The new config file is unusable, so I'll ignore it.") + log.msg("I will keep using the previous config file instead.") f.close() def loadConfig(self, f): diff --git a/buildbot/scripts/reconfig.py b/buildbot/scripts/reconfig.py new file mode 100644 index 0000000..a1a57be --- /dev/null +++ b/buildbot/scripts/reconfig.py @@ -0,0 +1,93 @@ + +import os, signal +from twisted.internet import reactor, task +from twisted.protocols.basic import LineOnlyReceiver + +class FakeTransport: + disconnecting = False + +class LogWatcher(LineOnlyReceiver): + POLL_INTERVAL = 0.1 + delimiter = "\n" + + def __init__(self, finished): + self.poller = task.LoopingCall(self.poll) + self.in_reconfig = False + self.finished_cb = finished + self.transport = FakeTransport() + + + def start(self, logfile): + try: + self.f = open(logfile, "rb") + self.f.seek(0, 2) + self.poller.start(self.POLL_INTERVAL) + except IOError: + print "Unable to follow %s" % logfile + return False + return True + + def finished(self, success): + self.in_reconfig = False + self.finished_cb(success) + + def lineReceived(self, line): + if "loading configuration from" in line: + self.in_reconfig = True + if self.in_reconfig: + print line + if "I will keep using the previous config file" in line: + self.finished(False) + if "configuration update complete" in line: + self.finished(True) + + def poll(self): + while True: + data = self.f.read(1000) + if not data: + return + self.dataReceived(data) + +class Reconfigurator: + def run(self, config): + + basedir = config['basedir'] + quiet = config['quiet'] + os.chdir(basedir) + f = open("twistd.pid", "rt") + pid = int(f.read().strip()) + if quiet: + os.kill(pid, signal.SIGHUP) + return + # keep reading twistd.log. Display all messages between "loading + # configuration from ..." and "configuration update complete" or + # "I will keep using the previous config file instead.", or until + # 5 seconds have elapsed. + reactor.callLater(5, self.timeout) + self.lw = lw = LogWatcher(self.finished) + if lw.start("twistd.log"): + # we're watching + # give the LogWatcher a chance to start reading + print "sending SIGHUP to process %d" % pid + reactor.callLater(0.2, os.kill, pid, signal.SIGHUP) + reactor.run() + else: + # we couldn't watch the file.. just SIGHUP it + os.kill(pid, signal.SIGHUP) + print "sent SIGHUP to process %d" % pid + + def finished(self, success): + if success: + print "Reconfiguration is complete." + else: + print "Reconfiguration failed." + reactor.stop() + + def timeout(self): + print "Never saw reconfiguration finish." + reactor.stop() + +def reconfig(config): + r = Reconfigurator() + r.run(config) + diff --git a/buildbot/scripts/runner.py b/buildbot/scripts/runner.py index 2afbf85..5bcbfea 100644 --- a/buildbot/scripts/runner.py +++ b/buildbot/scripts/runner.py @@ -427,6 +427,15 @@ class StopOptions(MakerBase): def getSynopsis(self): return "Usage: buildbot stop " +class ReconfigOptions(MakerBase): + optFlags = [ + ['quiet', 'q', "Don't display log messages about reconfiguration"], + ] + def getSynopsis(self): + return "Usage: buildbot reconfig " + + + class RestartOptions(MakerBase): def getSynopsis(self): return "Usage: buildbot restart " @@ -669,7 +678,9 @@ class Options(usage.Options): ['restart', None, RestartOptions, "Restart a buildmaster or buildslave"], - ['sighup', None, StopOptions, + ['reconfig', None, ReconfigOptions, + "SIGHUP a buildmaster to make it re-read the config file"], + ['sighup', None, ReconfigOptions, "SIGHUP a buildmaster to make it re-read the config file"], ['sendchange', None, SendChangeOptions, @@ -731,7 +742,8 @@ def run(): elif command == "restart": restart(so) elif command == "sighup": - stop(so, "HUP") + from buildbot.scripts.reconfig import Reconfigurator + Reconfigurator().run(so) elif command == "sendchange": sendchange(so, True) elif command == "debugclient": diff --git a/docs/buildbot.texinfo b/docs/buildbot.texinfo index 7d6d427..90294c6 100644 --- a/docs/buildbot.texinfo +++ b/docs/buildbot.texinfo @@ -1040,7 +1040,7 @@ The buildmaster will respond to a @code{SIGHUP} by re-reading its config file. The following shortcut is available: @example -buildbot sighup @var{BASEDIR} +buildbot reconfig @var{BASEDIR} @end example When you update the Buildbot code to a new release, you will need to @@ -1894,9 +1894,13 @@ system hosting the buildmaster, you can send a @code{SIGHUP} signal to it: the @command{buildbot} tool has a shortcut for this: @example -buildbot sighup @var{BASEDIR} +buildbot reconfig @var{BASEDIR} @end example +This command will show you all of the lines from @file{twistd.log} +that relate to the reconfiguration. If there are any problems during +the config-file reload, they will be displayed in these lines. + The debug tool (@code{buildbot debugclient --master HOST:PORT}) has a ``Reload .cfg'' button which will also trigger a reload. In the future, there will be other ways to accomplish this step (probably a -- 2.11.4.GIT