Ejemplo n.º 1
0
def host_service_graph_popup_cmk(site, host_name, service_description):
    graph_render_options = {
        "size": (30, 10),
        "font_size": 6.0,  # pt
        "resizable": False,
        "show_controls": False,
        "show_legend": False,
        "interaction": False,
        "show_time_range_previews": False,
    }

    end_time = time.time()
    start_time = end_time - 8 * 3600
    graph_data_range = {
        "time_range": (start_time, end_time),
    }

    graph_identification = ("template", {
        "site": site,
        "host_name": host_name,
        "service_description": service_description,
    })

    html.write_html(
        render_graphs_from_specification_html(graph_identification,
                                              graph_data_range,
                                              graph_render_options,
                                              render_async=False))
Ejemplo n.º 2
0
    def _show_tree(self):
        td_style = None if self._wrap_texts == "wrap" else "white-space: nowrap;"

        tree = self._get_tree()
        depth = status_tree_depth(tree)
        leaves = self._gen_table(tree, depth, len(self._row["aggr_hosts"]) > 1)

        html.open_table(class_=["aggrtree", "ltr"])
        odd = "odd"
        for code, colspan, parents in leaves:
            html.open_tr()

            leaf_td = html.render_td(code, class_=["leaf", odd], style=td_style, colspan=colspan)
            odd = "even" if odd == "odd" else "odd"

            tds = [leaf_td]
            for rowspan, c in parents:
                tds.append(html.render_td(c, class_=["node"], style=td_style, rowspan=rowspan))

            if self._mirror:
                tds.reverse()

            html.write_html(HTML("").join(tds))
            html.close_tr()

        html.close_table()
Ejemplo n.º 3
0
    def _show_popup(self, entry: PageMenuEntry) -> None:
        assert isinstance(entry.item, PageMenuPopup)

        if entry.name is None:
            raise ValueError("Missing \"name\" attribute on entry \"%s\"" % entry.title)

        classes: List[Optional[str]] = ["page_menu_popup"]
        classes += entry.item.css_classes
        if isinstance(entry.item, PageMenuSidePopup):
            classes.append("side_popup")

        popup_id = "popup_%s" % entry.name
        html.open_div(id_=popup_id, class_=classes)

        html.open_div(class_="head")
        html.h3(entry.title)
        html.a(html.render_icon("close"),
               class_="close_popup",
               href="javascript:void(0)",
               onclick="cmk.page_menu.close_popup(this)")
        html.close_div()

        if (isinstance(entry.item, PageMenuSidePopup) and entry.item.content and
                "side_popup_content" not in entry.item.content):
            raise RuntimeError(
                "Add a div container with the class \"side_popup_content\" to the popup content")

        html.open_div(class_="content")
        html.write_html(entry.item.content)
        html.close_div()
        html.close_div()

        if isinstance(entry.item, PageMenuSidePopup):
            html.final_javascript("cmk.page_menu.side_popup_add_simplebar_scrollbar(%s);" %
                                  json.dumps(popup_id))
Ejemplo n.º 4
0
def _show_output_box(title, content):
    html.h3(title, class_="table")
    html.open_div(class_="log_output")
    html.write_html(
        HTML(escaping.escape_attribute(content).replace("\n", "<br>").replace(" ", "&nbsp;"))
    )
    html.close_div()
Ejemplo n.º 5
0
    def _render_tag_tree_level(self, tree_spec, path, cwd, title,
                               tree) -> None:
        if not self._is_tag_subdir(
                path=path, cwd=cwd) and not self._is_tag_subdir(path=cwd,
                                                                cwd=path):
            return

        container: ContextManager[bool] = nullcontext(False)
        if path != cwd and self._is_tag_subdir(path, cwd):
            bullet = self._tag_tree_bullet(self._tag_tree_worst_state(tree),
                                           path, False)
            if self._tag_tree_has_svc_problems(tree):
                bullet += html.render_icon_button(
                    self._tag_tree_url(tree_spec, path, "svcproblems"),
                    _("Show the service problems contained in this branch"),
                    "svc_problems",
                    target="main",
                )

            if path:
                container = foldable_container(
                    treename="tag-tree",
                    id_=".".join(map(str, path)),
                    isopen=False,
                    title=bullet + title,
                    icon="foldable_sidebar",
                )

        with container:
            for (node_title, node_value), subtree in sorted(
                    tree.get("_children", {}).items()):
                subpath = path + [node_value or ""]
                url = self._tag_tree_url(tree_spec, subpath, "allhosts")

                if "_num_hosts" in subtree:
                    node_title += " (%d)" % subtree["_num_hosts"]

                node_title = html.render_a(node_title, href=url, target="main")

                if "_children" not in subtree:
                    if self._is_tag_subdir(path, cwd):
                        html.write_html(
                            self._tag_tree_bullet(subtree.get("_state", 0),
                                                  subpath, True))
                        if subtree.get("_svc_problems"):
                            url = self._tag_tree_url(tree_spec, subpath,
                                                     "svcproblems")
                            html.icon_button(
                                url,
                                _("Show the service problems contained in this branch"
                                  ),
                                "svc_problems",
                                target="main",
                            )
                        html.write_html(node_title)
                        html.br()
                else:
                    self._render_tag_tree_level(tree_spec, subpath, cwd,
                                                node_title, subtree)
Ejemplo n.º 6
0
def _show_graph_html_content(graph_artwork, graph_data_range,
                             graph_render_options) -> None:
    """Render the HTML code of a graph without its container

    That is a canvas object for drawing the actual graph and also legend, buttons, resize handle,
    etc.
    """
    graph_render_options = artwork.add_default_render_options(
        graph_render_options)

    html.open_div(
        class_=[
            "graph", "preview" if graph_render_options["preview"] else None
        ],
        style="font-size: %.1fpt;%s" %
        (graph_render_options["font_size"],
         _graph_padding_styles(graph_render_options)),
    )

    if graph_render_options["show_controls"]:
        _show_graph_add_to_icon_for_popup(graph_artwork, graph_data_range,
                                          graph_render_options)

    v_axis_label = graph_artwork["vertical_axis"]["axis_label"]
    if v_axis_label:
        html.div(v_axis_label, class_="v_axis_label")

    # Add the floating elements
    if graph_render_options[
            "show_graph_time"] and not graph_render_options["preview"]:
        html.div(
            graph_artwork["time_axis"]["title"] or "",
            css=[
                "time", "inline"
                if graph_render_options["show_title"] == "inline" else None
            ],
        )

    if graph_render_options["show_controls"] and graph_render_options[
            "resizable"]:
        html.img(src=theme.url("images/resize_graph.png"), class_="resize")

    _show_html_graph_title(graph_artwork, graph_render_options)
    _show_graph_canvas(graph_render_options)

    # Note: due to "omit_zero_metrics" the graph might not have any curves
    if _graph_legend_enabled(graph_render_options, graph_artwork):
        _show_graph_legend(graph_artwork, graph_render_options)

    model_params_repr = graph_artwork["definition"].get("model_params_repr")
    model_params_display = (graph_artwork["definition"].get(
        "model_params", {}).get("display_model_parametrization"))
    if model_params_repr and model_params_display:
        html.open_div(align="center")
        html.h2(_("Forecast Parametrization"))
        html.write_html(model_params_repr)
        html.close_div()

    html.close_div()
