Skip to content

Commit

Permalink
Added livestatus as data source
Browse files Browse the repository at this point in the history
... to conf2http (try "_livestatus" as config file name after putting
path/ip&port into conf2http.cfg)
... new command live2xml

and be a little bit more verbose in the config file of conf2http

Signed-off-by: Sven Velt <sven@velt.de>
  • Loading branch information
wAmpIre committed Sep 3, 2010
1 parent cd23355 commit 779ef24
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 8 deletions.
83 changes: 83 additions & 0 deletions nagixsc/__init__.py
Expand Up @@ -544,3 +544,86 @@ def setup(self):

##############################################################################

def prepare_socket(socket_path):
try:
if socket_path.startswith('/'):
s_family=socket.AF_UNIX
s_sockaddr = socket_path
elif socket_path.startswith('unix:'):
s_family=socket.AF_UNIX
s_sockaddr = socket_path[5:]
elif socket_path.find(':') >= 0:
s_port = socket_path.split(':')[-1]
s_host = ':'.join(socket_path.split(':')[:-1])
if s_host.startswith('[') and s_host.endswith(']'):
s_host = s_host[1:-1]
(s_family, s_socktype, s_proto, s_canonname, s_sockaddr) = socket.getaddrinfo(s_host, s_port, 0, socket.SOCK_STREAM)[0]
else:
return None
except:
return None

return (s_family, s_sockaddr)


def read_socket(s_opts, commands):
# print '%20s => %s %s' % (sock, s_family, s_sockaddr)

s = socket.socket(s_opts[0], socket.SOCK_STREAM)
s.connect(s_opts[1])
for line in commands:
if not line.endswith('\n'):
line += '\n'
s.send(line)
s.shutdown(socket.SHUT_WR)

answer = ''
try:
while True:
s.settimeout(10)
data = s.recv(32768)
if data:
answer += data
else:
break
except socket.timeout:
return ''

return answer


def livestatus2dict(s_opts, host=None, service=None):
checks = []

# Get host information only if NO service specified
if not service:
commands = []
commands.append('GET hosts\n')
commands.append('Columns: name state plugin_output long_plugin_output last_check\n')
if host:
commands.append('Filter: name = %s' % host)
answer = read_socket(s_opts, commands)

for line in answer.split('\n')[:-1]:
line = line.split(';')
checks.append({'host_name':line[0], 'service_description':None, 'returncode':line[1], 'output':'\n'.join([line[2], line[3]]).rstrip(), 'timestamp':str(line[4])})

# Get service information(s)
commands = []
commands.append('GET services\n')
commands.append('Columns: host_name description state plugin_output long_plugin_output last_check\n')
if host:
commands.append('Filter: host_name = %s' % host)
if service:
commands.append('Filter: description = %s' % service)

answer = read_socket(s_opts, commands)

for line in answer.split('\n')[:-1]:
line = line.split(';')
checks.append({'host_name':line[0], 'service_description':line[1], 'returncode':line[2], 'output':'\n'.join([line[3], line[4]]).rstrip(), 'timestamp':str(line[5])})


return checks
##############################################################################

30 changes: 23 additions & 7 deletions nagixsc_conf2http.py
Expand Up @@ -43,7 +43,8 @@
'ssl': False,
'sslcert': None,
'conf_dir': '',
'pidfile': '/var/run/nagixsc_conf2http.pid'
'pidfile': '/var/run/nagixsc_conf2http.pid',
'livestatus_socket' : None,
}

if 'ip' in cfgread.options('server'):
Expand Down Expand Up @@ -80,6 +81,9 @@
if 'pidfile' in cfgread.options('server'):
config['pidfile'] = cfgread.get('server', 'pidfile')

if 'livestatus_socket' in cfgread.options('server'):
config['livestatus_socket'] = prepare_socket(cfgread.get('server', 'livestatus_socket'))


users = {}
for u in cfgread.options('users'):
Expand Down Expand Up @@ -137,14 +141,26 @@ def do_GET(self):
self.http_error(500, 'Config file name contains invalid characters')
return

check_config = read_inifile(os.path.join(config['conf_dir'], configfile))
if not check_config:
self.http_error(500, 'Could not read config file "%s"' % configfile)
return
# Just be sure it exists
checks = None

# If config file name starts with "_" it's something special
if not configfile.startswith('_'):
# Try to read config file, execute checks
check_config = read_inifile(os.path.join(config['conf_dir'], configfile))
if not check_config:
self.http_error(500, 'Could not read config file "%s"' % configfile)
return
checks = conf2dict(check_config, host, service)

elif configfile=='_livestatus.conf' and config['livestatus_socket']:
# Read mk-livestatus and translate into XML
checks = livestatus2dict(config['livestatus_socket'], host, service)


