Пример #1
0
def _sanitize_yield_check_result(result: Iterable[Any]) -> ServiceCheckResult:
    subresults = list(result)

    # Empty list? Check returned nothing
    if not subresults:
        return ITEM_NOT_FOUND

    # Several sub results issued with multiple yields. Make that worst sub check
    # decide the total state, join the texts and performance data. Subresults with
    # an infotext of None are used for adding performance data.
    perfdata: List[MetricTuple] = []
    infotexts: List[ServiceDetails] = []
    status: ServiceState = 0

    for subresult in subresults:
        st, text, perf = _sanitize_tuple_check_result(subresult, allow_missing_infotext=True)
        status = worst_service_state(st, status, default=0)

        if text:
            infotexts.append(text + state_markers[st])

        if perf is not None:
            perfdata += perf

    return status, ", ".join(infotexts), perfdata
Пример #2
0
def _aggregate_subresults(*subresults: _DiscoverySubresult) -> _DiscoverySubresult:
    stati, texts, long_texts, perfdata_list = zip(*(result for result, _ in subresults))
    return ((
        worst_service_state(*stati, default=0),
        sum((list(t) for t in texts), []),
        sum((list(l) for l in long_texts), []),
        sum((list(p) for p in perfdata_list), []),
    ), any(need_rediscovery_flag for _, need_rediscovery_flag in subresults))
Пример #3
0
def _aggregate_subresults(*subresults: _DiscoverySubresult) -> _DiscoverySubresult:
    stati, texts, long_texts, perfdata_list, need_rediscovery_flags = zip(*subresults)
    return (
        worst_service_state(*stati, default=0),
        sum(texts, []),
        sum(long_texts, []),
        sum(perfdata_list, []),
        any(need_rediscovery_flags),
    )
Пример #4
0
def _check_data_sources(
    result: Sequence[Tuple[sources.Source, result_type.Result[HostSections, Exception]]],
) -> _DiscoverySubresult:
    summaries = [(source, source.summarize(host_sections)) for source, host_sections in result]
    return (
        worst_service_state(*(state for _s, (state, _t) in summaries), default=0),
        # Do not output informational (state = 0) things.  These information
        # are shown by the "Check_MK" service
        [f"[{src.id}] {text}" for src, (state, text) in summaries if state != 0],
        [],
        [],
        False,
    )
Пример #5
0
def _check_service_lists(
    *,
    host_name: HostName,
    services_by_transition: ServicesByTransition,
    params: config.DiscoveryCheckParameters,
    service_filters: _ServiceFilters,
    discovery_mode: DiscoveryMode,
) -> Tuple[ActiveCheckResult, bool]:

    status = 0
    infotexts = []
    long_infotexts = []
    need_rediscovery = False

    for transition, title, params_key, default_state, service_filter in [
        ("new", "unmonitored", "severity_unmonitored",
         config.inventory_check_severity, service_filters.new),
        ("vanished", "vanished", "severity_vanished", 0,
         service_filters.vanished),
    ]:

        affected_check_plugin_names: Counter[CheckPluginName] = Counter()
        unfiltered = False

        for (discovered_service,
             _found_on_nodes) in services_by_transition.get(transition, []):
            affected_check_plugin_names[
                discovered_service.check_plugin_name] += 1

            if not unfiltered and service_filter(host_name,
                                                 discovered_service):
                unfiltered = True

            #TODO In service_filter:we use config.service_description(...)
            # in order to finalize service_description (translation, etc.).
            # Why do we use discovered_service.description here?
            long_infotexts.append(u"%s: %s: %s" %
                                  (title, discovered_service.check_plugin_name,
                                   discovered_service.description))

        if affected_check_plugin_names:
            info = ", ".join(
                ["%s:%d" % e for e in affected_check_plugin_names.items()])
            st = params.get(params_key, default_state)
            status = worst_service_state(status, st, default=0)
            infotexts.append(u"%d %s services (%s)%s" % (
                sum(affected_check_plugin_names.values()),
                title,
                info,
                state_markers[st],
            ))

            if (unfiltered and ((transition == "new" and discovery_mode in
                                 (DiscoveryMode.NEW, DiscoveryMode.FIXALL,
                                  DiscoveryMode.REFRESH)) or
                                (transition == "vanished" and discovery_mode in
                                 (DiscoveryMode.REMOVE, DiscoveryMode.FIXALL,
                                  DiscoveryMode.REFRESH)))):
                need_rediscovery = True
        else:
            infotexts.append(u"no %s services found" % title)

    for (discovered_service,
         _found_on_nodes) in services_by_transition.get("ignored", []):
        long_infotexts.append(u"ignored: %s: %s" %
                              (discovered_service.check_plugin_name,
                               discovered_service.description))

    return ActiveCheckResult(status, infotexts, long_infotexts,
                             []), need_rediscovery
