Code

Added English translations for QUICKSTART.txt and obsess.README.
[nagixsc.git] / nagixsc_xml2nagios.py
1 #!/usr/bin/python
2 #
3 # Nag(ix)SC -- nagixsc_xml2nagios.py
4 #
5 # Copyright (C) 2009-2010 Sven Velt <sv@teamix.net>
6 #
7 # This program is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by the
9 # Free Software Foundation; only version 2 of the License is applicable.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along
17 # with this program; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20 #import base64
21 import libxml2
22 import optparse
23 import os
24 import sys
25 import time
27 NAGIOSCMDs = [ '/usr/local/nagios/var/rw/nagios.cmd', '/var/lib/nagios3/rw/nagios.cmd', ]
28 CHECKRESULTDIRs = [ '/usr/local/nagios/var/spool/checkresults', '/var/lib/nagios3/spool/checkresults', ]
29 MODEs = [ 'passive', 'passive_check', 'checkresult', 'checkresult_check', 'active', ]
31 parser = optparse.OptionParser()
33 parser.add_option('-u', '', dest='url', help='URL of status file (xml)')
34 parser.add_option('-l', '', dest='httpuser', help='HTTP user name')
35 parser.add_option('-a', '', dest='httppasswd', help='HTTP password')
36 parser.add_option('-f', '', dest='file', help='(Path and) file name of status file')
37 parser.add_option('-S', '', dest='schemacheck', help='Check XML against DTD')
38 parser.add_option('-s', '', dest='seconds', type='int', help='Maximum age in seconds of xml timestamp')
39 parser.add_option('-m', '', action='store_true', dest='markold', help='Mark (Set state) of too old checks as UNKNOWN')
40 parser.add_option('-O', '', dest='mode', help='Where/Howto output the results ("%s")' % '", "'.join(MODEs))
41 parser.add_option('-p', '', dest='pipe', help='Full path to nagios.cmd')
42 parser.add_option('-r', '', dest='checkresultdir', help='Full path to checkresult directory')
43 parser.add_option('-H', '', dest='host', help='Hostname to search for in XML file')
44 parser.add_option('-D', '', dest='service', help='Service description to search for in XML file')
45 parser.add_option('-v', '', action='count', dest='verb', help='Verbose output')
47 parser.set_defaults(url=None)
48 parser.set_defaults(httpuser=None)
49 parser.set_defaults(httppasswd=None)
50 parser.set_defaults(file='nagixsc.xml')
51 parser.set_defaults(schemacheck='')
52 parser.set_defaults(seconds=14400)
53 parser.set_defaults(markold=False)
54 parser.set_defaults(mode=False)
55 parser.set_defaults(pipe=None)
56 parser.set_defaults(checkresultdir=None)
57 parser.set_defaults(host=None)
58 parser.set_defaults(service=None)
59 parser.set_defaults(verb=0)
61 (options, args) = parser.parse_args()
63 ##############################################################################
65 from nagixsc import *
67 ##############################################################################
69 if options.mode not in MODEs:
70         print 'Not an allowed mode "%s" - allowed are: "%s"' % (options.mode, '", "'.join(MODEs))
71         sys.exit(127)
73 # Check command line options wrt mode
74 if options.mode == 'passive' or options.mode == 'passive_check':
75         debug(1, options.verb, 'Running in passive mode')
76         if options.pipe == None and options.verb <= 2:
77                 for nagioscmd in NAGIOSCMDs:
78                         if os.path.exists(nagioscmd):
79                                 options.pipe = nagioscmd
81         if options.pipe == None and options.verb <= 2:
82                 print 'Need full path to the nagios.cmd pipe!'
83                 sys.exit(127)
85         debug(2, options.verb, 'nagios.cmd found at %s' % options.pipe)
87 elif options.mode == 'checkresult' or options.mode == 'checkresult_check':
88         debug(1, options.verb, 'Running in checkresult mode')
89         if options.checkresultdir == None and options.verb <= 2:
90                 for crd in CHECKRESULTDIRs:
91                         if os.path.exists(crd):
92                                 options.checkresultdir = crd
94         if options.checkresultdir == None and options.verb <= 2:
95                 print 'Need full path to the checkresultdir!'
96                 sys.exit(127)
98         debug(2, options.verb, 'Checkresult dir: %s' % options.checkresultdir)
100 elif options.mode == 'active':
101         debug(1, options.verb, 'Running in active/plugin mode')
102         if options.host == None:
103                 debug(1, options.verb, 'No host specified on command line')
104         if options.service == None:
105                 debug(1, options.verb, 'No service specified on command line, looking at XML file later')
107 ##############################################################################
109 # Get URL or file
110 doc = read_xml(options)
112 # Now timestamp AFTER getting the XML file
113 now = long(time.time())
116 # Check XML against DTD
117 if options.schemacheck:
118         dtd = libxml2.parseDTD(None, options.schemacheck)
119         ctxt = libxml2.newValidCtxt()
120         ret = doc.validateDtd(ctxt, dtd)
121         if ret != 1:
122                 print "error doing DTD validation"
123                 sys.exit(1)
124         dtd.freeDtd()
125         del dtd
126         del ctxt
129 # Check XML file basics
130 (status, statusstring) = xml_check_version(doc)
131 debug(1, options.verb, statusstring)
132 if not status:
133         print statusstring
134         sys.exit(127)
137 # Get timestamp and check it
138 filetimestamp = xml_get_timestamp(doc)
139 if not filetimestamp:
140         print 'No timestamp found in XML file, exiting because of invalid XML data...'
141         sys.exit(127)
143 timedelta = int(now) - int(filetimestamp)
144 debug(1, options.verb, 'Age of XML file: %s seconds, max allowed: %s seconds' % (timedelta, options.seconds))
147 # Put XML to Python dict
148 checks = xml_to_dict(doc, options.verb, options.host, options.service)
150 # Loop over check results and perhaps mark them as outdated
151 for check in checks:
152         check = check_mark_outdated(check, now, options.seconds, options.markold)
155 # Next steps depend on mode, output results
156 # MODE: passive
157 if options.mode == 'passive' or options.mode == 'passive_check':
158         count_services = dict2out_passive(checks, xml_get_timestamp(doc), options.pipe, options.verb)
160         # Return/Exit as a Nagios Plugin if called with mode 'passive_check'
161         if options.mode == 'passive_check':
162                 returncode   = 0
163                 returnstring = 'OK'
164                 output       = '%s check results written which are %s seconds old' % (count_services, (now-filetimestamp))
166                 if options.markold:
167                         if (now - filetimestamp) > options.seconds:
168                                 returnstring = 'WARNING'
169                                 output = '%s check results written, which are %s(>%s) seconds old' % (count_services, (now-filetimestamp), options.seconds)
170                                 returncode = 1
172                 print 'Nag(ix)SC %s - %s' % (returnstring, output)
173                 sys.exit(returncode)
175 # MODE: checkresult: "checkresult", "checkresult_check"
176 elif options.mode.startswith('checkresult'):
177         (count_services, count_failed, list_failed) = dict2out_checkresult(checks, xml_get_timestamp(doc), options.checkresultdir, options.verb)
179         if options.mode == 'checkresult':
180                 if list_failed:
181                         for entry in list_failed:
182                                 print 'Could not write checkresult files "%s(.ok)" for "%s"/"%s"!' % (entry[0], entry[1], entry[2])
184                 if count_failed == 0:
185                         sys.exit(0)
186                 else:
187                         sys.exit(1)
189         elif options.mode == 'checkresult_check':
190                 returnstring = ''
191                 output       = ''
192                 if count_failed == 0:
193                         returnstring = 'OK'
194                         returncode   = 0
195                         output       = 'Wrote checkresult files for %s services' % count_services
196                 elif count_failed == count_services:
197                         returnstring = 'CRITICAL'
198                         returncode   = 2
199                         output       = 'No checkresult files could be writen!'
200                 else:
201                         returnstring = 'WARNING'
202                         returncode   = 1
203                         output       = 'Could not write %s out of %s checkresult files!' % (count_failed, count_services)
205                 print 'Nag(ix)SC %s - %s' % (returnstring, output)
206                 sys.exit(returncode)
208 # MODE: active
209 elif options.mode == 'active':
211         if len(checks) > 1:
212                 print 'Nag(ix)SC UNKNOWN - Found more (%s) than one host/service!' % len(checks)
213                 print 'Found: ' + ', '.join(['%s/%s' % (c['host_name'], c['service_description']) for c in checks])
214                 sys.exit(3)
215         elif len(checks) == 0:
216                 output = 'Nag(ix)SC UNKNOWN - No check found in XML'
217                 if options.host:
218                         output += ' - Host filter: "%s"' % options.host
219                 if options.service:
220                         output += ' - Service filter: "%s"' % options.service
221                 print output
222                 sys.exit(3)
224         print checks[0]['output']
225         sys.exit(int(checks[0]['returncode']))
227 else:
228         print 'Unknown mode! This should NEVER happen!'
229         sys.exit(127)