Exemple #1
0
def host_extra_conf_merged(hostname, conf):
    return _config.get_config_cache().host_extra_conf_merged(hostname, conf)
Exemple #2
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()
Exemple #3
0
def host_extra_conf(hostname, ruleset):
    # type: (HostName, _config.Ruleset) -> List
    return _config.get_config_cache().host_extra_conf(hostname, ruleset)
Exemple #4
0
def check_discovery(
    host_name: HostName,
    ipaddress: Optional[HostAddress],
    *,
    # The next argument *must* remain optional for the DiscoCheckExecutor.
    #   See Also: `cmk.base.checking.do_check()`.
    fetcher_messages: Sequence[FetcherMessage] = (),
) -> Tuple[int, List[str], List[str], List[Tuple]]:

    # Note: '--cache' is set in core_cmc, nagios template or even on CL and means:
    # 1. use caches as default:
    #    - Set FileCacheFactory.maybe = True (set max_cachefile_age, else 0)
    #    - Set FileCacheFactory.use_outdated = True
    # 2. Then these settings are used to read cache file or not

    config_cache = config.get_config_cache()
    host_config = config_cache.get_host_config(host_name)
    discovery_parameters = DiscoveryParameters(
        on_error="raise",
        load_labels=True,
        save_labels=False,
        only_host_labels=False,
    )

    params = host_config.discovery_check_parameters
    if params is None:
        params = host_config.default_discovery_check_parameters()

    # In case of keepalive discovery we always have an ipaddress. When called as non keepalive
    # ipaddress is always None
    if ipaddress is None and not host_config.is_cluster:
        ipaddress = config.lookup_ip_address(host_config)

    parsed_sections_broker, source_results = make_broker(
        config_cache=config_cache,
        host_config=host_config,
        ip_address=ipaddress,
        mode=Mode.DISCOVERY,
        fetcher_messages=fetcher_messages,
        selected_sections=NO_SELECTION,
        file_cache_max_age=(config.discovery_max_cachefile_age()
                            if cmk.core_helpers.cache.FileCacheFactory.maybe
                            else 0),
        force_snmp_cache_refresh=False,
        on_scan_error=discovery_parameters.on_error,
    )

    services, host_label_discovery_result = _get_host_services(
        host_config,
        ipaddress,
        parsed_sections_broker,
        discovery_parameters,
    )

    status, infotexts, long_infotexts, perfdata, need_rediscovery = _aggregate_subresults(
        _check_service_lists(host_name, services, params),
        _check_host_labels(host_label_discovery_result, params),
        _check_data_sources(source_results),
    )

    if need_rediscovery:
        if host_config.is_cluster and host_config.nodes:
            for nodename in host_config.nodes:
                _set_rediscovery_flag(nodename)
        else:
            _set_rediscovery_flag(host_name)
        infotexts.append(u"rediscovery scheduled")

    return status, infotexts, long_infotexts, perfdata
