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!')
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)
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")
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
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
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])
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)
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)
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)
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
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()
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))
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
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)
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))
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()
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))
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
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()