Commit | Line | Data |
---|---|---|
c187e616 P |
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 : | |
c5171941 | 14 | # - JID du destinataire |
c187e616 P |
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 { | |
c4f3f6b1 | 38 | # command_name notify-service-by-jabber |
c187e616 P |
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 { | |
c187e616 P |
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() | |
c4f3f6b1 P |
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 | |
c187e616 P |
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("'", "'").replace("<", "<") | |
116 | ||
117 | #print("data={}".format(data)) | |
118 | ||
119 | # construction des textes | |
c4f3f6b1 P |
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 | |
c187e616 P |
140 | |
141 | # construction du message | |
c187e616 | 142 | message = xmpp.protocol.Message(to=dest, body=text, typ="chat") |
c4f3f6b1 P |
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) | |
c187e616 P |
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) |