Hyperic HQ bietet durch seinen modularen Aufbau mehrere Moeglichkeiten, um die Funktionalitaet der Software zu erweitern. Zur Erweiterung stehen z.B. HQU-Plugins, Product Plugins oder die HQ API zur Verfuegung. In diesem Posting moechte ich aufzeigen, wie einfach es ist ein Product Plugin fuer Hyperic HQ zu entwickeln.
Product Plugin bedeutet ein zugeschnittenes Plugin zur Ueberwachung eines Dienstes oder einer bestimmten Software.
Beispielhaft soll der in Python geschriebene Applicationserver Zope ueberwacht werden.
Folgende Parameter sollen beachtet werden:
- Ueberwachung von Zope spezifischen Metriken
- Ausfuehren von Control Actions
- Autodiscovery
- moeglichst kein JAVA programmieren
Zunaechst moechte ich die oben aufgefuehrten Punkte und Begriffe erlaeutern. Im Administrationsmenu des Zope Servers, dem Control Panel, lassen sich verschiedene Statusinformationen abrufen und einige weitere Metriken lassen sich durch die Zope API abfragen. Die Firma gocept aus Halle hat sich darueber schon Gedanken gemacht und ein entsprechendes Plugin fuer Open Source Monitoringsoftware Nagios entwickelt. Dieses Zope-Product ZNagios dient als Grundlage um die Metriken aus Zope auszulesen.
Unter Control Actions versteht man bei Hyperic HQ das Ausfuehren von beliebigen serverspezifischen Kommandos. Im Hyperic-Universum versteht man unter einem Server eine auf einer Plattform installierte Software. Als Beispiele fuer solche Kommandos kann man z.B. das Reorganisieren einer Datenbank, das Erstellen eines Snapshots einer VMWare Virtual Machine oder den Neustart eines Daemons nennen. Am Beispiel von Zope sollen folgende Control Actions ausgefuehrt werden: Stoppen, Starten, Restarten und den Abfragen des Serverstatus des Zope-Servers.
Die Autodiscovery-Funktion ist eine der grossen Staerken von Hyperic HQ, wie auch bereits in einem frueheren Posting beschrieben. Nach Moeglichkeit sollen nach der Installation eines HQ Agent auf einer Plattform soviele Server und Services wie moeglich automatisch erkannt, zum Inventory des Servers hinzugefuegt und ueberwacht werden.
Der oder die installierten Zope-Server muessen auf dem System entdeckt und identifiziert werden. Da es bei Zope-Umgebungen nicht unueblich ist, mehrere Zope-Server auf einer Plattform laufen zu lassen muss hier leider noch haendisch Konfigurationsparameter geaendert werden. Die Autodiscovery-Funktion von Hyperic HQ gibt zur jetzigen Zeit (Version 4.0) leider nicht her, mehrere Server eines Typs auf einer Plattform automatisch zu “entdecken”.
Nach Moeglichkeit sollen alle oben aufgefuehrten realisiert werden, ohne Java Code zu schreiben und ein handliches JAR-Paket zu schnueren. Stattdessen soll eine einzige XML-Datei ausreichen.
Bei der Plugin-Entwicklung mit Hyperic HQ gibt es zwei grosse Fehler, die man unbedingt vermeiden sollte. Ein Fehler besteht darin, sein unfertiges Plugin im Server einzuspielen zu testen. Das Deployment des Plugins in der (womoeglich) Hyperic HQ Produktitvumgebung sollte zu den letzten Schritten gehoeren. Fuer die Entwicklung und alle Tests reicht ein Hyperic HQ Agent voellig aus !
Der zweite Fehler ist eher eine architekturbedingte Schwachstelle in Hyperic HQ. Wird ein neuer Service in Hyperic HQ Server angelegt, sei es durch manuelles Hinzufuegen oder durch die Autodiscovery Funktion, erfolgt das auf Basis des zum Zeitpunkt des Imports vorhandenen Plugins und dessen Metriken und Funktionen. Sollte man sich zu einem spaeteren Zeitpunkt entscheiden Aenderungen an dem Plugin durchzufuehren, z.B. neue Metriken hinzufuegen, so haben diese Aenderungen nur Einfluesse auf Server, die neu in Hyperic HQ angelegt werden.
Da die bereits angelegten Server auf Basis der alten Pluginversion erstellt wurden, werden die Aenderungen nicht wirksam. Die einzige Moeglichkeit besteht darin, die Server aus dem HQ Inventory zu loeschen und neu anzulegen bzw. den naechsten Autodiscovery Durchlauf abzuwarten. Leider gehen alle bisher erfassten Daten und erstellten Alarme und Verknuepfungen verloren. Daher sollte man bei der Pluginentwicklung darauf achten, moeglichst alle Metriken und Funktionen zu implementieren.
Hier noch ein paar generelle Empfehlungen zur Pluginentwicklung:
Wenn man im Lesen von JAVA Sourcecode geuebt ist, empfiehlt es sich den Sourcecode von Hyperic HQ bereitzuhaben. Man kann einfach einen SVN-Abzug herunterladen. Aus meiner Sicht ist die Dokumentation auf den Webseiten von Hyperic und im Wiki recht umfangreich, jedoch ist es manchmal absolut noetig Konfigurationsparameter im Quelltext nachzulesen. Ausserdem hat man dadurch alle bei Hyperic HQ enthaltenen Plugins im Quelltext vorliegen.
Hyperic bietet mehrere vordefinierte Plugins, vielleicht am besten als Plugin Support Classes zu bezeichnen. Es empfiehlt sich sein eigenes Plugin um diese Helper Klassen zu bauen. Dank dieser Helper Klassen braucht man auch nicht unbedingt Java zu programmieren
Ich habe damit begonnen Funktionen und Parameter der Plugin Support Classes zu dokumentieren.
Die Monitoringsoftware Nagios bietet eine Vielzahl an Plugins fuer diverse Software. Um das Rad nicht zu erfinden, nimmt man ein bestehendes Nagios Plugin als Grundlage. Anlaufstelle fuer Nagios Plugins ist nagiosexchange.org
Die ZNagios Erweiterung fuer Zope liefert unter einer mit HTTP Authentication geschuetzten URL die erfassten Metriken zurueck. Um die Metriken mit Hyperic HQ zu verarbeiten muessen sie zunaechst ausgelesen und in die Notation key=value umgewandelt werden. Dazu wird das Hyperic Script-Plugin verwendet. Mit Hilfe dieses Plugins koennen beliebige Programme/Scripte ausgefuehrt werden. Um die Werte auszulesen kann man z.B. ein Script um die Programme curl oder wget schreien oder sich an dem Plugin fuer nginx orientieren und ein in Python geschriebenes Script verwenden.
Die ZNagios Erweiterung liefert die Daten in folgendem Format zurueck:
uptime: 835.0 db-objects: 2719.0 db-stores: 0.0 db-cache-total-size: 52.0 db-cache-conn0-total-objects: 280.0 db-loads: 0.0 db-cache-conn0-active-objects: 52.0 db-bytes: 1370966.0 errors-total: 0.0 db-connections: 0.0 db-cache-target-size: 5000.0 refcount-total: 17193.0
Die Daten muessen also folgendermassen umformatiert werden:
uptime=835.0
Wir gehen mal davon aus das wir uns unter Unix/Linux befinden und das durch einen einfachen sed Kommando erreicht werden. Mit dem Skript ist ein wesentlicher Teil des Zope-Plugins fertiggestellt. Es handelt sich um ein einfaches Shell Skript an das vier Argumente uebergeben werden muessen.
#!/bin/sh if [ $# -ne 4 ] then exit 0 else ZOPE_URL='http://'$1':'$2'/Control_Panel/munin' if [ -x /usr/bin/curl ] then /usr/bin/curl -u $3:$4 $ZOPE_URL 2>/dev/null | /bin/sed s/": "/=/ exit 0 else [ -x /usr/bin/wget ] /usr/bin/wget --user=$3 --password=$4 -qO- $ZOPE_URL | /bin/sed s/": "/=/ exit 0 fi exit 0 fi exit 0
Die Skript Argumente der Reihenfolge nach: Hostname oder IP-Adresse des Zope-Servers, Port, Nutzername und Passwort.
Der Plugin XML Descriptor sieht zum derzeitigen Stand folgendermasssen aus:
<?xml version="1.0"?> <!DOCTYPE plugin [ <!ENTITY process-metrics SYSTEM "/pdk/plugins/process-metrics.xml"> ]> <plugin> <server name="Zope" version="2.x"> <config> <option name="process.query" description="Process Query" default="State.Name.ct=python,Args.1.ct=Zope2/Startup/run.py"/> <option name="hostname" description="Zope IP-address or hostname" default="localhost"/> <option name="port" description="Zope HTTP port" default="8080" /> <option name="username" description="Zope username" default="zopeadm" /> <option name="credentials" description="Zope password" type="secret" default="changeme" /> </config> <property name="PROC_QUERY" value="State.Name.ct=python,Args.1.ct=Zope2/Startup/run.py"/> <plugin type="autoinventory" class="org.hyperic.hq.product.DaemonDetector"/> <plugin type="measurement" class="org.hyperic.hq.product.MeasurementPlugin"/> <metric name="Availability" alias="Availability" template="sigar:Type=ProcState,Arg=%process.query%:State" category="AVAILABILITY" indicator="true" units="percentage" collectionType="dynamic"/> &process-metrics; <filter name="template" value="exec:args=%hostname% %port% %username% %credentials%,file=pdk/work/scripts/zope/zope-stat:${alias}"/> <metric name="uptime" units="sec" indicator="false"/> <metric name="db-objects" indicator="true"/> </plugin>
Im zweiten Teil nehmen wir den Plugin Descriptor auseinander. Fortsetzung folgt.