]>
Commit | Line | Data |
---|---|---|
02673eb0 ER |
1 | #!/usr/bin/python -u |
2 | # arekm@pld-linux.org, 2006-01 | |
3 | # glen@pld-linux.org, 2006-03-14 | |
ad7ac473 | 4 | # glen@pld-linux.org,arekm@pld-linux.org, 2006-10-30 - added ssl support (for gmail.com) |
8a0d8b38 | 5 | # glen@pld-linux.org 2006-11-03 - made it work with jabber.pld-linux.org again |
20bb0aca | 6 | # glen@pld-linux.org,arekm@pld-linux.org, 2006-11-13 - added config file support |
ebbef88a | 7 | # glen@pld-linux.org, 2006-12-07 - added html messages support (-x), thx goes to to jajcus |
071905aa | 8 | # luzik@pld-linux.org, 2007-03 - added digest auth method(jabber.gda.pl) |
b6621e54 | 9 | # arekm@pld-linux.org, 2009-07 - added fallback accounts support |
02673eb0 | 10 | # usage: |
b262787e | 11 | # jabber.alert [-x] [-c config] [-a account_id][,otheraccount_id] [-t timeout ] [-J from_jid -P password] to_jid1 to_jid2 to_jid3 |
02673eb0 ER |
12 | |
13 | import os | |
257cdecd | 14 | import hashlib |
02673eb0 ER |
15 | import re |
16 | import sys | |
17 | import getopt | |
eca05a2f | 18 | import logging |
c49eec10 | 19 | import socket |
02673eb0 ER |
20 | import string |
21 | import time | |
ebbef88a | 22 | import libxml2 |
02673eb0 ER |
23 | |
24 | from pyxmpp.jid import JID | |
25 | from pyxmpp.message import Message | |
26 | from pyxmpp.jabber.client import JabberClient | |
ad7ac473 | 27 | from pyxmpp.streamtls import TLSSettings |
02673eb0 ER |
28 | |
29 | try: | |
b262787e | 30 | opts, args = getopt.getopt(sys.argv[1:], "J:P:a:c:dt:x") |
02673eb0 | 31 | except getopt.GetoptError, e: |
b6621e54 | 32 | print >> sys.stderr, "%s: %s " % (sys.argv[0], e) |
02673eb0 ER |
33 | sys.exit(1) |
34 | ||
b6621e54 | 35 | jids = [] |
ebbef88a | 36 | html = False |
f985e683 | 37 | debug = False |
5cf88261 | 38 | timeout = 20 |
b262787e | 39 | cfg = "/etc/nagios/jabber-notify.ini" |
b6621e54 | 40 | tjid = None |
02673eb0 | 41 | for o, a in opts: |
458fe103 AM |
42 | if o == '-c': |
43 | cfg = a | |
f985e683 AM |
44 | if o == '-d': |
45 | debug = True | |
5cf88261 AM |
46 | if o == '-t': |
47 | timeout = float(a) | |
ebbef88a ER |
48 | if o == '-x': |
49 | html = True | |
02673eb0 | 50 | if o == '-J': |
b6621e54 | 51 | tjid = a |
02673eb0 | 52 | if o == '-P': |
b6621e54 | 53 | jids.append({ 'jid': tjid, 'password': a }) |
20bb0aca ER |
54 | if o == '-a': |
55 | import ConfigParser | |
56 | ||
57 | config = ConfigParser.ConfigParser() | |
b262787e | 58 | config.read(cfg) |
20bb0aca | 59 | |
b6621e54 AM |
60 | for section in a.split(','): |
61 | jids.append({ 'jid': config.get(section, 'jid'), 'password': config.get(section, 'password')}) | |
02673eb0 | 62 | |
5cf88261 AM |
63 | socket.setdefaulttimeout(timeout) |
64 | ||
02673eb0 ER |
65 | recpt = args |
66 | ||
b6621e54 AM |
67 | for section in jids: |
68 | if not section['jid'] or not section['password']: | |
69 | print >> sys.stderr, "%s: jid (-J) and password (-P) are required for `%s'" % (sys.argv[0], section) | |
70 | sys.exit(1) | |
71 | ||
72 | if not jids: | |
73 | print >> sys.stderr, "%s: no configured jid accounts found" % sys.argv[0] | |
02673eb0 ER |
74 | sys.exit(1) |
75 | ||
b6621e54 AM |
76 | if not recpt: |
77 | print >> sys.stderr, "%s: recipient jids are required" % sys.argv[0] | |
02673eb0 ER |
78 | sys.exit(1) |
79 | ||
f985e683 AM |
80 | if debug: |
81 | logger=logging.getLogger() | |
82 | logger.addHandler(logging.StreamHandler()) | |
83 | logger.setLevel(logging.DEBUG) | |
02673eb0 ER |
84 | |
85 | subject = "Nagios alert" | |
02673eb0 ER |
86 | |
87 | body = "" | |
88 | stdin_body = "" | |
89 | do_print = True | |
90 | for line in sys.stdin.readlines(): | |
91 | stdin_body += line | |
92 | ||
93 | body += stdin_body | |
94 | ||
8ccfe18b AM |
95 | if len(body.strip()) == 0: |
96 | body = "(nagios-jabber.alert warning: missing message body)"; | |
97 | ||
02673eb0 ER |
98 | message_type = 'chat' |
99 | ||
257cdecd MM |
100 | class XMPPStreamError(Exception): |
101 | def __init__(self, msg): | |
102 | self.msg = msg | |
103 | def __str__(self): | |
104 | return self.msg | |
105 | ||
02673eb0 ER |
106 | class Client(JabberClient): |
107 | def session_started(self): | |
ebbef88a ER |
108 | if (html == True): |
109 | import re | |
110 | message = re.sub('<.*?>', '', body) | |
b538c51f ER |
111 | doc = libxml2.parseDoc('<body>' + body + '</body>') |
112 | doc_element = doc.getRootElement().children | |
ebbef88a ER |
113 | else: |
114 | message = body | |
115 | ||
02673eb0 ER |
116 | for r in recpt: |
117 | jid_r = JID(r) | |
ae844770 AM |
118 | msg = Message(to_jid = jid_r, body = message, subject = subject, |
119 | stanza_type = message_type, thread = "Nagios") | |
ebbef88a ER |
120 | |
121 | if (html == True): | |
122 | node = msg.add_new_content('http://jabber.org/protocol/xhtml-im', 'html') | |
123 | xbody = node.newChild(None, "body", None) | |
124 | html_ns = xbody.newNs('http://www.w3.org/1999/xhtml', None) | |
125 | xbody.setNs(html_ns) | |
b538c51f | 126 | xbody.addChildList(doc_element.docCopyNodeList(xbody.doc)) |
ebbef88a | 127 | |
02673eb0 ER |
128 | self.stream.send(msg) |
129 | self.disconnect() | |
ad7ac473 | 130 | |
eca05a2f AM |
131 | def stream_state_changed(self,state,arg): |
132 | if debug: | |
133 | print "*** State changed: %s %r ***" % (state,arg) | |
134 | ||
257cdecd MM |
135 | def stream_error(self,err): |
136 | raise XMPPStreamError(err.get_message()) | |
137 | ||
138 | ||
b6621e54 AM |
139 | err = [] |
140 | for section in jids: | |
257cdecd MM |
141 | for attempt in ('first', 'second'): |
142 | jid = JID(section['jid']) | |
143 | resource = "Nagios/" + hashlib.md5(''.join(recpt)).hexdigest()[:10] | |
144 | if attempt == 'second': | |
145 | # if something went wrong the second time around, it's | |
146 | # most likely a resource name conflict on login, so let's | |
147 | # wait a bit, randomize the resource name and try again | |
148 | resource = resource + '/' + repr(os.getpid()) | |
149 | time.sleep(0.8) | |
150 | if not jid.resource: | |
151 | jid = JID(jid.node, jid.domain, resource) | |
152 | ||
153 | c = Client(jid, section['password'], auth_methods = ['sasl:DIGEST-MD5', 'sasl:PLAIN', 'digest'], | |
154 | tls_settings = TLSSettings(require = False, verify_peer = False)) | |
b6621e54 | 155 | try: |
257cdecd MM |
156 | c.connect() |
157 | try: | |
158 | c.loop(1) | |
159 | except XMPPStreamError, e: | |
160 | # Most likely a duplicate stream problem | |
161 | # don't log anything, just try again | |
162 | c.disconnect() | |
163 | continue | |
164 | except Exception, e: | |
165 | err.append("ERROR1: %s: %s" % (section['jid'], e)) | |
166 | c.disconnect() | |
167 | # don't try another attempt, jump straigt to | |
168 | # another section | |
169 | break | |
b6621e54 | 170 | c.disconnect() |
257cdecd MM |
171 | # stop after first successful attempt at sending the msg |
172 | sys.exit(0) | |
173 | except Exception, e: | |
174 | err.append("ERROR2: %s: %s" % (section['jid'], e)) | |
b6621e54 AM |
175 | |
176 | print >> sys.stderr, "\n".join(err) | |
177 | sys.exit(1) |