Module: check_mk
Branch: master
Commit: 5966bf6c178d19792f54d50539c44da20f387081
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=5966bf6c178d19…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Tue Aug 29 10:45:36 2017 +0200
5054 FIX SNMPv3 contextes were not always used during discovery
The SNMPv3 contextes configured for a host were not used correctly for the SNMP-GET
request made during service discovery. This has been fixed now. When a single OID
is requested by Check_MK all configured contextes for a check will be queried until
an answer is recevied using a context. e.g. in case you have configured two contextes
for a check, the first configured context will be queried first. In case it answers
with the OID, this value will be used. In case the requested OID does not exist in
this context, the next contex will be queried.
The check independent OIDs .1.3.6.1.2.1.1.1.0 and .1.3.6.1.2.1.1.2.0 will always
be queried without context.
Change-Id: I1c0a046c7c839c2109c536db3e40a6f83488c88d
---
.werks/5054 | 19 +++++++++++++++++++
cmk_base/classic_snmp.py | 19 ++++++++++---------
cmk_base/discovery.py | 2 +-
cmk_base/snmp.py | 32 ++++++++++++++++++++++----------
4 files changed, 52 insertions(+), 20 deletions(-)
diff --git a/.werks/5054 b/.werks/5054
new file mode 100644
index 0000000..306cb1b
--- /dev/null
+++ b/.werks/5054
@@ -0,0 +1,19 @@
+Title: SNMPv3 contextes were not always used during discovery
+Level: 1
+Component: core
+Compatible: compat
+Edition: cre
+Version: 1.5.0i1
+Date: 1503996131
+Class: fix
+
+The SNMPv3 contextes configured for a host were not used correctly for the SNMP-GET
+request made during service discovery. This has been fixed now. When a single OID
+is requested by Check_MK all configured contextes for a check will be queried until
+an answer is recevied using a context. e.g. in case you have configured two contextes
+for a check, the first configured context will be queried first. In case it answers
+with the OID, this value will be used. In case the requested OID does not exist in
+this context, the next contex will be queried.
+
+The check independent OIDs .1.3.6.1.2.1.1.1.0 and .1.3.6.1.2.1.1.2.0 will always
+be queried without context.
diff --git a/cmk_base/classic_snmp.py b/cmk_base/classic_snmp.py
index 82cff9f..fa4a5d9 100644
--- a/cmk_base/classic_snmp.py
+++ b/cmk_base/classic_snmp.py
@@ -48,12 +48,10 @@ from cmk_base.exceptions import MKSNMPError
# | Implements the neccessary function for Check_MK |
# '----------------------------------------------------------------------'
-def walk(hostname, ip, oid, hex_plain = False, context_name = None):
+def walk(hostname, ip, oid, hex_plain=False, context_name=None):
protospec = _snmp_proto_spec(hostname)
portspec = _snmp_port_spec(hostname)
- command = _snmp_walk_command(hostname)
- if context_name != None:
- command += [ "-n", context_name ]
+ command = _snmp_walk_command(hostname, context_name)
command += [ "-OQ", "-OU", "-On", "-Ot",
"%s%s%s" % (protospec, ip, portspec), oid ]
debug_cmd = [ "''" if a == "" else a for a in command ]
@@ -102,7 +100,7 @@ def walk(hostname, ip, oid, hex_plain = False, context_name = None):
return rowinfo
-def get(hostname, ipaddress, oid):
+def get(hostname, ipaddress, oid, context_name=None):
if oid.endswith(".*"):
oid_prefix = oid[:-2]
commandtype = "getnext"
@@ -112,7 +110,7 @@ def get(hostname, ipaddress, oid):
protospec = _snmp_proto_spec(hostname)
portspec = _snmp_port_spec(hostname)
- command = _snmp_base_command(commandtype, hostname) + \
+ command = _snmp_base_command(commandtype, hostname, context_name) + \
[ "-On", "-OQ", "-Oe", "-Ot",
"%s%s%s" % (protospec, ipaddress, portspec),
oid_prefix ]
@@ -168,8 +166,8 @@ def _snmp_proto_spec(hostname):
# Returns command lines for snmpwalk and snmpget including
# options for authentication. This handles communities and
# authentication for SNMP V3. Also bulkwalk hosts
-def _snmp_walk_command(hostname):
- return _snmp_base_command('walk', hostname) + [ "-Cc" ]
+def _snmp_walk_command(hostname, context_name):
+ return _snmp_base_command('walk', hostname, context_name) + [ "-Cc"
]
# if the credentials are a string, we use that as community,
@@ -181,7 +179,7 @@ def _snmp_walk_command(hostname):
# And if it is a six-tuple, it has the following additional arguments:
# (5) privacy protocol (DES|AES) (-x)
# (6) privacy protocol pass phrase (-X)
-def _snmp_base_command(what, hostname):
+def _snmp_base_command(what, hostname, context_name):
options = []
if what == 'get':
@@ -242,6 +240,9 @@ def _snmp_base_command(what, hostname):
if "retries" in settings:
options += [ "-r", "%d" % settings["retries"] ]
+ if context_name != None:
+ options += [ "-n", context_name ]
+
return command + options
#.
diff --git a/cmk_base/discovery.py b/cmk_base/discovery.py
index 8e0e142..550f914 100644
--- a/cmk_base/discovery.py
+++ b/cmk_base/discovery.py
@@ -838,7 +838,7 @@ def snmp_scan(hostname, ipaddress, on_error = "ignore",
for_inv=False):
if scan_function:
try:
def oid_function(oid, default_value=None):
- value = snmp.get_single_oid(hostname, ipaddress, oid)
+ value = snmp.get_single_oid(hostname, ipaddress, oid, check_type)
if value == None:
return default_value
else:
diff --git a/cmk_base/snmp.py b/cmk_base/snmp.py
index 3c57bd5..36d424a 100644
--- a/cmk_base/snmp.py
+++ b/cmk_base/snmp.py
@@ -206,7 +206,8 @@ def get_snmp_table(hostname, ip, check_type, oid_info,
use_snmpwalk_cache):
return info
-def get_single_oid(hostname, ipaddress, oid):
+# Contextes can only be used when check_type is given.
+def get_single_oid(hostname, ipaddress, oid, check_type=None):
# New in Check_MK 1.1.11: oid can end with ".*". In that case
# we do a snmpgetnext and try to find an OID with the prefix
# in question. The *cache* is working including the X, however.
@@ -236,15 +237,26 @@ def get_single_oid(hostname, ipaddress, oid):
value = None
else:
- try:
- if config.is_inline_snmp_host(hostname):
- value = inline_snmp.get(hostname, oid, ipaddress=ipaddress)
- else:
- value = classic_snmp.get(hostname, ipaddress, oid)
- except:
- if cmk.debug.enabled():
- raise
- value = None
+ # get_single_oid() can only return a single value. When SNMPv3 is used with
multiple
+ # SNMP contexts, all contextes will be queried until the first answer is
received.
+ if check_type is not None and config.is_snmpv3_host(hostname):
+ snmp_contexts = _snmpv3_contexts_of(hostname, check_type)
+ else:
+ snmp_contexts = [None]
+
+ for context_name in snmp_contexts:
+ try:
+ if config.is_inline_snmp_host(hostname):
+ value = inline_snmp.get(hostname, oid, ipaddress=ipaddress,
context_name=context_name)
+ else:
+ value = classic_snmp.get(hostname, ipaddress, oid,
context_name=context_name)
+
+ if value is not None:
+ break # Use first received answer in case of multiple contextes
+ except:
+ if cmk.debug.enabled():
+ raise
+ value = None
if value != None:
console.vverbose("%s%s%s%s\n" % (tty.bold, tty.green, value,
tty.normal))