def test_discovered_service_labels_repr():
    labels = DiscoveredServiceLabels()
    labels.add_label(ServiceLabel(u"äbc", u"123"))
    labels.add_label(ServiceLabel(u"ccc", u"ddd"))
    assert repr(
        labels
    ) == "DiscoveredServiceLabels(ServiceLabel('ccc', 'ddd'), ServiceLabel('äbc', '123'))"
Exemple #2
0
def test_ruleset_matcher_get_service_ruleset_values_labels(monkeypatch, hostname,
                                                           service_description, expected_result):
    ts = Scenario()

    ts.add_host("host1")
    ts.set_autochecks("host1", [
        Service("cpu.load",
                None,
                "CPU load",
                "{}",
                service_labels=DiscoveredServiceLabels(
                    ServiceLabel(u"os", u"linux"),
                    ServiceLabel(u"abc", u"xä"),
                    ServiceLabel(u"hu", u"ha"),
                ))
    ])

    ts.add_host("host2")
    ts.set_autochecks("host2", [
        Service("cpu.load", None, "CPU load", "{}", service_labels=DiscoveredServiceLabels()),
    ])

    config_cache = ts.apply(monkeypatch)
    matcher = config_cache.ruleset_matcher

    assert list(
        matcher.get_service_ruleset_values(config_cache.ruleset_match_object_of_service(
            hostname, service_description),
                                           ruleset=service_label_ruleset,
                                           is_binary=False)) == expected_result
Exemple #3
0
    def discovered_labels_of(self, hostname, service_desc):
        # type: (HostName, ServiceName) -> DiscoveredServiceLabels
        # Check if the autochecks for the given hostname were already read
        # The service in question might have no entry in the autochecks file
        # In this scenario it gets an empty DiscoveredServiceLabels entry
        host_results = self._discovered_labels_of.get(hostname)
        if host_results is not None:
            service_result = host_results.get(service_desc)
            if service_result is None:
                host_results[service_desc] = DiscoveredServiceLabels()
            return host_results[service_desc]

        # Only read the raw autochecks here. Do not compute the effective check parameters,
        # because that would invole ruleset matching which in would require the labels to
        # be already computed.
        # The following function reads the autochecks and populates the the discovered labels cache
        self._read_raw_autochecks_cached(hostname)
        result = self._discovered_labels_of.get(hostname, {}).get(service_desc)
        if result is None:
            # The service was not present in the autochecks, create an empty instance
            result = DiscoveredServiceLabels()
            self._discovered_labels_of.setdefault(hostname,
                                                  {})[service_desc] = result

        return result
Exemple #4
0
    def _read_raw_autochecks_uncached(
        self,
        hostname: HostName,
    ) -> Sequence[_AutocheckService]:
        """Read automatically discovered checks of one host"""
        path = _autochecks_path_for(hostname)
        try:
            autochecks_raw = _load_raw_autochecks(
                path=path,
                check_variables=None,
            )
        except SyntaxError as e:
            logger.exception("Syntax error in file %s: %s", path, e)
            if cmk.utils.debug.enabled():
                raise
            return []
        except Exception as e:
            logger.exception("Error in file %s:\n%s", path, e)
            if cmk.utils.debug.enabled():
                raise
            return []

        services = []
        for entry in autochecks_raw:
            try:
                item = entry["item"]
            except TypeError:  # pre 1.6 tuple!
                raise MKGeneralException(
                    "Invalid check entry '%r' of host '%s' (%s) found. This "
                    "entry is in pre Checkmk 1.6 format and needs to be converted. This is "
                    'normally done by "cmk-update-config -v" during "omd update". Please '
                    'execute "cmk-update-config -v" for convertig the old configuration.'
                    % (entry, hostname, path))

            try:
                plugin_name = CheckPluginName(
                    maincheckify(entry["check_plugin_name"]))
                assert item is None or isinstance(item, str)
            except Exception:
                raise MKGeneralException(
                    "Invalid check entry '%r' of host '%s' (%s) found. This "
                    "entry is in pre Checkmk 2.0 format and needs to be converted. This is "
                    'normally done by "cmk-update-config -v" during "omd update". Please '
                    'execute "cmk-update-config -v" for convertig the old configuration.'
                    % (entry, hostname, path))

            labels = DiscoveredServiceLabels()
            for label_id, label_value in entry["service_labels"].items():
                labels.add_label(ServiceLabel(label_id, label_value))

            services.append(
                _AutocheckService(
                    check_plugin_name=plugin_name,
                    item=item,
                    discovered_parameters=entry["parameters"],
                    service_labels=labels,
                ))

        return services
