예제 #1
0
def check_mk_remote_automation(site_id,
                               command,
                               args,
                               indata,
                               stdin_data=None,
                               timeout=None,
                               sync=True):
    site = config.site(site_id)
    if "secret" not in site:
        raise MKGeneralException(
            _("Cannot connect to site \"%s\": The site is not logged in") %
            site.get("alias", site_id))

    if not site.get("replication"):
        raise MKGeneralException(
            _("Cannot connect to site \"%s\": The replication is disabled") %
            site.get("alias", site_id))

    if sync:
        sync_changes_before_remote_automation(site_id)

    # Now do the actual remote command
    response = do_remote_automation(
        config.site(site_id),
        "checkmk-automation",
        [
            ("automation", command),  # The Check_MK automation command
            ("arguments", mk_repr(args)),  # The arguments for the command
            ("indata", mk_repr(indata)),  # The input data
            ("stdin_data", mk_repr(stdin_data)),  # The input data for stdin
            ("timeout", mk_repr(timeout)),  # The timeout
        ])
    return response
예제 #2
0
 def setup_request_fixture(self, monkeypatch: pytest.MonkeyPatch) -> None:
     monkeypatch.setattr(automation, "_get_login_secret", lambda **_kwargs: "secret")
     request.set_var("secret", "secret")
     request.set_var("command", "checkmk-automation")
     request.set_var("automation", "test")
     request.set_var("arguments", mk_repr(None).decode())
     request.set_var("indata", mk_repr(None).decode())
     request.set_var("stdin_data", mk_repr(None).decode())
     request.set_var("timeout", mk_repr(None).decode())
예제 #3
0
 def rule_url(rule: Rule) -> str:
     return folder_preserving_link([
         ("mode", "edit_rule"),
         ("varname", varname),
         ("rule_folder", rule.folder.path()),
         ("rule_id", rule.id),
         ("host", self._hostname),
         (
             "item",
             mk_repr(svc_desc_or_item).decode()
             if svc_desc_or_item else "",
         ),
         ("service", mk_repr(svc_desc).decode() if svc_desc else ""),
     ])
예제 #4
0
def _legacy_push_user_profile_to_site(site, user_id, profile):
    url = site["multisiteurl"] + "automation.py?" + urlencode_vars([
        ("command", "push-profile"),
        ("secret", site["secret"]),
        ("siteid", site['id']),
        ("debug", config.debug and "1" or ""),
    ])

    response = get_url(url,
                       site.get('insecure', False),
                       data={
                           'user_id': user_id,
                           'profile': mk_repr(profile),
                       },
                       timeout=60)

    if not response:
        raise MKAutomationException(_("Empty output from remote site."))

    try:
        response = mk_eval(response)
    except Exception:
        # The remote site will send non-Python data in case of an error.
        raise MKAutomationException("%s: <pre>%s</pre>" %
                                    (_("Got invalid data"), response))
    return response
예제 #5
0
def check_mk_remote_automation_serialized(
    *,
    site_id: SiteId,
    command: str,
    args: Optional[Sequence[str]],
    indata: Any,
    stdin_data: Optional[str] = None,
    timeout: Optional[int] = None,
    sync: bool = True,
    non_blocking_http: bool = False,
) -> SerializedResult:
    site = get_site_config(site_id)
    if "secret" not in site:
        raise MKGeneralException(
            _('Cannot connect to site "%s": The site is not logged in') %
            site.get("alias", site_id))

    if not site.get("replication"):
        raise MKGeneralException(
            _('Cannot connect to site "%s": The replication is disabled') %
            site.get("alias", site_id))

    if sync:
        sync_changes_before_remote_automation(site_id)

    if non_blocking_http:
        # This will start a background job process on the remote site to execute the automation
        # asynchronously. It then polls the remote site, waiting for completion of the job.
        return _do_check_mk_remote_automation_in_background_job_serialized(
            site_id,
            CheckmkAutomationRequest(command, args, indata, stdin_data,
                                     timeout))

    # Synchronous execution of the actual remote command in a single blocking HTTP request
    return SerializedResult(
        _do_remote_automation_serialized(
            site=get_site_config(site_id),
            command="checkmk-automation",
            vars_=[
                ("automation", command),  # The Checkmk automation command
                ("arguments", mk_repr(args)),  # The arguments for the command
                ("indata", mk_repr(indata)),  # The input data
                ("stdin_data",
                 mk_repr(stdin_data)),  # The input data for stdin
                ("timeout", mk_repr(timeout)),  # The timeout
            ],
        ))
