def _perform_snmpwalk(snmp_config, check_plugin_name, base_oid, fetchoid): added_oids = set([]) rowinfo = [] if snmp_utils.is_snmpv3_host(snmp_config): snmp_contexts = _snmpv3_contexts_of(snmp_config, check_plugin_name) else: snmp_contexts = [None] for context_name in snmp_contexts: snmp_backend = SNMPBackendFactory().factory(snmp_config, enforce_stored_walks=_enforce_stored_walks) rows = snmp_backend.walk(snmp_config, 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 (%s)\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: (snmp_utils.SNMPHostConfig, str, Optional[str], bool) -> Optional[str] # 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) else: oid = '.' + oid # TODO: Use generic cache mechanism if _is_in_single_oid_cache(snmp_config, oid): console.vverbose(" Using cached OID %s: " % oid) value = _get_oid_from_single_oid_cache(snmp_config, oid) console.vverbose("%s%s%s%s\n" % (tty.bold, tty.green, value, tty.normal)) return 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_utils.is_snmpv3_host( snmp_config): 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: snmp_backend = SNMPBackendFactory().factory( snmp_config, enforce_stored_walks=_enforce_stored_walks) value = snmp_backend.get(snmp_config, oid, 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%s%s\n" % (tty.bold, tty.green, value, tty.normal)) else: console.vverbose("failed.\n") set_single_oid_cache(snmp_config, oid, value) return value
def describe(self): snmp_config = self._snmp_config if snmp_config.is_usewalk_host: return "SNMP (use stored walk)" if snmp_config.is_inline_snmp_host: inline = "yes" else: inline = "no" if snmp_utils.is_snmpv3_host(snmp_config): credentials_text = "Credentials: '%s'" % ", ".join(snmp_config.credentials) else: credentials_text = "Community: %r" % snmp_config.credentials if snmp_utils.is_snmpv3_host(snmp_config) or snmp_config.is_bulkwalk_host: bulk = "yes" else: bulk = "no" return "%s (%s, Bulk walk: %s, Port: %d, Inline: %s)" % \ (self.title(), credentials_text, bulk, snmp_config.port, inline)
def _snmp_base_command(self, what, snmp_config, context_name): options = [] if what == 'get': command = ['snmpget'] elif what == 'getnext': command = ['snmpgetnext', '-Cf'] elif snmp_config.is_bulkwalk_host: command = ['snmpbulkwalk'] options.append("-Cr%d" % snmp_config.bulk_walk_size_of) else: command = ['snmpwalk'] if not snmp_utils.is_snmpv3_host(snmp_config): # Handle V1 and V2C if snmp_config.is_bulkwalk_host: options.append('-v2c') else: if what == 'walk': command = ['snmpwalk'] if snmp_config.is_snmpv2or3_without_bulkwalk_host: options.append('-v2c') else: options.append('-v1') options += ["-c", snmp_config.credentials] else: # Handle V3 if len(snmp_config.credentials) == 6: options += [ "-v3", "-l", snmp_config.credentials[0], "-a", snmp_config.credentials[1], "-u", snmp_config.credentials[2], "-A", snmp_config.credentials[3], "-x", snmp_config.credentials[4], "-X", snmp_config.credentials[5] ] elif len(snmp_config.credentials) == 4: options += [ "-v3", "-l", snmp_config.credentials[0], "-a", snmp_config.credentials[1], "-u", snmp_config.credentials[2], "-A", snmp_config.credentials[3] ] elif len(snmp_config.credentials) == 2: options += [ "-v3", "-l", snmp_config.credentials[0], "-u", snmp_config.credentials[1] ] else: raise MKGeneralException( "Invalid SNMP credentials '%r' for host %s: must be " "string, 2-tuple, 4-tuple or 6-tuple" % (snmp_config.credentials, snmp_config.hostname)) # Do not load *any* MIB files. This save lot's of CPU. options += ["-m", "", "-M", ""] # Configuration of timing and retries settings = snmp_config.timing if "timeout" in settings: options += ["-t", "%0.2f" % settings["timeout"]] if "retries" in settings: options += ["-r", "%d" % settings["retries"]] if context_name is not None: options += ["-n", context_name] return command + options