def page_menu_entries_related_monitoring( self, crash_info: CrashInfo, site_id: config.SiteId) -> Iterator[PageMenuEntry]: host = crash_info["details"]["host"] service = crash_info["details"]["description"] host_url = html.makeuri( [ ("view_name", "hoststatus"), ("host", host), ("site", site_id), ], filename="view.py", ) yield PageMenuEntry( title=_("Host status"), icon_name="status", item=make_simple_link(host_url), ) service_url = html.makeuri( [("view_name", "service"), ("host", host), ("service", service), ( "site", site_id, )], filename="view.py", ) yield PageMenuEntry( title=_("Service status"), icon_name="status", item=make_simple_link(service_url), )
def show_context_buttons(what, tardata): html.begin_context_buttons() if what == "check": site = html.request.var("site") host = html.request.var("host") service = html.request.var("service") host_url = html.makeuri([("view_name", "hoststatus"), ("host", host), ("site", site)], filename="view.py") html.context_button(_("Host status"), host_url, "status") host_url = html.makeuri([("view_name", "service"), ("host", host), ("service", service), ("site", site)], filename="view.py") html.context_button(_("Service status"), host_url, "status") download_url = html.makeuri([], filename="download_crash_report.py") html.context_button(_("Download"), download_url, "download") elif what == "gui": download_data_url = "data:application/octet-stream;base64,%s" % base64.b64encode( tardata) html.context_button( _("Download"), "javascript:cmk.crash_reporting.download('%s')" % download_data_url, "download") html.end_context_buttons()
def make_display_options_dropdown() -> PageMenuDropdown: return PageMenuDropdown( name="display", title=_("Display"), topics=[ PageMenuTopic( title=_("General display options"), entries=[ PageMenuEntry( title=_("This page without navigation"), icon_name="frameurl", item=PageMenuLink( Link( url=html.makeuri([]), target="_top", )), ), PageMenuEntry( title=_("This page with navigation"), icon_name="pageurl", item=PageMenuLink( Link( url=html.makeuri_contextless( [("start_url", html.makeuri([]))], filename="index.py", ), target="_top", )), ), ], ), ], )
def buttons(self): global_buttons() if self._topic: if len(self._path) == 2: back_url = html.makeuri([("topic", self._path[0])]) else: back_url = html.makeuri([("topic", "")]) html.context_button(_("Back"), back_url, "back")
def _page_menu_entries_details(self) -> Iterator[PageMenuEntry]: yield PageMenuEntry( title=_("Show only modified settings"), icon_name="trans", item=PageMenuCheckbox( is_checked=self._show_only_modified, check_url=html.makeuri([("_show_only_modified", "1")]), uncheck_url=html.makeuri([("_show_only_modified", "0")]), ), )
def paint_aggr_hosts(row, link_to_view): h = [] for site, host in row["aggr_hosts"]: url = html.makeuri([("view_name", link_to_view), ("site", site), ("host", host)]) h.append(html.render_a(host, url)) return "", HTML(" ").join(h)
def page(self): if not self._job_snapshot.exists(): # Skip if snapshot doesnt exists pass elif self._job_snapshot.is_active(): # Still running html.message( HTML(_("User synchronization currently running: ")) + self._job_details_link()) url = html.makeuri([]) html.immediate_browser_redirect(2, url) elif self._job_snapshot.state() == gui_background_job.background_job.JobStatusStates.FINISHED \ and not self._job_snapshot.acknowledged_by(): # Just finished, auto-acknowledge userdb.UserSyncBackgroundJob().acknowledge(config.user.id) #html.message(_("User synchronization successful")) elif not self._job_snapshot.acknowledged_by() and self._job_snapshot.has_exception(): # Finished, but not OK - show info message with links to details html.show_warning( HTML(_("Last user synchronization ran into an exception: ")) + self._job_details_link()) self._show_user_list()
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', html.makeuri([]))) 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 page_login() -> None: title = _("Check_MK Mobile") mobile_html_head(title) jqm_page_header(title, id_="login") html.div(_("Welcome to Check_MK Mobile."), id_="loginhead") html.begin_form("login", method='POST', add_transid=False) # Keep information about original target URL default_origtarget = "index.py" if html.myfile in ["login", "logout" ] else html.makeuri([]) origtarget = html.get_url_input("_origtarget", default_origtarget) html.hidden_field('_origtarget', escaping.escape_attribute(origtarget)) html.text_input("_username", label=_("Username:"******"username") html.password_input("_password", size=None, label=_("Password:"******"current-password") html.br() html.button("_login", _('Login')) html.set_focus("_username") html.end_form() html.open_div(id_="loginfoot") html.img("themes/classic/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 _render_manpage_topic(self): if isinstance(self._manpages, list): self._render_manpage_list(self._manpages, self._path[-1], self._topic_title) return if len(self._path) == 1 and self._has_second_level: # For some topics we render a second level in the same optic as the first level menu = MainMenu() for path_comp, subnode in self._manpages.items(): url = html.makeuri([("topic", "%s/%s" % (self._path[0], path_comp))]) title = self._titles.get(path_comp, path_comp) helptext = self._get_check_plugin_stats(subnode) menu.add_item( MenuItem( mode_or_url=url, title=title, icon="check_plugins", permission=None, description=helptext, )) menu.show() else: # For the others we directly display the tables entries = [] for path_comp, subnode in self._manpages.items(): title = self._titles.get(path_comp, path_comp) entries.append((title, subnode, path_comp)) for title, subnode, path_comp in sorted( entries, key=lambda x: x[0].lower()): self._render_manpage_list(subnode, path_comp, title)
def page(self): html.help( _("This catalog of check plugins gives you a complete listing of all plugins " "that are shipped with your Check_MK installation. It also allows you to " "access the rule sets for configuring the parameters of the checks and to " "manually create services in case you cannot or do not want to rely on the " "automatic service discovery.")) search_form("%s: " % _("Search for check plugins"), "check_plugins") # The maxium depth of the catalog paths is 3. The top level is being rendered # like the WATO main menu. The second and third level are being rendered like # the global settings. if self._topic and not self._search: self._render_manpage_topic() elif self._search: for path, manpages in self._get_manpages_after_search(): self._render_manpage_list(manpages, path, self._titles.get(path, path)) else: menu = MainMenu() for topic, _has_second_level, title, helptext in self._man_page_catalog_topics( ): menu.add_item( MenuItem(mode_or_url=html.makeuri([("topic", topic)]), title=title, icon="plugins_" + topic, permission=None, description=helptext)) menu.show()
def render(self, what, row, tags, custom_vars): if what == "service" \ and row["service_state"] == 3 \ and "check failed - please submit a crash report!" in row["service_plugin_output"]: if not config.user.may("general.see_crash_reports"): return 'crash', _( "This check crashed. Please inform a Check_MK user that is allowed " "to view and submit crash reports to the development team." ) # Extract the crash ID produced by cmk_base/crash_reporting.py from output match = re.search(r"\(Crash dump: ([^)]+)\)$", row["service_plugin_output"]) if not match: return 'crash', _( "This check crashed, but no crash dump is available, please report this " "to the development team.") crash_id = match.group(1) crashurl = html.makeuri( [ ("site", row["site"]), ("crash_id", crash_id), ], filename="crash.py", ) return 'crash', _( "This check crashed. Please click here for more information. You also can submit " "a crash report to the development team if you like." ), crashurl
def _page_menu(self, breadcrumb: Breadcrumb, crash_info: CrashInfo) -> PageMenu: return PageMenu( dropdowns=[ PageMenuDropdown( name="crash_reports", title=_("Crash reports"), topics=[ PageMenuTopic( title=_("This crash report"), entries=[ PageMenuEntry( title=_("Download"), icon_name="download", item=make_simple_link( html.makeuri([], filename="download_crash_report.py")), is_shortcut=True, is_suggested=True, ), ], ), ], ), PageMenuDropdown( name="related", title=_("Related"), topics=[ PageMenuTopic( title=_("Monitoring"), entries=list(self._page_menu_entries_related_monitoring(crash_info)), ), ], ), ], breadcrumb=breadcrumb, )
def show_log_list(): title = _("All problematic logfiles") breadcrumb = make_simple_page_breadcrumb( mega_menu_registry.menu_monitoring(), title) html.header(title, breadcrumb, _log_list_page_menu(breadcrumb)) if html.request.has_var( '_ack') and not html.request.var("_do_actions") == _("No"): do_log_ack(site=None, host_name=None, file_name=None) return for site, host_name, logs in all_logs(): if not logs: continue all_logs_empty = not any( [parse_file(site, host_name, file_name) for file_name in logs]) if all_logs_empty: continue # Logfile vanished html.h2( html.render_a(host_name, href=html.makeuri([('site', site), ('host', host_name)]))) list_logs(site, host_name, logs) html.footer()
def _show_form(self, profile_changed: bool) -> None: assert config.user.id is not None users = userdb.load_users() if profile_changed: html.reload_sidebar() html.show_message(_("Successfully updated user profile.")) # Ensure theme changes are applied without additional user interaction html.immediate_browser_redirect(0.5, html.makeuri([])) if html.has_user_errors(): html.show_user_errors() user = users.get(config.user.id) if user is None: html.show_warning(_("Sorry, your user account does not exist.")) html.footer() return html.begin_form("profile", method="POST") html.prevent_password_auto_completion() html.open_div(class_="wato") forms.header(self._page_title()) forms.section(_("Name"), simple=True) html.write_text(user.get("alias", config.user.id)) select_language(user) # Let the user configure how he wants to be notified rulebased_notifications = rulebased_notifications_enabled() if (not rulebased_notifications and config.user.may('general.edit_notifications') and user.get("notifications_enabled")): forms.section(_("Notifications")) html.help( _("Here you can configure how you want to be notified about host and service problems and " "other monitoring events.")) watolib.get_vs_flexible_notifications().render_input( "notification_method", user.get("notification_method")) if config.user.may('general.edit_user_attributes'): for name, attr in userdb.get_user_attributes(): if attr.user_editable(): vs = attr.valuespec() forms.section(_u(vs.title())) value = user.get(name, vs.default_value()) if not attr.permission() or config.user.may( attr.permission()): vs.render_input("ua_" + name, value) html.help(_u(vs.help())) else: html.write(vs.value_to_text(value)) forms.end() html.close_div() html.hidden_fields() html.end_form() html.footer()
def jqm_page_navfooter(items: NavigationBar, current: str, page_id: str) -> None: html.close_div() # close content html.open_div( **{ "data-role": "footer", "data-position": "fixed", "data-tap-toggle": "false", "data-hide-during-focus": "", }) html.open_div(**{"data-role": "navbar"}) html.open_ul() for href, title, icon, custom_css in items: href = html.makeuri([("page", href), ("search", "Search")]) if current == href: custom_css += ' ui-state-persist ui-btn-active' else: html.open_li() html.open_a(href=href, class_=custom_css, **{ "data-transition": "slide", "data-icon": icon, "data-iconpos": "bottom", }) html.write(title) html.close_a() html.close_li() html.close_ul() html.close_div() html.close_div() html.close_div() # close page-div
def _limit_labels(self, labels): show_all, limit = "", 3 if len(labels) > limit and html.request.var("_show_all") != "1": show_all = " %s" % html.render_a("... (%s)" % _("show all"), href=html.makeuri([("_show_all", "1")])) labels = dict(sorted(labels.items())[:limit]) return labels, show_all
def render_input(self, varprefix, value): # The display mode differs when the valuespec is activated vars_copy = dict(html.request.itervars()) # The timeperiod mode can be set by either the GUI switch or by the value itself # GUI switch overrules the information stored in the value if html.request.has_var(self.tp_toggle_var): is_active = self._is_switched_on() else: is_active = self.is_active(value) # Set the actual used mode html.hidden_field(self.tp_current_mode, "%d" % is_active) mode = _("Disable") if is_active else _("Enable") vars_copy[self.tp_toggle_var] = "%d" % (not is_active) toggle_url = html.makeuri(vars_copy.items()) if is_active: value = self._get_timeperiod_value(value) self._get_timeperiod_valuespec().render_input(varprefix, value) html.buttonlink(toggle_url, _("%s timespecific parameters") % mode, class_=["toggle_timespecific_parameter"]) else: value = self._get_timeless_value(value) r = self._enclosed_valuespec.render_input(varprefix, value) html.buttonlink(toggle_url, _("%s timespecific parameters") % mode, class_=["toggle_timespecific_parameter"]) return r
def _check_auth_cookie(cookie_name: str) -> Optional[UserId]: username, issue_time, cookie_hash = _parse_auth_cookie(cookie_name) _check_parsed_auth_cookie(username, issue_time, cookie_hash) # Check whether or not there is an idle timeout configured, delete cookie and # require the user to renew the log when the timeout exceeded. if userdb.login_timed_out(username, issue_time): del_auth_cookie() return None # Check whether or not a single user session is allowed at a time and the user # is doing this request with the currently active session. if config.single_user_session is not None: session_id = _get_session_id_from_cookie(username) if not userdb.is_valid_user_session(username, session_id): del_auth_cookie() return None # Once reached this the cookie is a good one. Renew it! _renew_cookie(cookie_name, username) if html.myfile != 'user_change_pw': result = userdb.need_to_change_pw(username) if result: raise HTTPRedirect('user_change_pw.py?_origtarget=%s&reason=%s' % (html.urlencode(html.makeuri([])), result)) # Return the authenticated username return username
def _process_notify_message(msg): msg['id'] = utils.gen_id() msg['time'] = time.time() if isinstance(msg['dest'], str): dest_what = msg['dest'] else: dest_what = msg['dest'][0] if dest_what == 'broadcast': recipients = list(config.multisite_users.keys()) elif dest_what == 'online': recipients = userdb.get_online_user_ids() elif dest_what == 'list': recipients = msg['dest'][1] else: recipients = [] num_recipients = len(recipients) num_success = {} for method in msg['methods']: num_success[method] = 0 # Now loop all notitification methods to send the notifications errors: Dict[str, List[Tuple]] = {} for user_id in recipients: for method in msg['methods']: try: handler = _notify_methods()[method]['handler'] handler(user_id, msg) num_success[method] = num_success[method] + 1 except MKInternalError as e: errors.setdefault(method, []).append((user_id, e)) message = _('The notification has been sent via<br>') message += "<table>" for method in msg['methods']: message += "<tr><td>%s</td><td>to %d of %d recipients</td></tr>" %\ (_notify_methods()[method]["title"], num_success[method], num_recipients) message += "</table>" message += _('<p>Sent notification to: %s</p>') % ', '.join(recipients) message += '<a href="%s">%s</a>' % (html.makeuri( []), _('Back to previous page')) html.show_message(HTML(message)) if errors: error_message = HTML() for method, method_errors in errors.items(): error_message += _( "Failed to send %s notifications to the following users:" ) % method table_rows = HTML() for user, exception in method_errors: table_rows += html.render_tr( html.render_td(html.render_tt(user)) + html.render_td(exception)) error_message += html.render_table(table_rows) + html.render_br() html.show_error(error_message)
def _render_werk_table_options(): werk_table_options = {} # type: Dict[str, Any] for name, height, vs, default_value in _werk_table_option_entries(): value = default_value try: if html.request.has_var("wo_set"): value = vs.from_html_vars("wo_" + name) vs.validate_value(value, "wo_" + name) except MKUserError as e: html.user_error(e) werk_table_options.setdefault(name, value) html.begin_foldable_container("werks", "options", isopen=True, title=_("Searching and Filtering"), indent=False) html.begin_form("werks") html.hidden_field("wo_set", "set") html.begin_floating_options("werks", is_open=True) for name, height, vs, default_value in _werk_table_option_entries(): html.render_floating_option(name, height, "wo_", vs, werk_table_options[name]) html.end_floating_options(reset_url=html.makeuri([], remove_prefix="")) html.hidden_fields() html.end_form() html.end_foldable_container() from_date, until_date = Timerange().compute_range( werk_table_options["date"])[0] werk_table_options["date_range"] = from_date, until_date return werk_table_options
def show_log_list(): title = _("All problematic logfiles") html.header(title, make_simple_page_breadcrumb(MegaMenuMonitoring, title)) html.begin_context_buttons() html.context_button( _("Analyze Patterns"), "%swato.py?mode=pattern_editor" % html.request.var('master_url', ''), 'analyze') ack_button() html.end_context_buttons() for site, host_name, logs in all_logs(): if not logs: continue all_logs_empty = not any( [parse_file(site, host_name, file_name) for file_name in logs]) if all_logs_empty: continue # Logfile vanished html.h2( html.render_a(host_name, href=html.makeuri([('site', site), ('host', host_name)]))) list_logs(site, host_name, logs) html.footer()
def list_logs(site, host_name, logfile_names): with table_element(empty_text=_("No logs found for this host.")) as table: for file_name in logfile_names: table.row() file_display = form_file_to_ext(file_name) uri = html.makeuri([('site', site), ('host', host_name), ('file', file_display)]) logfile_link = html.render_a(file_display, href=uri) try: log_chunks = parse_file(site, host_name, file_name) if not log_chunks: continue # Logfile vanished worst_log = get_worst_chunk(log_chunks) last_log = get_last_chunk(log_chunks) state = worst_log['level'] state_name = form_level(state) table.cell(_("Level"), state_name, css="state%d" % state) table.cell(_("Logfile"), logfile_link) table.cell(_("Last Entry"), form_datetime(last_log['datetime'])) table.cell(_("Entries"), len(log_chunks), css="number") except Exception: if config.debug: raise table.cell(_("Level"), "") table.cell(_("Logfile"), logfile_link) table.cell(_("Last Entry"), "") table.cell(_("Entries"), _("Corrupted"))
def jqm_page_navfooter(items, current, page_id): html.close_div() # close content html.open_div(**{"data-role": "footer", "data-position": "fixed"}) html.open_div(**{"data-role": "navbar"}) html.open_ul() for href, title, icon, custom_css in items: href = html.makeuri([("page", href), ("search", "Search")]) if custom_css is False: custom_css = "" if current == href: custom_css += ' ui-state-persist ui-btn-active' else: html.open_li() html.open_a(href=href, class_=custom_css, **{ "data-transition": "slide", "data-icon": icon, "data-iconpos": "bottom" }) html.write(title) html.close_a() html.close_li() html.close_ul() html.close_div() html.close_div() html.close_div() # close page-div
def render_availability_options(what): if html.request.var("_reset"): config.user.save_file("avoptions", {}) html.request.del_vars("avo_") html.request.del_var("avoptions") avoptions = availability.get_default_avoptions() # Users of older versions might not have all keys set. The following # trick will merge their options with our default options. avoptions.update(config.user.load_file("avoptions", {})) is_open = False html.begin_form("avoptions") html.hidden_field("avoptions", "set") avoption_entries = availability.get_avoption_entries(what) if html.request.var("avoptions") == "set": for name, height, _show_in_reporting, vs in avoption_entries: try: avoptions[name] = vs.from_html_vars("avo_" + name) vs.validate_value(avoptions[name], "avo_" + name) except MKUserError as e: html.add_user_error(e.varname, e) is_open = True if html.request.var("_unset_logrow_limit") == "1": avoptions["logrow_limit"] = 0 range_vs = None for name, height, _show_in_reporting, vs in avoption_entries: if name == 'rangespec': range_vs = vs try: range_, range_title = range_vs.compute_range(avoptions["rangespec"]) avoptions["range"] = range_, range_title except MKUserError as e: html.add_user_error(e.varname, e) if html.has_user_errors(): html.show_user_errors() html.begin_floating_options("avoptions", is_open) for name, height, _show_in_reporting, vs in avoption_entries: html.render_floating_option(name, height, "avo_", vs, avoptions.get(name)) html.end_floating_options(reset_url=html.makeuri( [("_reset", "1")], remove_prefix="avo_", delvars=["apply", "filled_in"], )) html.hidden_fields() html.end_form() if html.form_submitted(): config.user.save_file("avoptions", avoptions) return avoptions
def _render_manpage_list(self, manpage_list, path_comp, heading): def translate(t): return self._titles.get(t, t) html.h2(heading) with table_element(searchable=False, sortable=False, css="check_catalog") as table: for entry in sorted(manpage_list, cmp=lambda a, b: cmp(a["title"], b["title"])): if not isinstance(entry, dict): continue table.row() url = html.makeuri([("mode", "check_manpage"), ("check_type", entry["name"]), ("back", html.makeuri([]))]) table.cell( _("Type of Check"), "<a href='%s'>%s</a>" % (url, entry["title"]), css="title") table.cell(_("Plugin Name"), "<tt>%s</tt>" % entry["name"], css="name") table.cell( _("Agents"), ", ".join(map(translate, sorted(entry["agents"]))), css="agents")
def _bulk_actions(self, table, at_least_one_imported, top, withsearch, colspan, show_checkboxes): table.row(collect_headers=False, fixed=True) table.cell(css="bulksearch", colspan=3) if not show_checkboxes: onclick_uri = html.makeuri([('show_checkboxes', '1'), ('selection', weblib.selection_id())]) checkbox_title = _('Show Checkboxes and bulk actions') else: onclick_uri = html.makeuri([('show_checkboxes', '0')]) checkbox_title = _('Hide Checkboxes and bulk actions') html.toggle_button("checkbox_on", show_checkboxes, "checkbox", title=checkbox_title, onclick="location.href=\'%s\'" % onclick_uri, is_context_button=False) if withsearch: html.text_input("search") html.button("_search", _("Search")) html.set_focus("search") table.cell(css="bulkactions", colspan=colspan - 3) html.write_text(' ' + _("Selected hosts:\n")) if not self._folder.locked_hosts(): if config.user.may("wato.manage_hosts"): html.button("_bulk_delete", _("Delete")) if config.user.may("wato.edit_hosts"): html.button("_bulk_edit", _("Edit")) html.button("_bulk_cleanup", _("Cleanup")) if config.user.may("wato.services"): html.button("_bulk_inventory", _("Discovery")) if not self._folder.locked_hosts(): if config.user.may("wato.parentscan"): html.button("_parentscan", _("Parentscan")) if config.user.may("wato.edit_hosts") and config.user.may( "wato.move_hosts"): self._host_bulk_move_to_folder_combo(top) if at_least_one_imported: html.button("_bulk_movetotarget", _("Move to Target Folders"))
def _build_url(self, url_params, restore_regex=False): new_params = [] if restore_regex: for key, value in url_params: new_params.append((key, value.replace("\\", "\\\\"))) else: new_params.extend(url_params) return html.makeuri(new_params, delvars="q", filename="view.py")
def _host_log_list_page_menu(breadcrumb: Breadcrumb, site_id: config.SiteId, host_name: HostName) -> PageMenu: return PageMenu( dropdowns=[ PageMenuDropdown( name="logs", title=_("Logs"), topics=[ PageMenuTopic( title=_("Current log files"), entries=list( _page_menu_entry_acknowledge(site_id, host_name)), ), PageMenuTopic( title=_("Log files"), entries=[ PageMenuEntry( title=_("All log files"), icon_name="logwatch", item=make_simple_link( html.makeuri([('site', ''), ('host', ''), ('file', '')])), ), ], ), ], ), PageMenuDropdown( name="related", title=_("Related"), topics=[ PageMenuTopic( title=_("Monitoring"), entries=[ PageMenuEntry( title=_("Services of host"), icon_name="services", item=make_simple_link( services_url(site_id, host_name)), ), ], ), PageMenuTopic( title=_("Setup"), entries=[ PageMenuEntry( title=_("Analyze host patterns"), icon_name="analyze", item=make_simple_link( analyse_url(site_id, host_name)), ), ], ), ], ), ], breadcrumb=breadcrumb, )
def _show_status(self): job_status = self._get_job_status() html.h3(_("Job status")) if job_status["is_active"]: html.immediate_browser_redirect(0.8, html.makeuri([])) job = FetchAgentOutputBackgroundJob(self._request) gui_background_job.JobRenderer.show_job_details(job.get_job_id(), job_status)