0
0
Fork 0
mirror of https://github.com/alerta/alerta.git synced 2025-01-26 02:08:31 +00:00
alerta_alerta/alerta/ircbot/daemon.py
2013-03-08 23:49:50 +00:00

147 lines
4.9 KiB
Python

#!/usr/bin/env python
########################################
#
# alert-ircbot.py - Alert IRC client
#
########################################
import sys
import socket
import select
import json
import urllib2
from alerta.common import config
from alerta.common import log as logging
from alerta.common.daemon import Daemon
from alerta.alert import Alert, Heartbeat, status
from alerta.common.mq import Messaging, MessageHandler
from alerta.common.tokens import LeakyBucket
Version = '2.0.0'
LOG = logging.getLogger(__name__)
CONF = config.CONF
# TODO(nsatterl): this should be in the Alert class
def ack_alert(alertid):
url = "http://%s:%s/%s/alerts/alert/%s" % (CONF.api_host, CONF.api_port, CONF.api_endpoint, alertid)
params = json.dumps({'status': 'ACK'})
LOG.info('ACK request %s', url)
try:
output = urllib2.urlopen(url, params).read()
response = json.loads(output)['response']
except urllib2.URLError, e:
LOG.error('Could not post request and/or parse response from %s - %s', url, e)
return
if response['status'] == 'error':
LOG.error('Message not ACKed - %s', response['message'])
return
LOG.info('Successfully ACKed alert %s', alertid)
return
class IrcbotMessage(MessageHandler):
def __init__(self, irc, tokens):
#super(MessageHandler, self).__init__()
self.irc = irc
self.tokens = tokens
def on_message(self, headers, body):
if not self.tokens.get_token():
LOG.warning('%s : No tokens left, rate limiting this alert', headers['correlation-id'])
return
LOG.debug("Received: %s", body)
if headers['type'].endswith('Alert'):
ircAlert = Alert.parse_alert(body)
if ircAlert:
LOG.info('%s : Send IRC message to %s', ircAlert.get_id(), CONF.irc_channel)
try:
msg = 'PRIVMSG %s :%s [%s] %s' % (CONF.irc_channel, ircAlert.get_id(short=True),
ircAlert.alert.get('status', status.UNKNOWN), ircAlert.summary)
self.irc.send(msg + '\r\n')
except Exception, e:
LOG.error('%s : IRC send failed - %s', ircAlert.get_id(), e)
class IrcbotDaemon(Daemon):
def run(self):
self.running = True
# An IRC client may send 1 message every 2 seconds
# See section 5.8 in http://datatracker.ietf.org/doc/rfc2813/
tokens = LeakyBucket(tokens=20, rate=2)
tokens.start()
# Connect to IRC server
try:
irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
irc.connect((CONF.irc_host, CONF.irc_port))
irc.send('NICK %s\r\n' % CONF.irc_user)
irc.send('USER %s 8 * : %s\r\n' % (CONF.irc_user, CONF.irc_user))
LOG.debug('USER -> %s', irc.recv(4096))
irc.send('JOIN %s\r\n' % CONF.irc_channel)
LOG.debug('JOIN -> %s', irc.recv(4096))
except Exception, e:
LOG.error('IRC connection error: %s', e)
sys.exit(1)
LOG.info('Joined IRC channel %s on %s as USER %s', CONF.irc_channel, CONF.irc_host, CONF.irc_user)
# Connect to message queue
self.mq = Messaging()
self.mq.connect(callback=IrcbotMessage(irc, tokens))
self.mq.subscribe(destination=CONF.outbound_queue)
while not self.shuttingdown:
try:
LOG.debug('Waiting for IRC messages...')
ip, op, rdy = select.select([irc], [], [], CONF.loop_every)
if ip:
for i in ip:
if i == irc:
data = irc.recv(4096)
if len(data) > 0:
if 'ERROR' in data:
LOG.error('IRC server: %s', data)
else:
LOG.debug('IRC server: %s', data)
if 'PING' in data:
LOG.info('IRC PING received -> PONG ' + data.split()[1])
irc.send('PONG ' + data.split()[1] + '\r\n')
if 'ACK' in data:
LOG.info('Request to ACK %s by %s', data.split()[4], data.split()[0])
ack_alert(data.split()[4])
if data.find('!alerta quit') != -1:
irc.send('QUIT\r\n')
else:
LOG.debug('Send heartbeat...')
heartbeat = Heartbeat(version=Version)
self.mq.send(heartbeat)
except (KeyboardInterrupt, SystemExit):
self.shuttingdown = True
LOG.info('Shutdown request received...')
self.running = False
tokens.shutdown()
LOG.info('Disconnecting from message broker...')
self.mq.disconnect()