Checkmk Plugin Notify Pushbullet
Ich habe mir mal wieder Checkmk installiert. Für mich persönlich ist es mit Abstand das beste Monitoring System, welches ich jemals testen durfte und konnte. Darunter waren unter anderem Nagios und PRTG. Ich bin bei weitem kein Experte aber habe doch schon einiges an Erfahrung mit entsprechenden Tools. Der Fairness halber sollte ich aber erwähnen, dass ich auch beruflich mit Checkmk arbeite und daher hier wohl die meisten Erfahrungen sammeln durfte. So etwas schweißt ja bekanntlich zusammen :-). Wie dem auch sei, habe ich privat ein Problem bezüglich der Notifications. Und eigentlich untypisch für mich, habe ich es jedes mal wenn ich Checkmk neu aufsetze. Damit mir dies nicht nochmal passiert, machen wir es diesmal richtig. Aber Moment mal, worum geht es denn nun eigentlich?
Auf Arbeit nutzen wir einen Mailserver um uns über Ereignisse, aus dem Monitoringtool heraus, informieren zu lassen. Privat habe ich aber keine Lust mich um einen Mailserver zu kümmern, weshalb ich gerne auf Push Messenger ausweiche. Und genauer gesagt nutze ich hier pushbullet von Google. Jetzt werden einige Fragezeichen über dem Kopf haben und andere sofort sagen, da nutzt doch keiner und somit ist das sinnlos. Aber ehrlich gesagt finde ich das nicht schlimm. Ich nutze die App nur zur Kommunikation mit den Familienmitgliedern und natürlich kann mein Haus darüber mit mir sprechen. Aber sicherlich gäbe es auch andere Alternativen.
Eine große Stärke von Checkmk ist eigentlich die Unmenge an von Haus aus mitgebrachten Plugins. Sollte dort mal nicht das dabei sein was man sucht, dann gibt es noch eine Plugin Börse, wo externe Entwickler ihre selbst geschriebenen Plugins anderen zur Verfügung stellen können. Und wenn alle Stricke reißen, könnt ihr diese auch selber schreiben. Ich versuche in Zukunft ein paar Beispiele für so etwas zu bringen, an denen man sich orientieren kann.
In meinem Beispiel gibt es sogar ein geschriebenes Plugin von einem Entwickler Namens Whitestrake. Das Problem hieran ist aber, dass es für eine ältere Version von Check_MK geschrieben wurde. Da es beim Release auf die Version 2.0 größere Änderungen gab, funktioniert das Plugin leider nicht mehr. Ziel des Artikel ist es dieses für unsere Zwecke umzuschreiben.
Fangen wir an…..
Als erstes laden wir uns das „alte Plugin“ von der Checkmk Exchange herunter. Wichtig zu erwähnen wäre noch, ich beziehe mich hier auf die Checkmk Enterprise Edition. Diese kann man seit einiger Zeit, in beschränktem Rahmen, auch privat und gratis nutzen. Falls ihr die Raw Version nutzt ändert sich nur die Integration des Plugin in Checkmk. Eine Anleitung der Schritte auf der Kommandozeile, geht auch mit der Enterprise Edition, findet ihr in der Online Dokumentation unter dem Punkt 4. Hier benötigt ihr aber das Plugin auf unserem System auf welchem unser Checkmk läuft. Dies geht z.B. mit WinSCP. Es gibt aber auch noch andere Möglichkeiten. Ich will hierauf nicht zu genau eingehen. Wer hier mehr Infos benötigt kann sich diese gerne bei meinem Artikel, VM’S und Container umziehen, besorgen.
Wenn ihr wie ich die Enterprise Edition einsetzt geht es auch über die Web Oberfläche. Dazu rufen wir unter dem Menüpunkt Settings, genauer gesagt unter Maintenance, den Punkt Extension packages auf.
Mit einem Klick auf Upload package könnt ihr jetzt das heruntergeladene Plugin hochladen und installieren. Soweit so gut. Wir erwarten ja, dass etwas nicht geht. Aber wo genau der Fehler ist, müssen wir erst noch herausfinden. Weiterhin bin ich persönlich kein Freund davon, zwingend einen Channel zu nutzen. Dies ist aber vom Ersteller so konfiguriert. Auch darum kümmern wir uns dann gleich. Aber wie finden wir jetzt den Fehler? Am einfachsten geht dies, wenn wir das Plugin einmal ausführen und schauen was genau Checkmk zu bemängeln hat. Dazu legen wir uns eine neue Notification Rule an. Also unter Setup → Events → Notifications, oben rechts, auf den Button „Add Rule“ klicken und dann einfach eine Beschreibung eintragen. Weiterhin müssen wir als Notification Method „Notify via Pushbullet“ auswählen. Für den Test vergeben wir dazu noch einen zufälligen Token und einen Channel Tag. Wir wollen ja nur sehen ob es geht. Um zu speichern müssen wir noch mindestens einen Service oder etwas ähnliches auswählen. Ich habe mich für den Service „Postfix status“ entschieden.
Bevor wir wirklich einen Test durchführen können, müssen wir unserem User, mit welchem wir uns eingeloggt haben, noch eine Contact Group zuordnen. Dazu wählen wir unter Setup → User das Stift Symbol an unserem User aus (Standard ist cmkadmin). In dem sich öffnenden Menü, können wir jetzt unter Contact Group einfach „Everything“ auswählen. Natürlich müssenw ir diese Änderungen auch noch anwenden.
So aber jetzt. Wir suchen uns über unsere Hosts einen entsprechenden Service und wählen oben den Button „Show checkboxes“. Jetzt klicken wir die Checkbox vor dem Service unserer Wahl an und gehen oben auf „Commands“. Dort gibt es den Punkt „Fake check results“. Wenn wir den anklicken, können wir den Service auf den Status Critical springen lassen. Sobald wir das machen, sollten wir unter unserer Overview jetzt einen roten Banner sehen, welcher uns auf fehlgeschlagene Notifications hinweist.
Bitte wundert euch nicht. Ich habe es etwas häufiger probiert. Bei euch werden es wohl keine 12 Stück sein. Wenn wir jetzt auf diesen Banner klicken, gelangen wir zu der von uns gesuchten Erläuterung, was genau schief läuft. Das schauen wir uns doch mal genauer an.
Traceback (most recent call last):
-- File "/omd/sites/test/local/share/check_mk/notifications/pushbullet.py", line 44, in <module> -- urllib2.urlopen(req)
-- File "/usr/lib/python2.7/urllib2.py", line 154, in urlopen -- return opener.open(url, data, timeout)
-- File "/usr/lib/python2.7/urllib2.py", line 429, in open -- response = self._open(req, data)
-- File "/usr/lib/python2.7/urllib2.py", line 447, in _open -- '_open', req)
-- File "/usr/lib/python2.7/urllib2.py", line 407, in _call_chain -- result = func(*args)
-- File "/usr/lib/python2.7/urllib2.py", line 1241, in https_open -- context=self._context)
-- File "/usr/lib/python2.7/urllib2.py", line 1198, in do_open -- raise URLError(err) -- urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:727)>
Wenn wir uns das etwas genau anschauen fällt auf, dass hier ein Modul aufgerufen werden soll (urllib2), welches noch unter Python 2.7 läuft. Checkmk ist komplett auf Python 3 gewechselt. Somit haben wir doch direkt mal den ersten Fehler gefunden. Wenn wir uns die Dokumentation von pushbullet anschauen, gibt es dort total viele Beispiele und Erklärungen. In der Doku wird aber immer mit „curl“ gearbeitet. Zum einen weil es für fast alle Plattformen verfügbar ist und auch in den meisten Programmiersprachen einfach umzusetzen. Daher habe ich mich auch dafür entschieden. So müssen wir uns nicht erst noch mit der Syntax und der Unterstützung für „urllib“ herumschlagen.
Ein funktionierender Push auf alle unsere Devices, wenn kein spezielles Device angegeben wird erfolgt ein Broadcast, sieht folgendermaßen aus. Natürlich müsst ihr euren eigenen Access Token verwenden.
curl -u o.XXXNEA1xxxx82vyxxxYExxxoN2dsxT: -X POST https://api.pushbullet.com/v2/pushes --header 'Content-Type: application/json' --data-binary '{"type": "note", "title": "Test Titel", "body": "Test Body"}'
Jetzt gibt es einige Seiten im Netz, die uns die Übersetzung von einem normalen „curl“ String entsprechend in Python abnehmen. Ich habe auf die schnelle – https://curlconverter.com/ gefunden. Sicherlich gibt es hier aber auch andere. Dort wird aus obigem dann das folgende.
headers = {
'Content-Type': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
}
data = {
"type": "note",
"title": „Test Titel“,
"body": „Test Body“,
}
response = requests.post('https://api.pushbullet.com/v2/pushes', headers=headers, data=data, auth=(o.XXXNEA1xxxx82vyxxxYExxxoN2dsxT, ''))
Ok also schmeißen wir alles raus, was mit „urllib“ zu tun hat und bauen uns die Sektionen „Set up request“ und „Send to Pushbullet API“ neu. Daher öffnen wir uns die Datei unter ~/local/share/check_mk/notifications/pushbullet.py. Wir fangen direkt am Anfang der Datei an. Als erstes ändern wir die erste Zeile und sagen somit, dass hier Python3 zu nutzen ist.
#!/usr/bin/env python3
Danach passen wir die zu importierenden Module an. Anstatt von „urllib2“ benötigen wir jetzt „requests“.
import os, sys, requests, json
Jetzt schmeißen wir alles im Abschnitt „Set up request“ raus und fügen unsere Übersetzung von vorhin ein. Hier halten wir uns jetzt aber an die Namensgebung der Variablen im Script. Bitte beachtet, dass ich hier schon bewusst den Channel weglasse, da ich diesen nicht nutzen möchte. Solltet ihr dies anders handhaben wollen, könnt ihr diesen einfach im data Bereich mit aufnehmen. Final sollte es so aussehen.
headers = {
'Content-Type': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
}
data = {
"type": "note",
"title": push_title,
"body": push_body
}
Und als letzte Aktion, bereinigen wir den Abschnitt „Send to Pushbullet API“ und fügen dort unseren Post Aufruf ein. Auch hier passen wir uns den Namen im Script an um auf die Variablen zugreifen zu können.
response = requests.post('https://api.pushbullet.com/v2/pushes', headers=headers, data=data, auth=(push_token, ''))
So dann lasst uns doch mal testen ob und wie es jetzt läuft. Als erstes klicken wir auf den Mülleimer bei unserem Notification Fehler Banner und löschen alle anstehenden Alarme. Wir wollen ja sehen, wie es jetzt aussieht. Dann schnappen wir uns wieder einen Service wie vorhin und setzen diesen auf „Critical“.
Und schon erhalte ich eine Notification über Pushbullet mit dem Hinweis, dass ein Service ein Problem hat. Kurz darauf kommt auch die Clear Meldung. Es geht also! Jetzt sieht es aber noch etwas unschön aus, dass ich einen Channel Namen angeben muss. Ich kann diesen auch nicht einfach leer lassen, da dies im Script geprüft wird. Am schönsten fände ich es, wenn wir diesen weder im Formular haben noch im Script beachtet wird. Also schauen wir uns das noch schnell an.
Wir öffnen dazu die Datei ~/local/share/check_mk/web/plugins/wato/pushbullet.py und löschen den Dictionary Eintrag für den Channel. Übrig bleiben sollte dann nur noch folgendes.
#!/usr/bin/python
register_notification_parameters("pushbullet.py",
Dictionary(
optional_keys = [],
elements = [
( "push_token",
TextAscii(
title = _("Pushbullet Token"),
help = _("Your Pushbullet API token, available from https://www.pushbullet.com/#settings/account")
),
),
])
)
In der Notification Rule muss dann nochmal der Punkt „Call with following parameters“ ausgewählt werden. Jetzt seht ihr dort nur noch das Token Feld.
Jetzt nehmen wir uns noch das Notification Script vor. Wir öffnen dieses und suchen uns den Punkt „push_channel=os.getenv(‚NOTIFY_PARAMETER_PUSH_CHANNEL‘)“. Diesen löschen wir raus oder kommentieren diesen mit einer Raute aus. Im Abschnitt „Make sure token / channel aren’t empty“ schreiben wir die if Schleife um. Hier sollte dann nur noch folgendes stehen.
if (not push_token):
sys.exit("didn't receive the expected token")