Ejemplo n.º 7
0
    def page(self):
        is_configured = self._varname in self._current_settings
        is_configured_globally = self._varname in self._global_settings

        default_values = watolib.ABCConfigDomain.get_all_default_globals()

        defvalue = default_values[self._varname]
        value = self._current_settings.get(
            self._varname, self._global_settings.get(self._varname, defvalue))

        html.begin_form("value_editor", method="POST")
        forms.header(self._valuespec.title())
        if not config.wato_hide_varnames:
            forms.section(_("Configuration variable:"))
            html.tt(self._varname)

        forms.section(_("Current setting"))
        self._valuespec.render_input("ve", value)
        self._valuespec.set_focus("ve")
        html.help(self._valuespec.help())

        if is_configured_globally:
            self._show_global_setting()

        forms.section(_("Factory setting"))
        html.write_html(self._valuespec.value_to_text(defvalue))

        forms.section(_("Current state"))
        if is_configured_globally:
            html.write_text(
                _("This variable is configured in <a href=\"%s\">global settings</a>."
                  ) %
                ("wato.py?mode=edit_configvar&varname=%s" % self._varname))
        elif not is_configured:
            html.write_text(_("This variable is at factory settings."))
        else:
            curvalue = self._current_settings[self._varname]
            if is_configured_globally and curvalue == self._global_settings[
                    self._varname]:
                html.write_text(
                    _("Site setting and global setting are identical."))
            elif curvalue == defvalue:
                html.write_text(
                    _("Your setting and factory settings are identical."))
            else:
                html.write(self._valuespec.value_to_text(curvalue))

        forms.end()
        html.button("save", _("Save"))
        if self._config_variable.allow_reset() and is_configured:
            curvalue = self._current_settings[self._varname]
            html.button(
                "_reset",
                _("Remove explicit setting")
                if curvalue == defvalue else _("Reset to default"))
        html.hidden_fields()
        html.end_form()
Ejemplo n.º 8
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)
Ejemplo n.º 9
0
 def _show_row_cells(self, table, name, group):
     super(ModeContactgroups, self)._show_row_cells(table, name, group)
     table.cell(_("Members"))
     html.write_html(
         HTML(", ").join([
             html.render_a(alias,
                           href=watolib.folder_preserving_link([("mode", "edit_user"),
                                                                ("edit", userid)]))
             for userid, alias in self._members.get(name, [])
         ]))
Ejemplo n.º 10
0
def _show_output_box(title: str, content: bytes) -> None:
    html.h3(title, class_="table")
    html.open_div(class_="log_output")
    html.write_html(
        HTML(
            escaping.escape_attribute(content.decode(errors="surrogateescape"))
            .replace("\n", "<br>")
            .replace(" ", "&nbsp;")
        )
    )
    html.close_div()
Ejemplo n.º 11
0
 def _show_row_cells(self, table: Table, name: GroupName,
                     group: GroupSpec) -> None:
     super()._show_row_cells(table, name, group)
     table.cell(_("Members"))
     html.write_html(
         HTML(", ").join([
             html.render_a(
                 alias,
                 href=watolib.folder_preserving_link([("mode", "edit_user"),
                                                      ("edit", userid)]),
             ) for userid, alias in self._members.get(name, [])
         ]))
Ejemplo n.º 12
0
    def _show_subtree(self, tree, path, show_host):
        if self._is_leaf(tree):
            self._show_leaf(tree, show_host)
            return

        html.open_span(class_="title")

        is_empty = len(tree[3]) == 0
        if is_empty:
            mc = None
        else:
            mc = self._get_mousecode(path)

        css_class = "open" if self._is_open(path) else "closed"

        with self._show_node(tree,
                             show_host,
                             mousecode=mc,
                             img_class=css_class):
            if tree[2].get("icon"):
                html.write_html(html.render_icon(tree[2]["icon"]))
                html.write_text("&nbsp;")

            if tree[2].get("docu_url"):
                html.icon_button(
                    tree[2]["docu_url"],
                    _("Context information about this rule"),
                    "url",
                    target="_blank",
                )
                html.write_text("&nbsp;")

            html.write_text(tree[2]["title"])

        if not is_empty:
            html.open_ul(
                id_="%d:%s" %
                (self._expansion_level or 0, self._path_id(path)),
                class_=["subtree", css_class],
            )

            if not self._omit_content(path):
                for node in tree[3]:
                    if not node[2].get("hidden"):
                        new_path = path + [node[2]["title"]]
                        html.open_li()
                        self._show_subtree(node, new_path, show_host)
                        html.close_li()

            html.close_ul()

        html.close_span()
Ejemplo n.º 13
0
def jqm_page_index_topic_renderer(topic: str, items: Items) -> None:
    has_items_for_topic = any(i for i in items if i[0] == topic)
    if not has_items_for_topic:
        return

    html.p(topic)
    html.open_ul(**{"data-role": "listview", "data-inset": "true"})
    for top, href, title in items:
        if top == topic:
            html.open_li()
            html.open_a(href=href, **{"data-ajax": "false", "data-transition": "flip"})
            html.write_html(HTML(title))
            html.close_a()
            html.close_li()
    html.close_ul()
Ejemplo n.º 14
0
 def display(self, value: FilterHTTPVariables) -> None:
     actual_value = value.get(self._filter_range_config.column,
                              self._filter_range_config.default)
     html.add_form_var(self._filter_range_config.column)
     html.write_html(
         HTML(f"""
         <input
             id={self._filter_range_config.column}
             name={self._filter_range_config.column}
             style="pointer-events: all; width: 80%%;"
             oninput="{self._update_label()}" type="range"
             step="{self._filter_range_config.step}"
             min="{self._filter_range_config.min}"
             max="{self._filter_range_config.max}"
             value="{actual_value}">
         <label id={self._filter_range_config.column}_label>{actual_value}</>
         """))
