Icinga Reporting Bug – Servicegroup-Reports können nicht ausgewählt werden

Bildschirmfoto-3

Wessen Icinga-Web bei der Auswahl der Servicegroup-Reports so ausschaut und wer folgende Zeilen dazu im Logifle hat

[Fri Feb 1 10:50:50 2013] [fatal] Uncaught AppKitPHPError: PHP Error array_key_exists() expects parameter 2 to be array, null given (/usr/local/icinga-web/app/modules/Reporting/models/JasperParameterStructModel.class.php:136) (/usr/local/icinga-web/app/modules/AppKit/lib/logging/AppKitExceptionHandler.class.php:59) 
[Fri Feb 1 10:50:50 2013] [fatal] Uncaught AppKitPHPError: PHP Error array_key_exists() expects parameter 2 to be array, null given (/usr/local/icinga-web/app/modules/Reporting/models/JasperParameterStructModel.class.php:136) (/usr/local/icinga-web/app/modules/AppKit/lib/logging/AppKitExceptionHandler.class.php:59)

der muss seine Datei

/usr/local/icinga-web/app/modules/Reporting/config/module.xml

patchen.
In Icinga-1.8.1 und in den Versionen davor, so ich es gesehen habe, fehlt der Block

ae:parameter name="p_servicegroup_object_id">
<ae:parameter name="className">Icinga.Reporting.inputControl.ApiSelectionField</ae:parameter>
<ae:parameter name="target">servicegroup</ae:parameter>
<ae:parameter name="columns">
<ae:parameter>SERVICEGROUP_OBJECT_ID</ae:parameter>
<ae:parameter>SERVICEGROUP_NAME</ae:parameter>
</ae:parameter>
<ae:parameter name="valueField">SERVICEGROUP_OBJECT_ID</ae:parameter>
<ae:parameter name="displayField">SERVICEGROUP_NAME</ae:parameter>
</ae:parameter>

Dies führt dazu, dass beim Aufruf des Reports aus Icinga keine Variablen übergeben werden und der oben genannte Fehler im Icinga-Web Log auftaucht.

Der Patch dazu sieht folgendermaßen aus:

--- module.xml    2013-02-01 11:03:02.000000000 +0100
+++ module_neu.xml    2013-02-01 11:04:28.000000000 +0100
@@ -99,6 +99,16 @@
                         <ae:parameter name="displayField">SERVICE_NAME</ae:parameter>
                         <ae:parameter name="tpl"><![CDATA[{HOST_NAME} - {SERVICE_NAME}]]></ae:parameter>
                     </ae:parameter>
+            <ae:parameter name="p_servicegroup_object_id">
+            <ae:parameter name="className">Icinga.Reporting.inputControl.ApiSelectionField</ae:parameter>
+            <ae:parameter name="target">servicegroup</ae:parameter>
+            <ae:parameter name="columns">
+            <ae:parameter>SERVICEGROUP_OBJECT_ID</ae:parameter>
+            <ae:parameter>SERVICEGROUP_ALIAS</ae:parameter>
+            </ae:parameter>
+            <ae:parameter name="valueField">SERVICEGROUP_OBJECT_ID</ae:parameter>
+            <ae:parameter name="displayField">SERVICEGROUP_ALIAS</ae:parameter>
+            </ae:parameter>
                 </setting>

                 <!-- Mapping for datatypes e.g. 4 == Date -->		    

Ein offizieller Fix ist wohl in Icinga 1.8.3 enthalten. Der Bug-Report dazu ist hier zu finden:

https://dev.icinga.org/issues/3503

 

 

Icinga Check-Latency und die Rolle der idotuils, bzw. Datenbank

Wir haben ein Problem. Besser gesagt, wir hatten ein Problem. Seit einiger Zeit stieg die Latency in unserem Icinga-System kontinuierlich an. Zuerst hatten wir das Upgrade auf die Version 1.8.0 ein Stück weit im Verdacht. Mittlerweile hat sich aber herausgestellt, dass die Performance der Datenbank eine unmittelbare Auswirkung auf die Performance des gesamten Icinga-Systems hat.
Um das genauer zu erklären, muss erwähnt werden, dass wir für unsere Produktionsumgebung aus “Sicherheitsgründen” eine MySQL-Multi-Master Replikation einsetzen. Verwaltet wird diese Replikation über den Multi-Master Replication Manager
Dieser sorgt dafür, dass eine Writer-Rolle und 2 Reader-Rollen immer passend über 2 Datenbanken gemappt werden. Zusätzlich wir damit vermieden, dass gleichzeitig in beide Datenbank geschrieben werden kann. Da wir den “Slave” bewusst nur für den Notfall ausgelegt haben, verfügt dieser natürlich nicht mal annähernd über die Ressourcen des eigentlichen Master-Systems:

“Slave”

Smart Array P410i in Slot 0 (Embedded)
 
   array A
 
      physicaldrive 1I:1:1 (port 1I:box 1:bay 1, SAS, 300 GB, OK)
      physicaldrive 2I:1:5 (port 2I:box 1:bay 5, SAS, 300 GB, OK)

“Master”

Smart Array P400 in Slot 1
 
   array A
 
      physicaldrive 1I:1:5 (port 1I:box 1:bay 5, SAS, 146 GB, OK)
      physicaldrive 1I:1:6 (port 1I:box 1:bay 6, SAS, 146 GB, OK)
      physicaldrive 1I:1:7 (port 1I:box 1:bay 7, SAS, 146 GB, OK)
      physicaldrive 1I:1:8 (port 1I:box 1:bay 8, SAS, 146 GB, OK)
      physicaldrive 2I:1:1 (port 2I:box 1:bay 1, SAS, 146 GB, OK)
      physicaldrive 2I:1:2 (port 2I:box 1:bay 2, SAS, 146 GB, OK)
      physicaldrive 2I:1:3 (port 2I:box 1:bay 3, SAS, 146 GB, OK)
      physicaldrive 2I:1:4 (port 2I:box 1:bay 4, SAS, 146 GB, OK)

Was mit der Check-Latency passiert, wenn jetzt unbemerkt ein Switch der Writer-Adresse auf das eigentliche Slave-System passiert, kann man hier erkennen:

Deutlich wird das Dillema, da gleichzeitig mit dem Anstieg der Latency die Inserts in der Datenbank drastisch zurückgehen.

 

 

 

 

 

 

 

Beim Switch auf das leistungsschwächere System (2 Platten im RAID10-Verbund) reduziert sich die Anzahl der maximalen Inserts von ursprünglich konstanten 240 Inserts/Sekunde auf einen Wert zwischen 40 und maximal 120 Inserts/Sekunde.
Dies bedeutet eine Änderungen von den bisherigen ca. 7 Sekunden Check-Latency auf einen Wert um die 300 Sekunden.

Wir haben es jetzt sicherheitshalber einfach mal wieder zurückgestellt, da uns die Check-Latency von knapp 7 Sekunden im Schnitt besser gefällt.

BUG: Icinga Reporting 1.8.0 (./configure: line 1682: AM_INIT_AUTOMAKE: command not found)

https://dev.icinga.org/issues/3313

Beschreibung

Configure of icinga-reports-1.8.0 throws the following error:

root@localhost:/usr/src/icinga-reports-1.8.0# ./configure –with-jasper-server=/opt/jasperreports-server-cp-4.7.0
./configure: line 1682: AM_INIT_AUTOMAKE: command not found
checking build system type… x86_64-unknown-linux-gnu
checking host system type… x86_64-unknown-linux-gnu
checking for jasperserver… configure: creating ./config.status
config.status: creating Makefile

The fix provided in Bug #2623 works here too -> https://git.icinga.org/?p=icinga-reports.git;a=commit;h=c4e2d2b686eada065066b36bf5080640e0f58cbf

root@localhost:/usr/src/icinga-reports-1.8.0# rm configure
root@localhost:/usr/src/icinga-reports-1.8.0# aclocal
root@localhost:/usr/src/icinga-reports-1.8.0# autoconf
root@localhost:/usr/src/icinga-reports-1.8.0# ./configure –with-jasper-server=/opt/jasperreports-server-cp-4.7.0
checking for a BSD-compatible install… /usr/bin/install -c
checking whether build environment is sane… yes
checking for a thread-safe mkdir -p… /bin/mkdir -p
checking for gawk… no
checking for mawk… mawk
checking whether make sets $(MAKE)… yes
checking build system type… x86_64-unknown-linux-gnu
checking host system type… x86_64-unknown-linux-gnu
checking for jasperserver… configure: creating ./config.status
config.status: creating Makefile

Maybee it’s better to provide an install.sh for this which creates the configure script in the local environment.

Icinga-HTML-Mail

