예제 #1
0
def _extract_snmp_sections(
    inf_info: Dict[InventoryPluginNameStr, InventoryInfo],
    plugin_file_lookup: Dict[str, str],
) -> None:
    for plugin_name, plugin_info in sorted(inv_info.items()):
        if 'snmp_info' not in plugin_info:
            continue
        section_name = section_name_of(plugin_name)
        if isinstance(agent_based_register.get_section_plugin(SectionName(section_name)),
                      SNMPSectionPlugin):
            continue

        fallback_files = ([_include_file_path(i) for i in plugin_info.get('includes', [])] +
                          [plugin_file_lookup[plugin_name]])

        try:
            agent_based_register.add_section_plugin(
                create_snmp_section_plugin_from_legacy(
                    section_name,
                    {},
                    plugin_info['snmp_scan_function'],
                    plugin_info['snmp_info'],
                    scan_function_fallback_files=fallback_files,
                ))
        except (NotImplementedError, KeyError, AssertionError, ValueError):
            msg = config.AUTO_MIGRATION_ERR_MSG % ('section', plugin_name)
            if cmk.utils.debug.enabled():
                raise MKGeneralException(msg)
            console.warning(msg)
예제 #2
0
def _extract_snmp_sections(
    inf_info: Dict[InventoryPluginNameStr, InventoryInfo],
    plugin_file_lookup: Dict[str, str],
) -> List[str]:
    errors = []
    for plugin_name, plugin_info in sorted(inv_info.items()):
        if 'snmp_info' not in plugin_info:
            continue
        section_name = section_name_of(plugin_name)
        if isinstance(agent_based_register.get_section_plugin(SectionName(section_name)),
                      SNMPSectionPlugin):
            continue

        fallback_files = ([_include_file_path(i) for i in plugin_info.get('includes', [])] +
                          [plugin_file_lookup[plugin_name]])

        try:
            agent_based_register.add_section_plugin(
                create_snmp_section_plugin_from_legacy(
                    section_name,
                    {},
                    plugin_info['snmp_scan_function'],
                    plugin_info['snmp_info'],
                    scan_function_fallback_files=fallback_files,
                    # We have to validate, because we read inventory plugin files
                    # directly, and do not know whether they changed.
                    validate_creation_kwargs=True,
                ))
        except (NotImplementedError, KeyError, AssertionError, ValueError):
            msg = config.AUTO_MIGRATION_ERR_MSG % ('section', plugin_name)
            if cmk.utils.debug.enabled():
                raise MKGeneralException(msg)
            errors.append(msg)

    return errors
예제 #3
0
    def data(self):
        # type: () -> RawSNMPData
        info = {}  # type: RawSNMPData
        for check_plugin_name, oid_info in self._oid_infos.items():
            section_name = section_name_of(check_plugin_name)
            # Prevent duplicate data fetching of identical section in case of SNMP sub checks
            if section_name in info:
                self._logger.debug(
                    "%s: Skip fetching data (section already fetched)",
                    check_plugin_name)
                continue

            self._logger.debug("%s: Fetching data", check_plugin_name)

            # oid_info can now be a list: Each element  of that list is interpreted as one real oid_info
            # and fetches a separate snmp table.
            get_snmp = snmp_table.get_snmp_table_cached if self._use_snmpwalk_cache else snmp_table.get_snmp_table
            if isinstance(oid_info, list):
                # branch: List[ABCSNMPTree]
                check_info = []  # type: List[SNMPTable]
                for entry in oid_info:
                    check_info_part = get_snmp(self._snmp_config,
                                               check_plugin_name, entry)
                    check_info.append(check_info_part)
                info[section_name] = check_info
            else:
                # branch: OIDInfo
                info[section_name] = get_snmp(self._snmp_config,
                                              check_plugin_name, oid_info)
        return info
예제 #4
0
def _extract_snmp_sections():
    # type: () -> None
    for plugin_name, plugin_info in sorted(inv_info.items()):
        if 'snmp_info' not in plugin_info:
            continue
        section_name = section_name_of(plugin_name)
        if config.get_registered_section_plugin(PluginName(section_name)):
            continue

        fallback_files = (
            [_include_file_path(i) for i in plugin_info.get('includes', [])] +
            [_plugin_file_lookup[plugin_name]])

        try:
            snmp_section_plugin = create_snmp_section_plugin_from_legacy(
                section_name,
                {},
                plugin_info['snmp_scan_function'],
                plugin_info['snmp_info'],
                scan_function_fallback_files=fallback_files,
            )
        except (NotImplementedError, KeyError, AssertionError, ValueError):
            msg = config.AUTO_MIGRATION_ERR_MSG % ('section', plugin_name)
            if cmk.utils.debug.enabled():
                raise MKGeneralException(msg)
            # TODO (mo): bring this back:
            #console.warning(msg)
        else:
            config.registered_snmp_sections[
                snmp_section_plugin.name] = snmp_section_plugin