Exemple #5
0
def complete_raw_context(raw_context: EventContext, with_dump: bool) -> None:
    """Extend the raw notification context

    This ensures that all raw contexts processed in the notification code has specific variables
    set. Add a few further helper variables that are useful in notification and alert plugins.

    Please not that this is not only executed on the source system. When notifications are
    forwarded to another site and the analysis is executed on that site, this function will be
    executed on the central site. So be sure not to overwrite site specific things.
    """

    raw_keys = list(raw_context)

    try:
        raw_context["WHAT"] = "SERVICE" if raw_context.get(
            "SERVICEDESC") else "HOST"

        raw_context.setdefault("MONITORING_HOST", socket.gethostname())
        raw_context.setdefault("OMD_ROOT", str(cmk.utils.paths.omd_root))
        raw_context.setdefault("OMD_SITE", omd_site())

        # The Checkmk Micro Core sends the MICROTIME and no other time stamps. We add
        # a few Nagios-like variants in order to be compatible
        if "MICROTIME" in raw_context:
            microtime = int(raw_context["MICROTIME"])
            timestamp = float(microtime) / 1000000.0
            broken = time.localtime(timestamp)
            raw_context["DATE"] = time.strftime("%Y-%m-%d", broken)
            raw_context["SHORTDATETIME"] = time.strftime(
                "%Y-%m-%d %H:%M:%S", broken)
            raw_context["LONGDATETIME"] = time.strftime(
                "%a %b %d %H:%M:%S %Z %Y", broken)
        elif "MICROTIME" not in raw_context:
            # In case the microtime is not provided, e.g. when using Nagios, then set it here
            # from the current time. We could look for "LONGDATETIME" and calculate the timestamp
            # from that one, but we try to keep this simple here.
            raw_context["MICROTIME"] = "%d" % (time.time() * 1000000)

        url_host_view = "view.py?view_name=hoststatus&host=%s&site=%s" % (
            raw_context["HOSTNAME"],
            raw_context["OMD_SITE"],
        )
        raw_context["HOSTURL"] = "/check_mk/index.py?start_url=%s" % quote(
            url_host_view)

        if raw_context["WHAT"] == "SERVICE":
            url_service_view = "view.py?view_name=service&host=%s&service=%s&site=%s" % (
                raw_context["HOSTNAME"],
                raw_context["SERVICEDESC"],
                raw_context["OMD_SITE"],
            )
            raw_context[
                "SERVICEURL"] = "/check_mk/index.py?start_url=%s" % quote(
                    url_service_view)

        # Relative Timestamps for several macros
        for macro in [
                "LASTHOSTSTATECHANGE",
                "LASTSERVICESTATECHANGE",
                "LASTHOSTUP",
                "LASTSERVICEOK",
        ]:
            if macro in raw_context:
                raw_context[macro + "_REL"] = get_readable_rel_date(
                    raw_context[macro])

        # Rule based notifications enabled? We might need to complete a few macros
        contact = raw_context.get("CONTACTNAME")
        if not contact or contact == "check-mk-notify":
            add_rulebased_macros(raw_context)

        # For custom notifications the number is set to 0 by the core (Nagios and CMC). We force at least
        # number 1 here, so that rules with conditions on numbers do not fail (the minimum is 1 here)
        for key in ["HOSTNOTIFICATIONNUMBER", "SERVICENOTIFICATIONNUMBER"]:
            if key in raw_context and raw_context[key] == "0":
                if with_dump:
                    logger.info("Setting %s for notification from '0' to '1'",
                                key)
                raw_context[key] = "1"

        # Add the previous hard state. This is neccessary for notification rules that depend on certain transitions,
        # like OK -> WARN (but not CRIT -> WARN). The CMC sends PREVIOUSHOSTHARDSTATE and PREVIOUSSERVICEHARDSTATE.
        # Nagios does not have this information and we try to deduct this.
        if "PREVIOUSHOSTHARDSTATE" not in raw_context and "LASTHOSTSTATE" in raw_context:
            prev_state = raw_context["LASTHOSTSTATE"]
            # When the attempts are > 1 then the last state could be identical with
            # the current one, e.g. both critical. In that case we assume the
            # previous hard state to be OK.
            if prev_state == raw_context["HOSTSTATE"]:
                prev_state = "UP"
            elif "HOSTATTEMPT" not in raw_context or (
                    "HOSTATTEMPT" in raw_context
                    and raw_context["HOSTATTEMPT"] != "1"):
                # Here We do not know. The transition might be OK -> WARN -> CRIT and
                # the initial OK is completely lost. We use the artificial state "?"
                # here, which matches all states and makes sure that when in doubt a
                # notification is being sent out. But when the new state is UP, then
                # we know that the previous state was a hard state (otherwise there
                # would not have been any notification)
                if raw_context["HOSTSTATE"] != "UP":
                    prev_state = "?"
                logger.info(
                    "Previous host hard state not known. Allowing all states.")
            raw_context["PREVIOUSHOSTHARDSTATE"] = prev_state

        # Same for services
        if raw_context[
                "WHAT"] == "SERVICE" and "PREVIOUSSERVICEHARDSTATE" not in raw_context:
            prev_state = raw_context["LASTSERVICESTATE"]
            if prev_state == raw_context["SERVICESTATE"]:
                prev_state = "OK"
            elif "SERVICEATTEMPT" not in raw_context or (
                    "SERVICEATTEMPT" in raw_context
                    and raw_context["SERVICEATTEMPT"] != "1"):
                if raw_context["SERVICESTATE"] != "OK":
                    prev_state = "?"
                logger.info(
                    "Previous service hard state not known. Allowing all states."
                )
            raw_context["PREVIOUSSERVICEHARDSTATE"] = prev_state

        # Add short variants for state names (at most 4 characters)
        for key, value in list(raw_context.items()):
            if key.endswith("STATE"):
                raw_context[key[:-5] + "SHORTSTATE"] = value[:4]

        if raw_context["WHAT"] == "SERVICE":
            raw_context["SERVICEFORURL"] = quote(raw_context["SERVICEDESC"])
        raw_context["HOSTFORURL"] = quote(raw_context["HOSTNAME"])

        config_cache = config.get_config_cache()
        labels = config_cache.labels
        ruleset_matcher = config_cache.ruleset_matcher
        for k, v in labels.labels_of_host(ruleset_matcher,
                                          raw_context["HOSTNAME"]).items():
            raw_context["HOSTLABEL_" + k] = v
        if raw_context["WHAT"] == "SERVICE":
            for k, v in labels.labels_of_service(
                    ruleset_matcher, raw_context["HOSTNAME"],
                    raw_context["SERVICEDESC"]).items():
                raw_context["SERVICELABEL_" + k] = v

    except Exception as e:
        logger.info("Error on completing raw context: %s", e)

    if with_dump:
        log_context = "\n".join(
            sorted([
                "                    %s=%s" % (k, raw_context[k])
                for k in raw_context if k not in raw_keys
            ]))
        logger.info("Computed variables:\n%s", log_context)
