def parseResult(self, data):
        for result in data:
            if string.split(result['name'], '@')[1] in self.options.hostname:
                nodeData = result
        if nodeData:
            if self.options.type == 'mem':
                if nodeData['mem_alarm'] is True:
                    return Response(CRITICAL, 'memory alarm triggered!')
                self.percentage = nodeData[self.options.type + "_used"] / (
                    nodeData[self.options.type + "_limit"] / 100.0)
            if self.options.type == 'disk':
                if nodeData['disk_free_alarm'] is True:
                    return Response(CRITICAL, 'disk alarm triggered!')
                self.percentage = nodeData[
                    self.options.type + "_free_limit"] / (
                        nodeData[self.options.type + "_free"] / 100.0)

            if self.options.type == 'fd':
                self.percentage = nodeData[self.options.type + "_used"] / (
                    nodeData[self.options.type + "_total"] / 100.0)

            if self.options.type == 'proc':
                self.percentage = nodeData[self.options.type + "_used"] / (
                    nodeData[self.options.type + "_total"] / 100.0)

            if self.options.type == 'sockets':
                self.percentage = nodeData[self.options.type + "_used"] / (
                    nodeData[self.options.type + "_total"] / 100.0)

            return self.response_for_value(
                self.percentage, self.options.type + ' usage is ' +
                str(self.percentage) + ' used ')
        return Response(WARNING, 'No node data found!')
Example #2
0
 def test_str_has_performance_data(self):
     """
     Tests that with performance data, the status output
     will output the value along with the performance data.
     """
     instance = Response(pynagios.OK, message="yo")
     instance.set_perf_data("users", 20)
     instance.set_perf_data("foos", 80)
     expected = '%s: %s|users=20;;;; foos=80;;;;' % (pynagios.OK.name, "yo")
     assert expected == str(instance)
Example #3
0
    def parseResult(self, data):
        failed_repls = []
        for result in data:
            if result['status'] != 'running':
                msg = "%s %s %s %s" % (result['node'], result['vhost'],
                                       result['exchange'], result['status'])
                failed_repls.append(msg)

        if failed_repls:
            return Response(CRITICAL, (', '.join(failed_repls)))

        return Response(OK, "federation links are all up")
Example #4
0
 def test_multiple_responses(self):
     """
     Test that the add_response and all_responses mechanism is working
     """
     plugin = self.Klass()
     r1 = Response(pynagios.OK, 'foo')
     r2 = Response(pynagios.CRITICAL, 'bar')
     r3 = Response(pynagios.OK, 'baz')
     plugin.add_response(r1)
     plugin.add_response(r2)
     plugin.add_response(r3)
     assert pynagios.CRITICAL == plugin.all_responses().status
     assert "bar OK: foo, baz" == plugin.all_responses().message
Example #5
0
class FacedetectCheck(Plugin):
    port = make_option('-p',
                       '--port',
                       type='int',
                       default=4000,
                       help='Use the following port')
    use_ssl = make_option('-S',
                          '--use-ssl',
                          action='store_false',
                          default=False,
                          help="Use HTTPS instead of HTTP")
    expected = make_option('-e',
                           '--expected',
                           type='str',
                           default=None,
                           help="Expect the following string in response")

    def check(self):
        hostname = self.options.hostname
        port = self.options.port
        use_ssl = self.options.use_ssl
        expected = self.options.expected
        timeout = self.options.timeout if self.options.timeout > 0 else 10

        if not hostname:
            return Response(UNKNOWN, 'Hostname is missing')

        url = "http%s://%s:%s/status" % ('s'[:use_ssl], hostname, port)
        try:
            f = urllib2.urlopen(url, timeout=timeout)
            response = json.load(f)
        except urllib2.URLError, e:
            return Response(CRITICAL, e.reason[1])

        if not response:
            return Response(CRITICAL, 'No data received')

        status = response.pop('status')
        ret = OK
        if expected and expected not in status:
            ret = CRITICAL

        result = Response(ret, status)

        for k, v in response.items():
            result.set_perf_data(k, int(v))

        return result
Example #6
0
    def check(self):
        hostname = self.options.hostname
        port = self.options.port
        use_ssl = self.options.use_ssl
        expected = self.options.expected
        timeout = self.options.timeout if self.options.timeout > 0 else 10

        if not hostname:
            return Response(UNKNOWN, 'Hostname is missing')

        url = "http%s://%s:%s/status" % ('s'[:use_ssl], hostname, port)
        try:
            f = urllib2.urlopen(url, timeout=timeout)
            response = json.load(f)
        except urllib2.URLError, e:
            return Response(CRITICAL, e.reason[1])
Example #7
0
 def test_str_has_blank_message(self):
     """
     Tests that a response with no message given will not include
     anything in the output.
     """
     instance = Response(pynagios.OK)
     expected = "%s:" % pynagios.OK.name
     assert expected == str(instance)
Example #8
0
 def test_str_has_status_and_message(self):
     """
     Tests that without performance data, the status output
     will output the proper thing with status and a message.
     """
     instance = Response(pynagios.OK, message="Hi")
     expected = "%s: %s" % (pynagios.OK.name, "Hi")
     assert expected == str(instance)