예제 #5
0
    def _make_oid_infos(self):
        # type: () -> Dict[CheckPluginName, Union[OIDInfo, List[ABCSNMPTree]]]
        oid_infos = {
        }  # Dict[CheckPluginName, Union[OIDInfo, List[ABCSNMPTree]]]
        raw_sections_to_process = self._get_raw_section_names_to_process()
        for check_plugin_name in self._sort_check_plugin_names(
                raw_sections_to_process):
            # Is this an SNMP table check? Then snmp_info specifies the OID to fetch
            # Please note, that if the check_plugin_name is foo.bar then we lookup the
            # snmp info for "foo", not for "foo.bar".
            section_name = section_name_of(check_plugin_name)
            oid_info, has_snmp_info = self._oid_info_from_section_name(
                section_name)

            if not has_snmp_info and check_plugin_name in self._fetched_raw_section_names:
                continue

            if oid_info is None:
                continue

            # This checks data is configured to be persisted (snmp_check_interval) and recent enough.
            # Skip gathering new data here. The persisted data will be added later
            if self._persisted_sections and section_name in self._persisted_sections:
                self._logger.debug(
                    "%s: Skip fetching data (persisted info exists)",
                    check_plugin_name)
                continue

            oid_infos[check_plugin_name] = oid_info
        return oid_infos
예제 #6
0
def test_create_section_plugin_from_legacy(config_check_info, snmp_info,
                                           migrated_agent_sections,
                                           migrated_snmp_sections):
    for name, check_info_dict in config_check_info.items():
        # only test main checks
        if name != section_name_of(name):
            continue

        section_name = SectionName(name)

        with known_exceptions('section', name):
            section = migrated_agent_sections.get(section_name)
            if section is not None:
                assert isinstance(section, AgentSectionPlugin)
            else:
                section = migrated_snmp_sections.get(section_name)
                if section is None:
                    raise NotImplementedError(name)
                assert isinstance(section, SNMPSectionPlugin)

        if section is None:
            continue

        original_parse_function = check_info_dict["parse_function"]
        if original_parse_function is not None:
            assert original_parse_function.__name__ == section.parse_function.__name__
예제 #7
0
    def get_section_content(
            self,
            host_key: HostKey,
            management_board_info: str,
            check_plugin_name: CheckPluginNameStr,
            for_discovery: bool,
            service_description: Optional[ServiceName] = None) -> FinalSectionContent:
        """Prepares the section_content construct for a Check_MK check on ANY host

        The section_content construct is then handed over to the check, inventory or
        discovery functions for doing their work.

        If the host is a cluster, the sections from all its nodes is merged together
        here. Optionally the node info is added to the nodes section content.

        It handles the whole data and cares about these aspects:

        a) Extract the section_content for the given check_plugin_name
        b) Adds node_info to the section_content (if check asks for this)
        c) Applies the parse function (if check has some)
        d) Adds extra_sections (if check asks for this)
           and also applies node_info and extra_section handling to this

        It can return an section_content construct or None when there is no section content
        for this check available.
        """

        section_name = section_name_of(check_plugin_name)
        nodes_of_clustered_service = self._get_nodes_of_clustered_service(
            host_key.hostname, service_description)
        cache_key = (host_key, management_board_info, section_name, for_discovery,
                     bool(nodes_of_clustered_service))

        try:
            return self._section_content_cache[cache_key]
        except KeyError:
            pass

        section_content = self._get_section_content(
            host_key._replace(source_type=SourceType.MANAGEMENT if management_board_info ==
                              LEGACY_MGMT_ONLY else SourceType.HOST),
            check_plugin_name,
            SectionName(section_name),
            for_discovery,
            nodes_of_clustered_service,
        )

        # If we found nothing, see if we must check the management board:
        if (section_content is None and host_key.source_type is SourceType.HOST and
                management_board_info == LEGACY_HOST_PRECEDENCE):
            section_content = self._get_section_content(
                host_key._replace(source_type=SourceType.MANAGEMENT),
                check_plugin_name,
                SectionName(section_name),
                for_discovery,
                nodes_of_clustered_service,
            )

        self._section_content_cache[cache_key] = section_content
        return section_content
