4296ee5d099a473b5c9f5e5f8b0e0596c70ee96e
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('-f', '', dest='file', help='(Path and) file name of status file')
20 parser.add_option('-S', '', dest='schemacheck', help='Check XML against DTD')
21 parser.add_option('-s', '', dest='seconds', type='int', help='Maximum age in seconds of xml timestamp')
22 parser.add_option('-m', '', action='store_true', dest='markold', help='Mark (Set state) of too old checks as UNKNOWN')
23 parser.add_option('-O', '', dest='mode', help='Where/Howto output the results ("%s")' % '", "'.join(MODEs))
24 parser.add_option('-p', '', dest='pipe', help='Full path to nagios.cmd')
25 parser.add_option('-r', '', dest='checkresultdir', help='Full path to checkresult directory')
26 parser.add_option('-H', '', dest='host', help='Hostname to search for in XML file')
27 parser.add_option('-D', '', dest='service', help='Service description to search for in XML file')
28 parser.add_option('-v', '', action='count', dest='verb', help='Verbose output')
30 parser.set_defaults(url=None)
31 parser.set_defaults(file='nagixsc.xml')
32 parser.set_defaults(schemacheck='')
33 parser.set_defaults(seconds=14400)
34 parser.set_defaults(markold=False)
35 parser.set_defaults(mode=False)
36 parser.set_defaults(pipe=None)
37 parser.set_defaults(checkresultdir=None)
38 parser.set_defaults(host=None)
39 parser.set_defaults(service=None)
40 parser.set_defaults(verb=0)
42 (options, args) = parser.parse_args()
44 ##############################################################################
46 from nagixsc import *
48 ##############################################################################
50 if options.mode not in MODEs:
51 print 'Not an allowed mode "%s" - allowed are: %s' % (options.mode, ", ".join(MODEs))
52 sys.exit(127)
54 # Check command line options wrt mode
55 if options.mode == 'passive' or options.mode == 'passive_check':
56 debug(1, options.verb, 'Running in passive mode')
57 if options.pipe == None and options.verb <= 2:
58 for nagioscmd in NAGIOSCMDs:
59 if os.path.exists(nagioscmd):
60 options.pipe = nagioscmd
62 if options.pipe == None and options.verb <= 2:
63 print 'Need full path to the nagios.cmd pipe!'
64 sys.exit(127)
66 debug(2, options.verb, 'nagios.cmd found at %s' % options.pipe)
68 elif options.mode == 'checkresult' or options.mode == 'checkresult_check':
69 debug(1, options.verb, 'Running in checkresult mode')
70 if options.checkresultdir == None and options.verb <= 2:
71 for crd in CHECKRESULTDIRs:
72 if os.path.exists(crd):
73 options.checkresultdir = crd
75 if options.checkresultdir == None and options.verb <= 2:
76 print 'Need full path to the checkresultdir!'
77 sys.exit(127)
79 debug(2, options.verb, 'Checkresult dir: %s' % options.checkresultdir)
81 elif options.mode == 'active':
82 debug(1, options.verb, 'Running in active/plugin mode')
83 if options.host == None:
84 debug(1, options.verb, 'No host specified, using first host in XML file')
85 if options.service == None:
86 print 'No service specified on command line!'
87 sys.exit(127)
89 ##############################################################################
91 now = int(datetime.datetime.now().strftime('%s'))
93 # Get URL or file
94 if options.url != None:
95 import urllib2
97 response = urllib2.urlopen(options.url)
98 doc = libxml2.parseDoc(response.read())
99 response.close()
100 else:
101 doc = libxml2.parseFile(options.file)
104 # Check XML against DTD
105 if options.schemacheck:
106 dtd = libxml2.parseDTD(None, options.schemacheck)
107 ctxt = libxml2.newValidCtxt()
108 ret = doc.validateDtd(ctxt, dtd)
109 if ret != 1:
110 print "error doing DTD validation"
111 sys.exit(1)
112 dtd.freeDtd()
113 del dtd
114 del ctxt
117 # Check XML file basics
118 (status, statusstring) = xml_check_version(doc)
119 debug(1, options.verb, statusstring)
120 if not status:
121 print statusstring
122 sys.exit(127)
125 # Get timestamp and check it
126 filetimestamp = xml_get_timestamp(doc)
127 if not filetimestamp:
128 print 'No timestamp found in XML file, exiting because of invalid XML data...'
129 sys.exit(127)
131 timedelta = int(now) - int(filetimestamp)
132 debug(1, options.verb, 'Age of XML file: %s seconds, max allowed: %s seconds' % (timedelta, options.seconds))
135 # Put XML to Python dict
136 checks = xml_to_dict(doc, options.verb, options.host, options.service)
138 # Loop over check results and perhaps mark them as outdated
139 for check in checks:
140 check = check_mark_outdated(check, now, options.seconds, options.markold)
143 # Next steps depend on mode, output results
144 # MODE: passive
145 if options.mode == 'passive' or options.mode == 'passive_check':
146 # Prepare
147 if options.verb <= 2:
148 pipe = open(options.pipe, "w")
149 else:
150 pipe = None
152 # Output
153 for check in checks:
154 line = '[%s] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%s;%s' % (now, check['host_name'], check['service_description'], check['returncode'], check['output'].replace('\n', '\\n'))
156 if pipe:
157 pipe.write(line + '\n')
158 debug(2, options.verb, '%s / %s: %s - "%s"' % (check['host_name'], check['service_description'], check['returncode'], check['output'].replace('\n', '\\n')))
159 debug(3, options.verb, line)
161 # Close
162 if pipe:
163 pipe.close()
164 else:
165 print "Passive check results NOT written to Nagios pipe due to -vvv!"
167 # Return/Exit as a Nagios Plugin if called with mode 'passive_check'
168 if options.mode == 'passive_check':
169 returncode = 0
170 returnstring = 'OK'
171 output = ''
173 if options.markold:
174 if (now - filetimestamp) > options.seconds:
175 returnstring = 'WARNING'
176 output = 'Check results are %s(>%s) seconds old' % ((now-filetimestamp), options.seconds)
177 returncode = 1
179 if not output:
180 output = 'Check results are %s seconds old' % (now-filetimestamp)
182 print 'Nag(ix)SC %s - %s' % (returnstring, output)
183 sys.exit(returncode)
185 # MODE: checkresult
186 elif options.mode == 'checkresult' or options.mode == 'checkresult_check':
187 count_services = 0
188 count_failed = 0
190 chars = string.letters + string.digits
192 for check in checks:
193 count_services += 1
194 if check.has_key('timestamp'):
195 timestamp = check['timestamp']
196 else:
197 timestamp = xml_get_timestamp(xmldoc)
199 filename = os.path.join(options.checkresultdir, 'c' + ''.join([random.choice(chars) for i in range(6)]))
200 try:
201 crfile = open(filename, "w")
202 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') ) )
203 crfile.close()
205 # Create OK file
206 open(filename + '.ok', 'w').close()
207 except:
208 count_failed += 1
209 if options.mode == 'checkresult':
210 print 'Could not write checkresult files "%s(.ok)" for "%s"/"%s"!' % (filename, check['host_name'], check['service_description'])
212 if options.mode == 'checkresult_check':
213 returnstring = ''
214 output = ''
215 if count_failed == 0:
216 returnstring = 'OK'
217 returncode = 0
218 output = 'Wrote checkresult files for %s services' % count_services
219 elif count_failed == count_services:
220 returnstring = 'CRITICAL'
221 returncode = 2
222 output = 'No checkresult files could be writen!'
223 else:
224 returnstring = 'WARNING'
225 returncode = 1
226 output = 'Could not write %s out of %s checkresult files!' % (count_failed, count_services)
228 print 'Nag(ix)SC %s - %s' % (returnstring, output)
229 sys.exit(returncode)
231 if count_failed == 0:
232 sys.exit(0)
233 else:
234 sys.exit(1)
236 # MODE: active
237 elif options.mode == 'active':
239 if len(checks) > 1:
240 print 'Nag(ix)SC UNKNOWN - Found more (%s) than one host/service!' % len(checks)
241 sys.exit(3)
242 elif len(checks) == 0:
243 print 'Nag(ix)SC UNKNOWN - No check for "%s"/"%s" found in XML' % (options.host, options.service)
244 sys.exit(3)
246 print checks[0]['output']
247 sys.exit(int(checks[0]['returncode']))
249 else:
250 print 'Unknown mode! This should NEVER happen!'
251 sys.exit(127)