Skip to content

Instantly share code, notes, and snippets.

@yyuu
Created April 6, 2012 16:00
Show Gist options
  • Select an option

  • Save yyuu/2321002 to your computer and use it in GitHub Desktop.

Select an option

Save yyuu/2321002 to your computer and use it in GitHub Desktop.
mon monitor plugin to test http service
#!/usr/bin/env python
#
# pyhttp.monitor - mon monitor plugin to test http service
#
from __future__ import with_statement
import inspect
import logging
import optparse
import os
import re
import sys
import urllib2
import urlparse
class InvalidResponseError(Exception):
pass
def urlopen(url, data=None, timeout=None):
argspec = inspect.getargspec(urllib2.urlopen)
if len(argspec[0]) == 2: # urllib2 prior than py2.5 doesn't have urllib2.urlopen/3
return urllib2.urlopen(url, data)
else:
return urllib2.urlopen(url, data, timeout)
def main(args):
parser = optparse.OptionParser("usage %prog [OPTIONS]", add_help_option=False)
parser.add_option('-a', '--user-agent', default='mon.d/pyhttp.monitor', dest='user_agent', help='User-Agent, default to "mon.d/pyhttp.monitor"')
parser.add_option('-H', '--header-expects', default=[], action='append', dest='header_expects', help='match regex in response header')
parser.add_option('--help', action='help', help='show this message and exit.')
parser.add_option('-m', '--expects', default=[], action='append', dest='expects', help='match regex in response body')
parser.add_option('-p', '--port', type='int', default=[], action='append', dest='ports', help='TCP port to connect to (default to 80)')
parser.add_option('--proto', default=[], action='append', dest='protos', help='application layer protocol to use')
parser.add_option('-t', '--timeout', type='int', default=None, dest='timeout', help='timeout')
parser.add_option('-u', '--url', default='/', dest='path', help='path to get, default to "/"')
parser.add_option('-v', '--verbose', default=False, action='store_true', dest='verbose', help='show verbose message.')
(options, args) = parser.parse_args(args)
if options.verbose:
logging.basicConfig(level=logging.DEBUG)
protos = [ proto.lower() for proto in options.protos ] if 0 < len(options.protos) else [ 'http' ]
if 0 < len(options.ports):
ports = options.ports
else:
ports = []
if 'http' in protos:
ports.append(80)
if 'https' in protos:
ports.append(443)
f = 0
for scheme, host, port in [ (s, h, p) for s in protos for h in args[1:] for p in ports ]:
url = urlparse.urlunparse((scheme, "%s:%d" % (host, port), options.path, '', '', ''))
client = None
try:
client = urlopen(url, None, options.timeout)
got = client.read()
logging.debug("%s: got response body (%d bytes)" % (url, len(got)))
for expects in options.expects:
if re.search(expects, got, re.IGNORECASE | re.MULTILINE):
logging.debug("%s: response body (%d bytes) matched to %s." % (url, len(got), repr(expects)))
else:
raise(InvalidResponseError("%s: response body (%d bytes) not matched to %s" % (url, len(got), repr(expects))))
for header_expects in options.header_expects:
if header_expects.find('=') < 0:
expected_key, expected_value = header_expects, None
else:
expected_key, expected_value = header_expects.split('=', 2)
got_value = client.headers.getheader(expected_key, None)
if got_value:
logging.debug("%s: response header %s exists." % (url, repr(expected_key)))
if expected_value and re.search(expected_value, got_value, re.IGNORECASE | re.MULTILINE):
logging.debug("%s: response header %s (%d bytes) matched to %s." % (url, repr(expected_key), len(got_value), repr(expected_value)))
else:
raise(InvalidResponseError("%s: response header %s (%d bytes) not matched to %s" % (url, repr(expected_key), len(got_value), repr(expected_value))))
else:
raise(InvalidResponseError("%s: response header %s does not exist" % (url, repr(expected_key))))
except (InvalidResponseError, urllib2.URLError), error:
logging.error("%s: got an error: %s" % (url, error))
f += 1
finally:
if client:
client.close()
sys.exit(0 if f == 0 else 1)
if __name__ == "__main__":
main(sys.argv)
# vim:set ft=python :
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment