コード例 #1
0
    def page(self) -> AjaxPageResult:
        settings = json.loads(request.get_str_input_mandatory("settings"))

        try:
            dashlet_type = cast(Type[ABCFigureDashlet],
                                dashlet_registry[settings.get("type")])
        except KeyError:
            raise MKUserError("type",
                              _("The requested element type does not exist."))

        settings = dashlet_vs_general_settings(
            dashlet_type,
            dashlet_type.single_infos()).value_from_json(settings)

        raw_properties = request.get_str_input_mandatory("properties")
        properties = dashlet_type.vs_parameters().value_from_json(
            json.loads(raw_properties))
        context = json.loads(request.get_str_input_mandatory("context", "{}"))
        # Inject the infos because the datagenerator is a separate instance to dashlet
        # TODO: Can we do better than using fake arguments below? We *really* need an instance,
        # because in general, infos() is an *instance* method, not a class method.
        settings["infos"] = dashlet_type(dashboard_name="",
                                         dashboard={
                                             "context": {}
                                         },
                                         dashlet_id=0,
                                         dashlet={
                                             "context": {}
                                         }).infos()
        response_data = dashlet_type.generate_response_data(
            properties, context, settings)
        return create_figures_response(response_data)
コード例 #2
0
ファイル: weblib.py プロジェクト: LinuxHaus/checkmk
def ajax_tree_openclose() -> None:
    tree = request.get_str_input_mandatory("tree")
    name = request.get_str_input_mandatory("name")

    user.set_tree_state(tree, name, request.get_str_input("state"))
    user.save_tree_states()
    response.set_data("OK")  # Write out something to make debugging easier
コード例 #3
0
ファイル: weblib.py プロジェクト: LinuxHaus/checkmk
def ajax_set_rowselection() -> None:
    ident = request.get_str_input_mandatory("id")
    action = request.get_str_input_mandatory("action", "set")
    if action not in ["add", "del", "set", "unset"]:
        raise MKUserError(None, _("Invalid action"))

    rows = request.get_str_input_mandatory("rows", "").split(",")
    user.set_rowselection(selection_id(), ident, rows, action)
コード例 #4
0
def recover_pre_2_1_range_filter_request_vars(
        query: query_filters.NumberRangeQuery):
    """Some range filters used the _to suffix instead of the standard _until.

    Do inverse translation to search for this request vars."""
    request_var_match = ((var, re.sub("_until(_|$)", "_to\\1", var))
                         for var in query.request_vars)
    return {
        current_var: (request.get_str_input_mandatory(current_var, "")
                      or request.get_str_input_mandatory(old_var, ""))
        for current_var, old_var in request_var_match
    }
コード例 #5
0
ファイル: metrics.py プロジェクト: LinuxHaus/checkmk
def page_graph_dashlet() -> None:
    spec = request.var("spec")
    if not spec:
        raise MKUserError("spec", _("Missing spec parameter"))
    graph_identification = json.loads(request.get_str_input_mandatory("spec"))

    render = request.var("render")
    if not render:
        raise MKUserError("render", _("Missing render parameter"))
    custom_graph_render_options = json.loads(
        request.get_str_input_mandatory("render"))

    host_service_graph_dashlet_cmk(graph_identification,
                                   custom_graph_render_options)
コード例 #6
0
ファイル: webservice.py プロジェクト: LinuxHaus/checkmk
    def show(self, view: "View", rows: Rows) -> None:
        csv_separator = request.get_str_input_mandatory("csv_separator", ";")
        first = True
        resp = []
        for cell in view.group_cells + view.row_cells:
            if first:
                first = False
            else:
                resp.append(csv_separator)
            title = cell.export_title()
            resp.append('"%s"' % self._format_for_csv(title))

        for row in rows:
            resp.append("\n")
            first = True
            for cell in view.group_cells + view.row_cells:
                if first:
                    first = False
                else:
                    resp.append(csv_separator)
                joined_row = join_row(row, cell)
                content = cell.render_for_export(joined_row)
                resp.append('"%s"' % self._format_for_csv(content))

        response.set_data("".join(resp))
