2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
10 # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
29 from typing
import NamedTuple
, Union
, Tuple
, Optional
# pylint: disable=unused-import
31 OID_END
= 0 # Suffix-part of OID that was not specified
32 OID_STRING
= -1 # Complete OID as string ".1.3.6.1.4.1.343...."
33 OID_BIN
= -2 # Complete OID as binary string "\x01\x03\x06\x01..."
34 OID_END_BIN
= -3 # Same, but just the end part
35 OID_END_OCTET_STRING
= -4 # yet same, but omit first byte (assuming that is the length byte)
39 """Tell Check_MK to process this OID as binary data to the check."""
44 """Use this to mark OIDs as being cached for regular checks,
45 but not for discovery"""
49 def binstring_to_int(binstring
):
50 """Convert a string to an integer.
52 This is done by consideren the string to by a little endian byte string.
53 Such strings are sometimes used by SNMP to encode 64 bit counters without
54 needed COUNTER64 (which is not available in SNMP v1)."""
57 for byte
in binstring
[::-1]:
58 value
+= mult
* ord(byte
)
63 def is_snmpv3_host(host_config
):
64 return isinstance(host_config
.credentials
, tuple)
67 # TODO: Be more specific about the possible tuples
68 # if the credentials are a string, we use that as community,
69 # if it is a four-tuple, we use it as V3 auth parameters:
70 # (1) security level (-l)
71 # (2) auth protocol (-a, e.g. 'md5')
72 # (3) security name (-u)
73 # (4) auth password (-A)
74 # And if it is a six-tuple, it has the following additional arguments:
75 # (5) privacy protocol (DES|AES) (-x)
76 # (6) privacy protocol pass phrase (-X)
77 SNMPCredentials
= Union
[str, Tuple
[str, str, str, str], Tuple
[str, str, str, str], Tuple
[str, str]]
79 # Wraps the configuration of a host into a single object for the SNMP code
80 SNMPHostConfig
= NamedTuple(
83 ("is_ipv6_primary", bool),
86 ("credentials", SNMPCredentials
),
88 ("is_bulkwalk_host", bool),
89 ("is_snmpv2or3_without_bulkwalk_host", bool),
90 ("bulk_walk_size_of", int),
91 # TODO: Cleanup to named tuple
93 ("oid_range_limits", list),
97 class ABCSNMPBackend(object):
98 __metaclass__
= abc
.ABCMeta
101 def get(self
, host_config
, oid
, context_name
=None):
102 # type: (SNMPHostConfig, str, Optional[str]) -> Optional[str]
103 """Fetch a single OID from the given host in the given SNMP context
105 The OID may end with .* to perform a GETNEXT request. Otherwise a GET
106 request is sent to the given host.
108 raise NotImplementedError()
111 class MutexScanRegistry(object):
112 """Register scan functions that are checked before a fallback is used
114 Add any number of scan functions to a registry instance by decorating
117 @mutex_scan_registry_instance.register
118 def my_snmp_scan_function(oid):
121 You can then declare a scan function to be a fallback to those functions
122 by decorating it with "@mutex_scan_registry_instance.as_fallback",
123 meaning that the fallback function will only be evaluated if all of the
124 scan functions registered earlier return something falsey.
128 super(MutexScanRegistry
, self
).__init
__()
129 self
._specific
_scans
= []
131 def _is_specific(self
, oid
):
132 return any(scan(oid
) for scan
in self
._specific
_scans
)
134 def register(self
, scan_function
):
135 self
._specific
_scans
.append(scan_function
)
138 def as_fallback(self
, scan_function
):
139 @functools.wraps(scan_function
)
141 if self
._is
_specific
(oid
):
143 return scan_function(oid
)