Ich habe ja schon in der Vergangenheit über ein kleines Projekt berichtet, mit dem die E-Mails, welche Icinga versendet, etwas aufgehübscht werden. In unserer großen Installation ist mir aufgefallen, dass stellenweise Icinga kleine Aussetzer hat. Bevorzugt kommt dies vor, wenn eine Notification an viele Empfänger versendet werden soll. Da das Perl-Skript einiges tut und Daten sammelt, dauert das leider entsprechend lange. Verzögerungen von 60 – 120 Sekunden bei 5 oder mehr Empfängern sind keine Seltenheit gewesen.
Die Analyse des Problems hat mich dazu bewegt, ein kleines Wrapper-Skript für diesen Fall zu schreiben. Es sei gesagt, dass mit diesem Skript die Notificationfähigkeit des Icinga- oder Nagios-Kerns etwas manipuliert wird. Es kann in diesem Fall aufgrund der möglichen Laufzeit des icinga-mail.pl Skripts vorkommen, dass die eine oder andere Notification erzeugt wird, obwohl das Problem so nicht mehr existent ist.

Die Updates und Files gibt es wie immer unter Google Code zu finden:
https://code.google.com/p/icinga-html-mail-template/

Icinga-Mail-Skript
https://code.google.com/p/icinga-html-mail-template/downloads/detail?name=icinga_mail.pl&can=2&q=

Trigger-Skript
https://code.google.com/p/icinga-html-mail-template/downloads/detail?name=trigger_icinga_html_mail.sh&can=2&q=

Die Einrichtung selbst gestaltet sich ziemlich simpel.
Für das Trigger-Skript wird eine Notification-Methode in den Icinga-Objekten angelegt. Am besten packt man diese in eine entsprechende notifications.cfg:

define command {
        command_name    notify-by-html-email
        command_line    /usr/local/icinga/bin/trigger_icinga_html_mail.sh "$ADMINEMAIL$" "$CONTACTEMAIL$" "$NOTIFICATIONTYPE$" "$ADMINEMAIL$" "$HOSTNAME$" "$HOSTALIAS$" "$HOSTNOTES$" "$HOSTSTATE$" "$HOSTSTATETYPE$"  "$HOSTATTEMPT$" "$MAXHOSTATTEMPTS$" "$HOSTDURATION$" "$HOSTNOTIFICATIONNUMBER$" "$HOSTCHECKCOMMAND$" "$HOSTLATENCY$" "$LASTHOSTCHECK$" "$LASTHOSTSTATECHANGE$" "$LASTHOSTUP$" "$LASTHOSTDOWN$" "$LASTHOSTUNREACHABLE$" "$HOSTOUTPUT$" "$HOSTADDRESS$" "$HOSTNOTESURL$" "$SERVICEDESC$" "$SERVICESTATE$" "$SERVICENOTIFICATIONNUMBER$"  "$SERVICEOUTPUT$" "$LASTSERVICECHECK$" "$LASTSERVICESTATECHANGE$" "$LASTSERVICEOK$" "$LASTSERVICEWARNING$" "$LASTSERVICECRITICAL$" "$LASTSERVICEUNKNOWN$" "$SERVICESTATETYPE$" "$SERVICEATTEMPT$" "$MAXSERVICEATTEMPTS$" "$SERVICEDURATION$" "$SERVICECHECKCOMMAND$" "$SERVICEDISPLAYNAME$" "$SERVICELATENCY$" "$SERVICEPERCENTCHANGE$" "$SERVICEACTIONURL$" "$SERVICENOTESURL$" "$SERVICENOTES$" "$TIMET$" "$PROCESSSTARTTIME$" "$TOTALHOSTSUP$" "$TOTALHOSTSDOWN$" "$TOTALHOSTSUNREACHABLE$" "$TOTALSERVICESOK$" "$TOTALSERVICESWARNING$" "$TOTALSERVICESCRITICAL$" "$TOTALSERVICESUNKNOWN$" "$TOTALHOSTPROBLEMSUNHANDLED$" "$TOTALSERVICEPROBLEMSUNHANDLED$" "$NOTIFICATIONAUTHOR$" "$NOTIFICATIONCOMMENT$" "default"
}

Das Wort “default” kann ausgetauscht werden gegen die entsprechende nagios-bp.conf. Wir haben in unserem Fall für mehrere Projekte mehrere Configs im Einsatz.

Damit das alles nun funktioniert, muss am Kontakt selbst noch der Verweis auf das neue Notification-Command gesetzt werden. Dies funktioniert mit einem

service_notification_commands  notify-by-html-email
host_notification_commands     notify-by-html-email

Ist dies erledigt, muss Icinga noch mit einem Reload über die neue Konfiguration informiert werden. Ab diesem Zeitpunkt sollten dann die ersten Mails im neuen Layout kommen.