Exemple #6
0
def dump_host(hostname: HostName) -> None:
    config_cache = config.get_config_cache()
    host_config = config_cache.get_host_config(hostname)

    out.output("\n")
    if host_config.is_cluster:
        nodes = host_config.nodes
        if nodes is None:
            raise RuntimeError()
        color = tty.bgmagenta
        add_txt = " (cluster of " + (", ".join(nodes)) + ")"
    else:
        color = tty.bgblue
        add_txt = ""
    out.output("%s%s%s%-78s %s\n" %
               (color, tty.bold, tty.white, hostname + add_txt, tty.normal))

    ipaddress = _ip_address_for_dump_host(
        host_config, family=host_config.default_address_family)

    addresses: Optional[str] = ""
    if not host_config.is_ipv4v6_host:
        addresses = ipaddress
    else:
        try:
            secondary = _ip_address_for_dump_host(
                host_config,
                family=socket.AF_INET
                if host_config.is_ipv6_primary else socket.AF_INET6,
            )
        except Exception:
            secondary = "X.X.X.X"

        addresses = "%s, %s" % (ipaddress, secondary)
        if host_config.is_ipv6_primary:
            addresses += " (Primary: IPv6)"
        else:
            addresses += " (Primary: IPv4)"

    out.output(tty.yellow + "Addresses:              " + tty.normal +
               (addresses if addresses is not None else "No IP") + "\n")

    tag_template = tty.bold + "[" + tty.normal + "%s" + tty.bold + "]" + tty.normal
    tags = [(tag_template % ":".join(t))
            for t in sorted(host_config.tag_groups.items())]
    out.output(tty.yellow + "Tags:                   " + tty.normal +
               ", ".join(tags) + "\n")

    labels = [
        tag_template % ":".join(l) for l in sorted(host_config.labels.items())
    ]
    out.output(tty.yellow + "Labels:                 " + tty.normal +
               ", ".join(labels) + "\n")

    # TODO: Clean this up once cluster parent handling has been moved to HostConfig
    if host_config.is_cluster:
        parents_list = host_config.nodes
        if parents_list is None:
            raise RuntimeError()
    else:
        parents_list = host_config.parents
    if len(parents_list) > 0:
        out.output(tty.yellow + "Parents:                " + tty.normal +
                   ", ".join(parents_list) + "\n")
    out.output(tty.yellow + "Host groups:            " + tty.normal +
               ", ".join(host_config.hostgroups) + "\n")
    out.output(tty.yellow + "Contact groups:         " + tty.normal +
               ", ".join(host_config.contactgroups) + "\n")

    agenttypes = [
        source.description
        for source in sources.make_sources(host_config, ipaddress)
    ]

    if host_config.is_ping_host:
        agenttypes.append('PING only')

    out.output(tty.yellow + "Agent mode:             " + tty.normal)
    out.output(host_config.agent_description + "\n")

    out.output(tty.yellow + "Type of agent:          " + tty.normal)
    if len(agenttypes) == 1:
        out.output(agenttypes[0] + "\n")
    else:
        out.output("\n  ")
        out.output("\n  ".join(agenttypes) + "\n")

    out.output(tty.yellow + "Services:" + tty.normal + "\n")

    headers = ["checktype", "item", "params", "description", "groups"]
    colors = [tty.normal, tty.blue, tty.normal, tty.green, tty.normal]

    table_data = []
    for service in sorted(check_table.get_check_table(hostname).values(),
                          key=lambda s: s.description):
        table_data.append([
            str(service.check_plugin_name),
            str(service.item),
            _evaluate_params(service.parameters), service.description,
            ",".join(
                config_cache.servicegroups_of_service(hostname,
                                                      service.description))
        ])

    tty.print_table(headers, colors, table_data, "  ")
