home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.ee.lbl.gov
/
2014.05.ftp.ee.lbl.gov.tar
/
ftp.ee.lbl.gov
/
acld-1.11.tar.gz
/
acld-1.11.tar
/
acld-1.11
/
check_acld.py.in
< prev
next >
Wrap
Text File
|
2011-10-06
|
9KB
|
363 lines
#!@PYTHON@
"""check_acld - nagios plugin for acld"""
# @(#) $Id: check_acld.py.in 792 2011-10-06 21:47:07Z leres $ (LBL)
#
# Copyright (c) 2011
# The Regents of the University of California. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that: (1) source code distributions
# retain the above copyright notice and this paragraph in its entirety, (2)
# distributions including binary code include the above copyright notice and
# this paragraph in its entirety in the documentation or other materials
# provided with the distribution, and (3) all advertising materials mentioning
# features or use of this software display the following acknowledgement:
# ``This product includes software developed by the University of California,
# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
# the University nor the names of its contributors may be used to endorse
# or promote products derived from this software without specific prior
# written permission.
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
import optparse
import os
import re
import subprocess
import sys
OPTS = None
PROG = '?'
ACLDBIN = '@PREFIX@/libexec'
STR2STATUS = {
'OK': 0,
'WARNING': 1,
'CRITICAL': 2,
'UNKNOWN': 3,
}
STATUS2STR = {
0: 'OK',
1: 'WARNING',
2: 'CRITICAL',
3: 'UNKNOWN',
}
# Adjust our path
pathstr = 'PATH'
if not ACLDBIN in os.environ[pathstr].split(':'):
os.environ[pathstr] = '%s:%s' % (ACLDBIN, os.environ[pathstr])
def checkdroprestore(data):
"""Test drop/restore"""
results = []
addrs = data['args']
for addr in addrs:
result = None
for what in ['drop', 'restore']:
data['sout'] = ''
data['serr'] = ''
runacl(data, [what, addr])
if data['code'] != 0:
data['status'] = STR2STATUS['CRITICAL']
result = '%s-%s!' % (what, addr)
break
if result:
results.append(result)
elif OPTS.verbose > 0:
results.append(addr)
if results == []:
results.append('OK')
prefix = ', test drop/restore'
if len(addrs) != 1:
prefix += 's'
prefix += ': '
data['msg'] += prefix + ' '.join(results)
def checkfull(data):
"""Check if the acl is too full"""
pct = OPTS.fullpct
re_hiwater = re.compile(r'\A# hiwater for ACL (\S+) is (\d+)\Z')
re_limit = re.compile(r'\Alimit (\d+) (.+)\Z')
hiwaters = {}
limits = []
for line in data['sout'].split('\n'):
m = re_hiwater.search(line)
if m != None:
hiwaters[m.group(1)] = int(m.group(2))
continue
m = re_limit.search(line)
if m != None:
# List of ACL names followed by limit value
limits.append([m.group(2).split(), int(m.group(1))])
continue
results = []
for (acls, limit) in limits:
hiwater = 0
# Sum
for acl in acls:
hiwater += hiwaters[acl]
if limit <= 0:
val = 0
else:
val = (100 * hiwater) / limit
result = '%s=%d%%' % ('+'.join(acls), val)
if val >= pct:
result += '!'
data['status'] = STR2STATUS['CRITICAL']
results.append(result)
elif OPTS.verbose > 0:
results.append(result)
if results == []:
results.append('OK')
data['msg'] += ', hiwater PCTs: ' + ' '.join(results)
def checkrate(data):
"""Check if the add rate is ok"""
rate = OPTS.rate
re_rate = re.compile(r'\A# rate for ACL (\S+) is (\d+) acl/min\Z')
acls = {}
for line in data['sout'].split('\n'):
m = re_rate.search(line)
if m == None:
continue
acls[m.group(1)] = int(m.group(2))
keys = acls.keys()
keys.sort()
results = []
for key in acls:
val = acls[key]
result = '%s=%d' % (key, val)
if val >= rate:
result += '!'
data['status'] = STR2STATUS['CRITICAL']
results.append(result)
elif OPTS.verbose > 0:
results.append(result)
if results == []:
results.append('OK')
else:
results[-1] += ' acl/min'
data['msg'] += ', drop rates: ' + ' '.join(results)
def checkseq(data):
"""Check if any ACLs have high sequence numbers"""
pct = OPTS.seqpct
m = re.search(r'^seqrange (\d+) (\d+)\n', data['sout'], re.MULTILINE)
if m == None:
data['status'] = STR2STATUS['UNKNOWN']
data['msg'] += " Can't find seqrange"
return
seqrange = (int(m.group(1)), int(m.group(2)))
size = seqrange[1] - seqrange[0]
if size < 0:
data['status'] = STR2STATUS['UNKNOWN']
data['msg'] += " Can't figure out seqrange size"
return
re_lastseq = re.compile(r'\A# lastseq for ACL (\S+) is (\d+)\Z')
lines = data['sout'].split('\n')
results = []
for line in lines:
m = re_lastseq.search(line)
if m == None:
continue
acl = m.group(1)
lastseq = int(m.group(2))
n = lastseq - seqrange[0]
if n < 0:
n = 0
val = (100 * n) / size
result = '%s=%d%%' % (acl, val)
if val >= pct:
result += '!'
data['status'] = STR2STATUS['CRITICAL']
results.append(result)
elif OPTS.verbose > 0:
results.append(result)
if results == []:
results.append('OK')
data['msg'] += ', sequence number PCTs: ' + ' '.join(results)
def checkstate(data):
"""Check if the state is ok, return a dict containing information"""
# Extract host
m = re.search(r'^# host (.+)\n', data['sout'], re.MULTILINE)
if m == None:
data['status'] = STR2STATUS['UNKNOWN']
data['msg'] += "Can't determine acld host"
return
data['host'] = m.group(1)
# Extract state
m = re.search(r'^# state (.+)\n', data['sout'], re.MULTILINE)
if m == None:
data['status'] = STR2STATUS['UNKNOWN']
data['msg'] += "can't find state"
return
data['state'] = m.group(1)
if data['state'] != 'loggedin':
data['status'] = STR2STATUS['CRITICAL']
data['msg'] += 'acld on %s not logged in' % (data['host'])
else:
data['msg'] += 'acld on %s logged in and ready' % (data['host'])
def reportandexit(data):
"""Produce the nagios report and then exit with the appropriate code"""
status = data['status']
print '%s: %s' % (STATUS2STR[status], data['msg'])
return status
def runacl(data, args):
"""Check the status of an acl result"""
cmd = ['acl.exp' ]
# Set up environment
if OPTS.addr:
estr = 'ACLIPADDR'
if estr in os.environ:
oldaddrenv = os.environ[estr]
else:
oldaddrenv = None
os.environ[estr] = OPTS.addr
if OPTS.port:
estr = 'ACLPORT'
if estr in os.environ:
oldportenv = os.environ[estr]
else:
oldportenv = None
os.environ[estr] = unicode(OPTS.port)
cmd.extend(args)
try:
child = subprocess.Popen(cmd,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError, e:
data['code'] = 1
data['msg'] += '%s: %s' % (cmd[0], e.strerror)
finally:
# Child I/O
(data['sout'], data['serr']) = child.communicate()
data['code'] = child.returncode
# Restore environment
if OPTS.addr:
estr = 'ACLIPADDR'
if oldaddrenv != None:
os.environ[estr] = oldaddrenv
else:
del os.environ[estr]
if OPTS.port:
estr = 'ACLPORT'
if oldportenv != None:
os.environ[estr] = oldportenv
else:
del os.environ[estr]
def main(argv=sys.argv):
"""Main program"""
global OPTS
global PROG
PROG = os.path.basename(argv[0])
usage = [
'usage: %prog [-v] [-a addr] [-p port] [-u user] [-R rate]'
' [-H hiwaterpct] [-F fullpct] [addr ...]',
]
version = '$Revision: 792 $'.lstrip('$').rstrip('$')
parser = optparse.OptionParser(usage='\n'.join(usage), version=version)
parser.add_option('-v', None,
action='count', dest='verbose', default=0,
help='increase verbosity')
parser.add_option('-a', None,
action='store', dest='addr',
help='IP address of acld')
parser.add_option('-p', None,
action='store', dest='port', type='int',
help='TCP port of acld')
parser.add_option('-u', None,
action='store', dest='user', default=None,
help='USER to log requests as')
parser.add_option('-R', None,
action='store', dest='rate', default=None, type='int',
help='ACL drop rate to report critical')
parser.add_option('-F', None,
action='store', dest='fullpct', default=None, type='int',
help='ACL percentage used to report critical')
parser.add_option('-H', None,
action='store', dest='seqpct', default=None, type='int',
help='lastseq in use percentage to report critical')
(OPTS, args) = parser.parse_args()
data = {
'args': args,
'code': -1,
'msg': '',
'serr': '',
'sout': '',
'status': STR2STATUS['OK'],
}
# Optionally set the user these requests are always done on behalf of
if OPTS.user != None:
os.environ['USER'] = OPTS.user
runacl(data, ['state'])
if data['code'] != 0:
data['status'] = STR2STATUS['UNKNOWN']
if data['msg'] == '':
data['msg'] = 'acl.exp state failed'
return reportandexit(data)
# Are we logged in?
checkstate(data)
# Are any drop rates too high?
if OPTS.rate != None:
checkrate(data)
# Are any ACL lists getting to full?
if OPTS.fullpct != None:
checkfull(data)
# Are any sequence numbers getting to high?
if OPTS.seqpct != None:
checkseq(data)
# Are any drop rates too high (run this test last)
if OPTS.seqpct:
checkdroprestore(data)
# That's all, folks!
return reportandexit(data)
if __name__ == "__main__":
sys.exit(main())