mirror of
https://github.com/alerta/alerta.git
synced 2025-01-30 03:33:59 +00:00
154 lines
5.1 KiB
Python
154 lines
5.1 KiB
Python
|
|
import sys
|
|
import socket
|
|
import select
|
|
import time
|
|
|
|
from alerta.common import config
|
|
from alerta.common import log as logging
|
|
from alerta.common.daemon import Daemon
|
|
from alerta.common.alert import Alert
|
|
from alerta.common.heartbeat import Heartbeat
|
|
from alerta.common.mq import Messaging, MessageHandler
|
|
from alerta.common.tokens import LeakyBucket
|
|
from alerta.common.api import ApiClient
|
|
|
|
Version = '2.2.0'
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
CONF = config.CONF
|
|
|
|
|
|
class IrcbotMessage(MessageHandler):
|
|
|
|
def __init__(self, mq, irc, tokens):
|
|
|
|
self.mq = mq
|
|
self.irc = irc
|
|
self.tokens = tokens
|
|
|
|
MessageHandler.__init__(self)
|
|
|
|
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)
|
|
try:
|
|
ircAlert = Alert.parse_alert(body)
|
|
except ValueError:
|
|
return
|
|
|
|
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.status, ircAlert.summary)
|
|
self.irc.send(msg + '\r\n')
|
|
except Exception, e:
|
|
LOG.error('%s : IRC send failed - %s', ircAlert.get_id(), e)
|
|
|
|
def on_disconnected(self):
|
|
|
|
self.mq.reconnect()
|
|
|
|
|
|
class IrcbotDaemon(Daemon):
|
|
|
|
ircbot_opts = {
|
|
'irc_host': 'localhost',
|
|
'irc_port': 6667,
|
|
'irc_channel': '#alerts',
|
|
'irc_user': 'alerta',
|
|
}
|
|
|
|
def __init__(self, prog, **kwargs):
|
|
|
|
config.register_opts(IrcbotDaemon.ircbot_opts)
|
|
|
|
Daemon.__init__(self, prog, kwargs)
|
|
|
|
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()
|
|
|
|
api = ApiClient()
|
|
|
|
# Connect to IRC server
|
|
try:
|
|
irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
irc.connect((CONF.irc_host, CONF.irc_port))
|
|
time.sleep(1)
|
|
irc.send('NICK %s\r\n' % CONF.irc_user)
|
|
time.sleep(1)
|
|
irc.send('USER %s 8 * : %s\r\n' % (CONF.irc_user, CONF.irc_user))
|
|
LOG.debug('USER -> %s', irc.recv(4096))
|
|
time.sleep(1)
|
|
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(self.mq, irc, tokens))
|
|
self.mq.subscribe(destination=CONF.outbound_topic)
|
|
|
|
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).rstrip('\r\n')
|
|
if len(data) > 0:
|
|
if 'ERROR' in data:
|
|
LOG.error('%s. Exiting...', data)
|
|
sys.exit(1)
|
|
else:
|
|
LOG.debug('%s', data)
|
|
else:
|
|
LOG.warning('IRC server sent no data')
|
|
if 'PING' in data:
|
|
LOG.info('IRC PING received -> PONG ' + data.split()[1])
|
|
irc.send('PONG ' + data.split()[1] + '\r\n')
|
|
elif 'ack' in data.lower():
|
|
LOG.info('Request to ACK %s by %s', data.split()[4], data.split()[0])
|
|
api.ack(data.split()[4])
|
|
elif 'delete' in data.lower():
|
|
LOG.info('Request to DELETE %s by %s', data.split()[4], data.split()[0])
|
|
api.delete(data.split()[4])
|
|
elif data.find('!alerta quit') != -1:
|
|
irc.send('QUIT\r\n')
|
|
else:
|
|
LOG.debug('IRC: %s', data)
|
|
else:
|
|
i.recv()
|
|
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()
|
|
|
|
|
|
|