コード例 #7
0
    def page(self) -> PageResult:
        """Determines the hosts to be shown"""
        user.need_permission("general.parent_child_topology")

        topology_settings = TopologySettings()
        if request.var("filled_in"):
            # Parameters from the check_mk filters
            self._update_topology_settings_with_context(topology_settings)
        elif request.var("host_name"):
            # Explicit host_name. Used by icon linking to Topology
            topology_settings.growth_root_nodes = {
                HostName(html.request.get_str_input_mandatory("host_name"))
            }
        else:
            # Default page without further context
            topology_settings.growth_root_nodes = self._get_default_view_hostnames(
                topology_settings.growth_auto_max_nodes
            )

        if request.has_var("topology_settings"):
            # These parameters are usually generated within javascript through user interactions
            try:
                settings_from_var = json.loads(request.get_str_input_mandatory("topology_settings"))
                for key, value in settings_from_var.items():
                    setattr(topology_settings, key, value)
            except (TypeError, ValueError):
                raise MKGeneralException(_("Invalid topology_settings %r") % topology_settings)

        self.show_topology(topology_settings)
コード例 #8
0
 def value(self) -> FilterHTTPVariables:
     """Returns the current representation of the filter settings from the HTML
     var context. This can be used to persist the filter settings."""
     return {
         varname: request.get_str_input_mandatory(varname, "")
         for varname in self.htmlvars
     }
コード例 #9
0
 def page(self) -> AjaxPageResult:
     check_csrf_token()
     layout_var = request.get_str_input_mandatory("layout", "{}")
     layout_config = json.loads(layout_var)
     active_config.bi_layouts["templates"].update(layout_config)
     BILayoutManagement.save_layouts()
     return {}
コード例 #10
0
 def _ajax_tag_tree_enter(self):
     response.set_content_type("application/json")
     self._load()
     path = request.get_str_input_mandatory("path").split(
         "|") if request.var("path") else []
     self._cwds[self._current_tree_id] = path
     self._save_user_settings()
     response.set_data("OK")
コード例 #11
0
ファイル: pattern_editor.py プロジェクト: LinuxHaus/checkmk
    def _from_vars(self):
        self._hostname = self._vs_host().from_html_vars("host")
        self._vs_host().validate_value(self._hostname, "host")

        # TODO: validate all fields
        self._item = request.get_str_input_mandatory("file", "")
        self._match_txt = request.get_str_input_mandatory("match", "")

        self._host = Folder.current().host(self._hostname)

        if self._hostname and not self._host:
            raise MKUserError(None, _("This host does not exist."))

        if self._item and not self._hostname:
            raise MKUserError(
                None,
                _("You need to specify a host name to test file matching."))
コード例 #12
0
def _get_api_call() -> APICallDefinitionDict:
    action = request.get_str_input_mandatory("action")
    for cls in api_call_collection_registry.values():
        api_call = cls().get_api_calls().get(action)
        if api_call:
            return api_call
    raise MKUserError(
        None, "Unknown API action %s" % escaping.escape_attribute(action))
コード例 #13
0
def page_api() -> None:
    try:
        if not request.has_var("output_format"):
            response.set_content_type("application/json")
            output_format = "json"
        else:
            output_format = request.get_ascii_input_mandatory(
                "output_format", "json").lower()

        if output_format not in _FORMATTERS:
            response.set_content_type("text/plain")
            raise MKUserError(
                None,
                "Only %s are supported as output formats" %
                " and ".join('"%s"' % f for f in _FORMATTERS),
            )

        # TODO: Add some kind of helper for boolean-valued variables?
        pretty_print = False
        pretty_print_var = request.get_str_input_mandatory(
            "pretty_print", "no").lower()
        if pretty_print_var not in ("yes", "no"):
            raise MKUserError(None, 'pretty_print must be "yes" or "no"')
        pretty_print = pretty_print_var == "yes"

        api_call = _get_api_call()
        _check_permissions(api_call)
        request_object = _get_request(api_call)
        _check_formats(output_format, api_call, request_object)
        _check_request_keys(api_call, request_object)
        resp = _execute_action(api_call, request_object)

    except MKAuthException as e:
        resp = {
            "result_code":
            1,
            "result":
            _("Authorization Error. Insufficent permissions for '%s'") % e,
        }
    except MKException as e:
        resp = {
            "result_code":
            1,
            "result":
            _("Checkmk exception: %s\n%s") %
            (e, "".join(traceback.format_exc())),
        }
    except Exception:
        if active_config.debug:
            raise
        logger.exception("error handling web API call")
        resp = {
            "result_code": 1,
            "result": _("Unhandled exception: %s") % traceback.format_exc(),
        }

    response.set_data(
        _FORMATTERS[output_format][1 if pretty_print else 0](resp))