Exemple #5
0
def _parse_discovered_service_label_from_ast(ast_service_labels):
    # type: (ast.Dict) -> DiscoveredServiceLabels
    labels = DiscoveredServiceLabels()
    if not hasattr(ast_service_labels, "keys"):
        return labels
    for key, value in zip(ast_service_labels.keys, ast_service_labels.values):
        if key is not None:
            # mypy does not get the types of the ast objects here
            labels.add_label(ServiceLabel(
                key.s, value.s))  # type: ignore[attr-defined]
    return labels
Exemple #6
0
def _parse_discovered_service_label_from_dict(dict_service_labels: Dict) -> DiscoveredServiceLabels:
    labels = DiscoveredServiceLabels()
    if not isinstance(dict_service_labels, dict):
        return labels
    for key, value in dict_service_labels.items():
        if key is not None:
            labels.add_label(ServiceLabel(
                ensure_str(key),
                ensure_str(value),
            ))
    return labels
Exemple #7
0
def test_discovered_service_labels_to_dict():
    labels = DiscoveredServiceLabels()
    assert labels.to_dict() == {}

    labels["äbc"] = "123"
    labels["xyz"] = "blä"

    assert labels.to_dict() == {
        "äbc": "123",
        "xyz": "blä",
    }
Exemple #8
0
def test_ruleset_matcher_get_service_ruleset_values_labels(
    monkeypatch: MonkeyPatch,
    hostname: HostName,
    service_description: str,
    expected_result: Sequence[str],
) -> None:
    ts = Scenario()

    ts.add_host(HostName("host1"))
    ts.set_autochecks(
        HostName("host1"),
        [
            Service(
                CheckPluginName("cpu_load"),
                None,
                "CPU load",
                "{}",
                service_labels=DiscoveredServiceLabels(
                    ServiceLabel("os", "linux"),
                    ServiceLabel("abc", "xä"),
                    ServiceLabel("hu", "ha"),
                ),
            )
        ],
    )

    ts.add_host(HostName("host2"))
    ts.set_autochecks(
        HostName("host2"),
        [
            Service(
                CheckPluginName("cpu_load"),
                None,
                "CPU load",
                "{}",
                service_labels=DiscoveredServiceLabels(),
            ),
        ],
    )

    config_cache = ts.apply(monkeypatch)
    matcher = config_cache.ruleset_matcher

    assert (list(
        matcher.get_service_ruleset_values(
            config_cache.ruleset_match_object_of_service(
                hostname, ServiceName(service_description)),
            ruleset=service_label_ruleset,
            is_binary=False,
        )) == expected_result)
Exemple #9
0
 def __init__(self, check_plugin_name, item, description, parameters, service_labels=None):
     # type: (CheckPluginName, Item, Text, CheckParameters, DiscoveredServiceLabels) -> None
     self._check_plugin_name = check_plugin_name
     self._item = item
     self._description = description
     self._parameters = parameters
     self._service_labels = service_labels or DiscoveredServiceLabels()
Exemple #10
0
 def __init__(
         self,
         item: Item,
         parameters: LegacyCheckParameters = None,
         service_labels: Optional[DiscoveredServiceLabels] = None) -> None:
     self.item = item
     self.parameters = parameters
     self.service_labels = service_labels or DiscoveredServiceLabels()
Exemple #11
0
 def __init__(self,
              item: Item,
              parameters: LegacyCheckParameters = None,
              service_labels: DiscoveredServiceLabels = None,
              host_labels: DiscoveredHostLabels = None) -> None:
     self.item = item
     self.parameters = parameters
     self.service_labels = service_labels or DiscoveredServiceLabels()
     self.host_labels = host_labels or DiscoveredHostLabels()