Exemple #7
0
def do_inv_check(
    hostname: HostName, options: Dict[str, int]
) -> Tuple[ServiceState, List[ServiceDetails], List[ServiceAdditionalDetails],
           List[MetricTuple]]:
    _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)

    config_cache = config.get_config_cache()
    host_config = config.HostConfig.make_host_config(hostname)
    if host_config.is_cluster:
        ipaddress = None
    else:
        ipaddress = ip_lookup.lookup_ip_address(host_config)

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

    sources = checkers.make_sources(
        host_config,
        ipaddress,
        mode=checkers.Mode.INVENTORY,
    )
    inventory_tree, status_data_tree, results = _do_inv_for(
        config_cache,
        host_config,
        ipaddress,
        sources=sources,
        multi_host_sections=None,
    )

    #TODO add cluster if and only if all sources do not fail?
    if _all_sources_fail(host_config, ipaddress):
        old_tree, sources_state = None, 1
        status = max(status, sources_state)
        infotexts.append("Cannot update tree%s" %
                         check_api_utils.state_markers[sources_state])
    else:
        old_tree = _save_inventory_tree(hostname, inventory_tree)

    _run_inventory_export_hooks(host_config, inventory_tree)

    if inventory_tree.is_empty() and status_data_tree.is_empty():
        infotexts.append("Found no data")

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

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

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

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

                infotexts.append(infotext)

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

    for source, host_sections in results:
        source_state, source_output, _source_perfdata = source.summarize(
            host_sections)
        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, []
Exemple #8
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)

    filter_mode = None

    belongs_to_cluster = len(config_cache.clusters_of(hostname)) > 0
    if belongs_to_cluster:
        filter_mode = "include_clustered"

    services = check_table.get_precompiled_check_table(hostname,
                                                       remove_duplicates=True,
                                                       filter_mode=filter_mode)

    # 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()

    # Filter out check types which are not used on the node
    if belongs_to_cluster:
        pos_match = set()
        neg_match = set()
        for service in services:
            if hostname != config_cache.host_of_clustered_service(hostname, service.description):
                pos_match.add(service.check_plugin_name)
            else:
                neg_match.add(service.check_plugin_name)
        only_check_plugins -= (pos_match - neg_match)

    for service in services:
        if only_check_plugins is not None and service.check_plugin_name not in only_check_plugins:
            continue

        if belongs_to_cluster and hostname != config_cache.host_of_clustered_service(
                hostname, service.description):
            continue

        success = execute_check(config_cache, multi_host_sections, hostname, ipaddress,
                                service.check_plugin_name, service.item, service.parameters,
                                service.description)
        if success:
            num_success += 1
        elif success is None:
            # If the service is in any timeperiod we do not want to
            # - increase num_success or
            # - add to missing sections
            continue
        else:
            missing_sections.add(cmk.base.check_utils.section_name_of(service.check_plugin_name))

    import cmk.base.inventory as inventory
    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
Exemple #9
0
def do_discovery(
    arg_hostnames: Set[HostName],
    *,
    selected_sections: SectionNameCollection,
    run_only_plugin_names: Optional[Set[CheckPluginName]],
    arg_only_new: bool,
    only_host_labels: bool = False,
) -> None:
    config_cache = config.get_config_cache()
    use_caches = not arg_hostnames or cmk.core_helpers.cache.FileCacheFactory.maybe
    on_error = "raise" if cmk.utils.debug.enabled() else "warn"

    discovery_parameters = DiscoveryParameters(
        on_error=on_error,
        load_labels=arg_only_new,
        save_labels=True,
        only_host_labels=only_host_labels,
    )

    host_names = _preprocess_hostnames(arg_hostnames, config_cache, only_host_labels)

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

    # Now loop through all hosts
    for host_name in sorted(host_names):
        host_config = config_cache.get_host_config(host_name)
        section.section_begin(host_name)
        try:
            ipaddress = config.lookup_ip_address(host_config)
            nodes = sources.make_nodes(
                config_cache,
                host_config,
                ipaddress,
                mode,
                sources.make_sources(
                    host_config,
                    ipaddress,
                    mode=mode,
                    selected_sections=selected_sections,
                    on_scan_error=on_error,
                ),
            )
            max_cachefile_age = config.discovery_max_cachefile_age() if use_caches else 0

            parsed_sections_broker = ParsedSectionsBroker()
            sources.update_host_sections(
                parsed_sections_broker,
                nodes,
                max_cachefile_age=max_cachefile_age,
                host_config=host_config,
                fetcher_messages=list(
                    sources.fetch_all(
                        nodes,
                        max_cachefile_age=max_cachefile_age,
                        host_config=host_config,
                    )),
                selected_sections=selected_sections,
            )
            _do_discovery_for(
                host_name,
                ipaddress,
                parsed_sections_broker,
                run_only_plugin_names,
                arg_only_new,
                discovery_parameters,
            )

        except Exception as e:
            if cmk.utils.debug.enabled():
                raise
            section.section_error("%s" % e)
        finally:
            cmk.utils.cleanup.cleanup_globals()