コード例 #14
0
ファイル: view.py プロジェクト: LinuxHaus/checkmk
    def infos(self) -> SingleInfos:
        # Hack for create mode of dashlet editor. The user first selects a datasource and then the
        # single contexts, the dashlet editor needs to use these information.
        if requested_file_name(request) == "edit_dashlet" and request.has_var(
                "datasource"):
            ds_name = request.get_str_input_mandatory("datasource")
            return list(data_source_registry[ds_name]().infos)  # TODO: Hmmm...

        return self._get_infos_from_view_spec(self._dashlet_spec)
コード例 #15
0
def robotmk_report_page() -> cmk.gui.pages.PageResult:
    """Renders the content of the RobotMK html log file"""
    site_id, host_name, service_description = _get_mandatory_request_vars()
    report_type: str = request.get_str_input_mandatory("report_type")

    content = _get_html_from_livestatus(report_type, site_id, host_name,
                                        service_description)

    html_content = _get_cleaned_html_content(content[0].decode("utf-8"))
    html.write_html(html_content)
コード例 #16
0
ファイル: automation.py プロジェクト: LinuxHaus/checkmk
 def page(self):
     # To prevent mixups in written files we use the same lock here as for
     # the normal WATO page processing. This might not be needed for some
     # special automation requests, like inventory e.g., but to keep it simple,
     # we request the lock in all cases.
     lock_config = not (self._command == "checkmk-automation"
                        and request.get_str_input_mandatory("automation")
                        == "active-check")
     with store.lock_checkmk_configuration(
     ) if lock_config else nullcontext():
         self._execute_automation()
コード例 #17
0
ファイル: mega_menu.py プロジェクト: LinuxHaus/checkmk
 def page(self) -> AjaxPageResult:
     try:
         check_csrf_token()
         name = request.get_str_input_mandatory("name")
         url = makeuri_contextless(request, [("name", name)],
                                   "dashboard.py")
         validate_start_url(url, "")
         _set_user_attribute("start_url", repr(url))
     except Exception:
         raise MKUserError(None, _("Failed to set start URL"))
     return {}
コード例 #18
0
def ajax_save_treestate():
    path_id = request.get_str_input_mandatory("path")
    current_ex_level_str, path = path_id.split(":", 1)
    current_ex_level = int(current_ex_level_str)

    if user.bi_expansion_level != current_ex_level:
        user.set_tree_states("bi", {})
    user.set_tree_state("bi", path, request.var("state") == "open")
    user.save_tree_states()

    user.bi_expansion_level = current_ex_level
コード例 #19
0
ファイル: __init__.py プロジェクト: LinuxHaus/checkmk
def ajax_snapin():
    """Renders and returns the contents of the requested sidebar snapin(s) in JSON format"""
    response.set_content_type("application/json")
    user_config = UserSidebarConfig(user, active_config.sidebar)

    snapin_id = request.var("name")
    snapin_ids = ([snapin_id] if snapin_id else
                  request.get_str_input_mandatory("names", "").split(","))

    snapin_code: List[str] = []
    for snapin_id in snapin_ids:
        try:
            snapin_instance = user_config.get_snapin(snapin_id).snapin_type()
        except KeyError:
            continue  # Skip not existing snapins

        if not snapin_instance.may_see():
            continue

        # When restart snapins are about to be refreshed, only render
        # them, when the core has been restarted after their initial
        # rendering
        if not snapin_instance.refresh_regularly(
        ) and snapin_instance.refresh_on_restart():
            since = request.get_float_input_mandatory("since", 0)
            newest = since
            for site in sites.states().values():
                prog_start = site.get("program_start", 0)
                if prog_start > newest:
                    newest = prog_start
            if newest <= since:
                # no restart
                snapin_code.append("")
                continue

        with output_funnel.plugged():
            try:
                snapin_instance.show()
            except Exception as e:
                write_snapin_exception(e)
                e_message = (
                    _("Exception during element refresh (element '%s')") %
                    snapin_instance.type_name())
                logger.error("%s %s: %s", request.requested_url, e_message,
                             traceback.format_exc())
            finally:
                snapin_code.append(output_funnel.drain())

    response.set_data(json.dumps(snapin_code))
