[checkmk-commits] Check_MK Git: check_mk: Added multiple host mode to check_form_submit active check

Lars Michelsen lm at mathias-kettner.de
Thu Sep 12 12:03:40 CEST 2013


Module: check_mk
Branch: master
Commit: c4b450049f8c963587de6dcc78aa9cc9a3ea52fe
URL:    http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=c4b450049f8c963587de6dcc78aa9cc9a3ea52fe

Author: Lars Michelsen <lm at mathias-kettner.de>
Date:   Thu Sep 12 12:03:22 2013 +0200

Added multiple host mode to check_form_submit active check

---

 doc/treasures/active_checks/check_form_submit |  141 +++++++++++++++++--------
 1 file changed, 96 insertions(+), 45 deletions(-)

diff --git a/doc/treasures/active_checks/check_form_submit b/doc/treasures/active_checks/check_form_submit
index ac6c23a..dcd3858 100755
--- a/doc/treasures/active_checks/check_form_submit
+++ b/doc/treasures/active_checks/check_form_submit
@@ -54,9 +54,12 @@ def usage():
     sys.stderr.write("""
 USAGE: check_form_submit -I <HOSTADDRESS> [-u <URI>] [-p <PORT>] [-s] [-H <VHOST>]
             [-f <FORMNAME>] [-q <QUERYPARAMS>] [-e <REGEX>] [-t <TIMEOUT> ]
+            [-n <WARN>,<CRIT>]
 
 OPTIONS:
-  -I HOSTADDRESS                The IP address or hostname of the host to contact
+  -I HOSTADDRESS                The IP address or hostname of the host to contact.
+                                This option can be given multiple times to contact
+                                several hosts with the same query.
   -u URI                        The URL string to query, "/" by default
   -p PORT                       TCP Port to communicate with
   -s                            Encrypt the connection using SSL
@@ -67,12 +70,14 @@ OPTIONS:
   -e REGEX                      Expected regular expression in the HTML response
                                 after form submission
   -t TIMEOUT                    HTTP connect timeout in seconds
+  -n WARN,CRIT                  Is only used in "multiple" mode. Number of successful
+                                responses to result in a WARN and/or CRIT state
   -d                            Enable debug mode
   -h, --help                    Show this help message and exit
 
 """)
 
-short_options = 'I:u:p:H:f:q:e:t:sd'
+short_options = 'I:u:p:H:f:q:e:t:n:sd'
 
 try:
     opts, args = getopt.getopt(sys.argv[1:], short_options)
@@ -80,7 +85,8 @@ except getopt.GetoptError, err:
     sys.stderr.write("%s\n" % err)
     sys.exit(1)
 
-host         = None
+hosts        = []
+multiple     = False
 uri          = '/'
 port         = 80
 ssl          = False
@@ -90,13 +96,15 @@ params       = {}
 expect_regex = None
 opt_debug    = False
 timeout      = 10 # seconds
+num_warn     = None
+num_crit     = None
 
 for o,a in opts:
     if o == '-h':
         usage()
         sys.exit(0)
     elif o == '-I':
-    	host = a
+        hosts.append(a)
     elif o == '-u':
         uri = a
     elif o == '-p':
@@ -113,14 +121,22 @@ for o,a in opts:
         expect_regex = a
     elif o == '-t':
         timeout = int(a)
+    elif o == '-n':
+        if ',' in a:
+            num_warn, num_crit = map(int, a.split(',', 1))
+        else:
+            num_warn = int(a)
     elif o == '-d':
         opt_debug = True
 
-if host is None:
+if not hosts:
     sys.stderr.write('Please provide the host to query via -I <HOSTADDRESS>.\n')
     usage()
     sys.exit(1)
 
+if len(hosts) > 1:
+    multiple = True
+
 if not ssl and port == 443:
     ssl = True
 
@@ -128,6 +144,16 @@ def debug(s):
     if opt_debug:
         sys.stderr.write('%s\n' % s)
 
+class HostResult():
+    def __init__(self, result):
+        self.result = result
+
+def new_state(rc, s):
+    if multiple:
+        raise HostResult((rc, s))
+    else:
+        bail_out(rc, s)
+
 def bail_out(rc, s):
     stxt = ['OK', 'WARN', 'CRIT', 'UNKN'][rc]
     sys.stdout.write('%s - %s\n' % (stxt, s))
@@ -139,11 +165,9 @@ if (proto == 'http' and port == 80) or (proto == 'https' and port == 443):
 else:
     portspec = ':%d' % port
 
-def get_full_uri(uri):
+def get_full_uri(host, uri):
     return '%s://%s%s%s' % (proto, host, portspec, uri)
 
-url = get_full_uri(uri)
-
 def init_http():
     global g_cookies, g_opener
     import urllib2
@@ -173,9 +197,9 @@ def open_url(url, method = 'GET', data = None):
             debug('GET %s' % url)
             fd = g_opener.open(url, timeout = timeout) # GET
     except urllib2.HTTPError, e:
-        bail_out(2, 'Unable to open %s: [%d] %s' % (url, e.code, e.reason))
+        new_state(2, 'Unable to open %s: [%d] %s' % (url, e.code, e.reason))
     except urllib2.URLError, e:
-        bail_out(2, 'Unable to open %s: %s' % (url, e.reason))
+        new_state(2, 'Unable to open %s: %s' % (url, e.reason))
     real_url = fd.geturl()
     code     = fd.getcode()
     content  = fd.read()
@@ -223,23 +247,23 @@ def parse_form(content):
     num_forms = len(forms)
 
     if num_forms == 0:
-        bail_out(2, 'Found no form element in HTML code')
+        new_state(2, 'Found no form element in HTML code')
 
     elif num_forms == 1 and form_name is not None and form_name in forms:
-        bail_out(2, 'Found one form with name "%s" but expected name "%s"' %
+        new_state(2, 'Found one form with name "%s" but expected name "%s"' %
                                           (forms.keys()[0], form_name))
 
     elif num_forms == 1:
         form = forms[forms.keys()[0]]
 
     elif form_name is None:
-        bail_out(2, 'No form name provided but found multiple forms (Names: %s)' %
+        new_state(2, 'No form name provided but found multiple forms (Names: %s)' %
             (', '.join([ f for f in forms.keys() ])))
 
     else:
         form = forms.get(form_name)
         if form is None:
-            bail_out(2, 'Found no form with name "%s" (Available: %s)' %
+            new_state(2, 'Found no form with name "%s" (Available: %s)' %
                 (form_name, ', '.join([ f for f in forms.keys() ])))
 
     return form
@@ -252,37 +276,64 @@ def update_form_vars(form):
 try:
     init_http()
 
-    # Perform first HTTP request to fetch the page containing the form(s)
-    code, real_url, content = open_url(url)
-
-    form = parse_form(content)
-
-    # Get all fields and prefilled values from that form
-    # Put the values of the given query params in these forms
-    form_vars = update_form_vars(form)
-
-    # Issue a HTTP request with those parameters
-    # Extract the form target and method
-    method = form['attrs'].get('method', 'GET')
-    target = form['attrs'].get('action', real_url)
-    if target[0] == '/':
-        # target is given as absolute path, relative to hostname
-        target = get_full_uri(target)
-    elif target[0] != '':
-        # relative URL
-        target = '%s/%s' % ('/'.join(real_url.rstrip('/').split('/')[:-1]), target)
-
-    code, real_url, content = open_url(target, method, form_vars)
-
-    # If a expect_regex is given, check wether or not it is present in the response
-    if expect_regex is not None:
-        matches = re.search(expect_regex, content)
-        if matches is not None:
-            bail_out(0, 'Found expected regex "%s" in form response' % expect_regex)
-        else:
-            bail_out(2, 'Expected regex "%s" could not be found in form response' % expect_regex)
-    else:
-        bail_out(0, 'Form has been submitted')
+    states = {}
+    for host in hosts:
+        try:
+            # Perform first HTTP request to fetch the page containing the form(s)
+            url = get_full_uri(host, uri)
+            code, real_url, content = open_url(url)
+
+            form = parse_form(content)
+
+            # Get all fields and prefilled values from that form
+            # Put the values of the given query params in these forms
+            form_vars = update_form_vars(form)
+
+            # Issue a HTTP request with those parameters
+            # Extract the form target and method
+            method = form['attrs'].get('method', 'GET')
+            target = form['attrs'].get('action', real_url)
+            if target[0] == '/':
+                # target is given as absolute path, relative to hostname
+                target = get_full_uri(host, target)
+            elif target[0] != '':
+                # relative URL
+                target = '%s/%s' % ('/'.join(real_url.rstrip('/').split('/')[:-1]), target)
+
+            code, real_url, content = open_url(target, method, form_vars)
+
+            # If a expect_regex is given, check wether or not it is present in the response
+            if expect_regex is not None:
+                matches = re.search(expect_regex, content)
+                if matches is not None:
+                    new_state(0, 'Found expected regex "%s" in form response' % expect_regex)
+                else:
+                    new_state(2, 'Expected regex "%s" could not be found in form response' % expect_regex)
+            else:
+                new_state(0, 'Form has been submitted')
+        except HostResult, e:
+            states[host] = e.result
+
+    if multiple:
+        failed  = [ pair for pair in states.items() if pair[1][0] != 0 ]
+        success = [ pair for pair in states.items() if pair[1][0] == 0 ]
+        max_state   = max([ state for state, output in states.values() ])
+
+        sum_state = 0
+        if num_warn is None and num_crit is None:
+            # use the worst state as summary state
+            sum_state = max_state
+
+        elif num_crit is not None and len(failed) >= num_crit:
+            sum_state = 2
+
+        elif num_warn is not None and len(failed) >= num_warn:
+            sum_state = 1
+
+        txt = '%d succeeded, %d failed' % (len(success), len(failed))
+        if failed:
+            txt += ' (%s)' % ', '.join([ '%s: %s' % (n, s[1]) for n, s in failed ])
+        bail_out(sum_state, txt)
 
 except Exception, e:
     if opt_debug:



More information about the checkmk-commits mailing list