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 _show_table(self, request): html.open_table(class_="allhosts") html.open_tbody() for map_cfg in 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 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(), reverse=True): cls.render_job_row(job_id, job_status, odd, **kwargs) odd = "even" if odd == "odd" else "odd"
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() 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) else: self._show_ruleset("active_checks:%s" % self._check_type[6:]) html.close_table()
def section(title=None, checkbox=None, section_id=None, simple=False, hide=False, legend=True, css=None): global g_section_open if g_section_open: html.close_td() html.close_tr() html.open_tr(id_=section_id, class_=["open" if g_section_isopen else "closed", css], style="display:none;" if hide else None) if legend: html.open_td(class_=["legend", "simple" if simple else None]) if title: html.open_div(class_=["title", "withcheckbox" if checkbox else None], title=html.strip_tags(title)) html.write(html.permissive_attrencode(title)) html.span('.' * 100, class_="dots") html.close_div() if checkbox: html.open_div(class_="checkbox") if isinstance(checkbox, six.string_types + (HTML,)): html.write(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 None]) g_section_open = True
def display(self): choices: Choices = [(str(sec), title + " " + _("ago")) for sec, title in self.ranges] choices += [("abs", _("Date (YYYY-MM-DD)")), ("unix", _("UNIX timestamp"))] html.open_table(class_="filtertime") for what, whatname in [("from", _("From")), ("until", _("Until"))]: varprefix = self.ident + "_" + what html.open_tr() html.open_td() html.write("%s:" % whatname) html.close_td() html.open_td() html.text_input(varprefix) html.close_td() html.open_td() html.dropdown(varprefix + "_range", choices, deflt="3600") html.close_td() html.close_tr() 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 show_job_details(cls, job_id, job_status): """Renders the complete job details in a single table with left headers""" html.open_table(class_=["data", "headerleft", "job_details"]) # Static info for left, right in [ (_("ID"), job_id), (_("Title"), job_status.get("title", "")), (_("Started"), cmk.utils.render.date_and_time(job_status["started"])), (_("Owner"), job_status.get("user", "")), ]: html.open_tr() html.th(left) html.td(right) html.close_tr() # Actions html.open_tr() html.th(_("Actions")) html.open_td() if job_status.get("may_stop"): html.icon_button( html.makeactionuri([(ActionHandler.stop_job_var, job_id)]), _("Stop this job"), "disable_test", ) if job_status.get("may_delete"): html.icon_button( html.makeactionuri([(ActionHandler.delete_job_var, job_id)]), _("Delete this job"), "delete", ) html.close_td() html.close_tr() # Job state html.open_tr() html.th(_("State")) html.td(job_status["state"], css=cls.get_css_for_jobstate(job_status["state"])) html.close_tr() if job_status["state"] == background_job.JobStatusStates.EXCEPTION: html.open_tr() html.th(_("Acknowledged by")) html.td(job_status.get("acknowledged_by", "")) html.close_tr() # Dynamic data loginfo = job_status.get("loginfo") runtime_info = ensure_str( cmk.utils.render.timespan(job_status.get("duration", 0))) if job_status["state"] == background_job.JobStatusStates.RUNNING \ and job_status.get("estimated_duration") is not None: runtime_info += u" (%s: %s)" % ( _("estimated duration"), ensure_str( cmk.utils.render.timespan( job_status["estimated_duration"]))) for left, right in [ (_("Runtime"), runtime_info), (_("PID"), job_status["pid"] or ""), (_("Result"), "<br>".join(loginfo["JobResult"])), ]: if right is None: continue html.open_tr() html.th(left) html.td(HTML(right)) html.close_tr() # Exceptions exceptions = loginfo["JobException"] if exceptions: html.open_tr() html.th(_("Exceptions")) html.open_td() if exceptions and "logfile_path" in job_status: exceptions.append( _("More information can be found in %s") % job_status["logfile_path"]) html.open_div(class_="log_output", id_="exception_log") html.pre("\n".join(exceptions)) html.close_div() html.close_td() html.close_tr() # Progress Update html.open_tr() html.th(_("Progress Info")) html.open_td() html.open_div(class_="log_output", style="height: 400px;", id_="progress_log") html.pre(HTML("\n").join(loginfo["JobProgressUpdate"])) html.close_div() html.close_td() html.close_tr() html.close_table() html.javascript( "var log = document.getElementById('progress_log'); log.scrollTop = log.scrollHeight;" )
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): return watolib.folder_preserving_link([ ('mode', 'edit_rule'), ('varname', varname), ('rule_folder', rule.folder.path()), ('rulenr', rule.index()), ('host', self._hostname), ('item', watolib.mk_repr(svc_desc_or_item) if svc_desc_or_item else ''), ('service', watolib.mk_repr(svc_desc) if svc_desc else ''), ]) varname = rulespec.name valuespec = rulespec.valuespec url = watolib.folder_preserving_link([ ('mode', 'edit_ruleset'), ('varname', varname), ('host', self._hostname), ('item', watolib.mk_repr(svc_desc_or_item)), ('service', watolib.mk_repr(svc_desc)), ]) forms.section(html.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.i(_("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(valuespec.value_to_text(known_settings)) except Exception as e: if 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 watolib.Rulespec.NO_FACTORY_DEFAULT \ and rulespec.factory_default is not watolib.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 watolib.Rulespec.FACTORY_DEFAULT_UNUSED: # Some rulesets are ineffective if they are empty html.write_text(_("(unused)")) elif rulespec.factory_default is not watolib.Rulespec.NO_FACTORY_DEFAULT: # If there is a factory default then show that one setting = rulespec.factory_default html.write(valuespec.value_to_text(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( valuespec.value_to_text(valuespec.default_value())) # We have a setting elif valuespec: if ruleset.match_type() == "all": html.write(", ".join( [valuespec.value_to_text(e) for e in setting])) else: html.write(valuespec.value_to_text(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(title=_("yes") if setting else _("no"), icon=icon_name) html.close_td() 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 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 render_bi_availability(title, aggr_rows): # type: (Text, Rows) -> None config.user.need_permission("general.see_availability") av_mode = html.request.get_ascii_input_mandatory("av_mode", "availability") avoptions = get_availability_options_from_url("bi") if av_mode == "timeline": title = _("Timeline of") + " " + title else: title = _("Availability of") + " " + title if html.output_format != "csv_export": html.body_start(title) html.top_heading(title) html.begin_context_buttons() html.toggle_button("avoptions", False, "painteroptions", _("Configure details of the report")) html.context_button(_("Status View"), html.makeuri([("mode", "status")]), "status") if config.reporting_available() and config.user.may( "general.reporting"): html.context_button(_("Export as PDF"), html.makeuri([], filename="report_instant.py"), "report") if config.user.may("general.csv_export"): html.context_button( _("Export as CSV"), html.makeuri([("output_format", "csv_export")]), "download_csv") if av_mode == "timeline": html.context_button(_("Availability"), html.makeuri([("av_mode", "availability")]), "availability") elif len(aggr_rows) == 1: aggr_name = aggr_rows[0]["aggr_name"] aggr_group = aggr_rows[0]["aggr_group"] timeline_url = html.makeuri([("av_mode", "timeline"), ("av_aggr_name", aggr_name), ("av_aggr_group", aggr_group)]) html.context_button(_("Timeline"), timeline_url, "timeline") html.end_context_buttons() avoptions = render_availability_options("bi") if not html.has_user_errors(): logrow_limit = avoptions["logrow_limit"] if logrow_limit == 0: livestatus_limit = None else: livestatus_limit = (len(aggr_rows) * logrow_limit) spans = [] # type: List[AVSpan] # iterate all aggregation rows timewarpcode = HTML() timewarp = html.request.get_integer_input("timewarp") has_reached_logrow_limit = False timeline_containers, fetched_rows = availability.get_timeline_containers( aggr_rows, avoptions, timewarp, livestatus_limit + 1 if livestatus_limit is not None else None) if livestatus_limit and fetched_rows > livestatus_limit: has_reached_logrow_limit = True for timeline_container in timeline_containers: tree = timeline_container.aggr_tree these_spans = timeline_container.timeline timewarp_tree_state = timeline_container.timewarp_state spans += these_spans # render selected time warp for the corresponding aggregation row (should be matched by only one) if timewarp and timewarp_tree_state: state, assumed_state, node, _subtrees = timewarp_tree_state eff_state = state if assumed_state is not None: eff_state = assumed_state row = { "aggr_tree": tree, "aggr_treestate": timewarp_tree_state, "aggr_state": state, # state disregarding assumptions "aggr_assumed_state": assumed_state, # is None, if there are no assumptions "aggr_effective_state": eff_state, # is assumed_state, if there are assumptions, else real state "aggr_name": node["title"], "aggr_output": eff_state["output"], "aggr_hosts": node["reqhosts"], "aggr_function": node["func"], "aggr_group": html.request.var("aggr_group"), } renderer = bi.FoldableTreeRendererTree( row, omit_root=False, expansion_level=config.user.bi_expansion_level, only_problems=False, lazy=False) tdclass, htmlcode = renderer.css_class(), renderer.render() with html.plugged(): # TODO: SOMETHING IS WRONG IN HERE (used to be the same situation in original code!) # FIXME: WHAT is wrong in here?? html.open_h3() # render icons for back and forth button_back_shown = False button_forth_shown = False if int(these_spans[0]["from"]) == timewarp: html.disabled_icon_button("back_off") button_back_shown = True previous_span = None for span in these_spans: if not button_back_shown and int( span["from"] ) == timewarp and previous_span is not None: html.icon_button( html.makeuri([("timewarp", str(int(previous_span["from"]))) ]), _("Jump one phase back"), "back") button_back_shown = True # Multiple followup spans can have the same "from" time # We only show one forth-arrow with an actual time difference elif not button_forth_shown and previous_span and int( previous_span["from"]) == timewarp and int( span["from"]) != timewarp: html.icon_button( html.makeuri([("timewarp", str(int(span["from"])))]), _("Jump one phase forth"), "forth") button_forth_shown = True previous_span = span if not button_forth_shown: html.disabled_icon_button("forth_off") html.write_text(" ") html.icon_button(html.makeuri([("timewarp", "")]), _("Close Timewarp"), "closetimewarp") html.write_text("%s %s" % (_("Timewarp to "), time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timewarp)))) html.close_h3() html.open_table(class_=["data", "table", "timewarp"]) html.open_tr(class_=["data", "odd0"]) html.open_td(class_=tdclass) html.write_html(htmlcode) html.close_td() html.close_tr() html.close_table() timewarpcode += html.drain() # Note: 'spans_by_object' returns two arguments which are used by # all availability views but not by BI. There we have to take # only complete aggregations av_rawdata = availability.spans_by_object(spans, None)[0] av_data = availability.compute_availability("bi", av_rawdata, avoptions) # If we abolish the limit we have to fetch the data again # with changed logrow_limit = 0, which means no limit if has_reached_logrow_limit: text = _( "Your query matched more than %d log entries. " "<b>Note:</b> The shown data does not necessarily reflect the " "matched entries and the result might be incomplete. " ) % avoptions["logrow_limit"] text += html.render_a(_('Repeat query without limit.'), html.makeuri([("_unset_logrow_limit", "1")])) html.show_warning(text) if html.output_format == "csv_export" and config.user.may( "general.csv_export"): _output_csv("bi", av_mode, av_data, avoptions) return html.write(timewarpcode) do_render_availability("bi", av_rawdata, av_data, av_mode, None, avoptions) html.bottom_footer() html.body_end()
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(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(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()
def show(self): if not watolib.is_wato_slave_site(): if not config.wato_enabled: html.write_text(_("Setup is disabled.")) return False user_folders = compute_foldertree() # # Render link target selection # selected_topic, selected_target = user.load_file( "foldertree", (_("Hosts"), "allhosts")) # Apply some view specific filters views_to_show = [ (name, view) for name, view in views.get_permitted_views().items() if (not config.visible_views or name in config.visible_views) and ( not config.hidden_views or name not in config.hidden_views) ] 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, 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.title != selected_topic: default = "" style: Optional[str] = "display:none" else: default = selected_target 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")
def show(self): hosts = self._get_hosts() num_hosts = len(hosts) if num_hosts > 900: html.write_text( _("Sorry, I will not display more than 900 hosts.")) return # Choose smallest square number large enough # to show all hosts n = 1 while n * n < num_hosts: n += 1 rows = int(num_hosts / n) lastcols = num_hosts % n if lastcols > 0: rows += 1 # Calculate cell size (Automatic sizing with 100% does not work here) # - Get cell spacing: 1px between each cell # - Substract the cell spacing for each column from the total width # - Then divide the total width through the number of columns # - Then get the full-digit width of the cell and summarize the rest # to be substracted from the cell width # This is not a 100% solution but way better than having no links cell_spacing = 1 cell_size = int((snapin_width - cell_spacing * (n + 1)) / n) cell_size, cell_size_rest = divmod(cell_size, 1) style = 'width:%spx' % (snapin_width - n * cell_size_rest) html.open_table(class_=["content_center", "hostmatrix"], cellspacing="0", style=["border-collapse:collapse;", style]) col = 1 row = 1 for site, host, state, has_been_checked, worstsvc, downtimedepth in sorted( hosts): if col == 1: html.open_tr() if downtimedepth > 0: s = "d" elif not has_been_checked: s = "p" elif worstsvc == 2 or state == 1: s = "2" elif worstsvc == 3 or state == 2: s = "3" elif worstsvc == 1: s = "1" else: s = "0" url = "view.py?view_name=host&site=%s&host=%s" % ( html.urlencode(site), html.urlencode(host)) html.open_td(class_=["state", "state%s" % s]) html.a( '', href=url, title=host, target="main", style=["width:%spx;" % cell_size, "height:%spx;" % cell_size]) html.close_td() if col == n or (row == rows and n == lastcols): html.open_tr() col = 1 row += 1 else: col += 1 html.close_table()
def show(self): if not watolib.is_wato_slave_site(): if not config.wato_enabled: html.write_text(_("WATO is disabled.")) return False user_folders = compute_foldertree() # # Render link target selection # selected_topic, selected_target = config.user.load_file( "foldertree", (_('Hosts'), 'allhosts')) topic_views = visuals_by_topic( views.get_permitted_views().items() + dashboard.get_permitted_dashboards().items()) topics = [(t, t) for t, _s in topic_views] html.open_table() html.open_tr() html.td(_('Topic:'), class_="label") html.open_td() html.dropdown("topic", topics, deflt=selected_topic, onchange='cmk.sidebar.wato_tree_topic_changed(this)') html.close_td() html.close_tr() html.open_tr() html.td(_("View:"), class_="label") html.open_td() for topic, view_list in topic_views: targets = [] for t, title, name, is_view in view_list: if config.visible_views and name not in config.visible_views: continue if config.hidden_views and name in config.hidden_views: continue if t == topic: if not is_view: name = 'dashboard|' + name targets.append((name, title)) if topic != selected_topic: default, style = '', 'display:none' else: default, style = selected_target, None html.dropdown( "target_%s" % topic, 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')
def _show_inpage_search_field(self, item: PageMenuSearch) -> None: html.open_td(class_="inpage_search") inpage_search_form(mode=item.target_mode, default_value=item.default_value, placeholder=item.placeholder) html.close_td()
def _show_pending_changes_icon(self) -> None: html.open_td(class_="icon_container") html.icon_button("wato.py?mode=changelog", _("View pending changes"), "activate_changes") html.close_td()
def _write_table(self, rows, actions_enabled, actions_visible, search_term): headinfo = _("1 row") if len(rows) == 1 else _("%d rows") % len(rows) html.javascript("cmk.utils.update_header_info(%s);" % json.dumps(headinfo)) table_id = self.id num_cols = len(self.headers) empty_columns = self._get_empty_columns(rows, num_cols) 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 self.rows[0][2] != "header": 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 self.options["searchable"]: html.open_div(class_="search") html.text_input("_%s_search" % table_id) html.button("_%s_submit" % table_id, _("Search")) html.button("_%s_reset" % table_id, _("Reset search")) html.set_focus("_%s_search" % table_id) html.close_div() if html.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_spec, css, state, _fixed, attrs) in enumerate(rows): if not css and "class_" in attrs: css = attrs.pop("class_") if not css and "class" in attrs: css = attrs.pop("class") # Intermediate header if state == "header": # Show the header only, if at least one (non-header) row follows if nr < len(rows) - 1 and rows[nr + 1][2] != "header": html.open_tr(class_="groupheader") html.open_td(colspan=num_cols) html.open_h3() html.write(row_spec) html.close_h3() html.close_td() html.close_tr() self._render_headers(actions_enabled, actions_visible, empty_columns) continue oddeven_name = "even" if (nr - 1) % 2 == 0 else "odd" html.open_tr(class_=[ "data", "%s%d" % (oddeven_name, state), css if css else None ], **attrs) for col_index, (cell_content, css_classes, colspan) in enumerate(row_spec): if self.options["omit_empty_columns"] and empty_columns[ col_index]: continue html.open_td(class_=css_classes if css_classes else None, colspan=colspan if colspan else None) html.write(cell_content) html.close_td() 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 section_close() -> None: if g_section_open: html.close_td() html.close_tr()
def render_checkbox_td(view, row, num_tds): html.open_td(class_="checkbox") render_checkbox(view, row, num_tds) html.close_td()
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_=["content_center", "tacticaloverview"], cellspacing="2", cellpadding="0", border="0") show_stales = self.parameters()["show_stale"] and config.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 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")) html.th(_("Unhandled")) 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 = html.makeuri_contextless(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 = html.makeuri_contextless(getattr(row.views, ty) + context_vars, filename="view.py") html.open_td(class_=[td_class, "states prob" if value != 0 else None]) link(str(value), url) html.close_td() if show_stales and has_stale_objects: if row.views.stale: url = html.makeuri_contextless(row.views.stale + context_vars, filename="view.py") html.open_td(class_=[td_class, "states prob" if stales != 0 else None]) link(str(stales), url) html.close_td() else: html.td(html.render_span("0")) 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_service_info(self, all_rulesets): serviceinfo = watolib.check_mk_automation( self._host.site_id(), "analyse-service", [self._hostname, self._service]) if not serviceinfo: return forms.header(_("Check origin and parameters"), isopen=True, narrow=True, css="rulesettings") origin = serviceinfo["origin"] origin_txt = { "active": _("Active check"), "static": _("Manual check"), "auto": _("Inventorized check"), "classic": _("Classical check"), }[origin] self._render_rule_reason(_("Type of check"), None, "", "", False, origin_txt) # First case: discovered checks. They come from var/check_mk/autochecks/HOST. if origin == "auto": checkgroup = serviceinfo["checkgroup"] checktype = serviceinfo["checktype"] if not checkgroup: self._render_rule_reason( _("Parameters"), None, "", "", True, _("This check is not configurable via WATO")) # Logwatch needs a special handling, since it is not configured # via checkgroup_parameters but via "logwatch_rules" in a special # WATO module. elif checkgroup == "logwatch": rulespec = rulespec_registry["logwatch_rules"] self._output_analysed_ruleset( all_rulesets, rulespec, svc_desc_or_item=serviceinfo["item"], svc_desc=self._service, known_settings=serviceinfo["parameters"]) else: # Note: some discovered checks have a check group but # *no* ruleset for discovered checks. One example is "ps". # That can be configured as a manual check or created by # inventory. But in the later case all parameters are set # by the inventory. This will be changed in a later version, # but we need to address it anyway. grouprule = "checkgroup_parameters:" + checkgroup if grouprule not in rulespec_registry: try: rulespec = rulespec_registry["static_checks:" + checkgroup] except KeyError: rulespec = None if rulespec: url = watolib.folder_preserving_link([ ('mode', 'edit_ruleset'), ('varname', "static_checks:" + checkgroup), ('host', self._hostname) ]) self._render_rule_reason( _("Parameters"), url, _("Determined by discovery"), None, False, rulespec.valuespec._elements[2].value_to_text( serviceinfo["parameters"])) else: self._render_rule_reason( _("Parameters"), None, "", "", True, _("This check is not configurable via WATO")) else: rulespec = rulespec_registry[grouprule] self._output_analysed_ruleset( all_rulesets, rulespec, svc_desc_or_item=serviceinfo["item"], svc_desc=self._service, known_settings=serviceinfo["parameters"]) elif origin == "static": checkgroup = serviceinfo["checkgroup"] checktype = serviceinfo["checktype"] if not checkgroup: html.write_text(_("This check is not configurable via WATO")) else: rulespec = rulespec_registry["static_checks:" + checkgroup] itemspec = rulespec.item_spec if itemspec: item_text = itemspec.value_to_text(serviceinfo["item"]) title = rulespec.item_spec.title() else: item_text = serviceinfo["item"] title = _("Item") self._render_rule_reason(title, None, "", "", False, item_text) self._output_analysed_ruleset( all_rulesets, rulespec, svc_desc_or_item=serviceinfo["item"], svc_desc=self._service, known_settings=self._PARAMETERS_OMIT) html.write(rulespec.valuespec._elements[2].value_to_text( serviceinfo["parameters"])) html.close_td() html.close_tr() html.close_table() elif origin == "active": checktype = serviceinfo["checktype"] rulespec = rulespec_registry["active_checks:" + checktype] self._output_analysed_ruleset( all_rulesets, rulespec, svc_desc_or_item=None, svc_desc=None, known_settings=serviceinfo["parameters"]) elif origin == "classic": ruleset = all_rulesets.get("custom_checks") origin_rule_result = self._get_custom_check_origin_rule( ruleset, self._hostname, self._service) if origin_rule_result is None: raise MKUserError( None, _("Failed to determine origin rule of %s / %s") % (self._hostname, self._service)) rule_folder, rule_index, _rule = origin_rule_result url = watolib.folder_preserving_link([('mode', 'edit_ruleset'), ('varname', "custom_checks"), ('host', self._hostname)]) forms.section(html.render_a(_("Command Line"), href=url)) url = watolib.folder_preserving_link([('mode', 'edit_rule'), ('varname', "custom_checks"), ('rule_folder', rule_folder.path()), ('rulenr', rule_index), ('host', self._hostname)]) html.open_table(class_="setting") html.open_tr() html.open_td(class_="reason") html.a("%s %d %s %s" % (_("Rule"), rule_index + 1, _("in"), rule_folder.title()), href=url) html.close_td() html.open_td(class_=["settingvalue", "used"]) if "command_line" in serviceinfo: html.tt(serviceinfo["command_line"]) else: html.write_text(_("(no command line, passive check)")) html.close_td() html.close_tr() html.close_table() self._show_labels(serviceinfo.get("labels", {}), "service", serviceinfo.get("label_sources", {}))
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 _write_table(self, rows: TableRows, num_rows_unlimited: int, actions_enabled: bool, actions_visible: bool, search_term: Optional[str]) -> None: headinfo = _("1 row") if len( rows) == 1 else _("%d rows") % num_rows_unlimited html.javascript("cmk.utils.update_header_info(%s);" % json.dumps(headinfo)) 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 self.options["searchable"]: html.open_div(class_="search") html.text_input("_%s_search" % table_id) html.button("_%s_submit" % table_id, _("Search")) html.button("_%s_reset" % table_id, _("Reset search")) html.set_focus("_%s_search" % table_id) html.close_div() if html.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.open_h3() html.write(row.title) html.close_h3() html.close_td() html.close_tr() self._render_headers(actions_enabled, actions_visible, empty_columns) continue oddeven_name = "even" if (nr - 1) % 2 == 0 else "odd" class_ = ["data", "%s%d" % (oddeven_name, row.state)] if row.css: class_.append(row.css) else: for k in ["class_", "class"]: if k in row.row_attributes: cls_spec = cast(CSSSpec, row.row_attributes.pop(k)) if isinstance(cls_spec, list): class_.extend( [c for c in cls_spec if c is not None]) elif cls_spec is not None: class_.append(cls_spec) html.open_tr(class_=class_, **row.row_attributes) for col_index, cell in enumerate(row.cells): if self.options["omit_empty_columns"] and empty_columns[ col_index]: continue html.open_td(class_=cell.css, colspan=cell.colspan) html.write(cell.content) html.close_td() 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): 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 render_job_row(cls, job_id, job_status, odd, job_details_back_url=None): html.open_tr(css="data %s0" % odd) # Actions html.open_td(css="job_actions") if job_status.get("may_stop"): html.icon_button( html.makeactionuri([(ActionHandler.stop_job_var, job_id)]), _("Stop this job"), "disable_test") if job_status.get("may_delete"): html.icon_button( html.makeactionuri([(ActionHandler.delete_job_var, job_id)]), _("Delete this job"), "delete") html.close_td() # Job ID html.open_td(css="job_id") uri = makeuri_contextless( request, [ ("mode", "background_job_details"), ("back_url", job_details_back_url), ("job_id", job_id), ], filename="wato.py", ) html.a(job_id, href=uri) html.close_td() # Title html.td(job_status.get("title", _("Background Job")), css="job_title") # State html.td(job_status["state"], css=cls.get_css_for_jobstate(job_status["state"])) # Started html.td(cmk.utils.render.date_and_time(job_status["started"]), css="job_started") # Owner html.td(job_status.get("user", _("Unknown user")), css="job_owner") # PID html.td(job_status["pid"] or "", css="job_pid") # Druation html.td(cmk.utils.render.timespan(job_status.get("duration", 0)), css="job_runtime") # Progress info loginfo = job_status.get("loginfo") if loginfo: if job_status.get( "state") == background_job.JobStatusStates.EXCEPTION: html.td(HTML("<br>".join(loginfo["JobException"])), css="job_last_progress") else: progress_text = "" if loginfo["JobProgressUpdate"]: progress_text += "%s" % loginfo["JobProgressUpdate"][-1] html.td(HTML(progress_text), css="job_last_progress") html.td(HTML("<br>".join(loginfo["JobResult"])), css="job_result") else: html.td("", css="job_last_progress") html.td("", css="job_result")
def foldable_container( *, treename: str, id_: str, isopen: bool, title: HTMLContent, indent: Union[str, None, bool] = True, first: bool = False, 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, class_=[ "treeangle", "title", # Although foldable_sidebar is given via the argument icon it should not be # displayed as big as an icon. "icon" if icon != "foldable_sidebar" else None, "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(self): mode = self._host_mode_ident() sites.live().set_prepend_site(True) query = "GET hosts\nColumns: name state worst_service_state\nLimit: 100\n" view = "host" if mode == "problems": view = "problemsofhost" # Exclude hosts and services in downtime svc_query = "GET services\nColumns: host_name\n"\ "Filter: state > 0\nFilter: scheduled_downtime_depth = 0\n"\ "Filter: host_scheduled_downtime_depth = 0\nAnd: 3" problem_hosts = {x[1] for x in sites.live().query(svc_query)} query += "Filter: state > 0\nFilter: scheduled_downtime_depth = 0\nAnd: 2\n" for host in problem_hosts: query += "Filter: name = %s\n" % host query += "Or: %d\n" % (len(problem_hosts) + 1) hosts = sites.live().query(query) sites.live().set_prepend_site(False) hosts.sort() longestname = 0 for site, host, state, worstsvc in hosts: longestname = max(longestname, len(host)) if longestname > 15: num_columns = 1 else: num_columns = 2 target = views.get_context_link(config.user.id, view) html.open_table(class_="allhosts") col = 1 for site, host, state, worstsvc in hosts: if col == 1: html.open_tr() html.open_td() if state > 0 or worstsvc == 2: statecolor = 2 elif worstsvc == 1: statecolor = 1 elif worstsvc == 3: statecolor = 3 else: statecolor = 0 html.open_div(class_=["statebullet", "state%d" % statecolor]) html.nbsp() html.close_div() link(host, target + "&host=%s&site=%s" % (html.urlencode(host), html.urlencode(site))) html.close_td() if col == num_columns: html.close_tr() col = 1 else: col += 1 if col < num_columns: html.close_tr() html.close_table()
def render(self, what): html.open_table() html.open_tr() html.open_td() html.write_text("%s: " % _("Plugin output")) html.close_td() html.open_td() html.text_input("_fake_output", "", size=50) html.close_td() html.close_tr() html.open_tr() html.open_td() html.write_text("%s: " % _("Performance data")) html.close_td() html.open_td() html.text_input("_fake_perfdata", "", size=50) html.close_td() html.close_tr() html.open_tr() html.open_td() html.write_text(_("Result:")) html.close_td() html.open_td() if what == "host": html.button("_fake_0", _("Up")) html.button("_fake_1", _("Down")) else: html.button("_fake_0", _("OK")) html.button("_fake_1", _("Warning")) html.button("_fake_2", _("Critical")) html.button("_fake_3", _("Unknown")) html.close_td() html.close_tr() html.close_table()