コード例 #20
0
ファイル: automation.py プロジェクト: LinuxHaus/checkmk
 def _execute_cmk_automation(self):
     cmk_command = request.get_str_input_mandatory("automation")
     args = watolib_utils.mk_eval(
         request.get_str_input_mandatory("arguments"))
     indata = watolib_utils.mk_eval(
         request.get_str_input_mandatory("indata"))
     stdin_data = watolib_utils.mk_eval(
         request.get_str_input_mandatory("stdin_data"))
     timeout = watolib_utils.mk_eval(
         request.get_str_input_mandatory("timeout"))
     cmdline_cmd, serialized_result = check_mk_local_automation_serialized(
         command=cmk_command,
         args=args,
         indata=indata,
         stdin_data=stdin_data,
         timeout=timeout,
     )
     # Don't use write_text() here (not needed, because no HTML document is rendered)
     response.set_data(
         self._format_cmk_automation_result(
             serialized_result=SerializedResult(serialized_result),
             cmk_command=cmk_command,
             cmdline_cmd=cmdline_cmd,
         ))
コード例 #21
0
ファイル: weblib.py プロジェクト: LinuxHaus/checkmk
def selection_id() -> str:
    """Generates a selection id or uses the given one"""
    if not request.has_var("selection"):
        sel_id = utils.gen_id()
        request.set_var("selection", sel_id)
        return sel_id

    sel_id = request.get_str_input_mandatory("selection")

    # Avoid illegal file access by introducing .. or /
    if not re.match("^[-0-9a-zA-Z]+$", sel_id):
        new_id = utils.gen_id()
        request.set_var("selection", new_id)
        return new_id
    return sel_id
コード例 #22
0
ファイル: groups.py プロジェクト: LinuxHaus/checkmk
    def action(self) -> ActionResult:
        if not transactions.check_transaction():
            return redirect(mode_url("%s_groups" % self.type_name))

        alias = request.get_str_input_mandatory("alias").strip()
        self.group = {"alias": alias}

        self._determine_additional_group_data()

        if self._new:
            self._name = request.get_ascii_input_mandatory("name").strip()
            groups.add_group(self._name, self.type_name, self.group)
        else:
            assert self._name is not None
            groups.edit_group(self._name, self.type_name, self.group)

        return redirect(mode_url("%s_groups" % self.type_name))
コード例 #23
0
    def _evaluate_user_opts(self) -> Tuple[TableRows, bool, Optional[str]]:
        assert self.id is not None
        table_id = self.id
        rows = self.rows

        search_term = None
        actions_enabled = self.options["searchable"] or self.options["sortable"]

        if not actions_enabled:
            return rows, False, None

        table_opts = user.tableoptions.setdefault(table_id, {})

        # Handle the initial visibility of the actions
        actions_visible = table_opts.get("actions_visible", False)
        if request.get_ascii_input("_%s_actions" % table_id):
            actions_visible = request.get_ascii_input("_%s_actions" %
                                                      table_id) == "1"
            table_opts["actions_visible"] = actions_visible

        if self.options["searchable"]:
            search_term = request.get_str_input_mandatory("search", "")
            # Search is always lower case -> case insensitive
            search_term = search_term.lower()
            if search_term:
                request.set_var("search", search_term)
                rows = _filter_rows(rows, search_term)

        if request.get_ascii_input("_%s_reset_sorting" % table_id):
            request.del_var("_%s_sort" % table_id)
            if "sort" in table_opts:
                del table_opts["sort"]  # persist

        if self.options["sortable"]:
            # Now apply eventual sorting settings
            sort = self._get_sort_column(table_opts)
            if sort is not None:
                request.set_var("_%s_sort" % table_id, sort)
                table_opts["sort"] = sort  # persist
                sort_col, sort_reverse = map(int, sort.split(",", 1))
                rows = _sort_rows(rows, sort_col, sort_reverse)

        if actions_enabled:
            user.save_tableoptions()

        return rows, actions_visible, search_term