Exemple #12
0
 def __init__(self,
              item,
              parameters=None,
              service_labels=None,
              host_labels=None):
     # type: (Item, CheckParameters, DiscoveredServiceLabels, DiscoveredHostLabels) -> None
     self.item = item
     self.parameters = parameters
     self.service_labels = service_labels or DiscoveredServiceLabels()
     self.host_labels = host_labels or DiscoveredHostLabels()
 def discovered_labels_of(self, hostname, service_desc, service_description,
                          get_check_variables):
     # type: (HostName, ServiceName, GetServiceDescription, GetCheckVariables) -> DiscoveredServiceLabels
     if hostname not in self._discovered_labels_of:
         # Only read the raw autochecks here, do not compute the effective
         # check parameters. The latter would involve ruleset matching which
         # in turn would require already computed labels.
         self._read_raw_autochecks(hostname, service_description, get_check_variables)
     if service_desc not in self._discovered_labels_of[hostname]:
         self._discovered_labels_of[hostname][service_desc] = DiscoveredServiceLabels()
     return self._discovered_labels_of[hostname][service_desc]
Exemple #14
0
 def __init__(
     self,
     check_plugin_name: CheckPluginName,
     item: Item,
     description: str,
     parameters: LegacyCheckParameters,
     service_labels: Optional[DiscoveredServiceLabels] = None,
 ) -> None:
     self._check_plugin_name = check_plugin_name
     self._item = item
     self._description = description
     self._service_labels = service_labels or DiscoveredServiceLabels()
     self._parameters = parameters
Exemple #15
0
 def __init__(
     self,
     check_plugin_name: CheckPluginName,
     item: Item,
     description: str,
     parameters: LegacyCheckParameters,
     service_labels: Optional[DiscoveredServiceLabels] = None,
 ) -> None:
     self.check_plugin_name: Final = check_plugin_name
     self.item: Final = item
     self.description: Final = description
     self.service_labels: Final = service_labels or DiscoveredServiceLabels()
     self.parameters: Final = parameters
Exemple #16
0
def test_discovered_service_init():
    ser = discovery.Service(CheckPluginName("abc"), u"Item", u"ABC Item", None)
    assert ser.check_plugin_name == CheckPluginName("abc")
    assert ser.item == u"Item"
    assert ser.description == u"ABC Item"
    assert ser.parameters is None
    assert ser.service_labels.to_dict() == {}

    ser = discovery.Service(CheckPluginName("abc"), u"Item", u"ABC Item", None,
                            DiscoveredServiceLabels(ServiceLabel(u"läbel", u"lübel")))
    assert ser.service_labels.to_dict() == {u"läbel": u"lübel"}

    with pytest.raises(AttributeError):
        ser.xyz = "abc"  # type: ignore[attr-defined] # pylint: disable=assigning-non-slot
Exemple #17
0
def _enriched_discovered_services(
    host_name: HostName,
    check_plugin_name: CheckPluginName,
    plugins_services: checking_classes.DiscoveryResult,
) -> Generator[Service, None, None]:
    for service in plugins_services:
        description = config.service_description(host_name, check_plugin_name, service.item)
        # make sanity check
        if not description:
            console.error(
                f"{host_name}: {check_plugin_name} returned empty service description - ignoring it.\n"
            )
            continue

        yield Service(
            check_plugin_name=check_plugin_name,
            item=service.item,
            description=description,
            parameters=unwrap_parameters(service.parameters),
            # Convert from APIs ServiceLabel to internal ServiceLabel
            service_labels=DiscoveredServiceLabels(*(ServiceLabel(*l) for l in service.labels)),
        )
