Ejemplo n.º 1
0
    def describe(self):
        # type: () -> str
        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)
Ejemplo n.º 2
0
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 _is_in_single_oid_cache(oid):
        console.vverbose("       Using cached OID %s: " % oid)
        cached_value = _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_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%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

    set_single_oid_cache(oid, decoded_value)
    return decoded_value
Ejemplo n.º 3
0
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
    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
Ejemplo n.º 4
0
    def _snmp_base_command(self, what, snmp_config, context_name):
        # type: (str, snmp_utils.SNMPHostConfig, Optional[ContextName]) -> List[str]
        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')

            if not isinstance(snmp_config.credentials, str):
                raise TypeError()
            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