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 html.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') % html.render_text("%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 _show_main_menu_content(self) -> None: for menu_item in self._get_main_menu_items(): if isinstance(menu_item.icon, dict): active_icon: Icon = { "icon": menu_item.icon["icon"] + "_active", "emblem": menu_item.icon["emblem"] } else: active_icon = menu_item.icon + "_active" html.open_li() html.popup_trigger( (html.render_icon(menu_item.icon) + html.render_icon(active_icon, class_="active") + html.render_div(menu_item.title)), ident="mega_menu_" + menu_item.name, method=MethodInline(self._get_mega_menu_content(menu_item)), cssclass=menu_item.name, popup_group="main_menu_popup", hover_switch_delay=150, # ms onopen=menu_item.onopen, ) html.div("", id_="popup_shadow", onclick="cmk.popup_menu.close_popup()") html.close_li()
def _get_popup_trigger_content(self, active_icon: Icon, menu_item: MainMenuItem) -> HTML: content = html.render_icon(menu_item.icon) + html.render_icon(active_icon, class_="active") if not user.get_attribute("nav_hide_icons_title"): content += html.render_div(menu_item.title) return content
def render_addto_popup_entry(cls, type_name, name, title): html.open_li() html.open_a( href="javascript:void(0)", onclick="cmk.popup_menu.pagetype_add_to_container('%s', '%s');cmk.utils.reload_sidebar();" % (type_name, name)) html.render_icon(type_name) html.write_text(title) html.close_a() html.close_li()
def _show_main_menu_content(self) -> None: for menu_item in self._get_main_menu_items(): html.open_li() html.popup_trigger( (html.render_icon(menu_item.icon_name) + html.render_icon( menu_item.icon_name + "_active", class_="active") + html.render_div(menu_item.title)), ident="mega_menu_" + menu_item.name, method=MethodInline(self._get_mega_menu_content(menu_item)), cssclass=menu_item.name, popup_group="main_menu_popup", hover_switch_delay=150, # ms onopen=menu_item.onopen, ) html.close_li()
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 = ["page_menu_popup"] + html.normalize_css_spec(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))
def page(self) -> None: html.h3(_("Upload Icon")) html.p( _("Allowed are single PNG image files with a maximum size of 80x80 px." )) html.begin_form('upload_form', method='POST') self._vs_upload().render_input('_upload_icon', None) html.hidden_fields() html.end_form() icons = sorted(self._load_custom_icons().items()) with table_element("icons", _("Custom Icons")) as table: for icon_name, category_name in icons: table.row() table.cell(_("Actions"), css="buttons") delete_url = make_action_link([("mode", "icons"), ("_delete", icon_name)]) html.icon_button(delete_url, _("Delete this Icon"), "delete") table.cell(_("Icon"), html.render_icon(icon_name), css="buttons") table.text_cell(_("Name"), icon_name) table.text_cell(_("Category"), IconSelector.category_alias(category_name))
def render_object_ref_as_icon( object_ref: Optional[ObjectRef]) -> Optional[HTML]: if object_ref is None: return None url, title = _get_object_reference(object_ref) if not url: return None icons = { ObjectRefType.Host: "host", ObjectRefType.Folder: "folder", ObjectRefType.User: "******", ObjectRefType.Rule: "rule", ObjectRefType.Ruleset: "rulesets", } return html.render_a( content=html.render_icon( icons.get(object_ref.object_type, "link"), title="%s: %s" % (object_ref.object_type.name, title) if title else None, ), href=url, )
def render(self, what, row, tags, custom_vars): url_vars = [ ('host', row['host_name']), ] if row.get('site'): url_vars.append(('site', row['site'])) if what == 'service': url_vars.append(('service', row['service_description'])) if html.request.has_var('display_options'): url_vars.append( ('display_options', html.request.var('display_options'))) if html.request.has_var('_display_options'): url_vars.append( ('_display_options', html.request.var('_display_options'))) url_vars.append(('_back_url', makeuri(request, []))) return html.render_popup_trigger( html.render_icon('menu', _('Open the action menu'), cssclass="iconbutton"), 'action_menu', MethodAjax(endpoint='action_menu', url_vars=url_vars), )
def render_metrics_table(translated_metrics, host_name, service_description): output = "<table class=metricstable>" for metric_name, metric in sorted(translated_metrics.items(), key=lambda x: x[1]["title"]): output += "<tr>" output += "<td class=color>%s</td>" % render_color_icon( metric["color"]) output += "<td>%s:</td>" % metric["title"] output += "<td class=value>%s</td>" % metric["unit"]["render"]( metric["value"]) if cmk_graphs_possible(): output += "<td>" output += html.render_popup_trigger( html.render_icon("custom_graph", title=_("Add this metric to dedicated graph"), cssclass="iconbutton"), ident="add_metric_to_graph_" + host_name + ";" + service_description, what="add_metric_to_graph", url_vars=[ ("host", host_name), ("service", service_description), ("metric", metric_name), ]) output += "</td>" output += "</tr>" output += "</table>" return output
def render_metrics_table(translated_metrics, host_name, service_description): # type: (TranslatedMetrics, str, str) -> str # TODO: Don't paste together strings by hand, use our HTML utilities. output = "<table class=metricstable>" for metric_name, metric in sorted(translated_metrics.items(), key=lambda x: x[1]["title"]): output += "<tr>" output += "<td class=color>%s</td>" % render_color_icon(metric["color"]) output += "<td>%s:</td>" % metric["title"] output += "<td class=value>%s</td>" % metric["unit"]["render"](metric["value"]) if not cmk_version.is_raw_edition(): output += "<td>" output += str( html.render_popup_trigger( html.render_icon("custom_graph", title=_("Add this metric to dedicated graph"), cssclass="iconbutton"), ident="add_metric_to_graph_" + host_name + ";" + str(service_description), what="add_metric_to_graph", url_vars=[ ("host", host_name), ("service", service_description), ("metric", metric_name), ])) output += "</td>" output += "</tr>" output += "</table>" return output
def _pnp_icon(self, row, what): url = self._pnp_graph_icon_link(row, what) if not metrics.cmk_graphs_possible(row["site"]): # Directly ask PNP for all data, don't try to use the new graph fetching mechanism # to keep the number of single requests low force_pnp_graphing = True else: # Don't show the icon with Check_MK graphing. The hover makes no sense and there is no # mobile view for graphs, so the graphs on the bottom of the host/service view are enough # for the moment. if html.is_mobile(): return force_pnp_graphing = False return html.render_a( content=html.render_icon('pnp', ''), href=url, onmouseout="cmk.hover.hide()", onmouseover= "cmk.graph_integration.show_hover_graphs(event, %s, %s, %s, %s, %s);" % ( json.dumps(row['site']), json.dumps(row["host_name"]), json.dumps(row.get('service_description', '_HOST_')), json.dumps(self._pnp_popup_url(row, what)), json.dumps(force_pnp_graphing), ))
def _show_content(self, page_state: PageState) -> None: html.div(page_state.text, class_="text_container") if page_state.icon_name: html.div( html.render_icon(page_state.icon_name, id_="page_state_icon"), class_="icon_container", )
def _show_move_to_folder_action(self, obj): if isinstance(obj, watolib.Host): what = "host" what_title = _("host") ident = obj.name() style = None else: what = "folder" what_title = _("folder") ident = obj.path() style = "display:none" html.popup_trigger( html.render_icon("move", title=_("Move this %s to another folder") % what_title, cssclass="iconbutton"), ident="move_" + obj.name(), what="move_to_folder", url_vars=[ ("what", what), ("ident", ident), ("back_url", html.makeactionuri([])), ], style=style, )
def page(self) -> None: html.p( _("Here you can add icons, for example to use them in bookmarks or " "in custom actions of views. Allowed are single PNG image files " "with a maximum size of 80x80 px. Custom actions have to be defined " "in the global settings and can be used in the custom icons rules " "of hosts and services.")) html.begin_form('upload_form', method='POST') self._vs_upload().render_input('_upload_icon', None) html.hidden_fields() html.end_form() icons = sorted(self._load_custom_icons().items()) with table_element("icons", _("Custom Icons")) as table: for icon_name, category_name in icons: table.row() table.cell(_("Actions"), css="buttons") delete_url = make_confirm_link( url=make_action_link([("mode", "icons"), ("_delete", icon_name)]), message=_( "Do you really want to delete the icon <b>%s</b>?") % icon_name, ) html.icon_button(delete_url, _("Delete this Icon"), "delete") table.cell(_("Icon"), html.render_icon(icon_name), css="buttons") table.cell(_("Name"), icon_name) table.cell(_("Category"), IconSelector.category_alias(category_name))
def render(self, what, row, tags, custom_vars): url_vars = [ ("host", row["host_name"]), ] if row.get("site"): url_vars.append(("site", row["site"])) if what == "service": url_vars.append(("service", row["service_description"])) if request.has_var("display_options"): url_vars.append( ("display_options", request.var("display_options"))) if request.has_var("_display_options"): url_vars.append( ("_display_options", request.var("_display_options"))) url_vars.append(("_back_url", makeuri(request, []))) return html.render_popup_trigger( html.render_icon("menu", _("Open the action menu"), cssclass="iconbutton"), "action_menu", MethodAjax(endpoint="action_menu", url_vars=url_vars), )
def render(self, what, row, tags, custom_vars): img = row[what + '_icon_image'] if not img: return if img.endswith('.png'): img = img[:-4] return html.render_icon(img)
def _show_main_menu_content(self) -> None: html.open_li() html.popup_trigger( html.render_icon("main_search") + html.render_div(_("Search")), "mega_menu_search", method=MethodInline(self._get_search_menu_content()), ) html.close_li() for menu_item in self._get_main_menu_items(): html.open_li() html.popup_trigger( html.render_icon(menu_item.icon_name) + html.render_div(menu_item.title), ident="mega_menu_" + menu_item.name, method=MethodInline(self._get_mega_menu_content(menu_item)), cssclass=menu_item.name, ) html.close_li()
def DocumentationURL(): return TextAscii( title=_("Documentation URL"), help=HTML( _("An optional URL pointing to documentation or any other page. This will be displayed " "as an icon %s and open a new page when clicked. " "You can use either global URLs (beginning with <tt>http://</tt>), absolute local urls " "(beginning with <tt>/</tt>) or relative URLs (that are relative to <tt>check_mk/</tt>)." ) % html.render_icon("url")), size=80, )
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(" ") if tree[2].get("docu_url"): html.icon_button( tree[2]["docu_url"], _("Context information about this rule"), "url", target="_blank", ) html.write_text(" ") 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()
def page(self): if not self._folder.may("read"): html.show_message( html.render_icon("autherr", cssclass="authicon") + " " + self._folder.reason_why_may_not("read")) self._folder.show_locking_information() self._show_subfolders_of() if self._folder.may("read"): self._show_hosts() if not self._folder.has_hosts(): if self._folder.is_search_folder(): html.show_message(_("No matching hosts found.")) elif not self._folder.has_subfolders() and self._folder.may("write"): self._show_empty_folder_menu()
def render_graph_add_to_icon_for_popup(graph_artwork, graph_data_range, graph_render_options): icon_html = html.render_icon('menu', _('Add this graph to...')) element_type_name = "pnpgraph" # Data will be transferred via URL and Javascript magic eventually # to our function popup_add_element (htdocs/reporting.py) # argument report_name --> provided by popup system # further arguments: return html.render_popup_trigger( content=icon_html, ident='add_visual', method=MethodAjax(endpoint='add_visual', url_vars=[("add_type", "pnpgraph")]), data=[ element_type_name, None, graph_ajax_context(graph_artwork, graph_data_range, graph_render_options) ], style="z-index:2") # Ensures that graph canvas does not cover it
def _pnp_icon(self, row, what): url = self._graph_icon_link(row, what) # Don't show the icon with Checkmk graphing. The hover makes no sense and there is no # mobile view for graphs, so the graphs on the bottom of the host/service view are enough # for the moment. if html.is_mobile(): return return html.render_a( content=html.render_icon('graph', ''), href=url, onmouseout="cmk.hover.hide()", onmouseover="cmk.graph_integration.show_hover_graphs(event, %s, %s, %s);" % ( json.dumps(row['site']), json.dumps(row["host_name"]), json.dumps(row['service_description'] if what == "service" else '_HOST_'), ))
def render_list(ids, links): n = 0 for entry in links: n += 1 try: if isinstance(entry[1], type(True)): idss = ids + [str(n)] id_ = '/'.join(idss) html.begin_foldable_container("customlinks", id_, isopen=entry[1], title=entry[0], icon="foldable_sidebar") render_list(idss, entry[2]) html.end_foldable_container() elif isinstance(entry[1], str): frame = entry[3] if len(entry) > 3 else "main" if len(entry) > 2 and entry[2]: icon_file = entry[2] # Old configs used files named "link_<name>.gif". Those .gif files have # been removed from Checkmk. Replacing such images with the default icon if icon_file.endswith(".gif"): icon_name = "link" else: icon_name = icon_file.rsplit(".", 1)[0].replace( "icon_", "") else: icon_name = "link" linktext = HTML( html.render_icon(icon_name) + " " + entry[0]) simplelink(linktext, entry[1], frame) else: html.write_text( _("Second part of tuple must be list or string, not %s\n" ) % str(entry[1])) except Exception as e: html.write_text( _("invalid entry %s: %s<br>\n") % (entry, e))
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) )
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) html.open_div(id_="popup_%s" % entry.name, class_=["page_menu_popup"] + html.normalize_css_spec(entry.item.css_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() html.open_div(class_="content") html.write(HTML(entry.item.content)) html.close_div() html.close_div()
def _show_host_row(self, rendered_hosts, table, hostname, search_text, show_checkboxes, colspan, host_errors, contact_group_names): if search_text and (search_text.lower() not in hostname.lower()): return host = self._folder.host(hostname) rendered_hosts.append(hostname) effective = host.effective_attributes() table.row() # Column with actions (buttons) if show_checkboxes: table.cell(html.render_input( "_toggle_group", type_="button", class_="checkgroup", onclick="cmk.selection.toggle_all_rows();", value='X'), sortable=False, css="checkbox") # Use CSS class "failed" in order to provide information about # selective toggling inventory-failed hosts for Javascript html.input(name="_c_%s" % hostname, type_="checkbox", value=colspan, class_="failed" if host.discovery_failed() else None) html.label("", "_c_%s" % hostname) table.cell(_("Actions"), css="buttons", sortable=False) self._show_host_actions(host) # Hostname with link to details page (edit host) table.cell(_("Hostname")) errors = host_errors.get(hostname, []) + host.validation_errors() if errors: msg = _("Warning: This host has an invalid configuration: ") msg += ", ".join(errors) html.icon(msg, "validation_error") html.nbsp() if host.is_offline(): html.icon(_("This host is disabled"), "disabled") html.nbsp() if host.is_cluster(): html.icon( _("This host is a cluster of %s") % ", ".join(host.cluster_nodes()), "cluster") html.nbsp() html.a(hostname, href=host.edit_url()) # Show attributes for attr in host_attribute_registry.attributes(): if attr.show_in_table(): attrname = attr.name() if attrname in host.attributes(): tdclass, tdcontent = attr.paint( host.attributes()[attrname], hostname) else: tdclass, tdcontent = attr.paint(effective.get(attrname), hostname) tdclass += " inherited" table.cell(attr.title(), escaping.escape_attribute(tdcontent), css=tdclass) # Am I authorized? reason = host.reason_why_may_not("read") if not reason: icon = "authok" title = _("You have permission to this host.") else: icon = "autherr" title = escaping.strip_tags(reason) table.cell(_('Auth'), html.render_icon(icon, title), css="buttons", sortable=False) # Permissions and Contact groups - through complete recursion and inhertance permitted_groups, host_contact_groups, _use_for_services = host.groups( ) table.cell( _("Permissions"), HTML(", ").join([ self._render_contact_group(contact_group_names, g) for g in permitted_groups ])) table.cell( _("Contact Groups"), HTML(", ").join([ self._render_contact_group(contact_group_names, g) for g in host_contact_groups ])) if not config.wato_hide_hosttags: table.cell(_("Tags"), css="tag-ellipsis") tag_groups, show_all_code = self._limit_labels(host.tag_groups()) html.write( cmk.gui.view_utils.render_tag_groups(tag_groups, "host", with_links=False)) html.write(show_all_code) table.cell(_("Explicit labels"), css="tag-ellipsis") labels, show_all_code = self._limit_labels(host.labels()) html.write( cmk.gui.view_utils.render_labels( labels, "host", with_links=False, label_sources={k: "explicit" for k in labels.keys()})) html.write(show_all_code) # Located in folder if self._folder.is_search_folder(): table.cell(_("Folder")) html.a(host.folder().alias_path(), href=host.folder().url())