Sollte der Mail-Versand nicht funktionieren, so kann in der im Trigger-Skript definierten Log-Datei (z.B. /usr/local/icinga/var/icinga_mail.log) nach dem Fehler gesucht werden.
So fehlen z.B. auf den meisten Systemen die Perl-Pakete Mail/Sender, WWW/Mechanize oder JSON.

...
Can't locate Mail/Sender.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.10.1 /usr/local/share/perl/5.10.1 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl .) at /usr/local/icinga/bin/icinga_mail.pl line 38.
...
Can't locate WWW/Mechanize.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.10.1 /usr/local/share/perl/5.10.1 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl .) at /usr/local/icinga/bin/icinga_mail.pl line 42.
...
Can't locate JSON.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.10.1 /usr/local/share/perl/5.10.1 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl .) at /usr/local/icinga/bin/icinga_mail.pl line 43.
...

Unter Debian / Ubuntu lässt sich das am schnellsten mit

apt-get install libmail-sender-perl libwww-mechanize-perl libjson-perl

nachinstallieren.

Wer die PNP4Nagios-Grafiken in der Mail vermisst, sollte a) URL im Logfile prüfen und b) überlegen ob PNP4Nagios eventuell Passwort geschützt ist. Sollte b) der Fall sein, muss im Skript icinga-mail.pl der wget-Aufruf (Zeile 789) um –http-user und –http-password erweitert werden:

my $base64image = `wget <strong>--http-user=icinga</strong> <strong>--http-password=abc123</strong> --no-proxy ...

 

Icinga-HTML-Mail

Icinga Performance und Memory Usage

Icinga läuft hier jetzt seit ein paar Tagen mit 1584 Hosts und 9597 Services auf einer Instanz. Das ganze funktioniert soweit wunderbar und wie erwartet.
Hier ein paar Details:

Update:

Und hier das ganze nochmal ohne mk_livestatus.

Was das für mk_livestatus in der Installation bedeuten wird, dürfte sich erschließen :-) Vielleicht raucht dann Icinga auch weniger oft mit einem SIGSEV ab …

Falsche Performance-Daten im Plugin check_iftraffic3.pl

Wie gestern schon geschrieben, bin ich über ein Problem mit skalierten Performance-Daten im Plugin gestolpert.
Um nochmal alle zu beruhigen:

Es handelt es sich dabei weder um ein Problem in Icinga, noch um ein Problem von pnp4nagios, sondern einzig und allein um eine nicht vollständig durchdachte Ausgabe im Check-Plugin selbst.
Da die Änderung am pnp4nagios-Template gestern ein ziemlicher Schnellschuß war, welcher nicht durchgängig funktioniert, hier die vollständige, saubere Lösung.

Die Ausgabe der Performancedaten wird ungefähr ab Zeile 422 zusammengebastelt:

$output .=
"|inUsage=$in_usage%;$warn_usage;$crit_usage outUsage=$out_usage%;$warn_usage;$crit_usage"
  . " inBandwidth=" . $in_traffic . $in_prefix . $suffix . " outBandwidth=" . $out_traffic . $out_prefix . $suffix 
  . " inAbsolut=$in_traffic_absolut outAbsolut=$out_traffic_absolut";

Das Problem resultiert nun aus der Art und Weise, wie inBandwith und outBandwitdh gefüllt werden

inBandwidth=” . $in_traffic . $in_prefix . $suffix
$suffix . ” outBandwidth=” . $out_traffic . $out_prefix . $suffix

$in_traffic und $out_traffic alleine würde an dieser Stelle vollkommen ausreichen, da diese bereits als kbyte/s aus den vorhergehenden Funktionen (ca. Zeile 279 und 280) geliefert werden.

$in_bytes  = $response->{ $snmpIfInOctets . "." . $iface_number } / 1024; # in kiloBytes
$out_bytes = $response->{ $snmpIfOutOctets . "." . $iface_number } / 1024; # in kiloBytes

Leider, leider wird jetzt in den folgenden Zeilen munter auf diesen gleichen Variablen rumgerechnet. Das eigentliche Problem wird jetzt allerdings durch folgenden Code-Block verursacht:

my $in_prefix  = "K";
my $out_prefix = "K";
 
if ( $in_traffic > 1024 ) {
	$in_traffic = sprintf( "%.2f", $in_traffic / 1024 );
	$in_prefix = "M";
}
if ( $out_traffic > 1024 ) {
	$out_traffic = sprintf( "%.2f", $out_traffic / 1024 );
	$out_prefix = "M";
}
if ( $in_traffic > 1024 * 1024 ) {
	$in_traffic = sprintf( "%.2f", $in_traffic / 1024 * 1024 );
	$in_prefix = "G";
}
if ( $out_traffic > 1024 * 1024 ) {
	$out_traffic = sprintf( "%.2f",$out_traffic / 1024 * 1024 );
	$out_prefix = "G";
}

Gut gemeint, schlecht gemacht.
Diese Umformatierung sieht zwar im Standardoutput ziemlich cool und lesbar aus, macht aber wie schon beschrieben die Performance-Daten unbrauchbar.

Wie bereits gestern geschrieben …

  • Fixing the check_iftraffic script to NOT scale perfdata is the RIGHT way.
    Fixing the template like this is much more comfortable, because you have to touch only one server :-)
  • … hier ein kleiner Ansatz.
    Im Prinzip benötigt das komplette Plugin ein Refactoring. Leider fehlt mir dazu momentan die Zeit dazu.

    Ab Zeile 371 kommt folgender Code-Block rein:

    371  ### by js 14.03.2012 
    372  ### preserve $in_traffic and $out_traffic in original format to print unscaled perfdate
    373  my $in_traffic_k = $in_traffic;
    374  my $out_traffic_k = $out_traffic;

    Zusätzlich wird der vorherige Block durch

    426  ### by js 14.03.2012
    427  ### old perfdata output removed, because perfdata will be scaled from Kbyte/s to Mbyte/s or Gbyte/s
    428  ### $in_prefix and $out_prefix is fixed and always "K" (suffix determines if it is Bytes/s or Bit/s)
    429  # Changed 20091214 gj - commas should have been semi colons
    430  # $output .=
    431  # "|inUsage=$in_usage%;$warn_usage;$crit_usage outUsage=$out_usage%;$warn_usage;$crit_usage"
    432  # . " inBandwidth=" . $in_traffic . $in_prefix . $suffix . " outBandwidth=" . $out_traffic . $out_prefix . $suffix 
    433  # . " inAbsolut=$in_traffic_absolut outAbsolut=$out_traffic_absolut";
    434  $output .=
    435  	"|inUsage=$in_usage%;$warn_usage;$crit_usage outUsage=$out_usage%;$warn_usage;$crit_usage"
    436	. " inBandwidth=" . $in_traffic_k . "K" . $suffix . " outBandwidth=" . $out_traffic_k . "K" . $suffix 
    437	. " inAbsolut=$in_traffic_absolut outAbsolut=$out_traffic_absolut";

    ersetzt.
    Damit werden zumindest die Performance-Daten in einem unskalierten Format (entweder KBit/s oder KByte/s) ausgegeben.

    Das Skript selbt kann hier herunter geladen werden: check_iftraffic3.pl

    Why scaled #icinga perfdata still sucks …

    Today i run into some problems while graphing perfdata with pnp4nagios. While the discussion on Twitter is limited to 140 signs, I thought here is better way to explain the problem.

    On serveral servers we run the Nagios-/Icinga-Plugin “check_iftraffic” to monitor the network interface traffic. This works as expected. An alarm is generated if the usage is to high and the generated graphs looks very nicley.
    Today I had a deeper look into the graphs to find a problem with bandwith usage. During this I found a problem with the perfdate delivered by this plugin.

    The Perfdata-Output of check_iftraffic is by default

    CRITICAL – Average IN: 367.03KBs (2.87%), Average OUT: 13.53MBs (108.26%)
    Total RX: 4086.52 MBytes, Total TX: 283.60 MBytes|inUsage=2.87%;85;98 outUsage=108.26%;85;98 inBandwidth=367.03KBs outBandwidth=13.53MBs inAbsolut=4285026695 outAbsolut=297373172

    The inBandwidth=367.03KBs outBandwidth=13.53MBs will now cause some fancy effects in pnp4nagios.

    First, it’s neither a pnp4nagios nor an Icinga problem … It’s just bad coding style.

    First, it’s neither a pnp4nagios nor an Icinga problem … It’s just bad coding style.

    So here is the solution:

    The generated XML for pnp4nagios divides the value and the label like this:

    ...
    <name>inBandwidth</name>
    <label>inBandwidth</label>
    <unit>KBs</unit>
    <act>367.03</act>
    ...
    <name>outBandwidth</name>
    <label>outBandwidth</label>
    <unit>MBs</unit>
    <act>13.53</act>
    ...

    While the template does drawing like the following example shows:

    $section = "2";  # usage in bits
    $ds_name[$section] = "Bandwidth";
    $opt[$section]  = "--vertical-label \"bit\"  --title \"Bandwidth on $hostname in KBs\" "; 
    $def[$section]  = "DEF:var1=$RRDFILE[1]:$DS[3]:AVERAGE " ;  # inusage bits
    $def[$section] .= "DEF:var2=$RRDFILE[1]:$DS[4]:AVERAGE " ;  # outusage bits
    $def[$section] .= "CDEF:inusage=var1,-1,* ";
    $def[$section] .= "AREA:inusage#FF00FF " ;
    $def[$section] .= "AREA:outusage#0000A0 " ;
    $def[$section] .= "GPRINT:var1:LAST:\"Bandwidth(in) \\tLast %4.2lf $UNIT[3]\" ";
    $def[$section] .= "GPRINT:var1:MAX:\"Max %4.2lf  $UNIT[3]\" ";
    $def[$section] .= "GPRINT:var1:AVERAGE:\"Average %4.2lf  $UNIT[3] \\n\" ";
    $def[$section] .= "GPRINT:var2:LAST:\"Bandwidth(out) \\tLast %4.2lf $UNIT[4]\"  ";
    $def[$section] .= "GPRINT:var2:MAX:\"Max %4.2lf $UNIT[4] \" ";
    $def[$section] .= "GPRINT:var2:AVERAGE:\"Average %4.2lf $UNIT[4] \\n\"   ";

    This is pretty funny, because 13.53 (MBs) is in pnp4nagios now less than 367.03 (KBs). The printed graph is now MUCH lower than it should be (because 13.53 MBs are approx 13854,72 KBs).

    What’s next?
    Fixing the check_iftraffic script to NOT scale perfdata is the RIGHT way.

    Fixing the check_iftraffic script to NOT scale perfdata is the RIGHT way.

    Fixing the template like this is much more comfortable, because you have to touch only one server :-)


    if ($UNIT[3] == “MBs”) {
    $def[$section] .= “CDEF:inusage=var1,-1,*,1024,* “;
    $def[$section] .= “AREA:inusage#FF00FF ” ;
    } else {
    $def[$section] .= “CDEF:inusage=var1,-1,* “;
    $def[$section] .= “AREA:inusage#FF00FF ” ;
    }
    if ($UNIT[4] == “MBs”) {
    $def[$section] .= “CDEF:outusage=var2,1,*,1024,* “;
    $def[$section] .= “AREA:outusage#0000A0 ” ;
    } else {
    $def[$section] .= “CDEF:outusage=var2,1,* “;
    $def[$section] .= “AREA:outusage#0000A0 ” ;
    }

    Customized Mails in Icinga versenden – Teil 3

    Wie bereits in Teil 2 geschrieben wird Software ja nie richtig fertig :-)
    Da wir in der Firma uns hauptsächlich über Business Prozesse per Mail oder SMS benachrichtigen lassen und der Informationsgehalt dieser Nachrichten immer ziemlich mager war, habe ich jetzt noch eine Anbindung an NagiosBP geschaffen. Bisher mussten wir uns bei einer Benachrichtigung immer einloggen und im Icinga den entsprechenden Business Process genauer analysieren.
    In der neuen Version 0.2.0 des Skripts gibt es jetzt einen eigenen Block, in welchem die einzelnen Services des Business Processes angezeigt werden können.

    Konfiguriert wird das ganze über 3 Parameter

    [--nagiosbp_url http://icinga.localdomain/nagiosbp/cgi-bin/nagios-bp.cgi]
    Hier kommt die URL zum nagios-bp.cgi hin. Diese URL wird dann im Skript entsprechend der anderen Parameter erweitert, so dann anschließend etwas in der Art

    http://icinga.localdomain/nagiosbp/cgi-bin/nagios-bp.cgi?outformat=json&tree=test_bp&conf=MYCONF

    rauskommt.

    Sollte es an irgendeiner Stelle zu Problemen kommen, kann mit einem –debug 1 eine Ausgabe auf der Konsole erzeugt werden.
    Folgendes sollte eigentlich ausreichen. Die anderne Variablen erzeugen zwar Fehler, können aber ignoriert werden (Mail ist dann eben leer):

    ./icinga_mail.pl --debug 1 --smtphost 127.0.0.1 --icinga_url http://icinga.localdomain/icinga/ --pnp4nagios_url http://icinga.localdomain/pnp4nagios/ --nagiosbp_url "http://icinga.localdomain/nagiosbp/cgi-bin/nagios-bp.cgi" --nagiosbp_conf "MYCONF" --originator icinga@localhost --recipient jens@localhost --servicedesc check_bp_test

    [--nagiosbp_conf MYCONF]

    NagiosBP unterstützt ja mittlerweile mehrere Konfigurationen. Wenn keine angegeben wird, sollte automatisch der Standard verwendet werden. (Noch nicht getestet, da wir keine “Standard-Konfiguration im Einsatz haben).

    [--nagiosbp_state OK,WARNING,CRITICAL,UNKNOWN]

    Da die Liste der Services unter Umständen ziemlich lang werden kann, kann hier eingeschränkt werden, welche Status mitgeliefert werden sollen.
    Normalerweise sollte –nagiosbp_state WARNING,CRITICAL,UNKNOWN vollkommen ausreichen. Wer alles möchte, nimmt einfach das obengenannte Beispiel.

    Damit das ganze auch ohne Probleme funktioniert, sind zwei Voraussetzungen zu erfüllen:

    Alle Business-Process-Services müssen mit einem check_bp_ beginnen und mit dem entsprechenden Namen aus der nagios-bp.conf oder einer eigenen *.conf aufhören.

    Für einen Business-Prozess mit der Definition

    test = server1.localdomain;check_ping & server1.localdomain;check_load 
    display 4;test;Test-BP

    Muss folgender Service unter Icinga angelegt werden:

    define service {
             host_name      server1.localdomain
             service_description    check_bp_test
             ...
    }

    Die service_description muss leider so heißen, da zur Ermittlung der JSON-URL der letzte Teil der Servicedescription herangezogen wird.

    # transform icinga_servicedesc in nagiosbp_servicedesc (remove check_bp_ from icinga_servicedesc to match nagiosbp servicedesc in conf)
    $icinga_servicedesc =~ s/check_bp_//;
     
    # build root nagiosbp_url json url
    my $nagiosbp_json_url = $nagiosbp_url . "?outformat=json" . "&tree=$icinga_servicedesc" . "&conf=$nagiosbp_conf";

    Download über code.google.com.
    Issues und Feature-Requests dort einkippen. Über Rückmeldungen, wie sich das Skript in andere Plattformen integrieren lässt, würde ich mich freuen.

    Customized Mails in Icinga versenden – Teil 2

    So,nach einer aufschlußreichen Diskussion zum Thema Umgebungsvariablen in Icinga – Ich hatte mir darüber noch nie wirklich einen Kopf gemacht, da “es” ja funktioniert hat – und der Bitte darum, ein “vollständiges Skript” zu veröffentlichen hier mal der entsprechende Entwurf für einen ansprechenden Ersatz der Standard-Mail-Benachrichtigung.
    Das Grund-Layout stammt größtenteils von einem bestehenden Notification-Template wurde aber von mir nach Perl protiert und entsprechend umgebaut, bzw. angepasst.

    Das Skript generiert eine HTML-Mail mit einem Link zum entsprechenden PNP4Nagios-Graphen.

    Download

    Die Integration in Icinga gestaltet sich ziemlich simpel.
    Das Skript wird z.B. nach /usr/local/icinga/bin kopiert und ausführbar gemacht. Danach sollten die Abhängigkeiten zum Perl-Paket MAIL::Sender aufgelöst werden. Unter Debian geht das am einfachsten mit einem

    apt-get install libmail-sender-perl

    Sollte das Perl-Paket nicht in den Distribution-Quellen enthalten sein, kann man zur Not auch direkt CPAN bemühen

    cpan Mail::Sender install

    Danach fügt man entweder in eine bestehende commands.cfg oder am besten in eine “neue” notifications.cfg (Achtung, muss in der icinga.cfg unter Umständen eingefügt werden) folgenden Block ein

     define command {
     	command_name	notify-by-html-email
     	command_line	/usr/local/icinga/bin/icinga_mail.pl --debug 0 --smtphost 127.0.0.1 --icinga_url http://icinga.localdomain/icinga/ --pnp4nagios_url http://icinga.localdomain/pnp4nagios/ --originator "$ADMINEMAIL$" --recipient "$CONTACTEMAIL$" --notificationtype "$NOTIFICATIONTYPE$" --adminemail "$ADMINEMAIL$" --hostname "$HOSTNAME$" --hostalias "$HOSTALIAS$" --hostnotes "$HOSTNOTES$" --hoststate "$HOSTSTATE$" --hoststatetype "$HOSTSTATETYPE$" --hostattempt "$HOSTATTEMPT$" --maxhostattempt "$MAXHOSTATTEMPTS$" --hostduration "$HOSTDURATION$" --hostnotificationnumber "$HOSTNOTIFICATIONNUMBER$" --hostcheckcommand "$HOSTCHECKCOMMAND$" --hostlatency "$HOSTLATENCY$" --lasthostcheck "$LASTHOSTCHECK$" --lasthoststatechange "$LASTHOSTSTATECHANGE$" --lasthostup "$LASTHOSTUP$" --lasthostdown "$LASTHOSTDOWN$" --lasthostunreachable "$LASTHOSTUNREACHABLE$" --hostoutput "$HOSTOUTPUT$" --hostaddress "$HOSTADDRESS$" --hostnotesurl "$HOSTNOTESURL$" --servicedesc "$SERVICEDESC$" --servicestate "$SERVICESTATE$" --servicenotificationnumber "$SERVICENOTIFICATIONNUMBER$" --serviceoutput "$SERVICEOUTPUT$" --lastservicecheck "$LASTSERVICECHECK$" --lastservicestatechange "$LASTSERVICESTATECHANGE$" --lastserviceok "$LASTSERVICEOK$" --lastservicewarning "$LASTSERVICEWARNING$" --lastservicecritical "$LASTSERVICECRITICAL$" --lastserviceunknown "$LASTSERVICEINKNOWN$" --servicestatetype "$SERVICESTATETYPE$" --serviceattempt "$SERVICEATTEMPT$" --maxserviceattempts "$MAXSERVICEATTEMPTS$" --serviceduration "$SERVICEDURATION$" --servicecheckcommand "$SERVICECHECKCOMMAND$" --servicedisplayname "$SERVICEDISPLAYNAME$" --servicelatency "$SERVICELATENCY$" --servicepercentchange "$SERVICEPERCENTCHANGE$" --timet "$TIMET$" --processstarttime "$PROCESSSTARTTIME$" --totalhostsup "$TOTALHOSTSUP$" --totalhostsdown "$TOTALHOSTSDOWN$" --totalhostsunreachable "$TOTALHOSTSUNREACHABLE$" --totalservicesok "$TOTALSERVICESOK$" --totalserviceswarning "$TOTALSERVICESWARNING$" --totalservicescritical "$TOTALSERVICESCRITICAL$" --totalservicesunknown "$TOTALSERVICESUNKNOWN$" --totalhostproblemsunhandled "$TOTALHOSTPROBLEMSUNHANDLED$" --totalserviceproblemsunhandled "$TOTALSERVICEPROBLEMSUNHANDLED$" --notificationauthor "$NOTIFICATIONAUTHOR$" --notificationcomment "$NOTIFICATIONCOMMENT$"
    }

    Danach bekommt jeder “Contact” noch über host_notification_commands und service_notifications_commands das neue Notification-Template verpasst

    ...
    host_notification_commands notify-by-html-email
    service_notification_commands  notify-by-html-email
    ...

    Nach dem anschließenden Reload der Icinga-Config werden dann Mails mit dem “neuen” Template verschickt.

    UPDATE

    Wie es halt immer so ist … Eine Software wird nie fertig :-)
    Damit die PNP4Nagios-Graphen auch ausserhalb des Unternehmens funktionieren, dürfen diese nicht nur verlinkt werden, sondern müssen base64-codiert mitgeschickt werden.
    Ich habe das Skript um einen Wget-Call erweitert und den base64-Code im IMG-Tag eingebaut:

    <img src="data:image/png;base64, iVBORw0KGgoAAAANSU...MyBzOjAuMDEgcjowLjEzCg==" alt="pnp4nagios: hostname service" />

    Dazu die Datei icinga_mail_base64.pl herunterladen und in icinga_mail.pl umbenennen.

    Download – pnp4nagios über base64

    Für den Wget-Call habe ich versucht die allgemeingültigsten Parameter –no-proxy –no-check-certificate zu verwenden. Wer über einen Proxy oder mit einem gültigen Zertifikat auf Icinga zugreift, muss das in der Zeile 716

    # get pnp4nagios images as base64
    my $base64image = `wget --no-proxy --no-check-certificate -O - '$pnp4nagios_url/image?host=$icinga_hostname&srv=$icinga_servicedesc&view=1&source=0' 2> /dev/null | base64`;

    entsprechen anpassen.

    UPDATE 2

    Das ganze ist jetzt auch Google Code Project verfügbar:

    Issues und Bugs bitte dort einkippen.