Пример #6
0
def do_check(
    hostname: HostName,
    ipaddress: Optional[HostAddress],
    *,
    # The following arguments *must* remain optional for Nagios and the `DiscoCheckExecutor`.
    #   See Also: `cmk.base.discovery.check_discovery()`
    fetcher_messages: Sequence[FetcherMessage] = (),
    run_plugin_names: Container[CheckPluginName] = EVERYTHING,
    selected_sections: SectionNameCollection = NO_SELECTION,
    dry_run: bool = False,
    show_perfdata: bool = False,
) -> Tuple[int, List[ServiceDetails], List[ServiceAdditionalDetails], List[str]]:
    console.vverbose("Checkmk version %s\n", cmk_version.__version__)

    config_cache = config.get_config_cache()
    host_config = config_cache.get_host_config(hostname)

    exit_spec = host_config.exit_code_spec()

    mode = Mode.CHECKING if selected_sections is NO_SELECTION else Mode.FORCE_SECTIONS

    status: ServiceState = 0
    infotexts: List[ServiceDetails] = []
    long_infotexts: List[ServiceAdditionalDetails] = []
    perfdata: List[str] = []
    try:
        license_usage.try_history_update()

        # In case of keepalive we always have an ipaddress (can be 0.0.0.0 or :: when
        # address is unknown). When called as non keepalive ipaddress may be None or
        # is already an address (2nd argument)
        if ipaddress is None and not host_config.is_cluster:
            ipaddress = config.lookup_ip_address(host_config)

        services_to_check = _get_services_to_check(
            config_cache=config_cache,
            host_name=hostname,
            run_plugin_names=run_plugin_names,
        )

        with CPUTracker() as tracker:

            broker, source_results = make_broker(
                config_cache=config_cache,
                host_config=host_config,
                ip_address=ipaddress,
                mode=mode,
                selected_sections=selected_sections,
                file_cache_max_age=host_config.max_cachefile_age,
                fetcher_messages=fetcher_messages,
                force_snmp_cache_refresh=False,
                on_scan_error="raise",
            )

            num_success, plugins_missing_data = _do_all_checks_on_host(
                config_cache,
                host_config,
                ipaddress,
                parsed_sections_broker=broker,
                services=services_to_check,
                dry_run=dry_run,
                show_perfdata=show_perfdata,
            )

            if run_plugin_names is EVERYTHING:
                inventory.do_inventory_actions_during_checking_for(
                    config_cache,
                    host_config,
                    ipaddress,
                    parsed_sections_broker=broker,
                )

            for source, host_sections in source_results:
                source_state, source_output = source.summarize(host_sections)
                if source_output != "":
                    status = worst_service_state(status, source_state, default=3)
                    infotexts.append("[%s] %s" % (source.id, source_output))

            if plugins_missing_data:
                missing_data_status, missing_data_infotext = _check_plugins_missing_data(
                    plugins_missing_data,
                    exit_spec,
                    bool(num_success),
                )
                status = max(status, missing_data_status)
                infotexts.append(missing_data_infotext)

        total_times = tracker.duration
        for msg in fetcher_messages:
            total_times += msg.stats.duration

        infotexts.append("execution time %.1f sec" % total_times.process.elapsed)
        if config.check_mk_perfdata_with_times:
            perfdata += [
                "execution_time=%.3f" % total_times.process.elapsed,
                "user_time=%.3f" % total_times.process.user,
                "system_time=%.3f" % total_times.process.system,
                "children_user_time=%.3f" % total_times.process.children_user,
                "children_system_time=%.3f" % total_times.process.children_system,
            ]
            summary: DefaultDict[str, Snapshot] = defaultdict(Snapshot.null)
            for msg in fetcher_messages if fetcher_messages else ():
                if msg.fetcher_type in (
                        FetcherType.PIGGYBACK,
                        FetcherType.PROGRAM,
                        FetcherType.SNMP,
                        FetcherType.TCP,
                ):
                    summary[{
                        FetcherType.PIGGYBACK: "agent",
                        FetcherType.PROGRAM: "ds",
                        FetcherType.SNMP: "snmp",
                        FetcherType.TCP: "agent",
                    }[msg.fetcher_type]] += msg.stats.duration
            for phase, duration in summary.items():
                perfdata.append("cmk_time_%s=%.3f" % (phase, duration.idle))
        else:
            perfdata.append("execution_time=%.3f" % total_times.process.elapsed)

        return status, infotexts, long_infotexts, perfdata
    finally:
        _submit_to_core.finalize()
Пример #7
0
def test_worst_service_state_unknown():
    assert worst_service_state(0, 1, 3, default=0) == 3
Пример #8
0
def test_worst_service_state_empty():
    assert worst_service_state(default=0) == 0
    assert worst_service_state(default=1) == 1
    assert worst_service_state(default=2) == 2
    assert worst_service_state(default=3) == 3
Пример #9
0
def test_worst_service_state_crit():
    assert worst_service_state(0, 1, 2, 3, default=0) == 2
Пример #10
0
def test_worst_service_state_warn():
    assert worst_service_state(0, 1, default=0) == 1
Пример #11
0
def test_worst_service_state_ok():
    assert worst_service_state(0, 0, default=0) == 0
