Icinga und Nagios sind Computer Überwachungswerkzeuge. Icinga ist ein Fork von Nagios und gilt als rückwärtskompatibel zu diesem. Die nachfolgenden Beispielen beziehen sich auf die Nagios API sind daher aber auch kompatibel zu Icinga.
Beide Überwachungswerkzeuge nutzen Plugins, instantiiert als Services, um die Prozessorauslastung, Speicherbelegung, spezielle Software Prozesse oder physikalische Werte, wie die Temperatur, zu überwachen. Die jeweilige Dokumentation gibt hier weitere Informationen.
Plugins werden genutzt um überwachende Services zu erzeugen. Dies sind Programme mit einem definierten Rückgabewert (z.B. 0=OK, 1=Warning, 2=Critical, 3=Unknown). Deren Standardausgabe wird von Nagios genutzt um Informationen über deren Zustand zu bekommen. Die Nagios Developer Guidelines geben hier weitere Auskünfte.
Nach der Grundinstallation von Nagios kann damit begonnen werden ein eigens Plugin zu entwickeln. Als erstes sollten die Bindings für die gewünschte Programmiersprache installiert werden. Anschließend kann das eigene Plugin unter Beachtung der Nagios Developer Guidelines geschrieben werden.
Für dieses Beispiel nutzen wir die Python Bindings. Das Skript nutzt das Temperature oder PTC Bricklet um die Temperatur zu messen und zu warnen falls zu hohe Temperaturen gemessen werden.
Das kleine Skript, check_tf_temp.py
genannt, besitzt folgende Schnittstelle:
usage: check_tf_temp.py [-h] -u UID -t {temp,ptc} [-H HOST] [-P PORT]
[-m {none,high,low,range}] [-w WARNING] [-c CRITICAL]
[-w2 WARNING2] [-c2 CRITICAL2]
optional arguments:
-h, --help show this help message and exit
-u UID, --uid UID UID from Temperature Bricklet
-t {temp,ptc}, --type {temp,ptc}
Type: temp = Temperature Bricklet, ptc = PTC Bricklet
-H HOST, --host HOST Host Server (default=localhost)
-P PORT, --port PORT Port (default=4223)
-m {none,high,low,range}, --modus {none,high,low,range}
Modus: none (default, only print temperature), high,
low or range
-w WARNING, --warning WARNING
Warning temperature level (temperatures above this
level will trigger a warning message in high mode,
temperature below this level will trigger a warning
message in low mode)
-c CRITICAL, --critical CRITICAL
Critical temperature level (temperatures above this
level will trigger a critical message in high mode,
temperature below this level will trigger a critical
message in low mode)
-w2 WARNING2, --warning2 WARNING2
Warning temperature level (temperatures below this
level will trigger a warning message in range mode)
-c2 CRITICAL2, --critical2 CRITICAL2
Critical temperature level (temperatures below this
level will trigger a critical message in range mode)
Der Großteil der Schnittstelle sollte selbsterklärend sein. Diese unterstützt drei Modi:
high
: Nachricht wird abgegeben wenn die gemessene Temperatur über WARNING oder CRITICAL liegtlow
: Nachricht wird abgegeben wenn die gemessene Temperatur unter WARNING oder CRITICAL liegtrange
: Nachricht wird abgegeben falls die Temperatur über WARNING oder CRITICAL der unter WARNING2 oder CRITICAL2 liegtDas Skript sollte global ausführbar sein, z.B. durch speichern unter /usr/local/bin
.
Das folgende Beispiel verbindet zu einer Ethernet Extension mit dem Hostnamen
ServerMonitoring
und zu einem Temperature Bricklet mit der UID SCT31
. Eine
Warning Nachricht wird bei Temperaturen über 26°C abgegeben und eine Critical
Nachricht bei Temperaturen über 27°C:
check_tf_temp.py -H ServerMonitoring -u SCT31 -t temp -m high -w 26 -c 27
Das folgende Beispiel erzeugt ein Warning bei Temperaturen unter 10°C oder über 30°C und Critical Nachrichten bei Temperaturen unter 8°C und über 35°C:
check_tf_temp.py -H ServerMonitoring -u SCT31 -t temp -m range -w 10 -w2 30 -c 8 -c2 35
Um diese Funktion mit einem PTC Bricklet anstatt mit dem Temperature Bricklet zu nutzen muss die UID und der Typ des Bricklets entsprechend angepasst werden. Das Kommando sieht dann wie folgt aus:
check_tf_temp.py -H ServerMonitoring -u fow -t ptc -m range -w 10 -w2 30 -c 8 -c2 35
Das check_tf_temp.py
Skript kann einfach an andere Tinkerforge Sensoren
angepasst werden. Die read
Methode ist der Hauptteil des Skripts. Diese liest
das Bricklet aus und vergleicht die gemessene Temperatur mit den Warning
und Critical Grenzwerten. Falls notwendig generiert sie eine Meldung und
den dazu passenden Rückgabewert. Das gesamte Skript sieht wie folgt aus (download):
#!/usr/bin/env python
# -*- coding: utf8 -*-
'''
Based on Wiki project:
http://www.tinkerunity.org/wiki/index.php/EN/Projects/IT_Infrastructure_Monitoring_-_Nagios_Plugin
'''
import sys
import argparse
from tinkerforge.bricklet_ptc import PTC
from tinkerforge.bricklet_ptc_v2 import PTCV2
from tinkerforge.ip_connection import IPConnection
from tinkerforge.bricklet_temperature import Temperature
from tinkerforge.bricklet_temperature_v2 import TemperatureV2
OK = 0
WARNING = 1
CRITICAL = 2
UNKNOWN = 3
TYPE_PTC = 'ptc'
TYPE_TEMPERATURE = 'temp'
class CheckTFTemperature(object):
def __init__(self, host='localhost', port=4223):
self.host = host
self.port = port
self.ipcon = IPConnection()
def connect(self, type, uid):
self.ipcon.connect(self.host, self.port)
self.connected_type = type
if self.connected_type == TYPE_PTC:
ptc = PTC(uid, self.ipcon)
if ptc.get_identity().device_identifier == PTCV2.DEVICE_IDENTIFIER:
ptc = PTCV2(uid, self.ipcon)
self.func = ptc.get_temperature
elif self.connected_type == TYPE_TEMPERATURE:
temperature = Temperature(uid, self.ipcon)
if temperature.get_identity().device_identifier == TemperatureV2.DEVICE_IDENTIFIER:
temperature = TemperatureV2(uid, self.ipcon)
self.func = temperature.get_temperature
def disconnect(self):
self.ipcon.disconnect()
def read_temperature(self):
return self.func()/100.0
def read(self, warning, critical, mode='none', warning2=0, critical2=0):
temp = self.read_temperature()
if mode == 'none':
print "temperature %s °C" % temp
else:
if mode == 'low':
warning2 = warning
critical2 = critical
if temp >= critical and (mode == 'high' or mode == 'range'):
print "CRITICAL : temperature too high %s °C" % temp
return CRITICAL
elif temp >= warning and (mode == 'high' or mode == 'range'):
print "WARNING : temperature is high %s °C" % temp
return WARNING
elif temp <= critical2 and (mode == 'low' or mode == 'range'):
print "CRITICAL : temperature too low %s °C" % temp
return CRITICAL
elif temp <= warning2 and (mode == 'low' or mode == 'range'):
print "WARNING : temperature is low %s °C" % temp
return WARNING
elif (temp < warning and mode == 'high') or \
(temp > warning2 and mode == 'low') or \
(temp < warning and temp > warning2 and mode == 'range'):
print "OK : %s°C " % temp
return OK
else:
print "UNKNOWN : can't read temperature"
return UNKNOWN
if __name__ == '__main__':
parse = argparse.ArgumentParser()
parse.add_argument(
'-u',
'--uid',
help = 'UID from Temperature Bricklet', required=True)
parse.add_argument(
'-t',
'--type',
help = 'Type: temp = Temperature Bricklet, ptc = PTC Bricklet',
type = str,
choices = [TYPE_TEMPERATURE, TYPE_PTC],
required = True)
parse.add_argument(
'-H',
'--host',
help = 'Host Server (default=localhost)',
default = 'localhost')
parse.add_argument(
'-P',
'--port',
help = 'Port (default=4223)',
type = int,
default = 4223)
parse.add_argument(
'-m',
'--modus',
help = 'Modus: none (default, only print temperature), high, low or range',
type = str,
choices = ['none', 'high','low','range'],
default = 'none')
parse.add_argument(
'-w',
'--warning',
help = 'Warning temperature level (temperatures above this level will trigger a warning message in high mode, temperature below this level will trigger a warning message in low mode)',
required = False,
type = float)
parse.add_argument(
'-c',
'--critical',
help = 'Critical temperature level (temperatures above this level will trigger a critical message in high mode, temperature below this level will trigger a critical message in low mode)',
required = False,
type = float)
parse.add_argument(
'-w2',
'--warning2',
help = 'Warning temperature level (temperatures below this level will trigger a warning message in range mode)',
type = float)
parse.add_argument(
'-c2',
'--critical2',
help = 'Critical temperature level (temperatures below this level will trigger a critical message in range mode)',
type = float)
args = parse.parse_args()
tf = CheckTFTemperature(args.host, args.port)
tf.connect(args.type, args.uid)
exit_code = tf.read(
args.warning,
args.critical,
args.modus,
args.warning2,
args.critical2)
tf.disconnect()
sys.exit(exit_code)
Um das Skript mit Nagios auszuführen muss es zuerst registriert werden.
Dazu wird dieses mit den folgenden Zeilen in einer Command Konfigurationsdatei
(z.B. /usr/local/nagios/etc/checkcommands.cfg
oder /etc/icinga/commands.cfg
)
registriert:
define command {
command_name check_tf_temp
command_line /usr/local/bin/check_tf_temp.py -H ServerMonitoring -u SCT31 -t temp -m high -w 26 -c 27
}
Anschließend kann dieses Kommando einem Service zugeordnet werden. Ein neuer Service kann in eine Service Konfigurationsdatei mit den folgenden Zeilen:
define service {
use generic-service
host_name localhost
service_description Check Temperature
check_command check_tf_temp
check_interval 1
}
erzeugt werden. Mögliche Konfigurationsdateien befinden sich unter
/usr/local/nagios/etc/services.cfg
, /etc/icinga/objects/services_icinga.cfg
oder an anderen Positionen. Die jeweilige Dokumentation gibt hier Aufschluss.
Das war es. Es sollte ein neuer Service im Web-Interface angezeigt werden, der vor zu hohen Temperaturen warnt.