예제 #8
0
def is_snmp_check(check_plugin_name: str) -> bool:
    cache = _runtime_cache.get_dict("is_snmp_check")
    try:
        return cache[check_plugin_name]
    except KeyError:
        snmp_checks = _runtime_cache.get_set("check_type_snmp")
        result = section_name_of(check_plugin_name) in snmp_checks
        cache[check_plugin_name] = result
        return result
예제 #9
0
def is_tcp_check(check_plugin_name):
    # type: (str) -> bool
    cache = _runtime_cache.get_dict("is_tcp_check")
    try:
        return cache[check_plugin_name]
    except KeyError:
        tcp_checks = _runtime_cache.get_set("check_type_tcp")
        result = section_name_of(check_plugin_name) in tcp_checks
        cache[check_plugin_name] = result
        return result
예제 #10
0
def test_create_section_plugin_from_legacy(inv_info):
    for name, inv_info_dict in inv_info.items():
        if 'snmp_info' not in inv_info_dict:
            continue

        section_name = PluginName(section_name_of(name))
        with known_exceptions(name):
            if section_name not in config.registered_snmp_sections:
                raise NotImplementedError(name)
            section = config.registered_snmp_sections[section_name]
            assert isinstance(section, SNMPSectionPlugin)
예제 #11
0
def _get_detection_spec_from_plugin_name(check_plugin_name, inv_info):
    # type: (CheckPluginName, Dict[str, Any]) -> Union[SNMPDetectSpec, Optional[ScanFunction]]
    # This function will hopefully shrink and finally disappear during API development.
    section_name = section_name_of(check_plugin_name)
    section_plugin = config.registered_snmp_sections.get(PluginName(section_name))
    if section_plugin:
        return section_plugin.detect_spec

    # TODO (mo): migrate section definitions from inventory plugins to
    #            section plugins and remove this conditional entirely
    info = inv_info[section_name]
    return info.get("snmp_scan_function")
예제 #12
0
    def get_section_content(
            self,
            hostname,  # type: HostName
            ipaddress,  # type: Optional[HostAddress]
            check_plugin_name,  # type: CheckPluginName
            for_discovery,  # type: bool
            service_description=None  # type: Optional[ServiceName]
    ):
        # type: (...) -> FinalSectionContent
        """Prepares the section_content construct for a Check_MK check on ANY host

        The section_content construct is then handed over to the check, inventory or
        discovery functions for doing their work.

        If the host is a cluster, the sections from all its nodes is merged together
        here. Optionally the node info is added to the nodes section content.

        It handles the whole data and cares about these aspects:

        a) Extract the section_content for the given check_plugin_name
        b) Adds node_info to the section_content (if check asks for this)
        c) Applies the parse function (if check has some)
        d) Adds extra_sections (if check asks for this)
           and also applies node_info and extra_section handling to this

        It can return an section_content construct or None when there is no section content
        for this check available.
        """

        section_name = section_name_of(check_plugin_name)
        nodes_of_clustered_service = self._get_nodes_of_clustered_service(
            hostname, service_description)
        cache_key = (hostname, ipaddress, section_name, for_discovery,
                     bool(nodes_of_clustered_service))

        try:
            return self._section_content_cache[cache_key]
        except KeyError:
            section_content = self._get_section_content(
                hostname, ipaddress, check_plugin_name, section_name,
                for_discovery, nodes_of_clustered_service)
            self._section_content_cache[cache_key] = section_content
            return section_content
예제 #13
0
def test_no_subcheck_with_snmp_keywords(snmp_info):
    for name in snmp_info:
        assert name == section_name_of(name)
