Make bot.py behave like a daemon

This includes a number of changes to prevent printing to stdout and
enable using daemonContext so that we can run bot.py as a daemon.
This commit is contained in:
Matthew Treinish 2013-09-18 17:45:12 -04:00
parent b0b024e080
commit 545012839a
4 changed files with 35 additions and 21 deletions

30
bot.py
View File

@ -25,7 +25,6 @@ openstack-qa:
import ConfigParser
import daemon
import lockfile
import irc.bot
import os
import sys
@ -37,6 +36,14 @@ import logging
from elasticRecheck import Stream
from elasticRecheck import Classifier
try:
import daemon.pidlockfile
pid_file_module = daemon.pidlockfile
except Exception:
# as of python-daemon 1.6 it doesn't bundle pidlockfile anymore
# instead it depends on lockfile-0.9.1
import daemon.pidfile
pid_file_module = daemon.pidfile
class RecheckWatchBot(irc.bot.SingleServerIRCBot):
@ -47,7 +54,7 @@ class RecheckWatchBot(irc.bot.SingleServerIRCBot):
self.channel_list = channels
self.nickname = nickname
self.password = password
self.log = logging.getLogger('gerritbot')
self.log = logging.getLogger('recheckwatchbot')
def on_nicknameinuse(self, c, e):
self.log.info('Nick previously in use, recovering.')
@ -73,13 +80,15 @@ class RecheckWatchBot(irc.bot.SingleServerIRCBot):
self.connection.privmsg(channel, msg)
time.sleep(0.5)
class RecheckWatch(threading.Thread):
def __init__(self, ircbot, channel_config, username):
def __init__(self, ircbot, channel_config, username, queries):
threading.Thread.__init__(self)
self.ircbot = ircbot
self.channel_config = channel_config
self.log = logging.getLogger('recheckwatchbot')
self.username = username
self.queries = queries
self.connected = False
def new_error(self, channel, data):
@ -108,7 +117,7 @@ class RecheckWatch(threading.Thread):
self.new_error(channel, data)
def run(self):
classifier = Classifier()
classifier = Classifier(self.queries)
stream = Stream(self.username)
while True:
event = stream.get_failed_tempest()
@ -120,7 +129,6 @@ class RecheckWatch(threading.Thread):
else:
event['bug_number'] = bug_number
self._read(event)
class ChannelConfig(object):
@ -160,7 +168,9 @@ def _main():
config.get('ircbot', 'server'),
config.getint('ircbot', 'port'),
config.get('ircbot', 'server_password'))
recheck = RecheckWatch(bot, channel_config, config.get('gerrit', 'user'))
recheck = RecheckWatch(bot, channel_config,
config.get('gerrit', 'user'),
config.get('gerrit', 'query_file'))
recheck.start()
bot.start()
@ -171,10 +181,10 @@ def main():
print "Usage: %s CONFIGFILE" % sys.argv[0]
sys.exit(1)
pid = lockfile.FileLock(
"/var/run/recheckwatchbot/recheckwatchbot.pid", 10)
# with daemon.DaemonContext(pidfile=pid):
_main()
pid = pid_file_module.TimeoutPIDLockFile(
"/tmp/recheckwatchbot.pid", 10)
with daemon.DaemonContext(pidfile=pid):
_main()
def setup_logging(config):

View File

@ -3,7 +3,8 @@ nick=RecheckWatchBot
pass=
server=irc.freenode.net
port=6667
channel_config=recheckwatchbot.yaml
channel_config=/home/mtreinish/elasticRecheck/recheckwatchbot.yaml
[gerrit]
user=jogo
user=treinish
query_file=/home/mtreinish/elasticRecheck/queries.json

View File

@ -104,9 +104,10 @@ class Classifier():
queries = None
def __init__(self):
def __init__(self, queries):
self.es = ElasticSearch(self.ES_URL)
self.queries = json.loads(open('queries.json').read())
self.queries = json.loads(open(queries).read())
self.log = logging.getLogger("recheckwatchbot")
def _apply_template(self, template, values):
query = copy.deepcopy(template)
@ -121,7 +122,7 @@ class Classifier():
def last_failures(self):
for x in self.queries:
print "Looking for bug: https://bugs.launchpad.net/bugs/%s" % x['bug']
self.log.debug("Looking for bug: https://bugs.launchpad.net/bugs/%s" % x['bug'])
query = self._apply_template(self.general_template, x['query'])
results = self.es.search(query, size='10')
self._parse_results(results)
@ -131,10 +132,10 @@ class Classifier():
try:
change = x["_source"]['@fields']['build_change']
patchset = x["_source"]['@fields']['build_patchset']
print "build_name %s" % x["_source"]['@fields']['build_name']
print "https://review.openstack.org/#/c/%(change)s/%(patchset)s" % locals()
self.log.debug("build_name %s" % x["_source"]['@fields']['build_name'])
self.log.debug("https://review.openstack.org/#/c/%(change)s/%(patchset)s" % locals())
except KeyError:
print "build_name %s" % x["_source"]['@fields']['build_name']
self.log.debug("build_name %s" % x["_source"]['@fields']['build_name'])
def classify(self, change_number, patch_number, comment):
"""Returns either None or a bug number"""
@ -143,7 +144,7 @@ class Classifier():
#Wait till Elastic search is ready
self._wait_till_ready(change_number, patch_number, comment)
for x in self.queries:
print "Looking for bug: https://bugs.launchpad.net/bugs/%s" % x['bug']
self.log.debug("Looking for bug: https://bugs.launchpad.net/bugs/%s" % x['bug'])
query = self._apply_template(self.targeted_template, (x['query'],
change_number, patch_number))
results = self.es.search(query, size='10')
@ -201,7 +202,7 @@ class Classifier():
def main():
classifier = Classifier()
#classifier.test()
config = ConfigParser.ConfigParser()
if len(sys.argv) is 2:
@ -210,6 +211,8 @@ def main():
config_path = 'elasticRecheck.conf'
config.read(config_path)
user = config.get('gerrit', 'user', 'jogo')
queries = config.get('gerrit', 'query_file', 'queries.json')
classifier = Classifier(queries)
stream = Stream(user)
while True:
event = stream.get_failed_tempest()

View File

@ -1,4 +1,4 @@
openstack-recheck-watch-test:
openstack-qa:
events:
- positive
- negative