Exemple #18
0
    def _read_raw_autochecks_uncached(
        self,
        hostname: HostName,
        service_description: GetServiceDescription,
    ) -> List[Service]:
        """Read automatically discovered checks of one host"""
        path = _autochecks_path_for(hostname)
        try:
            autochecks_raw = _load_raw_autochecks(
                path=path,
                check_variables=None,
            )
        except SyntaxError as e:
            console.verbose("Syntax error in file %s: %s\n",
                            path,
                            e,
                            stream=sys.stderr)
            if cmk.utils.debug.enabled():
                raise
            return []
        except Exception as e:
            console.verbose("Error in file %s:\n%s\n",
                            path,
                            e,
                            stream=sys.stderr)
            if cmk.utils.debug.enabled():
                raise
            return []

        services: List[Service] = []
        for entry in autochecks_raw:
            try:
                item = entry["item"]
            except TypeError:  # pre 1.6 tuple!
                raise MKGeneralException(
                    "Invalid check entry '%r' of host '%s' (%s) found. This "
                    "entry is in pre Checkmk 1.6 format and needs to be converted. This is "
                    "normally done by \"cmk-update-config -v\" during \"omd update\". Please "
                    "execute \"cmk-update-config -v\" for convertig the old configuration."
                    % (entry, hostname, path))

            try:
                plugin_name = CheckPluginName(
                    maincheckify(entry["check_plugin_name"]))
                assert item is None or isinstance(item, str)
            except Exception:
                raise MKGeneralException(
                    "Invalid check entry '%r' of host '%s' (%s) found. This "
                    "entry is in pre Checkmk 1.7 format and needs to be converted. This is "
                    "normally done by \"cmk-update-config -v\" during \"omd update\". Please "
                    "execute \"cmk-update-config -v\" for convertig the old configuration."
                    % (entry, hostname, path))

            labels = DiscoveredServiceLabels()
            for label_id, label_value in entry["service_labels"].items():
                labels.add_label(ServiceLabel(label_id, label_value))

            try:
                description = service_description(hostname, plugin_name, item)
            except Exception:
                continue  # ignore

            services.append(
                Service(
                    check_plugin_name=plugin_name,
                    item=item,
                    description=description,
                    parameters=entry["parameters"],
                    service_labels=labels,
                ))

        return services
Exemple #19
0
    def _read_raw_autochecks_uncached(
        self,
        hostname: HostName,
        service_description: GetServiceDescription,
    ) -> List[Service]:
        """Read automatically discovered checks of one host"""
        path = _autochecks_path_for(hostname)
        try:
            autochecks_raw = _load_raw_autochecks(
                path=path,
                check_variables=None,
            )
        except SyntaxError as e:
            console.verbose("Syntax error in file %s: %s\n",
                            path,
                            e,
                            stream=sys.stderr)
            if cmk.utils.debug.enabled():
                raise
            return []
        except Exception as e:
            console.verbose("Error in file %s:\n%s\n",
                            path,
                            e,
                            stream=sys.stderr)
            if cmk.utils.debug.enabled():
                raise
            return []

        services: List[Service] = []
        for entry in autochecks_raw:
            if isinstance(entry, tuple):
                raise MKGeneralException(
                    "Invalid check entry '%r' of host '%s' (%s) found. This "
                    "entry is in pre Checkmk 1.6 format and needs to be converted. This is "
                    "normally done by \"cmk-update-config -v\" during \"omd update\". Please "
                    "execute \"cmk-update-config -v\" for convertig the old configuration."
                    % (entry, hostname, path))

            labels = DiscoveredServiceLabels()
            for label_id, label_value in entry["service_labels"].items():
                labels.add_label(ServiceLabel(label_id, label_value))

            # With Check_MK 1.2.7i3 items are now defined to be unicode strings. Convert
            # items from existing autocheck files for compatibility. TODO remove this one day
            item = entry["item"]

            if not isinstance(entry["check_plugin_name"], str):
                raise MKGeneralException(
                    "Invalid entry '%r' in check table of host '%s': "
                    "The check type must be a string." % (entry, hostname))

            check_plugin_name_str = str(entry["check_plugin_name"])
            # TODO (mo): centralize maincheckify: CMK-4295
            check_plugin_name = CheckPluginName(
                maincheckify(check_plugin_name_str))
            try:
                description = service_description(hostname, check_plugin_name,
                                                  item)
            except Exception:
                continue  # ignore

            services.append(
                Service(
                    check_plugin_name=check_plugin_name_str,
                    item=item,
                    description=description,
                    parameters=entry["parameters"],
                    service_labels=labels,
                ))

        return services
