def table_test_cubical(sortable, searchable, limit, output_format): import table html = TableTester() __builtin__.html = html # Test data rows = [(i, i**3) for i in range(10)] header = ["Number", "Cubical"] # Table options table_id = 0 title = " TEST " separator = ';' html.add_var('_%s_sort' % table_id, "1,0") html.add_var('_%s_actions' % table_id, '1') # Table construction table.begin(table_id=table_id, title=title, sortable=sortable, searchable=searchable, limit=limit, output_format=output_format) for row in rows: table.row() for i in range(len(header)): table.cell(_(header[i]), row[i]) table.end() # Get generated html text = html.written_text # Data assertions if not output_format in ['html', 'csv']: return False, 'Fetch is not yet implemented' if output_format == 'html': data = read_out_simple_table(text) if not data.pop(0) == header: return False, 'Wrong header' elif output_format == 'csv': data = read_out_csv(text, separator) limit = len(data) if not data.pop(0) == header: return False, 'Wrong header' else: return False, 'Not yet implemented' # Reconstruct table data data = [tuple(map(int, row)) for row in data if row and row[0]] if limit is None: limit = len(rows) # Assert data correctness if not len(data) <= limit: return False, 'Wrong number of rows: Got %s, should be <= %s' % ( len(data), limit) if not data == rows[:limit]: return False, "Incorrect data: %s\n\nVS\n%s" % (data, rows[:limit]) return True, ''
def output_availability_csv(what, av_data, avoptions): def cells_from_row(object_titles, cell_titles, row_object, row_cells): for title, (name, url) in zip(object_titles, row_object): table.cell(title, name) for (title, help), (text, css) in zip(cell_titles, row_cells): table.cell(title, text) av_output_set_content_disposition(_("Check_MK-Availability")) availability_tables = availability.compute_availability_groups(what, av_data, avoptions) table.begin("av_items", output_format="csv") for group_title, availability_table in availability_tables: av_table = availability.layout_availability_table(what, group_title, availability_table, avoptions) pad = 0 for row in av_table["rows"]: table.row() cells_from_row(av_table["object_titles"], av_table["cell_titles"], row["object"], row["cells"]) # presumably all rows have the same width pad = len(row["object"]) - 1 table.row() cells_from_row( av_table["object_titles"], av_table["cell_titles"], [(_("Summary"), "")] + [("", "")] * pad, av_table["summary"], ) table.end()
def output_availability_csv(what, av_data, avoptions): def cells_from_row(object_titles, cell_titles, row_object, row_cells): for title, (name, url) in zip(object_titles, row_object): table.cell(title, name) for (title, help), (text, css) in zip(cell_titles, row_cells): table.cell(title, text) av_output_set_content_disposition(_("Check_MK-Availability")) availability_tables = availability.compute_availability_groups( what, av_data, avoptions) table.begin("av_items", output_format="csv") for group_title, availability_table in availability_tables: av_table = availability.layout_availability_table( what, group_title, availability_table, avoptions) pad = 0 for row in av_table["rows"]: table.row() cells_from_row(av_table["object_titles"], av_table["cell_titles"], row["object"], row["cells"]) # presumably all rows have the same width pad = len(row["object"]) - 1 table.row() cells_from_row(av_table["object_titles"], av_table["cell_titles"], [(_("Summary"), "")] + [("", "")] * pad, av_table["summary"]) table.end()
def dashlet_notify_users(nr, dashlet): html.write('<div class="notify_users">') table.begin("notify_users", sortable=False, searchable=False, omit_if_empty=True) for entry in sorted(notify.get_gui_messages(), key=lambda e: e["time"], reverse=True): if "dashlet" in entry["methods"]: table.row() msg_id = entry["id"] datetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(entry['time'])) message = entry["text"].replace("\n", " ") table.cell(_("Actions"), css="buttons", sortable=False) html.icon_button("", _("Delete"), "delete", onclick="delete_user_notification('%s', this);" % msg_id) table.cell(_("Message"), html.attrencode(message)) table.cell(_("Date"), datetime) table.end() html.javascript('function delete_user_notification(msg_id, btn) {' 'post_url("ajax_delete_user_notification.py", "id=" + msg_id);' 'var row = btn.parentNode.parentNode;' 'row.parentNode.removeChild(row);}') html.write("</div>")
def test_nesting(): from table import Table html = TableTester() __builtin__.html = html id = 0 title = " TEST " table = Table(id, title, searchable=False, sortable=False) table.row() table.cell("A", "1") table.cell("B", "") t2 = Table(id + 1, title + "2", searchable=False, sortable=False) t2.row() t2.cell("_", "+") t2.cell("|", "-") t2.end() table.end() text = html.written_text assert compare_html( text, '''<h3> TEST </h3> <table class="data oddeven"> <tr> <th> A </th> <th> B </th> </tr> <tr class="data odd0"> <td> 1 </td> <td> <h3> TEST 2</h3> <table class="data oddeven"> <tr><th>_</th><th>|</th></tr> <tr class="data odd0"><td>+</td><td>-</td></tr> </table> </td> </tr> </table>'''), text
def render_availability_timeline(what, av_entry, avoptions): html.open_h3() html.write("%s %s" % (_("Timeline of"), availability.object_title(what, av_entry))) html.close_h3() timeline_rows = av_entry["timeline"] if not timeline_rows: html.div(_("No information available"), class_="info") return timeline_layout = availability.layout_timeline( what, timeline_rows, av_entry["considered_duration"], avoptions, "standalone") render_timeline_bar(timeline_layout, "standalone") render_date = timeline_layout["render_date"] render_number = availability.render_number_function(avoptions) # TODO: Hier fehlt bei BI der Timewarpcode (also der Baum im Zauberzustand) # if what == "bi": # render_timewarp( # Table with detailed events table.begin("av_timeline", "", css="timelineevents") for row_nr, row in enumerate(timeline_layout["table"]): table.row() table.cell(_("Links"), css="buttons") if what == "bi": url = html.makeuri([("timewarp", str(int(row["from"])))]) if html.var("timewarp") and int(html.var("timewarp")) == int( row["from"]): html.disabled_icon_button("timewarp_off") else: html.icon_button( url, _("Time warp - show BI aggregate during this time period"), "timewarp") else: url = html.makeuri([("anno_site", av_entry["site"]), ("anno_host", av_entry["host"]), ("anno_service", av_entry["service"]), ("anno_from", str(row["from"])), ("anno_until", str(row["until"]))]) html.icon_button(url, _("Create an annotation for this period"), "annotation") table.cell(_("From"), row["from_text"], css="nobr narrow") table.cell(_("Until"), row["until_text"], css="nobr narrow") table.cell(_("Duration"), row["duration_text"], css="narrow number") table.cell(_("State"), row["state_name"], css=row["css"] + " state narrow") table.cell(_("Last Known Plugin Output"), row.get("log_output", "")) table.end() # Legend for timeline if "display_timeline_legend" in avoptions["labelling"]: render_timeline_legend(what)
def test_nesting_context(): import table html = TableTester() __builtin__.html = html id = 0 title = " TEST " with table.open(table_id=id, title=title, searchable=False, sortable=False): table.row() table.cell("A", "1") table.cell("B", "") with table.open(id + 1, title + "2", searchable=False, sortable=False): table.row() table.cell("_", "+") table.cell("|", "-") text = html.written_text assert compare_html( text, '''<h3> TEST </h3> <table class="data oddeven"> <tr> <th> A </th> <th> B </th> </tr> <tr class="data odd0"> <td> 1 </td> <td> <h3> TEST 2</h3> <table class="data oddeven"> <tr><th>_</th><th>|</th></tr> <tr class="data odd0"><td>+</td><td>-</td></tr> </table> </td> </tr> </table>'''), text
def render_availability_table(group_title, availability_table, what, avoptions): av_table = availability.layout_availability_table(what, group_title, availability_table, avoptions) # TODO: If summary line is activated, then sorting should now move that line to the # top. It should also stay at the bottom. This would require an extension to the # table.py module. table.begin("av_items", av_table["title"], css="availability", searchable=False, limit=None, omit_headers="omit_headers" in avoptions["labelling"]) for row in av_table["rows"]: table.row() # Column with icons timeline_url = None if row["urls"]: table.cell("", css="buttons") for image, tooltip, url in row["urls"]: html.icon_button(url, tooltip, image) if image == "timeline": timeline_url = url # Column with host/service or aggregate name for title, (name, url) in zip(av_table["object_titles"], row["object"]): table.cell(title, '<a href="%s">%s</a>' % (url, name)) if "timeline" in row: table.cell(_("Timeline"), css="timeline") html.open_a(href=timeline_url) render_timeline_bar(row["timeline"], "inline") html.close_a() # Columns with the actual availability data for (title, help), (text, css) in zip(av_table["cell_titles"], row["cells"]): table.cell(title, text, css=css, help=help) if "summary" in av_table: table.row(css="summary") if row["urls"]: table.cell("", "") # Empty cell in URLs column table.cell("", _("Summary"), css="heading") for x in range(1, len(av_table["object_titles"])): table.cell("", "") # empty cells, of more object titles than one if "timeline" in row: table.cell("", "") for (title, help), (text, css) in zip(av_table["cell_titles"], av_table["summary"]): table.cell(title, text, css="heading " + css, help=help) return table.end() # returns Table data if fetch == True
def list_logs(site, host_name, logfile_names): table.begin(empty_text=_("No logs found for this host.")) for file_name in logfile_names: table.row() file_display = form_file_to_ext(file_name) logfile_link = "<a href=\"%s\">%s</a></td>\n" % \ (html.makeuri([('site', site), ('host', host_name), ('file', file_display)]), html.attrencode(file_display)) try: log_chunks = parse_file(site, host_name, file_name) if log_chunks == None: continue # Logfile vanished worst_log = get_worst_chunk(log_chunks) last_log = get_last_chunk(log_chunks) state = worst_log['level'] state_name = form_level(state) table.cell(_("Level"), state_name, css="state%d" % state) table.cell(_("Logfile"), logfile_link) table.cell(_("Last Entry"), form_datetime(last_log['datetime'])) table.cell(_("Entries"), len(log_chunks), css="number") except Exception, e: if config.debug: raise table.cell(_("Level"), "") table.cell(_("Logfile"), logfile_link) table.cell(_("Last Entry"), "") table.cell(_("Entries"), _("Corrupted"))
def list_logs(site, host_name, logfile_names): table.begin(empty_text = _("No logs found for this host.")) for file_name in logfile_names: table.row() file_display = form_file_to_ext(file_name) logfile_link = "<a href=\"%s\">%s</a></td>\n" % \ (html.makeuri([('site', site), ('host', host_name), ('file', file_display)]), html.attrencode(file_display)) try: log_chunks = parse_file(site, host_name, file_name) if log_chunks == None: continue # Logfile vanished worst_log = get_worst_chunk(log_chunks) last_log = get_last_chunk(log_chunks) state = worst_log['level'] state_name = form_level(state) table.cell(_("Level"), state_name, css="state%d" % state) table.cell(_("Logfile"), logfile_link) table.cell(_("Last Entry"), form_datetime(last_log['datetime'])) table.cell(_("Entries"), len(log_chunks), css="number") except Exception, e: if config.debug: raise table.cell(_("Level"), "") table.cell(_("Logfile"), logfile_link) table.cell(_("Last Entry"), "") table.cell(_("Entries"), _("Corrupted"))
def dashlet_notify_users(nr, dashlet): html.open_div(class_="notify_users") table.begin("notify_users", sortable=False, searchable=False, omit_if_empty=True) for entry in sorted(notify.get_gui_messages(), key=lambda e: e["time"], reverse=True): if "dashlet" in entry["methods"]: table.row() msg_id = entry["id"] datetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(entry['time'])) message = entry["text"].replace("\n", " ") table.cell(_("Actions"), css="buttons", sortable=False) html.icon_button("", _("Delete"), "delete", onclick="delete_user_notification('%s', this);" % msg_id) table.cell(_("Message"), html.attrencode(message)) table.cell(_("Date"), datetime) table.end() html.javascript('function delete_user_notification(msg_id, btn) {' 'post_url("ajax_delete_user_notification.py", "id=" + msg_id);' 'var row = btn.parentNode.parentNode;' 'row.parentNode.removeChild(row);}') html.close_div()
def render_werks_table(): werk_table_options = render_werk_table_options() if html.var("show_unack") and not html.var("wo_set"): werk_table_options = default_werk_table_options() werk_table_options["compatibility"] = ["incomp_unack"] current_group = False def begin_group(title): table.begin(title=title, limit=None, searchable=False, sortable=False, css="werks") werklist = [] if werk_table_options["grouping"] == "version": werklist = werks_sorted_by_version(g_werks.values()) else: werklist = werks_sorted_by_date(g_werks.values()) for werk in werklist: if werk_matches_options(werk, werk_table_options): group = werk_group_value(werk, werk_table_options["grouping"]) if group != current_group: if current_group != False: table.end() begin_group(group) current_group = group table.row() table.cell(_("ID"), render_werk_id(werk, with_link=True), css="number narrow") table.cell(_("Version"), werk["version"], css="number narrow") table.cell(_("Date"), render_werk_date(werk), css="number narrow") table.cell(_("Class"), render_werk_class(werk), css="werkclass werkclass%s" % werk["class"]) table.cell(_("Level"), render_werk_level(werk), css="werklevel werklevel%d" % werk["level"]) table.cell(_("Compatibility"), render_werk_compatibility(werk), css="werkcomp werkcomp%s" % werk["compatible"]) table.cell(_("Component"), render_werk_component(werk), css="nowrap") table.cell(_("Title"), render_werk_title(werk)) if current_group != False: table.end() else: html.write("<h3>%s</h3>" % _("No matching Werks found."))
def render_availability_table(group_title, availability_table, what, avoptions): av_table = availability.layout_availability_table(what, group_title, availability_table, avoptions) # TODO: If summary line is activated, then sorting should now move that line to the # top. It should also stay at the bottom. This would require an extension to the # table.py module. table.begin( "av_items", av_table["title"], css="availability", searchable=False, limit=None, omit_headers="omit_headers" in avoptions["labelling"], ) for row in av_table["rows"]: table.row() # Column with icons timeline_url = None if row["urls"]: table.cell("", css="buttons") for image, tooltip, url in row["urls"]: html.icon_button(url, tooltip, image) if image == "timeline": timeline_url = url # Column with host/service or aggregate name for title, (name, url) in zip(av_table["object_titles"], row["object"]): table.cell(title, '<a href="%s">%s</a>' % (url, name)) if "timeline" in row: table.cell(_("Timeline"), css="timeline") html.write('<a href="%s">' % timeline_url) render_timeline_bar(row["timeline"], "inline") html.write("</a>") # Columns with the actual availability data for (title, help), (text, css) in zip(av_table["cell_titles"], row["cells"]): table.cell(title, text, css=css, help=help) if "summary" in av_table: table.row(css="summary") if row["urls"]: table.cell("", "") # Empty cell in URLs column table.cell("", _("Summary"), css="heading") for x in range(1, len(av_table["object_titles"])): table.cell("", "") # empty cells, of more object titles than one if "timeline" in row: table.cell("", "") for (title, help), (text, css) in zip(av_table["cell_titles"], av_table["summary"]): table.cell(title, text, css="heading " + css, help=help) return table.end() # returns Table data if fetch == True
def render_annotations(annotations, by_host, what, avoptions, omit_service): (from_time, until_time), range_title = avoptions["range"] format = "%H:%M:%S" if time.localtime(from_time)[:3] != time.localtime(until_time-1)[:3]: format = "%Y-%m-%d " + format def render_date(ts): return time.strftime(format, time.localtime(ts)) annos_to_render = [] for site_host, avail_entries in by_host.iteritems(): for service in avail_entries.keys(): site_host_svc = site_host[0], site_host[1], (service or None) for annotation in annotations.get(site_host_svc, []): if (annotation["from"] >= from_time and annotation["from"] <= until_time) or \ (annotation["until"] >= from_time and annotation["until"] <= until_time): annos_to_render.append((site_host_svc, annotation)) annos_to_render.sort(cmp=lambda a,b: cmp(a[1]["from"], b[1]["from"]) or cmp(a[0], b[0])) labelling = avoptions["labelling"] table.begin(title = _("Annotations"), omit_if_empty = True) for (site_id, host, service), annotation in annos_to_render: table.row() table.cell("", css="buttons") anno_vars = [ ( "anno_site", site_id ), ( "anno_host", host ), ( "anno_service", service or "" ), ( "anno_from", int(annotation["from"]) ), ( "anno_until", int(annotation["until"]) ), ] edit_url = html.makeuri(anno_vars) html.icon_button(edit_url, _("Edit this annotation"), "edit") delete_url = html.makeactionuri([("_delete_annotation", "1")] + anno_vars) html.icon_button(delete_url, _("Delete this annotation"), "delete") if not omit_service: if not "omit_host" in labelling: host_url = "view.py?" + html.urlencode_vars([("view_name", "hoststatus"), ("site", site_id), ("host", host)]) table.cell(_("Host"), '<a href="%s">%s</a>' % (host_url, host)) if service: service_url = "view.py?" + html.urlencode_vars([("view_name", "service"), ("site", site_id), ("host", host), ("service", service)]) # TODO: honor use_display_name. But we have no display names here... service_name = service table.cell(_("Service"), '<a href="%s">%s</a>' % (service_url, service_name)) table.cell(_("From"), render_date(annotation["from"]), css="nobr narrow") table.cell(_("Until"), render_date(annotation["until"]), css="nobr narrow") table.cell(_("Annotation"), html.attrencode(annotation["text"])) table.cell(_("Author"), annotation["author"]) table.cell(_("Entry"), render_date(annotation["date"]), css="nobr narrow") table.end()
def render_availability_timeline(what, av_entry, avoptions): html.write("<h3>%s %s</h3>" % (_("Timeline of"), availability.object_title(what, av_entry))) timeline_rows = av_entry["timeline"] if not timeline_rows: html.write("<div class=info>%s</div>" % _("No information available")) return timeline_layout = availability.layout_timeline( what, timeline_rows, av_entry["considered_duration"], avoptions, "standalone" ) render_timeline_bar(timeline_layout, "standalone") render_date = timeline_layout["render_date"] render_number = availability.render_number_function(avoptions) # TODO: Hier fehlt bei BI der Timewarpcode (also der Baum im Zauberzustand) # if what == "bi": # render_timewarp( # Table with detailed events table.begin("av_timeline", "", css="timelineevents") for row_nr, row in enumerate(timeline_layout["table"]): table.row() table.cell(_("Links"), css="buttons") if what == "bi": url = html.makeuri([("timewarp", str(int(row["from"])))]) if html.var("timewarp") and int(html.var("timewarp")) == int(row["from"]): html.disabled_icon_button("timewarp_off") else: html.icon_button(url, _("Time warp - show BI aggregate during this time period"), "timewarp") else: url = html.makeuri( [ ("anno_site", av_entry["site"]), ("anno_host", av_entry["host"]), ("anno_service", av_entry["service"]), ("anno_from", str(row["from"])), ("anno_until", str(row["until"])), ] ) html.icon_button(url, _("Create an annotation for this period"), "annotation") table.cell(_("From"), row["from_text"], css="nobr narrow") table.cell(_("Until"), row["until_text"], css="nobr narrow") table.cell(_("Duration"), row["duration_text"], css="narrow number") table.cell(_("State"), row["state_name"], css=row["css"] + " state narrow") table.cell(_("Last Known Plugin Output"), row.get("log_output", "")) table.end() # Legend for timeline if "display_timeline_legend" in avoptions["labelling"]: render_timeline_legend(what)
def output_availability_csv(what, av_data, avoptions): av_output_csv_mimetype(_("Check_MK-Availability")) availability_tables = availability.compute_availability_groups(what, av_data, avoptions) table.begin("av_items", output_format = "csv") for group_title, availability_table in availability_tables: av_table = availability.layout_availability_table(what, group_title, availability_table, avoptions) for row in av_table["rows"]: table.row() for title, (name, url) in zip(av_table["object_titles"], row["object"]): table.cell(title, name) for (title, help), (text, css) in zip(av_table["cell_titles"], row["cells"]): table.cell(title, text) table.end()
def render_notification_table(failed_notifications): table.begin() header = dict([(name, idx) for idx, name in enumerate(g_columns)]) for row in failed_notifications: table.row() table.cell(_("Time"), lib.age_human_readable(time.time() - row[header['time']])) table.cell(_("Contact"), row[header['contact_name']]) table.cell(_("Plugin"), row[header['type']]) table.cell(_("Host"), row[header['host_name']]) table.cell(_("Service"), row[header['service_description']]) table.cell(_("Output"), row[header['comment']]) table.end()
def render_notification_table(failed_notifications): table.begin(title=_("Failed Notifications")) #header = dict([(name, idx) for idx, name in enumerate(header)]) header = dict([(name, idx) for idx, name in enumerate(g_columns)]) for row in failed_notifications: table.row() table.cell(_("Time"), lib.age_human_readable(time.time() - row[header['time']])) table.cell(_("Contact"), row[header['contact_name']]) table.cell(_("Plugin"), row[header['type']]) table.cell(_("Host"), row[header['host_name']]) table.cell(_("Service"), row[header['service_description']]) table.cell(_("Output"), row[header['comment']]) table.end()
def render_annotations(annotations, av_rawdata, what, avoptions, omit_service): annos_to_render, render_date = get_relevant_annotations(annotations, av_rawdata, what, avoptions) table.begin(title = _("Annotations"), omit_if_empty = True) for (site_id, host, service), annotation in annos_to_render: table.row() table.cell("", css="buttons") anno_vars = [ ( "anno_site", site_id ), ( "anno_host", host ), ( "anno_service", service or "" ), ( "anno_from", int(annotation["from"]) ), ( "anno_until", int(annotation["until"]) ), ] edit_url = html.makeuri(anno_vars) html.icon_button(edit_url, _("Edit this annotation"), "edit") delete_url = html.makeactionuri([("_delete_annotation", "1")] + anno_vars) html.icon_button(delete_url, _("Delete this annotation"), "delete") if not omit_service: if not "omit_host" in avoptions["labelling"]: host_url = "view.py?" + html.urlencode_vars([("view_name", "hoststatus"), ("site", site_id), ("host", host)]) table.cell(_("Host"), '<a href="%s">%s</a>' % (host_url, host)) if what == "service": if service: service_url = "view.py?" + html.urlencode_vars([("view_name", "service"), ("site", site_id), ("host", host), ("service", service)]) # TODO: honor use_display_name. But we have no display names here... service_name = service table.cell(_("Service"), '<a href="%s">%s</a>' % (service_url, service_name)) else: table.cell(_("Service"), "") # Host annotation in service table table.cell(_("From"), render_date(annotation["from"]), css="nobr narrow") table.cell(_("Until"), render_date(annotation["until"]), css="nobr narrow") table.cell("", css="buttons") if annotation.get("downtime") == True: html.icon(_("This period has been reclassified as a scheduled downtime"), "downtime") elif annotation.get("downtime") == False: html.icon(_("This period has been reclassified as a not being a scheduled downtime"), "nodowntime") table.cell(_("Annotation"), html.render_text(annotation["text"])) table.cell(_("Author"), annotation["author"]) table.cell(_("Entry"), render_date(annotation["date"]), css="nobr narrow") table.end()
def page(self): table.begin(title=self._table_title(), searchable=False, sortable=False) for key_id, key in sorted(self.keys.items()): cert = crypto.load_certificate(crypto.FILETYPE_PEM, key["certificate"]) table.row() table.cell(_("Actions"), css="buttons") if self._may_edit_config(): delete_url = html.makeactionuri([("_delete", key_id)]) html.icon_button(delete_url, _("Delete this key"), "delete") download_url = html.makeuri_contextless([("mode", self.download_mode), ("key", key_id)]) html.icon_button(download_url, _("Download this key"), "download") table.cell(_("Description"), html.attrencode(key["alias"])) table.cell(_("Created"), date_human_readable(key["date"])) table.cell(_("By"), html.attrencode(key["owner"])) table.cell(_("Digest (MD5)"), html.attrencode(cert.digest("md5"))) table.end()
def page(self): table.begin(title = self._table_title(), searchable=False, sortable=False) for key_id, key in sorted(self.keys.items()): cert = crypto.load_certificate(crypto.FILETYPE_PEM, key["certificate"]) table.row() table.cell(_("Actions"), css="buttons") if self._may_edit_config(): delete_url = html.makeactionuri([("_delete", key_id)]) html.icon_button(delete_url, _("Delete this key"), "delete") download_url = html.makeuri_contextless([ ("mode", self.download_mode), ("key", key_id)]) html.icon_button(download_url, _("Download this key"), "download") table.cell(_("Description"), html.attrencode(key["alias"])) table.cell(_("Created"), date_human_readable(key["date"])) table.cell(_("By"), html.attrencode(key["owner"])) table.cell(_("Digest (MD5)"), html.attrencode(cert.digest("md5"))) table.end()
def render_werks_table(): werk_table_options = render_werk_table_options() if html.var("show_unack") and not html.var("wo_set"): werk_table_options = default_werk_table_options() werk_table_options["compatibility"] = [ "incomp_unack" ] current_group = False def begin_group(title): table.begin(title=title, limit=None, searchable = False, sortable = False, css="werks") werklist = [] if werk_table_options["grouping"] == "version": werklist = werks_sorted_by_version(g_werks.values()) else: werklist = werks_sorted_by_date(g_werks.values()) for werk in werklist: if werk_matches_options(werk, werk_table_options): group = werk_group_value(werk, werk_table_options["grouping"]) if group != current_group: if current_group != False: table.end() begin_group(group) current_group = group table.row() table.cell(_("ID"), render_werk_id(werk, with_link=True), css="number narrow") table.cell(_("Version"), werk["version"], css="number narrow") table.cell(_("Date"), render_werk_date(werk), css="number narrow") table.cell(_("Class"), render_werk_class(werk), css="werkclass werkclass%s" % werk["class"]) table.cell(_("Level"), render_werk_level(werk), css="werklevel werklevel%d" % werk["level"]) table.cell(_("Compatibility"), render_werk_compatibility(werk), css="werkcomp werkcomp%s" % werk["compatible"]) table.cell(_("Component"), render_werk_component(werk), css="nowrap") table.cell(_("Title"), render_werk_title(werk)) if current_group != False: table.end() else: html.write("<h3>%s</h3>" % _("No matching Werks found."))
def test_context(): import table html = TableTester() __builtin__.html = html table_id = 0 rows = [(i, i**3) for i in range(10)] header = ["Number", "Cubical"] with table.open(table_id=table_id, searchable=False, sortable=False): for row in rows: table.row() for i in range(len(header)): table.cell(_(header[i]), row[i]) text = html.written_text data = read_out_simple_table(text) assert data.pop(0) == header data = [tuple(map(int, row)) for row in data if row and row[0]] assert data == rows
def page_config(): is_admin = config.user.may('general.glpi_config') if not is_admin: config.user.need_permission('general.glpi_config') global glpi_config glpi_config = load_glpi_config() errlog = load_glpi_errlog() html.disable_request_timeout() html.header(_('GLPI Sync'), stylesheets=['pages', 'views', 'status', 'glpi']) html.begin_context_buttons() html.context_button(_('Sync now'), make_action_link([('_sync', 'true')]), icon='glpi', hot=do_sync(True)) html.end_context_buttons() html.begin_foldable_container( 'host_sync_errors', 'host_sync_errors', False, HTML('<b>HOST SYNC ERRORS (%d)</b>' % len(errlog))) table.begin(table_id='host_sync_errors', empty_text='No errors') for hostname in errlog: table.row() table.cell('Hostname', hostname) table.cell('Error', errlog[hostname]) table.end() html.end_foldable_container() settings = [] settings_elements = [ ( 'host', TextUnicode( title = _('GLPI Server'), allow_empty = False, )), ( 'db_name', TextUnicode( title = _('GLPI Database Name'), allow_empty = False, )), ( 'db_user', TextUnicode( title = _('GLPI Database User'), allow_empty = False, )), ( 'db_passwd', Password( title = _('GLPI Database Password'), allow_empty = False, )), ( 'states', ListChoice( title = _('Update hosts with these states'), orientation = 'horizontal', allow_empty = False, choices = [ ('prod', _('Production system'), ), ('uat', _('UAT system'), ), ('dev', _('Development system'), ), ] )), ( 'states_to_add', ListChoice( title = _('Add new hosts with these states'), orientation = 'horizontal', choices = [ ('prod', _('Production system'), ), ('uat', _('UAT system'), ), ('dev', _('Development system'), ), ], help = _('Add new hosts with these states only.') )), ( 'ignored_hosts', ListOfStrings( valuespec = RegExpUnicode(mode = RegExpUnicode.prefix), title = _('Do not add these hosts'), orientation = 'horizontal', elements = [], help = _('Do not add these hosts. Regular expressions are possible.') )), ( 'dns_suffixes', ListOfStrings( title = _('DNS suffixes to add'), orientation = 'horizontal', elements = [], help = _('DNS suffixes to add if hosts have them in their FQDN.') )), ( 'type_matches', ListOf( Tuple( show_titles = True, orientation = 'horizontal', elements = [ TextUnicode( title = _('Computer Type in GLPI'), ), TextUnicode( title = _('Internal ID type'), ), ], ), title = _('Host Tags: Type'), help = _('Substring match for Type from GLPI table "glpi_computertypes" to Internal ID "type".') )), ( 'os_matches', ListOf( Tuple( show_titles = True, orientation = 'horizontal', elements = [ TextUnicode( title = _('OS in GLPI'), ), TextUnicode( title = _('Internal ID os'), ), ], ), title = _('Host Tags: OS'), help = _('Substring match for OS from GLPI table "glpi_operatingsystems" to Internal ID "os".') )), ( 'discover_services', Checkbox( title = _('Discover services for new hosts'), label = _('Enable'), )), ( 'cron', Checkbox( title = _('Synchronization by Сron'), label = _('Enable'), )), ( 'cron_user', TextUnicode( title = _('User to run Cron job'), allow_empty = False, )), ( 'period', SchedulePeriod() ), ( 'timeofday', Timeofday( title = _('Time of day to run sync'), )), ] settings.append( ( 'general', Dictionary( title = _('Settings'), optional_keys = None, elements = settings_elements, )) ) edit_settings = { 'context' : visuals.pack_context_for_editing(glpi_config, None), 'general' : glpi_config, } dict_settings = forms.edit_dictionaries(settings, edit_settings, method='POST') if dict_settings != None: new_settings = dict_settings['general'] save_glpi_config(new_settings) html.immediate_browser_redirect(1, config_page) html.message(_('Your settings have been saved.')) html.footer()
def render_timeline(timeline_rows, from_time, until_time, considered_duration, timeline, range_title, render_number, what, timewarpcode): if not timeline_rows: html.write('<div class=info>%s</div>' % _("No information available")) return # Timeformat: show date only if the displayed time range spans over # more than one day. format = "%H:%M:%S" if time.localtime(from_time)[:3] != time.localtime(until_time - 1)[:3]: format = "%Y-%m-%d " + format def render_date(ts): return time.strftime(format, time.localtime(ts)) if type(timeline) == tuple: tl_site, tl_host, tl_service = timeline if tl_service: availability_columns = service_availability_columns else: availability_columns = host_availability_columns else: availability_columns = bi_availability_columns # Render graphical representation # Make sure that each cell is visible, if possible min_percentage = min(100.0 / len(timeline_rows), 1) rest_percentage = 100 - len(timeline_rows) * min_percentage html.write('<div class=timelinerange>') html.write('<div class=from>%s</div><div class=until>%s</div></div>' % (render_date(from_time), render_date(until_time))) html.write('<table class=timeline>') html.write('<tr class=timeline>') for row_nr, (row, state_id) in enumerate(timeline_rows): for sid, css, sname, help in availability_columns: if sid == state_id: title = _("From %s until %s (%s) %s") % ( render_date(row["from"]), render_date(row["until"]), render_number(row["duration"], considered_duration), sname) if row["log_output"]: title += " - " + row["log_output"] width = min_percentage + rest_percentage * row[ "duration"] / considered_duration html.write( '<td onmouseover="timeline_hover(%d, 1);" onmouseout="timeline_hover(%d, 0);" ' 'style="width: %.1f%%" title="%s" class="%s"></td>' % (row_nr, row_nr, width, title, css)) html.write('</tr></table>') # Render timewarped BI aggregate (might be empty) html.write(timewarpcode) # Render Table table.begin("", css="timelineevents") for row_nr, (row, state_id) in enumerate(timeline_rows): table.row() if what == "bi": table.cell(_("Links"), css="buttons") url = html.makeuri([("timewarp", str(int(row["from"])))]) html.icon_button( url, _("Time warp - show BI aggregate during this time period"), "timewarp") table.cell(_("From"), render_date(row["from"]), css="nobr narrow") table.cell(_("Until"), render_date(row["until"]), css="nobr narrow") table.cell(_("Duration"), render_number(row["duration"], considered_duration), css="narrow number") for sid, css, sname, help in availability_columns: if sid == state_id: table.cell(_("State"), sname, css=css + " state narrow") table.cell(_("Additional information"), row["log_output"]) table.end()
else: foreign_instances.append(instance) for title, instances in [ (_("Customized"), my_instances), (_("Owned by other users"), foreign_instances), (_("Builtin"), builtin_instances), ]: if not instances: continue html.write("<h3>" + title + "</h3>") table.begin(limit=None) for instance in instances: table.row() # Actions table.cell(_("Actions"), css="buttons visuals") # Clone / Customize buttontext = _("Create a customized copy of this") html.icon_button(instance.clone_url(), buttontext, "new_" + self.type_name()) # Delete if instance.may_delete(): html.icon_button(instance.delete_url(), _("Delete!"), "delete") # Edit # TODO: Reihenfolge der Aktionen. Ist nicht delete immer nach edit? Sollte # nicht clone und edit am gleichen Platz sein?
def render_availability_table(availability, from_time, until_time, range_title, what, avoptions, render_number): # Some columns might be unneeded due to state treatment options sg = avoptions["state_grouping"] state_groups = [sg["warn"], sg["unknown"], sg["host_down"]] # Helper function, needed in row and in summary line def cell_active(sid): if sid == "outof_notification_period" and avoptions[ "notification_period"] != "honor": return False elif sid == "in_downtime" and avoptions["downtimes"][ "include"] != "honor": return False elif sid == "unmonitored" and not avoptions["consider"]["unmonitored"]: return False elif sid == "flapping" and not avoptions["consider"]["flapping"]: return False elif sid in ["warn", "unknown", "host_down" ] and sid not in state_groups: return False else: return True # Render the stuff availability.sort() show_summary = what != "bi" and avoptions.get("summary") summary = {} table.begin(_("Availability") + " " + range_title, css="availability") for site, host, service, states, considered_duration in availability: table.row() if what != "bi": table.cell("", css="buttons") history_url = history_url_of(site, host, service, from_time, until_time) html.icon_button(history_url, _("Event History"), "history") timeline_url = html.makeuri([("timeline", "yes"), ("timeline_site", site), ("timeline_host", host), ("timeline_service", service)]) html.icon_button(timeline_url, _("Timeline"), "timeline") host_url = "view.py?" + htmllib.urlencode_vars( [("view_name", "hoststatus"), ("site", site), ("host", host)]) if what == "bi": bi_url = "view.py?" + htmllib.urlencode_vars( [("view_name", "aggr_single"), ("aggr_name", service)]) table.cell(_("Aggregate"), '<a href="%s">%s</a>' % (bi_url, service)) availability_columns = bi_availability_columns else: table.cell(_("Host"), '<a href="%s">%s</a>' % (host_url, host)) if what == "service": service_url = "view.py?" + htmllib.urlencode_vars( [("view_name", "service"), ("site", site), ("host", host), ("service", service)]) table.cell(_("Service"), '<a href="%s">%s</a>' % (service_url, service)) availability_columns = service_availability_columns else: availability_columns = host_availability_columns for sid, css, sname, help in availability_columns: if not cell_active(sid): continue number = states.get(sid, 0) if not number: css = "unused" elif show_summary: summary.setdefault(sid, 0.0) summary[sid] += number table.cell(sname, render_number(number, considered_duration), css="number " + css, help=help) if show_summary: table.row(css="summary") table.cell("") table.cell("", _("Summary")) if what == "service": table.cell("", "") considered_duration = until_time - from_time for sid, css, sname, help in availability_columns: if not cell_active(sid): continue number = summary.get(sid, 0) if show_summary == "average" or avoptions["timeformat"].startswith( "percentage"): number /= len(availability) if not number: css = "unused" table.cell(sname, render_number(number, considered_duration), css="number " + css, help=help) table.end()
def page_config(): is_admin = config.user.may('general.glpi_config') if not is_admin: config.user.need_permission('general.glpi_config') global glpi_config glpi_config = load_glpi_config() errlog = load_glpi_errlog() html.disable_request_timeout() html.header(_('GLPI Sync'), stylesheets=['pages', 'views', 'status', 'glpi']) html.begin_context_buttons() html.context_button(_('Sync now'), make_action_link([('_sync', 'true')]), icon='glpi', hot=do_sync(True)) html.end_context_buttons() html.begin_foldable_container( 'host_sync_errors', 'host_sync_errors', False, HTML('<b>HOST SYNC ERRORS (%d)</b>' % len(errlog))) table.begin(table_id='host_sync_errors', empty_text='No errors') for hostname in errlog: table.row() table.cell('Hostname', hostname) table.cell('Error', errlog[hostname]) table.end() html.end_foldable_container() settings = [] settings_elements = [ ('host', TextUnicode( title=_('GLPI Server'), allow_empty=False, )), ('db_name', TextUnicode( title=_('GLPI Database Name'), allow_empty=False, )), ('db_user', TextUnicode( title=_('GLPI Database User'), allow_empty=False, )), ('db_passwd', Password( title=_('GLPI Database Password'), allow_empty=False, )), ('states', ListChoice(title=_('Update hosts with these states'), orientation='horizontal', allow_empty=False, choices=[ ( 'prod', _('Production system'), ), ( 'uat', _('UAT system'), ), ( 'dev', _('Development system'), ), ])), ('states_to_add', ListChoice(title=_('Add new hosts with these states'), orientation='horizontal', choices=[ ( 'prod', _('Production system'), ), ( 'uat', _('UAT system'), ), ( 'dev', _('Development system'), ), ], help=_('Add new hosts with these states only.'))), ('ignored_hosts', ListOfStrings( valuespec=RegExpUnicode(mode=RegExpUnicode.prefix), title=_('Do not add these hosts'), orientation='horizontal', elements=[], help=_('Do not add these hosts. Regular expressions are possible.' ))), ('dns_suffixes', ListOfStrings( title=_('DNS suffixes to add'), orientation='horizontal', elements=[], help=_('DNS suffixes to add if hosts have them in their FQDN.'))), ('type_matches', ListOf( Tuple( show_titles=True, orientation='horizontal', elements=[ TextUnicode(title=_('Computer Type in GLPI'), ), TextUnicode(title=_('Internal ID type'), ), ], ), title=_('Host Tags: Type'), help= _('Substring match for Type from GLPI table "glpi_computertypes" to Internal ID "type".' ))), ('os_matches', ListOf( Tuple( show_titles=True, orientation='horizontal', elements=[ TextUnicode(title=_('OS in GLPI'), ), TextUnicode(title=_('Internal ID os'), ), ], ), title=_('Host Tags: OS'), help= _('Substring match for OS from GLPI table "glpi_operatingsystems" to Internal ID "os".' ))), ('discover_services', Checkbox( title=_('Discover services for new hosts'), label=_('Enable'), )), ('cron', Checkbox( title=_('Synchronization by Сron'), label=_('Enable'), )), ('cron_user', TextUnicode( title=_('User to run Cron job'), allow_empty=False, )), ('period', SchedulePeriod()), ('timeofday', Timeofday(title=_('Time of day to run sync'), )), ] settings.append(('general', Dictionary( title=_('Settings'), optional_keys=None, elements=settings_elements, ))) edit_settings = { 'context': visuals.pack_context_for_editing(glpi_config, None), 'general': glpi_config, } dict_settings = forms.edit_dictionaries(settings, edit_settings, method='POST') if dict_settings != None: new_settings = dict_settings['general'] save_glpi_config(new_settings) html.immediate_browser_redirect(1, config_page) html.message(_('Your settings have been saved.')) html.footer()
def render_timeline(timeline_rows, from_time, until_time, considered_duration, timeline, range_title, render_number, what, timewarpcode): if not timeline_rows: html.write('<div class=info>%s</div>' % _("No information available")) return # Timeformat: show date only if the displayed time range spans over # more than one day. format = "%H:%M:%S" if time.localtime(from_time)[:3] != time.localtime(until_time-1)[:3]: format = "%Y-%m-%d " + format def render_date(ts): return time.strftime(format, time.localtime(ts)) if type(timeline) == tuple: tl_site, tl_host, tl_service = timeline if tl_service: availability_columns = service_availability_columns else: availability_columns = host_availability_columns else: availability_columns = bi_availability_columns # Render graphical representation # Make sure that each cell is visible, if possible min_percentage = min(100.0 / len(timeline_rows), 1) rest_percentage = 100 - len(timeline_rows) * min_percentage html.write('<div class=timelinerange>') html.write('<div class=from>%s</div><div class=until>%s</div></div>' % ( render_date(from_time), render_date(until_time))) html.write('<table class=timeline>') html.write('<tr class=timeline>') for row_nr, (row, state_id) in enumerate(timeline_rows): for sid, css, sname, help in availability_columns: if sid == state_id: title = _("From %s until %s (%s) %s") % ( render_date(row["from"]), render_date(row["until"]), render_number(row["duration"], considered_duration), sname) if row["log_output"]: title += " - " + row["log_output"] width = min_percentage + rest_percentage * row["duration"] / considered_duration html.write('<td onmouseover="timeline_hover(%d, 1);" onmouseout="timeline_hover(%d, 0);" ' 'style="width: %.1f%%" title="%s" class="%s"></td>' % ( row_nr, row_nr, width, title, css)) html.write('</tr></table>') # Render timewarped BI aggregate (might be empty) html.write(timewarpcode) # Render Table table.begin("", css="timelineevents") for row_nr, (row, state_id) in enumerate(timeline_rows): table.row() if what == "bi": table.cell(_("Links"), css="buttons") url = html.makeuri([("timewarp", str(int(row["from"])))]) html.icon_button(url, _("Time warp - show BI aggregate during this time period"), "timewarp") table.cell(_("From"), render_date(row["from"]), css="nobr narrow") table.cell(_("Until"), render_date(row["until"]), css="nobr narrow") table.cell(_("Duration"), render_number(row["duration"], considered_duration), css="narrow number") for sid, css, sname, help in availability_columns: if sid == state_id: table.cell(_("State"), sname, css=css + " state narrow") table.cell(_("Additional information"), row["log_output"]) table.end()
def render_availability_table(availability, from_time, until_time, range_title, what, avoptions, render_number): # Some columns might be unneeded due to state treatment options sg = avoptions["state_grouping"] state_groups = [ sg["warn"], sg["unknown"], sg["host_down"] ] # Helper function, needed in row and in summary line def cell_active(sid): if sid == "outof_notification_period" and avoptions["notification_period"] != "honor": return False elif sid == "in_downtime" and avoptions["downtimes"]["include"] != "honor": return False elif sid == "unmonitored" and not avoptions["consider"]["unmonitored"]: return False elif sid == "flapping" and not avoptions["consider"]["flapping"]: return False elif sid in [ "warn", "unknown", "host_down" ] and sid not in state_groups: return False else: return True # Render the stuff availability.sort() show_summary = what != "bi" and avoptions.get("summary") summary = {} table.begin(_("Availability") + " " + range_title, css="availability") for site, host, service, states, considered_duration in availability: table.row() if what != "bi": table.cell("", css="buttons") history_url = history_url_of(site, host, service, from_time, until_time) html.icon_button(history_url, _("Event History"), "history") timeline_url = html.makeuri([ ("timeline", "yes"), ("timeline_site", site), ("timeline_host", host), ("timeline_service", service)]) html.icon_button(timeline_url, _("Timeline"), "timeline") host_url = "view.py?" + htmllib.urlencode_vars([("view_name", "hoststatus"), ("site", site), ("host", host)]) if what == "bi": bi_url = "view.py?" + htmllib.urlencode_vars([("view_name", "aggr_single"), ("aggr_name", service)]) table.cell(_("Aggregate"), '<a href="%s">%s</a>' % (bi_url, service)) availability_columns = bi_availability_columns else: table.cell(_("Host"), '<a href="%s">%s</a>' % (host_url, host)) if what == "service": service_url = "view.py?" + htmllib.urlencode_vars([("view_name", "service"), ("site", site), ("host", host), ("service", service)]) table.cell(_("Service"), '<a href="%s">%s</a>' % (service_url, service)) availability_columns = service_availability_columns else: availability_columns = host_availability_columns for sid, css, sname, help in availability_columns: if not cell_active(sid): continue number = states.get(sid, 0) if not number: css = "unused" elif show_summary: summary.setdefault(sid, 0.0) summary[sid] += number table.cell(sname, render_number(number, considered_duration), css="number " + css, help=help) if show_summary: table.row(css="summary") table.cell("") table.cell("", _("Summary")) if what == "service": table.cell("", "") considered_duration = until_time - from_time for sid, css, sname, help in availability_columns: if not cell_active(sid): continue number = summary.get(sid, 0) if show_summary == "average" or avoptions["timeformat"].startswith("percentage"): number /= len(availability) if not number: css = "unused" table.cell(sname, render_number(number, considered_duration), css="number " + css, help=help) table.end()
or instance.may_delete() or instance.may_edit(): foreign_instances.append(instance) for title, instances in [ (_('Customized'), my_instances), (_('Owned by other users'), foreign_instances), (_('Builtin'), builtin_instances), ]: if not instances: continue html.write('<h3>' + title + '</h3>') table.begin(limit=None) for instance in instances: table.row() # Actions table.cell(_('Actions'), css='buttons visuals') # Edit if instance.may_edit(): html.icon_button(instance.edit_url(), _("Edit"), "edit") # Clone / Customize buttontext = _("Create a customized copy of this") html.icon_button(instance.clone_url(), buttontext, "new_" + self.type_name()) # Delete if instance.may_delete():