def render_unacknowleged_werks(): werks = unacknowledged_incompatible_werks() if werks and not request.has_var("show_unack"): html.open_div(class_=["warning"]) html.write_text( _("<b>Warning:</b> There are %d unacknowledged incompatible werks:" ) % len(werks)) html.br() html.br() html.a( _("Show unacknowledged incompatible werks"), href=makeuri_contextless(request, [("show_unack", "1"), ("wo_compatibility", "3")]), ) html.close_div()
def page(self): html.begin_form("random") forms.header(_("Add random hosts")) forms.section(_("Number to create")) html.write_text("%s: " % _("Hosts to create in each folder")) html.text_input("count", default_value="10", cssclass="number") html.set_focus("count") html.br() html.write_text("%s: " % _("Number of folders to create in each level")) html.text_input("folders", default_value="10", cssclass="number") html.br() html.write_text("%s: " % _("Levels of folders to create")) html.text_input("levels", default_value="1", cssclass="number") forms.end() html.hidden_fields() html.end_form()
def _show_tree_selection(self): html.begin_form("vtree") html.dropdown( "vtree", self._tree_choices(), deflt="%s" % self._current_tree_id, onchange="virtual_host_tree_changed(this)", style="width:210px" if self._current_tree_path else None, ) # Give chance to change one level up, if we are in a subtree if self._current_tree_path: upurl = "javascript:virtual_host_tree_enter('%s')" % "|".join( self._current_tree_path[:-1]) html.icon_button(upurl, _("Go up one tree level"), "back") html.br() html.end_form() html.final_javascript(self._javascript())
def display(self, value: FilterHTTPVariables) -> None: html.text_input(self._varprefix + "name") html.br() display_filter_radiobuttons( varname=self._varprefix + "match", options=[ ("exact", _("exact match")), ("regex", _("regular expression, substring match")), ], default="exact", value=value, ) html.br() html.open_span(class_="min_max_row") html.write_text(_("Min. Version: ")) html.text_input( self._varprefix + "version_from", default_value=value.get(self._varprefix + "version_from", ""), size=9, ) html.write_text(" ") html.write_text(_("Max. Vers.: ")) html.text_input( self._varprefix + "version_to", default_value=value.get(self._varprefix + "version_from", ""), size=9, ) html.close_span() html.br() html.checkbox( self._varprefix + "negate", False, label=_("Negate: find hosts <b>not</b> having this package"), )
def page_login() -> None: title = _("Checkmk Mobile") mobile_html_head(title) jqm_page_header(title, id_="login") html.div(_("Welcome to Checkmk Mobile."), id_="loginhead") html.begin_form("login", method="POST", add_transid=False) # Keep information about original target URL default_origtarget = ( "index.py" if requested_file_name(request) in ["login", "logout"] else makeuri(request, []) ) origtarget = request.get_url_input("_origtarget", default_origtarget) html.hidden_field("_origtarget", escaping.escape_attribute(origtarget)) html.text_input("_username", label=_("Username:"******"username", id_="input_user") html.password_input( "_password", size=None, label=_("Password:"******"current-password", id_="input_pass", ) html.br() html.button("_login", _("Login")) html.set_focus("_username") html.end_form() html.open_div(id_="loginfoot") html.img("themes/facelift/images/logo_cmk_small.png", class_="logomk") html.div( HTML(_('© <a target="_blank" href="https://checkmk.com">tribe29 GmbH</a>')), class_="copyright", ) html.close_div() # close content-div html.close_div() html.close_div() # close page-div mobile_html_foot()
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_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 = HTMLWriter.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)
def _rename_tags_after_confirmation( breadcrumb: Breadcrumb, operation: 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. Returns: True: Proceed, no "question" dialog shown False: "Question dialog" shown str: Action done after "question" dialog """ repair_mode = 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): undeclare_host_tag_attribute(operation.tag_group_id) affected_folders, affected_hosts, affected_rulesets = change_host_tags_in_folders( operation, mode, Folder.root_folder()) return _( "Modified folders: %d, modified hosts: %d, modified rulesets: %d" ) % ( len(affected_folders), len(affected_hosts), len(affected_rulesets), ) message = HTML() affected_folders, affected_hosts, affected_rulesets = change_host_tags_in_folders( operation, TagCleanupMode.CHECK, Folder.root_folder()) if affected_folders: with output_funnel.plugged(): html.write_text( _("Affected folders with an explicit reference to this tag " "group and that are affected by the change") + ":") _show_affected_folders(affected_folders) message += HTML(output_funnel.drain()) if affected_hosts: with output_funnel.plugged(): html.write_text( _("Hosts where this tag group is explicitely set " "and that are effected by the change") + ":") _show_affected_hosts(affected_hosts) message += HTML(output_funnel.drain()) if affected_rulesets: with output_funnel.plugged(): html.write_text( _("Rulesets that contain rules with references to the changed tags" ) + ":") _show_affected_rulesets(affected_rulesets) message += HTML(output_funnel.drain()) if message: wato_html_head(title=operation.confirm_title(), breadcrumb=breadcrumb) html.open_div(class_="really") html.h3(_("Your modifications affect some objects")) html.write_text(message) html.br() html.write_text( _("Setup 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 iconlink(text: str, url: str, icon: Icon) -> None: html.open_a(class_=["iconlink", "link"], target="main", href=url) html.icon(icon, cssclass="inline") html.write_text(text) html.close_a() html.br()
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()
class UserLoginTwoFactor(Page): def page(self) -> None: assert user.id is not None html.render_headfoot = False html.add_body_css_class("login") html.add_body_css_class("two_factor") make_header(html, _("Two-factor authentication"), Breadcrumb(), javascripts=[]) html.open_div(id_="login") html.open_div(id_="login_window") html.open_a(href="https://checkmk.com") html.img( src=theme.detect_icon_path(icon_name="logo", prefix="mk-"), id_="logo", class_="custom" if theme.has_custom_logo() else None, ) html.close_a() if not is_two_factor_login_enabled(user.id): raise MKGeneralException( _("Two-factor authentication not enabled")) html.begin_form("two_factor_login", method="POST", add_transid=False, action="user_login_two_factor.py") html.prevent_password_auto_completion() html.hidden_field( "_origtarget", origtarget := request.get_url_input("_origtarget", "index.py")) if backup_code := request.get_ascii_input("_backup_code"): if is_two_factor_backup_code_valid(user.id, backup_code): set_two_factor_completed() raise HTTPRedirect(origtarget) html.label( _("Two-factor authentication"), for_="webauthn_message", id_="label_2fa", class_="legend", ) html.div("", id_="webauthn_message") with foldable_container( treename="webauthn_backup_codes", id_="backup_container", isopen=False, title=_("Use backup code"), indent=False, save_state=False, ): html.label( "%s:" % _("Backup code"), id_="label_pass", class_=["legend"], for_="_backup_code", ) html.br() html.password_input("_backup_code", id_="input_pass", size=None) html.open_div(id_="button_text") html.button("_use_backup_code", _("Use backup code"), cssclass="hot") html.close_div() html.close_div() if user_errors: html.open_div(id_="login_error") html.show_user_errors() html.close_div() html.javascript("cmk.webauthn.login()") html.hidden_fields() html.end_form() html.close_div() html.footer()
def render_input(self, varprefix: str, value: Any) -> None: value = convert_cgroups_from_tuple(value) # If we're just editing a host, then some of the checkboxes will be missing. # This condition is not very clean, but there is no other way to savely determine # the context. is_host = bool(request.var("host")) or request.var("mode") == "newhost" is_search = varprefix == "host_search" # Only show contact groups I'm currently in and contact # groups already listed here. self.load_data() self._vs_contactgroups().render_input(varprefix + self.name(), value["groups"]) html.hr() if is_host: html.checkbox( varprefix + self.name() + "_use", value["use"], label=_("Add these contact groups to the host"), ) elif not is_search: html.checkbox( varprefix + self.name() + "_recurse_perms", value["recurse_perms"], label=_( "Give these groups also <b>permission on all subfolders</b>" ), ) html.hr() html.checkbox( varprefix + self.name() + "_use", value["use"], label= _("Add these groups as <b>contacts</b> to all hosts <b>in this folder</b>" ), ) html.br() html.checkbox( varprefix + self.name() + "_recurse_use", value["recurse_use"], label= _("Add these groups as <b>contacts</b> to all hosts <b>in all subfolders of this folder</b>" ), ) html.hr() html.help( _("With this option contact groups that are added to hosts are always " "being added to services, as well. This only makes a difference if you have " "assigned other contact groups to services via rules in <i>Host & Service Parameters</i>. " "As long as you do not have any such rule a service always inherits all contact groups " "from its host.")) html.checkbox( varprefix + self.name() + "_use_for_services", value.get("use_for_services", False), label=_("Always add host contact groups also to its services") if is_host else _("Always add these groups as <b>contacts</b> to all services <b>in all subfolders of this folder</b>" ), )
def _output_analysed_ruleset(self, all_rulesets, rulespec, svc_desc_or_item, svc_desc, known_settings=None): if known_settings is None: known_settings = self._PARAMETERS_UNKNOWN def rule_url(rule: Rule) -> str: return folder_preserving_link([ ("mode", "edit_rule"), ("varname", varname), ("rule_folder", rule.folder.path()), ("rule_id", rule.id), ("host", self._hostname), ( "item", mk_repr(svc_desc_or_item).decode() if svc_desc_or_item else "", ), ("service", mk_repr(svc_desc).decode() if svc_desc else ""), ]) varname = rulespec.name valuespec = rulespec.valuespec url = folder_preserving_link([ ("mode", "edit_ruleset"), ("varname", varname), ("host", self._hostname), ("item", mk_repr(svc_desc_or_item).decode()), ("service", mk_repr(svc_desc).decode()), ]) forms.section(HTMLWriter.render_a(rulespec.title, url)) ruleset = all_rulesets.get(varname) setting, rules = ruleset.analyse_ruleset(self._hostname, svc_desc_or_item, svc_desc) html.open_table(class_="setting") html.open_tr() html.open_td(class_="reason") # Show reason for the determined value if len(rules) == 1: rule_folder, rule_index, rule = rules[0] url = rule_url(rule) html.a(_("Rule %d in %s") % (rule_index + 1, rule_folder.title()), href=rule_url(rule)) elif len(rules) > 1: html.a("%d %s" % (len(rules), _("Rules")), href=url) else: html.span(_("Default value")) html.close_td() # Show the resulting value or factory setting html.open_td( class_=["settingvalue", "used" if len(rules) > 0 else "unused"]) if isinstance(known_settings, dict) and "tp_computed_params" in known_settings: computed_at = known_settings["tp_computed_params"]["computed_at"] html.write_text( _("Timespecific parameters computed at %s") % cmk.utils.render.date_and_time(computed_at)) html.br() known_settings = known_settings["tp_computed_params"]["params"] # In some cases we now the settings from a check_mk automation if known_settings is self._PARAMETERS_OMIT: return # Special handling for logwatch: The check parameter is always None. The actual # patterns are configured in logwatch_rules. We do not have access to the actual # patterns here but just to the useless "None". In order not to complicate things # we simply display nothing here. if varname == "logwatch_rules": pass elif known_settings is not self._PARAMETERS_UNKNOWN: try: html.write_text(valuespec.value_to_html(known_settings)) except Exception as e: if active_config.debug: raise html.write_text( _("Invalid parameter %r: %s") % (known_settings, e)) else: # For match type "dict" it can be the case the rule define some of the keys # while other keys are taken from the factory defaults. We need to show the # complete outcoming value here. if rules and ruleset.match_type() == "dict": if (rulespec.factory_default is not Rulespec.NO_FACTORY_DEFAULT and rulespec.factory_default is not Rulespec.FACTORY_DEFAULT_UNUSED): fd = rulespec.factory_default.copy() fd.update(setting) setting = fd if valuespec and not rules: # show the default value if rulespec.factory_default is Rulespec.FACTORY_DEFAULT_UNUSED: # Some rulesets are ineffective if they are empty html.write_text(_("(unused)")) elif rulespec.factory_default is not Rulespec.NO_FACTORY_DEFAULT: # If there is a factory default then show that one setting = rulespec.factory_default html.write_text(valuespec.value_to_html(setting)) elif ruleset.match_type() in ("all", "list"): # Rulesets that build lists are empty if no rule matches html.write_text(_("(no entry)")) else: # Else we use the default value of the valuespec html.write_text( valuespec.value_to_html(valuespec.default_value())) # We have a setting elif valuespec: if ruleset.match_type() == "all": for s in setting: html.write_text(valuespec.value_to_html(s)) else: html.write_text(valuespec.value_to_html(setting)) # Binary rule, no valuespec, outcome is True or False else: icon_name = "rule_%s%s" % ("yes" if setting else "no", "_off" if not rules else "") html.icon(icon_name, title=_("yes") if setting else _("no")) html.close_td() html.close_tr() html.close_table()
def _iconlink(self, text, url, icon): html.open_a(class_=["iconlink", "link"], target="main", href=url) html.icon("/webconf/images/icon_%s.png" % icon, cssclass="inline") html.write_text(text) html.close_a() html.br()