Example #9
0
    def check(self):
        timeout = self.options.timeout if self.options.timeout > 0 else 10
        metric = self.options.metric.strip().lower()

        if not self.options.hostname:
            return Response(UNKNOWN, 'Hostname is missing')

        try:
            self._connect(self.options.hostname, self.options.port, timeout)
            self._socket.sendall('stats')
            data = ''
            while True:
                data += self._socket.recv(1024)
                if data and 'END' in data:
                    break
            self._socket.close()
        except socket.error, (errno, msg):
            return Response(CRITICAL, msg)
Example #10
0
    def check(self):
        value = check_graphite(self.options)
        if value is None:
            return Response(UNKNOWN, "No results returned!")

        message = "{} ({} is {})".format(self.options.name, self.options.func,
                                         value)
        response = self.response_for_value(value, message)
        response.set_perf_data(self.options.func, value)
        return response
Example #11
0
    def test_exit(self, monkeypatch):
        """
        Tests that responses exit with the proper exit code and
        stdout output.
        """
        def mock_exit(code):
            mock_exit.exit_status = code

        mock_exit.exit_status = None

        output = cStringIO.StringIO()
        monkeypatch.setattr(sys, 'stdout', output)
        monkeypatch.setattr(sys, 'exit', mock_exit)

        instance = Response(pynagios.OK)
        instance.exit()

        assert pynagios.OK.exit_code == mock_exit.exit_status
        assert "%s\n" % str(instance) == output.getvalue()
Example #12
0
    def test_exit(self, monkeypatch):
        """
        Tests that responses exit with the proper exit code and
        stdout output.
        """
        def mock_exit(code):
            mock_exit.exit_status = code

        mock_exit.exit_status = None

        output = cStringIO.StringIO()
        monkeypatch.setattr(sys, 'stdout', output)
        monkeypatch.setattr(sys, 'exit', mock_exit)

        instance = Response(pynagios.OK)
        instance.exit()

        assert pynagios.OK.exit_code == mock_exit.exit_status
        assert "%s\n" % str(instance) == output.getvalue()
Example #13
0
    def test_multiple_responses_default(self):
        """
        Test that the default parameter to all_responses is working
        """

        plugin = self.Klass()
        assert pynagios.OK == plugin.all_responses().status

        r1 = Response(pynagios.UNKNOWN, 'default test')
        assert r1.status == plugin.all_responses(r1).status
        assert r1.message == plugin.all_responses(r1).message
    def check(self):
        """
        returns a response and perf data for this check
        """
        try:
            self.rabbit_error = 0
            self.rabbit_note = "action performed successfully"

            if not self.testOptions():
                return Response(UNKNOWN, "Incorrect check config" + self.rabbit_note)

            if not self.options.hostname or not self.options.port or not self.options.username or not self.options.password or not self.testOptions():
                return Response(UNKNOWN, "Incorrect missing options")

            if not self.makeUrl():
                return Response(UNKNOWN, "Error with URL")

            response = self.doApiGet()

            if self.rabbit_error > 0:
                return Response(CRITICAL, self.rabbit_note)

            data = self.parseJson(response)

            if self.rabbit_error > 0:
                return Response(CRITICAL, self.rabbit_note)

            result = self.parseResult(data)
            self.setPerformanceData(data, result)
            return result
        except Exception as e:
            return Response(UNKNOWN, "Error occurred:" + str(e))
Example #15
0
    def check(self):
        if self.options.debug:
            logging.basicConfig(level=logging.DEBUG)
        else:
            logging.basicConfig(level=logging.INFO)
            logging.getLogger("urllib3").setLevel(logging.WARNING)

        payload = {}
        auth = None

        if self.options.user and self.options.password:
            auth = HTTPBasicAuth(self.options.user, self.options.password)
        if self.options.checks:
            payload['checks'] = []
            for check in self.options.checks.split(';'):
                payload['checks'].append(check)

        final_url = urljoin(self.options.url, '/repositories/' + self.options.repository + '/health')

        start = time.time()
        try:
            response = requests.get(final_url, params=payload, auth=auth)
            total_time = time.time() - start
        except Exception as ex:
            return Response(CRITICAL, "Error occurred while making connection to GraphDB instance:\n%s" % ex)

        if self.options.critical is None:
            self.options.critical = Range('@500:')
        if self.options.warning is None:
            self.options.warning = Range('@206:500')

        result = self.response_for_value(response.status_code, "Repository[%s] at [%s]\nResponse: %s\nResponse time: %ss\n" % (
            self.options.repository, self.options.url, trim_response(response.text), total_time))
        result.set_perf_data('response-time', total_time, uom='s')

        for check, state in response.json().iteritems():
            if check == 'status' or check == 'master-status':
                if state == 'green':
                    status_in_percent = 100
                elif state == 'yellow':
                    status_in_percent = 50
                else:
                    status_in_percent = 0
                result.set_perf_data(check, status_in_percent, uom='%', warn=Range('50'), crit=Range('0'))
            else:
                if state == 'OK':
                    status_in_percent = 100
                else:
                    status_in_percent = 0
                result.set_perf_data(check, status_in_percent, uom='%', warn=Range('50'), crit=Range('0'))

        return result
