| 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-jc |
| 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 | # contact_name jc |
| 44 | # ... |
| 45 | # host_notification_commands notify-host-by-jabber,notify-host-by-email |
| 46 | # service_notification_commands notify-service-by-jabber,notify-service-by-email |
| 47 | # ... |
| 48 | # } |
| 49 | |
| 50 | from __future__ import print_function |
| 51 | import sys # argv, stdin |
| 52 | import time # strptime, strftime |
| 53 | import xmpp |
| 54 | |
| 55 | _CONFIG = { |
| 56 | "jid": "nagios.announce@auf.org", |
| 57 | "password": "super-secret", |
| 58 | } |
| 59 | |
| 60 | if len(sys.argv) != 2 or sys.argv[1] == "-h" or sys.argv[1] == "--help": |
| 61 | print("Usage: echo message | {} user@server".format(sys.argv[0])) |
| 62 | sys.exit(1) |
| 63 | |
| 64 | dest = sys.argv[1] |
| 65 | text = sys.stdin.read() |
| 66 | |
| 67 | # construit un dictionnaire d'informations |
| 68 | items = [l.split(":", 1) for l in text.splitlines()] |
| 69 | data = {k.strip().lower():v.strip() for k,v in items} |
| 70 | #print("data={}".format(data)) |
| 71 | |
| 72 | # remanie la date (si possible) |
| 73 | if "date" in data: |
| 74 | try: |
| 75 | dt = time.strptime(data["date"], "%a %b %d %H:%M:%S %Z %Y") |
| 76 | data["date"] = time.strftime("%Y-%m-%d %H:%M:%S", dt) |
| 77 | except: |
| 78 | pass |
| 79 | |
| 80 | # fonction qui renvoie la couleur prévue pour un statut donné |
| 81 | def state_color(state): |
| 82 | color = "blue" |
| 83 | if state == "OK" or state == "UP": |
| 84 | color = "green" |
| 85 | elif state == "WARNING" or state == "UNKNOWN": |
| 86 | color = "orange" |
| 87 | elif state == "CRITICAL" or state == "DOWN": |
| 88 | color = "red" |
| 89 | return color |
| 90 | |
| 91 | # fonction qui renvoie un texte enrichi pour le statut |
| 92 | def state_enriched(state): |
| 93 | return "<strong>[<span style='color: {0};'>{1}</span>]</strong>"\ |
| 94 | .format(state_color(state), state) |
| 95 | |
| 96 | # ajout du statut enrichi |
| 97 | if "state" in data: |
| 98 | data["rich_state"] = state_enriched(data["state"]) |
| 99 | |
| 100 | # remaniement des infos (suppression des redondances, gestion des lignes) |
| 101 | if "info" in data: |
| 102 | if "service" in data and data["info"].startswith(data["service"]): |
| 103 | data["info"] = data["info"][len(data["service"]):].strip(" :-") |
| 104 | if "state" in data and data["info"].startswith(data["state"]): |
| 105 | data["info"] = data["info"][len(data["state"]):].strip(" :-") |
| 106 | data["info"] = data["info"].replace("\\n", "\n").strip("\n") |
| 107 | # prepare enriched info |
| 108 | data["rich_info"] = data["info"].replace("\n", "<br/>") |
| 109 | data["rich_info"] = data["rich_info"].replace("WARNING", state_enriched("WARNING")) |
| 110 | data["escaped_info"] = data["info"].replace("'", "'").replace("<", "<") |
| 111 | |
| 112 | #print("data={}".format(data)) |
| 113 | |
| 114 | # construction des textes |
| 115 | if "service" in data: |
| 116 | text = "{date}\t{state}\t{service} @{host}[{address}]\n{info}".format(**data) |
| 117 | enriched_text = "<span style='color: black;'><span>{date}</span> "\ |
| 118 | "<a href='void();' title='{escaped_info}'>{rich_state}</a> "\ |
| 119 | "<span style='color: blue;'>{service}</span> "\ |
| 120 | "@<span style='color: blue;'>{host}</span>"\ |
| 121 | "[<span style='color: blue;'>{address}</span>]"\ |
| 122 | "</span>".format(**data) |
| 123 | #"<br/><em>{rich_info}</em></span>".format(**data) |
| 124 | else: |
| 125 | text = "{date}\t{state}\t{host}\n{info}".format(**data) |
| 126 | enriched_text = "<span style='color: black;'><span>{date}</span> "\ |
| 127 | "<a href='void();' title='{escaped_info}'>{rich_state}</a> "\ |
| 128 | "<span style='color: blue;'>{host}</span>"\ |
| 129 | "</span>".format(**data) |
| 130 | #"<br/><em>{rich_info}</em></span>".format(**data) |
| 131 | |
| 132 | # construction du message |
| 133 | html = xmpp.Node("html", {"xmlns": "http://jabber.org/protocol/xhtml-im"}) |
| 134 | html.addChild(node=xmpp.simplexml.XML2Node( |
| 135 | "<body xmlns='http://www.w3.org/1999/xhtml'>{}</body>".format(enriched_text))) |
| 136 | message = xmpp.protocol.Message(to=dest, body=text, typ="chat") |
| 137 | message.addChild(node=html) |
| 138 | |
| 139 | # envoi du message |
| 140 | jid = xmpp.protocol.JID(_CONFIG["jid"]) |
| 141 | client = xmpp.Client(jid.getDomain(), debug=[]) |
| 142 | client.connect() |
| 143 | client.auth(jid.getNode(), _CONFIG["password"], "server") |
| 144 | client.send(message) |