Exemple #10
0
def test_mode_discover_all_hosts(mocker):
    _patch_data_source(mocker, maybe=True, max_age=120)
    cmk.base.modes.check_mk.mode_discover({"discover": 1}, [])
    active_real_hosts = config.get_config_cache().all_active_realhosts()
    assert ABCChecker.check.call_count == (  # type: ignore[attr-defined]
        len(active_real_hosts) * 2)
Exemple #11
0
def do_check(hostname, ipaddress, only_check_plugin_names=None):
    # type: (HostName, Optional[HostAddress], Optional[List[CheckPluginName]]) -> Tuple[int, List[ServiceDetails], List[ServiceAdditionalDetails], List[Text]]
    cpu_tracking.start("busy")
    console.verbose("Check_MK version %s\n", six.ensure_str(cmk.__version__))

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

    exit_spec = host_config.exit_code_spec()

    status = 0  # type: ServiceState
    infotexts = []  # type: List[ServiceDetails]
    long_infotexts = []  # type: List[ServiceAdditionalDetails]
    perfdata = []  # type: List[Text]
    try:
        # 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 = ip_lookup.lookup_ip_address(hostname)

        item_state.load(hostname)

        sources = data_sources.DataSources(hostname, ipaddress)

        num_success, missing_sections = \
            _do_all_checks_on_host(sources, host_config, ipaddress, only_check_plugin_names)

        if _submit_to_core:
            item_state.save(hostname)

        for source in sources.get_data_sources():
            source_state, source_output, source_perfdata = source.get_summary_result_for_checking()
            if source_output != "":
                status = max(status, source_state)
                infotexts.append("[%s] %s" % (source.id(), source_output))
                perfdata.extend([_convert_perf_data(p) for p in source_perfdata])

        if missing_sections and num_success > 0:
            missing_sections_status, missing_sections_infotext = \
                _check_missing_sections(missing_sections, exit_spec)
            status = max(status, missing_sections_status)
            infotexts.append(missing_sections_infotext)

        elif missing_sections:
            infotexts.append("Got no information from host")
            status = max(status, cast(int, exit_spec.get("empty_output", 2)))

        cpu_tracking.end()
        phase_times = cpu_tracking.get_times()
        total_times = phase_times["TOTAL"]
        run_time = total_times[4]

        infotexts.append("execution time %.1f sec" % run_time)
        if config.check_mk_perfdata_with_times:
            perfdata += [
                "execution_time=%.3f" % run_time,
                "user_time=%.3f" % total_times[0],
                "system_time=%.3f" % total_times[1],
                "children_user_time=%.3f" % total_times[2],
                "children_system_time=%.3f" % total_times[3],
            ]

            for phase, times in phase_times.items():
                if phase in ["agent", "snmp", "ds"]:
                    t = times[4] - sum(times[:4])  # real time - CPU time
                    perfdata.append("cmk_time_%s=%.3f" % (phase, t))
        else:
            perfdata.append("execution_time=%.3f" % run_time)

        return status, infotexts, long_infotexts, perfdata
    finally:
        if _checkresult_file_fd is not None:
            _close_checkresult_file()

        # "ipaddress is not None": At least when working with a cluster host it seems the ipaddress
        # may be None.  This needs to be understood in detail and cleaned up. As the InlineSNMP
        # stats feature is a very rarely used debugging feature, the analyzation and fix is
        # postponed now.
        if config.record_inline_snmp_stats \
           and ipaddress is not None \
           and host_config.snmp_config(ipaddress).is_inline_snmp_host:
            inline_snmp.save_snmp_stats()
Exemple #12
0
def is_ipv6_primary(hostname):
    # type: (HostName) -> bool
    return _config.get_config_cache().get_host_config(hostname).is_ipv6_primary
