def _push_snapshot_to_site(self): """Calls a remote automation call push-snapshot which is handled by AutomationPushSnapshot()""" site = config.site(self._site_id) url = html.makeuri_contextless( [ ("command", "push-snapshot"), ("secret", site["secret"]), ("siteid", site["id"]), ("debug", config.debug and "1" or ""), ], filename=site["multisiteurl"] + "automation.py", ) response_text = self._upload_file(url, site.get('insecure', False)) try: return ast.literal_eval(response_text) except SyntaxError: raise cmk.gui.watolib.automations.MKAutomationException( _("Garbled automation response: <pre>%s</pre>") % (html.attrencode(response_text)))
def render(self, what, row, tags, custom_vars): if what == "service" and config.wato_enabled and config.user.may( "wato.use"): command = row["service_check_command"] if command.startswith("check_mk-"): check_type = command[9:] elif command.startswith("check_mk_active-"): check_name = command[16:].split("!")[0] check_type = "check_" + check_name elif command in ["check-mk", "check-mk-inventory"]: if command == "check-mk": check_type = "check-mk" elif command == "check-mk-inventory": check_type = "check-mk-inventory" else: return else: return urlvars = [("mode", "check_manpage"), ("check_type", check_type)] return 'check_plugins', _( "Manual page for this check type"), html.makeuri_contextless( urlvars, "wato.py")
def render(self, what, row, tags, custom_vars): # Link to aggregations of the host/service # When precompile on demand is enabled, this icon is displayed for all hosts/services # otherwise only for the hosts/services which are part of aggregations. if config.bi_precompile_on_demand \ or bi.is_part_of_aggregation(what, row["site"], row["host_name"], row.get("service_description")): view_name = "aggr_%s" % what if not config.user.may("view.%s" % view_name): return urivars = [ ("view_name", view_name), ("aggr_%s_site" % what, row["site"]), ("aggr_%s_host" % what, row["host_name"]), ] if what == "service": urivars += [("aggr_service_service", row["service_description"])] url = html.makeuri_contextless(urivars, filename="view.py") return 'aggr', _("BI Aggregations containing this %s") % \ (what == "host" and _("Host") or _("Service")), url
def _show_ruleset(self, varname): if varname not in rulespec_registry: return rulespec = rulespec_registry[varname] url = html.makeuri_contextless([("mode", "edit_ruleset"), ("varname", varname)]) param_ruleset = html.render_a(rulespec.title, url) html.open_tr() html.th(_("Parameter rule set")) html.open_td() html.icon_button(url, _("Edit parameter rule set for this check type"), "check_parameters") html.write(param_ruleset) html.close_td() html.close_tr() html.open_tr() html.th(_("Example for Parameters")) html.open_td() vs = rulespec.valuespec vs.render_input("dummy", vs.default_value()) html.close_td() html.close_tr()
def do_execute(self, diagnostics_params, job_interface): # type: (DiagnosticsParams, BackgroundProcessInterface) -> None job_interface.send_progress_update(_("Diagnostics dump started...")) site = diagnostics_params["site"] timeout = html.request.request_timeout - 2 result = check_mk_automation(site, "create-diagnostics-dump", timeout=timeout, non_blocking_http=True) job_interface.send_progress_update(result["output"]) tarfile_path = result['tarfile_path'] download_url = html.makeuri_contextless( [("site", site), ("tarfile_name", str(Path(tarfile_path)))], "download_diagnostics_dump.py") button = html.render_icon_button(download_url, _("Download"), "diagnostics_dump_file") job_interface.send_progress_update(_("Dump file: %s") % tarfile_path) job_interface.send_result_message( _("%s Creating dump file successfully") % button)
def _show_site_status(self): if not self.parameters().get("show_sites_not_connected"): return sites_not_connected = [ site_id for site_id, site_status in sites.states().items() if site_status["state"] != "online" ] if len(sites_not_connected) == 0: return html.open_div(class_="spacertop") html.open_div(class_="tacticalalert") message_template = ungettext("%d site is not connected", "%d sites are not connected", len(sites_not_connected)) tooltip_template = ungettext( "Associated hosts, services and events are not included " "in the Tactical Overview. The disconnected site is %s.", "Associated hosts, services and events are not included " "in the Tactical Overview. The disconnected sites are %s.", len(sites_not_connected)) message = message_template % len(sites_not_connected) tooltip = tooltip_template % ', '.join(sites_not_connected) if config.user.may("wato.sites"): url = html.makeuri_contextless([("mode", "sites")], filename="wato.py") html.icon_button(url, tooltip, "sites", target="main") html.a(message, target="main", href=url) else: html.icon(tooltip, "sites") html.write_text(message) html.close_div() html.close_div()
def _paint_download_host_info(what, row, tags, host_custom_vars, ty): if (what == "host" or (what == "service" and row["service_description"] == "Check_MK")) \ and config.user.may("wato.download_agent_output") \ and not row["host_check_type"] == 2: # Not for shadow hosts # Not 100% acurate to use the tags here, but this is the best we can do # with the available information. # Render "download agent output" for non agent hosts, because there might # be piggyback data available which should be downloadable. if ty == "walk" and "snmp" not in tags: return if ty == "agent" and "snmp" in tags and "tcp" not in tags: return params = [ ("host", row["host_name"]), ("folder", _wato_folder_from_filename(row["host_filename"])), ("type", ty), ("_start", "1"), ] # When the download icon is part of the host/service action menu, then # the _back_url set in paint_action_menu() needs to be used. Otherwise # html.makeuri([]) (not html.requested_uri()) is the right choice. back_url = html.get_url_input("_back_url", html.makeuri([])) if back_url: params.append(("back_url", back_url)) if ty == "agent": title = _("Download agent output") else: title = _("Download SNMP walk") url = html.makeuri_contextless(params, filename="fetch_agent_output.py") return "agent_output", title, url
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 = html.makeuri_contextless([("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 services_url(site, host_name): return html.makeuri_contextless([("view_name", "host"), ("site", site), ("host", host_name)], filename="view.py")
def buttons(self): global_buttons() html.context_button(self._new_context_button_label(), html.makeuri_contextless([("mode", self._mode_type.edit_mode_name())]), "new")
def _back_url(self) -> str: return html.makeuri_contextless([("mode", "users")], filename="wato.py")
def render(self, what, row, tags, custom_vars): url = html.makeuri_contextless([("hostnames", json.dumps([row["host_name"]]))], filename="parent_child_topology.py") return "aggr", _("Host Parent/Child topology"), url
def show(self): pie_id = "dashlet_%d" % self._dashlet_id pie_diameter = 130 pie_left_aspect = 0.5 pie_right_aspect = 0.8 table = self._table() filter_headers, only_sites = visuals.get_filter_headers( table=self._livestatus_table(), infos=self.infos(), context=self.context) query = "GET %s\n" % self._livestatus_table() for entry in table: query += entry[3] query += self._filter() + filter_headers if only_sites: try: sites.live().set_only_sites(only_sites) result = sites.live().query_row(query) finally: sites.live().set_only_sites() else: try: result = sites.live().query_summed_stats(query) except MKLivestatusNotFoundError: result = [] pies = list(zip(table, result)) total = sum([x[1] for x in pies]) html.open_div(class_="stats") html.canvas('', class_="pie", id_="%s_stats" % pie_id, width=pie_diameter, height=pie_diameter, style="float: left") html.img(html.theme_url("images/globe.png"), class_="globe") html.open_table(class_=["hoststats"] + (["narrow"] if len(pies) > 0 else []), style="float:left") table_entries = pies while len(table_entries) < 6: table_entries = table_entries + [( ("", None, [], ""), HTML(" "))] table_entries.append(((_("Total"), "", [], ""), total)) for (name, color, table_url_vars, query), count in table_entries: url_vars = [ ("view_name", self._view_name()), ("filled_in", "filter"), ("search", "1"), ] + table_url_vars + self._dashlet_context_vars() url = html.makeuri_contextless(url_vars, filename="view.py") html.open_tr() html.th(html.render_a(name, href=url)) html.td('', class_="color", style="background-color: %s" % color if color else '') html.td(html.render_a(count, href=url)) html.close_tr() html.close_table() pie_parts = [] if total > 0: # Count number of non-empty classes num_nonzero = 0 for _info, value in pies: if value > 0: num_nonzero += 1 # Each non-zero class gets at least a view pixels of visible thickness. # We reserve that space right now. All computations are done in percent # of the radius. separator = 0.02 # 3% of radius remaining_separatorspace = num_nonzero * separator # space for separators remaining_radius = 1 - remaining_separatorspace # remaining space remaining_part = 1.0 # keep track of remaining part, 1.0 = 100% # Loop over classes, begin with most outer sphere. Inner spheres show # worse states and appear larger to the user (which is the reason we # are doing all this stuff in the first place) for (name, color, _unused, _q), value in pies[::1]: if value > 0 and remaining_part > 0: # skip empty classes # compute radius of this sphere *including all inner spheres!* The first # sphere always gets a radius of 1.0, of course. radius = remaining_separatorspace + remaining_radius * ( remaining_part**(1 / 3.0)) pie_parts.append('chart_pie("%s", %f, %f, %r, true);' % (pie_id, pie_right_aspect, radius, color)) pie_parts.append('chart_pie("%s", %f, %f, %r, false);' % (pie_id, pie_left_aspect, radius, color)) # compute relative part of this class part = float(value) / total # ranges from 0 to 1 remaining_part -= part remaining_separatorspace -= separator html.close_div() html.javascript( """ function chart_pie(pie_id, x_scale, radius, color, right_side) { var context = document.getElementById(pie_id + "_stats").getContext('2d'); if (!context) return; var pie_x = %(x)f; var pie_y = %(y)f; var pie_d = %(d)f; context.fillStyle = color; context.save(); context.translate(pie_x, pie_y); context.scale(x_scale, 1); context.beginPath(); if(right_side) context.arc(0, 0, (pie_d / 2) * radius, 1.5 * Math.PI, 0.5 * Math.PI, false); else context.arc(0, 0, (pie_d / 2) * radius, 0.5 * Math.PI, 1.5 * Math.PI, false); context.closePath(); context.fill(); context.restore(); context = null; } if (cmk.dashboard.has_canvas_support()) { %(p)s } """ % { "x": int(pie_diameter / 2.0), "y": int(pie_diameter / 2.0), "d": pie_diameter, 'p': '\n'.join(pie_parts) })
def page_url(self): return html.makeuri_contextless([(self.ident_attr(), self.name())], filename="%s.py" % self.type_name())
def buttons(self): html.context_button( _("Back"), html.makeuri_contextless([("mode", self.back_mode)]), "back")
def title_url(self): view_name = self._dashlet_spec["name"] return html.makeuri_contextless( [('view_name', view_name)] + list(self._dashlet_context_vars().iteritems()), filename='view.py')
def buttons(self): global_buttons() html.context_button( _("New %s") % self._mode_type.name_singular(), html.makeuri_contextless([("mode", self._mode_type.edit_mode_name())]), "new")
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 _search_url(self, ident): return html.makeuri_contextless([("mode", "rulesets"), ("search_p_rule_predefined_condition", DropdownChoice.option_id(ident)), ("search_p_rule_predefined_condition_USE", "on")])
def _breadcrumb_url(self) -> str: """Ensure the URL is computed correctly when linking from man pages to the topic""" return html.makeuri_contextless([("mode", self.name()), ("topic", self._topic)], filename="wato.py")
def render(self, what, row, tags, custom_vars): url = html.makeuri_contextless([("host_regex", "^%s$" % row["host_name"])], filename="parent_child_topology.py") return "aggr", _("Host Parent/Child topology"), url
def buttons(self): html.context_button( _("Back"), html.makeuri_contextless([ ("mode", self._mode_type.list_mode_name()) ]), "back")
def _breadcrumb_url(self) -> str: return html.makeuri_contextless([("mode", self.name()), ("edit", self._user_id)], filename="wato.py")