예제 #1
0
def _parse_autocheck_entry(hostname, entry):
    # type: (str, Union[ast.Tuple, ast.Dict]) -> Optional[DiscoveredService]
    if isinstance(entry, ast.Tuple):
        ast_check_plugin_name, ast_item, ast_parameters_unresolved = _parse_pre_16_tuple_autocheck_entry(
            entry)
        ast_service_labels = ast.Dict()
    elif isinstance(entry, ast.Dict):
        ast_check_plugin_name, ast_item, ast_parameters_unresolved, ast_service_labels = \
            _parse_dict_autocheck_entry(entry)
    else:
        raise Exception("Invalid autocheck: Wrong type: %r" % entry)

    if not isinstance(ast_check_plugin_name, ast.Str):
        raise Exception("Invalid autocheck: Wrong check plugin type: %r" %
                        ast_check_plugin_name)
    check_plugin_name = ast_check_plugin_name.s

    item = None  # type: Item
    if isinstance(ast_item, ast.Str):
        item = ast_item.s
    elif isinstance(ast_item, ast.Num):
        item = int(ast_item.n)
    elif isinstance(ast_item, ast.Name) and ast_item.id == "None":
        item = None
    else:
        raise Exception("Invalid autocheck: Wrong item type: %r" % ast_item)

    # With Check_MK 1.2.7i3 items are now defined to be unicode
    # strings. Convert items from existing autocheck files for
    # compatibility.
    if isinstance(item, str):
        item = config.decode_incoming_string(item)

    if isinstance(ast_parameters_unresolved, ast.Name):
        # Keep check variable names as they are: No evaluation of check parameters
        parameters_unresolved = ast_parameters_unresolved.id
    else:
        # Other structures, like dicts, lists and so on should also be loaded as repr() str
        # instead of an interpreted structure
        parameters_unresolved = repr(
            eval(
                compile(ast.Expression(ast_parameters_unresolved),
                        filename="<ast>",
                        mode="eval")))

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

    return DiscoveredService(
        check_plugin_name,
        item,
        description,
        parameters_unresolved,
        service_labels=_parse_discovered_service_label_from_ast(
            ast_service_labels))
예제 #2
0
def _parse_autocheck_entry(hostname, entry):
    # type: (str, Union[ast.Tuple, ast.Dict]) -> Optional[DiscoveredService]
    if isinstance(entry, ast.Tuple):
        ast_check_plugin_name, ast_item, ast_parameters_unresolved = _parse_pre_16_tuple_autocheck_entry(
            entry)
        ast_service_labels = ast.Dict()
    elif isinstance(entry, ast.Dict):
        ast_check_plugin_name, ast_item, ast_parameters_unresolved, ast_service_labels = \
            _parse_dict_autocheck_entry(entry)
    else:
        raise Exception("Invalid autocheck: Wrong type: %r" % entry)

    if not isinstance(ast_check_plugin_name, ast.Str):
        raise Exception("Invalid autocheck: Wrong check plugin type: %r" %
                        ast_check_plugin_name)
    check_plugin_name = ast_check_plugin_name.s

    item = None  # type: Item
    if isinstance(ast_item, ast.Str):
        item = ast_item.s
    elif isinstance(ast_item, ast.Num):
        item = int(ast_item.n)
    elif isinstance(ast_item, ast.Name) and ast_item.id == "None":
        item = None
    else:
        raise Exception("Invalid autocheck: Wrong item type: %r" % ast_item)

    # With Check_MK 1.2.7i3 items are now defined to be unicode
    # strings. Convert items from existing autocheck files for
    # compatibility.
    if isinstance(item, str):
        item = config.decode_incoming_string(item)

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

    return DiscoveredService(
        check_plugin_name,
        item,
        description,
        _parse_unresolved_parameters_from_ast(ast_parameters_unresolved),
        service_labels=_parse_discovered_service_label_from_ast(
            ast_service_labels))
예제 #3
0
    def _read_raw_autochecks_of(self, hostname):
        # type: (str) -> 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(
                file(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:
            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 = config.decode_incoming_string(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))

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

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

        return result