Exemple #13
0
def tags_of_host(hostname):
    # type: (HostName) -> Set[str]
    return _config.get_config_cache().get_host_config(hostname).tags
Exemple #14
0
def all_matching_hosts(tags, hostlist, with_foreign_hosts):
    return _config.get_config_cache(
    ).ruleset_matcher.ruleset_optimizer._all_matching_hosts(
        tags, hostlist, with_foreign_hosts)
Exemple #15
0
def is_ipv6_primary(hostname: HostName) -> bool:
    return _config.get_config_cache().get_host_config(hostname).is_ipv6_primary
Exemple #16
0
def do_check(
    hostname: HostName,
    ipaddress: Optional[HostAddress],
    only_check_plugin_names: Optional[Set[CheckPluginName]] = None
) -> Tuple[int, List[ServiceDetails], List[ServiceAdditionalDetails],
           List[str]]:
    cpu_tracking.start("busy")
    console.verbose("Check_MK 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()

    status: ServiceState = 0
    infotexts: List[ServiceDetails] = []
    long_infotexts: List[ServiceAdditionalDetails] = []
    perfdata: List[str] = []
    try:
        # 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 = ip_lookup.lookup_ip_address(host_config)

        item_state.load(hostname)

        services = _get_filtered_services(
            host_name=hostname,
            belongs_to_cluster=len(config_cache.clusters_of(hostname)) > 0,
            config_cache=config_cache,
            only_check_plugins=only_check_plugin_names,
        )

        # see which raw sections we may need
        selected_raw_sections = _get_relevant_raw_sections(
            services, host_config)

        sources = data_sources.make_sources(
            host_config,
            ipaddress,
            mode=data_sources.Mode.CHECKING,
        )
        mhs = data_sources.make_host_sections(
            config_cache,
            host_config,
            ipaddress,
            data_sources.Mode.CHECKING,
            sources=sources,
            selected_raw_sections=selected_raw_sections,
            max_cachefile_age=host_config.max_cachefile_age,
        )
        num_success, plugins_missing_data = _do_all_checks_on_host(
            config_cache,
            host_config,
            ipaddress,
            multi_host_sections=mhs,
            services=services,
            only_check_plugins=only_check_plugin_names,
        )
        inventory.do_inventory_actions_during_checking_for(
            config_cache,
            host_config,
            ipaddress,
            sources=sources,
            multi_host_sections=mhs,
        )

        if _submit_to_core:
            item_state.save(hostname)

        for source in sources:
            source_state, source_output, source_perfdata = source.get_summary_result(
            )
            if source_output != "":
                status = max(status, source_state)
                infotexts.append("[%s] %s" % (source.id, source_output))
                perfdata.extend(
                    [_convert_perf_data(p) for p in source_perfdata])

        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)

        cpu_tracking.end()
        phase_times = cpu_tracking.get_times()
        total_times = phase_times["TOTAL"]
        run_time = total_times[4]

        infotexts.append("execution time %.1f sec" % run_time)
        if config.check_mk_perfdata_with_times:
            perfdata += [
                "execution_time=%.3f" % run_time,
                "user_time=%.3f" % total_times[0],
                "system_time=%.3f" % total_times[1],
                "children_user_time=%.3f" % total_times[2],
                "children_system_time=%.3f" % total_times[3],
            ]

            for phase, times in phase_times.items():
                if phase in ["agent", "snmp", "ds"]:
                    t = times[4] - sum(times[:4])  # real time - CPU time
                    perfdata.append("cmk_time_%s=%.3f" % (phase, t))
        else:
            perfdata.append("execution_time=%.3f" % run_time)

        return status, infotexts, long_infotexts, perfdata
    finally:
        if _checkresult_file_fd is not None:
            _close_checkresult_file()

        # "ipaddress is not None": At least when working with a cluster host it seems the ipaddress
        # may be None.  This needs to be understood in detail and cleaned up. As the InlineSNMP
        # stats feature is a very rarely used debugging feature, the analyzation and fix is
        # postponed now.
        if config.record_inline_snmp_stats \
           and ipaddress is not None \
           and host_config.snmp_config(ipaddress).is_inline_snmp_host:
            inline.snmp_stats_save()
Exemple #17
0
 def __init__(self, hostname, ipaddress):
     super(PiggyBackDataSource, self).__init__(hostname, ipaddress)
     self._processed_file_reasons = set()
     self._time_settings = config.get_config_cache().get_piggybacked_hosts_time_settings(
         piggybacked_hostname=self._hostname)
