[Pkg-nagios-changes] [pkg-nagios-plugins-contrib] 11/24: check_mongodb: Updating to latest version 3805751

Jan Wagner waja at moszumanska.debian.org
Wed Dec 13 22:07:35 UTC 2017


This is an automated email from the git hooks/post-receive script.

waja pushed a commit to branch master
in repository pkg-nagios-plugins-contrib.

commit 3eb4cf6ac79220a1a6175dec974780ba88c473f7
Author: Jan Wagner <waja at cyconet.org>
Date:   Tue Nov 28 21:53:48 2017 +0100

    check_mongodb: Updating to latest version 3805751
---
 check_mongodb/check_mongodb.py | 142 ++++++++++++++++++++++++++++-------------
 check_mongodb/control          |   2 +-
 2 files changed, 99 insertions(+), 45 deletions(-)

diff --git a/check_mongodb/check_mongodb.py b/check_mongodb/check_mongodb.py
index 11654fb..9f96116 100644
--- a/check_mongodb/check_mongodb.py
+++ b/check_mongodb/check_mongodb.py
@@ -18,7 +18,8 @@
 #   - @Andor on github
 #   - Steven Richards - Captainkrtek on github
 #   - Max Vernimmen - @mvernimmen-CG / @mvernimmen on github
-#   - Kris Childress - @kris at nivenly.com github.com/kris-nova
+#   - Kris Nova - @kris at nivenly.com github.com/kris-nova
+#   - Jan Kantert - firstname at lastname.net
 #
 # USAGE
 #
@@ -126,14 +127,16 @@ def main(argv):
     p = optparse.OptionParser(conflict_handler="resolve", description="This Nagios plugin checks the health of mongodb.")
 
     p.add_option('-H', '--host', action='store', type='string', dest='host', default='127.0.0.1', help='The hostname you want to connect to')
+    p.add_option('-h', '--host-to-check', action='store', type='string', dest='host_to_check', default=None, help='The hostname you want to check (if this is different from the host you are connecting)')
     p.add_option('-P', '--port', action='store', type='int', dest='port', default=27017, help='The port mongodb is running on')
+    p.add_option('--port-to-check', action='store', type='int', dest='port_to_check', default=None, help='The port you want to check (if this is different from the port you are connecting)')
     p.add_option('-u', '--user', action='store', type='string', dest='user', default=None, help='The username you want to login as')
     p.add_option('-p', '--pass', action='store', type='string', dest='passwd', default=None, help='The password you want to use for that user')
     p.add_option('-W', '--warning', action='store', dest='warning', default=None, help='The warning threshold you want to set')
     p.add_option('-C', '--critical', action='store', dest='critical', default=None, help='The critical threshold you want to set')
     p.add_option('-A', '--action', action='store', type='choice', dest='action', default='connect', help='The action you want to take',
                  choices=['connect', 'connections', 'replication_lag', 'replication_lag_percent', 'replset_state', 'memory', 'memory_mapped', 'lock',
-                          'flushing', 'last_flush_time', 'index_miss_ratio', 'databases', 'collections', 'database_size', 'database_indexes', 'collection_indexes', 'collection_size',
+                          'flushing', 'last_flush_time', 'index_miss_ratio', 'databases', 'collections', 'database_size', 'database_indexes', 'collection_documents', 'collection_indexes', 'collection_size',
                           'collection_storageSize', 'queues', 'oplog', 'journal_commits_in_wl', 'write_data_files', 'journaled', 'opcounters', 'current_lock', 'replica_primary',
                           'page_faults', 'asserts', 'queries_per_second', 'page_faults', 'chunks_balance', 'connect_primary', 'collection_state', 'row_count', 'replset_quorum'])
     p.add_option('--max-lag', action='store_true', dest='max_lag', default=False, help='Get max replication lag (for replication_lag action only)')
@@ -150,11 +153,14 @@ def main(argv):
       choices=['2','3'])
     p.add_option('-a', '--authdb', action='store', type='string', dest='authdb', default='admin', help='The database you want to authenticate against')
     p.add_option('--insecure', action='store_true', dest='insecure', default=False, help="Don't verify SSL/TLS certificates")
+    p.add_option('--ssl-ca-cert-file', action='store', type='string', dest='ssl_ca_cert_file', default=None, help='Path to Certificate Authority file for SSL')
     p.add_option('-f', '--ssl-cert-file', action='store', type='string', dest='cert_file', default=None, help='Path to PEM encoded key and cert for client authentication')
 
     options, arguments = p.parse_args()
     host = options.host
+    host_to_check = options.host_to_check if options.host_to_check else options.host
     port = options.port
+    port_to_check = options.port_to_check if options.port_to_check else options.port
     user = options.user
     passwd = options.passwd
     authdb = options.authdb
@@ -177,6 +183,7 @@ def main(argv):
     ssl = options.ssl
     replicaset = options.replicaset
     insecure = options.insecure
+    ssl_ca_cert_file = options.ssl_ca_cert_file
     cert_file = options.cert_file
 
     if action == 'replica_primary' and replicaset is None:
@@ -188,7 +195,7 @@ def main(argv):
     # moving the login up here and passing in the connection
     #
     start = time.time()
-    err, con = mongo_connect(host, port, ssl, user, passwd, replicaset, authdb, insecure, cert_file)
+    err, con = mongo_connect(host, port, ssl, user, passwd, replicaset, authdb, insecure, ssl_ca_cert_file, cert_file)
 
     if err != 0:
         return err
@@ -204,9 +211,9 @@ def main(argv):
     if action == "connections":
         return check_connections(con, warning, critical, perf_data)
     elif action == "replication_lag":
-        return check_rep_lag(con, host, warning, critical, False, perf_data, max_lag, user, passwd)
+        return check_rep_lag(con, host_to_check, port_to_check, warning, critical, False, perf_data, max_lag, user, passwd)
     elif action == "replication_lag_percent":
-        return check_rep_lag(con, host, warning, critical, True, perf_data, max_lag, user, passwd, ssl, insecure, cert_file)
+        return check_rep_lag(con, host_to_check, port_to_check, warning, critical, True, perf_data, max_lag, user, passwd, ssl, insecure, ssl_ca_cert_file, cert_file)
     elif action == "replset_state":
         return check_replset_state(con, perf_data, warning, critical)
     elif action == "memory":
@@ -240,6 +247,8 @@ def main(argv):
             return check_database_size(con, database, warning, critical, perf_data)
     elif action == "database_indexes":
         return check_database_indexes(con, database, warning, critical, perf_data)
+    elif action == "collection_documents":
+        return check_collection_documents(con, database, collection, warning, critical, perf_data)
     elif action == "collection_indexes":
         return check_collection_indexes(con, database, collection, warning, critical, perf_data)
     elif action == "collection_size":
@@ -274,7 +283,7 @@ def main(argv):
         return check_connect(host, port, warning, critical, perf_data, user, passwd, conn_time)
 
 
-def mongo_connect(host=None, port=None, ssl=False, user=None, passwd=None, replica=None, authdb="admin", insecure=False, ssl_cert=None):
+def mongo_connect(host=None, port=None, ssl=False, user=None, passwd=None, replica=None, authdb="admin", insecure=False, ssl_ca_cert_file=None, ssl_cert=None):
     from pymongo.errors import ConnectionFailure
     from pymongo.errors import PyMongoError
     import ssl as SSL
@@ -287,8 +296,10 @@ def mongo_connect(host=None, port=None, ssl=False, user=None, passwd=None, repli
         else:
             con_args['ssl_cert_reqs'] = SSL.CERT_REQUIRED
         con_args['ssl'] = ssl
+        if ssl_ca_cert_file:
+            con_args['ssl_ca_certs'] = ssl_ca_cert_file
         if ssl_cert:
-	    con_args['ssl_certfile'] = ssl_cert
+            con_args['ssl_certfile'] = ssl_cert
 
     try:
         # ssl connection for pymongo > 2.3
@@ -299,10 +310,9 @@ def mongo_connect(host=None, port=None, ssl=False, user=None, passwd=None, repli
                 con = pymongo.MongoClient(host, port, read_preference=pymongo.ReadPreference.SECONDARY, replicaSet=replica, **con_args)
         else:
             if replica is None:
-                con = pymongo.MongoClient(host, port, slave_okay=True)
+                con = pymongo.Connection(host, port, slave_okay=True, network_timeout=10)
             else:
-                con = pymongo.MongoClient(host, port, slave_okay=True)
-                #con = pymongo.Connection(host, port, slave_okay=True, replicaSet=replica, network_timeout=10)
+                con = pymongo.Connection(host, port, slave_okay=True, network_timeout=10)
 
         try:
           result = con.admin.command("ismaster")
@@ -321,6 +331,9 @@ def mongo_connect(host=None, port=None, ssl=False, user=None, passwd=None, repli
             except PyMongoError:
                 sys.exit("Username/Password incorrect")
 
+        # Ping to check that the server is responding.
+        con.admin.command("ping")
+
     except Exception, e:
         if isinstance(e, pymongo.errors.AutoReconnect) and str(e).find(" is an arbiter") != -1:
             # We got a pymongo AutoReconnect exception that tells us we connected to an Arbiter Server
@@ -389,12 +402,12 @@ def check_connections(con, warning, critical, perf_data):
         return exit_with_general_critical(e)
 
 
-def check_rep_lag(con, host, warning, critical, percent, perf_data, max_lag, user, passwd, ssl=None, insecure=None, cert_file=None):
+def check_rep_lag(con, host, port, warning, critical, percent, perf_data, max_lag, user, passwd, ssl=None, insecure=None, ssl_ca_cert_file=None, cert_file=None):
     # Get mongo to tell us replica set member name when connecting locally
     if "127.0.0.1" == host:
         if not "me" in con.admin.command("ismaster","1").keys():
-            print "OK - This is not replicated MongoDB"
-            sys.exit(3)
+            print "UNKNOWN - This is not replicated MongoDB"
+            return 3
 
         host = con.admin.command("ismaster","1")["me"].split(':')[0]
 
@@ -414,8 +427,8 @@ def check_rep_lag(con, host, warning, critical, percent, perf_data, max_lag, use
             rs_status = con.admin.command("replSetGetStatus")
         except pymongo.errors.OperationFailure, e:
             if ((e.code == None and str(e).find('failed: not running with --replSet"')) or (e.code == 76 and str(e).find('not running with --replSet"'))):
-                print "OK - Not running with replSet"
-                return 0
+                print "UNKNOWN - Not running with replSet"
+                return 3
 
         serverVersion = tuple(con.server_info()['version'].split('.'))
         if serverVersion >= tuple("2.0.0".split(".")):
@@ -436,7 +449,7 @@ def check_rep_lag(con, host, warning, critical, percent, perf_data, max_lag, use
             for member in rs_status["members"]:
                 if member["stateStr"] == "PRIMARY":
                     primary_node = member
-                if member.get('self') == True:
+                if member.get('name') == "{0}:{1}".format(host, port):
                     host_node = member
 
             # Check if we're in the middle of an election and don't have a primary
@@ -478,8 +491,8 @@ def check_rep_lag(con, host, warning, critical, percent, perf_data, max_lag, use
                         message += performance_data(perf_data, [(maximal_lag, "replication_lag", warning, critical)])
                     return check_levels(maximal_lag, warning, critical, message)
             elif host_node["stateStr"] == "ARBITER":
-                print "OK - This is an arbiter"
-                return 0
+                print "UNKNOWN - This is an arbiter"
+                return 3
 
             # Find the difference in optime between current node and PRIMARY
 
@@ -498,7 +511,7 @@ def check_rep_lag(con, host, warning, critical, percent, perf_data, max_lag, use
                 lag = float(optime_lag.seconds + optime_lag.days * 24 * 3600)
 
             if percent:
-                err, con = mongo_connect(primary_node['name'].split(':')[0], int(primary_node['name'].split(':')[1]), ssl, user, passwd, None, None, insecure, cert_file)
+                err, con = mongo_connect(primary_node['name'].split(':')[0], int(primary_node['name'].split(':')[1]), ssl, user, passwd, None, None, insecure, ssl_ca_cert_file, cert_file)
                 if err != 0:
                     return err
                 primary_timediff = replication_get_time_diff(con)
@@ -800,42 +813,61 @@ def check_replset_state(con, perf_data, warning="", critical=""):
 
     ok = range(-1, 8)  # should include the range of all posiible values
     try:
+        worst_state = -2
+        message = ""
         try:
             try:
                 set_read_preference(con.admin)
                 data = con.admin.command(pymongo.son_manipulator.SON([('replSetGetStatus', 1)]))
             except:
                 data = con.admin.command(son.SON([('replSetGetStatus', 1)]))
-            state = int(data['myState'])
+            members = data['members'];
+            my_state = int(data['myState'])
+            worst_state = my_state
+            for member in members:
+                their_state = int(member['state'])
+                message += " %s: %i (%s)" % (member['name'], their_state, state_text(their_state))
+                if state_is_worse(their_state, worst_state, warning, critical):
+                    worst_state = their_state;
+            message += performance_data(perf_data, [(my_state, "state")])
+
         except pymongo.errors.OperationFailure, e:
             if ((e.code == None and str(e).find('failed: not running with --replSet"')) or (e.code == 76 and str(e).find('not running with --replSet"'))):
-                state = -1
-
-        if state == 8:
-            message = "State: %i (Down)" % state
-        elif state == 4:
-            message = "State: %i (Fatal error)" % state
-        elif state == 0:
-            message = "State: %i (Starting up, phase1)" % state
-        elif state == 3:
-            message = "State: %i (Recovering)" % state
-        elif state == 5:
-            message = "State: %i (Starting up, phase2)" % state
-        elif state == 1:
-            message = "State: %i (Primary)" % state
-        elif state == 2:
-            message = "State: %i (Secondary)" % state
-        elif state == 7:
-            message = "State: %i (Arbiter)" % state
-        elif state == -1:
-            message = "Not running with replSet"
-        else:
-            message = "State: %i (Unknown state)" % state
-        message += performance_data(perf_data, [(state, "state")])
-        return check_levels(state, warning, critical, message, ok)
+                worst_state = -1
+
+        return check_levels(worst_state, warning, critical, message, ok)
     except Exception, e:
         return exit_with_general_critical(e)
 
+def state_is_worse(state, worst_state, warning, critical):
+    if worst_state in critical:
+        return False
+    if worst_state in warning:
+        return state in critical
+    return (state in warning) or (state in critical)
+
+def state_text(state):
+    if state == 8:
+        return "Down"
+    elif state == 4:
+        return "Fatal error"
+    elif state == 0:
+        return "Starting up, phase1"
+    elif state == 3:
+        return "Recovering"
+    elif state == 5:
+        return "Starting up, phase2"
+    elif state == 1:
+        return  "Primary"
+    elif state == 2:
+        return  "Secondary"
+    elif state == 7:
+        return  "Arbiter"
+    elif state == -1:
+        return  "Not running with replSet"
+    else:
+        return  "Unknown state"
+
 
 def check_databases(con, warning, critical, perf_data=None):
     try:
@@ -953,6 +985,28 @@ def check_database_indexes(con, database, warning, critical, perf_data):
         return exit_with_general_critical(e)
 
 
+def check_collection_documents(con, database, collection, warning, critical, perf_data):
+    perfdata = ""
+    try:
+        set_read_preference(con.admin)
+        data = con[database].command('collstats', collection)
+        documents = data['count']
+        if perf_data:
+            perfdata += " | collection_documents=%i;%i;%i" % (documents, warning, critical)
+
+        if documents >= critical:
+            print "CRITICAL - %s.%s documents: %s %s" % (database, collection, documents, perfdata)
+            return 2
+        elif documents >= warning:
+            print "WARNING - %s.%s documents: %s %s" % (database, collection, documents, perfdata)
+            return 1
+        else:
+            print "OK - %s.%s documents: %s %s" % (database, collection, documents, perfdata)
+            return 0
+    except Exception, e:
+        return exit_with_general_critical(e)
+
+
 def check_collection_indexes(con, database, collection, warning, critical, perf_data):
     #
     # These thresholds are basically meaningless, and must be customized to your application
diff --git a/check_mongodb/control b/check_mongodb/control
index 33a2012..067df0c 100644
--- a/check_mongodb/control
+++ b/check_mongodb/control
@@ -1,6 +1,6 @@
 Uploaders: Jan Wagner <waja at cyconet.org>
 Recommends: python-pymongo
-Version: 7248618
+Version: 3805751
 Homepage: https://github.com/mzupan/nagios-plugin-mongodb
 Watch: https://github.com/mzupan/nagios-plugin-mongodb <a class="commit-tease-sha"[^>]*>\s+([0-9a-f]+)\s+</a>
 Description: Plugin script to monitor your MongoDB server(s)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-nagios/pkg-nagios-plugins-contrib.git



More information about the Pkg-nagios-changes mailing list