def render_input(self, varprefix, value): html.dropdown(varprefix + "attr_" + self.name(), self._enumlist, value)
def page(self): search = get_search_expression() search_form(_("Search for permissions: "), "edit_role") html.begin_form("role", method="POST") # ID forms.header(_("Basic Properties")) forms.section(_("Internal ID"), simple="builtin" in self._role) if self._role.get("builtin"): html.write_text("%s (%s)" % (self._role_id, _("builtin role"))) html.hidden_field("id", self._role_id) else: html.text_input("id", self._role_id) html.set_focus("id") # Alias forms.section(_("Alias")) html.help(_("An alias or description of the role")) html.text_input("alias", self._role.get("alias", ""), size=50) # Based on if not self._role.get("builtin"): forms.section(_("Based on role")) html.help( _("Each user defined role is based on one of the builtin roles. " "When created it will start with all permissions of that role. When due to a software " "update or installation of an addons new permissions appear, the user role will get or " "not get those new permissions based on the default settings of the builtin role it's " "based on.")) choices = [(i, r["alias"]) for i, r in self._roles.items() if r.get("builtin")] html.dropdown("basedon", choices, deflt=self._role.get("basedon", "user"), ordered=True) forms.end() html.h2(_("Permissions")) # Permissions base_role_id = self._role.get("basedon", self._role_id) html.help( _("When you leave the permissions at "default" then they get their " "settings from the factory defaults (for builtin roles) or from the " "factory default of their base role (for user define roles). Factory defaults " "may change due to software updates. When choosing another base role, all " "permissions that are on default will reflect the new base role.")) for section in permission_section_registry.get_sorted_sections(): # Now filter by the optional search term filtered_perms = [] for perm in permission_registry.get_sorted_permissions(section): if search and (search not in perm.title.lower() and search not in perm.name.lower()): continue filtered_perms.append(perm) if not filtered_perms: continue forms.header(section.title, isopen=search is not None) for perm in filtered_perms: forms.section(perm.title) pvalue = self._role["permissions"].get(perm.name) def_value = base_role_id in perm.defaults choices = [("yes", _("yes")), ("no", _("no")), ("default", _("default (%s)") % (def_value and _("yes") or _("no")))] deflt = {True: "yes", False: "no"}.get(pvalue, "default") html.dropdown("perm_" + perm.name, choices, deflt=deflt, style="width: 130px;") html.help(perm.description) forms.end() html.button("save", _("Save")) html.hidden_fields() html.end_form()
def page(self): # Let exceptions from loading notification scripts happen now watolib.load_notification_scripts() html.begin_form("user", method="POST") html.prevent_password_auto_completion() forms.header(_("Identity")) # ID forms.section(_("Username"), simple=not self._is_new_user) if self._is_new_user: vs_user_id = UserID(allow_empty=False) else: vs_user_id = FixedValue(self._user_id) vs_user_id.render_input("user_id", self._user_id) def lockable_input(name, dflt): if not self._is_locked(name): html.text_input(name, self._user.get(name, dflt), size=50) else: html.write_text(self._user.get(name, dflt)) html.hidden_field(name, self._user.get(name, dflt)) # Full name forms.section(_("Full name")) lockable_input('alias', self._user_id) html.help(_("Full name or alias of the user")) # Email address forms.section(_("Email address")) email = self._user.get("email", "") if not self._is_locked("email"): EmailAddress().render_input("email", email) else: html.write_text(email) html.hidden_field("email", email) html.help( _("The email address is optional and is needed " "if the user is a monitoring contact and receives notifications " "via Email.")) forms.section(_("Pager address")) lockable_input('pager', '') html.help(_("The pager address is optional ")) if cmk_version.is_managed_edition(): forms.section(self._vs_customer.title()) self._vs_customer.render_input("customer", managed.get_customer_id(self._user)) html.help(self._vs_customer.help()) vs_sites = self._vs_sites() forms.section(vs_sites.title()) authorized_sites = self._user.get("authorized_sites", vs_sites.default_value()) if not self._is_locked("authorized_sites"): vs_sites.render_input("authorized_sites", authorized_sites) else: html.write_html(vs_sites.value_to_text(authorized_sites)) html.help(vs_sites.help()) self._show_custom_user_attributes('ident') forms.header(_("Security")) forms.section(_("Authentication")) is_automation = self._user.get("automation_secret", None) is not None html.radiobutton("authmethod", "password", not is_automation, _("Normal user login with password")) html.open_ul() html.open_table() html.open_tr() html.td(_("password:"******"_password_" + self._pw_suffix(), autocomplete="new-password") html.close_td() html.close_tr() html.open_tr() html.td(_("repeat:")) html.open_td() html.password_input("_password2_" + self._pw_suffix(), autocomplete="new-password") html.write_text(" (%s)" % _("optional")) html.close_td() html.close_tr() html.open_tr() html.td("%s:" % _("Enforce change")) html.open_td() # Only make password enforcement selection possible when user is allowed to change the PW uid = None if self._user_id is None else UserId(self._user_id) if (self._is_new_user or (config.user_may(uid, 'general.edit_profile') and config.user_may(uid, 'general.change_password'))): html.checkbox( "enforce_pw_change", self._user.get("enforce_pw_change", False), label=_("Change password at next login or access")) else: html.write_text( _("Not permitted to change the password. Change can not be enforced." )) else: html.i( _('The password can not be changed (It is locked by the user connector).' )) html.hidden_field('_password', '') html.hidden_field('_password2', '') html.close_td() html.close_tr() html.close_table() html.close_ul() html.radiobutton("authmethod", "secret", is_automation, _("Automation secret for machine accounts")) html.open_ul() html.text_input("_auth_secret", self._user.get("automation_secret", ""), size=30, id_="automation_secret") html.write_text(" ") html.open_b(style=["position: relative", "top: 4px;"]) html.write(" ") html.icon_button( "javascript:cmk.wato.randomize_secret('automation_secret', 20);", _("Create random secret"), "random") html.close_b() html.close_ul() html.help( _("If you want the user to be able to login " "then specify a password here. Users without a login make sense " "if they are monitoring contacts that are just used for " "notifications. The repetition of the password is optional. " "<br>For accounts used by automation processes (such as fetching " "data from views for further procession), set the method to " "<u>secret</u>. The secret will be stored in a local file. Processes " "with read access to that file will be able to use Multisite as " "a webservice without any further configuration.")) # Locking forms.section(_("Disable password"), simple=True) if not self._is_locked('locked'): html.checkbox("locked", self._user.get("locked", False), label=_("disable the login to this account")) else: html.write_text( _('Login disabled') if self._user. get("locked", False) else _('Login possible')) html.hidden_field('locked', '1' if self._user.get("locked", False) else '') html.help( _("Disabling the password will prevent a user from logging in while " "retaining the original password. Notifications are not affected " "by this setting.")) forms.section(_("Idle timeout")) idle_timeout = self._user.get("idle_timeout") if not self._is_locked("idle_timeout"): watolib.get_vs_user_idle_timeout().render_input( "idle_timeout", idle_timeout) else: html.write_text(idle_timeout) html.hidden_field("idle_timeout", idle_timeout) # Roles forms.section(_("Roles")) is_member_of_at_least_one = False for role_id, role in sorted(self._roles.items(), key=lambda x: (x[1]["alias"], x[0])): if not self._is_locked("roles"): html.checkbox("role_" + role_id, role_id in self._user.get("roles", [])) url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", role_id)]) html.a(role["alias"], href=url) html.br() else: is_member = role_id in self._user.get("roles", []) if is_member: is_member_of_at_least_one = True url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", role_id)]) html.a(role["alias"], href=url) html.br() html.hidden_field("role_" + role_id, '1' if is_member else '') if self._is_locked('roles') and not is_member_of_at_least_one: html.i(_('No roles assigned.')) self._show_custom_user_attributes('security') # Contact groups forms.header(_("Contact Groups"), isopen=False) forms.section() groups_page_url = watolib.folder_preserving_link([("mode", "contact_groups")]) group_assign_url = watolib.folder_preserving_link([ ("mode", "rulesets"), ("group", "grouping") ]) if not self._contact_groups: html.write( _("Please first create some <a href='%s'>contact groups</a>") % groups_page_url) else: entries = sorted([(group['alias'] or c, c) for c, group in self._contact_groups.items()]) is_member_of_at_least_one = False for alias, gid in entries: is_member = gid in self._user.get("contactgroups", []) if not self._is_locked('contactgroups'): html.checkbox("cg_" + gid, gid in self._user.get("contactgroups", [])) else: if is_member: is_member_of_at_least_one = True html.hidden_field("cg_" + gid, '1' if is_member else '') if not self._is_locked('contactgroups') or is_member: url = watolib.folder_preserving_link([ ("mode", "edit_contact_group"), ("edit", gid) ]) html.a(alias, href=url) html.br() if self._is_locked( 'contactgroups') and not is_member_of_at_least_one: html.i(_('No contact groups assigned.')) html.help( _("Contact groups are used to assign monitoring " "objects to users. If you haven't defined any contact groups yet, " "then first <a href='%s'>do so</a>. Hosts and services can be " "assigned to contact groups using <a href='%s'>rules</a>.<br><br>" "If you do not put the user into any contact group " "then no monitoring contact will be created for the user.") % (groups_page_url, group_assign_url)) forms.header(_("Notifications"), isopen=False) if not self._rbn_enabled(): forms.section(_("Enabling"), simple=True) html.checkbox("notifications_enabled", self._user.get("notifications_enabled", False), label=_("enable notifications")) html.help( _("Notifications are sent out " "when the status of a host or service changes.")) # Notification period forms.section(_("Notification time period")) user_np = self._user.get("notification_period") if not isinstance(user_np, str): raise Exception("invalid notification period %r" % (user_np, )) choices: Choices = [(id_, "%s" % (tp["alias"])) for (id_, tp) in self._timeperiods.items()] html.dropdown("notification_period", choices, deflt=user_np, ordered=True) html.help( _("Only during this time period the " "user will get notifications about host or service alerts.")) # Notification options notification_option_names = { # defined here: _() must be executed always! "host": { "d": _("Host goes down"), "u": _("Host gets unreachble"), "r": _("Host goes up again"), }, "service": { "w": _("Service goes into warning state"), "u": _("Service goes into unknown state"), "c": _("Service goes into critical state"), "r": _("Service recovers to OK"), }, "both": { "f": _("Start or end of flapping state"), "s": _("Start or end of a scheduled downtime"), } } forms.section(_("Notification Options")) for title, what, opts in [(_("Host events"), "host", "durfs"), (_("Service events"), "service", "wucrfs")]: html.write_text("%s:" % title) html.open_ul() user_opts = self._user.get(what + "_notification_options", opts) for opt in opts: opt_name = notification_option_names[what].get( opt, notification_option_names["both"].get(opt)) html.checkbox(what + "_" + opt, opt in user_opts, label=opt_name) html.br() html.close_ul() html.help( _("Here you specify which types of alerts " "will be notified to this contact. Note: these settings will only be saved " "and used if the user is member of a contact group.")) forms.section(_("Notification Method")) watolib.get_vs_flexible_notifications().render_input( "notification_method", self._user.get("notification_method")) else: forms.section(_("Fallback notifications"), simple=True) html.checkbox("fallback_contact", self._user.get("fallback_contact", False), label=_("Receive fallback notifications")) html.help( _("In case none of your notification rules handles a certain event a notification " "will be sent to this contact. This makes sure that in that case at least <i>someone</i> " "gets notified. Furthermore this contact will be used for notifications to any host or service " "that is not known to the monitoring. This can happen when you forward notifications " "from the Event Console.<br><br>Notification fallback can also configured in the global " "setting <a href=\"wato.py?mode=edit_configvar&varname=notification_fallback_email\">" "Fallback email address for notifications</a>.")) self._show_custom_user_attributes('notify') forms.header(_("Personal Settings"), isopen=False) select_language(self._user) self._show_custom_user_attributes('personal') # Later we could add custom macros here, which then could be used # for notifications. On the other hand, if we implement some check_mk # --notify, we could directly access the data in the account with the need # to store values in the monitoring core. We'll see what future brings. forms.end() if self._is_new_user: html.set_focus("user_id") else: html.set_focus("alias") html.hidden_fields() html.end_form()
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')) dashboard.load_dashboards() topic_views = visuals_by_topic(views.get_permitted_views().items() + dashboard.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", user_folders.values()[0], 'cmk.sidebar.wato_tree_click')
def page(self): # TODO: remove subclass specific things specifict things (everything with _type == 'user') html.begin_form("attr") forms.header(_("Properties")) forms.section(_("Name"), simple=not self._new) html.help( _("The name of the attribute is used as an internal key. It cannot be " "changed later.")) if self._new: html.text_input("name", self._attr.get('name', '')) html.set_focus("name") else: html.write_text(self._name) html.set_focus("title") forms.section(_("Title") + "<sup>*</sup>") html.help(_("The title is used to label this attribute.")) html.text_input("title", self._attr.get('title', '')) forms.section(_('Topic')) html.help( _('The attribute is added to this section in the edit dialog.')) html.dropdown('topic', self._topics, deflt=self._attr.get('topic', self._default_topic)) forms.section(_('Help Text') + "<sup>*</sup>") html.help( _('You might want to add some helpful description for the attribute.' )) html.text_area('help', self._attr.get('help', '')) forms.section(_('Data type')) html.help(_('The type of information to be stored in this attribute.')) if self._new: html.dropdown('type', custom_attr_types(), deflt=self._attr.get('type', '')) else: html.write(dict(custom_attr_types())[self._attr.get('type')]) self._add_extra_form_sections() forms.section(_('Show in WATO host table')) html.help( _('This attribute is only visibile on the edit host and folder pages by default, but ' 'you can also make it visible in the host overview tables of WATO.' )) html.checkbox( 'show_in_table', self._attr.get('show_in_table', False), label=_( "Show the setting of the attribute in the WATO host list table" )) forms.section(_('Add to monitoring configuration')) html.help(self._macro_help) html.checkbox('add_custom_macro', self._attr.get('add_custom_macro', False), label=self._macro_label) forms.end() html.show_localization_hint() html.button("save", _("Save")) html.hidden_fields() html.end_form()
def page_graph(): host = html.request.get_str_input_mandatory("host") service = html.request.get_str_input_mandatory("service") dsname = html.request.get_str_input_mandatory("dsname") html.header(_("Prediction for %s - %s - %s") % (host, service, dsname)) # Get current value from perf_data via Livestatus current_value = get_current_perfdata(host, service, dsname) pred_dir = prediction.predictions_dir(host, service, dsname) if not os.path.exists(pred_dir): raise MKGeneralException( _("There is currently no prediction information " "available for this service.")) # Load all prediction information, sort by time of generation tg_name = html.request.var("timegroup") timegroup = None timegroups: List[prediction.PredictionInfo] = [] now = time.time() for f in os.listdir(pred_dir): if not f.endswith(".info"): continue tg_info = prediction.retrieve_data_for_prediction( pred_dir + "/" + f, "<unknown>" if timegroup is None else timegroup) if tg_info is None: continue tg_info["name"] = f[:-5] timegroups.append(tg_info) if tg_info["name"] == tg_name or (tg_name is None and (tg_info["range"][0] <= now <= tg_info["range"][1])): timegroup = tg_info tg_name = tg_info["name"] timegroups.sort(key=lambda x: x["range"][0]) choices = [(tg_info_["name"], tg_info_["name"].title()) for tg_info_ in timegroups] if not timegroup: if not timegroups: raise MKGeneralException(_("Missing prediction information.")) timegroup = timegroups[0] tg_name = choices[0][0] if tg_name is None: raise Exception("should not happen") html.begin_form("prediction") html.write(_("Show prediction for ")) html.dropdown("timegroup", choices, deflt=tg_name, onchange="document.prediction.submit();") html.hidden_fields() html.end_form() # Get prediction data path = pred_dir + "/" + timegroup["name"] tg_data = prediction.retrieve_data_for_prediction(path, tg_name) if tg_data is None: raise MKGeneralException(_("Missing prediction data.")) swapped = swap_and_compute_levels(tg_data, timegroup['params']) vertical_range = compute_vertical_range(swapped) legend = [ ("#000000", _("Reference")), ("#ffffff", _("OK area")), ("#ffff00", _("Warning area")), ("#ff0000", _("Critical area")), ] if current_value is not None: legend.append(("#0000ff", _("Current value: %.2f") % current_value)) create_graph(timegroup["name"], graph_size, timegroup["range"], vertical_range, legend) if "levels_upper" in timegroup['params']: render_dual_area(swapped["upper_warn"], swapped["upper_crit"], "#fff000", 0.4) render_area_reverse(swapped["upper_crit"], "#ff0000", 0.1) if "levels_lower" in timegroup['params']: render_dual_area(swapped["lower_crit"], swapped["lower_warn"], "#fff000", 0.4) render_area(swapped["lower_crit"], "#ff0000", 0.1) vscala_low = vertical_range[0] vscala_high = vertical_range[1] vert_scala = compute_vertical_scala(vscala_low, vscala_high) time_scala = [[timegroup["range"][0] + i * 3600, "%02d:00" % i] for i in range(0, 25, 2)] render_coordinates(vert_scala, time_scala) if "levels_lower" in timegroup['params']: render_dual_area(swapped["average"], swapped["lower_warn"], "#ffffff", 0.5) render_curve(swapped["lower_warn"], "#e0e000", square=True) render_curve(swapped["lower_crit"], "#f0b0a0", square=True) if "levels_upper" in timegroup['params']: render_dual_area(swapped["upper_warn"], swapped["average"], "#ffffff", 0.5) render_curve(swapped["upper_warn"], "#e0e000", square=True) render_curve(swapped["upper_crit"], "#f0b0b0", square=True) render_curve(swapped["average"], "#000000") render_curve(swapped["average"], "#000000") # repetition makes line bolder # Try to get current RRD data and render it also from_time, until_time = timegroup["range"] now = time.time() if from_time <= now <= until_time: timeseries = prediction.get_rrd_data(host, service, dsname, "MAX", from_time, until_time) rrd_data = timeseries.values render_curve(rrd_data, "#0000ff", 2) if current_value is not None: rel_time = (now - prediction.timezone_at(now)) % timegroup["slice"] render_point(timegroup["range"][0] + rel_time, current_value, "#0000ff") html.footer()
def render(self, what): html.write_text(_('Downtime Comment') + ": ") html.text_input("_down_comment", "", size=60, submit="") html.hr() html.button("_down_from_now", _("From now for")) html.nbsp() html.text_input("_down_minutes", default_value="60", size=4, submit="_down_from_now", cssclass="number") html.write_text(" " + _("minutes")) html.hr() for time_range in config.user_downtime_timeranges: html.button("_downrange__%s" % time_range['end'], _u(time_range['title'])) if what != "aggr" and config.user.may("action.remove_all_downtimes"): html.write_text(" - ") html.button("_down_remove", _("Remove all")) html.hr() if config.adhoc_downtime and config.adhoc_downtime.get("duration"): adhoc_duration = config.adhoc_downtime.get("duration") adhoc_comment = config.adhoc_downtime.get("comment", "") html.button("_down_adhoc", _("Adhoc for %d minutes") % adhoc_duration) html.nbsp() html.write_text(_('with comment') + ": ") html.write(adhoc_comment) html.hr() html.button("_down_custom", _("Custom time range")) self._vs_down_from().render_input("_down_from", time.time()) html.write_text(" " + _('to') + " ") self._vs_down_to().render_input("_down_to", time.time() + 7200) html.hr() html.checkbox("_down_flexible", False, label="%s " % _('flexible with max. duration')) self._vs_duration().render_input("_down_duration", 7200) if what == "host": html.hr() html.checkbox("_include_childs", False, label=_('Also set downtime on child hosts')) html.write_text(" ") html.checkbox("_include_childs_recurse", False, label=_('Do this recursively')) elif what == "service": html.hr() html.checkbox("_on_hosts", False, label=_('Schedule downtimes on the affected ' '<b>hosts</b> instead of on the individual ' 'services')) if self._has_recurring_downtimes(): html.hr() html.checkbox("_down_do_recur", False, label=_("Repeat this downtime on a regular basis every")) html.write_text(" ") from cmk.gui.cee.plugins.wato.cmc import recurring_downtimes_types # pylint: disable=no-name-in-module recurring_selections = [ (str(k), v) for (k, v) in sorted(recurring_downtimes_types().items()) ] html.dropdown("_down_recurring", recurring_selections, deflt="3") html.write_text(_("(This only works when using CMC)"))
def _preview(self) -> None: html.begin_form("preview", method="POST") self._preview_form() attributes = self._attribute_choices() # first line could be missing in situation of import error csv_reader = self._open_csv_file() if not csv_reader: return # don't try to show preview when CSV could not be read html.h2(_("Preview")) attribute_list = "<ul>%s</ul>" % "".join( ["<li>%s (%s)</li>" % a for a in attributes if a[0] is not None] ) html.help( _( "This list shows you the first 10 rows from your CSV file in the way the import is " "currently parsing it. If the lines are not splitted correctly or the title line is " "not shown as title of the table, you may change the import settings above and try " "again." ) + "<br><br>" + _( "The first row below the titles contains fields to specify which column of the " "CSV file should be imported to which attribute of the created hosts. The import " "progress is trying to match the columns to attributes automatically by using the " "titles found in the title row (if you have some). " "If you use the correct titles, the attributes can be mapped automatically. The " "currently available attributes are:" ) + attribute_list + _( "You can change these assignments according to your needs and then start the " "import by clicking on the <i>Import</i> button above." ) ) # Wenn bei einem Host ein Fehler passiert, dann wird die Fehlermeldung zu dem Host angezeigt, so dass man sehen kann, was man anpassen muss. # Die problematischen Zeilen sollen angezeigt werden, so dass man diese als Block in ein neues CSV-File eintragen kann und dann diese Datei # erneut importieren kann. if self._has_title_line: try: headers = list(next(csv_reader)) except StopIteration: headers = [] # nope, there is no header else: headers = [] rows = list(csv_reader) # Determine how many columns should be rendered by using the longest column num_columns = max([len(r) for r in [headers] + rows]) with table_element( sortable=False, searchable=False, omit_headers=not self._has_title_line ) as table: # Render attribute selection fields table.row() for col_num in range(num_columns): header = headers[col_num] if len(headers) > col_num else None table.cell(escape_html_permissive(header)) attribute_varname = "attribute_%d" % col_num if request.var(attribute_varname): attribute_method = request.get_ascii_input_mandatory(attribute_varname) else: attribute_method = self._try_detect_default_attribute(attributes, header) request.del_var(attribute_varname) html.dropdown( "attribute_%d" % col_num, attributes, deflt=attribute_method, autocomplete="off" ) # Render sample rows for row in rows: table.row() for cell in row: table.cell(None, cell) html.end_form()
def display(self): html.dropdown("site", self._choices())
def page_graph(): host = request.get_str_input_mandatory("host") service = request.get_str_input_mandatory("service") dsname = request.get_str_input_mandatory("dsname") breadcrumb = make_service_breadcrumb(host, service) html.header( _("Prediction for %s - %s - %s") % (host, service, dsname), breadcrumb) # Get current value from perf_data via Livestatus current_value = get_current_perfdata(host, service, dsname) prediction_store = prediction.PredictionStore(host, service, dsname) timegroup, choices = _load_prediction_information( tg_name=request.var("timegroup"), prediction_store=prediction_store, ) html.begin_form("prediction") html.write_text(_("Show prediction for ")) html.dropdown("timegroup", choices, deflt=timegroup.name, onchange="document.prediction.submit();") html.hidden_fields() html.end_form() # Get prediction data tg_data = prediction_store.get_data(timegroup.name) if tg_data is None: raise MKGeneralException(_("Missing prediction data.")) swapped = swap_and_compute_levels(tg_data, timegroup.params) vertical_range = compute_vertical_range(swapped) legend = [ ("#000000", _("Reference")), ("#ffffff", _("OK area")), ("#ffff00", _("Warning area")), ("#ff0000", _("Critical area")), ] if current_value is not None: legend.append(("#0000ff", _("Current value: %.2f") % current_value)) create_graph(timegroup.name, graph_size, timegroup.range, vertical_range, legend) if "levels_upper" in timegroup.params: render_dual_area(swapped["upper_warn"], swapped["upper_crit"], "#fff000", 0.4) render_area_reverse(swapped["upper_crit"], "#ff0000", 0.1) if "levels_lower" in timegroup.params: render_dual_area(swapped["lower_crit"], swapped["lower_warn"], "#fff000", 0.4) render_area(swapped["lower_crit"], "#ff0000", 0.1) vscala_low = vertical_range[0] vscala_high = vertical_range[1] vert_scala = compute_vertical_scala(vscala_low, vscala_high) time_scala = [[timegroup.range[0] + i * 3600, "%02d:00" % i] for i in range(0, 25, 2)] render_coordinates(vert_scala, time_scala) if "levels_lower" in timegroup.params: render_dual_area(swapped["average"], swapped["lower_warn"], "#ffffff", 0.5) render_curve(swapped["lower_warn"], "#e0e000", square=True) render_curve(swapped["lower_crit"], "#f0b0a0", square=True) if "levels_upper" in timegroup.params: render_dual_area(swapped["upper_warn"], swapped["average"], "#ffffff", 0.5) render_curve(swapped["upper_warn"], "#e0e000", square=True) render_curve(swapped["upper_crit"], "#f0b0b0", square=True) render_curve(swapped["average"], "#000000") render_curve(swapped["average"], "#000000") # repetition makes line bolder # Try to get current RRD data and render it also from_time, until_time = timegroup.range now = time.time() if from_time <= now <= until_time: timeseries = prediction.get_rrd_data(host, service, dsname, "MAX", from_time, until_time) rrd_data = timeseries.values render_curve(rrd_data, "#0000ff", 2) if current_value is not None: rel_time = (now - prediction.timezone_at(now)) % timegroup.slice render_point(timegroup.range[0] + rel_time, current_value, "#0000ff") html.footer()