Пример #12
0
def do_inv_check(hostname: HostName, options: Dict[str, int]) -> ActiveCheckResult:
    _inv_hw_changes = options.get("hw-changes", 0)
    _inv_sw_changes = options.get("sw-changes", 0)
    _inv_sw_missing = options.get("sw-missing", 0)
    _inv_fail_status = options.get("inv-fail-status", 1)

    host_config = config.HostConfig.make_host_config(hostname)

    inv_result = _do_active_inventory_for(
        host_config=host_config,
        selected_sections=NO_SELECTION,
        run_plugin_names=EVERYTHING,
    )
    trees = inv_result.trees

    status = 0
    infotexts: List[str] = []
    long_infotexts: List[str] = []

    if inv_result.safe_to_write:
        old_tree = _save_inventory_tree(hostname, trees.inventory)
    else:
        old_tree, sources_state = None, 1
        status = worst_service_state(status, sources_state, default=3)
        infotexts.append("Cannot update tree%s" % state_markers[sources_state])

    _run_inventory_export_hooks(host_config, trees.inventory)

    if trees.inventory.is_empty() and trees.status_data.is_empty():
        infotexts.append("Found no data")

    else:
        infotexts.append("Found %d inventory entries" % trees.inventory.count_entries())

        # Node 'software' is always there because _do_inv_for creates this node for cluster info
        if not trees.inventory.get_sub_container(['software']).has_edge('packages')\
           and _inv_sw_missing:
            infotexts.append("software packages information is missing" +
                             state_markers[_inv_sw_missing])
            status = max(status, _inv_sw_missing)

        if old_tree is not None:
            if not old_tree.is_equal(trees.inventory, edges=["software"]):
                infotext = "software changes"
                if _inv_sw_changes:
                    status = max(status, _inv_sw_changes)
                    infotext += state_markers[_inv_sw_changes]
                infotexts.append(infotext)

            if not old_tree.is_equal(trees.inventory, edges=["hardware"]):
                infotext = "hardware changes"
                if _inv_hw_changes:
                    status = max(status, _inv_hw_changes)
                    infotext += state_markers[_inv_hw_changes]

                infotexts.append(infotext)

        if not trees.status_data.is_empty():
            infotexts.append("Found %s status entries" % trees.status_data.count_entries())

    for source, host_sections in inv_result.source_results:
        source_state, source_output = source.summarize(host_sections, mode=Mode.INVENTORY)
        if source_state != 0:
            # Do not output informational things (state == 0). Also do not use source states
            # which would overwrite "State when inventory fails" in the ruleset
            # "Do hardware/software Inventory".
            # These information and source states are handled by the "Check_MK" service
            status = max(_inv_fail_status, status)
            infotexts.append("[%s] %s" % (source.id, source_output))

    return status, infotexts, long_infotexts, []
Пример #13
0
def _check_service_lists(
    host_name: HostName,
    services_by_transition: ServicesByTransition,
    params: config.DiscoveryCheckParameters,
) -> _DiscoverySubresult:

    status = 0
    infotexts = []
    long_infotexts = []
    perfdata: List[Tuple] = []
    need_rediscovery = False

    service_filters = _ServiceFilters.from_settings(
        _get_rediscovery_parameters(params))
    rediscovery_mode = _get_rediscovery_mode(params)

    for transition, title, params_key, default_state, service_filter in [
        ("new", "unmonitored", "severity_unmonitored",
         config.inventory_check_severity, service_filters.new),
        ("vanished", "vanished", "severity_vanished", 0,
         service_filters.vanished),
    ]:

        affected_check_plugin_names: Counter[CheckPluginName] = Counter()
        unfiltered = False

        for (discovered_service,
             _found_on_nodes) in services_by_transition.get(transition, []):
            affected_check_plugin_names[
                discovered_service.check_plugin_name] += 1

            if not unfiltered and service_filter(host_name,
                                                 discovered_service):
                unfiltered = True

            #TODO In service_filter:we use config.service_description(...)
            # in order to finalize service_description (translation, etc.).
            # Why do we use discovered_service.description here?
            long_infotexts.append(u"%s: %s: %s" %
                                  (title, discovered_service.check_plugin_name,
                                   discovered_service.description))

        if affected_check_plugin_names:
            info = ", ".join(
                ["%s:%d" % e for e in affected_check_plugin_names.items()])
            st = params.get(params_key, default_state)
            status = worst_service_state(status, st, default=0)
            infotexts.append(u"%d %s services (%s)%s" % (
                sum(affected_check_plugin_names.values()),
                title,
                info,
                state_markers[st],
            ))

            if (unfiltered and
                ((transition == "new"
                  and rediscovery_mode in ("new", "fixall", "refresh")) or
                 (transition == "vanished"
                  and rediscovery_mode in ("remove", "fixall", "refresh")))):
                need_rediscovery = True
        else:
            infotexts.append(u"no %s services found" % title)

    for (discovered_service,
         _found_on_nodes) in services_by_transition.get("ignored", []):
        long_infotexts.append(u"ignored: %s: %s" %
                              (discovered_service.check_plugin_name,
                               discovered_service.description))

    return status, infotexts, long_infotexts, perfdata, need_rediscovery