예제 #6
0
def check_mk_remote_automation(site_id,
                               command,
                               args,
                               indata,
                               stdin_data=None,
                               timeout=None,
                               sync=True,
                               non_blocking_http=False):
    # type: (SiteId, str, Optional[Sequence[Union[str, Text]]], Any, Optional[str], Optional[int], bool, bool) -> Any
    site = config.site(site_id)
    if "secret" not in site:
        raise MKGeneralException(
            _("Cannot connect to site \"%s\": The site is not logged in") %
            site.get("alias", site_id))

    if not site.get("replication"):
        raise MKGeneralException(
            _("Cannot connect to site \"%s\": The replication is disabled") %
            site.get("alias", site_id))

    if sync:
        sync_changes_before_remote_automation(site_id)

    if non_blocking_http:
        # This will start a background job process on the remote site to execute the automation
        # asynchronously. It then polls the remote site, waiting for completion of the job.
        return _do_check_mk_remote_automation_in_background_job(
            site_id,
            CheckmkAutomationRequest(command, args, indata, stdin_data,
                                     timeout))

    # Synchronous execution of the actual remote command in a single blocking HTTP request
    return do_remote_automation(
        config.site(site_id),
        "checkmk-automation",
        [
            ("automation", command),  # The Check_MK automation command
            ("arguments", mk_repr(args)),  # The arguments for the command
            ("indata", mk_repr(indata)),  # The input data
            ("stdin_data", mk_repr(stdin_data)),  # The input data for stdin
            ("timeout", mk_repr(timeout)),  # The timeout
        ])
예제 #7
0
 def _execute_push_profile(self):
     try:
         response.set_data(
             str(watolib_utils.mk_repr(self._automation_push_profile())))
     except Exception as e:
         logger.exception("error pushing profile")
         if active_config.debug:
             raise
         response.set_data(
             _("Internal automation error: %s\n%s") %
             (e, traceback.format_exc()))
예제 #8
0
    def _output_analysed_ruleset(self,
                                 all_rulesets,
                                 rulespec,
                                 svc_desc_or_item,
                                 svc_desc,
                                 known_settings=None):
        if known_settings is None:
            known_settings = self._PARAMETERS_UNKNOWN

        def rule_url(rule: Rule) -> str:
            return folder_preserving_link([
                ("mode", "edit_rule"),
                ("varname", varname),
                ("rule_folder", rule.folder.path()),
                ("rule_id", rule.id),
                ("host", self._hostname),
                (
                    "item",
                    mk_repr(svc_desc_or_item).decode()
                    if svc_desc_or_item else "",
                ),
                ("service", mk_repr(svc_desc).decode() if svc_desc else ""),
            ])

        varname = rulespec.name
        valuespec = rulespec.valuespec

        url = folder_preserving_link([
            ("mode", "edit_ruleset"),
            ("varname", varname),
            ("host", self._hostname),
            ("item", mk_repr(svc_desc_or_item).decode()),
            ("service", mk_repr(svc_desc).decode()),
        ])

        forms.section(HTMLWriter.render_a(rulespec.title, url))

        ruleset = all_rulesets.get(varname)
        setting, rules = ruleset.analyse_ruleset(self._hostname,
                                                 svc_desc_or_item, svc_desc)

        html.open_table(class_="setting")
        html.open_tr()
        html.open_td(class_="reason")

        # Show reason for the determined value
        if len(rules) == 1:
            rule_folder, rule_index, rule = rules[0]
            url = rule_url(rule)
            html.a(_("Rule %d in %s") % (rule_index + 1, rule_folder.title()),
                   href=rule_url(rule))

        elif len(rules) > 1:
            html.a("%d %s" % (len(rules), _("Rules")), href=url)

        else:
            html.span(_("Default value"))
        html.close_td()

        # Show the resulting value or factory setting
        html.open_td(
            class_=["settingvalue", "used" if len(rules) > 0 else "unused"])

        if isinstance(known_settings,
                      dict) and "tp_computed_params" in known_settings:
            computed_at = known_settings["tp_computed_params"]["computed_at"]
            html.write_text(
                _("Timespecific parameters computed at %s") %
                cmk.utils.render.date_and_time(computed_at))
            html.br()
            known_settings = known_settings["tp_computed_params"]["params"]

        # In some cases we now the settings from a check_mk automation
        if known_settings is self._PARAMETERS_OMIT:
            return

        # Special handling for logwatch: The check parameter is always None. The actual
        # patterns are configured in logwatch_rules. We do not have access to the actual
        # patterns here but just to the useless "None". In order not to complicate things
        # we simply display nothing here.
        if varname == "logwatch_rules":
            pass

        elif known_settings is not self._PARAMETERS_UNKNOWN:
            try:
                html.write_text(valuespec.value_to_html(known_settings))
            except Exception as e:
                if active_config.debug:
                    raise
                html.write_text(
                    _("Invalid parameter %r: %s") % (known_settings, e))

        else:
            # For match type "dict" it can be the case the rule define some of the keys
            # while other keys are taken from the factory defaults. We need to show the
            # complete outcoming value here.
            if rules and ruleset.match_type() == "dict":
                if (rulespec.factory_default is not Rulespec.NO_FACTORY_DEFAULT
                        and rulespec.factory_default
                        is not Rulespec.FACTORY_DEFAULT_UNUSED):
                    fd = rulespec.factory_default.copy()
                    fd.update(setting)
                    setting = fd

            if valuespec and not rules:  # show the default value
                if rulespec.factory_default is Rulespec.FACTORY_DEFAULT_UNUSED:
                    # Some rulesets are ineffective if they are empty
                    html.write_text(_("(unused)"))

                elif rulespec.factory_default is not Rulespec.NO_FACTORY_DEFAULT:
                    # If there is a factory default then show that one
                    setting = rulespec.factory_default
                    html.write_text(valuespec.value_to_html(setting))

                elif ruleset.match_type() in ("all", "list"):
                    # Rulesets that build lists are empty if no rule matches
                    html.write_text(_("(no entry)"))

                else:
                    # Else we use the default value of the valuespec
                    html.write_text(
                        valuespec.value_to_html(valuespec.default_value()))

            # We have a setting
            elif valuespec:
                if ruleset.match_type() == "all":
                    for s in setting:
                        html.write_text(valuespec.value_to_html(s))
                else:
                    html.write_text(valuespec.value_to_html(setting))

            # Binary rule, no valuespec, outcome is True or False
            else:
                icon_name = "rule_%s%s" % ("yes" if setting else "no",
                                           "_off" if not rules else "")
                html.icon(icon_name, title=_("yes") if setting else _("no"))
        html.close_td()
        html.close_tr()
        html.close_table()
