def test_rule_indipendent( self, monkeypatch, hostname, ipaddress, ): plugin = section_plugins.create_snmp_section_plugin( name="norris", parse_function=lambda string_table: None, trees=[ SNMPTree( base='.1.2.3', oids=['2.3'], ), ], detect_spec=SNMPDetectSpec([[('.1.2.3.4.5', 'Foo.*', True)]]), ) source = self.do_monkeypatch_and_make_source( monkeypatch, plugin, hostname, ipaddress, ) assert source._make_snmp_section_detects() == [(plugin.name, plugin.detect_spec)]
def test_create_snmp_section_plugin(): trees: List[SNMPTree] = [ SNMPTree( base='.1.2.3', oids=[OIDEnd(), '2.3'], ), ] detect = SNMPDetectSpec([ [('.1.2.3.4.5', 'Foo.*', True)], ]) plugin = section_plugins.create_snmp_section_plugin( name="norris", parsed_section_name="chuck", parse_function=_parse_dummy, fetch=trees, detect_spec=detect, supersedes=["foo", "bar"], ) assert isinstance(plugin, SNMPSectionPlugin) assert len(plugin) == 8 assert plugin.name == SectionName("norris") assert plugin.parsed_section_name == ParsedSectionName("chuck") assert plugin.parse_function is _parse_dummy assert plugin.host_label_function is section_plugins._noop_host_label_function assert plugin.detect_spec == detect assert plugin.trees == trees assert plugin.supersedes == {SectionName("bar"), SectionName("foo")}
def test_snmptree(base, oids): tree = SNMPTree(base=base, oids=oids) assert tree.base == OIDSpec(base) assert isinstance(tree.oids, list) for oid in tree.oids: assert isinstance(oid, (OIDSpec, OIDEnd))
def from_json(cls, serialized: Dict[str, Any]) -> 'SNMPFetcher': # The SNMPv3 configuration is represented by a tuple of different lengths (see # SNMPCredentials). Since we just deserialized from JSON, we have to convert the # list used by JSON back to a tuple. # SNMPv1/v2 communities are represented by a string: Leave it untouched. if isinstance(serialized["snmp_config"]["credentials"], list): serialized["snmp_config"]["credentials"] = tuple( serialized["snmp_config"]["credentials"]) return cls( file_cache=SNMPFileCache.from_json(serialized.pop("file_cache")), snmp_section_trees={ SectionName(name): [SNMPTree.from_json(tree) for tree in trees ] for name, trees in serialized["snmp_section_trees"].items() }, snmp_section_detects=[ ( SectionName(name), # The cast is necessary as mypy does not infer types in a list comprehension. # See https://github.com/python/mypy/issues/5068 SNMPDetectSpec([[cast(SNMPDetectAtom, tuple(inner)) for inner in outer] for outer in specs]), ) for name, specs in serialized["snmp_section_detects"] ], configured_snmp_sections={ SectionName(name) for name in serialized["configured_snmp_sections"] }, on_error=serialized["on_error"], missing_sys_description=serialized["missing_sys_description"], use_snmpwalk_cache=serialized["use_snmpwalk_cache"], snmp_config=SNMPHostConfig(**serialized["snmp_config"]), )
def _create_snmp_trees_from_tuple( snmp_info_element: tuple) -> Tuple[List[SNMPTree], Optional[LayoutRecoverSuboids]]: """Create a SNMPTrees from (part of) a legacy definition Legacy definition *elements* can be 2-tuple or 3-tuple. We are quite generous here: we will make sure that * base will not end with '.' * subtrees are strings, starting but not ending with '.' * oids are not the empty string. """ assert isinstance(snmp_info_element, tuple) assert len(snmp_info_element) in (2, 3) base = snmp_info_element[0].rstrip('.') # "Triple"-case: recursively return a list if len(snmp_info_element) == 3: tmp_base, suboids, oids = snmp_info_element base_list = [("%s.%s" % (tmp_base, str(i).strip('.'))) for i in suboids] return sum((_create_snmp_trees_from_tuple((base, oids))[0] for base in base_list), []), suboids # this fixes 7 weird cases: oids = ["%d" % oid if isinstance(oid, int) and oid > 0 else oid for oid in snmp_info_element[1]] if '' in oids: # this fixes 19 cases base, tail = str(base).rsplit('.', 1) oids = [ o if isinstance(o, int) else type(o)(("%s.%s" % (tail, o)).strip('.')) for o in oids ] else: # this fixes 21 cases common, oids = _extract_conmmon_part(oids) if common: base = "%s.%s" % (base, common) return [SNMPTree(base=base, oids=oids)], None
def fetcher_fixture(self, fc_conf): return SNMPFetcher.from_json( json_identity({ "file_cache": fc_conf.configure(), "snmp_section_trees": { "pim": [SNMPTree(base=".1.1.1", oids=["1.2", "3.4"]).to_json()], "pam": [ SNMPTree(base=".1.2.3", oids=["4.5", "6.7", "8.9"]).to_json() ], "pum": [ SNMPTree(base=".2.2.2", oids=["2.2"]).to_json(), SNMPTree(base=".3.3.3", oids=["2.2"]).to_json(), ], }, "snmp_section_detects": [ ("pim", [[("1.2.3.4", "pim device", True)]]), ("pam", [[("1.2.3.4", "pam device", True)]]), ], "configured_snmp_sections": [], "on_error": "raise", "missing_sys_description": False, "use_snmpwalk_cache": False, "snmp_config": SNMPHostConfig( is_ipv6_primary=False, hostname="bob", ipaddress="1.2.3.4", credentials=(), port=42, is_bulkwalk_host=False, is_snmpv2or3_without_bulkwalk_host=False, bulk_walk_size_of=0, timing={}, oid_range_limits=[], snmpv3_contexts=[], character_encoding=None, is_usewalk_host=False, is_inline_snmp_host=False, record_stats=False, )._asdict(), }))
def deserialize(cls, serialized: Dict[str, Any]) -> "SNMPPluginStoreItem": try: return cls( [SNMPTree.from_json(tree) for tree in serialized["trees"]], SNMPDetectSpec.from_json(serialized["detect_spec"]), ) except (LookupError, TypeError, ValueError) as exc: raise ValueError(serialized) from exc
def from_json(cls, serialized: Dict[str, Any]) -> 'SNMPDataFetcher': return cls( { name: [SNMPTree.from_json(tree) for tree in trees] for name, trees in serialized["oid_infos"].items() }, serialized["use_snmpwalk_cache"], SNMPHostConfig(**serialized["snmp_config"]), )
def from_json(cls, serialized: Dict[str, Any]) -> 'SNMPFetcher': return cls( SNMPFileCache.from_json(serialized.pop("file_cache")), { SectionName(name): [SNMPTree.from_json(tree) for tree in trees ] for name, trees in serialized["oid_infos"].items() }, serialized["use_snmpwalk_cache"], SNMPHostConfig(**serialized["snmp_config"]), )
def fetcher_fixture(self, file_cache): return SNMPFetcher( file_cache, snmp_section_trees={ SectionName("pim"): [SNMPTree(base=".1.1.1", oids=["1.2", "3.4"])], SectionName("pam"): [SNMPTree(base=".1.2.3", oids=["4.5", "6.7", "8.9"])], SectionName("pum"): [ SNMPTree(base=".2.2.2", oids=["2.2"]), SNMPTree(base=".3.3.3", oids=["2.2"]), ], }, snmp_section_detects={ SectionName("pim"): SNMPDetectSpec([[("1.2.3.4", "pim device", True)]]), SectionName("pam"): SNMPDetectSpec([[("1.2.3.4", "pam device", True)]]), }, disabled_sections=set(), configured_snmp_sections=set(), structured_data_snmp_sections=set(), on_error="raise", missing_sys_description=False, use_snmpwalk_cache=False, snmp_config=SNMPHostConfig( is_ipv6_primary=False, hostname="bob", ipaddress="1.2.3.4", credentials="public", port=42, is_bulkwalk_host=False, is_snmpv2or3_without_bulkwalk_host=False, bulk_walk_size_of=0, timing={}, oid_range_limits=[], snmpv3_contexts=[], character_encoding=None, is_usewalk_host=False, snmp_backend=SNMPBackend.classic, ), )
def test_create_snmp_section_plugin(): trees: List[SNMPTree] = [ SNMPTree( base='.1.2.3', oids=[OIDEnd(), '2.3'], ), ] detect = [ [('.1.2.3.4.5', 'Foo.*', True)], ] with pytest.raises(NotImplementedError): plugin = section_plugins.create_snmp_section_plugin( name="norris", parsed_section_name="chuck", parse_function=_parse_dummy, trees=trees, detect_spec=detect, supersedes=None, ) with pytest.raises(NotImplementedError): plugin = section_plugins.create_snmp_section_plugin( name="norris", parsed_section_name=None, parse_function=_parse_dummy, trees=trees, detect_spec=detect, supersedes=["Foo", "Bar"], ) plugin = section_plugins.create_snmp_section_plugin( name="norris", parsed_section_name=None, # "chuck", parse_function=_parse_dummy, trees=trees, detect_spec=detect, supersedes=None, # ["Foo", "Bar"], ) assert isinstance(plugin, SNMPSectionPlugin) assert len(plugin) == 8 assert plugin.name == SectionName("norris") assert plugin.parsed_section_name == ParsedSectionName( "norris") # "chuck") assert plugin.parse_function is _parse_dummy assert plugin.host_label_function is section_plugins._noop_host_label_function assert plugin.detect_spec == detect assert plugin.trees == trees assert plugin.supersedes == [] # [SectionName("Bar"), SectionName("Foo")]
def test_get_data_types(backend, type_name, oid, expected_response): response = snmp_modes.get_single_oid(oid, backend=backend) assert response == expected_response assert isinstance(response, str) oid_start, oid_end = oid.rsplit(".", 1) table = snmp_table.get_snmp_table( section_name=SectionName("my_Section"), oid_info=SNMPTree(base=oid_start, oids=[oid_end]), backend=backend, ) assert table[0][0] == expected_response assert isinstance(table[0][0], str)
def test_get_simple_snmp_table_oid_end(backend): oid_info = SNMPTree( base=".1.3.6.1.2.1.2.2.1", oids=["1", "2", "3", OIDEnd()], ) table = snmp_table.get_snmp_table( section_name=SectionName("my_Section"), oid_info=oid_info, backend=backend, ) assert table == [ [u'1', u'lo', u'24', u'1'], [u'2', u'eth0', u'6', u'2'], ]
def test_create_snmp_section_plugin_single_tree(): single_tree = SNMPTree(base='.1.2.3', oids=[OIDEnd(), '2.3']) plugin = section_plugins.create_snmp_section_plugin( name="norris", parse_function=lambda string_table: string_table, # just one, no list: fetch=single_tree, detect_spec=SNMPDetectSpec([[('.1.2.3.4.5', 'Foo.*', True)]]), ) assert plugin.trees == [single_tree] # the plugin only specified a single tree (not a list), # so a wrapper should unpack the argument: assert plugin.parse_function([[['A', 'B']]]) == [['A', 'B']]
def test_get_simple_snmp_table_oid_end_bin(backend): oid_info = SNMPTree( base=".1.3.6.1.2.1.2.2.1", # deprecated with checkmk version 2.0 oids=["1", "2", "3", OID_END_BIN], # type: ignore[list-item] ) table = snmp_table.get_snmp_table( section_name=SectionName("my_Section"), oid_info=oid_info, backend=backend, ) assert table == [ [u'1', u'lo', u'24', u'\x01'], [u'2', u'eth0', u'6', u'\x02'], ]
def from_json(cls, serialized: Dict[str, Any]) -> 'SNMPFetcher': return cls( file_cache=SNMPFileCache.from_json(serialized.pop("file_cache")), snmp_section_trees={ SectionName(name): [SNMPTree.from_json(tree) for tree in trees ] for name, trees in serialized["snmp_section_trees"].items() }, snmp_section_detects=[ (SectionName(name), specs) for name, specs in serialized["snmp_section_detects"] ], configured_snmp_sections={ SectionName(name) for name in serialized["configured_snmp_sections"] }, on_error=serialized["on_error"], missing_sys_description=serialized["missing_sys_description"], use_snmpwalk_cache=serialized["use_snmpwalk_cache"], snmp_config=SNMPHostConfig(**serialized["snmp_config"]), )
def test_get_simple_snmp_table_with_hex_str(backend): oid_info = SNMPTree( base=".1.3.6.1.2.1.2.2.1", oids=["6"], ) table = snmp_table.get_snmp_table( section_name=SectionName("my_Section"), oid_info=oid_info, backend=backend, ) assert table == [ [u''], [ u'\x00\x12yb\xf9@', ], ]
def test_make_snmp_section_detects_for_inventory(monkeypatch, hostname, ipaddress, check_plugin): plugin = section_plugins.create_snmp_section_plugin( name="norris", parse_function=lambda string_table: None, fetch=[ SNMPTree( base='.1.2.3', oids=['2.3'], ), ], detect_spec=SNMPDetectSpec([[('.1.2.3.4.5', 'Foo.*', True)]]), ) monkeypatch.setattr(_config, 'registered_snmp_sections', {plugin.name: plugin}) monkeypatch.setattr(_config, 'registered_inventory_plugins', {check_plugin.name: check_plugin}) Scenario().add_host(hostname).apply(monkeypatch) source = SNMPSource.snmp(hostname, ipaddress, mode=Mode.INVENTORY) assert source._make_snmp_section_detects() == {plugin.name: plugin.detect_spec}
def test_get_simple_snmp_table(backend): oid_info = SNMPTree( base=".1.3.6.1.2.1.1", oids=["1.0", "2.0", "5.0"], ) table = snmp_table.get_snmp_table( section_name=SectionName("my_Section"), oid_info=oid_info, backend=backend, ) assert table == [ [ u'Linux zeus 4.8.6.5-smp #2 SMP Sun Nov 13 14:58:11 CDT 2016 i686', u'.1.3.6.1.4.1.8072.3.2.10', u'new system name', ], ] assert isinstance(table[0][0], str)
def test_create_snmp_section_plugin_from_legacy(): plugin = section_plugins_legacy.create_snmp_section_plugin_from_legacy( "norris", { 'parse_function': old_school_parse_function, 'inventory_function': old_school_discover_function, }, old_school_scan_function, (".1.2.3.4.5", ["2", 3]), ) assert plugin.name == SectionName("norris") assert plugin.parsed_section_name == ParsedSectionName("norris") assert plugin.parse_function.__name__ == "old_school_parse_function" assert plugin.host_label_function.__name__ == "host_label_function" assert plugin.supersedes == set() assert plugin.detect_spec == [[(".1.2.3.4.5", "norris.*", True)]] assert plugin.trees == [SNMPTree(base=".1.2.3.4.5", oids=["2", "3"])]
def test_rule_dependent( self, monkeypatch, discovery_rulesets, hostname, ipaddress, ): detect_spec_1 = SNMPDetectSpec([[('.1.2.3.4.5', 'Bar.*', False)]]) detect_spec_2 = SNMPDetectSpec([[('.7.8.9', 'huh.*', True)]]) def evaluator(discovery_ruleset): if len(discovery_ruleset) > 0 and discovery_ruleset[0]: return detect_spec_1 return detect_spec_2 plugin = section_plugins.create_snmp_section_plugin( name="norris", parse_function=lambda string_table: None, trees=[ SNMPTree( base='.1.2.3', oids=['2.3'], ), ], detect_spec=SNMPDetectSpec([[('.1.2.3.4.5', 'Foo.*', True)]]), rule_dependent_detect_spec=SNMPRuleDependentDetectSpec( [RuleSetName('discovery_ruleset')], evaluator, ), ) snmp_configurator = self.do_monkeypatch_and_make_configurator( monkeypatch, plugin, hostname, ipaddress, ) assert snmp_configurator._make_snmp_scan_sections() == [ SNMPScanSection( plugin.name, detect_spec_1, ) ]
def test_make_snmp_section_detects(monkeypatch, hostname, ipaddress): plugin = section_plugins.create_snmp_section_plugin( name="norris", parse_function=lambda string_table: None, fetch=[ SNMPTree( base='.1.2.3', oids=['2.3'], ), ], detect_spec=SNMPDetectSpec([[('.1.2.3.4.5', 'Foo.*', True)]]), ) monkeypatch.setattr( register, 'iter_all_snmp_sections', lambda: [plugin], ) Scenario().add_host(hostname).apply(monkeypatch) source = SNMPSource.snmp(hostname, ipaddress, mode=Mode.DISCOVERY) assert source._make_snmp_section_detects() == {plugin.name: plugin.detect_spec}
def test_get_simple_snmp_table_wrong_credentials(backend): if backend.config.is_usewalk_host: pytest.skip("Not relevant") backend.config = backend.config.update(credentials="dingdong") oid_info = SNMPTree( base=".1.3.6.1.2.1.1", oids=["1.0", "2.0", "5.0"], ) # TODO: Unify different error messages if backend.config.snmp_backend == SNMPBackend.inline: exc_match = "SNMP query timed out" else: exc_match = "Timeout: No Response from" with pytest.raises(MKSNMPError, match=exc_match): snmp_table.get_snmp_table( section_name=SectionName("my_Section"), oid_info=oid_info, backend=backend, )
def test_get_simple_snmp_table_not_resolvable(backend): if backend.config.is_usewalk_host: pytest.skip("Not relevant") backend.config = backend.config.update(ipaddress="bla.local") oid_info = SNMPTree( base=".1.3.6.1.2.1.1", oids=["1.0", "2.0", "5.0"], ) # TODO: Unify different error messages if backend.config.snmp_backend == SNMPBackend.inline: exc_match = "Failed to initiate SNMP" else: exc_match = "Unknown host" with pytest.raises(MKSNMPError, match=exc_match): snmp_table.get_snmp_table( section_name=SectionName("my_Section"), oid_info=oid_info, backend=backend, )
continue parsed.setdefault( "%s %s" % (name_part, num), {"current": get_status_info(amperage_str, device_state)}) return parsed register.snmp_section( name="apc_rackpdu_power", parse_function=parse_apc_rackpdu_power, trees=[ SNMPTree( base=".1.3.6.1.4.1.318.1.1.12.1", oids=[ '1', # rPDUIdentName '16', # rPDUIdentDevicePowerWatts ], ), SNMPTree( base=".1.3.6.1.4.1.318.1.1.12.2.1", oids=[ '2', # rPDULoadDevNumPhases ], ), SNMPTree( base=".1.3.6.1.4.1.318.1.1.12.2.3.1.1", oids=[ '2', # rPDULoadStatusLoad '3', # rPDULoadStatusLoadState '4', # rPDULoadStatusPhaseNumber
['2.C0FEFE', 'C0FEFE'], ['2.C0FEFE', 'C0FEFE'], ] @pytest.mark.parametrize("column", snmp_table.SPECIAL_COLUMNS) def test_value_encoding(column): assert snmp_table._value_encoding(column) == "string" @pytest.mark.parametrize("snmp_info, expected_values", [ ( SNMPTree( base='.1.3.6.1.4.1.13595.2.2.3.1', oids=[ OIDEnd(), OIDBytes("16"), ], ), DATA_2TUPLE, ), (TREE_2TUPLE, DATA_2TUPLE), (TREE_3TUPLE, DATA_3TUPLE), ([TREE_2TUPLE, TREE_3TUPLE], [DATA_2TUPLE, DATA_3TUPLE]), ]) def test_get_snmp_table(monkeypatch, snmp_info, expected_values): def get_all_snmp_tables(info): backend = SNMPTestBackend(SNMPConfig, logger) if not isinstance(info, list): return snmp_table.get_snmp_table(SectionName("unit_test"), info,
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 # This file is part of Checkmk (https://checkmk.com). It is subject to the terms and # conditions defined in the file COPYING, which is part of this source code package. # .1.3.6.1.2.1.1.1.0 Linux gateway1 2.6.18-92cp #1 SMP Tue Dec 4 21:44:22 IST 2012 i686 # .1.3.6.1.4.1.2620.1.1.25.3.0 19190 from cmk.snmplib.type_defs import SNMPTree from .agent_based_api.v0 import register from .utils import checkpoint def parse_checkpoint_connections(string_table): raw_value = string_table[0][0][0] return {"count": int(raw_value)} register.snmp_section( name="checkpoint_connections", parse_function=parse_checkpoint_connections, detect=checkpoint.DETECT, trees=[SNMPTree(base=".1.3.6.1.4.1.2620.1.1.25", oids=['3'])], )
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 # This file is part of Checkmk (https://checkmk.com). It is subject to the terms and # conditions defined in the file COPYING, which is part of this source code package. from cmk.snmplib.type_defs import OIDEnd, SNMPTree from .agent_based_api.v0 import exists, parse_to_string_table, register register.snmp_section( name="snmp_extended_info", parse_function=parse_to_string_table, trees=[ SNMPTree( base=".1.3.6.1.2.1.47.1.1.1.1", oids=[ OIDEnd(), "2", # entPhysicalDescr "4", # entPhysicalContainedIn "5", # entPhysicalClass "7", # entPhysicalName "10", # entPhysicalSoftwareRev (NEW) "11", # entPhysicalSerialNum "12", # entPhysicalMfgName (NEW) "13", # entPhysicalModelName ], ), ], detect=exists(".1.3.6.1.2.1.47.1.1.1.1.*"), )
except KeyError: pass return parsed register.snmp_section( name="ucd_mem", parse_function=parse_ucd_mem, trees=[ SNMPTree( base=".1.3.6.1.4.1.2021.4", oids=[ "5", # memTotalReal "6", # memAvailReal "3", # memTotalSwap "4", # memAvailSwap "11", # MemTotalFree "12", # memMinimumSwap "13", # memShared "14", # memBuffer "15", # memCached "100", # memSwapError "2", # memErrorName "101", # smemSwapErrorMsg ], ), ], detect=ucd_hr_detection.USE_UCD_MEM, )
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 # This file is part of Checkmk (https://checkmk.com). It is subject to the terms and # conditions defined in the file COPYING, which is part of this source code package. from cmk.snmplib.type_defs import SNMPTree from .agent_based_api.v0 import exists, parse_to_string_table, register register.snmp_section( name="snmp_quantum_storage_info", parse_function=parse_to_string_table, trees=[ SNMPTree( base=".1.3.6.1.4.1.2036.2.1.1", # qSystemInfo oids=[ "4", # 0 1 qVendorID "5", # 0 2 qProdId "6", # 0 3 qProdRev "12", # 0 4 qSerialNumber ], ), ], detect=exists(".1.3.6.1.4.1.2036.2.1.1.4.0"), )