Ejemplo n.º 15
0
    def page(self):
        if not config.user.may("wato.automation"):
            raise MKAuthException(_("This account has no permission for automation."))

        html.set_output_format("python")

        if not html.request.has_var("_version"):
            # Be compatible to calls from sites using versions before 1.5.0p10.
            # Deprecate with 1.7 by throwing an exception in this situation.
            response = _get_login_secret(create_on_demand=True)
        else:
            response = {
                "version": cmk_version.__version__,
                "edition_short": cmk_version.edition_short(),
                "login_secret": _get_login_secret(create_on_demand=True),
            }
        html.write_html(repr(response))
Ejemplo n.º 16
0
    def _change_table(self):
        with table_element(
                "changes",
                title=_("Pending changes (%s)") % self._get_amount_changes(),
                sortable=False,
                searchable=False,
                css="changes",
                limit=None,
                empty_text=_("Currently there are no changes to activate."),
                foldable=Foldable.FOLDABLE_STATELESS,
        ) as table:
            for _change_id, change in reversed(self._changes):
                css = []
                if self._is_foreign(change):
                    css.append("foreign")
                if not user.may("wato.activateforeign"):
                    css.append("not_permitted")

                table.row(css=" ".join(css))

                table.cell("", css="buttons")
                rendered = render_object_ref_as_icon(change["object"])
                if rendered:
                    html.write_html(rendered)

                table.cell(_("Time"),
                           render.date_and_time(change["time"]),
                           css="narrow nobr")
                table.cell(_("User"), css="narrow nobr")
                html.write_text(change["user_id"] if change["user_id"] else "")
                if self._is_foreign(change):
                    html.icon("foreign_changes",
                              _("This change has been made by another user"))

                # Text is already escaped (see ActivateChangesWriter._add_change_to_site). We have
                # to handle this in a special way because of the SiteChanges file format. Would be
                # cleaner to transport the text type (like AuditLogStore is doing it).
                table.cell(_("Change"), HTML(change["text"]))

                table.cell(_("Affected sites"), css="affected_sites")
                if self._affects_all_sites(change):
                    html.write_text("<i>%s</i>" % _("All sites"))
                else:
                    html.write_text(", ".join(sorted(
                        change["affected_sites"])))
Ejemplo n.º 17
0
    def _show_labels(self, labels, object_type, label_sources):
        forms.section(_("Effective labels"))
        html.open_table(class_="setting")
        html.open_tr()

        html.open_td(class_="reason")
        html.i(_("Explicit, ruleset, discovered"))
        html.close_td()
        html.open_td(class_=["settingvalue", "used"])
        html.write_html(
            cmk.gui.view_utils.render_labels(
                labels, object_type, with_links=False, label_sources=label_sources
            )
        )
        html.close_td()

        html.close_tr()
        html.close_table()
Ejemplo n.º 18
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())
Ejemplo n.º 19
0
    def show(self):
        html.open_table(class_="dashlet_overview")
        html.open_tr()
        html.open_td(valign="top")
        html.open_a(href="https://checkmk.com/")
        html.img(html.theme_url("images/check_mk.trans.120.png"),
                 style="margin-right: 30px;")
        html.close_a()
        html.close_td()

        html.open_td()
        html.h2("CheckMK")
        html.write_html(
            'Welcome to CheckMK. If you want to learn more about CheckMK, please visit '
            'our <a href="https://checkmk.com/" target="_blank">user manual</a>.'
        )
        html.close_td()

        html.close_tr()
        html.close_table()
Ejemplo n.º 20
0
def mobile_html_head(title: str) -> None:
    html.write_html(
        HTML(
            """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">"""
        ))
    html.open_html()
    html.open_head()
    html.default_html_headers()
    html.meta(name="viewport", content="initial-scale=1.0")
    html.meta(name="apple-mobile-web-app-capable", content="yes")
    html.meta(name="apple-mobile-web-app-title", content="Check_MK")
    html.title(title)
    html.stylesheet(href="jquery/jquery.mobile-1.4.5.min.css")
    html.stylesheet(href="themes/facelift/theme.css")

    html.link(rel="apple-touch-icon", href="themes/facelift/images/ios_logo.png")
    html.javascript_file(src='js/mobile_min.js')

    html.close_head()
    html.open_body(class_="mobile")
Ejemplo n.º 21
0
    def show(self):
        html.open_table(class_="dashlet_overview")
        html.open_tr()
        html.open_td(valign="top")
        html.open_a(href="https://mathias-kettner.com/check_mk.html")
        html.img(html.theme_url("images/check_mk.trans.120.png"),
                 style="margin-right: 30px;")
        html.close_a()
        html.close_td()

        html.open_td()
        html.h2("Check_MK Multisite")
        html.write_html(
            'Welcome to Check_MK Multisite. If you want to learn more about Multisite, please visit '
            'our <a href="https://mathias-kettner.com/checkmk_multisite.html">online documentation</a>. '
            'Multisite is part of <a href="https://mathias-kettner.com/check_mk.html">Check_MK</a> - an Open Source '
            'project by <a href="https://mathias-kettner.com">Mathias Kettner</a>.'
        )
        html.close_td()

        html.close_tr()
        html.close_table()