예제 #14
0
def _execute_check_legacy_mode(multi_host_sections, hostname, ipaddress,
                               service):
    # type: (data_sources.MultiHostSections, HostName, Optional[HostAddress], Service) -> bool
    check_function = config.check_info[service.check_plugin_name].get(
        "check_function")
    if check_function is None:
        _submit_check_result(hostname, service.description,
                             CHECK_NOT_IMPLEMENTED, None)
        return True
    # Make a bit of context information globally available, so that functions
    # called by checks know this context
    check_api_utils.set_service(service.check_plugin_name, service.description)
    item_state.set_item_state_prefix(service.check_plugin_name, service.item)

    section_name = section_name_of(service.check_plugin_name)

    section_content = None
    try:
        # TODO: There is duplicate code with discovery._execute_discovery(). Find a common place!
        try:
            section_content = multi_host_sections.get_section_content(
                hostname,
                ipaddress,
                config.get_management_board_precedence(section_name,
                                                       config.check_info),
                section_name,
                for_discovery=False,
                service_description=service.description)
        except MKParseFunctionError as e:
            x = e.exc_info()
            # re-raise the original exception to not destory the trace. This may raise a MKCounterWrapped
            # exception which need to lead to a skipped check instead of a crash
            # TODO CMK-3729, PEP-3109
            new_exception = x[0](x[1])
            new_exception.__traceback__ = x[2]  # type: ignore[attr-defined]
            raise new_exception

        # TODO: Move this to a helper function
        if section_content is None:  # No data for this check type
            return False

        # Call the actual check function
        item_state.reset_wrapped_counters()

        raw_result = check_function(
            service.item, legacy_determine_check_params(service.parameters),
            section_content)
        result = sanitize_check_result(raw_result)
        item_state.raise_counter_wrap()

    except item_state.MKCounterWrapped as e:
        # handle check implementations that do not yet support the
        # handling of wrapped counters via exception on their own.
        # Do not submit any check result in that case:
        console.verbose("%-20s PEND - Cannot compute check result: %s\n",
                        ensure_str(service.description), e)
        # Don't submit to core - we're done.
        return True

    except MKTimeout:
        raise

    except Exception:
        if cmk.utils.debug.enabled():
            raise
        result = 3, cmk.base.crash_reporting.create_check_crash_dump(
            hostname, service.check_plugin_name, service.item,
            is_manual_check(hostname, service.check_plugin_name, service.item),
            service.parameters, service.description, section_content), []

    _submit_check_result(
        hostname,
        service.description,
        result,
        _legacy_determine_cache_info(multi_host_sections, section_name),
    )
    return True
예제 #15
0
def _do_all_checks_on_host(sources,
                           host_config,
                           ipaddress,
                           only_check_plugin_names=None):
    # type: (data_sources.DataSources, config.HostConfig, Optional[HostAddress], Optional[List[str]]) -> Tuple[int, List[SectionName]]
    hostname = host_config.hostname  # type: HostName
    config_cache = config.get_config_cache()

    num_success, missing_sections = 0, set()

    check_api_utils.set_hostname(hostname)

    belongs_to_cluster = len(config_cache.clusters_of(hostname)) > 0

    services = check_table.get_precompiled_check_table(
        hostname,
        remove_duplicates=True,
        filter_mode="include_clustered" if belongs_to_cluster else None,
    )

    # When check types are specified via command line, enforce them. Otherwise use the
    # list of checks defined by the check table.
    if only_check_plugin_names is None:
        only_check_plugins = {
            service.check_plugin_name
            for service in services
        }
    else:
        only_check_plugins = set(only_check_plugin_names)

    sources.enforce_check_plugin_names(only_check_plugins)

    # Gather the data from the sources
    multi_host_sections = sources.get_host_sections()

    def _is_not_of_host(host_name, service):
        return hostname != config_cache.host_of_clustered_service(
            hostname, service.description)

    # Filter out check types which are not used on the node
    if belongs_to_cluster:
        removed_plugins = {
            plugin
            for plugin in only_check_plugins if all(
                _is_not_of_host(hostname, service) for service in services
                if service.check_plugin_name == plugin)
        }
        only_check_plugins -= removed_plugins

    for service in services:
        if service.check_plugin_name not in only_check_plugins:
            continue
        if belongs_to_cluster and _is_not_of_host(hostname, service):
            continue
        if service_outside_check_period(config_cache, hostname,
                                        service.description):
            continue

        success = execute_check(multi_host_sections, host_config, ipaddress,
                                service)
        if success:
            num_success += 1
        else:
            missing_sections.add(section_name_of(service.check_plugin_name))

    import cmk.base.inventory as inventory  # pylint: disable=import-outside-toplevel
    inventory.do_inventory_actions_during_checking_for(sources,
                                                       multi_host_sections,
                                                       host_config, ipaddress)

    missing_section_list = sorted(missing_sections)
    return num_success, missing_section_list
