Changeset 5319


Ignore:
Timestamp:
05/30/14 16:02:32 (10 years ago)
Author:
Sander Maijers
Message:
  • Recommit last working revision of this file.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • monitoring/plugins/mpi/generic_tla_monitoring.py

    r5318 r5319  
     1#!/usr/bin/python2
     2
     3import sys, getopt, httplib, xml.etree.ElementTree, subprocess, re, pdb, traceback, datetime, urlparse, urllib
     4import simplejson as json
     5import pwd, os
     6
     7nagios_codes    = {
     8                    'OK'        : 0,
     9                    'WARNING'   : 1,
     10                    'CRITICAL'  : 2,
     11                    'UNKNOWN'   : 3,
     12                    'DEPENDENT' : 4
     13                    }
     14
     15def nagios_return(code, response) :
     16    """ prints the response message
     17        and exits the script with one
     18        of the defined exit codes
     19        DOES NOT RETURN
     20    """
     21    print code + ": " + response
     22    sys.exit(nagios_codes[code])
     23
     24def nagios_return_complex(results, reporter) :
     25    def deal_with_result(result, reporter) :
     26        print "[" + reporter + "] " + result['code'] + ": " + result['message']
     27        return result['code']
     28
     29    #pdb.set_trace()
     30
     31    # Scan all condition/status check results and create a list of appropriate exit codes.
     32    exit_code_keys          = map(lambda result     : deal_with_result(result, reporter), results)
     33    suggested_exit_codes    = list(map(lambda key   : nagios_codes[key], exit_code_keys))
     34
     35    # Exit with the highest suggested exit code, because the higher the exit code the more problematic the status is and problems have priority over harmony.
     36    sys.exit(max(suggested_exit_codes))
     37
     38def usage(command_line_parameters_usage_string) :
     39    """ returns Nagios status UNKNOWN with
     40        a one line usage description
     41        usage() calls nagios_return()
     42    """
     43    nagios_return('UNKNOWN',
     44                  "command line usage: \n" + sys.argv[0] + command_line_parameters_usage_string)
     45
     46def generic_validator(data,
     47                      descriptive_string,
     48                      kwargs,
     49                      special_validator) :
     50   
     51    special_plugin_file_name = kwargs['special_plugin_file_name'] # X-
     52
     53    timestamp = datetime.datetime.today().isoformat()
     54    valid = False
     55
     56    try :
     57        valid = special_validator(data,
     58                                  descriptive_string,
     59                                  kwargs)
     60    except :
     61        traceback_string = traceback.format_exc()
     62        #pdb.set_trace()
     63
     64        err_log_file_path = os.path.normpath("/tmp/" + special_plugin_file_name + "_err_generic_validator__" + descriptive_string.replace('/' , '%2F') + "__" + timestamp + ".log")
     65
     66        with open(name = err_log_file_path,
     67                  mode = "wt") as debugging_output_file :
     68            debugging_output_file.write(traceback_string)
     69        #sys.exit(999) # X- exit with some special error status
     70   
     71    return valid
     72
     73
     74def check_HTML_wellformedness(data,
     75                              descriptive_string,
     76                              **kwargs) : # X-
     77
     78    def special_validator(data,
     79                          descriptive_string,
     80                          kwargs) :
     81        pattern                 = '.*<html.*>.+</html>.*'
     82        pattern_regex           = re.compile(pattern, re.MULTILINE | re.IGNORECASE | re.DOTALL)
     83        results                 = pattern_regex.search(data)
     84
     85        # special_plugin_file_name
     86       
     87        if results is not None :
     88            return True
     89        else :
     90            return False
     91
     92    #pdb.set_trace()
     93
     94    # X- Do PROPER wellformedness check - once the tools are availble.
     95    wellformedness = generic_validator(data,
     96                                       descriptive_string,
     97                                       kwargs,
     98                                       special_validator)
     99
     100    return wellformedness
     101
     102
     103def check_JSON_wellformedness(data,
     104                              descriptive_string,
     105                              **kwargs) :
     106    def special_validator(data,
     107                          descriptive_string,
     108                          kwargs) :
     109
     110        try :
     111            json.loads(data)
     112        except JSONDecodeError :
     113            valid = False
     114        else :
     115            valid = True
     116
     117        return valid
     118
     119    wellformedness = generic_validator(data,
     120                                       descriptive_string,
     121                                       kwargs,
     122                                       special_validator)
     123
     124    return wellformedness
     125
     126
     127def check_XML_validity(data,
     128                       descriptive_string,
     129                       **kwargs) :
     130
     131    def special_validator(data,
     132                          descriptive_string,
     133                          kwargs) :
     134
     135        try :           
     136            data_tree_root_element = xml.etree.ElementTree.XML(text = data)
     137               
     138            if data_tree_root_element.tag == kwargs['valid_root_element_tag'] :
     139                return True
     140            else :
     141                return False
     142        except :
     143            return False
     144
     145    wellformedness = generic_validator(data,
     146                                       descriptive_string,
     147                                       kwargs,
     148                                       special_validator)
     149    return wellformedness
     150
     151
     152def check_LDAP_validity(data,
     153                       descriptive_string,
     154                       **kwargs) :
     155
     156    def special_validator(data,
     157                          descriptive_string,
     158                          kwargs) :
     159        try :           
     160            return True # X-
     161        except :
     162            return False
     163
     164    wellformedness = generic_validator(data,
     165                                       descriptive_string,
     166                                       kwargs,
     167                                       special_validator)
     168    return wellformedness
     169
     170
     171def check_ldap(host,
     172               bind_DN) :
     173
     174    OpenDJ_directory_path = '/srv/LDAP/OpenDJ-2.5.0-Xpress1/'
     175
     176    base_DN = 'dc=clarin,dc=eu'
     177    query = '(objectClass=CLARINPerson)'
     178
     179    command = [OpenDJ_directory_path + "/bin/ldapsearch",
     180              '--port', '10389',
     181              '--baseDN', base_DN,
     182              '--useStartTLS',
     183              '--trustAll',
     184              '--hostname', host,
     185              '--bindDN', bind_DN,
     186              "--bindPasswordFile", '/root/LDAP_passwdfile',
     187              query,
     188              'isMemberOf']
     189
     190    # Run OpenDJ's "ldapsearch" command line utility
     191    #pdb.set_trace()
     192
     193    OpenDJ_uid = pwd.getpwnam('opendj')[2]
     194    Nagios_uid = pwd.getpwnam('nagios')[2]
     195
     196    #import multiprocessing
     197
     198    def LDAP_query(OpenDJ_uid, command) :
     199
     200        #pdb.set_trace()
     201
     202        try :
     203            os.setuid(0) # OpenDJ_uid
     204        except OSError, e :
     205            raise e
     206        else :
     207            process = subprocess.Popen(command,
     208                                       stdout = subprocess.PIPE,
     209                                       stderr = subprocess.PIPE)
     210
     211            #print " ".join(command)
     212
     213            stdout, stderr = process.communicate()
     214           
     215            if process.returncode == 0 :
     216                return True
     217                #LDAP_result_queue.put(True)
     218            else :
     219                return False
     220                #LDAP_result_queue.put(False)
     221
     222
     223    # LDAP_result_queue = multiprocessing.Queue()
     224    # LDAP_query_process = multiprocessing.Process(target = LDAP_query, args = (OpenDJ_uid, command, LDAP_result_queue))
     225    # LDAP_query_process.start()
     226    # result = LDAP_result_queue.get()
     227    # LDAP_query_process.join()
     228
     229    result = LDAP_query(OpenDJ_uid, command)
     230
     231    if result == True:
     232        return { "code"      : "OK",
     233                 "message"   : 'Host %s is up and responds as expected to a query "%s" with base DN "%s".' % (host, query, base_DN)
     234               }
     235    else :
     236        return { "code"      : "CRITICAL",
     237                 "message"   : 'Host %s is not up or does not respond as expected to a query "%s" with base DN "%s".' % (host, query, base_DN)
     238               }
     239
     240    # current_process_ID = os.fork()
     241
     242    # if current_process_ID == 0 :
     243    #     ## Child process code
     244       
     245     
     246
     247    #     os._exit(0)
     248     
     249    # ## Parent process code. Wait for ldapsearch child process.
     250    # os.waitpid(current_process_ID, 0)
     251   
     252    # try :
     253    #     os.setuid(Nagios_uid)
     254    # except OSError, e :
     255    #     raise e
     256
     257    #print stdout
     258    #print stderr
     259    #pdb.set_trace()
     260
     261    return result
     262
     263
     264def check_condition(host,
     265                    http_path,
     266                    protocol,
     267                    HTTP_method,
     268                    port_number,
     269                    authorize,
     270                    validator,
     271                    **validator_arguments) :
     272
     273    #pdb.set_trace()
     274    # X- remove implicit argument values
     275    #if port_number is None : port_number = 80
     276    #if authorize is None : authorize = True
     277
     278    try :
     279        port_number = int(port_number)
     280    except ValueError :
     281        return { "code"      : "CRITICAL",
     282         "message"   : 'The port number specified, "{0}", cannot be converted to an integer.'.format(port_number)
     283       }
     284    except TypeError :
     285        port_number = None
     286
     287    def handle_connection_failure(problem_description) :
     288        err_log_file_path = os.path.normpath("/tmp/" + special_plugin_file_name + "_err_connection_failure__" + http_path.replace('/' , '%2F') + "__" + timestamp + ".log")
     289
     290        with open(name = err_log_file_path,
     291                  mode = "wt") as debugging_output_file :
     292           debugging_output_file.write(problem_description)
     293
     294    special_plugin_file_name = validator_arguments['special_plugin_file_name'] # X-
     295   
     296    #http_path  = str(urllib.quote_plus(http_path))   
     297   
     298    timestamp = datetime.datetime.today().isoformat()
     299   
     300    try :
     301        if protocol == 'http' :
     302            conn = httplib.HTTPConnection(host = host,
     303                                          port = port_number,
     304                                          strict = True)
     305        elif protocol == 'https' :           
     306            conn = httplib.HTTPSConnection(host = host,
     307                                           port = port_number,
     308                                           strict = True)
     309        request = conn.request(HTTP_method,
     310                               http_path)
     311    except :
     312        traceback_string = traceback.format_exc()
     313
     314        handle_connection_failure(traceback_string + "\nThis problem originates from location 1 in '" + special_plugin_file_name + "'.\n")
     315
     316        return {
     317                "code"      : "CRITICAL",
     318                "message"   : '{protocol} connection on port {port_number} to host "{host}" failed.'.format(protocol = protocol,
     319                                                                                                            port_number = port_number,
     320                                                                                                            host = host)
     321               }
     322    else :
     323        try :
     324            response = conn.getresponse()
     325
     326            data = response.read()
     327           
     328            conn.close()
     329        except :
     330            traceback_string = traceback.format_exc()
     331
     332            handle_connection_failure(traceback_string + "\nThis problem originates from location 2 in '" + special_plugin_file_name + "'.\n")
     333        else :
     334
     335            redirecting_responses = frozenset([
     336                                            httplib.MOVED_PERMANENTLY,
     337                                            httplib.FOUND,
     338                                            httplib.SEE_OTHER,
     339                                            httplib.TEMPORARY_REDIRECT,
     340                                          ]) 
     341
     342            if response.status == httplib.OK :
     343                # HTTP status codes 200 and 302
     344                # X- Resolve redirect in case of HTTP status == 302
     345                well_formed = validator(data                   = data,
     346                                        descriptive_string     = http_path,
     347                                        **validator_arguments) # ['validator_arguments'])
     348
     349                if well_formed :
     350                    return {
     351                            "code"      : "OK",
     352                            "message"   : 'Host "{host}" is up and returns well-formed data at "{http_path}".'.format(host = host, http_path = http_path)
     353                           }
     354                else :
     355                    return {
     356                            "code"      : "CRITICAL",
     357                            "message"   : 'Host "{host}" is up but returns non-well-formed data at "{http_path}".'.format(host = host, http_path = http_path)
     358                            }
     359
     360            elif response.status in redirecting_responses :
     361                new_location_URL = dict(response.getheaders())['location']
     362
     363                parsed_new_location_URL = urlparse.urlsplit(new_location_URL)
     364                new_http_path = parsed_new_location_URL.path
     365                if parsed_new_location_URL.query != '' :
     366                    new_http_path = new_http_path + '?' + parsed_new_location_URL.query
     367               
     368                if parsed_new_location_URL.scheme == protocol and host == parsed_new_location_URL.netloc and http_path == new_http_path :
     369                    return {
     370                              "code"    : "CRITICAL",
     371                              "message" : 'Host "{host}" is up but the response to GET "{http_path}" implies an infinite redirection to itself.'.format(host = host, http_path = http_path)
     372                            }
     373
     374                else :
     375
     376                    #pdb.set_trace()
     377
     378                    return check_condition(host        = parsed_new_location_URL.netloc,
     379                                           http_path   = new_http_path,
     380                                           protocol    = parsed_new_location_URL.scheme,
     381                                           HTTP_method = HTTP_method,
     382                                           port_number = parsed_new_location_URL.port,
     383                                           authorize   = authorize,
     384                                           validator   = validator,
     385                                           **validator_arguments) # special_plugin_file_name = validator_arguments['special_plugin_file_name']
     386
     387            elif response.status == httplib.UNAUTHORIZED and authorize == False :
     388                return {
     389                        "code"      : "OK",
     390                        "message"   : 'Host "{host}" is up and requests authorization at "{http_path}".'.format(host = host, http_path = http_path)
     391                       }
     392
     393            else :
     394                #pdb.set_trace()
     395                handle_connection_failure("Unreachable URL! HTTP response code: " + str(response.status) +
     396                                            "\nThis problem originates from location 3 in '" + special_plugin_file_name + "'.\n")
     397
     398                return {
     399                        "code"      : "CRITICAL",
     400                        "message"   : 'Host "{host}" has a problem with the URL path component "{http_path}".'.format(host = host, http_path = http_path)
     401                       }
     402
     403def main(special_main_subroutine,
     404         command_line_parameters) :
     405   
     406    ## Process plugin-specific command line parameters.
     407    command_line_parameters_getopt_string = command_line_parameters_usage_string = "\\ \n"
     408    for (parameter, description) in command_line_parameters :
     409       command_line_parameters_usage_string = command_line_parameters_usage_string + parameter + "  " + description + "\\ \n"
     410       command_line_parameters_getopt_string = command_line_parameters_getopt_string + parameter.lstrip("-")  + ":"
     411
     412    try :
     413        opts = filter(None, getopt.getopt(sys.argv[1:], command_line_parameters_getopt_string))
     414        if len(opts) > 0 : opts = opts[0]
     415    except getopt.GetoptError, err :
     416        usage(command_line_parameters_usage_string)
     417    else :
     418        if len(command_line_parameters) == len(opts) :
     419            ## main_subroutine_argument_values is based on the argument order of special_main_subroutine(). They are not mapped to the argument names!
     420            ## Therefore, command_line_parameters must be in the same order as special_main_subroutine()'s arguments.
     421            main_subroutine_argument_values = [parameter_value for parameter_name, parameter_value in opts]
     422            # pdb.set_trace()
     423            special_main_subroutine(*main_subroutine_argument_values)       
     424        else :
     425            usage(command_line_parameters_usage_string)
     426   
     427
     428if __name__ == "__main__" :
     429    main()
Note: See TracChangeset for help on using the changeset viewer.