]> git.pld-linux.org Git - packages/nagios-alert-jabber.git/blob - nagios-jabber.alert
Ver 1.3; convert to python3 and pyxmpp2 (more polishing would be nice)
[packages/nagios-alert-jabber.git] / nagios-jabber.alert
1 #!/usr/bin/python3 -u
2 # usage:
3 #   jabber.alert [-x] [-c config] [-a account_id][,otheraccount_id] [-t timeout ] [-J from_jid -P password] to_jid1 to_jid2 to_jid3
4
5 import os
6 import hashlib
7 import re
8 import sys
9 import getopt
10 import logging
11 import signal
12 import socket
13 import string
14 import time
15 import libxml2
16
17 from pyxmpp2.jid import JID
18 from pyxmpp2.message import Message
19 from pyxmpp2.client import Client
20 from pyxmpp2.settings import XMPPSettings
21 from pyxmpp2.interfaces import EventHandler, event_handler, QUIT
22 from pyxmpp2.streamevents import AuthorizedEvent, DisconnectedEvent
23
24 try:
25     opts, args = getopt.getopt(sys.argv[1:], "J:P:a:b:c:ds:t:x")
26 except getopt.GetoptError as e:
27     print("%s: %s " % (sys.argv[0], e), file=sys.stderr)
28     sys.exit(1)
29
30 jids = []
31 html = False
32 debug = False
33 timeout = 20
34 cfg = "/etc/nagios/jabber-notify.ini"
35 tjid = None
36 body = ""
37 subject = "Nagios alert"
38 for o, a in opts:
39     if o == '-b':
40         body += a
41     if o == '-c':
42         cfg = a
43     if o == '-d':
44         debug = True
45     if o == '-t':
46         timeout = float(a)
47     if o == '-x':
48         html = True
49     if o == '-J':
50         tjid = a
51     if o == '-P':
52         jids.append({ 'jid': tjid, 'password': a })
53     if o == '-s':
54         subject = a
55     if o == '-a':
56         import configparser
57
58         config = configparser.ConfigParser()
59         config.read(cfg)
60
61         for section in a.split(','):
62             jids.append({ 'jid': config.get(section, 'jid'), 'password': config.get(section, 'password')})
63
64 socket.setdefaulttimeout(timeout)
65
66 recpt = args
67
68 for section in jids:
69     if not section['jid'] or not section['password']:
70         print("%s: jid (-J) and password (-P) are required for `%s'" % (sys.argv[0], section), file=sys.stderr)
71         sys.exit(1)
72
73 if not jids:
74     print("%s: no configured jid accounts found" % sys.argv[0], file=sys.stderr)
75     sys.exit(1)
76
77 if not recpt:
78     print("%s: recipient jids are required" % sys.argv[0], file=sys.stderr)
79     sys.exit(1)
80
81 if debug:
82     logger=logging.getLogger()
83     logger.addHandler(logging.StreamHandler())
84     logger.setLevel(logging.DEBUG)
85
86 if not body:
87     stdin_body = ""
88     for line in sys.stdin.readlines():
89         stdin_body += line
90
91     body += stdin_body
92
93 if len(body.strip()) == 0:
94     body = "(nagios-jabber.alert warning: missing message body)";
95
96 class NagiosHandler(EventHandler):
97     """Echo Bot implementation."""
98     def __init__(self):
99         signal.signal(signal.SIGINT, self.exit_gracefully)
100         signal.signal(signal.SIGTERM, self.exit_gracefully)
101
102     def run(self):
103         """Request client connection and start the main loop."""
104         self.client.connect()
105         self.client.run()
106
107     def exit_gracefully(self, signum, frame):
108         logging.info(u"Received signal {0}".format(signum))
109         self.client.main_loop.quit()
110
111     def disconnect(self):
112         """Request disconnection and let the main loop run for a 2 more
113         seconds for graceful disconnection."""
114         self.client.disconnect()
115         self.client.run(timeout = 2)
116
117     @event_handler(AuthorizedEvent)
118     def handle_authorized(self, event):
119         if (html == True):
120             import re
121             message = re.sub('<.*?>', '', body)
122             doc = libxml2.parseDoc('<body>' + body + '</body>')
123             doc_element = doc.getRootElement().children
124         else:
125             message = body
126
127         for r in recpt:
128             jid_r = JID(r)
129             msg = Message(to_jid = jid_r, body = message, subject = subject,
130                             stanza_type = 'chat', thread = "Nagios")
131
132             if (html == True):
133                 node = msg.add_new_content('http://jabber.org/protocol/xhtml-im', 'html')
134                 xbody = node.newChild(None, "body", None)
135                 html_ns = xbody.newNs('http://www.w3.org/1999/xhtml', None)
136                 xbody.setNs(html_ns)
137                 xbody.addChildList(doc_element.docCopyNodeList(xbody.doc))
138
139             event.stream.send(msg)
140         event.stream.disconnect()
141
142     @event_handler(DisconnectedEvent)
143     def handle_disconnected(self, event):
144         """Quit the main loop upon disconnection."""
145         return QUIT
146
147     @event_handler()
148     def handle_all(self, event):
149         """Log all events."""
150         logging.info(u"-- {0}".format(event))
151
152 err = []
153 for section in jids:
154     for attempt in ('first', 'second'):
155         jid = JID(section['jid'])
156         resource = "Nagios/" + hashlib.md5(''.join(recpt).encode('utf-8')).hexdigest()[:10]
157         if attempt == 'second':
158             # if something went wrong the second time around, it's
159             # most likely a resource name conflict on login, so let's
160             # wait a bit, randomize the resource name and try again
161             resource = resource + '/' + repr(os.getpid())
162             time.sleep(0.8)
163         if not jid.resource:
164             jid = JID(jid.local, jid.domain, resource)
165
166         settings = XMPPSettings({
167                             u"password": section['password'],
168                             u"software_name": "Nagios notify jabber",
169                             u"starttls": True,
170                             u"tls_verify_peer": True,
171                             u"tls_cacert_file": "/etc/pki/tls/certs/ca-bundle.crt"
172                             })
173
174         handler = NagiosHandler()
175         try:
176             c = Client(jid, [handler], settings)
177             try:
178                 c.connect()
179                 c.run()
180             except KeyboardInterrupt:
181                 c.disconnect()
182                 logging.info(u"Disconnected due to KeyboardInterrupt")
183                 sys.exit(0)
184             except Exception as e:
185                 err.append("ERROR1: %s: %s" % (jid, e))
186                 # don't try another attempt, jump straigt to
187                 # another section
188                 break
189             else:
190                 c.disconnect()
191                 logging.info(u"Disconnected")
192                 # stop after first successful attempt at sending the msg
193                 sys.exit(0)
194         except Exception as e:
195             err.append("ERROR2: %s: %s" % (jid, e))
196
197 print("\n".join(err), file=sys.stderr)
198 sys.exit(1)
This page took 0.059133 seconds and 4 git commands to generate.