def test_create_snmp_section_plugin(): trees: List[SNMPTree] = [ section_types.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, forbidden_names=[], ) 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"], forbidden_names=[], ) 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"], forbidden_names=[], ) assert isinstance(plugin, section_types.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_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_create_snmp_section_plugin(): trees: List[SNMPTree] = [ SNMPTree( base=".1.2.3", oids=[OIDEnd(), "2.3"], ), ] detect = SNMPDetectSpecification([ [(".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) == 11 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.host_label_default_parameters is None assert plugin.host_label_ruleset_name is None assert plugin.host_label_ruleset_type == "merged" assert plugin.detect_spec == detect assert plugin.trees == trees assert plugin.supersedes == {SectionName("bar"), SectionName("foo")}
def create_snmp_section_plugin_from_legacy(check_plugin_name, check_info_dict, snmp_scan_function, snmp_info): # type: (str, Dict[str, Any], Callable, Any) -> SNMPSectionPlugin trees, recover_layout_function = _create_snmp_trees(snmp_info) parse_function = _create_snmp_parse_function( check_info_dict.get('parse_function'), recover_layout_function, ) host_label_function = _create_host_label_function( check_info_dict.get('inventory_function'), check_info_dict.get('extra_sections', []), ) detect_spec = create_detect_spec( check_plugin_name, snmp_scan_function, ) return create_snmp_section_plugin( name=get_section_name(check_plugin_name), parse_function=parse_function, host_label_function=host_label_function, forbidden_names=[], trees=trees, detect_spec=detect_spec, )
def create_snmp_section_plugin_from_legacy( check_plugin_name: str, check_info_dict: Dict[str, Any], snmp_scan_function: Callable, snmp_info: Any, scan_function_fallback_files: Optional[List[str]] = None, *, validate_creation_kwargs: bool, ) -> SNMPSectionPlugin: if check_info_dict.get("node_info"): # We refuse to tranform these. There's no way we get the data layout recovery right. # This would add 19 plugins to list of failures, but some are on the list anyway. raise NotImplementedError("cannot auto-migrate cluster aware plugins") trees, recover_layout_function = _create_snmp_trees(snmp_info) parse_function = _create_snmp_parse_function( check_info_dict.get('parse_function'), recover_layout_function, handle_empty_info=bool(check_info_dict.get("handle_empty_info")), ) detect_spec = create_detect_spec( check_plugin_name, snmp_scan_function, scan_function_fallback_files or [], ) return create_snmp_section_plugin( name=get_section_name(check_plugin_name), parse_function=parse_function, fetch=trees, detect_spec=detect_spec, validate_creation_kwargs=validate_creation_kwargs, )
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 snmp_section( #*, name=None, # type: Optional[str] parsed_section_name=None, # type: Optional[str] parse_function=None, # type: Optional[SNMPParseFunction] host_label_function=None, # type: Optional[HostLabelFunction] detect=None, # type: Optional[SNMPDetectSpec] trees=None, # type: Optional[List[SNMPTree]] supersedes=None, # type: Optional[List[str]] ): # type: (...) -> None """Register an snmp section to checkmk The snmp information will be gathered and parsed according to the functions and options given to this function: :param name: The name of the section to be processed. It must be unique, and match the section header of the agent oufput ('<<<name>>>'). :params parsed_section_name: not yet implemented. :params parse_function: The function responsible for parsing the raw snmp data. It must accept exactly one argument by the name 'string_table'. It may return an arbitrary object. Note that if the return value is falsey, no forther processing will take place. :params host_label_function: The function responsible for extracting HostLabels from the parsed data. It must accept exactly one argument by the name 'section'. When the function is called, it will be passed the parsed data as returned by the parse function. It is expected to yield objects of type 'HostLabel'. :params detect: The conditions on single OIDs that will result in the attempt to fetch snmp data and discover services. This should only match devices to which the section is applicable. :params trees: The specification of snmp data that should be fetched from the device. It must be a list of SNMPTree objects. The parse function will be passed a list of one SNMP table per specified Tree, where an SNMP tree is a list of lists of strings. :params supersedes: not yet implemented. """ # TODO (mo): unhack this CMK-3983 if name is None or parse_function is None or detect is None or trees is None: raise TypeError( "missing argument: name, parse_function, detect or trees") forbidden_names = list(config.registered_agent_sections) + list( config.registered_snmp_sections) section_plugin = create_snmp_section_plugin( name=name, parsed_section_name=parsed_section_name, parse_function=parse_function, host_label_function=host_label_function, detect_spec=detect, trees=trees, supersedes=supersedes, forbidden_names=forbidden_names, ) config.registered_snmp_sections[section_plugin.name] = section_plugin
def snmp_section( *, name: str, parsed_section_name: Optional[str] = None, parse_function: SNMPParseFunction, host_label_function: Optional[HostLabelFunction] = None, detect: SNMPDetectSpec, trees: List[SNMPTree], supersedes: Optional[List[str]] = None, ) -> None: """Register an snmp section to checkmk The snmp information will be gathered and parsed according to the functions and options given to this function: :param name: The name of the section to be processed. It must be unique, and match the section header of the agent oufput ('<<<name>>>'). :params parsed_section_name: not yet implemented. :params parse_function: The function responsible for parsing the raw snmp data. It must accept exactly one argument by the name 'string_table'. It may return an arbitrary object. Note that if the return value is falsey, no forther processing will take place. :params host_label_function: The function responsible for extracting HostLabels from the parsed data. It must accept exactly one argument by the name 'section'. When the function is called, it will be passed the parsed data as returned by the parse function. It is expected to yield objects of type 'HostLabel'. :params detect: The conditions on single OIDs that will result in the attempt to fetch snmp data and discover services. This should only match devices to which the section is applicable. :params trees: The specification of snmp data that should be fetched from the device. It must be a list of SNMPTree objects. The parse function will be passed a list of one SNMP table per specified Tree, where an SNMP tree is a list of lists of strings. :params supersedes: not yet implemented. """ section_plugin = create_snmp_section_plugin( name=name, parsed_section_name=parsed_section_name, parse_function=parse_function, host_label_function=host_label_function, detect_spec=detect, trees=trees, supersedes=supersedes, module=get_plugin_module_name(), ) if (section_plugin.name in config.registered_agent_sections or section_plugin.name in config.registered_snmp_sections): raise ValueError("duplicate section definition: %s" % section_plugin.name) config.registered_snmp_sections[section_plugin.name] = section_plugin
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=SNMPDetectSpecification([[(".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_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_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 create_snmp_section_plugin_from_legacy( check_plugin_name: str, check_info_dict: Dict[str, Any], snmp_scan_function: Callable, snmp_info: Any, scan_function_fallback_files: Optional[List[str]] = None ) -> SNMPSectionPlugin: if check_info_dict.get("node_info"): # We refuse to tranform these. There's no way we get the data layout recovery right. # This would add 19 plugins to list of failures, but some are on the list anyway. raise NotImplementedError("cannot auto-migrate cluster aware plugins") trees, recover_layout_function = _create_snmp_trees(snmp_info) parse_function = _create_snmp_parse_function( check_info_dict.get('parse_function'), recover_layout_function, ) host_label_function = _create_host_label_function( check_info_dict.get('inventory_function'), check_info_dict.get('extra_sections', []), ) detect_spec = create_detect_spec( check_plugin_name, snmp_scan_function, scan_function_fallback_files or [], ) return create_snmp_section_plugin( name=get_section_name(check_plugin_name), parse_function=parse_function, host_label_function=host_label_function, forbidden_names=[], trees=trees, detect_spec=detect_spec, )
section_plugin = create_snmp_section_plugin( name="if", parse_function=parse_if, trees=[ SNMPTree( base=".1.3.6.1.2.1.2.2.1", oids=[ "1", # ifIndex 0 "2", # ifDescr 1 "3", # ifType 2 "5", # ifSpeed 3 "8", # ifOperStatus 4 "10", # ifInOctets 5 "11", # ifInUcastPkts 6 "12", # ifInNUcastPkts 7 "13", # ifInDiscards 8 "14", # ifInErrors 9 "16", # ifOutOctets 10 "17", # ifOutUcastPkts 11 "18", # ifOutNUcastPkts 12 "19", # ifOutDiscards 13 "20", # ifOutErrors 14 "21", # ifOutQLen 15 OIDBytes("6"), # ifPhysAddress 16 ], ), ], detect_spec=never_detect, # does not matter what we put here rule_dependent_detect_spec=SNMPRuleDependentDetectSpec( [RuleSetName('if_disable_if64_hosts')], compute_detect_spec_if, ), )
def snmp_section( *, name: str, detect: SNMPDetectSpec, fetch: Union[SNMPTree, List[SNMPTree]], parse_function: Optional[SNMPParseFunction] = None, parsed_section_name: Optional[str] = None, host_label_function: Optional[HostLabelFunction] = None, supersedes: Optional[List[str]] = None, ) -> None: """Register an snmp section to checkmk The snmp information will be gathered and parsed according to the functions and options given to this function: Args: name: The unique name of the section to be registered. detect: The conditions on single OIDs that will result in the attempt to fetch snmp data and discover services. This should only match devices to which the section is applicable. It is higly recomended to check the system description OID at the very first, as this will make the discovery much more responsive and consume less resources. fetch: The specification of snmp data that should be fetched from the device. It must be an :class:`SNMPTree` object, or a non-empty list of them. The parse function will be passed a single :class:`StringTable` or a list of them accordingly. parse_function: The function responsible for parsing the raw snmp data. It must accept exactly one argument by the name 'string_table'. It will be passed either a single :class:`StringTable`, or a list of them, depending on the value type of the `fetch` argument. It may return an arbitrary object. Note that if the return value is `None`, no forther processing will take place (just as if the agent had not sent any data). parsed_section_name: The name under which the parsed section will be available to the plugins. Defaults to the original name. host_label_function: The function responsible for extracting host labels from the parsed data. It must accept exactly one argument by the name 'section'. When the function is called, it will be passed the parsed data as returned by the parse function. It is expected to yield objects of type :class:`HostLabel`. supersedes: A list of section names which are superseded by this sections. If this section will be parsed to something that is not `None` (see above) all superseded section will not be considered at all. """ section_plugin = create_snmp_section_plugin( name=name, parsed_section_name=parsed_section_name, parse_function=parse_function, host_label_function=host_label_function, detect_spec=detect, fetch=fetch, supersedes=supersedes, module=get_validated_plugin_module_name(), ) if is_registered_section_plugin(section_plugin.name): raise ValueError("duplicate section definition: %s" % section_plugin.name) add_section_plugin(section_plugin)
>>> compute_detect_spec_if_brocade([True]) [[('.1.3.6.1.2.1.1.2.0', '(?!x)x', True)]] """ if if64.is_disabled(if_disable_if64_hosts): return never_detect return all_of(contains(".1.3.6.1.2.1.1.1.0", "Brocade VDX Switch"), if64.HAS_ifHCInOctets) section_plugin = create_snmp_section_plugin( name="if_brocade", parse_function=lambda string_table: parse_if64_brocade_lancom( string_table, ["Point-2-Point"], ), trees=SNMP_TREES, detect_spec=never_detect, # does not matter what we put here rule_dependent_detect_spec=SNMPRuleDependentDetectSpec( [RuleSetName('if_disable_if64_hosts')], compute_detect_spec_if_brocade, ), supersedes=['if', 'if64', 'if64adm'], ) add_section_plugin(section_plugin) assert section_plugin.rule_dependent_detect_spec for discovery_ruleset in section_plugin.rule_dependent_detect_spec.rulesets: add_discovery_ruleset(discovery_ruleset) def compute_detect_spec_if_lancom( if_disable_if64_hosts: Sequence[bool], ) -> SNMPDetectSpec: r"""
[[('.1.3.6.1.2.1.1.2.0', '(?!x)x', True)]] """ if if64.is_disabled(if_disable_if64_hosts) or not if64.need_if64adm(use_if64adm): return never_detect return if64.HAS_ifHCInOctets section_plugin = create_snmp_section_plugin( name="if64adm", parse_function=if64.parse_if64_if6adm, trees=[ SNMPTree( base=if64.BASE_OID, oids=if64.END_OIDS + [ "2.2.1.7", # ifAdminStatus ], ), ], detect_spec=never_detect, # does not matter what we put here rule_dependent_detect_spec=SNMPRuleDependentDetectSpec( [RuleSetName('if_disable_if64_hosts'), RuleSetName('use_if64adm')], compute_detect_spec_if64adm, ), ) add_section_plugin(section_plugin) assert section_plugin.rule_dependent_detect_spec for discovery_ruleset in section_plugin.rule_dependent_detect_spec.rulesets: add_discovery_ruleset(discovery_ruleset) # ================================================================================================== register.check_plugin(