コード例 #24
0
def ajax_render_tree():
    aggr_group = request.get_str_input("group")
    aggr_title = request.get_str_input("title")
    omit_root = bool(request.var("omit_root"))
    only_problems = bool(request.var("only_problems"))

    rows = []
    bi_manager = BIManager()
    bi_manager.status_fetcher.set_assumed_states(user.bi_assumptions)
    aggregation_id = request.get_str_input_mandatory("aggregation_id")
    bi_aggregation_filter = BIAggregationFilter(
        [],
        [],
        [aggregation_id],
        [aggr_title] if aggr_title is not None else [],
        [aggr_group] if aggr_group is not None else [],
        [],
    )
    rows = bi_manager.computer.compute_legacy_result_for_filter(
        bi_aggregation_filter)

    # TODO: Cleanup the renderer to use a class registry for lookup
    renderer_class_name = request.var("renderer")
    if renderer_class_name == "FoldableTreeRendererTree":
        renderer_cls: Type[ABCFoldableTreeRenderer] = FoldableTreeRendererTree
    elif renderer_class_name == "FoldableTreeRendererBoxes":
        renderer_cls = FoldableTreeRendererBoxes
    elif renderer_class_name == "FoldableTreeRendererBottomUp":
        renderer_cls = FoldableTreeRendererBottomUp
    elif renderer_class_name == "FoldableTreeRendererTopDown":
        renderer_cls = FoldableTreeRendererTopDown
    else:
        raise NotImplementedError()

    renderer = renderer_cls(
        rows[0],
        omit_root=omit_root,
        expansion_level=user.bi_expansion_level,
        only_problems=only_problems,
        lazy=False,
    )
    html.write_html(renderer.render())
コード例 #25
0
def robotmk_download_page() -> cmk.gui.pages.PageResult:
    user.need_permission("general.see_crash_reports")

    site_id, host_name, service_description = _get_mandatory_request_vars()
    report_type: str = request.get_str_input_mandatory("report_type")

    filename = "Robot_Framework_log_%s_%s_%s_%s.tar.gz" % (
        urlencode(site_id),
        urlencode(host_name),
        urlencode(service_description),
        time.strftime("%Y-%m-%d_%H-%M-%S"),
    )

    response.headers[
        "Content-Disposition"] = "Attachment; filename=%s" % filename
    response.headers["Content-Type"] = "application/x-tar"
    html_content: bytes = _get_html_from_livestatus(report_type, site_id,
                                                    host_name,
                                                    service_description)[0]
    response.set_data(_pack_html_content(report_type, html_content))
コード例 #26
0
    def _from_vars(self):
        self._start = bool(request.var("_start"))
        # 'all' not set -> only scan checked hosts in current folder, no recursion
        # otherwise: all host in this folder, maybe recursively
        self._all = bool(request.var("all"))
        self._complete_folder = self._all

        # Ignored during initial form display
        self._settings = ParentScanSettings(
            where=request.get_ascii_input_mandatory("where", "subfolder"),
            alias=request.get_str_input_mandatory("alias", "").strip(),
            recurse=html.get_checkbox("recurse") or False,
            select=request.get_ascii_input_mandatory("select", "noexplicit"),
            timeout=request.get_integer_input_mandatory("timeout", 8),
            probes=request.get_integer_input_mandatory("probes", 2),
            max_ttl=request.get_integer_input_mandatory("max_ttl", 10),
            force_explicit=html.get_checkbox("force_explicit") or False,
            ping_probes=request.get_integer_input_mandatory("ping_probes", 5),
        )
        self._job = ParentScanBackgroundJob()
コード例 #27
0
 def _report_type(self) -> str:
     return request.get_str_input_mandatory("report_type")
コード例 #28
0
def _get_mandatory_request_vars() -> Tuple[SiteId, HostName, str]:
    site_id: SiteId = SiteId(request.get_str_input_mandatory("site"))
    host_name: HostName = request.get_str_input_mandatory("host")
    service_description: str = request.get_str_input_mandatory("service")

    return site_id, host_name, service_description
