Code

WIP: Obsessing/distributed setup with Nag(ix)SC
authorSven Velt <sven@velt.de>
Thu, 23 Sep 2010 08:11:48 +0000 (10:11 +0200)
committerSven Velt <sven@velt.de>
Thu, 23 Sep 2010 08:11:48 +0000 (10:11 +0200)
Signed-off-by: Sven Velt <sven@velt.de>
obsess.README [new file with mode: 0644]
obsess_daemon.py [new file with mode: 0755]

diff --git a/obsess.README b/obsess.README
new file mode 100644 (file)
index 0000000..72c0edf
--- /dev/null
@@ -0,0 +1,53 @@
+nagios.cfg:
+===========
+
+obsess_over_services=1
+ocsp_command=ocsp2out
+obsess_over_hosts=1
+ochp_command=ochp2out
+
+
+
+commands:
+=========
+
+define command {
+  command_name  ocsp2out
+  command_line  echo >>/tmp/nagixsc.spool/new/$TIMET$ LASTSERVICECHECK::$LASTSERVICECHECK$ HOSTNAME::\'$HOSTNAME$\' SERVICEDESC::\'$SERVICEDESC$\' SERVICESTATEID::$SERVICESTATEID$ SERVICEOUTPUT::\'$SERVICEOUTPUT$\' LONGSERVICEOUTPUT::\'$LONGSERVICEOUTPUT$\'
+}
+
+define command {
+  command_name  ochp2out
+  command_line  echo >>/tmp/nagixsc.spool/new/$TIMET$ LASTHOSTCHECK::$LASTHOSTCHECK$ HOSTNAME::\'$HOSTNAME$\' HOSTSTATEID::$HOSTSTATEID$ HOSTOUTPUT::\'$HOSTOUTPUT$\' LONGHOSTOUTPUT::\'$LONGHOSTOUTPUT$\'
+}
+
+
+Vorteile:
+=========
+
+- Anders als in der originalen Dokumentation wird NICHT noch eine Shell
+  gestartet, die die Return-Codes analysiert und dann mit Hilfe von "printf"
+  den String formatiert.
+- Das Original-Skript ruft "send_nsca" direkt auf. Dies wiederum blockiert den
+  Nagios so lange, bis das NSCA-Netzwerkpaket verschickt werden konnte (Man
+  bedenke das Timeout, wenn der Server nicht erreicht werden kann).
+  Das Wegschreiben der Spool-Datei hier macht die von Nagios sowieso geforkte
+  und gestartete Shell. Die Blockierung des Nagios-Prozess (sollte) ist somit
+  minimal.
+- Nagios schreibt mehrere Check-Ergebniss praktisch auf einmal weg (vgl.
+  Zeitstempel). NSCA schickt alle Pakete einzeln (für jedes einen
+  TCP-Handshake...), Nag(ix)SC packt die Ergebnisse aus einem Spool-File in
+  ein XML und schickt mehrere bis viele Check-Ergebnisse auf einmal los.
+- Das Senden der XML-Files passiert unabhängig von Nagios durch einen eigenen
+  Prozess ("obsess_daemon.py")
+
+
+Hinweis:
+========
+
+- "obsess_daemon.py" ist noch kein richtiger Daemon, einfach an der
+  Kommandozeile start und gut laufen lassen (Debug-Ausgaben!)
+- Zum "auf die Finger guggen":
+  % cd /tmp/nagixsc.spool
+  % watch -n2 "cat */*[0-9] |wc -l; (for F in xmlout/*; do ~/src/nagixsc/nagixsc_read_xml.py -f \$F; done)|grep -c RetCode"
+
diff --git a/obsess_daemon.py b/obsess_daemon.py
new file mode 100755 (executable)
index 0000000..1712c4e
--- /dev/null
@@ -0,0 +1,77 @@
+#!/usr/bin/python
+
+import os
+import re
+import time
+
+##############################################################################
+from nagixsc import *
+##############################################################################
+
+def check_dir(dirpath):
+       if not os.path.isdir(dirpath):
+               # dirpath does not exist, try to create it
+               try:
+                       os.path.os.mkdir(dirpath, 0777) # FIXME
+               except OSError:
+                       print 'Could not create directory "%s"!' % dirpath
+                       sys.exit(1)
+
+       if not os.access(dirpath,os.W_OK):
+               # dirpath is not writeable
+               print 'No write access to directory "%s"!' % dirpath
+               sys.exit(1)
+
+##############################################################################
+
+spoolpath_base = '/tmp/nagixsc.spool'
+spoolpath_new = os.path.join(spoolpath_base, 'new')
+spoolpath_work = os.path.join(spoolpath_base, 'work')
+spoolpath_done = os.path.join(spoolpath_base, 'done')
+
+for d in [spoolpath_base, spoolpath_new, spoolpath_work, spoolpath_done]:
+       check_dir(d)
+
+# Output XML files to this directory
+outdir = os.path.join(spoolpath_base, 'xmlout')
+check_dir(outdir)
+
+service_analyzer = re.compile("^LASTSERVICECHECK::'?(\d+)'?\s+HOSTNAME::'?([^']+)'?\s+SERVICEDESC::'?([^']+)'?\s+SERVICESTATEID::'?(\d+)'?\s+SERVICEOUTPUT::'?([^']*)'?\s+LONGSERVICEOUTPUT::'?([^']*)'?$")
+host_analyzer = re.compile("LASTHOSTCHECK::'?(\d+)'?\s+HOSTNAME::'?([^']+)'?\s+HOSTSTATEID::'?(\d+)'?\s+HOSTOUTPUT::'?([^']*)'?\s+LONGHOSTOUTPUT::'?([^']*)'?$")
+
+
+while True:
+       if os.listdir(spoolpath_new):
+               checks = []
+               files_done = []
+               for filename in os.listdir(spoolpath_new):
+                       spoolfile = os.path.join(spoolpath_work, filename)
+                       os.rename(os.path.join(spoolpath_new, filename), spoolfile)
+
+                       # Work with file
+                       f = open(spoolfile)
+
+                       print 'Read ' + spoolfile
+                       for line in f:
+                               if line.startswith('LASTSERVICECHECK'):
+                                       m = service_analyzer.match(line)
+                                       if m:
+                                               checks.append({'host_name':m.group(2), 'service_description':m.group(3), 'returncode':m.group(4), 'output':'\n'.join(m.group(5,6)), 'timestamp':m.group(1)})
+
+                               elif line.startswith('LASTHOSTCHECK'):
+                                       m = host_analyzer.match(line)
+                                       if m:
+                                               checks.append({'host_name':m.group(2), 'service_description':None, 'returncode':m.group(3), 'output':'\n'.join(m.group(4,5)), 'timestamp':m.group(1)})
+
+                       f.close()
+                       files_done.append(filename)
+
+               outfilename = str(int(time.time())) + '.xml'
+               xmldoc = xml_from_dict(checks)
+               xmldoc.saveFile(os.path.join(outdir, outfilename)) # FIXME
+               for filename in files_done:
+                       os.rename(os.path.join(spoolpath_work, filename), os.path.join(spoolpath_done, filename))
+               print 'Written ' + outfilename
+
+       time.sleep(5)
+