Exemple #1
0
def iter_active_check_services(
    check_name: str,
    active_info: Mapping[str, Any],
    hostname: str,
    host_attrs: config.ObjectAttributes,
    params: Dict[Any, Any],
) -> Iterator[Tuple[str, str]]:
    """Iterate active service descriptions and arguments

    This function is used to allow multiple active services per one WATO rule.
    This functionality is now used only in ICMP active check and it's NOT
    part of an official API. This function can be changed at any time.
    """
    host_config = _get_host_address_config(hostname, host_attrs)

    if "service_generator" in active_info:
        for desc, args in active_info["service_generator"](host_config, params):
            yield str(desc), str(args)
        return

    description = config.active_check_service_description(
        host_config.hostname, host_config.alias, check_name, params
    )
    arguments = active_check_arguments(
        host_config.hostname, description, active_info["argument_function"](params)
    )

    yield description, arguments
Exemple #2
0
def _merge_manual_services(
    host_config: config.HostConfig,
    services: ServicesTable,
    discovery_parameters: DiscoveryParameters,
) -> ServicesByTransition:
    """Add/replace manual and active checks and handle ignoration"""
    host_name = host_config.hostname

    # Find manual checks. These can override discovered checks -> "manual"
    manual_items = check_table.get_check_table(host_name, skip_autochecks=True)
    for service in manual_items.values():
        services[service.id()] = ('manual', service, [host_name])

    # Add custom checks -> "custom"
    for entry in host_config.custom_checks:
        services[(CheckPluginName('custom'), entry['service_description'])] = (
            'custom',
            Service(
                check_plugin_name=CheckPluginName('custom'),
                item=entry['service_description'],
                description=entry['service_description'],
                parameters=None,
            ),
            [host_name],
        )

    # Similar for 'active_checks', but here we have parameters
    for plugin_name, entries in host_config.active_checks:
        for params in entries:
            descr = config.active_check_service_description(
                host_name, plugin_name, params)
            services[(CheckPluginName(plugin_name), descr)] = (
                'active',
                Service(
                    check_plugin_name=CheckPluginName(plugin_name),
                    item=descr,
                    description=descr,
                    parameters=params,
                ),
                [host_name],
            )

    # Handle disabled services -> "ignored"
    for check_source, discovered_service, _found_on_nodes in services.values():
        if check_source in ["legacy", "active", "custom"]:
            # These are ignored later in get_check_preview
            # TODO: This needs to be cleaned up. The problem here is that service_description() can not
            # calculate the description of active checks and the active checks need to be put into
            # "[source]_ignored" instead of ignored.
            continue

        if config.service_ignored(host_name,
                                  discovered_service.check_plugin_name,
                                  discovered_service.description):
            services[discovered_service.id()] = ("ignored", discovered_service,
                                                 [host_name])

    return _group_by_transition(services.values())
Exemple #3
0
def _active_items(host_config: config.HostConfig) -> Iterable[Tuple[ServiceID, ServicesTableEntry]]:
    # Similar for 'active_checks', but here we have parameters
    host_name = host_config.hostname
    for plugin_name, entries in host_config.active_checks:
        for params in entries:
            descr = config.active_check_service_description(host_name, plugin_name, params)
            yield (CheckPluginName(plugin_name), descr), (
                'active',
                Service(
                    check_plugin_name=CheckPluginName(plugin_name),
                    item=descr,
                    description=descr,
                    parameters=params,
                ),
                [host_name],
            )
Exemple #4
0
def get_active_check_descriptions(
    hostname: HostName,
    hostalias: str,
    host_attrs: ObjectAttributes,
    check_name: str,
    params: Dict,
) -> Iterator[str]:
    host_config = _get_host_address_config(hostname, host_attrs)
    active_check_info = config.active_check_info[check_name]

    if "service_generator" in active_check_info:
        for description, _ in active_check_info["service_generator"](host_config, params):
            yield str(description)
        return

    yield config.active_check_service_description(hostname, hostalias, check_name, params)