예제 #9
0
    def _show_patterns(self):
        import cmk.gui.logwatch as logwatch

        collection = SingleRulesetRecursively("logwatch_rules")
        collection.load()
        ruleset = collection.get("logwatch_rules")

        html.h3(_("Logfile patterns"))
        if ruleset.is_empty():
            html.open_div(class_="info")
            html.write_text(
                "There are no logfile patterns defined. You may create "
                'logfile patterns using the <a href="%s">Rule Editor</a>.' %
                folder_preserving_link([
                    ("mode", "edit_ruleset"),
                    ("varname", "logwatch_rules"),
                ]))
            html.close_div()

        # Loop all rules for this ruleset
        already_matched = False
        abs_rulenr = 0
        for folder, rulenr, rule in ruleset.get_rules():
            # Check if this rule applies to the given host/service
            if self._hostname:
                service_desc = self._get_service_description(
                    self._hostname, "logwatch", self._item)

                # If hostname (and maybe filename) try match it
                rule_matches = rule.matches_host_and_item(
                    Folder.current(), self._hostname, self._item, service_desc)
            else:
                # If no host/file given match all rules
                rule_matches = True

            with foldable_container(
                    treename="rule",
                    id_=str(abs_rulenr),
                    isopen=True,
                    title=HTML("<b>Rule #%d</b>" % (abs_rulenr + 1)),
                    indent=False,
            ), table_element("pattern_editor_rule_%d" % abs_rulenr,
                             sortable=False,
                             css="logwatch") as table:
                abs_rulenr += 1

                # TODO: What's this?
                pattern_list = rule.value
                if isinstance(pattern_list, dict):
                    pattern_list = pattern_list["reclassify_patterns"]

                # Each rule can hold no, one or several patterns. Loop them all here
                for state, pattern, comment in pattern_list:
                    match_class = ""
                    disp_match_txt = HTML("")
                    match_img = ""
                    if rule_matches:
                        # Applies to the given host/service
                        matched = re.search(pattern, self._match_txt)
                        if matched:

                            # Prepare highlighted search txt
                            match_start = matched.start()
                            match_end = matched.end()
                            disp_match_txt = (
                                escape_to_html(self._match_txt[:match_start]) +
                                HTMLWriter.render_span(
                                    self._match_txt[match_start:match_end],
                                    class_="match") +
                                escape_to_html(self._match_txt[match_end:]))

                            if not already_matched:
                                # First match
                                match_class = "match first"
                                match_img = "match"
                                match_title = _(
                                    "This logfile pattern matches first and will be used for "
                                    "defining the state of the given line.")
                                already_matched = True
                            else:
                                # subsequent match
                                match_class = "match"
                                match_img = "imatch"
                                match_title = _(
                                    "This logfile pattern matches but another matched first."
                                )
                        else:
                            match_img = "nmatch"
                            match_title = _(
                                "This logfile pattern does not match the given string."
                            )
                    else:
                        # rule does not match
                        match_img = "nmatch"
                        match_title = _("The rule conditions do not match.")

                    table.row()
                    table.cell(_("Match"))
                    html.icon("rule%s" % match_img, match_title)

                    cls = ([
                        "state%d" %
                        logwatch.level_state(state), "fillbackground"
                    ] if match_class == "match first" else [])

                    table.cell(_("State"),
                               HTMLWriter.render_span(
                                   logwatch.level_name(state)),
                               css=cls)
                    table.cell(_("Pattern"), HTMLWriter.render_tt(pattern))
                    table.cell(_("Comment"), comment)
                    table.cell(_("Matched line"), disp_match_txt)

                table.row(fixed=True)
                table.cell(colspan=5)
                edit_url = folder_preserving_link([
                    ("mode", "edit_rule"),
                    ("varname", "logwatch_rules"),
                    ("rulenr", rulenr),
                    ("item", mk_repr(self._item).decode()),
                    ("rule_folder", folder.path()),
                    ("rule_id", rule.id),
                ])
                html.icon_button(edit_url, _("Edit this rule"), "edit")