checks = conf2dict(check_config, host, service)
# No check results? No (good) answer...
if not checks:
self.http_error(500, 'No checks executed')
self.http_error(500, 'No check results')
return

self.send_response(200)
Expand Down
75 changes: 75 additions & 0 deletions nagixsc_live2xml.py
@@ -0,0 +1,75 @@
#!/usr/bin/python

import optparse
import sys

##############################################################################

from nagixsc import *

##############################################################################

parser = optparse.OptionParser()

parser.add_option('-s', '', dest='socket', help='Livestatus socket to connect')
parser.add_option('-o', '', dest='outfile', help='Output file name, "-" for STDOUT or HTTP POST URL')
parser.add_option('-e', '', dest='encoding', help='Encoding ("%s")' % '", "'.join(available_encodings()) )
parser.add_option('-H', '', dest='host', help='Hostname/section to search for in config file')
parser.add_option('-D', '', dest='service', help='Service description to search for in config file (needs -H)')
parser.add_option('-l', '', dest='httpuser', help='HTTP user name, if outfile is HTTP(S) URL')
parser.add_option('-a', '', dest='httppasswd', help='HTTP password, if outfile is HTTP(S) URL')
parser.add_option('-v', '', action='count', dest='verb', help='Verbose output')

parser.set_defaults(socket=None)
parser.set_defaults(outfile='-')
parser.set_defaults(encoding='base64')
parser.set_defaults(host=None)
parser.set_defaults(service=None)
parser.set_defaults(verb=0)

(options, args) = parser.parse_args()

##############################################################################

if not options.socket:
print 'No socket specified!\n'
parser.print_help()
sys.exit(1)

if not check_encoding(options.encoding):
print 'Wrong encoding method "%s"!' % options.encoding
print 'Could be one of: "%s"' % '", "'.join(available_encodings())
sys.exit(1)

##############################################################################

# Prepare socket
s_opts = prepare_socket(options.socket)

# Read informations from livestatus
checks = livestatus2dict(s_opts, options.host, options.service)

# Convert to XML
xmldoc = xml_from_dict(checks, options.encoding)

# Output
if options.outfile.startswith('http'):
(headers, body) = encode_multipart(xmldoc, options.httpuser, options.httppasswd)

try:
response = urllib2.urlopen(urllib2.Request(options.outfile, body, headers)).read()
except urllib2.HTTPError, error:
print error
sys.exit(6)
except urllib2.URLError, error:
print error.reason[1]
sys.exit(7)

print response

elif options.outfile == '-':
xmldoc.saveFormatFile('-', format=1)

else:
xmldoc.saveFile(options.outfile)

41 changes: 40 additions & 1 deletion sample-configs/conf2http.cfg
@@ -1,16 +1,55 @@
; Lines starting with "#" are defaults

[server]
; ### ip (0.0.0.0) ###
; IP to bind server
#ip: 0.0.0.0

; ### port (15666) ###
; Port to bind server
#port: 15666

; ### ssl (false) ###
; Use SSL for server communication
#ssl: false
#sslcert: server.pem

; ### sslcert (no default) ###
; Read server key and certificate from this file
;
; Example
;sslcert: server.pem

; ### conf_dir (no default) ###
; Directory where your config files are stored
;
; Absolute file names recommended, but for quick start it is set relative
; to the source directory
conf_dir: ./sample-configs/conf

; ### pidfile (/var/run/nagixsc_conf2http.pid) ###
; Where to store pid file if daemonizing
;
#pidfile: /var/run/nagixsc_conf2http.pid

; ### livestatus_socket (no default) ###
; Query mk-livestatus (http://mathias-kettner.de/checkmk_livestatus.html)
; "livestatus_socket" could be
; - local path and filename of socket ("/var/lib/nagios3/rw/live.sock")
; - IPv4 address and port ("127.0.0.1:6557")
; - IPv6 address and port ("[::1]:6557" or "::1:6557")
; - DNS resolvable name and port ("localhost:6557") - could be IPv4 *or* IPv6!
;
; Examples:
;livestatus_socket: /var/lib/nagios3/rw/live.sock
;livestatus_socket: /usr/local/nagios/var/rw/live
;livestatus_socket: 127.0.0.1:6557
;livestatus_socket: [::1]:6557
;livestatus_socket: localhost:6557
livestatus_socket: 172.21.254.99:6557

[users]
; All users who are allowed to connect and request informations are stored here.
; Passwords must be md5 encrypted, for example in shell use:
; echo -n "Password" | md5sum -
nagixsc: 019b0966d98fb71d1a4bc4ca0c81d5cc ; PW: nagixsc

0 comments on commit 779ef24

Please sign in to comment.