Exemple #20
0

def test_remove_autochecks_file():
    assert autochecks.has_autochecks("host") is False
    autochecks.save_autochecks_file("host", [])
    assert autochecks.has_autochecks("host") is True
    autochecks.remove_autochecks_file("host")
    assert autochecks.has_autochecks("host") is False


@pytest.mark.parametrize("items,expected_content", [
    ([], "[\n]\n"),
    ([
        discovery.DiscoveredService(
            'df', u'/xyz', u"Filesystem /xyz", "None",
            DiscoveredServiceLabels(ServiceLabel(u"x", u"y"))),
        discovery.DiscoveredService(
            'df', u'/', u"Filesystem /", "{}",
            DiscoveredServiceLabels(ServiceLabel(u"x", u"y"))),
        discovery.DiscoveredService(
            'cpu.loads', None, "CPU load", "cpuload_default_levels",
            DiscoveredServiceLabels(ServiceLabel(u"x", u"y"))),
    ], """[
  {'check_plugin_name': 'cpu.loads', 'item': None, 'parameters': cpuload_default_levels, 'service_labels': {u'x': u'y'}},
  {'check_plugin_name': 'df', 'item': u'/', 'parameters': {}, 'service_labels': {u'x': u'y'}},
  {'check_plugin_name': 'df', 'item': u'/xyz', 'parameters': None, 'service_labels': {u'x': u'y'}},
]\n"""),
])
def test_save_autochecks_file(items, expected_content):
    autochecks.save_autochecks_file("host", items)
Exemple #21
0
    autochecks.remove_autochecks_file(HostName("host"))
    assert autochecks.has_autochecks(HostName("host")) is False


