list2form : gestion des erreurs et des petits fichiers (merci cgi.py…)
[progfou.git] / nagios / nagios2jabber.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*
3 # Copyright: Agence universitaire de la Francophonie -- www.auf.org
4 # Licence: GPL-3
5 # Author: Jean Christophe André
6 # Created: 2015-10-23
7 #
8 # Debian-Depends: python-xmpp
9 #
10 #
11 # Exploite la norme XEP-0071 pour enrichir le message d'alerte envoyé par Nagios.
12 #
13 # Paramètres d'appel du script :
14 # - JID du destinataire
15 #
16 # Informations transmises via l'entrée standard (stdin):
17 # - dans le cas d'une annonce concernant un hôte :
18 # Host: $HOSTALIAS$
19 # State: $HOSTSTATE$
20 # Info: $HOSTOUTPUT$
21 # Date: $LONGDATETIME$
22 # - dans le cas d'une annonce concernant un service :
23 # Service: $SERVICEDESC$
24 # Host: $HOSTNAME$
25 # Address: $HOSTADDRESS$
26 # State: $SERVICESTATE$
27 # Info: $SERVICEOUTPUT$
28 # Date: $LONGDATETIME$
29 #
30 # Mise en place :
31 # - installation de ce script dans /usr/local/lib/nagios2jabber.py
32 # - configuration de l'appel au script dans /etc/nagios3/commands.cfg :
33 # define command {
34 # command_name notify-host-by-jabber
35 # command_line /usr/bin/printf "%b" "Host: $HOSTALIAS$\nState: $HOSTSTATE$\nInfo: $HOSTOUTPUT$\nDate: $LONGDATETIME$" | /usr/local/lib/nagios2jabber.py $CONTACTPAGER$
36 # }
37 # define command {
38 # command_name notify-service-by-jabber
39 # command_line /usr/bin/printf "%b" "Service: $SERVICEDESC$\nHost: $HOSTNAME$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\nInfo: $SERVICEOUTPUT$\nDate: $LONGDATETIME$" | /usr/local/lib/nagios2jabber.py $CONTACTPAGER$
40 # }
41 # - configuration des envois de messages jabber dans /etc/nagios3/conf.d/contacts.cfg
42 # define contact {
43 # ...
44 # host_notification_commands notify-host-by-jabber,notify-host-by-email
45 # service_notification_commands notify-service-by-jabber,notify-service-by-email
46 # ...
47 # }
48
49 from __future__ import print_function
50 import sys # argv, stdin
51 import time # strptime, strftime
52 import xmpp
53
54 _CONFIG = {
55 "jid": "nagios.announce@auf.org",
56 "password": "super-secret",
57 }
58
59 if len(sys.argv) != 2 or sys.argv[1] == "-h" or sys.argv[1] == "--help":
60 print("Usage: echo message | {} user@server".format(sys.argv[0]))
61 sys.exit(1)
62
63 dest = sys.argv[1]
64 text = sys.stdin.read()
65 rich_text = None
66
67 # quelques variables dépendant du client
68 client_is_pidgin = dest not in ("jean-christophe.andre@auf.org", )
69 want_detailed_info = dest in ("moussa.nombre@auf.org", )
70 link_fully_supported = not client_is_pidgin
71
72 # construit un dictionnaire d'informations
73 items = [l.split(":", 1) for l in text.splitlines()]
74 data = {k.strip().lower():v.strip() for k,v in items}
75 #print("data={}".format(data))
76
77 # remanie la date (si possible)
78 if "date" in data:
79 try:
80 dt = time.strptime(data["date"], "%a %b %d %H:%M:%S %Z %Y")
81 data["date"] = time.strftime("%Y-%m-%d %H:%M:%S", dt)
82 except:
83 pass
84
85 # fonction qui renvoie la couleur prévue pour un statut donné
86 def state_color(state):
87 color = "blue"
88 if state == "OK" or state == "UP":
89 color = "green"
90 elif state == "WARNING" or state == "UNKNOWN":
91 color = "orange"
92 elif state == "CRITICAL" or state == "DOWN":
93 color = "red"
94 return color
95
96 # fonction qui renvoie un texte enrichi pour le statut
97 def state_enriched(state):
98 return "<strong>[<span style='color: {0};'>{1}</span>]</strong>"\
99 .format(state_color(state), state)
100
101 # ajout du statut enrichi
102 if "state" in data:
103 data["rich_state"] = state_enriched(data["state"])
104
105 # remaniement des infos (suppression des redondances, gestion des lignes)
106 if "info" in data:
107 if "service" in data and data["info"].startswith(data["service"]):
108 data["info"] = data["info"][len(data["service"]):].strip(" :-")
109 if "state" in data and data["info"].startswith(data["state"]):
110 data["info"] = data["info"][len(data["state"]):].strip(" :-")
111 data["info"] = data["info"].replace("\\n", "\n").strip("\n")
112 # prepare enriched info
113 data["rich_info"] = data["info"].replace("\n", "<br/>")
114 data["rich_info"] = data["rich_info"].replace("WARNING", state_enriched("WARNING"))
115 data["escaped_info"] = data["info"].replace("'", "&#39;").replace("<", "&lt;")
116
117 #print("data={}".format(data))
118
119 # construction des textes
120 try:
121 rich_text_list = [ "<span style='color: black;'><span>{date}</span> " ]
122 if link_fully_supported:
123 rich_text_list.append("<a href='void();' title='{escaped_info}'>{rich_state}</a>")
124 else:
125 rich_text_list.append("{rich_state}")
126 if "service" in data:
127 text = "{date}\t[{state}]\t{service} @{host}[{address}]\n{info}".format(**data)
128 rich_text_list.append(" <span style='color: blue;'>{service}</span> ")
129 rich_text_list.append("@<span style='color: blue;'>{host}</span>")
130 rich_text_list.append("[<span style='color: blue;'>{address}</span>]")
131 else:
132 text = "{date}\t[{state}]\t{host}\n{info}".format(**data)
133 rich_text_list.append(" <span style='color: blue;'>{host}</span>")
134 rich_text_list.append("</span>")
135 rich_text = ("".join(rich_text_list)).format(**data)
136 if want_detailed_info or not link_fully_supported:
137 rich_text = "<p>{}<br/><em>{rich_info}</em></p>".format(rich_text)
138 except KeyError:
139 pass
140
141 # construction du message
142 message = xmpp.protocol.Message(to=dest, body=text, typ="chat")
143 if rich_text is not None:
144 html = xmpp.Node("html", {"xmlns": "http://jabber.org/protocol/xhtml-im"})
145 html.addChild(node=xmpp.simplexml.XML2Node(
146 "<body xmlns='http://www.w3.org/1999/xhtml'>{}</body>".format(rich_text)))
147 message.addChild(node=html)
148
149 # envoi du message
150 jid = xmpp.protocol.JID(_CONFIG["jid"])
151 client = xmpp.Client(jid.getDomain(), debug=[])
152 client.connect()
153 client.auth(jid.getNode(), _CONFIG["password"], "server")
154 client.send(message)