Exemple #5
0
def _create_nagios_servicedefs(cfg, config_cache, hostname, host_attrs):
    # type: (NagiosConfig, ConfigCache, HostName, ObjectAttributes) -> None
    import cmk.base.check_table as check_table  # pylint: disable=import-outside-toplevel

    host_config = config_cache.get_host_config(hostname)

    check_mk_attrs = core_config.get_service_attributes(
        hostname, "Check_MK", config_cache)

    #   _____
    #  |___ /
    #    |_ \
    #   ___) |
    #  |____/   3. Services

    def do_omit_service(hostname, description):
        # type: (HostName, ServiceName) -> bool
        if config.service_ignored(hostname, None, description):
            return True
        if hostname != config_cache.host_of_clustered_service(
                hostname, description):
            return True
        return False

    def get_dependencies(hostname, servicedesc):
        # type: (HostName, ServiceName) -> str
        result = ""
        for dep in config.service_depends_on(hostname, servicedesc):
            result += _format_nagios_object(
                "servicedependency", {
                    "use": config.service_dependency_template,
                    "host_name": hostname,
                    "service_description": dep,
                    "dependent_host_name": hostname,
                    "dependent_service_description": servicedesc,
                })

        return result

    services = check_table.get_check_table(hostname,
                                           remove_duplicates=True).values()
    have_at_least_one_service = False
    used_descriptions = {
    }  # type: Dict[ServiceName, Tuple[CheckPluginName, Item]]
    for service in sorted(services,
                          key=lambda s: (s.check_plugin_name, s.item)):
        if service.check_plugin_name not in config.check_info:
            continue  # simply ignore missing checks

        # Make sure, the service description is unique on this host
        if service.description in used_descriptions:
            cn, it = used_descriptions[service.description]
            # TODO: Remove "type: ignore" once we are on python3
            core_config.warning(
                "ERROR: Duplicate service description '%s' for host '%s'!\n"  # type: ignore[arg-type]
                " - 1st occurrance: checktype = %s, item = %r\n"
                " - 2nd occurrance: checktype = %s, item = %r\n" %
                (service.description, hostname, cn, it,
                 service.check_plugin_name, service.item))
            continue

        used_descriptions[service.description] = (service.check_plugin_name,
                                                  service.item)
        if config.check_info[service.check_plugin_name].get(
                "has_perfdata", False):
            template = config.passive_service_template_perf
        else:
            template = config.passive_service_template

        # Services Dependencies for autochecks
        cfg.write(get_dependencies(hostname, service.description))

        service_spec = {
            "use": template,
            "host_name": hostname,
            "service_description": service.description,
            "check_command": "check_mk-%s" % service.check_plugin_name,
        }

        service_spec.update(
            core_config.get_cmk_passive_service_attributes(
                config_cache, host_config, service, check_mk_attrs))
        service_spec.update(
            _extra_service_conf_of(cfg, config_cache, hostname,
                                   service.description))

        cfg.write(_format_nagios_object("service", service_spec))

        cfg.checknames_to_define.add(service.check_plugin_name)
        have_at_least_one_service = True

    # Active check for check_mk
    if have_at_least_one_service:
        service_spec = {
            "use": config.active_service_template,
            "host_name": hostname,
            "service_description": "Check_MK",
        }
        service_spec.update(check_mk_attrs)
        service_spec.update(
            _extra_service_conf_of(cfg, config_cache, hostname, "Check_MK"))
        cfg.write(_format_nagios_object("service", service_spec))

    # legacy checks via active_checks
    actchecks = []
    for plugin_name, entries in host_config.active_checks:
        cfg.active_checks_to_define.add(plugin_name)
        act_info = config.active_check_info[plugin_name]
        for params in entries:
            actchecks.append((plugin_name, act_info, params))

    if actchecks:
        cfg.write("\n\n# Active checks\n")
        for acttype, act_info, params in actchecks:
            # Make hostname available as global variable in argument functions
            check_api_utils.set_hostname(hostname)

            has_perfdata = act_info.get('has_perfdata', False)
            description = config.active_check_service_description(
                hostname, acttype, params)

            if do_omit_service(hostname, description):
                continue

            # compute argument, and quote ! and \ for Nagios
            args = core_config.active_check_arguments(
                hostname,
                description, act_info["argument_function"](params)).replace(
                    "\\", "\\\\").replace("!", "\\!")

            if description in used_descriptions:
                cn, it = used_descriptions[description]
                # If we have the same active check again with the same description,
                # then we do not regard this as an error, but simply ignore the
                # second one. That way one can override a check with other settings.
                if cn == "active(%s)" % acttype:
                    continue

                # TODO: Remove "type: ignore" once we are on python3
                core_config.warning(
                    "ERROR: Duplicate service description (active check) '%s' for host '%s'!\n"  # type: ignore[arg-type]
                    " - 1st occurrance: checktype = %s, item = %r\n"
                    " - 2nd occurrance: checktype = active(%s), item = None\n"
                    % (description, hostname, cn, it, acttype))
                continue

            used_descriptions[description] = ("active(" + acttype + ")",
                                              description)

            template = "check_mk_perf," if has_perfdata else ""

            if host_attrs["address"] in ["0.0.0.0", "::"]:
                command_name = "check-mk-custom"
                command = command_name + "!echo \"CRIT - Failed to lookup IP address and no explicit IP address configured\" && exit 2"
                cfg.custom_commands_to_define.add(command_name)
            else:
                command = "check_mk_active-%s!%s" % (acttype, args)

            service_spec = {
                "use": "%scheck_mk_default" % template,
                "host_name": hostname,
                "service_description": description,
                "check_command": _simulate_command(cfg, command),
                "active_checks_enabled": str(1),
            }
            service_spec.update(
                core_config.get_service_attributes(hostname, description,
                                                   config_cache))
            service_spec.update(
                _extra_service_conf_of(cfg, config_cache, hostname,
                                       description))
            cfg.write(_format_nagios_object("service", service_spec))

            # write service dependencies for active checks
            cfg.write(get_dependencies(hostname, description))

    # Legacy checks via custom_checks
    custchecks = host_config.custom_checks
    if custchecks:
        cfg.write("\n\n# Custom checks\n")
        for entry in custchecks:
            # entries are dicts with the following keys:
            # "service_description"        Service description to use
            # "command_line"  (optional)   Unix command line for executing the check
            #                              If this is missing, we create a passive check
            # "command_name"  (optional)   Name of Monitoring command to define. If missing,
            #                              we use "check-mk-custom"
            # "has_perfdata"  (optional)   If present and True, we activate perf_data
            description = config.get_final_service_description(
                hostname, entry["service_description"])
            has_perfdata = entry.get("has_perfdata", False)
            command_name = entry.get("command_name", "check-mk-custom")
            command_line = entry.get("command_line", "")

            if do_omit_service(hostname, description):
                continue

            if command_line:
                command_line = core_config.autodetect_plugin(
                    command_line).replace("\\", "\\\\").replace("!", "\\!")

            if "freshness" in entry:
                freshness = {
                    "check_freshness": 1,
                    "freshness_threshold": 60 * entry["freshness"]["interval"],
                }
                command_line = "echo %s && exit %d" % (_quote_nagios_string(
                    entry["freshness"]["output"]), entry["freshness"]["state"])
            else:
                freshness = {}

            cfg.custom_commands_to_define.add(command_name)

            if description in used_descriptions:
                cn, it = used_descriptions[description]
                # If we have the same active check again with the same description,
                # then we do not regard this as an error, but simply ignore the
                # second one.
                if cn == "custom(%s)" % command_name:
                    continue
                # TODO: Remove "type: ignore" once we are on python3
                core_config.warning(
                    "ERROR: Duplicate service description (custom check) '%s' for host '%s'!\n"  # type: ignore[arg-type]
                    " - 1st occurrance: checktype = %s, item = %r\n"
                    " - 2nd occurrance: checktype = custom(%s), item = %r\n" %
                    (description, hostname, cn, it, command_name, description))
                continue

            used_descriptions[description] = ("custom(%s)" % command_name,
                                              description)

            template = "check_mk_perf," if has_perfdata else ""
            command = "%s!%s" % (command_name, command_line)

            service_spec = {
                "use":
                "%scheck_mk_default" % template,
                "host_name":
                hostname,
                "service_description":
                description,
                "check_command":
                _simulate_command(cfg, command),
                "active_checks_enabled":
                str(1 if (command_line and not freshness) else 0),
            }
            service_spec.update(freshness)
            service_spec.update(
                core_config.get_service_attributes(hostname, description,
                                                   config_cache))
            service_spec.update(
                _extra_service_conf_of(cfg, config_cache, hostname,
                                       description))
            cfg.write(_format_nagios_object("service", service_spec))

            # write service dependencies for custom checks
            cfg.write(get_dependencies(hostname, description))

    service_discovery_name = config_cache.service_discovery_name()

    # Inventory checks - if user has configured them.
    params = host_config.discovery_check_parameters
    if host_config.add_service_discovery_check(params, service_discovery_name):
        service_spec = {
            "use": config.inventory_check_template,
            "host_name": hostname,
            "service_description": service_discovery_name,
        }
        service_spec.update(
            core_config.get_service_attributes(hostname,
                                               service_discovery_name,
                                               config_cache))

        service_spec.update(
            _extra_service_conf_of(cfg, config_cache, hostname,
                                   service_discovery_name))

        service_spec.update({
            "check_interval": params["check_interval"],
            "retry_interval": params["check_interval"],
        })

        cfg.write(_format_nagios_object("service", service_spec))

        if have_at_least_one_service:
            cfg.write(
                _format_nagios_object(
                    "servicedependency", {
                        "use": config.service_dependency_template,
                        "host_name": hostname,
                        "service_description": "Check_MK",
                        "dependent_host_name": hostname,
                        "dependent_service_description":
                        service_discovery_name,
                    }))

    # No check_mk service, no legacy service -> create PING service
    if not have_at_least_one_service and not actchecks and not custchecks:
        _add_ping_service(cfg, config_cache, host_config,
                          host_attrs["address"],
                          host_config.is_ipv6_primary and 6 or 4, "PING",
                          host_attrs.get("_NODEIPS"))

    if host_config.is_ipv4v6_host:
        if host_config.is_ipv6_primary:
            _add_ping_service(cfg, config_cache, host_config,
                              host_attrs["_ADDRESS_4"], 4, "PING IPv4",
                              host_attrs.get("_NODEIPS_4"))
        else:
            _add_ping_service(cfg, config_cache, host_config,
                              host_attrs["_ADDRESS_6"], 6, "PING IPv6",
                              host_attrs.get("_NODEIPS_6"))