Ejemplo n.º 22
0
def render_bi_availability(title, aggr_rows):
    # type: (Text, Rows) -> None
    config.user.need_permission("general.see_availability")

    av_mode = html.request.get_ascii_input_mandatory("av_mode", "availability")
    avoptions = get_availability_options_from_url("bi")
    if av_mode == "timeline":
        title = _("Timeline of") + " " + title
    else:
        title = _("Availability of") + " " + title

    if html.output_format != "csv_export":
        html.body_start(title)
        html.top_heading(title)
        html.begin_context_buttons()
        html.toggle_button("avoptions", False, "painteroptions",
                           _("Configure details of the report"))
        html.context_button(_("Status View"),
                            html.makeuri([("mode", "status")]), "status")
        if config.reporting_available() and config.user.may(
                "general.reporting"):
            html.context_button(_("Export as PDF"),
                                html.makeuri([], filename="report_instant.py"),
                                "report")
        if config.user.may("general.csv_export"):
            html.context_button(
                _("Export as CSV"),
                html.makeuri([("output_format", "csv_export")]),
                "download_csv")

        if av_mode == "timeline":
            html.context_button(_("Availability"),
                                html.makeuri([("av_mode", "availability")]),
                                "availability")

        elif len(aggr_rows) == 1:
            aggr_name = aggr_rows[0]["aggr_name"]
            aggr_group = aggr_rows[0]["aggr_group"]
            timeline_url = html.makeuri([("av_mode", "timeline"),
                                         ("av_aggr_name", aggr_name),
                                         ("av_aggr_group", aggr_group)])
            html.context_button(_("Timeline"), timeline_url, "timeline")
        html.end_context_buttons()

        avoptions = render_availability_options("bi")

    if not html.has_user_errors():
        logrow_limit = avoptions["logrow_limit"]
        if logrow_limit == 0:
            livestatus_limit = None
        else:
            livestatus_limit = (len(aggr_rows) * logrow_limit)

        spans = []  # type: List[AVSpan]

        # iterate all aggregation rows
        timewarpcode = HTML()
        timewarp = html.request.get_integer_input("timewarp")

        has_reached_logrow_limit = False
        timeline_containers, fetched_rows = availability.get_timeline_containers(
            aggr_rows, avoptions, timewarp,
            livestatus_limit + 1 if livestatus_limit is not None else None)
        if livestatus_limit and fetched_rows > livestatus_limit:
            has_reached_logrow_limit = True

        for timeline_container in timeline_containers:
            tree = timeline_container.aggr_tree
            these_spans = timeline_container.timeline
            timewarp_tree_state = timeline_container.timewarp_state

            spans += these_spans

            # render selected time warp for the corresponding aggregation row (should be matched by only one)
            if timewarp and timewarp_tree_state:
                state, assumed_state, node, _subtrees = timewarp_tree_state
                eff_state = state
                if assumed_state is not None:
                    eff_state = assumed_state
                row = {
                    "aggr_tree": tree,
                    "aggr_treestate": timewarp_tree_state,
                    "aggr_state": state,  # state disregarding assumptions
                    "aggr_assumed_state":
                    assumed_state,  # is None, if there are no assumptions
                    "aggr_effective_state":
                    eff_state,  # is assumed_state, if there are assumptions, else real state
                    "aggr_name": node["title"],
                    "aggr_output": eff_state["output"],
                    "aggr_hosts": node["reqhosts"],
                    "aggr_function": node["func"],
                    "aggr_group": html.request.var("aggr_group"),
                }

                renderer = bi.FoldableTreeRendererTree(
                    row,
                    omit_root=False,
                    expansion_level=config.user.bi_expansion_level,
                    only_problems=False,
                    lazy=False)
                tdclass, htmlcode = renderer.css_class(), renderer.render()

                with html.plugged():
                    # TODO: SOMETHING IS WRONG IN HERE (used to be the same situation in original code!)
                    # FIXME: WHAT is wrong in here??

                    html.open_h3()
                    # render icons for back and forth
                    button_back_shown = False
                    button_forth_shown = False
                    if int(these_spans[0]["from"]) == timewarp:
                        html.disabled_icon_button("back_off")
                        button_back_shown = True

                    previous_span = None
                    for span in these_spans:
                        if not button_back_shown and int(
                                span["from"]
                        ) == timewarp and previous_span is not None:
                            html.icon_button(
                                html.makeuri([("timewarp",
                                               str(int(previous_span["from"])))
                                              ]), _("Jump one phase back"),
                                "back")
                            button_back_shown = True
                        # Multiple followup spans can have the same "from" time
                        # We only show one forth-arrow with an actual time difference
                        elif not button_forth_shown and previous_span and int(
                                previous_span["from"]) == timewarp and int(
                                    span["from"]) != timewarp:
                            html.icon_button(
                                html.makeuri([("timewarp",
                                               str(int(span["from"])))]),
                                _("Jump one phase forth"), "forth")
                            button_forth_shown = True
                        previous_span = span
                    if not button_forth_shown:
                        html.disabled_icon_button("forth_off")

                    html.write_text(" &nbsp; ")
                    html.icon_button(html.makeuri([("timewarp", "")]),
                                     _("Close Timewarp"), "closetimewarp")
                    html.write_text("%s %s" %
                                    (_("Timewarp to "),
                                     time.strftime("%Y-%m-%d %H:%M:%S",
                                                   time.localtime(timewarp))))
                    html.close_h3()

                    html.open_table(class_=["data", "table", "timewarp"])
                    html.open_tr(class_=["data", "odd0"])
                    html.open_td(class_=tdclass)
                    html.write_html(htmlcode)
                    html.close_td()
                    html.close_tr()
                    html.close_table()

                    timewarpcode += html.drain()

        # Note: 'spans_by_object' returns two arguments which are used by
        # all availability views but not by BI. There we have to take
        # only complete aggregations
        av_rawdata = availability.spans_by_object(spans, None)[0]
        av_data = availability.compute_availability("bi", av_rawdata,
                                                    avoptions)

        # If we abolish the limit we have to fetch the data again
        # with changed logrow_limit = 0, which means no limit
        if has_reached_logrow_limit:
            text = _(
                "Your query matched more than %d log entries. "
                "<b>Note:</b> The shown data does not necessarily reflect the "
                "matched entries and the result might be incomplete. "
            ) % avoptions["logrow_limit"]
            text += html.render_a(_('Repeat query without limit.'),
                                  html.makeuri([("_unset_logrow_limit", "1")]))
            html.show_warning(text)

        if html.output_format == "csv_export" and config.user.may(
                "general.csv_export"):
            _output_csv("bi", av_mode, av_data, avoptions)
            return

        html.write(timewarpcode)
        do_render_availability("bi", av_rawdata, av_data, av_mode, None,
                               avoptions)

    html.bottom_footer()
    html.body_end()
Ejemplo n.º 23
0
 def _show_global_setting(self):
     forms.section(_("Global setting"))
     html.write_html(HTML(self._valuespec.value_to_text(self._global_settings[self._varname])))
Ejemplo n.º 24
0
def link(text: Union[str, HTML],
         url: str,
         target: str = "main",
         onclick: Optional[str] = None) -> None:
    html.write_html(render_link(text, url, target=target, onclick=onclick))