Example #16
0
    def check(self):
        value = check_graphite(self.options)
        if value is None:
            return Response(UNKNOWN, "No results returned!")

        message = "{0} ({1} is {2})".format(self.options.name,
                                            self.options.func, value)
        response = self.response_for_value(value, message)
        try:
            response.set_perf_data(self.options.func, value)
        except ValueError as e:
            raise ValueError("failed to set {} as perf data: {}".format(
                value, str(e)))
        return response
    def parseResult(self, data, result):
        value = None
        message = None
        if data.get('messages'):
            value = data['messages']
            message = ' found ' + str(value) + ' messages'
        else:
            value = 0
            message = ' No messages found in queue'
            
        status = OK
        if self.options.critical is not None and self.options.critical.in_range(value):
            status = CRITICAL
        elif self.options.warning is not None and self.options.warning.in_range(value):
            status = WARNING

        if result is None:
            result = Response(status, message)
        elif result.status.exit_code < status.exit_code:
            result.status = status
            result.message = message
        self.rabbit_note = result.message
        return result
    def check(self):
        hostname = self.options.hostname
        port = self.options.port
        username = self.options.username
        password = self.options.password
        timeout = self.options.timeout if self.options.timeout > 0 else 10

        if not hostname:
            return Response(UNKNOWN, 'Hostname is missing!')

        if username and password:
            auth = '%s:%s@' % (username, password)
        else:
            auth = ''

        procs = None
        try:
            url = "http://%s%s:%s" % (auth, hostname, port)
            socket.setdefaulttimeout(timeout)
            s = xmlrpclib.ServerProxy(url)
            procs = s.supervisor.getAllProcessInfo()
        except xmlrpclib.Fault, e:
            return Response(UNKNOWN, "getAllProcessInfo: %s" % e.faultString)
Example #19
0
 def test_str_has_performance_data(self):
     """
     Tests that with performance data, the status output
     will output the value along with the performance data.
     """
     instance = Response(pynagios.OK, message="yo")
     instance.set_perf_data("users", 20)
     instance.set_perf_data("foos", 80)
     expected = '%s: %s|users=20;;;; foos=80;;;;' % (pynagios.OK.name, "yo")
     assert expected == str(instance)
Example #20
0
class StatsdCheck(Plugin):
    port = make_option('-p', '--port', type='int', default=8126)
    metric = make_option('-m', '--metric', type='str', default='uptime')
    _socket = None

    def _connect(self, host, port, timeout):
        exception = None

        for (af, socktype, proto, cname, sa) in socket.getaddrinfo(
                host, port, socket.AF_UNSPEC, socket.SOCK_STREAM):

            try:
                self._socket = socket.socket(af, socktype, proto)
                self._socket.settimeout(timeout)
                self._socket.connect(sa)
                return
            except socket.error as e:
                if self._socket:
                    self._socket.close()
                    self._socket = None
                exception = e

        raise exception

    def check(self):
        timeout = self.options.timeout if self.options.timeout > 0 else 10
        metric = self.options.metric.strip().lower()

        if not self.options.hostname:
            return Response(UNKNOWN, 'Hostname is missing')

        try:
            self._connect(self.options.hostname, self.options.port, timeout)
            self._socket.sendall('stats')
            data = ''
            while True:
                data += self._socket.recv(1024)
                if data and 'END' in data:
                    break
            self._socket.close()
        except socket.error, (errno, msg):
            return Response(CRITICAL, msg)
        except socket.timeout, msg:
            return Response(CRITICAL, msg)
    def check(self):
        """
        returns a response and perf data for this check
        """
        try:
            self.rabbit_error = 0
            self.rabbit_note = "action performed successfully"

            if not self.testOptions():
                return Response(UNKNOWN, "Incorrect check config" + self.rabbit_note)

            if not self.options.hostname or not self.options.port or not self.options.username or not self.options.password or not self.testOptions():
                return Response(UNKNOWN, "Incorrect missing options")

            if not self.makeUrl():
                return Response(UNKNOWN, "Error with URL")

            response = self.parseJson(self.doApiGet())

            if response is None:
                return Response(UNKNOWN, "The server did not respond")

            queueMatcher = re.compile(self.options.pattern)
            result = None
            for queue in response: 
                if queueMatcher.match(queue["name"]) is None:
                    continue

                self.generateQueueUrl(queue["name"])

                if self.rabbit_error > 0:
                    return Response(CRITICAL, self.rabbit_note)

                data = self.parseJson(self.doApiGet())

                if self.rabbit_error > 0:
                    return Response(CRITICAL, self.rabbit_note)

                result = self.parseResult(data, result)

                self.setPerformanceData(data, result, queue["name"])
            print result
        except Exception as e:
            print str(e)
            return Response(UNKNOWN, "Error occurred:" + str(e))
class SupervisordXmlRpcCheck(Plugin):
    port = make_option('-p',
                       '--port',
                       type='int',
                       default=9080,
                       help='Use the following port for XML-RPC connection')
    username = make_option('-u',
                           '--user',
                           type='str',
                           default=None,
                           help='Username for XML-RPC connection')
    password = make_option('-P',
                           '--password',
                           type='str',
                           default=None,
                           help='Password for XML-RPC connection')

    def check(self):
        hostname = self.options.hostname
        port = self.options.port
        username = self.options.username
        password = self.options.password
        timeout = self.options.timeout if self.options.timeout > 0 else 10

        if not hostname:
            return Response(UNKNOWN, 'Hostname is missing!')

        if username and password:
            auth = '%s:%s@' % (username, password)
        else:
            auth = ''

        procs = None
        try:
            url = "http://%s%s:%s" % (auth, hostname, port)
            socket.setdefaulttimeout(timeout)
            s = xmlrpclib.ServerProxy(url)
            procs = s.supervisor.getAllProcessInfo()
        except xmlrpclib.Fault, e:
            return Response(UNKNOWN, "getAllProcessInfo: %s" % e.faultString)
        except (socket.gaierror, socket.timeout, socket.error), e:
            return Response(CRITICAL, "%s: %s" % (hostname, e))
