mirror of
https://github.com/ranl/monitor-utils.git
synced 2024-11-21 15:13:41 +01:00
activemq nagios plugin
This commit is contained in:
parent
6b08f8accc
commit
9c4860049d
268
nagios/check_activemq.py
Executable file
268
nagios/check_activemq.py
Executable file
@ -0,0 +1,268 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Monitor ActiveMQ server via its http web interface
|
||||
'''
|
||||
|
||||
from HTMLParser import HTMLParser
|
||||
from optparse import OptionParser
|
||||
import xml.etree.ElementTree as ET
|
||||
import json
|
||||
import urllib2
|
||||
import urllib
|
||||
|
||||
EXIT_CODE = {
|
||||
'OK': 0,
|
||||
'WARN': 1,
|
||||
'CRIT': 2,
|
||||
'UNKNOWN': 3,
|
||||
}
|
||||
|
||||
def prepareOpts():
|
||||
'''
|
||||
Parse options from the shell
|
||||
'''
|
||||
|
||||
cmds = {
|
||||
'queues' : 'notify if there is a least one queue with no consumers (--exlcude)',
|
||||
'consumer': 'notify if the specific consumers does not consume the queues (--queues, --client)',
|
||||
}
|
||||
def err( string ):
|
||||
print 'Error: {0}'.format( string )
|
||||
parser.print_help()
|
||||
print __doc__
|
||||
exit(1)
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option('-H', '--server', dest='server', type='string', help='ActiveMQ fqdn or ip', default='localhost')
|
||||
parser.add_option('-U', '--user', dest='user', type='string', help='http username', default=None)
|
||||
parser.add_option('-P', '--password', dest='password', type='string', help='http password', default=None)
|
||||
parser.add_option('-p', '--port', dest='port', type='int', help='ActiveMQ web interface port', default=8161)
|
||||
parser.add_option('-t', '--timeout', dest='timeout', type='float', help='how many seconds to wait for each http request', default=5)
|
||||
parser.add_option('-T', '--type', dest='type', type='choice', choices=cmds.keys(), help='what to check: {0}'.format(cmds.keys()) )
|
||||
parser.add_option('-e', '--exclude', dest='exclude', type='string', help='csv list of queues to exclude (implies -T queues)', default=None )
|
||||
parser.add_option('-q', '--queues', dest='queues', type='string', help='csv list of queues (implies -T consumer)', default=None)
|
||||
parser.add_option('-c', '--client', dest='client', type='string', help='the client prefix to search (implies -T consumer)', default=None )
|
||||
(opts, args) = parser.parse_args()
|
||||
|
||||
kargs = {}
|
||||
|
||||
if opts.user is None and opts.password is not None:
|
||||
err('missing -P')
|
||||
elif opts.password is None and opts.user is not None:
|
||||
err('missing -U')
|
||||
|
||||
if not opts.type:
|
||||
err('missing -T')
|
||||
elif opts.type == 'consumer':
|
||||
if opts.client is None:
|
||||
err('missing -c')
|
||||
if opts.queues is None:
|
||||
err('missing -q')
|
||||
else:
|
||||
kargs.update({'queues': opts.queues.split(',')})
|
||||
kargs.update({'client': opts.client})
|
||||
elif opts.exclude is not None:
|
||||
kargs.update({'exclude': opts.exclude.split(',')})
|
||||
|
||||
|
||||
return (opts, kargs)
|
||||
|
||||
class AmqException(Exception):
|
||||
def __init__(self, msg, xcode):
|
||||
self.msg = msg
|
||||
self.xcode = xcode
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
def getXcode(self):
|
||||
return self.xcode
|
||||
def getMsg(self):
|
||||
return self.msg
|
||||
|
||||
class ConsumerHTMLParser(HTMLParser):
|
||||
'''
|
||||
Parse the consumers id from http://url/admin/queueConsumers.jsp?JMSDestination=QUEUENAME
|
||||
'''
|
||||
|
||||
consumers = []
|
||||
table = False
|
||||
body = False
|
||||
tr = False
|
||||
td = False
|
||||
a = False
|
||||
|
||||
def reset_vars(self):
|
||||
self.consumers = []
|
||||
self.table = False
|
||||
self.body = False
|
||||
self.tr = False
|
||||
self.td = False
|
||||
self.a = False
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if self.td and tag == 'a':
|
||||
self.a = True
|
||||
elif self.tr and tag == 'td':
|
||||
self.td = True
|
||||
elif self.body and tag == 'tr':
|
||||
self.tr = True
|
||||
elif self.table and tag == 'tbody':
|
||||
self.body = True
|
||||
elif tag == 'table':
|
||||
self.table = ('id', 'messages') in attrs
|
||||
|
||||
def handle_data(self, data):
|
||||
if self.a:
|
||||
if not data in self.consumers:
|
||||
self.consumers.append( data )
|
||||
self.a = False
|
||||
self.td = False
|
||||
self.tr = False
|
||||
|
||||
def get_consumers(self):
|
||||
return self.consumers
|
||||
|
||||
class ActivemqMonitor():
|
||||
'''
|
||||
Monitor ActiveMQ via http web interface
|
||||
'''
|
||||
|
||||
def __init__(self, server, port, timeout, user=None, password=None, realm='ActiveMQRealm'):
|
||||
self.url = 'http://{0}:{1}'.format(server, port)
|
||||
self.server = server
|
||||
self.port = port
|
||||
self.timeout = timeout
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.realm = realm
|
||||
if user is not None and password is not None:
|
||||
urllib2.install_opener(
|
||||
self._auth(
|
||||
self.url, self.user, self.password, self.realm
|
||||
)
|
||||
)
|
||||
|
||||
def _auth(self, uri, user, password, realm):
|
||||
'''
|
||||
returns a authentication handler.
|
||||
'''
|
||||
|
||||
basic = urllib2.HTTPBasicAuthHandler()
|
||||
basic.add_password(
|
||||
realm=realm, uri=uri, user=user, passwd=password
|
||||
)
|
||||
digest = urllib2.HTTPDigestAuthHandler()
|
||||
digest.add_password(
|
||||
realm=realm, uri=uri, user=user, passwd=password
|
||||
)
|
||||
|
||||
return urllib2.build_opener(basic, digest)
|
||||
|
||||
def _wget(self, url):
|
||||
'''
|
||||
create the http request to AMQ web UI
|
||||
'''
|
||||
|
||||
try:
|
||||
ret = urllib2.urlopen(url, timeout=self.timeout).read()
|
||||
except urllib2.URLError:
|
||||
raise AmqException(
|
||||
'UNKNOWN: Could not create http request to ActiveMQ',
|
||||
EXIT_CODE['UNKNOWN']
|
||||
)
|
||||
|
||||
return ret
|
||||
|
||||
def _getQueueConsumers(self, queue, parser):
|
||||
'''
|
||||
Get the parsed data of the queue
|
||||
'''
|
||||
|
||||
url = '{0}/admin/queueConsumers.jsp?{1}'.format(
|
||||
self.url,
|
||||
urllib.urlencode( { 'JMSDestination': queue } ),
|
||||
)
|
||||
parser.reset_vars()
|
||||
parser.feed( self._wget(url) )
|
||||
return parser.get_consumers()
|
||||
|
||||
def _eval_queues(self, res, opts):
|
||||
if res:
|
||||
return {
|
||||
'msg': 'CRIT: the following queues are not consumed {0}'.format(','.join(res)),
|
||||
'exit': EXIT_CODE['CRIT']
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'msg': 'OK: All the queues are consumed',
|
||||
'exit': EXIT_CODE['OK']
|
||||
}
|
||||
|
||||
def _eval_consumer(self, res, opts):
|
||||
if res:
|
||||
return {
|
||||
'msg': 'CRIT: the following queues are not consumed by {0} {1}'.format(
|
||||
opts.client, ','.join(res)
|
||||
),
|
||||
'exit': EXIT_CODE['CRIT']
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'msg': 'OK: {0} is consuming all of its queues'.format(opts.client),
|
||||
'exit': EXIT_CODE['OK']
|
||||
}
|
||||
|
||||
def queues(self, exclude=[]):
|
||||
'''
|
||||
return all the queues with zero consumers
|
||||
'''
|
||||
errors = []
|
||||
url = '{0}/admin/xml/queues.jsp'.format(self.url, )
|
||||
html = self._wget(url)
|
||||
for q in ET.fromstring( html ).findall('queue'):
|
||||
if q.get('name') not in exclude and int(q.find('stats').get('consumerCount')) <= 0:
|
||||
errors.append(q.get('name'))
|
||||
|
||||
return errors
|
||||
|
||||
def consumer(self, client, queues):
|
||||
'''
|
||||
check if the clientid is configured as a subscriber on the queue
|
||||
'''
|
||||
|
||||
missing = list(queues)
|
||||
parser = ConsumerHTMLParser()
|
||||
for queue in queues:
|
||||
for consumer in self._getQueueConsumers(queue, parser):
|
||||
if client in consumer:
|
||||
missing.remove(queue)
|
||||
break
|
||||
|
||||
return missing
|
||||
|
||||
@staticmethod
|
||||
def main():
|
||||
'''
|
||||
Main function
|
||||
'''
|
||||
(opts, kargs) = prepareOpts()
|
||||
amq = ActivemqMonitor(
|
||||
opts.server, opts.port, opts.timeout, opts.user, opts.password
|
||||
)
|
||||
|
||||
method = getattr(amq, opts.type)
|
||||
try:
|
||||
res = method(**kargs)
|
||||
except AmqException as e:
|
||||
print e.getMsg()
|
||||
exit(e.getXcode())
|
||||
|
||||
eval_method = getattr(
|
||||
amq, '_eval_{0}'.format(opts.type)
|
||||
)
|
||||
ret = eval_method(res, opts)
|
||||
print ret['msg']
|
||||
exit(ret['exit'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
ActivemqMonitor.main()
|
@ -60,36 +60,36 @@ class ConsumerHTMLParser(HTMLParser):
|
||||
a = False
|
||||
|
||||
def reset_vars(self):
|
||||
ConsumerHTMLParser.consumers = []
|
||||
ConsumerHTMLParser.table = False
|
||||
ConsumerHTMLParser.body = False
|
||||
ConsumerHTMLParser.tr = False
|
||||
ConsumerHTMLParser.td = False
|
||||
ConsumerHTMLParser.a = False
|
||||
self.consumers = []
|
||||
self.table = False
|
||||
self.body = False
|
||||
self.tr = False
|
||||
self.td = False
|
||||
self.a = False
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if ConsumerHTMLParser.td and tag == 'a':
|
||||
ConsumerHTMLParser.a = True
|
||||
elif ConsumerHTMLParser.tr and tag == 'td':
|
||||
ConsumerHTMLParser.td = True
|
||||
elif ConsumerHTMLParser.body and tag == 'tr':
|
||||
ConsumerHTMLParser.tr = True
|
||||
elif ConsumerHTMLParser.table and tag == 'tbody':
|
||||
ConsumerHTMLParser.body = True
|
||||
if self.td and tag == 'a':
|
||||
self.a = True
|
||||
elif self.tr and tag == 'td':
|
||||
self.td = True
|
||||
elif self.body and tag == 'tr':
|
||||
self.tr = True
|
||||
elif self.table and tag == 'tbody':
|
||||
self.body = True
|
||||
elif tag == 'table':
|
||||
ConsumerHTMLParser.table = ('id', 'messages') in attrs
|
||||
self.table = ('id', 'messages') in attrs
|
||||
|
||||
def handle_data(self, data):
|
||||
if ConsumerHTMLParser.a:
|
||||
if self.a:
|
||||
tmp = data.split('-')[0]
|
||||
if not tmp in ConsumerHTMLParser.consumers:
|
||||
ConsumerHTMLParser.consumers.append( tmp )
|
||||
ConsumerHTMLParser.a = False
|
||||
ConsumerHTMLParser.td = False
|
||||
ConsumerHTMLParser.tr = False
|
||||
if not tmp in self.consumers:
|
||||
self.consumers.append( tmp )
|
||||
self.a = False
|
||||
self.td = False
|
||||
self.tr = False
|
||||
|
||||
def get_consumers(self):
|
||||
return ConsumerHTMLParser.consumers
|
||||
return self.consumers
|
||||
|
||||
|
||||
class ActivemqMonitor():
|
||||
|
Loading…
Reference in New Issue
Block a user