Exemple #18
0
def service_extra_conf(hostname: HostName, service: ServiceName,
                       ruleset: _config.Ruleset) -> List:
    return _config.get_config_cache().service_extra_conf(
        hostname, service, ruleset)
Exemple #19
0
 def __init__(self):
     # type: () -> None
     super(MultiHostSections, self).__init__()
     self._config_cache = config.get_config_cache()
     self._multi_host_sections = {}  # type: MultiHostSectionsData
     self._section_content_cache = caching.DictCache()
Exemple #20
0
def host_extra_conf(hostname: HostName, ruleset: _config.Ruleset) -> List:
    return _config.get_config_cache().host_extra_conf(hostname, ruleset)
Exemple #21
0
def get_check_preview(
    *,
    host_name: HostName,
    max_cachefile_age: int,
    use_cached_snmp_data: bool,
    on_error: str,
) -> Tuple[CheckPreviewTable, QualifiedDiscovery[HostLabel]]:
    """Get the list of service of a host or cluster and guess the current state of
    all services if possible"""
    config_cache = config.get_config_cache()
    host_config = config_cache.get_host_config(host_name)

    ip_address = None if host_config.is_cluster else config.lookup_ip_address(
        host_config)
    discovery_parameters = DiscoveryParameters(
        on_error=on_error,
        load_labels=True,
        save_labels=False,
        only_host_labels=False,
    )

    _set_cache_opts_of_checkers(use_cached_snmp_data=use_cached_snmp_data)

    parsed_sections_broker, _source_results = make_broker(
        config_cache=config_cache,
        host_config=host_config,
        ip_address=ip_address,
        mode=Mode.DISCOVERY,
        file_cache_max_age=max_cachefile_age,
        selected_sections=NO_SELECTION,
        fetcher_messages=(),
        force_snmp_cache_refresh=not use_cached_snmp_data,
        on_scan_error=on_error,
    )

    grouped_services, host_label_result = _get_host_services(
        host_config,
        ip_address,
        parsed_sections_broker,
        discovery_parameters,
    )

    table: CheckPreviewTable = []
    for check_source, services_with_nodes in grouped_services.items():
        for service, found_on_nodes in services_with_nodes:
            plugin = agent_based_register.get_check_plugin(
                service.check_plugin_name)
            params = _preview_params(host_name, service, plugin, check_source)

            if check_source in ['legacy', 'active', 'custom']:
                exitcode = None
                output = u"WAITING - %s check, cannot be done offline" % check_source.title(
                )
                ruleset_name: Optional[RulesetName] = None
            else:

                ruleset_name = (str(plugin.check_ruleset_name) if plugin
                                and plugin.check_ruleset_name else None)
                wrapped_params = (
                    Parameters(wrap_parameters(params)) if plugin
                    and plugin.check_default_parameters is not None else None)

                exitcode, output, _perfdata = checking.get_aggregated_result(
                    parsed_sections_broker,
                    host_config,
                    ip_address,
                    service,
                    plugin,
                    lambda p=wrapped_params:
                    p,  # type: ignore[misc]  # "type of lambda"
                ).result

            # Service discovery never uses the perfdata in the check table. That entry
            # is constantly discarded, yet passed around(back and forth) as part of the
            # discovery result in the request elements. Some perfdata VALUES are not parsable
            # by ast.literal_eval such as "inf" it lead to ValueErrors. Thus keep perfdata empty
            perfdata: List[MetricTuple] = []
            table.append((
                _preview_check_source(host_name, service, check_source),
                str(service.check_plugin_name),
                ruleset_name,
                service.item,
                service.parameters,
                params,
                service.description,
                exitcode,
                output,
                perfdata,
                service.service_labels.to_dict(),
                found_on_nodes,
            ))

    return table, host_label_result
Exemple #22
0
def in_binary_hostlist(hostname: HostName, ruleset: _config.Ruleset) -> bool:
    return _config.get_config_cache().in_binary_hostlist(hostname, ruleset)
Exemple #23
0
def update():
    config.load_all_agent_based_plugins(check_api.get_check_api_context)
    config.load()

    config_cache = config.get_config_cache()
    update_service_info(config_cache, get_hostnames(config_cache))
Exemple #24
0
def host_extra_conf_merged(hostname: HostName,
                           conf: _config.Ruleset) -> Dict[str, Any]:
    return _config.get_config_cache().host_extra_conf_merged(hostname, conf)