Example #23
0
            data = ''
            while True:
                data += self._socket.recv(1024)
                if data and 'END' in data:
                    break
            self._socket.close()
        except socket.error, (errno, msg):
            return Response(CRITICAL, msg)
        except socket.timeout, msg:
            return Response(CRITICAL, msg)

        data = data.strip().split('\n')
        data.remove('END')

        if not data:
            return Response(CRITICAL, 'No stats received')

        stats = {}
        for stat in data:
            k, v = stat.split(':')
            stats[k.strip().lower()] = v.strip()

        result = self.response_for_value(float(stats[metric]), '%s: %s' % (
            metric, stats[metric]))

        for k, v in stats.items():
            result.set_perf_data(k, int(v))

        return result

    def check(self):
        try:
            self.merge_options()
            self.configure_logging()

            merged_options = self.merged_options
            hostname = ''
            if 'hostname' in merged_options and merged_options['hostname']:
                hostname = merged_options['hostname']
            self.results_db_conn_opts = {}

            if 'results_host' in merged_options and merged_options[
                    'results_host']:
                self.results_db_conn_opts['host'] = merged_options[
                    'results_host']

            if 'results_port' in merged_options and merged_options[
                    'results_port']:
                self.results_db_conn_opts['port'] = merged_options[
                    'results_port']

            if 'results_user' in merged_options and merged_options[
                    'results_user']:
                self.results_db_conn_opts['user'] = merged_options[
                    'results_user']

            if 'results_password' in merged_options and merged_options[
                    'results_password']:
                self.results_db_conn_opts['passwd'] = merged_options[
                    'results_password']

            if 'results_database' in merged_options and merged_options[
                    'results_database']:
                self.results_db_conn_opts['db'] = merged_options[
                    'results_database']

            if self.results_db_conn_opts:
                if not ('db' in self.results_db_conn_opts
                        and self.results_db_conn_opts['db']):
                    raise Error('results_database is required.')

            log.debug('Check started with the following options:\n%s' %
                      (pprint.pformat(self.merged_options), ))

            schema_tables = self.get_schema_tables()

            log.debug('Schema tables:\n%s' % (pprint.pformat(schema_tables), ))

            q = Queue.Queue()
            for v in schema_tables.itervalues():
                q.put(v)

            threads = self.merged_options['threads']
            results = Queue.Queue()
            thread_list = []
            for n in range(threads):
                thread = TableProcessor(schema_tables=q,
                                        merged_options=self.merged_options,
                                        results=results)
                thread.name = 'Thread #%d' % (n, )
                thread.daemon = True
                thread.start()
                thread_list.append(thread)

            # wait for all threads to finish
            log.debug('Waiting for all threads to finish running.')
            while True:
                dead = []
                for thread in thread_list:
                    dead.append(not thread.is_alive())
                if all(dead):
                    break
                time.sleep(0.01)
            log.debug('All threads finished.')

            critical_columns = []
            warning_columns = []
            errors = []
            investigate_columns = []
            while True:
                try:
                    result = results.get_nowait()

                    if 'critical_column' in result:
                        critical_columns.append(result['critical_column'])

                    if 'warning_column' in result:
                        warning_columns.append(result['warning_column'])

                    if 'error' in result:
                        errors.append(result['error'])

                    if 'investigate_column' in result:
                        investigate_columns.append(
                            result['investigate_column'])

                    results.task_done()
                except Queue.Empty, e:
                    break

            log.info('Critical columns:\n%s\n\nWarning columns:\n%s' %
                     (pprint.pformat(critical_columns),
                      pprint.pformat(warning_columns)))

            if len(critical_columns) > 0:
                columns = sorted(critical_columns) + sorted(warning_columns)
                status = pynagios.CRITICAL
            elif len(warning_columns) > 0:
                columns = warning_columns
                status = pynagios.WARNING
            else:
                status = pynagios.OK

            msg = ''
            if status != pynagios.OK:
                msg = '\n'.join(
                    '%s.%s\t%s\t%s\t%s\t%.2f%%' %
                    (col.get('schema'), col.get('table'),
                     col.get('column_name'), col.get('column_type'),
                     col.get('max_value'), col.get('overflow_percentage'))
                    for col in columns)
                msg = '\n' + msg

                ##############################################################
                # store critical/warning columns in db
                ##############################################################
                if self.results_db_conn_opts:
                    conn = MySQLdb.connect(**self.results_db_conn_opts)
                    with conn as cursor:
                        sql = ("INSERT INTO int_overflow_check_results("
                               "  hostname, dbname, table_name, column_name, "
                               "  max_size, percentage, reason, timestamp) "
                               "VALUE (%s, %s, %s, %s, %s, %s, %s, %s)")

                        for col in critical_columns:
                            cursor.execute(
                                sql,
                                (hostname, col.get('schema'), col.get('table'),
                                 col.get('column_name'), col.get('max_value'),
                                 col.get('overflow_percentage'), 'critical',
                                 datetime.datetime.now()))

                        for col in warning_columns:
                            cursor.execute(
                                sql,
                                (hostname, col.get('schema'), col.get('table'),
                                 col.get('column_name'), col.get('max_value'),
                                 col.get('overflow_percentage'), 'warning',
                                 datetime.datetime.now()))

            row_count_max_ratio = self.merged_options.get(
                'row_count_max_ratio', 0)
            if investigate_columns:
                log.info('Investigate columns:\n%s' %
                         (pprint.pformat(investigate_columns, )))
                if msg:
                    msg += '\n'
                msg += ((
                    '\nColumns containing high values compared to maximum for the column datatype, but number of rows is less than %s%% of maximum for the column type:\n'
                    % (row_count_max_ratio, )) + ('\n'.join(
                        '%s.%s\t%s\t%s\t%s\t%.2f%%' %
                        (col.get('schema'), col.get('table'),
                         col.get('column_name'), col.get('column_type'),
                         col.get('max_value'), col.get('overflow_percentage'))
                        for col in investigate_columns)))

                ##############################################################
                # store investigate columns in db
                ##############################################################
                if self.results_db_conn_opts:
                    conn = MySQLdb.connect(**self.results_db_conn_opts)
                    with conn as cursor:
                        sql = ("INSERT INTO int_overflow_check_results("
                               "  hostname, dbname, table_name, column_name, "
                               "  max_size, percentage, reason, timestamp) "
                               "VALUE (%s, %s, %s, %s, %s, %s, %s, %s)")

                        for col in investigate_columns:
                            cursor.execute(
                                sql,
                                (hostname, col.get('schema'), col.get('table'),
                                 col.get('column_name'), col.get('max_value'),
                                 col.get('overflow_percentage'), 'investigate',
                                 datetime.datetime.now()))

            log.info('status: %s\n\nmsg:\n%s' % (status, msg))

            self.exit_code = status.exit_code
            return Response(status, msg)
                     'BACKOFF': [], 'STOPPING': [], 'EXITED': [],
                     'FATAL': [], 'UNKNOWN': []}
        for proc in procs:
            processes[proc['statename']].append(proc['name'])

        ret = OK
        for state in ('STOPPING', 'STARTING'):
            if len(processes[state]):
                ret = WARNING

        if len(processes['UNKNOWN']):
            ret = UNKNOWN

        for state in ('EXITED', 'BACKOFF', 'FATAL'):
            if len(processes[state]):
                ret = CRITICAL

        result = Response(ret, processes)

        msg = []
        for k, v in processes.items():
            if v:
                msg.append('%s: %s' % (k, ', '.join(v)))
            result.set_perf_data(k, len(v))

        result.message = ' '.join(msg)
        return result