@pytest.mark.parametrize(
    "items,expected_content",
    [
        ([], "[\n]\n"),
        (
            [
                discovery.Service(
                    CheckPluginName("df"),
                    "/xyz",
                    "Filesystem /xyz",
                    None,
                    DiscoveredServiceLabels(ServiceLabel("x", "y")),
                ),
                discovery.Service(
                    CheckPluginName("df"),
                    "/",
                    "Filesystem /",
                    {},
                    DiscoveredServiceLabels(ServiceLabel("x", "y")),
                ),
                discovery.Service(
                    CheckPluginName("cpu_loads"),
                    None,
                    "CPU load",
                    {},
                    DiscoveredServiceLabels(ServiceLabel("x", "y")),
                ),
Exemple #22
0
class AutochecksManager:
    """Read autochecks from the configuration

    Autochecks of a host are once read and cached for the whole lifetime of the
    AutochecksManager."""
    def __init__(self) -> None:
        super().__init__()
        self._autochecks: Dict[HostName, List[Service]] = {}
        # Extract of the autochecks: This cache is populated either on the way while
        # processing get_autochecks_of() or when directly calling discovered_labels_of().
        self._discovered_labels_of: Dict[HostName,
                                         Dict[ServiceName,
                                              DiscoveredServiceLabels]] = {}
        self._raw_autochecks_cache: Dict[HostName,
                                         Sequence[_AutocheckService]] = {}

    def get_autochecks_of(
        self,
        hostname: HostName,
        compute_check_parameters: ComputeCheckParameters,
        get_service_description: GetServiceDescription,
        get_effective_hostname: HostOfClusteredService,
    ) -> List[Service]:
        if hostname not in self._autochecks:
            self._autochecks[hostname] = list(
                self._get_autochecks_of_uncached(
                    hostname,
                    compute_check_parameters,
                    get_service_description,
                    get_effective_hostname,
                ))
        return self._autochecks[hostname]

    def _get_autochecks_of_uncached(
        self,
        hostname: HostName,
        compute_check_parameters: ComputeCheckParameters,
        get_service_description: GetServiceDescription,
        get_effective_hostname: HostOfClusteredService,
    ) -> Iterable[Service]:
        """Read automatically discovered checks of one host"""
        for autocheck_service in self._read_raw_autochecks(hostname):
            try:
                service_name = get_service_description(
                    hostname, autocheck_service.check_plugin_name,
                    autocheck_service.item)
            except Exception:  # I dont't really know why this is ignored. Feels utterly wrong.
                continue

            yield Service(
                check_plugin_name=autocheck_service.check_plugin_name,
                item=autocheck_service.item,
                description=service_name,
                parameters=compute_check_parameters(
                    get_effective_hostname(hostname, service_name),
                    autocheck_service.check_plugin_name,
                    autocheck_service.item,
                    autocheck_service.discovered_parameters,
                ),
                service_labels=autocheck_service.service_labels,
            )

    def discovered_labels_of(
        self,
        hostname: HostName,
        service_desc: ServiceName,
        get_service_description: GetServiceDescription,
    ) -> DiscoveredServiceLabels:
        # NOTE: this returns an empty labels object for non-existing services
        with suppress(KeyError):
            return self._discovered_labels_of[hostname][service_desc]

        hosts_labels = self._discovered_labels_of.setdefault(hostname, {})
        # Only read the raw autochecks here, do not compute the effective
        # check parameters. The latter would involve ruleset matching which
        # in turn would require already computed labels.
        for autocheck_service in self._read_raw_autochecks(hostname):
            try:
                hosts_labels[get_service_description(
                    hostname, autocheck_service.check_plugin_name,
                    autocheck_service.item)] = autocheck_service.service_labels
            except Exception:
                continue  # ignore

        if (labels := hosts_labels.get(service_desc)) is not None:
            return labels
        return DiscoveredServiceLabels()
Exemple #23
0
def labels(request):
    if request.param == "host":
        return DiscoveredHostLabels()
    return DiscoveredServiceLabels()
Exemple #24
0
    def _read_raw_autochecks_of(self, hostname):
        # type: (HostName) -> List[Service]
        """Read automatically discovered checks of one host"""
        basedir = cmk.utils.paths.autochecks_dir
        filepath = basedir + '/' + hostname + '.mk'

        result = []  # type: List[Service]
        if not os.path.exists(filepath):
            return result

        check_config = config.get_check_variables()
        try:
            cmk.base.console.vverbose("Loading autochecks from %s\n", filepath)
            autochecks_raw = eval(
                open(filepath).read().decode("utf-8"), check_config,
                check_config)  # type: List[Dict]
        except SyntaxError as e:
            cmk.base.console.verbose("Syntax error in file %s: %s\n",
                                     filepath,
                                     e,
                                     stream=sys.stderr)
            if cmk.utils.debug.enabled():
                raise
            return result
        except Exception as e:
            cmk.base.console.verbose("Error in file %s:\n%s\n", filepath, e, stream=sys.stderr)
            if cmk.utils.debug.enabled():
                raise
            return result

        for entry in autochecks_raw:
            if isinstance(entry, tuple):
                raise MKGeneralException(
                    "Invalid check entry '%r' of host '%s' (%s) found. This "
                    "entry is in pre Checkmk 1.6 format and needs to be converted. This is "
                    "normally done by \"cmk-update-config -v\" during \"omd update\". Please "
                    "execute \"cmk-update-config -v\" for convertig the old configuration." %
                    (entry, hostname, filepath))

            labels = DiscoveredServiceLabels()
            for label_id, label_value in entry["service_labels"].items():
                labels.add_label(ServiceLabel(label_id, label_value))

            # With Check_MK 1.2.7i3 items are now defined to be unicode strings. Convert
            # items from existing autocheck files for compatibility. TODO remove this one day
            item = entry["item"]
            if isinstance(item, str):
                item = convert_to_unicode(item)

            if not isinstance(entry["check_plugin_name"], six.string_types):
                raise MKGeneralException("Invalid entry '%r' in check table of host '%s': "
                                         "The check type must be a string." % (entry, hostname))

            check_plugin_name = str(entry["check_plugin_name"])

            try:
                description = config.service_description(hostname, check_plugin_name, item)
            except Exception:
                continue  # ignore

            result.append(
                Service(
                    check_plugin_name=check_plugin_name,
                    item=item,
                    description=description,
                    parameters=entry["parameters"],
                    service_labels=labels,
                ))

        return result