Code

Added check to reset future timestamps
[nagixsc.git] / nagixsc.py
1 import base64
2 import datetime
3 import libxml2
4 import sys
6 def debug(level, verb, string):
7         if level <= verb:
8                 print "%s: %s" % (level, string)
11 ##############################################################################
13 def available_encodings():
14         return ['base64', 'plain',]
17 def decode(data, encoding):
18         if encoding == 'plain':
19                 return data
20         else:
21                 return base64.b64decode(data)
24 def encode(data, encoding=None):
25         if encoding == 'plain':
26                 return data
27         else:
28                 return base64.b64encode(data)
31 ##############################################################################
33 def read_xml(options):
34         if options.url != None:
35                 import urllib2
37                 if options.httpuser and options.httppasswd:
38                         passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
39                         passman.add_password(None, options.url, options.httpuser, options.httppasswd)
40                         authhandler = urllib2.HTTPBasicAuthHandler(passman)
41                         opener = urllib2.build_opener(authhandler)
42                         urllib2.install_opener(opener)
44                 try:
45                         response = urllib2.urlopen(options.url)
46                 except urllib2.HTTPError, error:
47                         print error
48                         sys.exit(0)
49                 except urllib2.URLError, error:
50                         print error.reason[1]
51                         sys.exit(0)
53                 doc = libxml2.parseDoc(response.read())
54                 response.close()
56         else:
57                 doc = libxml2.parseFile(options.file)
59         return doc
62 ##############################################################################
64 def xml_check_version(xmldoc):
65         # FIXME: Check XML structure
66         try:
67                 xmlnagixsc = xmldoc.xpathNewContext().xpathEval('/nagixsc')[0]
68         except:
69                 return (False, 'Not a Nag(IX)SC XML file!')
71         try:
72                 if xmlnagixsc.prop('version') != "1.0":
73                         return (False, 'Wrong version (found "%s", need "1.0") of XML file!' % xmlnagixsc.prop('version'))
74         except:
75                 return (False, 'No version information found in XML file!')
77         return (True, 'XML seems to be ok')
80 def xml_get_timestamp(xmldoc):
81         try:
82                 timestamp = int(xmldoc.xpathNewContext().xpathEval('/nagixsc/timestamp')[0].get_content())
83         except:
84                 return False
86         return timestamp
89 def xml_to_dict(xmldoc, verb=0, hostfilter=None, servicefilter=None):
90         checks = []
91         now = int(datetime.datetime.now().strftime('%s'))
92         filetimestamp = reset_future_timestamp(xml_get_timestamp(xmldoc), now)
94         if hostfilter:
95                 hosts = xmldoc.xpathNewContext().xpathEval('/nagixsc/host[name="%s"] | /nagixsc/host[name="%s"]' % (hostfilter, encode(hostfilter)))
96         else:
97                 hosts = xmldoc.xpathNewContext().xpathEval('/nagixsc/host')
99         for host in hosts:
100                 xmlhostname = host.xpathEval('name')[0]
101                 hostname = decode(xmlhostname.get_content(), xmlhostname.prop('encoding'))
102                 debug(2, verb, 'Found host "%s"' % hostname)
104                 # Look for Host check result
105                 if host.xpathEval('returncode'):
106                         retcode   = host.xpathEval('returncode')[0].get_content()
107                 else:
108                         retcode   = None
110                 if host.xpathEval('output'):
111                         xmloutput = host.xpathEval('output')[0]
112                         output    = decode(xmloutput.get_content(), xmloutput.prop('encoding')).rstrip()
113                 else:
114                         output    = None
116                 if host.xpathEval('timestamp'):
117                         timestamp = reset_future_timestamp(int(host.xpathEval('timestamp')[0].get_content()), now)
118                 else:
119                         timestamp = filetimestamp
121                 if retcode and output:
122                         checks.append({'host_name':hostname, 'service_description':None, 'returncode':retcode, 'output':output, 'timestamp':timestamp})
125                 # Look for service filter
126                 if servicefilter:
127                         services = host.xpathEval('service[description="%s"] | service[description="%s"]' % (servicefilter, encode(servicefilter)))
128                 else:
129                         services = host.xpathEval('service')
131                 # Loop over services in host
132                 for service in services:
133                         service_dict = {}
135                         xmldescr  = service.xpathEval('description')[0]
136                         xmloutput = service.xpathEval('output')[0]
138                         srvdescr = decode(xmldescr.get_content(), xmldescr.prop('encoding'))
139                         retcode  = service.xpathEval('returncode')[0].get_content()
140                         output   = decode(xmloutput.get_content(), xmloutput.prop('encoding')).rstrip()
142                         try:
143                                 timestamp = reset_future_timestamp(int(service.xpathEval('timestamp')[0].get_content()), now)
144                         except:
145                                 timestamp = filetimestamp
147                         debug(2, verb, 'Found service "%s"' % srvdescr)
149                         service_dict = {'host_name':hostname, 'service_description':srvdescr, 'returncode':retcode, 'output':output, 'timestamp':timestamp}
150                         checks.append(service_dict)
152                         debug(1, verb, 'Host: "%s" - Service: "%s" - RetCode: "%s" - Output: "%s"' % (hostname, srvdescr, retcode, output) )
154         return checks
157 def xml_from_dict(checks, encoding='base64'):
158         lasthost = None
160         db = [(check['host_name'], check) for check in checks]
161         db.sort()
163         xmldoc = libxml2.newDoc('1.0')
164         xmlroot = xmldoc.newChild(None, 'nagixsc', None)
165         xmlroot.setProp('version', '1.0')
166         xmltimestamp = xmlroot.newChild(None, 'timestamp', datetime.datetime.now().strftime('%s'))
168         for entry in db:
169                 check = entry[1]
171                 if check['host_name'] != lasthost:
172                         xmlhost = xmlroot.newChild(None, 'host', None)
173                         xmlhostname = xmlhost.newChild(None, 'name', encode(check['host_name'], encoding))
174                         lasthost = check['host_name']
176                 if check['service_description'] == '' or check['service_description'] == None:
177                         # Host check result
178                         xmlreturncode = xmlhost.newChild(None, 'returncode', str(check['returncode']))
179                         xmloutput     = xmlhost.newChild(None, 'output', encode(check['output'], encoding))
180                         xmloutput.setProp('encoding', encoding)
181                         if check.has_key('timestamp'):
182                                 xmltimestamp  = xmlhost.newChild(None, 'timestamp', str(check['timestamp']))
183                 else:
184                         # Service check result
185                         xmlservice    = xmlhost.newChild(None, 'service', None)
186                         xmlname       = xmlservice.newChild(None, 'description', encode(check['service_description'], encoding))
187                         xmlname.setProp('encoding', encoding)
188                         xmlreturncode = xmlservice.newChild(None, 'returncode', str(check['returncode']))
189                         xmloutput     = xmlservice.newChild(None, 'output', encode(check['output'], encoding))
190                         xmloutput.setProp('encoding', encoding)
191                         if check.has_key('timestamp'):
192                                 xmltimestamp  = xmlservice.newChild(None, 'timestamp', str(check['timestamp']))
194         return xmldoc
197 def check_mark_outdated(check, now, maxtimediff, markold):
198         timedelta = now - check['timestamp']
199         if timedelta > maxtimediff:
200                 check['output'] = 'Nag(ix)SC: Check result is %s(>%s) seconds old - %s' % (timedelta, maxtimediff, check['output'])
201                 if markold:
202                         check['returncode'] = 3
203         return check
206 def reset_future_timestamp(timestamp, now):
207         if timestamp <= now:
208                 return timestamp
209         else:
210                 return now