def _show_leaf(self, tree, show_host): site, host = tree[2]["host"] service = tree[2].get("service") # Four cases: # (1) zbghora17 . Host status (show_host == True, service is None) # (2) zbghora17 . CPU load (show_host == True, service is not None) # (3) Host Status (show_host == False, service is None) # (4) CPU load (show_host == False, service is not None) if show_host or not service: host_url = makeuri_contextless( request, [("view_name", "hoststatus"), ("site", site), ("host", host)], filename="view.py", ) if service: service_url = makeuri_contextless( request, [("view_name", "service"), ("site", site), ("host", host), ("service", service)], filename="view.py", ) with self._show_node(tree, show_host): self._assume_icon(site, host, service) if show_host: html.a(host.replace(" ", " "), href=host_url) html.b(HTML("♦"), class_="bullet") if not service: html.a(_("Host status"), href=host_url) else: html.a(service.replace(" ", " "), href=service_url)
def page(self): header = self._manpage["header"] html.open_table(class_=["data", "headerleft"]) html.open_tr() html.th(_("Title")) html.open_td() html.b(header["title"]) html.close_td() html.close_tr() html.open_tr() html.th(_("Name of plugin")) html.open_td() html.tt(self._check_type) html.close_td() html.close_tr() html.open_tr() html.th(_("Description")) html.td(self._manpage_text(header["description"])) html.close_tr() if self._manpage["type"] == "check_mk": html.open_tr() html.th(_("Service name")) html.td( HTML(self._manpage["service_description"].replace( "%s", "☐"))) html.close_tr() discovery = header.get("discovery") or header.get("inventory") if discovery: html.open_tr() html.th(_("Discovery")) html.td(self._manpage_text(discovery)) html.close_tr() check_ruleset_name = self._manpage.get("check_ruleset_name") if check_ruleset_name is not None: self._show_ruleset("checkgroup_parameters:%s" % check_ruleset_name) cluster = header.get("cluster") if cluster: html.open_tr() html.th(_("Cluster behaviour")) html.td(self._manpage_text(cluster)) html.close_tr() else: self._show_ruleset("active_checks:%s" % self._check_type[6:]) html.close_table()
def render_werk_description(werk) -> HTML: with output_funnel.plugged(): html.open_p() in_list = False in_code = False for line in werk["body"]: if line.startswith("LI:"): if not in_list: html.open_ul() in_list = True html.li(line[3:]) else: if in_list: html.close_ul() in_list = False if line.startswith("H2:"): html.h3(line[3:]) elif line.startswith("C+:"): html.open_pre(class_="code") in_code = True elif line.startswith("F+:"): file_name = line[3:] if file_name: html.div(file_name, class_="filename") html.open_pre(class_="file") in_code = True elif line.startswith("C-:") or line.startswith("F-:"): html.close_pre() in_code = False elif line.startswith("OM:"): html.write_text("OMD[mysite]:~$ ") html.b(line[3:]) elif line.startswith("RP:"): html.write_text("root@myhost:~# ") html.b(line[3:]) elif not line.strip() and not in_code: html.p("") else: html.write_text(line + "\n") if in_list: html.close_ul() html.close_p() return HTML(output_funnel.drain())
def page(self): html.open_table(class_=["data", "headerleft"]) html.open_tr() html.th(_("Title")) html.open_td() html.b(self._manpage["header"]["title"]) html.close_td() html.close_tr() html.open_tr() html.th(_("Name of plugin")) html.open_td() html.tt(self._check_type) html.close_td() html.close_tr() html.open_tr() html.th(_("Description")) html.td(self._manpage_text(self._manpage["header"]["description"])) html.close_tr() if self._manpage["type"] == "check_mk": html.open_tr() html.th(_("Service name")) html.td( HTML(self._manpage["service_description"].replace( "%s", "☐"))) html.close_tr() if self._manpage.get("group"): group = self._manpage["group"] varname = "checkgroup_parameters:" + group self._show_ruleset(varname) else: varname = "active_checks:" + self._check_type[6:] self._show_ruleset(varname) html.close_table()
def page(self): # Show outcome of host validation. Do not validate new hosts errors = None if self._mode == "edit": errors = (watolib.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 = watolib.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=watolib.Folder.current(), basic_attributes=basic_attributes, ) if self._mode != "edit": html.set_focus("host") forms.end() html.hidden_fields() html.end_form()
def render_snapin(self, snapin: UserSidebarSnapin) -> str: snapin_class = snapin.snapin_type name = snapin_class.type_name() snapin_instance = snapin_class() html.open_div(id_="snapin_container_%s" % name, class_="snapin") self._render_snapin_styles(snapin_instance) # When not permitted to open/close snapins, the snapins are always opened if snapin.visible == SnapinVisibility.OPEN or not config.user.may( "general.configure_sidebar"): style = None else: style = "display:none" toggle_url = "sidebar_openclose.py?name=%s&state=" % name # If the user may modify the sidebar then add code for dragging the snapin head_actions: Dict[str, str] = {} if config.user.may("general.configure_sidebar"): head_actions = { "onmouseover": "document.body.style.cursor='move';", "onmouseout ": "document.body.style.cursor='';", "onmousedown": "cmk.sidebar.snapin_start_drag(event)", "onmouseup": "cmk.sidebar.snapin_stop_drag(event)" } html.open_div(class_=["head", snapin.visible.value], **head_actions) if config.user.may("general.configure_sidebar"): # Icon for mini/maximizing html.div("", class_="minisnapin", title=_("Toggle this snapin"), onclick="cmk.sidebar.toggle_sidebar_snapin(this, '%s')" % toggle_url) # Button for closing (removing) a snapin html.open_div(class_="closesnapin") close_url = "sidebar_openclose.py?name=%s&state=off" % name html.icon_button( url=None, title=_("Remove this snapin"), icon="closesnapin", onclick="cmk.sidebar.remove_sidebar_snapin(this, '%s')" % close_url) html.close_div() # The heading. A click on the heading mini/maximizes the snapin toggle_actions: Dict[str, str] = {} if config.user.may("general.configure_sidebar"): toggle_actions = { "onclick": "cmk.sidebar.toggle_sidebar_snapin(this,'%s')" % toggle_url, "onmouseover": "this.style.cursor='pointer'", "onmouseout": "this.style.cursor='auto'" } html.b(snapin_class.title(), class_=["heading"], **toggle_actions) # End of header html.close_div() # Now comes the content html.open_div(class_="content", id_="snapin_%s" % name, style=style) refresh_url = '' try: # TODO: Refactor this confusing special case. Add deddicated method or something # to let the snapins make the sidebar know that there is a URL to fetch. url = snapin_instance.show() if url is not None: # Fetch the contents from an external URL. Don't render it on our own. refresh_url = url html.javascript( "cmk.ajax.get_url(\"%s\", cmk.utils.update_contents, \"snapin_%s\")" % (refresh_url, name)) except Exception as e: logger.exception("error rendering snapin %s", name) write_snapin_exception(e) html.close_div() html.close_div() return refresh_url
def _rename_tags_after_confirmation(operation): # type: (ABCOperation) -> Union[bool, str] """Handle renaming and deletion of tags Find affected hosts, folders and rules. Remove or fix those rules according the users' wishes. """ repair_mode = html.request.var("_repair") if repair_mode is not None: try: mode = TagCleanupMode(repair_mode) except ValueError: raise MKUserError("_repair", "Invalid mode") if mode == TagCleanupMode.ABORT: raise MKUserError("id_0", _("Aborting change.")) # make attribute unknown to system, important for save() operations if isinstance(operation, OperationRemoveTagGroup): watolib.host_attributes.undeclare_host_tag_attribute( operation.tag_group_id) affected_folders, affected_hosts, affected_rulesets = \ _change_host_tags_in_folders(operation, mode, watolib.Folder.root_folder()) return _("Modified folders: %d, modified hosts: %d, modified rulesets: %d") % \ (len(affected_folders), len(affected_hosts), len(affected_rulesets)) message = u"" affected_folders, affected_hosts, affected_rulesets = \ _change_host_tags_in_folders(operation, TagCleanupMode.CHECK, watolib.Folder.root_folder()) if affected_folders: message += _("Affected folders with an explicit reference to this tag " "group and that are affected by the change") + ":" with html.plugged(): _show_affected_folders(affected_folders) message += html.drain() if affected_hosts: message += _("Hosts where this tag group is explicitely set " "and that are effected by the change") + ":" with html.plugged(): _show_affected_hosts(affected_hosts) message += html.drain() if affected_rulesets: message += _( "Rulesets that contain rules with references to the changed tags" ) + ":" with html.plugged(): _show_affected_rulesets(affected_rulesets) message += html.drain() if message: wato_html_head(operation.confirm_title()) html.open_div(class_="really") html.h3(_("Your modifications affect some objects")) html.write_text(message) html.br() html.write_text( _("WATO can repair things for you. It can rename tags in folders, host and rules. " "Removed tag groups will be removed from hosts and folders, removed tags will be " "replaced with the default value for the tag group (for hosts and folders). What " "rules concern, you have to decide how to proceed.")) html.begin_form("confirm", method="POST") if affected_rulesets and _is_removing_tags(operation): html.br() html.b( _("Some tags that are used in rules have been removed by you. What " "shall we do with that rules?")) html.open_ul() html.radiobutton( "_repair", "remove", True, _("Just remove the affected tags from the rules.")) html.br() html.radiobutton( "_repair", "delete", False, _("Delete rules containing tags that have been removed, if tag is used in a positive sense. Just remove that tag if it's used negated." )) else: html.open_ul() html.radiobutton("_repair", "repair", True, _("Fix affected folders, hosts and rules.")) html.br() html.radiobutton("_repair", "abort", False, _("Abort your modifications.")) html.close_ul() html.button("_do_confirm", _("Proceed"), "") html.hidden_fields(add_action_vars=True) html.end_form() html.close_div() return False return True
def _show_node(self, tree, show_host, mousecode=None, img_class=None): # Check if we have an assumed state: comparing assumed state (tree[1]) with state (tree[0]) if tree[1] and tree[0] != tree[1]: addclass: Optional[str] = "assumed" effective_state = tree[1] else: addclass = None effective_state = tree[0] class_: List[Optional[str]] = [ "content", # "state", "state%d" % (effective_state["state"] if effective_state["state"] is not None else -1), addclass, ] html.open_span(class_=class_) html.write_text(self._render_bi_state(effective_state["state"])) html.close_span() if mousecode: if img_class: html.img( src=theme.url("images/tree_closed.svg"), class_=["treeangle", img_class], onclick=mousecode, ) html.open_span(class_=["content", "name"]) icon_name, icon_title = None, None if tree[0]["in_downtime"] == 2: icon_name = "downtime" icon_title = _("This element is currently in a scheduled downtime.") elif tree[0]["in_downtime"] == 1: # only display host downtime if the service has no own downtime icon_name = "derived_downtime" icon_title = _("One of the subelements is in a scheduled downtime.") if tree[0]["acknowledged"]: icon_name = "ack" icon_title = _("This problem has been acknowledged.") if not tree[0]["in_service_period"]: icon_name = "outof_serviceperiod" icon_title = _("This element is currently not in its service period.") if icon_name and icon_title: html.icon(icon_name, title=icon_title, class_=["icon", "bi"]) yield if mousecode: if str(effective_state["state"]) in tree[2].get("state_messages", {}): html.b(HTML("♦"), class_="bullet") html.write_text(tree[2]["state_messages"][str(effective_state["state"])]) html.close_span() output: HTML = cmk.gui.view_utils.format_plugin_output( effective_state["output"], shall_escape=config.escape_plugin_output ) if output: output = html.render_b(HTML("♦"), class_="bullet") + output else: output = HTML() html.span(output, class_=["content", "output"])
def _rename_tags_after_confirmation(tag_id, operations): """Handle renaming and deletion of tags Find affected hosts, folders and rules. Remove or fix those rules according the the users' wishes. In case auf auxiliary tags the tag_id is None. In other cases it is the id of the tag group currently being edited. """ mode = html.request.var("_repair") if mode == "abort": raise MKUserError("id_0", _("Aborting change.")) elif mode: # make attribute unknown to system, important for save() operations if tag_id and isinstance(operations, list): watolib.host_attributes.undeclare_host_tag_attribute(tag_id) affected_folders, affected_hosts, affected_rulesets = \ _change_host_tags_in_folders(tag_id, operations, mode, watolib.Folder.root_folder()) return _("Modified folders: %d, modified hosts: %d, modified rulesets: %d") % \ (len(affected_folders), len(affected_hosts), len(affected_rulesets)) message = "" affected_folders, affected_hosts, affected_rulesets = \ _change_host_tags_in_folders(tag_id, operations, "check", watolib.Folder.root_folder()) if affected_folders: message += _("Affected folders with an explicit reference to this tag " "group and that are affected by the change") + ":<ul>" for folder in affected_folders: message += '<li><a href="%s">%s</a></li>' % (folder.edit_url(), folder.alias_path()) message += "</ul>" if affected_hosts: message += _("Hosts where this tag group is explicitely set " "and that are effected by the change") + ":<ul><li>" for nr, host in enumerate(affected_hosts): if nr > 20: message += "... (%d more)" % (len(affected_hosts) - 20) break elif nr > 0: message += ", " message += '<a href="%s">%s</a>' % (host.edit_url(), host.name()) message += "</li></ul>" if affected_rulesets: message += _("Rulesets that contain rules with references to the changed tags") + ":<ul>" for ruleset in affected_rulesets: message += '<li><a href="%s">%s</a></li>' % (watolib.folder_preserving_link( [("mode", "edit_ruleset"), ("varname", ruleset.name)]), ruleset.title()) message += "</ul>" if not message and isinstance(operations, tuple): # deletion of unused tag group html.open_div(class_="really") html.begin_form("confirm") html.write_text(_("Please confirm the deletion of the tag group.")) html.button("_abort", _("Abort")) html.button("_do_confirm", _("Proceed")) html.hidden_fields(add_action_vars=True) html.end_form() html.close_div() elif message: if isinstance(operations, list): wato_html_head(_("Confirm tag deletion")) else: wato_html_head(_("Confirm tag modifications")) html.open_div(class_="really") html.h3(_("Your modifications affect some objects")) html.write_text(message) html.br() html.write_text( _("WATO can repair things for you. It can rename tags in folders, host and rules. " "Removed tag groups will be removed from hosts and folders, removed tags will be " "replaced with the default value for the tag group (for hosts and folders). What " "rules concern, you have to decide how to proceed.")) html.begin_form("confirm") # Check if operations contains removal if isinstance(operations, list): have_removal = True else: have_removal = False for new_val in operations.values(): if not new_val: have_removal = True break if affected_rulesets and have_removal: html.br() html.b( _("Some tags that are used in rules have been removed by you. What " "shall we do with that rules?")) html.open_ul() html.radiobutton("_repair", "remove", True, _("Just remove the affected tags from the rules.")) html.br() html.radiobutton( "_repair", "delete", False, _("Delete rules containing tags that have been removed, if tag is used in a positive sense. Just remove that tag if it's used negated." )) else: html.open_ul() html.radiobutton("_repair", "repair", True, _("Fix affected folders, hosts and rules.")) html.br() html.radiobutton("_repair", "abort", False, _("Abort your modifications.")) html.close_ul() html.button("_do_confirm", _("Proceed"), "") html.hidden_fields(add_action_vars=True) html.end_form() html.close_div() return False return True
def page(self): # Show outcome of host validation. Do not validate new hosts errors = None if self._mode != "edit": watolib.Folder.current().show_breadcrump() else: errors = watolib.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(title=None, 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 = "" if watolib.Folder.current().locked_hosts(): if watolib.Folder.current().locked_hosts() is True: lock_message = _( "Host attributes locked (You cannot edit this host)") else: lock_message = watolib.Folder.current().locked_hosts() if len(lock_message) > 0: html.div(lock_message, class_="info") html.begin_form("edit_host", method="POST") html.prevent_password_auto_completion() forms.header(_("General Properties")) self._show_host_name() # Cluster: nodes if self._is_cluster(): forms.section(_("Nodes")) self._vs_cluster_nodes().render_input( "nodes", self._host.cluster_nodes() if self._host else []) html.help( _('Enter the host names of the cluster nodes. These ' 'hosts must be present in WATO. ')) 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=watolib.Folder.current()) forms.end() if not watolib.Folder.current().locked_hosts(): html.button("services", _("Save & go to Services"), "submit") html.button("save", _("Save & Finish"), "submit") if not self._is_cluster(): html.button("diag_host", _("Save & Test"), "submit") html.hidden_fields() html.end_form()