Exemple #25
0
def get_aggregated_result(
    parsed_sections_broker: ParsedSectionsBroker,
    host_config: config.HostConfig,
    ipaddress: Optional[HostAddress],
    service: Service,
    plugin: Optional[checking_classes.CheckPlugin],
    params_function: Callable[[], Parameters],
    *,
    value_store_manager: item_state.ValueStoreManager,
) -> AggregatedResult:
    """Run the check function and aggregate the subresults

    This function is also called during discovery.
    """
    if plugin is None:
        return AggregatedResult(
            submit=True,
            data_received=True,
            result=CHECK_NOT_IMPLEMENTED,
            cache_info=None,
        )

    check_function = (plugin.cluster_check_function
                      if host_config.is_cluster else plugin.check_function)

    source_type = (SourceType.MANAGEMENT
                   if service.check_plugin_name.is_management_name() else SourceType.HOST)

    config_cache = config.get_config_cache()

    kwargs = {}
    try:
        kwargs = parsed_sections_broker.get_section_cluster_kwargs(
            config_cache.get_clustered_service_node_keys(
                host_config.hostname,
                source_type,
                service.description,
            ) or [],
            plugin.sections,
        ) if host_config.is_cluster else parsed_sections_broker.get_section_kwargs(
            HostKey(host_config.hostname, ipaddress, source_type),
            plugin.sections,
        )

        if not kwargs and not service.check_plugin_name.is_management_name():
            # in 1.6 some plugins where discovered for management boards, but with
            # the regular host plugins name. In this case retry with the source type
            # forced to MANAGEMENT:
            kwargs = parsed_sections_broker.get_section_cluster_kwargs(
                config_cache.get_clustered_service_node_keys(
                    host_config.hostname,
                    SourceType.MANAGEMENT,
                    service.description,
                ) or [],
                plugin.sections,
            ) if host_config.is_cluster else parsed_sections_broker.get_section_kwargs(
                HostKey(host_config.hostname, ipaddress, SourceType.MANAGEMENT),
                plugin.sections,
            )

        if not kwargs:  # no data found
            return AggregatedResult(
                submit=False,
                data_received=False,
                result=RECEIVED_NO_DATA,
                cache_info=None,
            )

        if service.item is not None:
            kwargs["item"] = service.item

        if plugin.check_default_parameters is not None:
            kwargs["params"] = params_function()

        with plugin_contexts.current_host(host_config.hostname), \
            plugin_contexts.current_service(service), \
            value_store_manager.namespace(service.id()):
            result = _aggregate_results(check_function(**kwargs))

    except (item_state.MKCounterWrapped, checking_classes.IgnoreResultsError) as e:
        msg = str(e) or "No service summary available"
        return AggregatedResult(
            submit=False,
            data_received=True,
            result=(0, msg, []),
            cache_info=None,
        )

    except MKTimeout:
        raise

    except Exception:
        if cmk.utils.debug.enabled():
            raise
        table = check_table.get_check_table(host_config.hostname, skip_autochecks=True)
        result = 3, cmk.base.crash_reporting.create_check_crash_dump(
            host_name=host_config.hostname,
            service_name=service.description,
            plugin_name=service.check_plugin_name,
            plugin_kwargs=kwargs,
            is_manual=service.id() in table,
        ), []

    return AggregatedResult(
        submit=True,
        data_received=True,
        result=result,
        cache_info=parsed_sections_broker.get_cache_info(plugin.sections),
    )
Exemple #26
0
def all_matching_hosts(condition: Dict[str, Any],
                       with_foreign_hosts: bool) -> Set[HostName]:
    return _config.get_config_cache(
    ).ruleset_matcher.ruleset_optimizer._all_matching_hosts(
        condition, with_foreign_hosts)
Exemple #27
0
def service_extra_conf(hostname, service, ruleset):
    # type: (HostName, ServiceName, _config.Ruleset) -> List
    return _config.get_config_cache().service_extra_conf(
        hostname, service, ruleset)
Exemple #28
0
def tags_of_host(hostname: HostName) -> Set[str]:
    return _config.get_config_cache().get_host_config(hostname).tags
Exemple #29
0
def in_binary_hostlist(hostname, ruleset):
    # type: (HostName, _config.Ruleset) -> bool
    return _config.get_config_cache().in_binary_hostlist(hostname, ruleset)
Exemple #30
0
def in_binary_hostlist(hostname, ruleset):
    return _config.get_config_cache().in_binary_hostlist(hostname, ruleset)