コード例 #29
0
    def action(self) -> ActionResult:
        if html.form_submitted("search"):
            return None

        alias = request.get_str_input_mandatory("alias")

        unique, info = groups.is_alias_used("roles", self._role_id, alias)
        if not unique:
            assert info is not None
            raise MKUserError("alias", info)

        new_id = request.get_ascii_input_mandatory("id")
        if not new_id:
            raise MKUserError("id", "You have to provide a ID.")
        if not re.match("^[-a-z0-9A-Z_]*$", new_id):
            raise MKUserError(
                "id", _("Invalid role ID. Only the characters a-z, A-Z, 0-9, _ and - are allowed.")
            )
        if new_id != self._role_id:
            if new_id in self._roles:
                raise MKUserError("id", _("The ID is already used by another role"))

        self._role["alias"] = alias

        # based on
        if not self._role.get("builtin"):
            basedon = request.get_ascii_input_mandatory("basedon")
            if basedon not in builtin_role_ids:
                raise MKUserError(
                    "basedon", _("Invalid valid for based on. Must be id of builtin rule.")
                )
            self._role["basedon"] = basedon

        # Permissions
        permissions = self._role["permissions"]
        for var_name, value in request.itervars(prefix="perm_"):
            try:
                perm = permission_registry[var_name[5:]]
            except KeyError:
                continue

            if value == "yes":
                permissions[perm.name] = True
            elif value == "no":
                permissions[perm.name] = False
            elif value == "default":
                try:
                    del permissions[perm.name]
                except KeyError:
                    pass  # Already at defaults

        if self._role_id != new_id:
            self._roles[new_id] = self._role
            del self._roles[self._role_id]
            self._rename_user_role(self._role_id, new_id)

        self._save_roles()
        _changes.add_change(
            "edit-roles", _("Modified user role '%s'") % new_id, sites=get_login_sites()
        )
        return redirect(mode_url("roles"))
コード例 #30
0
    def _end(self) -> None:
        if not self.rows and self.options["omit_if_empty"]:
            return

        if self.options["output_format"] == "csv":
            self._write_csv(csv_separator=request.get_str_input_mandatory(
                "csv_separator", ";"))
            return

        container: ContextManager[bool] = nullcontext(False)
        if self.title:
            if self.options["foldable"] in [
                    Foldable.FOLDABLE_SAVE_STATE,
                    Foldable.FOLDABLE_STATELESS,
            ]:
                html.open_div(class_="foldable_wrapper")
                container = foldable_container(
                    treename="table",
                    id_=self.id,
                    isopen=self.isopen,
                    indent=False,
                    title=HTMLWriter.render_h3(self.title,
                                               class_=["treeangle", "title"]),
                    save_state=self.options["foldable"] ==
                    Foldable.FOLDABLE_SAVE_STATE,
                )
            else:
                html.h3(self.title, class_="table")

        with container:
            if self.help:
                html.help(self.help)

            if not self.rows:
                html.div(self.empty_text, class_="info")
                return

            # Controls whether or not actions are available for a table
            rows, actions_visible, search_term = self._evaluate_user_opts()

            # Apply limit after search / sorting etc.
            num_rows_unlimited = len(rows)
            limit = self.limit
            if limit:
                # only use rows up to the limit plus the fixed rows
                limited_rows = []
                for index in range(num_rows_unlimited):
                    row = rows[index]
                    if index < limit or isinstance(row,
                                                   GroupHeader) or row.fixed:
                        limited_rows.append(row)
                # Display corrected number of rows
                num_rows_unlimited -= len([
                    r for r in limited_rows
                    if isinstance(row, GroupHeader) or r.fixed
                ])
                rows = limited_rows

            # Render header
            if self.limit_hint is not None:
                num_rows_unlimited = self.limit_hint

            if limit and num_rows_unlimited > limit:

                html.show_message(
                    _("This table is limited to show only %d of %d rows. "
                      'Click <a href="%s">here</a> to disable the limitation.')
                    % (limit, num_rows_unlimited,
                       makeuri(request, [("limit", "none")])))

            self._write_table(rows, num_rows_unlimited,
                              self._show_action_row(), actions_visible,
                              search_term)

        if self.title and self.options["foldable"] in [
                Foldable.FOLDABLE_SAVE_STATE,
                Foldable.FOLDABLE_STATELESS,
        ]:
            html.close_div()

        return