예제 #16
0
    def get_section_content(
        self,
        host_key: HostKey,
        management_board_info: str,
        check_plugin_name: str,
        for_discovery: bool,
        *,
        cluster_node_keys: Optional[List[HostKey]] = None,
        check_legacy_info: Dict[str, Dict[str, Any]],
    ) -> Union[None, ParsedSectionContent, List[ParsedSectionContent]]:
        """Prepares the section_content construct for a Check_MK check on ANY host

        The section_content construct is then handed over to the check, inventory or
        discovery functions for doing their work.

        If the host is a cluster, the sections from all its nodes is merged together
        here. Optionally the node info is added to the nodes section content.

        It handles the whole data and cares about these aspects:

        a) Extract the section_content for the given check_plugin_name
        b) Adds node_info to the section_content (if check asks for this)
        c) Applies the parse function (if check has some)

        It can return an section_content construct or None when there is no section content
        for this check available.
        """

        section_name = section_name_of(check_plugin_name)
        cache_key = (host_key, management_board_info, section_name, for_discovery,
                     bool(cluster_node_keys))

        try:
            return self._section_content_cache[cache_key]
        except KeyError:
            pass

        section_content = self._get_section_content(
            host_key._replace(source_type=SourceType.MANAGEMENT if management_board_info ==
                              LEGACY_MGMT_ONLY else SourceType.HOST),
            check_plugin_name,
            SectionName(section_name),
            for_discovery,
            cluster_node_keys=cluster_node_keys,
            check_legacy_info=check_legacy_info,
        )

        # If we found nothing, see if we must check the management board:
        if (section_content is None and host_key.source_type is SourceType.HOST and
                management_board_info == LEGACY_HOST_PRECEDENCE):
            section_content = self._get_section_content(
                host_key._replace(source_type=SourceType.MANAGEMENT),
                check_plugin_name,
                SectionName(section_name),
                for_discovery,
                cluster_node_keys=cluster_node_keys,
                check_legacy_info=check_legacy_info,
            )

        self._section_content_cache[cache_key] = section_content
        return section_content
예제 #17
0
def is_snmp_plugin(check_plugin_name):
    # type: (str) -> bool
    section_name = section_name_of(check_plugin_name)
    return PluginName(section_name) in config.registered_snmp_sections
예제 #18
0
def is_snmp_plugin(check_plugin_name: str) -> bool:
    section_name = section_name_of(check_plugin_name)
    return SectionName(section_name) in config.registered_snmp_sections
예제 #19
0
def _execute_check_legacy_mode(multi_host_sections: MultiHostSections, hostname: HostName,
                               ipaddress: Optional[HostAddress], service: Service) -> bool:
    check_function = config.check_info[service.check_plugin_name].get("check_function")
    if check_function is None:
        _submit_check_result(hostname, service.description, CHECK_NOT_IMPLEMENTED, None)
        return True
    # Make a bit of context information globally available, so that functions
    # called by checks know this context
    check_api_utils.set_service(service.check_plugin_name, service.description)
    item_state.set_item_state_prefix(service.check_plugin_name, service.item)

    section_name = section_name_of(service.check_plugin_name)

    section_content = None
    mgmt_board_info = config.get_management_board_precedence(section_name, config.check_info)
    try:
        # TODO: There is duplicate code with discovery._execute_discovery().
        section_content = multi_host_sections.get_section_content(
            HostKey(
                hostname,
                ipaddress,
                SourceType.MANAGEMENT if mgmt_board_info == LEGACY_MGMT_ONLY else SourceType.HOST,
            ),
            mgmt_board_info,
            section_name,
            for_discovery=False,
            service_description=service.description,
        )

        # TODO: Move this to a helper function
        if section_content is None:  # No data for this check type
            return False

        # Call the actual check function
        item_state.reset_wrapped_counters()

        used_params = legacy_determine_check_params(service.parameters)
        raw_result = check_function(service.item, used_params, section_content)
        result = sanitize_check_result(raw_result)
        item_state.raise_counter_wrap()

    except item_state.MKCounterWrapped as e:
        # handle check implementations that do not yet support the
        # handling of wrapped counters via exception on their own.
        # Do not submit any check result in that case:
        console.verbose("%-20s PEND - Cannot compute check result: %s\n",
                        ensure_str(service.description), e)
        # Don't submit to core - we're done.
        return True

    except MKTimeout:
        raise

    except Exception:
        if cmk.utils.debug.enabled():
            raise
        result = 3, cmk.base.crash_reporting.create_check_crash_dump(
            hostname,
            service.check_plugin_name,
            {
                "item": service.item,
                "params": used_params,
                "section_content": section_content
            },
            is_manual_check(hostname, service.check_plugin_name, service.item),
            service.description,
        ), []

    _submit_check_result(
        hostname,
        service.description,
        result,
        _legacy_determine_cache_info(multi_host_sections, SectionName(section_name)),
    )
    return True
예제 #20
0
def is_snmp_plugin(check_plugin_name):
    # type: (str) -> bool
    section_name = section_name_of(check_plugin_name)
    return "snmp_info" in inv_info.get(section_name, {}) \
           or cmk.base.check_utils.is_snmp_check(check_plugin_name)