Code

Output service only if description is set
[nagixsc.git] / nagixsc_xml2nagios.py
1 #!/usr/bin/python
3 #import base64
4 import datetime
5 import libxml2
6 import optparse
7 import os
8 import random
9 import string
10 import sys
12 NAGIOSCMDs = [ '/usr/local/nagios/var/rw/nagios.cmd', '/var/lib/nagios3/rw/nagios.cmd', ]
13 CHECKRESULTDIRs = [ '/usr/local/nagios/var/spool/checkresults', '/var/lib/nagios3/spool/checkresults', ]
14 MODEs = [ 'passive', 'passive_check', 'checkresult', 'checkresult_check', 'active', ]
16 parser = optparse.OptionParser()
18 parser.add_option('-u', '', dest='url', help='URL of status file (xml)')
19 parser.add_option('-l', '', dest='httpuser', help='HTTP user name')
20 parser.add_option('-a', '', dest='httppasswd', help='HTTP password')
21 parser.add_option('-f', '', dest='file', help='(Path and) file name of status file')
22 parser.add_option('-S', '', dest='schemacheck', help='Check XML against DTD')
23 parser.add_option('-s', '', dest='seconds', type='int', help='Maximum age in seconds of xml timestamp')
24 parser.add_option('-m', '', action='store_true', dest='markold', help='Mark (Set state) of too old checks as UNKNOWN')
25 parser.add_option('-O', '', dest='mode', help='Where/Howto output the results ("%s")' % '", "'.join(MODEs))
26 parser.add_option('-p', '', dest='pipe', help='Full path to nagios.cmd')
27 parser.add_option('-r', '', dest='checkresultdir', help='Full path to checkresult directory')
28 parser.add_option('-H', '', dest='host', help='Hostname to search for in XML file')
29 parser.add_option('-D', '', dest='service', help='Service description to search for in XML file')
30 parser.add_option('-v', '', action='count', dest='verb', help='Verbose output')
32 parser.set_defaults(url=None)
33 parser.set_defaults(httpuser=None)
34 parser.set_defaults(httppasswd=None)
35 parser.set_defaults(file='nagixsc.xml')
36 parser.set_defaults(schemacheck='')
37 parser.set_defaults(seconds=14400)
38 parser.set_defaults(markold=False)
39 parser.set_defaults(mode=False)
40 parser.set_defaults(pipe=None)
41 parser.set_defaults(checkresultdir=None)
42 parser.set_defaults(host=None)
43 parser.set_defaults(service=None)
44 parser.set_defaults(verb=0)
46 (options, args) = parser.parse_args()
48 ##############################################################################
50 from nagixsc import *
52 ##############################################################################
54 if options.mode not in MODEs:
55         print 'Not an allowed mode "%s" - allowed are: %s' % (options.mode, ", ".join(MODEs))
56         sys.exit(127)
58 # Check command line options wrt mode
59 if options.mode == 'passive' or options.mode == 'passive_check':
60         debug(1, options.verb, 'Running in passive mode')
61         if options.pipe == None and options.verb <= 2:
62                 for nagioscmd in NAGIOSCMDs:
63                         if os.path.exists(nagioscmd):
64                                 options.pipe = nagioscmd
66         if options.pipe == None and options.verb <= 2:
67                 print 'Need full path to the nagios.cmd pipe!'
68                 sys.exit(127)
70         debug(2, options.verb, 'nagios.cmd found at %s' % options.pipe)
72 elif options.mode == 'checkresult' or options.mode == 'checkresult_check':
73         debug(1, options.verb, 'Running in checkresult mode')
74         if options.checkresultdir == None and options.verb <= 2:
75                 for crd in CHECKRESULTDIRs:
76                         if os.path.exists(crd):
77                                 options.checkresultdir = crd
79         if options.checkresultdir == None and options.verb <= 2:
80                 print 'Need full path to the checkresultdir!'
81                 sys.exit(127)
83         debug(2, options.verb, 'Checkresult dir: %s' % options.checkresultdir)
85 elif options.mode == 'active':
86         debug(1, options.verb, 'Running in active/plugin mode')
87         if options.host == None:
88                 debug(1, options.verb, 'No host specified, using first host in XML file')
89         if options.service == None:
90                 print 'No service specified on command line!'
91                 sys.exit(127)
93 ##############################################################################
95 # Get URL or file
96 doc = read_xml(options)
98 # Now timestamp AFTER getting the XML file
99 now = int(datetime.datetime.now().strftime('%s'))
102 # Check XML against DTD
103 if options.schemacheck:
104         dtd = libxml2.parseDTD(None, options.schemacheck)
105         ctxt = libxml2.newValidCtxt()
106         ret = doc.validateDtd(ctxt, dtd)
107         if ret != 1:
108                 print "error doing DTD validation"
109                 sys.exit(1)
110         dtd.freeDtd()
111         del dtd
112         del ctxt
115 # Check XML file basics
116 (status, statusstring) = xml_check_version(doc)
117 debug(1, options.verb, statusstring)
118 if not status:
119         print statusstring
120         sys.exit(127)
123 # Get timestamp and check it
124 filetimestamp = xml_get_timestamp(doc)
125 if not filetimestamp:
126         print 'No timestamp found in XML file, exiting because of invalid XML data...'
127         sys.exit(127)
129 timedelta = int(now) - int(filetimestamp)
130 debug(1, options.verb, 'Age of XML file: %s seconds, max allowed: %s seconds' % (timedelta, options.seconds))
133 # Put XML to Python dict
134 checks = xml_to_dict(doc, options.verb, options.host, options.service)
136 # Loop over check results and perhaps mark them as outdated
137 for check in checks:
138         check = check_mark_outdated(check, now, options.seconds, options.markold)
141 # Next steps depend on mode, output results
142 # MODE: passive
143 if options.mode == 'passive' or options.mode == 'passive_check':
144         count_services = 0
145         # Prepare
146         if options.verb <= 2:
147                 pipe = open(options.pipe, "w")
148         else:
149                 pipe = None
151         # Output
152         for check in checks:
153                 count_services += 1
154                 if check['service_description'] == None or check['service_description'] == '':
155                         # Host check
156                         line = '[%s] PROCESS_HOST_CHECK_RESULT;%s;%s;%s' % (now, check['host_name'], check['returncode'], check['output'].replace('\n', '\\n'))
157                 else:
158                         # Service check
159                         line = '[%s] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%s;%s' % (now, check['host_name'], check['service_description'], check['returncode'], check['output'].replace('\n', '\\n'))
161                 if pipe:
162                         pipe.write(line + '\n')
163                 debug(2, options.verb, '%s / %s: %s - "%s"' % (check['host_name'], check['service_description'], check['returncode'], check['output'].replace('\n', '\\n')))
164                 debug(3, options.verb, line)
166         # Close
167         if pipe:
168                 pipe.close()
169         else:
170                 print "Passive check results NOT written to Nagios pipe due to -vvv!"
172         # Return/Exit as a Nagios Plugin if called with mode 'passive_check'
173         if options.mode == 'passive_check':
174                 returncode   = 0
175                 returnstring = 'OK'
176                 output       = ''
178                 if options.markold:
179                         if (now - filetimestamp) > options.seconds:
180                                 returnstring = 'WARNING'
181                                 output = '%s check results written, which are %s(>%s) seconds old' % (count_services, (now-filetimestamp), options.seconds)
182                                 returncode = 1
184                 if not output:
185                         output = '%s check results written which are %s seconds old' % (count_services, (now-filetimestamp))
187                 print 'Nag(ix)SC %s - %s' % (returnstring, output)
188                 sys.exit(returncode)
190 # MODE: checkresult
191 elif options.mode == 'checkresult' or options.mode == 'checkresult_check':
192         count_services = 0
193         count_failed   = 0
195         chars = string.letters + string.digits
197         for check in checks:
198                 count_services += 1
199                 if check.has_key('timestamp'):
200                         timestamp = check['timestamp']
201                 else:
202                         timestamp = xml_get_timestamp(xmldoc)
204                 filename = os.path.join(options.checkresultdir, 'c' + ''.join([random.choice(chars) for i in range(6)]))
205                 try:
206                         crfile = open(filename, "w")
207                         if check['service_description'] == None or check['service_description'] == '':
208                                 # Host check
209                                 crfile.write('### Active Check Result File ###\nfile_time=%s\n\n### Nagios Service Check Result ###\n# Time: %s\nhost_name=%s\ncheck_type=0\ncheck_options=0\nscheduled_check=1\nreschedule_check=1\nlatency=0.0\nstart_time=%s.00\nfinish_time=%s.05\nearly_timeout=0\nexited_ok=1\nreturn_code=%s\noutput=%s\n' % (timestamp, datetime.datetime.now().ctime(), check['host_name'], timestamp, timestamp, check['returncode'], check['output'].replace('\n', '\\n') ) )
210                         else:
211                                 # Service check
212                                 crfile.write('### Active Check Result File ###\nfile_time=%s\n\n### Nagios Service Check Result ###\n# Time: %s\nhost_name=%s\nservice_description=%s\ncheck_type=0\ncheck_options=0\nscheduled_check=1\nreschedule_check=1\nlatency=0.0\nstart_time=%s.00\nfinish_time=%s.05\nearly_timeout=0\nexited_ok=1\nreturn_code=%s\noutput=%s\n' % (timestamp, datetime.datetime.now().ctime(), check['host_name'], check['service_description'], timestamp, timestamp, check['returncode'], check['output'].replace('\n', '\\n') ) )
213                         crfile.close()
215                         # Create OK file
216                         open(filename + '.ok', 'w').close()
217                 except:
218                         count_failed += 1
219                         if options.mode == 'checkresult':
220                                 print 'Could not write checkresult files "%s(.ok)" for "%s"/"%s"!' % (filename, check['host_name'], check['service_description'])
222         if options.mode == 'checkresult_check':
223                 returnstring = ''
224                 output       = ''
225                 if count_failed == 0:
226                         returnstring = 'OK'
227                         returncode   = 0
228                         output       = 'Wrote checkresult files for %s services' % count_services
229                 elif count_failed == count_services:
230                         returnstring = 'CRITICAL'
231                         returncode   = 2
232                         output       = 'No checkresult files could be writen!'
233                 else:
234                         returnstring = 'WARNING'
235                         returncode   = 1
236                         output       = 'Could not write %s out of %s checkresult files!' % (count_failed, count_services)
238                 print 'Nag(ix)SC %s - %s' % (returnstring, output)
239                 sys.exit(returncode)
241         if count_failed == 0:
242                 sys.exit(0)
243         else:
244                 sys.exit(1)
246 # MODE: active
247 elif options.mode == 'active':
249         if len(checks) > 1:
250                 print 'Nag(ix)SC UNKNOWN - Found more (%s) than one host/service!' % len(checks)
251                 sys.exit(3)
252         elif len(checks) == 0:
253                 print 'Nag(ix)SC UNKNOWN - No check for "%s"/"%s" found in XML' % (options.host, options.service)
254                 sys.exit(3)
256         print checks[0]['output']
257         sys.exit(int(checks[0]['returncode']))
259 else:
260         print 'Unknown mode! This should NEVER happen!'
261         sys.exit(127)