if __name__ == '__main__':
    SupervisordXmlRpcCheck().check().exit()
Example #26
0
 def test_message_gets_set_by_initializer(self):
     "Tests that the message can be set by the constructor."
     instance = Response(message="Hello!")
     assert "Hello!" == instance.message
class CheckMaxValue(Plugin):
    """A nagios plugin for checking Integer Overflow"""

    port = make_option('-P',
                       '--port',
                       dest='port',
                       type='int',
                       default=3306,
                       help='The port to be used')

    user = make_option('-u', '--user', dest='user', help='Database user')

    password = make_option('-p',
                           '--password',
                           dest='password',
                           help='Database password')

    use_dbs = make_option(
        '-d',
        '--use-dbs',
        dest='use_dbs',
        help='A comma-separated list of db names to be inspected')

    ignore_dbs = make_option(
        '-i',
        '--ignore-dbs',
        dest='ignore_dbs',
        help='A comma-separated list of db names to be ignored')

    config = make_option('-C',
                         '--config',
                         dest='config',
                         help='Configuration filename')

    threads = make_option('-T',
                          '--threads',
                          dest='threads',
                          type=int,
                          default=2,
                          help='Number of threads to spawn')

    exclude_columns = make_option(
        '-e',
        '--exclude-columns',
        dest='exclude_columns',
        help=('Specify columns to exclude in the following format: '
              'schema1.table1=col1,col2,colN;schemaN.tableN=colN;...'))

    row_count_max_ratio = make_option(
        '--row-count-max-ratio',
        default=50,
        type=float,
        help=
        'If table row count is less than this value, exclude this column from display.'
    )

    display_row_count_max_ratio_columns = make_option(
        '--display-row-count-max-ratio-columns',
        action='store_true',
        help=
        'In separate section, display columns containing high values compared to maximum for the column datatype, but number of rows is less than the value of --row-count-max-ratio.'
    )

    results_host = make_option('--results-host',
                               default=None,
                               help='Results database hostname.')

    results_database = make_option('--results-database',
                                   default=None,
                                   help='Results database name.')

    results_user = make_option('--results-user',
                               default=None,
                               help='Results database username.')

    results_password = make_option('--results-password',
                                   default=None,
                                   help='Results database password.')

    results_port = make_option('--results-port',
                               default=None,
                               help='Results database port.')

    scan_all_columns = make_option('--scan-all-columns',
                                   action='store_true',
                                   help='All columns are searched.',
                                   default=False)

    secondary_keys = make_option('--secondary-keys',
                                 action='store_true',
                                 help='Secondary keys are also searched.',
                                 default=False)

    def get_options_from_config_file(self):
        """Returns options from YAML file."""
        if self.options.config:
            with open(self.options.config) as f:
                return yaml.load(f)
        else:
            return None

    def get_merged_options(self, additional_options):
        """Returns argument options merged with additional options."""
        options = {}
        if self.options.ignore_dbs:
            options['ignore_dbs'] = self.options.ignore_dbs
        if self.options.use_dbs:
            options['use_dbs'] = self.options.use_dbs
        if self.options.port:
            options['port'] = self.options.port
        if self.options.user:
            options['user'] = self.options.user
        if self.options.password:
            options['password'] = self.options.password
        if self.options.hostname:
            options['hostname'] = self.options.hostname
        if self.options.warning:
            options['warning'] = self.options.warning
        if self.options.critical:
            options['critical'] = self.options.critical
        if self.options.threads:
            options['threads'] = self.options.threads
        if self.options.exclude_columns:
            options['exclude_columns'] = self.options.exclude_columns
        if self.options.row_count_max_ratio:
            options['row_count_max_ratio'] = self.options.row_count_max_ratio
        if self.options.display_row_count_max_ratio_columns:
            options[
                'display_row_count_max_ratio_columns'] = self.options.display_row_count_max_ratio_columns

        if self.options.results_host:
            options['results_host'] = self.options.results_host
        if self.options.results_database:
            options['results_database'] = self.options.results_database
        if self.options.results_user:
            options['results_user'] = self.options.results_user
        if self.options.results_password:
            options['results_password'] = self.options.results_password
        if self.options.results_port:
            options['results_port'] = self.options.results_port

        options['scan_all_columns'] = self.options.scan_all_columns
        options['secondary_keys'] = self.options.secondary_keys

        if additional_options:
            options.update(additional_options)
        return options

    def create_exclude_columns_dict(self, s):
        """Convert string of format 'schema.table=col1,colN;...' to dict."""
        d = {}
        items = s.split(';')
        for item in items:
            schema_table, columns = item.split('=')
            column_list = columns.split(',')
            d[schema_table] = column_list
        return d

    def merge_options(self):
        self.config_options = self.get_options_from_config_file()
        merged_options = self.get_merged_options(self.config_options)

        # Thresholds
        if self.config_options and 'critical' in self.config_options:
            critical = float(self.config_options['critical'])
        else:
            critical = (float(self.options.critical.__str__())
                        if self.options.critical is not None else 100)
        if self.config_options and 'warning' in self.config_options:
            warning = float(self.config_options['warning'])
        else:
            warning = (float(self.options.warning.__str__())
                       if self.options.warning is not None else 100)

        merged_options['critical'] = critical
        merged_options['warning'] = warning

        # fix string versions of ignore_dbs, use_dbs, exclude_columns
        if 'ignore_dbs' in merged_options:
            ignore_dbs = merged_options['ignore_dbs']
            if ignore_dbs and isinstance(ignore_dbs, basestring):
                # convert string to list
                ignore_dbs = ignore_dbs.strip()
                if ignore_dbs:
                    merged_options['ignore_dbs'] = ignore_dbs.split(',')
        if 'use_dbs' in merged_options:
            use_dbs = merged_options['use_dbs']
            if use_dbs and isinstance(use_dbs, basestring):
                # convert string to list
                use_dbs = use_dbs.strip()
                if use_dbs:
                    merged_options['use_dbs'] = use_dbs.split(',')
        if 'exclude_columns' in merged_options:
            exclude_columns = merged_options['exclude_columns']
            if exclude_columns and isinstance(exclude_columns, basestring):
                # convert string to dict
                exclude_columns = exclude_columns.strip('; ')
                if exclude_columns:
                    merged_options['exclude_columns'] = (
                        self.create_exclude_columns_dict(exclude_columns))

        self.merged_options = merged_options

    def get_schema_tables(self):
        merged_options = self.merged_options

        query = """
            SELECT
                c.TABLE_SCHEMA, c.TABLE_NAME, c.COLUMN_NAME, c.COLUMN_TYPE,
                t.TABLE_ROWS, c.COLUMN_KEY, s.SEQ_IN_INDEX
            FROM INFORMATION_SCHEMA.COLUMNS c
            LEFT JOIN INFORMATION_SCHEMA.TABLES t
            ON c.TABLE_SCHEMA = t.TABLE_SCHEMA AND c.TABLE_NAME = t.TABLE_NAME
            LEFT JOIN INFORMATION_SCHEMA.STATISTICS s
            ON c.TABLE_SCHEMA = s.TABLE_SCHEMA AND c.TABLE_NAME = s.TABLE_NAME AND c.COLUMN_NAME = s.COLUMN_NAME
            WHERE c.COLUMN_TYPE LIKE '%int%'
        """

        if 'use_dbs' in merged_options:
            # set comma separated schema names enclosed in single-quotes
            use_dbs = ','.join("'%s'" % (db, )
                               for db in merged_options['use_dbs'])
            if use_dbs:
                query += """
                    AND c.TABLE_SCHEMA IN (%s)
                    """ % (use_dbs, )

        if 'ignore_dbs' in merged_options:
            # set comma separated schema names enclosed in single-quotes
            ignore_dbs = ','.join("'%s'" % (db, )
                                  for db in merged_options['ignore_dbs'])
            if ignore_dbs:
                query += """
                    AND c.TABLE_SCHEMA NOT IN (%s)
                    """ % (ignore_dbs, )

        conn = create_connection(merged_options)
        try:
            log.debug('%s' % (query, ))
            rows = fetchall(conn, query)
            log.debug('len(rows)=%s' % (len(rows), ))
            log.debug(pprint.pformat(rows))

            if 'exclude_columns' in self.merged_options:
                exclude_columns = self.merged_options['exclude_columns']
            else:
                exclude_columns = None

            schema_tables = {}
            added_columns = []

            for row in rows:
                schema = row[0]
                table = row[1]
                column = row[2]
                column_type = row[3]
                row_count = row[4]
                column_key = row[5]
                if column_key is not None:
                    column_key = column_key.strip().lower()
                seq_in_index = row[6]

                scan_secondary_keys = merged_options['secondary_keys']
                scan_all_columns = merged_options['scan_all_columns']

                schema_table = '%s.%s' % (schema, table)
                if (exclude_columns and schema_table in exclude_columns
                        and column in exclude_columns[schema_table]):
                    # this column is excluded

                    log.debug('Excluded column: %s.%s.%s' %
                              (schema, table, column))

                    pass
                else:
                    include_column = False

                    if column_key and column_key == 'pri':
                        # always include primary keys
                        include_column = True

                    if scan_secondary_keys:
                        if (column_key and column_key != 'pri' and seq_in_index
                                and seq_in_index == 1):
                            include_column = True

                    # if (
                    #         (not merged_options['primary_keys']) and
                    #         (not merged_options['secondary_keys'])):
                    #     include_column = True
                    if scan_all_columns:
                        include_column = True

                    if include_column:
                        column_to_add = '%s.%s.%s' % (schema, table, column)
                        if column_to_add in added_columns:
                            # prevent duplicates
                            include_column = False
                        else:
                            added_columns.append(column_to_add)

                    if include_column:
                        if schema_table in schema_tables:
                            schema_tables[schema_table]['columns'].append(
                                dict(column_name=column,
                                     column_type=column_type))
                        else:
                            schema_tables[schema_table] = dict(
                                schema=schema,
                                table=table,
                                row_count=row_count,
                                columns=[
                                    dict(column_name=column,
                                         column_type=column_type)
                                ])

            # end for
        finally:
            conn.close()

        return schema_tables

    def configure_logging(self):
        try:
            from logging.config import dictConfig
        except ImportError:
            from logutils.dictconfig import dictConfig

        if 'logging' in self.merged_options and self.merged_options['logging']:
            dictConfig(self.merged_options['logging'])

    def check(self):
        try:
            self.merge_options()
            self.configure_logging()

            merged_options = self.merged_options
            hostname = ''
            if 'hostname' in merged_options and merged_options['hostname']:
                hostname = merged_options['hostname']
            self.results_db_conn_opts = {}

            if 'results_host' in merged_options and merged_options[
                    'results_host']:
                self.results_db_conn_opts['host'] = merged_options[
                    'results_host']

            if 'results_port' in merged_options and merged_options[
                    'results_port']:
                self.results_db_conn_opts['port'] = merged_options[
                    'results_port']

            if 'results_user' in merged_options and merged_options[
                    'results_user']:
                self.results_db_conn_opts['user'] = merged_options[
                    'results_user']

            if 'results_password' in merged_options and merged_options[
                    'results_password']:
                self.results_db_conn_opts['passwd'] = merged_options[
                    'results_password']

            if 'results_database' in merged_options and merged_options[
                    'results_database']:
                self.results_db_conn_opts['db'] = merged_options[
                    'results_database']

            if self.results_db_conn_opts:
                if not ('db' in self.results_db_conn_opts
                        and self.results_db_conn_opts['db']):
                    raise Error('results_database is required.')

            log.debug('Check started with the following options:\n%s' %
                      (pprint.pformat(self.merged_options), ))

            schema_tables = self.get_schema_tables()

            log.debug('Schema tables:\n%s' % (pprint.pformat(schema_tables), ))

            q = Queue.Queue()
            for v in schema_tables.itervalues():
                q.put(v)

            threads = self.merged_options['threads']
            results = Queue.Queue()
            thread_list = []
            for n in range(threads):
                thread = TableProcessor(schema_tables=q,
                                        merged_options=self.merged_options,
                                        results=results)
                thread.name = 'Thread #%d' % (n, )
                thread.daemon = True
                thread.start()
                thread_list.append(thread)

            # wait for all threads to finish
            log.debug('Waiting for all threads to finish running.')
            while True:
                dead = []
                for thread in thread_list:
                    dead.append(not thread.is_alive())
                if all(dead):
                    break
                time.sleep(0.01)
            log.debug('All threads finished.')

            critical_columns = []
            warning_columns = []
            errors = []
            investigate_columns = []
            while True:
                try:
                    result = results.get_nowait()

                    if 'critical_column' in result:
                        critical_columns.append(result['critical_column'])

                    if 'warning_column' in result:
                        warning_columns.append(result['warning_column'])

                    if 'error' in result:
                        errors.append(result['error'])

                    if 'investigate_column' in result:
                        investigate_columns.append(
                            result['investigate_column'])

                    results.task_done()
                except Queue.Empty, e:
                    break

            log.info('Critical columns:\n%s\n\nWarning columns:\n%s' %
                     (pprint.pformat(critical_columns),
                      pprint.pformat(warning_columns)))

            if len(critical_columns) > 0:
                columns = sorted(critical_columns) + sorted(warning_columns)
                status = pynagios.CRITICAL
            elif len(warning_columns) > 0:
                columns = warning_columns
                status = pynagios.WARNING
            else:
                status = pynagios.OK

            msg = ''
            if status != pynagios.OK:
                msg = '\n'.join(
                    '%s.%s\t%s\t%s\t%s\t%.2f%%' %
                    (col.get('schema'), col.get('table'),
                     col.get('column_name'), col.get('column_type'),
                     col.get('max_value'), col.get('overflow_percentage'))
                    for col in columns)
                msg = '\n' + msg

                ##############################################################
                # store critical/warning columns in db
                ##############################################################
                if self.results_db_conn_opts:
                    conn = MySQLdb.connect(**self.results_db_conn_opts)
                    with conn as cursor:
                        sql = ("INSERT INTO int_overflow_check_results("
                               "  hostname, dbname, table_name, column_name, "
                               "  max_size, percentage, reason, timestamp) "
                               "VALUE (%s, %s, %s, %s, %s, %s, %s, %s)")

                        for col in critical_columns:
                            cursor.execute(
                                sql,
                                (hostname, col.get('schema'), col.get('table'),
                                 col.get('column_name'), col.get('max_value'),
                                 col.get('overflow_percentage'), 'critical',
                                 datetime.datetime.now()))

                        for col in warning_columns:
                            cursor.execute(
                                sql,
                                (hostname, col.get('schema'), col.get('table'),
                                 col.get('column_name'), col.get('max_value'),
                                 col.get('overflow_percentage'), 'warning',
                                 datetime.datetime.now()))

            row_count_max_ratio = self.merged_options.get(
                'row_count_max_ratio', 0)
            if investigate_columns:
                log.info('Investigate columns:\n%s' %
                         (pprint.pformat(investigate_columns, )))
                if msg:
                    msg += '\n'
                msg += ((
                    '\nColumns containing high values compared to maximum for the column datatype, but number of rows is less than %s%% of maximum for the column type:\n'
                    % (row_count_max_ratio, )) + ('\n'.join(
                        '%s.%s\t%s\t%s\t%s\t%.2f%%' %
                        (col.get('schema'), col.get('table'),
                         col.get('column_name'), col.get('column_type'),
                         col.get('max_value'), col.get('overflow_percentage'))
                        for col in investigate_columns)))

                ##############################################################
                # store investigate columns in db
                ##############################################################
                if self.results_db_conn_opts:
                    conn = MySQLdb.connect(**self.results_db_conn_opts)
                    with conn as cursor:
                        sql = ("INSERT INTO int_overflow_check_results("
                               "  hostname, dbname, table_name, column_name, "
                               "  max_size, percentage, reason, timestamp) "
                               "VALUE (%s, %s, %s, %s, %s, %s, %s, %s)")

                        for col in investigate_columns:
                            cursor.execute(
                                sql,
                                (hostname, col.get('schema'), col.get('table'),
                                 col.get('column_name'), col.get('max_value'),
                                 col.get('overflow_percentage'), 'investigate',
                                 datetime.datetime.now()))

            log.info('status: %s\n\nmsg:\n%s' % (status, msg))

            self.exit_code = status.exit_code
            return Response(status, msg)
        except Exception, e:
            log.exception('Exception.')
            return Response(pynagios.UNKNOWN, 'ERROR: {0}'.format(e))