예제 #4
0
    def _parse_info(self, lines):
        """Split agent output in chunks, splits lines by whitespaces.

        Returns a HostSections() object.
        """
        sections = {}
        # Unparsed info for other hosts. A dictionary, indexed by the piggybacked host name.
        # The value is a list of lines which were received for this host.
        piggybacked_raw_data = {}
        persisted_sections = {}  # handle sections with option persist(...)
        host = None
        section_content = []
        section_options = {}
        agent_cache_info = {}
        separator = None
        encoding = None
        for line in lines:
            line = line.rstrip("\r")
            stripped_line = line.strip()
            if stripped_line[:4] == '<<<<' and stripped_line[-4:] == '>>>>':
                host = stripped_line[4:-4]
                if not host:
                    host = None
                else:
                    host = config.translate_piggyback_host(
                        self._hostname, host)
                    if host == self._hostname:
                        host = None  # unpiggybacked "normal" host

                    # Protect Check_MK against unallowed host names. Normally source scripts
                    # like agent plugins should care about cleaning their provided host names
                    # up, but we need to be sure here to prevent bugs in Check_MK code.
                    # a) Replace spaces by underscores
                    if host:
                        host = host.replace(" ", "_")

            elif host:  # processing data for an other host
                piggybacked_raw_data.setdefault(host, []).append(line)

            # Found normal section header
            # section header has format <<<name:opt1(args):opt2:opt3(args)>>>
            elif stripped_line[:3] == '<<<' and stripped_line[-3:] == '>>>':
                section_header = stripped_line[3:-3]
                headerparts = section_header.split(":")
                section_name = headerparts[0]
                section_options = {}
                for o in headerparts[1:]:
                    opt_parts = o.split("(")
                    opt_name = opt_parts[0]
                    if len(opt_parts) > 1:
                        opt_args = opt_parts[1][:-1]
                    else:
                        opt_args = None
                    section_options[opt_name] = opt_args

                section_content = sections.get(section_name, None)
                if section_content is None:  # section appears in output for the first time
                    section_content = []
                    sections[section_name] = section_content
                try:
                    separator = chr(int(section_options["sep"]))
                except Exception:
                    separator = None

                # Split of persisted section for server-side caching
                if "persist" in section_options:
                    until = int(section_options["persist"])
                    cached_at = int(time.time())  # Estimate age of the data
                    cache_interval = int(until - cached_at)
                    agent_cache_info[section_name] = (cached_at,
                                                      cache_interval)
                    persisted_sections[section_name] = (cached_at, until,
                                                        section_content)

                if "cached" in section_options:
                    agent_cache_info[section_name] = tuple(
                        map(int, section_options["cached"].split(",")))

                # The section data might have a different encoding
                encoding = section_options.get("encoding")

            elif stripped_line != '':
                if "nostrip" not in section_options:
                    line = stripped_line

                if encoding:
                    line = config.decode_incoming_string(line, encoding)
                else:
                    line = config.decode_incoming_string(line)

                section_content.append(line.split(separator))

        return HostSections(sections, agent_cache_info, piggybacked_raw_data,
                            persisted_sections)
예제 #5
0
    def _parse_info(self, lines):
        """Split agent output in chunks, splits lines by whitespaces.

        Returns a HostSections() object.
        """
        sections = {}
        # Unparsed info for other hosts. A dictionary, indexed by the piggybacked host name.
        # The value is a list of lines which were received for this host.
        piggybacked_raw_data = {}
        piggybacked_hostname = None
        piggybacked_cached_at = int(time.time())
        # Transform to seconds and give the piggybacked host a little bit more time
        piggybacked_cache_age = int(1.5 * 60 *
                                    self._host_config.check_mk_check_interval)

        persisted_sections = {}  # handle sections with option persist(...)
        section_content = []
        section_options = {}
        agent_cache_info = {}
        separator = None
        encoding = None
        for line in lines:
            line = line.rstrip("\r")
            stripped_line = line.strip()
            if stripped_line[:4] == '<<<<' and stripped_line[-4:] == '>>>>':
                piggybacked_hostname =\
                    self._get_sanitized_and_translated_piggybacked_hostname(stripped_line)

            elif piggybacked_hostname:  # processing data for an other host
                if stripped_line[:3] == '<<<' and stripped_line[-3:] == '>>>':
                    line = self._add_cached_info_to_piggybacked_section_header(
                        stripped_line, piggybacked_cached_at,
                        piggybacked_cache_age)
                piggybacked_raw_data.setdefault(piggybacked_hostname,
                                                []).append(line)

            # Found normal section header
            # section header has format <<<name:opt1(args):opt2:opt3(args)>>>
            elif stripped_line[:3] == '<<<' and stripped_line[-3:] == '>>>':
                section_header = stripped_line[3:-3]
                headerparts = section_header.split(":")
                section_name = headerparts[0]
                section_options = {}
                for o in headerparts[1:]:
                    opt_parts = o.split("(")
                    opt_name = opt_parts[0]
                    if len(opt_parts) > 1:
                        opt_args = opt_parts[1][:-1]
                    else:
                        opt_args = None
                    section_options[opt_name] = opt_args

                section_content = sections.get(section_name, None)
                if section_content is None:  # section appears in output for the first time
                    section_content = []
                    sections[section_name] = section_content
                try:
                    separator = chr(int(section_options["sep"]))
                except Exception:
                    separator = None

                # Split of persisted section for server-side caching
                if "persist" in section_options:
                    until = int(section_options["persist"])
                    cached_at = int(time.time())  # Estimate age of the data
                    cache_interval = int(until - cached_at)
                    agent_cache_info[section_name] = (cached_at,
                                                      cache_interval)
                    persisted_sections[section_name] = (cached_at, until,
                                                        section_content)

                if "cached" in section_options:
                    agent_cache_info[section_name] = tuple(
                        map(int, section_options["cached"].split(",")))

                # The section data might have a different encoding
                encoding = section_options.get("encoding")

            elif stripped_line != '':
                if "nostrip" not in section_options:
                    line = stripped_line

                if encoding:
                    line = config.decode_incoming_string(line, encoding)
                else:
                    line = config.decode_incoming_string(line)

                section_content.append(line.split(separator))

        return HostSections(sections, agent_cache_info, piggybacked_raw_data,
                            persisted_sections)