def _show_shortcuts(self, menu: PageMenu) -> None: html.open_td(class_="shortcuts") for entry in menu.shortcuts: ShortcutRenderer().show(entry) html.close_td()
def _table_head( treename: str, id_: str, isopen: bool, title: str, show_more_toggle: bool, help_text: Union[str, HTML, None] = None, ) -> None: onclick = foldable_container_onclick(treename, id_, fetch_url=None) img_id = foldable_container_img_id(treename, id_) html.open_thead() html.open_tr(class_="heading") html.open_td(id_="nform.%s.%s" % (treename, id_), onclick=onclick, colspan=2) html.img( id_=img_id, class_=["treeangle", "nform", "open" if isopen else "closed"], src=theme.url("images/tree_closed.svg"), align="absbottom", ) html.write_text(title) html.help(help_text) if show_more_toggle: html.more_button("foldable_" + id_, dom_levels_up=4, with_text=True) html.close_td() html.close_tr() html.close_thead()
def show_job_class_infos(cls, job_class_infos, **kwargs): """Renders all jobs from the job_class_infos in a single multi-table""" html.open_table(css="job_table data") for job_class, jobs_info in sorted(job_class_infos.items(), key=lambda x: x[0].gui_title()): html.open_tr() html.open_td(colspan=len(cls.get_headers())) html.h3(job_class.gui_title()) html.close_td() html.close_tr() if not jobs_info: html.open_tr() html.open_td(colspan=len(cls.get_headers())) html.div(_("No entries"), css="info") html.close_td() html.close_tr() continue cls.show_job_row_headers() odd = "even" for job_id, job_status in sorted(jobs_info.items(), key=lambda x: x[1]["started"], reverse=True): cls.render_job_row(job_id, job_status, odd, **kwargs) odd = "even" if odd == "odd" else "odd"
def show_details(self, crash_info: CrashInfo, row) -> None: details = crash_info["details"] html.h3(_("Details"), class_="table") html.open_table(class_="data") _crash_row(_("Page"), details["page"], odd=False, legend=True) _crash_row(_("Request Method"), details.get("request_method", _("Unknown"))) html.open_tr(class_="data even0") html.td(_("HTTP Parameters"), class_="left") html.open_td() debug_vars(html, html.request, vars_=details["vars"], hide_with_mouse=False) html.close_td() html.close_tr() _crash_row(_("Referer"), details.get("referer", _("Unknown"))) _crash_row(_("Username"), details["username"], odd=False) _crash_row(_("User Agent"), details["user_agent"]) _crash_row(_("Mobile GUI"), details["is_mobile"], odd=False) _crash_row(_("SSL"), details["is_ssl_request"]) _crash_row(_("Language"), details["language"], odd=False) html.close_table()
def create_graph(name, size, bounds, v_range, legend): html.open_table(class_="prediction") html.open_tr() html.open_td() html.canvas( "", class_="prediction", id_="content_%s" % name, style="width: %dpx; height: %dpx;" % (int(size[0] / 2.0), int(size[1] / 2.0)), width=size[0], height=size[1], ) html.close_td() html.close_tr() html.open_tr() html.open_td(class_="legend") for color, title in legend: html.div("", class_="color", style="background-color: %s" % color) html.div(title, class_="entry") html.close_td() html.close_tr() html.close_table() html.javascript( 'cmk.prediction.create_graph("content_%s", %.4f, %.4f, %.4f, %.4f);' % (name, bounds[0], bounds[1], v_range[0], v_range[1]))
def page(self): html.open_div(class_="diag_host") html.open_table() html.open_tr() html.open_td() html.begin_form("diag_host", method="POST") html.prevent_password_auto_completion() forms.header(_("Host Properties")) forms.section(legend=False) # The diagnose page shows both snmp variants at the same time # We need to analyse the preconfigured community and set either the # snmp_community or the snmp_v3_credentials vs_dict = {} for key, value in self._host.attributes().items(): if key == "snmp_community" and isinstance(value, tuple): vs_dict["snmp_v3_credentials"] = value continue vs_dict[key] = value vs_host = self._vs_host() vs_host.render_input("vs_host", vs_dict) html.help(vs_host.help()) forms.end() html.open_div(style="margin-bottom:10px") html.close_div() forms.header(_("Options")) value = {} forms.section(legend=False) vs_rules = self._vs_rules() vs_rules.render_input("vs_rules", value) html.help(vs_rules.help()) forms.end() # When clicking "Save & Test" on the "Edit host" page, this will be set # to immediately execute the tests using the just saved settings if request.has_var("_start_on_load"): html.final_javascript("cmk.page_menu.form_submit('diag_host', '_save');") html.hidden_fields() html.end_form() html.close_td() html.open_td(style="padding-left:10px;") self._show_diagnose_output()
def _show_diagnose_output(self): if not request.var("_save"): html.show_message( _( "You can diagnose the connection to a specific host using this dialog. " "You can either test whether your current configuration is still working " "or investigate in which ways a host can be reached. Simply configure the " "connection options you like to try on the right side of the screen and " 'press the "Test" button. The results will be displayed here.' ) ) return if user_errors: html.show_user_errors() return # TODO: Insert any vs_host valuespec validation # These tests can be called with invalid valuespec settings... # TODO: Replace hard coded icon paths with dynamic ones to old or new theme for ident, title in ModeDiagHost.diag_host_tests(): html.h3(title) html.open_table(class_=["data", "test"]) html.open_tr(class_=["data", "odd0"]) html.open_td(class_="icons") html.open_div() html.icon("reload", id_="%s_img" % ident) html.open_a(href="") html.icon( "reload", title=_("Retry this test"), cssclass="retry", id_="%s_retry" % ident ) html.close_a() html.close_div() html.close_td() html.open_td() html.div("", class_="log", id="%s_log" % ident) html.close_td() html.close_tr() html.close_table() html.javascript( "cmk.host_diagnose.start_test(%s, %s, %s)" % ( json.dumps(ident), json.dumps(self._hostname), json.dumps(transactions.fresh_transid()), ) )
def _show_suggestions(self, menu: PageMenu) -> None: entries = menu.suggestions if not entries: return html.open_tr(id_="suggestions") html.open_td(colspan=3) for entry in entries: classes = ["suggestion"] classes += self._get_entry_css_classes(entry) html.open_div(class_=classes) SuggestedEntryRenderer().show(entry) html.close_div() html.close_td() html.close_tr()
def _show_dropdowns(self, menu: PageMenu) -> None: html.open_td(class_="menues") for dropdown in menu.dropdowns: if dropdown.is_empty: continue html.open_div( id_="page_menu_dropdown_%s" % dropdown.name, class_=["menucontainer"] + (["disabled"] if not dropdown.is_enabled else []), ) self._show_dropdown_trigger(dropdown) html.close_div() # menucontainer html.close_td()
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()
def display(self, value: FilterHTTPVariables): html.open_table(class_="filtertime") for what, whatname in [("from", _("From")), ("until", _("Until"))]: varprefix = self.ident + "_" + what html.open_tr() html.td("%s:" % whatname) html.open_td() html.text_input(varprefix, default_value=value.get(varprefix, "")) html.close_td() html.open_td() html.dropdown( varprefix + "_range", query_filters.time_filter_options(), deflt=value.get(varprefix + "_range", "3600"), ) html.close_td() html.close_tr() html.close_table()
def section( title: Union[None, HTML, str] = None, checkbox: Union[None, HTML, str, Tuple[str, bool, str]] = None, section_id: Optional[str] = None, simple: bool = False, hide: bool = False, legend: bool = True, css: Optional[str] = None, is_show_more: bool = False, is_changed: bool = False, is_required: bool = False, ) -> None: global g_section_open section_close() html.open_tr( id_=section_id, class_=([] if css is None else [css]) + ["show_more_mode" if is_show_more and not is_changed else "basic"], style="display:none;" if hide else None, ) if legend: html.open_td(class_=["legend"] + (["simple"] if simple else [])) if title: html.open_div( class_=["title"] + (["withcheckbox"] if checkbox else []), title=escaping.strip_tags(title), ) html.write_text(title) html.span("." * 200, class_=["dots"] + (["required"] if is_required else [])) html.close_div() if checkbox: html.open_div(class_="checkbox") if isinstance(checkbox, (str, HTML)): html.write_text(checkbox) else: name, active, attrname = checkbox html.checkbox( name, active, onclick="cmk.wato.toggle_attribute(this, '%s')" % attrname ) html.close_div() html.close_td() html.open_td(class_=["content"] + (["simple"] if simple else [])) g_section_open = True
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(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_text( _("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()
def render(self, rows, view, group_cells, cells, num_columns, show_checkboxes): # N columns. Each should contain approx the same number of entries groups = [] last_group = None for row in rows: this_group = group_value(row, group_cells) if this_group != last_group: last_group = this_group current_group: List[Tuple[str, Any]] = [] groups.append((this_group, current_group)) current_group.append((row_id(view, row), row)) # Create empty columns columns: List[List[Any]] = [] for _x in range(num_columns): columns.append([]) # First put everything into the first column for group in groups: columns[0].append(group) # Shift from left to right as long as useful did_something = True while did_something: did_something = False for i in range(0, num_columns - 1): if self._balance(columns[i], columns[i + 1]): did_something = True # render table html.open_table(class_=["boxlayout", self._css_class()]) html.open_tr() for column in columns: html.open_td(class_="boxcolumn") for header, rows_with_ids in column: self._render_group(rows_with_ids, header, view, group_cells, cells, num_columns, show_checkboxes) html.close_td() html.close_tr() html.close_table()
def page(self): html.open_table(class_=["data", "headerleft"]) html.open_tr() html.th(_("Title")) html.open_td() html.b(self._manpage.title) html.close_td() html.close_tr() html.open_tr() html.th(_("Name of plugin")) html.open_td() html.tt(self._check_plugin_name) html.close_td() html.close_tr() html.open_tr() html.th(_("Description")) html.td(self._manpage_text(self._manpage.description)) html.close_tr() if self._check_type == "check_mk": html.open_tr() html.th(_("Service name")) html.td(HTML(self._service_description.replace("%s", "☐"))) html.close_tr() if discovery := self._manpage.discovery: html.open_tr() html.th(_("Discovery")) html.td(self._manpage_text(discovery)) html.close_tr() if self._manpage.cluster: html.open_tr() html.th(_("Cluster behaviour")) html.td(self._manpage_text(self._manpage.cluster)) html.close_tr()
def _show_ruleset(self, varname): if varname not in rulespec_registry: return rulespec = rulespec_registry[varname] url = makeuri_contextless(request, [("mode", "edit_ruleset"), ("varname", varname)]) html.open_tr() html.th(_("Parameter rule set")) html.open_td() html.icon_button(url, _("Edit parameter rule set for this check type"), "check_parameters") html.a(rulespec.title, url) html.close_td() html.close_tr() html.open_tr() html.th(_("Example for Parameters")) html.open_td() vs = rulespec.valuespec vs.render_input("dummy", vs.default_value()) html.close_td() html.close_tr()
def _show_table(self, api_request): html.open_table(class_="allhosts") html.open_tbody() for map_cfg in api_request["maps"]: html.open_tr() html.open_td() html.div( "", class_=[ "statebullet", self._state_class(map_cfg), self._sub_state_class(map_cfg), self._stale_class(map_cfg), ], title=self._state_title(map_cfg), ) html.a(map_cfg["alias"], href=map_cfg["url"], class_="link", target="main") html.close_td() html.close_tr() html.close_tbody() html.close_table()
def grouped_row_title(index, group_spec, num_rows, trclass, num_cells): is_open = user.get_tree_state("grouped_rows", index, False) html.open_tr(class_=[ "data", "grouped_row_header", "closed" if not is_open else "", "%s0" % trclass ]) html.open_td( colspan=num_cells, onclick="cmk.views.toggle_grouped_rows('grouped_rows', '%s', this, %d)" % (index, num_rows), ) html.img( theme.url("images/tree_closed.svg"), align="absbottom", class_=["treeangle", "nform", "open" if is_open else "closed"], ) html.write_text("%s (%d)" % (group_spec["title"], num_rows)) html.close_td() html.close_tr() return not is_open
def section_close() -> None: if g_section_open: html.close_td() html.close_tr()
def render(self, rows, view, group_cells, cells, num_columns, show_checkboxes): repeat_heading_every = 20 # in case column_headers is "repeat" html.open_table(class_="data table") last_group = None odd = "odd" column = 1 group_open = False num_cells = len(cells) if show_checkboxes: num_cells += 1 if not group_cells and view.get("column_headers") != "off": self._show_header_line(cells, num_columns, show_checkboxes) rows_with_ids = [(row_id(view, row), row) for row in rows] groups, rows_with_ids = calculate_view_grouping_of_services( rows_with_ids, row_group_cells=group_cells) visible_row_number = 0 group_hidden, num_grouped_rows = None, 0 for index, row in rows_with_ids: # Show group header, if a new group begins. But only if grouping # is activated if group_cells: this_group = group_value(row, group_cells) if this_group != last_group: if column != 1: # not a the beginning of a new line for _i in range(column - 1, num_columns): html.td("", class_="gap") html.td("", class_="fillup", colspan=num_cells) html.close_tr() column = 1 group_open = True visible_row_number = 0 # paint group header, but only if it is non-empty header_is_empty = True for cell in group_cells: _tdclass, content = cell.render(row) if content: header_is_empty = False break if not header_is_empty: html.open_tr(class_="groupheader") html.open_td( class_="groupheader", colspan=(num_cells * (num_columns + 2) + (num_columns - 1)), ) html.open_table(class_="groupheader", cellspacing="0", cellpadding="0", border="0") html.open_tr() painted = False for cell in group_cells: if painted: html.td(", ") painted = cell.paint(row) html.close_tr() html.close_table() html.close_td() html.close_tr() odd = "odd" # Table headers if view.get("column_headers") != "off": self._show_header_line(cells, num_columns, show_checkboxes) last_group = this_group # Should we wrap over to a new line? if column >= num_columns + 1: html.close_tr() column = 1 # At the beginning of the line? Beginn new line if column == 1: if view.get("column_headers") == "repeat": if visible_row_number > 0 and visible_row_number % repeat_heading_every == 0: self._show_header_line(cells, num_columns, show_checkboxes) visible_row_number += 1 # In one-column layout we use the state of the service # or host - if available - to color the complete line if num_columns == 1: # render state, if available through whole tr if not row.get("service_description"): state = row.get("host_state", 0) if state > 0: state += 1 # 1 is critical for hosts else: state = row.get("service_state", 0) else: state = 0 if index in groups: group_spec, num_grouped_rows = groups[index] group_hidden = grouped_row_title(index, group_spec, num_grouped_rows, odd, num_cells) odd = "even" if odd == "odd" else "odd" css_classes = [] hide = "" if num_grouped_rows > 0: num_grouped_rows -= 1 if group_hidden: hide = "display:none" if group_hidden is not None and num_grouped_rows == 0: # last row in group css_classes.append("group_end") group_hidden = None odd = "even" if odd == "odd" else "odd" if num_columns > 1: css_classes.append("multicolumn") css_classes += ["%s%d" % (odd, state)] html.open_tr(class_=["data"] + css_classes, style=hide) # Not first columns: Create one empty column as separator else: html.open_td(class_="gap") html.close_td() if show_checkboxes: render_checkbox_td(view, row, num_cells) for cell in cells: cell.paint(row) column += 1 if group_open: for _i in range(column - 1, num_columns): html.td("", class_="gap") html.td("", class_="fillup", colspan=num_cells) html.close_tr() html.close_table() if not user.may("general.act"): return init_rowselect(_get_view_name(view))
def page(self): # Show outcome of host validation. Do not validate new hosts errors = None if self._mode == "edit": errors = (validate_all_hosts([self._host.name()]).get( self._host.name(), []) + self._host.validation_errors()) if errors: html.open_div(class_="info") html.open_table(class_="validationerror", boder="0", cellspacing="0", cellpadding="0") html.open_tr() html.open_td(class_="img") html.icon("validation_error") html.close_td() html.open_td() html.open_p() html.h3(_("Warning: This host has an invalid configuration!")) html.open_ul() for error in errors: html.li(error) html.close_ul() html.close_p() if html.form_submitted(): html.br() html.b(_("Your changes have been saved nevertheless.")) html.close_td() html.close_tr() html.close_table() html.close_div() lock_message = "" locked_hosts = Folder.current().locked_hosts() if locked_hosts: if locked_hosts is True: lock_message = _( "Host attributes locked (You cannot edit this host)") elif isinstance(locked_hosts, str): lock_message = locked_hosts if lock_message: html.div(lock_message, class_="info") html.begin_form("edit_host", method="POST") html.prevent_password_auto_completion() basic_attributes = [ # attribute name, valuepec, default value ("host", self._vs_host_name(), self._host.name()), ] if self._is_cluster(): basic_attributes += [ # attribute name, valuepec, default value ( "nodes", self._vs_cluster_nodes(), self._host.cluster_nodes() if self._host else [], ), ] configure_attributes( new=self._mode != "edit", hosts={self._host.name(): self._host} if self._mode != "new" else {}, for_what="host" if not self._is_cluster() else "cluster", parent=Folder.current(), basic_attributes=basic_attributes, ) if self._mode != "edit": html.set_focus("host") forms.end() html.hidden_fields() html.end_form()
def _show_start_form(self): html.begin_form("parentscan", method="POST") html.hidden_fields() # Mode of action html.open_p() if not self._complete_folder: num_selected = len(get_hosts_from_checkboxes()) html.write_text(_("You have selected <b>%d</b> hosts for parent scan. ") % num_selected) html.p( _( "The parent scan will try to detect the last gateway " "on layer 3 (IP) before a host. This will be done by " "calling <tt>traceroute</tt>. If a gateway is found by " "that way and its IP address belongs to one of your " "monitored hosts, that host will be used as the hosts " "parent. If no such host exists, an artifical ping-only " "gateway host will be created if you have not disabled " "this feature." ) ) forms.header(_("Settings for Parent Scan")) self._settings = ParentScanSettings( **user.load_file( "parentscan", { "where": "subfolder", "alias": _("Created by parent scan"), "recurse": True, "select": "noexplicit", "timeout": 8, "probes": 2, "ping_probes": 5, "max_ttl": 10, "force_explicit": False, }, ) ) # Selection forms.section(_("Selection")) if self._complete_folder: html.checkbox("recurse", self._settings.recurse, label=_("Include all subfolders")) html.br() html.radiobutton( "select", "noexplicit", self._settings.select == "noexplicit", _("Skip hosts with explicit parent definitions (even if empty)") + "<br>", ) html.radiobutton( "select", "no", self._settings.select == "no", _("Skip hosts hosts with non-empty parents (also if inherited)") + "<br>", ) html.radiobutton( "select", "ignore", self._settings.select == "ignore", _("Scan all hosts") + "<br>" ) # Performance forms.section(_("Performance")) html.open_table() html.open_tr() html.open_td() html.write_text(_("Timeout for responses") + ":") html.close_td() html.open_td() html.text_input("timeout", str(self._settings.timeout), size=2, cssclass="number") html.write_text(_("sec")) html.close_td() html.close_tr() html.open_tr() html.open_td() html.write_text(_("Number of probes per hop") + ":") html.close_td() html.open_td() html.text_input("probes", str(self._settings.probes), size=2, cssclass="number") html.close_td() html.close_tr() html.open_tr() html.open_td() html.write_text(_("Maximum distance (TTL) to gateway") + ":") html.close_td() html.open_td() html.text_input("max_ttl", str(self._settings.max_ttl), size=2, cssclass="number") html.close_td() html.close_tr() html.open_tr() html.open_td() html.write_text(_("Number of PING probes") + ":") html.help( _( "After a gateway has been found, Check_MK checks if it is reachable " "via PING. If not, it is skipped and the next gateway nearer to the " "monitoring core is being tried. You can disable this check by setting " "the number of PING probes to 0." ) ) html.close_td() html.open_td() html.text_input("ping_probes", str(self._settings.ping_probes), size=2, cssclass="number") html.close_td() html.close_tr() html.close_table() # Configuring parent forms.section(_("Configuration")) html.checkbox( "force_explicit", deflt=self._settings.force_explicit, label=_( "Force explicit setting for parents even if setting matches that of the folder" ), ) # Gateway creation forms.section(_("Creation of gateway hosts")) html.write_text(_("Create gateway hosts in")) html.open_ul() html.radiobutton( "where", "subfolder", self._settings.where == "subfolder", _("in the subfolder <b>%s/Parents</b>") % Folder.current_disk_folder().title(), ) html.br() html.radiobutton( "where", "here", self._settings.where == "here", _("directly in the folder <b>%s</b>") % Folder.current_disk_folder().title(), ) html.br() html.radiobutton( "where", "there", self._settings.where == "there", _("in the same folder as the host") ) html.br() html.radiobutton( "where", "nowhere", self._settings.where == "nowhere", _("do not create gateway hosts") ) html.close_ul() html.write_text(_("Alias for created gateway hosts") + ": ") html.text_input("alias", default_value=self._settings.alias) forms.end() # Start button html.button("_start", _("Start")) html.hidden_fields() html.end_form()
def render(self, rows, view, group_cells, cells, num_columns, show_checkboxes): header_majorities = self._matrix_find_majorities_for_header( rows, group_cells) value_counts, row_majorities = self._matrix_find_majorities( rows, cells) painter_options = PainterOptions.get_instance() for groups, unique_row_ids, matrix_cells in create_matrices( rows, group_cells, cells, num_columns): # Paint the matrix. Begin with the group headers html.open_table(class_="data matrix") odd = "odd" for cell_nr, cell in enumerate(group_cells): odd = "even" if odd == "odd" else "odd" html.open_tr(class_="data %s0" % odd) html.open_td(class_="matrixhead") html.write_text(cell.title(use_short=False)) html.close_td() for _group, group_row in groups: tdclass, content = cell.render(group_row) if cell_nr > 0: gv = group_value(group_row, [cell]) majority_value = header_majorities.get( cell_nr - 1, None) if majority_value is not None and majority_value != gv: tdclass += " minority" html.open_td(class_=["left", tdclass]) html.write_text(content) html.close_td() html.close_tr() # Now for each unique service^H^H^H^H^H^H ID column paint one row for rid in unique_row_ids: # Omit rows where all cells have the same values if painter_options.get("matrix_omit_uniform"): at_least_one_different = False for counts in value_counts[rid].values(): if len(counts) > 1: at_least_one_different = True break if not at_least_one_different: continue odd = "even" if odd == "odd" else "odd" html.open_tr(class_="data %s0" % odd) tdclass, content = cells[0].render( list(matrix_cells[rid].values())[0]) html.open_td(class_=["left", tdclass]) html.write_text(content) html.close_td() # Now go through the groups and paint the rest of the # columns for group_id, group_row in groups: cell_row = matrix_cells[rid].get(group_id) if cell_row is None: html.td("") else: if len(cells) > 2: html.open_td(class_="cell") html.open_table() for cell_nr, cell in enumerate(cells[1:]): tdclass, content = cell.render(cell_row) gv = group_value(cell_row, [cell]) majority_value = row_majorities[rid].get( cell_nr, None) if majority_value is not None and majority_value != gv: tdclass += " minority" if len(cells) > 2: html.open_tr() html.td(content, class_=tdclass) if len(cells) > 2: html.close_tr() if len(cells) > 2: html.close_table() html.close_td() html.close_tr() html.close_table()
def show(self): if not site_config.is_wato_slave_site(): if not active_config.wato_enabled: html.write_text(_("Setup is disabled.")) return False user_folders = compute_foldertree() # # Render link target selection # # Apply some view specific filters views_to_show: List[Tuple[str, ViewSpec]] = [] dflt_target_name: str = "allhosts" dflt_topic_name: str = "" for name, view in views.get_permitted_views().items(): if (not active_config.visible_views or name in active_config.visible_views) and ( not active_config.hidden_views or name not in active_config.hidden_views ): views_to_show.append((name, view)) if name == dflt_target_name: dflt_topic_name = view["topic"] selected_topic_name: str selected_target_name: str selected_topic_name, selected_target_name = user.load_file( "foldertree", (dflt_topic_name, dflt_target_name) ) visuals_to_show = [("views", e) for e in views_to_show] visuals_to_show += [("dashboards", e) for e in dashboard.get_permitted_dashboards().items()] topics = make_topic_menu(visuals_to_show) topic_choices: Choices = [(topic.title, topic.title) for topic in topics] html.open_table() html.open_tr() html.open_td() html.dropdown( "topic", topic_choices, deflt=selected_topic_name, onchange="cmk.sidebar.wato_tree_topic_changed(this)", ) html.close_td() html.close_tr() html.open_tr() html.open_td() for topic in topics: targets: Choices = [] for item in topic.items: if item.url and item.url.startswith("dashboard.py"): name = "dashboard|" + item.name else: name = item.name targets.append((name, item.title)) if topic.name != selected_topic_name: default = "" style: Optional[str] = "display:none" else: default = selected_target_name style = None html.dropdown( "target_%s" % topic.title, targets, deflt=default, onchange="cmk.sidebar.wato_tree_target_changed(this)", style=style, ) html.close_td() html.close_tr() html.close_table() # Now render the whole tree if user_folders: render_tree_folder( "wato-hosts", list(user_folders.values())[0], "cmk.sidebar.wato_tree_click" ) return None
def _write_table( self, rows: TableRows, num_rows_unlimited: int, actions_enabled: bool, actions_visible: bool, search_term: Optional[str], ) -> None: if not self.options["omit_update_header"]: row_info = _("1 row") if len( rows) == 1 else _("%d rows") % num_rows_unlimited html.javascript("cmk.utils.update_row_info(%s);" % json.dumps(row_info)) table_id = self.id num_cols = self._get_num_cols(rows) empty_columns = self._get_empty_columns(rows, num_cols) if self.options["omit_empty_columns"]: num_cols -= len([v for v in empty_columns if v]) html.open_table(class_=["data", "oddeven"] + self.css) # If we have no group headers then paint the headers now if self.rows and not isinstance(self.rows[0], GroupHeader): self._render_headers( actions_enabled, actions_visible, empty_columns, ) if actions_enabled and actions_visible: html.open_tr(class_=["data", "even0", "actions"]) html.open_td(colspan=num_cols) if not html.in_form(): html.begin_form("%s_actions" % table_id) if request.has_var("_%s_sort" % table_id): html.open_div(class_=["sort"]) html.button("_%s_reset_sorting" % table_id, _("Reset sorting")) html.close_div() if not html.in_form(): html.begin_form("%s_actions" % table_id) html.hidden_fields() html.end_form() html.close_tr() for nr, row in enumerate(rows): # Intermediate header if isinstance(row, GroupHeader): # Show the header only, if at least one (non-header) row follows if nr < len(rows) - 1 and not isinstance( rows[nr + 1], GroupHeader): html.open_tr(class_="groupheader") html.open_td(colspan=num_cols) html.h3(row.title) html.close_td() html.close_tr() self._render_headers(actions_enabled, actions_visible, empty_columns) continue oddeven_name = "even" if nr % 2 == 0 else "odd" class_ = ["data", "%s%d" % (oddeven_name, row.state)] if isinstance(row.css, list): class_.extend([c for c in row.css if c is not None]) elif row.css is not None: class_.append(row.css) html.open_tr(class_=class_, id_=row.id_, onmouseover=row.onmouseover, onmouseout=row.onmouseout) for col_index, cell in enumerate(row.cells): if self.options["omit_empty_columns"] and empty_columns[ col_index]: continue html.td(cell.content, class_=cell.css, colspan=cell.colspan) html.close_tr() if not rows and search_term: html.open_tr(class_=["data", "odd0", "no_match"]) html.td( _("Found no matching rows. Please try another search term."), colspan=num_cols) html.close_tr() html.close_table()
def render(self, rows, view, group_cells, cells, num_columns, show_checkboxes): html.open_table(class_="data tiled") last_group = None group_open = False for row in rows: # Show group header if group_cells: this_group = group_value(row, group_cells) if this_group != last_group: # paint group header if group_open: html.close_td() html.close_tr() html.open_tr() html.open_td() html.open_table(class_="groupheader") html.open_tr(class_="groupheader") painted = False for cell in group_cells: if painted: html.td(", ") painted = cell.paint(row) html.close_tr() html.close_table() html.close_td() html.close_tr() html.open_tr() html.open_td(class_="tiles") group_open = True last_group = this_group # background color of tile according to item state state = row.get("service_state", -1) if state == -1: hbc = row.get("host_has_been_checked", 1) if hbc: state = row.get("host_state", 0) sclass = "hhstate%d" % state else: sclass = "hhstatep" else: hbc = row.get("service_has_been_checked", 1) if hbc: sclass = "sstate%d" % state else: sclass = "sstatep" if not group_open: html.open_tr() html.open_td(class_="tiles") group_open = True html.open_div(class_=["tile", sclass]) html.open_table() # We need at least five cells if len(cells) < 5: cells = cells + ([EmptyCell(view)] * (5 - len(cells))) rendered = [cell.render(row) for cell in cells] html.open_tr() html.open_td(class_=["tl", rendered[1][0]]) if show_checkboxes: render_checkbox(view, row, len(cells) - 1) html.write_text(rendered[1][1]) html.close_td() html.open_td(class_=["tr", rendered[2][0]]) html.write_text(rendered[2][1]) html.close_td() html.close_tr() html.open_tr() html.open_td(colspan=2, class_=["center", rendered[0][0]]) html.write_text(rendered[0][1]) html.close_td() html.close_tr() for css, cont in rendered[5:]: html.open_tr() html.open_td(colspan=2, class_=["cont", css]) html.write_text(cont) html.close_td() html.close_tr() html.open_tr() html.open_td(class_=["bl", rendered[3][0]]) html.write_text(rendered[3][1]) html.close_td() html.open_td(class_=["br", rendered[4][0]]) html.write_text(rendered[4][1]) html.close_td() html.close_tr() html.close_table() html.close_div() if group_open: html.close_td() html.close_tr() html.close_table() if not user.may("general.act"): return init_rowselect(_get_view_name(view))
def _show_rows(self): rows = self._get_rows() if bool([r for r in rows if r.stats is None]): html.center(_("No data from any site")) return html.open_table(class_=["tacticaloverview"], cellspacing="2", cellpadding="0", border="0") show_stales = self.parameters()["show_stale"] and user.may( "general.see_stales_in_tactical_overview" ) has_stale_objects = bool([r for r in rows if r.what != "events" and r.stats[-1]]) for row in rows: if row.what == "events": amount, problems, unhandled_problems = row.stats stales = 0 # no events open and disabled in local site: don't show events if amount == 0 and not active_config.mkeventd_enabled: continue else: amount, problems, unhandled_problems, stales = row.stats context_vars = get_context_url_variables(row.context) html.open_tr() html.th(row.title) html.th(_("Problems"), class_="show_more_mode") html.th( HTMLWriter.render_span(_("Unhandled"), class_="more") + HTMLWriter.render_span(_("Unhandled p."), class_="less") ) if show_stales and has_stale_objects: html.th(_("Stale")) html.close_tr() td_class = "col4" if has_stale_objects else "col3" html.open_tr() url = makeuri_contextless(request, row.views.total + context_vars, filename="view.py") html.open_td(class_=["total", td_class]) html.a("%s" % amount, href=url, target="main") html.close_td() for value, ty in [(problems, "handled"), (unhandled_problems, "unhandled")]: url = makeuri_contextless( request, getattr(row.views, ty) + context_vars, filename="view.py", ) html.open_td( class_=[td_class] + ([] if value == 0 else ["states prob"]) + ["show_more_mode" if ty == "handled" else "basic"] ) link(str(value), url) html.close_td() if show_stales and has_stale_objects: if row.views.stale: url = makeuri_contextless( request, row.views.stale + context_vars, filename="view.py", ) html.open_td(class_=[td_class] + ([] if stales == 0 else ["states prob"])) link(str(stales), url) html.close_td() else: html.td(HTMLWriter.render_span("0")) html.close_tr() html.close_table()
def page(self): html.open_div(id_="ldap") html.open_table() html.open_tr() html.open_td() html.begin_form("connection", method="POST") html.prevent_password_auto_completion() vs = self._valuespec() vs.render_input("connection", self._connection_cfg) vs.set_focus("connection") html.hidden_fields() html.end_form() html.close_td() html.open_td(style="padding-left:10px;vertical-align:top") html.h2(_("Diagnostics")) if not request.var("_test") or not self._connection_id: html.show_message( HTML("<p>%s</p><p>%s</p>" % ( _("You can verify the single parts of your ldap configuration using this " "dialog. Simply make your configuration in the form on the left side and " 'hit the "Save & Test" button to execute the tests. After ' "the page reload, you should see the results of the test here." ), _("If you need help during configuration or experience problems, please refer " 'to the <a target="_blank" ' 'href="https://checkmk.com/checkmk_multisite_ldap_integration.html">' "LDAP Documentation</a>."), ))) else: connection = userdb.get_connection(self._connection_id) assert isinstance(connection, LDAPUserConnector) for address in connection.servers(): html.h3("%s: %s" % (_("Server"), address)) with table_element("test", searchable=False) as table: for title, test_func in self._tests(): table.row() try: state, msg = test_func(connection, address) except Exception as e: state = False msg = _("Exception: %s") % e logger.exception("error testing LDAP %s for %s", title, address) if state: img = html.render_icon("success", _("Success")) else: img = html.render_icon("failed", _("Failed")) table.cell(_("Test"), title) table.cell(_("State"), img) table.cell(_("Details"), msg) connection.disconnect() html.close_td() html.close_tr() html.close_table() html.close_div()
def foldable_container( *, treename: str, id_: str, isopen: bool, title: HTMLContent, indent: Union[str, None, bool] = True, icon: Optional[str] = None, fetch_url: Optional[str] = None, title_url: Optional[str] = None, title_target: Optional[str] = None, padding: int = 15, save_state: bool = True, ) -> Iterator[bool]: isopen = user.get_tree_state(treename, id_, isopen) onclick = foldable_container_onclick(treename, id_, fetch_url, save_state) img_id = foldable_container_img_id(treename, id_) container_id = foldable_container_id(treename, id_) html.open_div(class_=["foldable", "open" if isopen else "closed"]) html.open_div(class_="foldable_header", onclick=None if title_url else onclick) if isinstance(title, HTML): # custom HTML code html.write_text(title) else: html.open_b(class_=["treeangle", "title"]) if title_url: html.a(title, href=title_url, target=title_target) else: html.write_text(title) html.close_b() if icon: html.img( id_=img_id, # Although foldable_sidebar is given via the argument icon it should not be displayed as big as an icon. class_=(["treeangle", "title"] + (["icon"] if icon != "foldable_sidebar" else []) + ["open" if isopen else "closed"]), src=theme.detect_icon_path(icon, "icon_"), onclick=onclick if title_url else None, ) else: html.img( id_=img_id, class_=["treeangle", "open" if isopen else "closed"], src=theme.url("images/tree_closed.svg"), onclick=onclick if title_url else None, ) html.close_div() indent_style = "padding-left: %dpx; " % (padding if indent else 0) if indent == "form": html.close_td() html.close_tr() html.close_table() indent_style += "margin: 0; " html.open_ul(id_=container_id, class_=["treeangle", "open" if isopen else "closed"], style=indent_style) yield isopen html.close_ul() html.close_div()
def _show_master_control_site( self, site_id: sites.SiteId, site_status_info: Dict[sites.SiteId, List], items: List[Tuple[str, str]], ) -> None: site_state = sites.states().get(site_id) if not site_state: html.show_error(_("Site state is unknown")) return if site_state["state"] == "dead": html.show_error(str(site_state["exception"])) return if site_state["state"] == "disabled": html.show_message(_("Site is disabled")) return if site_state["state"] == "unknown": if site_state.get("exception"): html.show_error(str(site_state["exception"])) else: html.show_error(_("Site state is unknown")) return is_cmc = site_state["program_version"].startswith("Check_MK ") try: site_info = site_status_info[site_id] except KeyError: html.show_error(_("Site state is unknown")) return html.open_table(class_="master_control") for i, (colname, title) in enumerate(items): # Do not show event handlers on Checkmk Micro Core if is_cmc and title == _("Event handlers"): continue if not is_cmc and title == _("Alert handlers"): continue colvalue = site_info[i] url = makeactionuri_contextless( request, transactions, [ ("site", site_id), ("switch", colname), ("state", "%d" % (1 - colvalue)), ], filename="switch_master_state.py", ) onclick = ( "cmk.ajax.get_url('%s', cmk.utils.update_contents, 'snapin_master_control')" % url ) html.open_tr() html.td(title, class_="left") html.open_td() html.toggle_switch( enabled=colvalue, help_txt=_("Switch '%s' to '%s'") % (title, _("off") if colvalue else _("on")), onclick=onclick, ) html.close_td() html.close_tr() html.close_table()