Example #28
0
 def test_status_gets_set_by_initializer(self):
     "Tests that the status can be set by the constructor."
     instance = Response(pynagios.OK)
     assert pynagios.OK == instance.status
Example #29
0
def main(args):
    try:
        return GraphiteNagios(args).check().exit()
    except Exception as e:
        message = "{0}: {1}".format(e.__class__.__name__, str(e))
        Response(UNKNOWN, "Client error: " + message).exit()
 def parseResult(self, data):
     return Response(UNKNOWN, "No result set!")
	def parseResult(self, data):
		if data['status'] == 'ok':
			return Response(OK, "Response status was ok")
		return Response(CRITICAL, data['status'])
        }
        for proc in procs:
            processes[proc['statename']].append(proc['name'])

        ret = OK
        for state in ('STOPPING', 'STARTING'):
            if len(processes[state]):
                ret = WARNING

        if len(processes['UNKNOWN']):
            ret = UNKNOWN

        for state in ('EXITED', 'BACKOFF', 'FATAL'):
            if len(processes[state]):
                ret = CRITICAL

        result = Response(ret, processes)

        msg = []
        for k, v in processes.items():
            if v:
                msg.append('%s: %s' % (k, ', '.join(v)))
            result.set_perf_data(k, len(v))

        result.message = ' '.join(msg)
        return result


if __name__ == '__main__':
    SupervisordXmlRpcCheck().check().exit()