Ejemplo n.º 25
0
    def page(self):
        # Let exceptions from loading notification scripts happen now
        watolib.load_notification_scripts()

        html.begin_form("user", method="POST")
        html.prevent_password_auto_completion()

        forms.header(_("Identity"))

        # ID
        forms.section(_("Username"), simple=not self._is_new_user)
        if self._is_new_user:
            vs_user_id = UserID(allow_empty=False)

        else:
            vs_user_id = FixedValue(self._user_id)
        vs_user_id.render_input("user_id", self._user_id)

        def lockable_input(name, dflt):
            if not self._is_locked(name):
                html.text_input(name, self._user.get(name, dflt), size=50)
            else:
                html.write_text(self._user.get(name, dflt))
                html.hidden_field(name, self._user.get(name, dflt))

        # Full name
        forms.section(_("Full name"))
        lockable_input('alias', self._user_id)
        html.help(_("Full name or alias of the user"))

        # Email address
        forms.section(_("Email address"))
        email = self._user.get("email", "")
        if not self._is_locked("email"):
            EmailAddressUnicode().render_input("email", email)
        else:
            html.write_text(email)
            html.hidden_field("email", email)

        html.help(
            _("The email address is optional and is needed "
              "if the user is a monitoring contact and receives notifications "
              "via Email."))

        forms.section(_("Pager address"))
        lockable_input('pager', '')
        html.help(_("The pager address is optional "))

        if cmk.is_managed_edition():
            forms.section(self._vs_customer.title())
            self._vs_customer.render_input("customer", managed.get_customer_id(self._user))

            html.help(self._vs_customer.help())

        vs_sites = self._vs_sites()
        forms.section(vs_sites.title())
        authorized_sites = self._user.get("authorized_sites", vs_sites.default_value())
        if not self._is_locked("authorized_sites"):
            vs_sites.render_input("authorized_sites", authorized_sites)
        else:
            html.write_html(vs_sites.value_to_text(authorized_sites))
        html.help(vs_sites.help())

        self._show_custom_user_attributes('ident')

        forms.header(_("Security"))
        forms.section(_("Authentication"))

        is_automation = self._user.get("automation_secret", None) is not None
        html.radiobutton("authmethod", "password", not is_automation,
                         _("Normal user login with password"))
        html.open_ul()
        html.open_table()
        html.open_tr()
        html.td(_("password:"******"_password_" + self._pw_suffix(), autocomplete="new-password")
            html.close_td()
            html.close_tr()

            html.open_tr()
            html.td(_("repeat:"))
            html.open_td()
            html.password_input("_password2_" + self._pw_suffix(), autocomplete="new-password")
            html.write_text(" (%s)" % _("optional"))
            html.close_td()
            html.close_tr()

            html.open_tr()
            html.td("%s:" % _("Enforce change"))
            html.open_td()
            # Only make password enforcement selection possible when user is allowed to change the PW
            if self._is_new_user or config.user_may(self._user_id,
                                                    'general.edit_profile') and config.user_may(
                                                        self._user_id, 'general.change_password'):
                html.checkbox("enforce_pw_change",
                              self._user.get("enforce_pw_change", False),
                              label=_("Change password at next login or access"))
            else:
                html.write_text(
                    _("Not permitted to change the password. Change can not be enforced."))
        else:
            html.i(_('The password can not be changed (It is locked by the user connector).'))
            html.hidden_field('_password', '')
            html.hidden_field('_password2', '')

        html.close_td()
        html.close_tr()
        html.close_table()
        html.close_ul()

        html.radiobutton("authmethod", "secret", is_automation,
                         _("Automation secret for machine accounts"))

        html.open_ul()
        html.text_input("_auth_secret",
                        self._user.get("automation_secret", ""),
                        size=30,
                        id_="automation_secret")
        html.write_text(" ")
        html.open_b(style=["position: relative", "top: 4px;"])
        html.write(" &nbsp;")
        html.icon_button("javascript:cmk.wato.randomize_secret('automation_secret', 20);",
                         _("Create random secret"), "random")
        html.close_b()
        html.close_ul()

        html.help(
            _("If you want the user to be able to login "
              "then specify a password here. Users without a login make sense "
              "if they are monitoring contacts that are just used for "
              "notifications. The repetition of the password is optional. "
              "<br>For accounts used by automation processes (such as fetching "
              "data from views for further procession), set the method to "
              "<u>secret</u>. The secret will be stored in a local file. Processes "
              "with read access to that file will be able to use Multisite as "
              "a webservice without any further configuration."))

        # Locking
        forms.section(_("Disable password"), simple=True)
        if not self._is_locked('locked'):
            html.checkbox("locked",
                          self._user.get("locked", False),
                          label=_("disable the login to this account"))
        else:
            html.write_text(
                _('Login disabled') if self._user.get("locked", False) else _('Login possible'))
            html.hidden_field('locked', '1' if self._user.get("locked", False) else '')
        html.help(
            _("Disabling the password will prevent a user from logging in while "
              "retaining the original password. Notifications are not affected "
              "by this setting."))

        forms.section(_("Idle timeout"))
        idle_timeout = self._user.get("idle_timeout")
        if not self._is_locked("idle_timeout"):
            watolib.get_vs_user_idle_timeout().render_input("idle_timeout", idle_timeout)
        else:
            html.write_text(idle_timeout)
            html.hidden_field("idle_timeout", idle_timeout)

        # Roles
        forms.section(_("Roles"))
        entries = self._roles.items()
        entries.sort(key=lambda x: (x[1]["alias"], x[0]))
        is_member_of_at_least_one = False
        for role_id, role in entries:
            if not self._is_locked("roles"):
                html.checkbox("role_" + role_id, role_id in self._user.get("roles", []))
                url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", role_id)])
                html.a(role["alias"], href=url)
                html.br()
            else:
                is_member = role_id in self._user.get("roles", [])
                if is_member:
                    is_member_of_at_least_one = True
                    url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", role_id)])
                    html.a(role["alias"], href=url)
                    html.br()

                html.hidden_field("role_" + role_id, '1' if is_member else '')
        if self._is_locked('roles') and not is_member_of_at_least_one:
            html.i(_('No roles assigned.'))
        self._show_custom_user_attributes('security')

        # Contact groups
        forms.header(_("Contact Groups"), isopen=False)
        forms.section()
        groups_page_url = watolib.folder_preserving_link([("mode", "contact_groups")])
        group_assign_url = watolib.folder_preserving_link([("mode", "rulesets"),
                                                           ("group", "grouping")])
        if not self._contact_groups:
            html.write(
                _("Please first create some <a href='%s'>contact groups</a>") % groups_page_url)
        else:
            entries = sorted([(group['alias'] or c, c) for c, group in self._contact_groups.items()
                             ])
            is_member_of_at_least_one = False
            for alias, gid in entries:
                is_member = gid in self._user.get("contactgroups", [])

                if not self._is_locked('contactgroups'):
                    html.checkbox("cg_" + gid, gid in self._user.get("contactgroups", []))
                else:
                    if is_member:
                        is_member_of_at_least_one = True
                    html.hidden_field("cg_" + gid, '1' if is_member else '')

                if not self._is_locked('contactgroups') or is_member:
                    url = watolib.folder_preserving_link([("mode", "edit_contact_group"),
                                                          ("edit", gid)])
                    html.a(alias, href=url)
                    html.br()

            if self._is_locked('contactgroups') and not is_member_of_at_least_one:
                html.i(_('No contact groups assigned.'))

        html.help(
            _("Contact groups are used to assign monitoring "
              "objects to users. If you haven't defined any contact groups yet, "
              "then first <a href='%s'>do so</a>. Hosts and services can be "
              "assigned to contact groups using <a href='%s'>rules</a>.<br><br>"
              "If you do not put the user into any contact group "
              "then no monitoring contact will be created for the user.") %
            (groups_page_url, group_assign_url))

        forms.header(_("Notifications"), isopen=False)
        if not self._rbn_enabled():
            forms.section(_("Enabling"), simple=True)
            html.checkbox("notifications_enabled",
                          self._user.get("notifications_enabled", False),
                          label=_("enable notifications"))
            html.help(
                _("Notifications are sent out "
                  "when the status of a host or service changes."))

            # Notification period
            forms.section(_("Notification time period"))
            choices = [(id_, "%s" % (tp["alias"])) for (id_, tp) in self._timeperiods.items()]
            html.dropdown("notification_period",
                          choices,
                          deflt=self._user.get("notification_period"),
                          ordered=True)
            html.help(
                _("Only during this time period the "
                  "user will get notifications about host or service alerts."))

            # Notification options
            notification_option_names = {  # defined here: _() must be executed always!
                "host": {
                    "d": _("Host goes down"),
                    "u": _("Host gets unreachble"),
                    "r": _("Host goes up again"),
                },
                "service": {
                    "w": _("Service goes into warning state"),
                    "u": _("Service goes into unknown state"),
                    "c": _("Service goes into critical state"),
                    "r": _("Service recovers to OK"),
                },
                "both": {
                    "f": _("Start or end of flapping state"),
                    "s": _("Start or end of a scheduled downtime"),
                }
            }

            forms.section(_("Notification Options"))
            for title, what, opts in [(_("Host events"), "host", "durfs"),
                                      (_("Service events"), "service", "wucrfs")]:
                html.write_text("%s:" % title)
                html.open_ul()

                user_opts = self._user.get(what + "_notification_options", opts)
                for opt in opts:
                    opt_name = notification_option_names[what].get(
                        opt, notification_option_names["both"].get(opt))
                    html.checkbox(what + "_" + opt, opt in user_opts, label=opt_name)
                    html.br()
                html.close_ul()

            html.help(
                _("Here you specify which types of alerts "
                  "will be notified to this contact. Note: these settings will only be saved "
                  "and used if the user is member of a contact group."))

            forms.section(_("Notification Method"))
            watolib.get_vs_flexible_notifications().render_input(
                "notification_method", self._user.get("notification_method"))

        else:
            forms.section(_("Fallback notifications"), simple=True)

            html.checkbox("fallback_contact",
                          self._user.get("fallback_contact", False),
                          label=_("Receive fallback notifications"))

            html.help(
                _("In case none of your notification rules handles a certain event a notification "
                  "will be sent to this contact. This makes sure that in that case at least <i>someone</i> "
                  "gets notified. Furthermore this contact will be used for notifications to any host or service "
                  "that is not known to the monitoring. This can happen when you forward notifications "
                  "from the Event Console.<br><br>Notification fallback can also configured in the global "
                  "setting <a href=\"wato.py?mode=edit_configvar&varname=notification_fallback_email\">"
                  "Fallback email address for notifications</a>."))

        self._show_custom_user_attributes('notify')

        forms.header(_("Personal Settings"), isopen=False)
        select_language(self._user)
        self._show_custom_user_attributes('personal')

        # Later we could add custom macros here, which then could be used
        # for notifications. On the other hand, if we implement some check_mk
        # --notify, we could directly access the data in the account with the need
        # to store values in the monitoring core. We'll see what future brings.
        forms.end()
        html.button("save", _("Save"))
        if self._is_new_user:
            html.set_focus("user_id")
        else:
            html.set_focus("alias")
        html.hidden_fields()
        html.end_form()
Ejemplo n.º 26
0
    def _show_user_list(self):
        visible_custom_attrs = [
            (name, attr) for name, attr in userdb.get_user_attributes() if attr.show_in_table()
        ]

        users = userdb.load_users()

        entries = users.items()

        html.begin_form("bulk_delete_form", method="POST")

        roles = userdb.load_roles()
        timeperiods = watolib.timeperiods.load_timeperiods()
        contact_groups = load_contact_group_information()

        with table_element("users", None, empty_text=_("No users are defined yet.")) as table:
            online_threshold = time.time() - config.user_online_maxage
            for uid, user in sorted(entries, key=lambda x: x[1].get("alias", x[0]).lower()):
                table.row()

                # Checkboxes
                table.cell(html.render_input("_toggle_group",
                                             type_="button",
                                             class_="checkgroup",
                                             onclick="cmk.selection.toggle_all_rows();",
                                             value='X'),
                           sortable=False,
                           css="checkbox")

                if uid != config.user.id:
                    html.checkbox("_c_user_%s" % base64.b64encode(uid.encode("utf-8")))

                user_connection_id = userdb.cleanup_connection_id(user.get('connector'))
                connection = userdb.get_connection(user_connection_id)

                # Buttons
                table.cell(_("Actions"), css="buttons")
                if connection:  # only show edit buttons when the connector is available and enabled
                    edit_url = watolib.folder_preserving_link([("mode", "edit_user"),
                                                               ("edit", uid)])
                    html.icon_button(edit_url, _("Properties"), "edit")

                    clone_url = watolib.folder_preserving_link([("mode", "edit_user"),
                                                                ("clone", uid)])
                    html.icon_button(clone_url, _("Create a copy of this user"), "clone")

                delete_url = make_action_link([("mode", "users"), ("_delete", uid)])
                html.icon_button(delete_url, _("Delete"), "delete")

                notifications_url = watolib.folder_preserving_link([("mode", "user_notifications"),
                                                                    ("user", uid)])
                if watolib.load_configuration_settings().get("enable_rulebased_notifications"):
                    html.icon_button(notifications_url, _("Custom notification table of this user"),
                                     "notifications")

                # ID
                table.cell(_("ID"), uid)

                # Online/Offline
                if config.save_user_access_times:
                    last_seen = user.get('last_seen', 0)
                    if last_seen >= online_threshold:
                        title = _('Online')
                        img_txt = 'online'
                    elif last_seen != 0:
                        title = _('Offline')
                        img_txt = 'offline'
                    elif last_seen == 0:
                        title = _('Never logged in')
                        img_txt = 'inactive'

                    title += ' (%s %s)' % (render.date(last_seen), render.time_of_day(last_seen))
                    table.cell(_("Act."))
                    html.icon(title, img_txt)

                    table.cell(_("Last seen"))
                    if last_seen != 0:
                        html.write_text("%s %s" %
                                        (render.date(last_seen), render.time_of_day(last_seen)))
                    else:
                        html.write_text(_("Never logged in"))

                if cmk.is_managed_edition():
                    table.cell(_("Customer"), managed.get_customer_name(user))

                # Connection
                if connection:
                    table.cell(_("Connection"),
                               '%s (%s)' % (connection.short_title(), user_connection_id))
                    locked_attributes = userdb.locked_attributes(user_connection_id)
                else:
                    table.cell(_("Connection"),
                               "%s (%s) (%s)" % (_("UNKNOWN"), user_connection_id, _("disabled")),
                               css="error")
                    locked_attributes = []

                # Authentication
                if "automation_secret" in user:
                    auth_method = _("Automation")
                elif user.get("password") or 'password' in locked_attributes:
                    auth_method = _("Password")
                else:
                    auth_method = "<i>%s</i>" % _("none")
                table.cell(_("Authentication"), auth_method)

                table.cell(_("State"))
                if user.get("locked", False):
                    html.icon(_('The login is currently locked'), 'user_locked')

                if "disable_notifications" in user and isinstance(user["disable_notifications"],
                                                                  bool):
                    disable_notifications_opts = {"disable": user["disable_notifications"]}
                else:
                    disable_notifications_opts = user.get("disable_notifications", {})

                if disable_notifications_opts.get("disable", False):
                    html.icon(_('Notifications are disabled'), 'notif_disabled')

                # Full name / Alias
                table.text_cell(_("Alias"), user.get("alias", ""))

                # Email
                table.text_cell(_("Email"), user.get("email", ""))

                # Roles
                table.cell(_("Roles"))
                if user.get("roles", []):
                    role_links = [(watolib.folder_preserving_link([("mode", "edit_role"),
                                                                   ("edit", role)]),
                                   roles[role].get("alias")) for role in user["roles"]]
                    html.write_html(
                        HTML(", ").join(
                            html.render_a(alias, href=link) for (link, alias) in role_links))

                # contact groups
                table.cell(_("Contact groups"))
                cgs = user.get("contactgroups", [])
                if cgs:
                    cg_aliases = [
                        contact_groups[c]['alias'] if c in contact_groups else c for c in cgs
                    ]
                    cg_urls = [
                        watolib.folder_preserving_link([("mode", "edit_contact_group"),
                                                        ("edit", c)]) for c in cgs
                    ]
                    html.write_html(
                        HTML(", ").join(
                            html.render_a(content, href=url)
                            for (content, url) in zip(cg_aliases, cg_urls)))
                else:
                    html.i(_("none"))

                #table.cell(_("Sites"))
                #html.write(vs_authorized_sites().value_to_text(user.get("authorized_sites",
                #                                                vs_authorized_sites().default_value())))

                # notifications
                if not watolib.load_configuration_settings().get("enable_rulebased_notifications"):
                    table.cell(_("Notifications"))
                    if not cgs:
                        html.i(_("not a contact"))
                    elif not user.get("notifications_enabled", True):
                        html.write_text(_("disabled"))
                    elif user.get("host_notification_options", "") == "" and \
                         user.get("service_notification_options", "") == "":
                        html.write_text(_("all events disabled"))
                    else:
                        tp = user.get("notification_period", "24X7")
                        if tp not in timeperiods:
                            tp = tp + _(" (invalid)")
                        elif tp not in watolib.timeperiods.builtin_timeperiods():
                            url = watolib.folder_preserving_link([("mode", "edit_timeperiod"),
                                                                  ("edit", tp)])
                            tp = html.render_a(timeperiods[tp].get("alias", tp), href=url)
                        else:
                            tp = timeperiods[tp].get("alias", tp)
                        html.write(tp)

                # the visible custom attributes
                for name, attr in visible_custom_attrs:
                    vs = attr.valuespec()
                    table.cell(html.attrencode(_u(vs.title())))
                    html.write(vs.value_to_text(user.get(name, vs.default_value())))

        html.button("_bulk_delete_users", _("Bulk Delete"), "submit", style="margin-top:10px")
        html.hidden_fields()
        html.end_form()

        if not load_contact_group_information():
            url = "wato.py?mode=contact_groups"
            html.open_div(class_="info")
            html.write(
                _("Note: you haven't defined any contact groups yet. If you <a href='%s'>"
                  "create some contact groups</a> you can assign users to them und thus "
                  "make them monitoring contacts. Only monitoring contacts can receive "
                  "notifications.") % url)
            html.write(" you can assign users to them und thus "
                       "make them monitoring contacts. Only monitoring contacts can receive "
                       "notifications.")
            html.close_div()
Ejemplo n.º 27
0
 def _show_page_content(self, content: Optional["HTML"]):
     html.open_div(id_="content_area")
     if content is not None:
         html.write_html(content)
     html.close_div()
Ejemplo n.º 28
0
def _show_graph_legend(graph_artwork, graph_render_options) -> None:
    """Render legend that describe the metrics"""
    graph_width = graph_render_options["size"][0] * html_size_per_ex
    font_size_style = "font-size: %dpt;" % graph_render_options["font_size"]

    scalars = get_scalars(graph_artwork, graph_render_options)

    if graph_render_options["show_vertical_axis"] or graph_render_options[
            "show_controls"]:
        legend_margin_left = 49
    else:
        legend_margin_left = 0

    style = []
    legend_width = graph_width - legend_margin_left

    # In case there is no margin show: Add some to the legend since it looks
    # ugly when there is no space between the outer graph border and the legend
    if not graph_render_options["show_margin"]:
        legend_width -= 5 * 2
        style.append("margin: 8px 5px 5px 5px")

    style.append("width:%dpx" % legend_width)

    if legend_margin_left:
        style.append("margin-left:%dpx" % legend_margin_left)

    html.open_table(class_="legend", style=style)

    # Render the title row
    html.open_tr()
    html.th("")
    for scalar, title, inactive in scalars:
        classes = ["scalar", scalar]
        if inactive and graph_artwork["step"] != 60:
            descr = _(
                "This graph is based on data consolidated with the function \"%s\". The "
                "values in this column are the \"%s\" values of the \"%s\" values "
                "aggregated in %s steps. Assuming a check interval of 1 minute, the %s "
                "values here are based on the %s value out of %d raw values."
            ) % (
                graph_artwork["definition"]["consolidation_function"],
                scalar,
                graph_artwork["definition"]["consolidation_function"],
                artwork.get_step_label(graph_artwork["step"]),
                scalar,
                graph_artwork["definition"]["consolidation_function"],
                (graph_artwork["step"] / 60),
            )

            descr += "\n\n" + _("Click here to change the graphs "
                                "consolidation function to \"%s\".") % scalar

            classes.append("inactive")
        else:
            descr = ""

        html.th(title, class_=classes, style=font_size_style, title=descr)
    html.close_tr()

    # Render the curve related rows
    for curve in graph_curves(graph_artwork):
        html.open_tr()
        html.open_td(style=font_size_style)
        html.write_html(render_color_icon(curve["color"]))
        html.write_text(curve["title"])
        html.close_td()

        for scalar, title, inactive in scalars:
            if scalar == "pin" and not show_pin_time(graph_artwork,
                                                     graph_render_options):
                continue

            if inactive and graph_artwork["step"] != 60:
                inactive_cls: Optional[str] = "inactive"
            else:
                inactive_cls = None

            html.td(curve["scalars"][scalar][1],
                    class_=inactive_cls,
                    style=font_size_style)

        html.close_tr()

    # Render scalar values
    if graph_artwork["horizontal_rules"]:
        first = True
        for _value, readable, color, title in graph_artwork[
                "horizontal_rules"]:
            html.open_tr(class_=["scalar", "first" if first else None])
            html.open_td(style=font_size_style)
            html.write_html(render_color_icon(color))
            html.write_text(title)
            html.close_td()

            # A colspan of 5 has to be used here, since the pin that is added by a click into
            # the graph introduces a new column.
            html.td(readable,
                    colspan=5,
                    class_="scalar",
                    style=font_size_style)
            html.close_tr()
            first = False

    html.close_table()
Ejemplo n.º 29
0
def host_service_graph_dashlet_cmk(
    graph_identification: GraphIdentifier,
    custom_graph_render_options,
):
    graph_render_options = {**default_dashlet_graph_render_options}
    graph_render_options = artwork.add_default_render_options(
        graph_render_options)
    graph_render_options.update(custom_graph_render_options)

    width_var = request.get_float_input_mandatory("width", 0.0)
    width = int((width_var / html_size_per_ex))

    height_var = request.get_float_input_mandatory("height", 0.0)
    height = int((height_var / html_size_per_ex))

    bounds = _graph_margin_ex(graph_render_options)
    height -= _graph_title_height_ex(graph_render_options)
    height -= bounds.top + bounds.bottom
    width -= bounds.left + bounds.right

    graph_render_options["size"] = (width, height)

    # The timerange is specified in PNP like manner.
    range_secs = {
        "0": 4 * 3600,
        "1": 25 * 3600,
        "2": 7 * 86400,
        "3": 31 * 86400,
        "4": 366 * 86400,
    }

    secs_var = request.var("timerange")
    if secs_var not in range_secs:
        secs = 4 * 3600
    else:
        secs = range_secs[secs_var]
    end_time = time.time()
    start_time = end_time - secs
    graph_data_range = {
        "time_range": (start_time, end_time),
    }

    graph_data_range["step"] = estimate_graph_step_for_html(
        graph_data_range["time_range"], graph_render_options)

    graph_recipes = resolve_graph_recipe_with_error_handling(
        graph_identification,
        destination=GraphDestinations.dashlet,
    )
    if not isinstance(graph_recipes, list):
        return graph_recipes  # This is to html.write the exception
    if graph_recipes:
        graph_recipe = graph_recipes[0]
    else:
        raise MKGeneralException(_("Failed to calculate a graph recipe."))

    # When the legend is enabled, we need to reduce the height by the height of the legend to
    # make the graph fit into the dashlet area.
    if graph_render_options["show_legend"]:
        # TODO FIXME: This graph artwork is calulated twice. Once here and once in render_graphs_from_specification_html()
        graph_artwork = artwork.compute_graph_artwork(graph_recipe,
                                                      graph_data_range,
                                                      graph_render_options)
        if graph_artwork["curves"]:
            legend_height = graph_legend_height_ex(graph_render_options,
                                                   graph_artwork)
            graph_render_options["size"] = (width, height - legend_height)

    html_code = render_graphs_from_definitions([graph_recipe],
                                               graph_data_range,
                                               graph_render_options,
                                               render_async=False)
    html.write_html(html_code)
Ejemplo n.º 30
0
    def show(self):
        # type: () -> None
        filename = Path(cmk.utils.paths.omd_root).joinpath(
            'var/dokuwiki/data/pages/sidebar.txt')

        html.open_form(id_="wiki_search",
                       onsubmit="cmk.sidebar.wiki_search('%s');" %
                       config.omd_site())
        html.input(id_="wiki_search_field", type_="text", name="wikisearch")
        html.icon_button("#",
                         _("Search"),
                         "wikisearch",
                         onclick="cmk.sidebar.wiki_search('%s');" %
                         config.omd_site())
        html.close_form()
        html.div('', id_="wiki_side_clear")

        start_ul = True
        ul_started = False
        try:
            title = None
            for line in filename.open(encoding="utf-8").readlines():
                line = line.strip()
                if line == "":
                    if ul_started:
                        html.end_foldable_container()
                        start_ul = True
                        ul_started = False
                elif line.endswith(":"):
                    title = line[:-1]
                elif line == "----":
                    pass
                    # html.br()

                elif line.startswith("*"):
                    if start_ul:
                        if title:
                            html.begin_foldable_container("wikisnapin",
                                                          title,
                                                          True,
                                                          title,
                                                          indent=True)
                        else:
                            html.open_ul()
                        start_ul = False
                        ul_started = True

                    erg = re.findall(r'\[\[(.*)\]\]', line)
                    if len(erg) == 0:
                        continue
                    erg = erg[0].split('|')
                    if len(erg) > 1:
                        link = erg[0]
                        name = erg[1]
                    else:
                        link = erg[0]
                        name = erg[0]

                    if link.startswith("http://") or link.startswith(
                            "https://"):
                        simplelink(name, link, "_blank")
                    else:
                        erg = name.split(':')
                        if len(erg) > 0:
                            name = erg[-1]
                        else:
                            name = erg[0]
                        bulletlink(
                            name, "/%s/wiki/doku.php?id=%s" %
                            (config.omd_site(), link))

                else:
                    html.write_text(line)

            if ul_started:
                html.close_ul()
        except IOError:
            html.write_html(
                html.render_p(
                    html.render_text(
                        "To get a navigation menu, you have to create a ") +
                    html.render_a("sidebar",
                                  href="/%s/wiki/doku.php?id=%s" %
                                  (config.omd_site(), _("sidebar")),
                                  target="main") +  #
                    html.render_text(" in your wiki first.")))