def _perform_snmpwalk(snmp_config, check_plugin_name, base_oid, fetchoid): # type: (SNMPHostConfig, CheckPluginName, OID, OID) -> SNMPRowInfo added_oids = set([]) # type: Set[OID] rowinfo = [] # type: SNMPRowInfo for context_name in snmp_config.snmpv3_contexts_of(check_plugin_name): rows = SNMPBackendFactory.walk(snmp_config, oid=fetchoid, check_plugin_name=check_plugin_name, table_base_oid=base_oid, context_name=context_name) # I've seen a broken device (Mikrotik Router), that broke after an # update to RouterOS v6.22. It would return 9 time the same OID when # .1.3.6.1.2.1.1.1.0 was being walked. We try to detect these situations # by removing any duplicate OID information if len(rows) > 1 and rows[0][0] == rows[1][0]: console.vverbose( "Detected broken SNMP agent. Ignoring duplicate OID %s.\n" % rows[0][0]) rows = rows[:1] for row_oid, val in rows: if row_oid in added_oids: console.vverbose("Duplicate OID found: %s (%r)\n" % (row_oid, val)) else: rowinfo.append((row_oid, val)) added_oids.add(row_oid) return rowinfo
def get_single_oid(snmp_config, oid, check_plugin_name=None, do_snmp_scan=True): # type: (SNMPHostConfig, str, Optional[str], bool) -> Optional[DecodedString] # The 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. if oid[0] != '.': if cmk.utils.debug.enabled(): raise MKGeneralException( "OID definition '%s' does not begin with a '.'" % oid) oid = '.' + oid # TODO: Use generic cache mechanism if snmp_cache.is_in_single_oid_cache(oid): console.vverbose(" Using cached OID %s: " % oid) cached_value = snmp_cache.get_oid_from_single_oid_cache(oid) console.vverbose("%s%s%r%s\n" % (tty.bold, tty.green, cached_value, tty.normal)) return cached_value # 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_plugin_name is not None and snmp_config.is_snmpv3_host: snmp_contexts = _snmpv3_contexts_of(snmp_config, check_plugin_name) else: snmp_contexts = [None] console.vverbose(" Getting OID %s: " % oid) for context_name in snmp_contexts: try: value = SNMPBackendFactory.get(snmp_config, use_cache=_enforce_stored_walks, oid=oid, context_name=context_name) if value is not None: break # Use first received answer in case of multiple contextes except Exception: if cmk.utils.debug.enabled(): raise value = None if value is not None: console.vverbose("%s%s%r%s\n" % (tty.bold, tty.green, value, tty.normal)) else: console.vverbose("failed.\n") if value is not None: decoded_value = convert_to_unicode( value, encoding=snmp_config.character_encoding ) # type: Optional[DecodedString] else: decoded_value = value snmp_cache.set_single_oid_cache(oid, decoded_value) return decoded_value
def walk_for_export(snmp_config, oid): # type: (SNMPHostConfig, OID) -> SNMPRowInfoForStoredWalk rows = SNMPBackendFactory.walk(snmp_config, use_cache=False, oid=oid) return _convert_rows_for_stored_walk(rows)