Licenses: Updated the list of licenses and added a PDF containing all license texts
[check_mk.git] / cmk_base / snmp_scan.py
blob45fe57f16733279ff14eae17eb394043510850a7
1 #!/usr/bin/python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
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.
27 from cmk.utils.exceptions import MKGeneralException
28 import cmk.utils.tty as tty
30 import cmk_base.check_utils
31 import cmk_base.config as config
32 import cmk_base.console as console
33 from cmk_base.exceptions import MKSNMPError
34 import cmk_base.snmp as snmp
35 import cmk_base.check_api_utils as check_api_utils
38 # gather auto_discovered check_plugin_names for this host
39 def gather_snmp_check_plugin_names(host_config,
40 on_error,
41 do_snmp_scan,
42 for_inventory=False,
43 for_mgmt_board=False):
44 check_plugin_names = set()
46 try:
47 check_plugin_names.update(
48 _snmp_scan(
49 host_config,
50 on_error=on_error,
51 do_snmp_scan=do_snmp_scan,
52 for_inv=for_inventory,
53 for_mgmt_board=for_mgmt_board))
54 except Exception as e:
55 if on_error == "raise":
56 raise
57 elif on_error == "warn":
58 console.error("SNMP scan failed: %s\n" % e)
60 return list(check_plugin_names)
63 def _snmp_scan(host_config,
64 on_error="ignore",
65 for_inv=False,
66 do_snmp_scan=True,
67 for_mgmt_board=False):
68 import cmk_base.inventory_plugins as inventory_plugins
70 # Make hostname globally available for scan functions.
71 # This is rarely used, but e.g. the scan for if/if64 needs
72 # this to evaluate if_disabled_if64_checks.
73 check_api_utils.set_hostname(host_config.hostname)
75 snmp.initialize_single_oid_cache(host_config)
76 console.vverbose(" SNMP scan:\n")
77 if not config.in_binary_hostlist(host_config.hostname, config.snmp_without_sys_descr):
78 for oid, name in [(".1.3.6.1.2.1.1.1.0", "system description"),
79 (".1.3.6.1.2.1.1.2.0", "system object")]:
80 value = snmp.get_single_oid(host_config, oid, do_snmp_scan=do_snmp_scan)
81 if value is None:
82 raise MKSNMPError(
83 "Cannot fetch %s OID %s. This might be OK for some bogus devices. "
84 "In that case please configure the ruleset \"Hosts without system "
85 "description OID\" to tell Check_MK not to fetch the system "
86 "description and system object OIDs." % (name, oid))
87 else:
88 # Fake OID values to prevent issues with a lot of scan functions
89 console.vverbose(" Skipping system description OID "
90 "(Set .1.3.6.1.2.1.1.1.0 and .1.3.6.1.2.1.1.2.0 to \"\")\n")
91 snmp.set_single_oid_cache(host_config, ".1.3.6.1.2.1.1.1.0", "")
92 snmp.set_single_oid_cache(host_config, ".1.3.6.1.2.1.1.2.0", "")
94 found_check_plugin_names = []
95 if for_inv:
96 items = inventory_plugins.inv_info.items()
97 else:
98 items = config.check_info.items()
100 positive_found = []
101 default_found = []
103 for check_plugin_name, _unused_check in items:
104 if config.service_ignored(host_config.hostname, check_plugin_name, None):
105 continue
106 else:
107 if for_inv and not inventory_plugins.is_snmp_plugin(check_plugin_name):
108 continue
109 elif not for_inv and not cmk_base.check_utils.is_snmp_check(check_plugin_name):
110 continue
112 section_name = cmk_base.check_utils.section_name_of(check_plugin_name)
113 # The scan function should be assigned to the section_name, because
114 # subchecks sharing the same SNMP info of course should have
115 # an identical scan function. But some checks do not do this
116 # correctly
117 if check_plugin_name in config.snmp_scan_functions:
118 scan_function = config.snmp_scan_functions[check_plugin_name]
119 elif section_name in config.snmp_scan_functions:
120 scan_function = config.snmp_scan_functions[section_name]
121 elif section_name in inventory_plugins.inv_info:
122 scan_function = inventory_plugins.inv_info[section_name].get("snmp_scan_function")
123 else:
124 scan_function = None
126 if scan_function:
127 try:
129 def oid_function(oid, default_value=None, cp_name=check_plugin_name):
130 value = snmp.get_single_oid(
131 host_config, oid, cp_name, do_snmp_scan=do_snmp_scan)
132 return default_value if value is None else value
134 result = scan_function(oid_function)
135 if result is not None and not isinstance(result, (str, bool)):
136 if on_error == "warn":
137 console.warning(" SNMP scan function of %s returns invalid type %s." %
138 (check_plugin_name, type(result)))
139 elif on_error == "raise":
140 raise MKGeneralException("SNMP Scan aborted.")
141 elif result:
142 found_check_plugin_names.append(check_plugin_name)
143 positive_found.append(check_plugin_name)
144 except MKGeneralException:
145 # some error messages which we explicitly want to show to the user
146 # should be raised through this
147 raise
148 except:
149 if on_error == "warn":
150 console.warning(" Exception in SNMP scan function of %s" % check_plugin_name)
151 elif on_error == "raise":
152 raise
153 else:
154 found_check_plugin_names.append(check_plugin_name)
155 default_found.append(check_plugin_name)
157 _output_snmp_check_plugins("SNMP scan found", positive_found)
158 if default_found:
159 _output_snmp_check_plugins("SNMP without scan function", default_found)
161 filtered = config.filter_by_management_board(
162 host_config.hostname,
163 found_check_plugin_names,
164 for_mgmt_board,
165 for_discovery=True,
166 for_inventory=for_inv)
168 _output_snmp_check_plugins("SNMP filtered check plugin names", filtered)
169 snmp.write_single_oid_cache(host_config)
170 return sorted(filtered)
173 def _output_snmp_check_plugins(title, collection):
174 if collection:
175 collection_out = " ".join(sorted(collection))
176 else:
177 collection_out = "-"
178 console.vverbose(" %-35s%s%s%s%s\n" % \
179 (title, tty.bold, tty.yellow, collection_out, tty.normal))