Add specific visualization for labels depending on their source
[check_mk.git] / cmk / gui / plugins / views / painters.py
blob640284ff0e325806865834b86340df03e66ac8fe
1 #!/usr/bin/python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
10 # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
27 import abc
28 import os
29 import time
31 import cmk.utils.paths
32 import cmk.utils.render
33 import cmk.utils.man_pages as man_pages
34 from cmk.utils.defines import short_service_state_name, short_host_state_name
36 import cmk.gui.config as config
37 import cmk.gui.metrics as metrics
38 from cmk.gui.htmllib import HTML
39 from cmk.gui.i18n import _
40 from cmk.gui.globals import html
41 from cmk.gui.valuespec import (
42 Timerange,
43 DropdownChoice,
44 DateFormat,
45 Dictionary,
46 ListChoice,
49 from cmk.gui.plugins.views.icons import (
50 get_icons,
51 iconpainter_columns,
54 from cmk.gui.plugins.views import (
55 painter_registry,
56 Painter,
57 painter_option_registry,
58 PainterOption,
59 PainterOptions,
60 transform_action_url,
61 is_stale,
62 paint_stalified,
63 paint_host_list,
64 format_plugin_output,
65 display_options,
66 link_to_view,
67 get_perfdata_nth_value,
68 get_graph_timerange_from_painter_options,
69 paint_age,
70 paint_nagiosflag,
71 replace_action_url_macros,
72 render_cache_info,
73 render_tag_groups,
74 get_tag_groups,
75 render_labels,
76 get_labels,
77 get_label_sources,
80 # .--Painter Options-----------------------------------------------------.
81 # | ____ _ _ |
82 # | | _ \ __ _(_)_ __ | |_ ___ _ __ |
83 # | | |_) / _` | | '_ \| __/ _ \ '__| |
84 # | | __/ (_| | | | | | || __/ | |
85 # | |_| \__,_|_|_| |_|\__\___|_| |
86 # | |
87 # | ___ _ _ |
88 # | / _ \ _ __ | |_(_) ___ _ __ ___ |
89 # | | | | | '_ \| __| |/ _ \| '_ \/ __| |
90 # | | |_| | |_) | |_| | (_) | | | \__ \ |
91 # | \___/| .__/ \__|_|\___/|_| |_|___/ |
92 # | |_| |
93 # +----------------------------------------------------------------------+
94 # | Painter options influence how painters render their data. Painter |
95 # | options are stored together with "refresh" and "columns" as "View |
96 # | options". |
97 # '----------------------------------------------------------------------'
100 @painter_option_registry.register
101 class PainterOptionPNPTimerange(PainterOption):
102 @property
103 def ident(self):
104 return "pnp_timerange"
106 @property
107 def valuespec(self):
108 return Timerange(
109 title=_("Graph time range"),
110 default_value=None,
111 include_time=True,
115 @painter_option_registry.register
116 class PainterOptionTimestampFormat(PainterOption):
117 @property
118 def ident(self):
119 return "ts_format"
121 @property
122 def valuespec(self):
123 return DropdownChoice(
124 title=_("Time stamp format"),
125 default_value=config.default_ts_format,
126 choices=[
127 ("mixed", _("Mixed")),
128 ("abs", _("Absolute")),
129 ("rel", _("Relative")),
130 ("both", _("Both")),
131 ("epoch", _("Unix Timestamp (Epoch)")),
136 @painter_option_registry.register
137 class PainterOptionTimestampDate(PainterOption):
138 @property
139 def ident(self):
140 return "ts_date"
142 @property
143 def valuespec(self):
144 return DateFormat()
147 @painter_option_registry.register
148 class PainterOptionMatrixOmitUniform(PainterOption):
149 @property
150 def ident(self):
151 return "matrix_omit_uniform"
153 @property
154 def valuespec(self):
155 return DropdownChoice(
156 title=_("Find differences..."),
157 choices=[
158 (False, _("Always show all rows")),
159 (True, _("Omit rows where all columns are identical")),
164 # .--Helpers-------------------------------------------------------------.
165 # | _ _ _ |
166 # | | | | | ___| |_ __ ___ _ __ ___ |
167 # | | |_| |/ _ \ | '_ \ / _ \ '__/ __| |
168 # | | _ | __/ | |_) | __/ | \__ \ |
169 # | |_| |_|\___|_| .__/ \___|_| |___/ |
170 # | |_| |
171 # '----------------------------------------------------------------------'
174 # This helper function returns the value of the given custom var
175 def paint_custom_var(what, key, row, choices=None):
176 if choices is None:
177 choices = []
179 if what:
180 what += '_'
182 custom_vars = dict(
183 zip(row[what + "custom_variable_names"], row[what + "custom_variable_values"]))
185 if key in custom_vars:
186 custom_val = custom_vars[key]
187 if choices:
188 custom_val = dict(choices).get(int(custom_val), custom_val)
189 return key, html.attrencode(custom_val)
191 return key, ""
194 def paint_nagios_link(row):
195 # We need to use the Nagios-URL as configured
196 # in sites.
197 baseurl = config.site(row["site"])["url_prefix"] + "nagios/cgi-bin"
198 url = baseurl + "/extinfo.cgi?host=" + html.urlencode(row["host_name"])
199 svc = row.get("service_description")
200 if svc:
201 url += "&type=2&service=" + html.urlencode(svc)
202 what = "service"
203 else:
204 url += "&type=1"
205 what = "host"
206 return "singleicon", html.render_a(
207 html.render_icon('nagios',
208 _('Show this %s in Nagios') % what), url)
211 def paint_future_time(timestamp):
212 if timestamp <= 0:
213 return "", "-"
214 return paint_age(timestamp, True, 0, what='future')
217 def paint_day(timestamp):
218 return "", time.strftime("%A, %Y-%m-%d", time.localtime(timestamp))
221 # Paint column with various icons. The icons use
222 # a plugin based mechanism so it is possible to
223 # register own icon "handlers".
224 # what: either "host" or "service"
225 # row: the data row of the host or service
226 def paint_icons(what, row):
227 # EC: In case of unrelated events also skip rendering this painter. All the icons
228 # that display a host state are useless in this case. Maybe we make this decision
229 # individually for the single icons one day.
230 if not row["host_name"] or row.get("event_is_unrelated"):
231 return "", "" # Host probably does not exist
233 toplevel_icons = get_icons(what, row, toplevel=True)
235 # In case of non HTML output, just return the top level icon names
236 # as space separated string
237 if html.output_format != 'html':
238 return 'icons', ' '.join([i[1] for i in toplevel_icons])
240 output = ''
241 for icon in toplevel_icons:
242 if len(icon) == 4:
243 icon_name, title, url_spec = icon[1:]
244 if url_spec:
245 url, target_frame = transform_action_url(url_spec)
246 url = replace_action_url_macros(url, what, row)
248 onclick = ''
249 if url.startswith('onclick:'):
250 onclick = url[8:]
251 url = 'javascript:void(0)'
253 output += html.render_icon_button(
254 url, title, icon_name, onclick=onclick, target=target_frame)
255 else:
256 output += html.render_icon(icon_name, title)
257 else:
258 output += icon[1]
260 return "icons", output
263 # TODO: Refactor to one icon base class
264 @painter_registry.register
265 class PainterServiceIcons(Painter):
266 @property
267 def ident(self):
268 return "service_icons"
270 @property
271 def title(self):
272 return _("Service icons")
274 @property
275 def short_title(self):
276 return _("Icons")
278 @property
279 def columns(self):
280 return iconpainter_columns("service", toplevel=None)
282 @property
283 def printable(self):
284 return False
286 def group_by(self, row):
287 return ("",) # Do not account for in grouping
289 def render(self, row, cell):
290 return paint_icons("service", row)
293 @painter_registry.register
294 class PainterHostIcons(Painter):
295 @property
296 def ident(self):
297 return "host_icons"
299 @property
300 def title(self):
301 return _("Host icons")
303 @property
304 def short_title(self):
305 return _("Icons")
307 @property
308 def columns(self):
309 return iconpainter_columns("host", toplevel=None)
311 @property
312 def printable(self):
313 return False
315 def group_by(self, row):
316 return ("",) # Do not account for in grouping
318 def render(self, row, cell):
319 return paint_icons("host", row)
323 # .--Site----------------------------------------------------------------.
324 # | ____ _ _ |
325 # | / ___|(_) |_ ___ |
326 # | \___ \| | __/ _ \ |
327 # | ___) | | || __/ |
328 # | |____/|_|\__\___| |
329 # | |
330 # +----------------------------------------------------------------------+
331 # | Column painters showing information about a site. |
332 # '----------------------------------------------------------------------'
335 @painter_registry.register
336 class PainterSiteIcon(Painter):
337 @property
338 def ident(self):
339 return "site_icon"
341 @property
342 def title(self):
343 return _("Site icon")
345 @property
346 def short_title(self):
347 return u""
349 @property
350 def columns(self):
351 return ['site']
353 @property
354 def sorter(self):
355 return 'site'
357 def render(self, row, cell):
358 if row.get("site") and config.use_siteicons:
359 return None, "<img class=siteicon src=\"icons/site-%s-24.png\">" % row["site"]
360 return None, ""
363 @painter_registry.register
364 class PainterSitenamePlain(Painter):
365 @property
366 def ident(self):
367 return "sitename_plain"
369 @property
370 def title(self):
371 return _("Site ID")
373 @property
374 def short_title(self):
375 return _("Site")
377 @property
378 def columns(self):
379 return ['site']
381 @property
382 def sorter(self):
383 return 'site'
385 def render(self, row, cell):
386 return (None, row["site"])
389 @painter_registry.register
390 class PainterSitealias(Painter):
391 @property
392 def ident(self):
393 return "sitealias"
395 @property
396 def title(self):
397 return _("Site alias")
399 @property
400 def columns(self):
401 return ['site']
403 def render(self, row, cell):
404 return (None, html.attrencode(config.site(row["site"])["alias"]))
408 # .--Services------------------------------------------------------------.
409 # | ____ _ |
410 # | / ___| ___ _ ____ _(_) ___ ___ ___ |
411 # | \___ \ / _ \ '__\ \ / / |/ __/ _ \/ __| |
412 # | ___) | __/ | \ V /| | (_| __/\__ \ |
413 # | |____/ \___|_| \_/ |_|\___\___||___/ |
414 # | |
415 # +----------------------------------------------------------------------+
416 # | Painters for services |
417 # '----------------------------------------------------------------------'
420 def paint_service_state_short(row):
421 if row["service_has_been_checked"] == 1:
422 state = str(row["service_state"])
423 name = short_service_state_name(row["service_state"], "")
424 else:
425 state = "p"
426 name = short_service_state_name(-1, "")
428 if is_stale(row):
429 state = str(state) + " stale"
431 return "state svcstate state%s" % state, name
434 def paint_host_state_short(row, short=False):
435 if row["host_has_been_checked"] == 1:
436 state = row["host_state"]
437 # A state of 3 is sent by livestatus in cases where no normal state
438 # information is avaiable, e.g. for "DOWNTIMESTOPPED (UP)"
439 name = short_host_state_name(row["host_state"], "")
440 else:
441 state = "p"
442 name = _("PEND")
444 if is_stale(row):
445 state = str(state) + " stale"
447 if short:
448 name = name[0]
450 return "state hstate hstate%s" % state, name
453 @painter_registry.register
454 class PainterServiceNagiosLink(Painter):
455 @property
456 def ident(self):
457 return "service_nagios_link"
459 @property
460 def title(self):
461 return _("Icon with link to service in Nagios GUI")
463 @property
464 def short_title(self):
465 return u""
467 @property
468 def columns(self):
469 return ['site', 'host_name', 'service_description']
471 def render(self, row, cell):
472 return paint_nagios_link(row)
475 @painter_registry.register
476 class PainterServiceState(Painter):
477 @property
478 def ident(self):
479 return "service_state"
481 @property
482 def title(self):
483 return _("Service state")
485 @property
486 def short_title(self):
487 return _("State")
489 @property
490 def columns(self):
491 return ['service_has_been_checked', 'service_state']
493 @property
494 def sorter(self):
495 return 'svcstate'
497 def render(self, row, cell):
498 return paint_service_state_short(row)
501 @painter_registry.register
502 class PainterSvcPluginOutput(Painter):
503 @property
504 def ident(self):
505 return "svc_plugin_output"
507 @property
508 def title(self):
509 return _("Output of check plugin")
511 @property
512 def short_title(self):
513 return _("Status detail")
515 @property
516 def columns(self):
517 return ['service_plugin_output', 'service_custom_variables']
519 @property
520 def sorter(self):
521 return 'svcoutput'
523 def render(self, row, cell):
524 return paint_stalified(row, format_plugin_output(row["service_plugin_output"], row))
527 @painter_registry.register
528 class PainterSvcLongPluginOutput(Painter):
529 @property
530 def ident(self):
531 return "svc_long_plugin_output"
533 @property
534 def title(self):
535 return _("Long output of check plugin (multiline)")
537 @property
538 def short_title(self):
539 return _("Status detail")
541 @property
542 def columns(self):
543 return ['service_long_plugin_output', 'service_custom_variables']
545 def render(self, row, cell):
546 return paint_stalified(
547 row,
548 format_plugin_output(row["service_long_plugin_output"],
549 row).replace('\\n', '<br>').replace('\n', '<br>'))
552 @painter_registry.register
553 class PainterSvcPerfData(Painter):
554 @property
555 def ident(self):
556 return "svc_perf_data"
558 @property
559 def title(self):
560 return _("Service performance data (source code)")
562 @property
563 def short_title(self):
564 return _("Perfdata")
566 @property
567 def columns(self):
568 return ['service_perf_data']
570 def render(self, row, cell):
571 return paint_stalified(row, row["service_perf_data"])
574 @painter_registry.register
575 class PainterSvcMetrics(Painter):
576 @property
577 def ident(self):
578 return "svc_metrics"
580 @property
581 def title(self):
582 return _("Service Metrics")
584 @property
585 def short_title(self):
586 return _("Metrics")
588 @property
589 def columns(self):
590 return ['service_check_command', 'service_perf_data']
592 @property
593 def printable(self):
594 return False
596 def render(self, row, cell):
597 translated_metrics = metrics.translate_perf_data(row["service_perf_data"],
598 row["service_check_command"])
600 if row["service_perf_data"] and not translated_metrics:
601 return "", _("Failed to parse performance data string: %s") % row["service_perf_data"]
603 return "", metrics.render_metrics_table(translated_metrics, row["host_name"],
604 row["service_description"])
607 # TODO: Use a parameterized painter for this instead of 10 painter classes
608 class PainterSvcPerfVal(Painter):
609 _num = 0
611 @property
612 def ident(self):
613 return "svc_perf_val%02d" % self._num
615 @property
616 def title(self):
617 return _("Service performance data - value number %2d") % self._num
619 @property
620 def short_title(self):
621 return _("Val. %d") % self._num
623 @property
624 def columns(self):
625 return ['service_perf_data']
627 def render(self, row, cell):
628 return paint_stalified(row, get_perfdata_nth_value(row, self._num - 1))
631 @painter_registry.register
632 class PainterSvcPerfVal01(PainterSvcPerfVal):
633 _num = 1
636 @painter_registry.register
637 class PainterSvcPerfVal02(PainterSvcPerfVal):
638 _num = 2
641 @painter_registry.register
642 class PainterSvcPerfVal03(PainterSvcPerfVal):
643 _num = 3
646 @painter_registry.register
647 class PainterSvcPerfVal04(PainterSvcPerfVal):
648 _num = 4
651 @painter_registry.register
652 class PainterSvcPerfVal05(PainterSvcPerfVal):
653 _num = 5
656 @painter_registry.register
657 class PainterSvcPerfVal06(PainterSvcPerfVal):
658 _num = 6
661 @painter_registry.register
662 class PainterSvcPerfVal07(PainterSvcPerfVal):
663 _num = 7
666 @painter_registry.register
667 class PainterSvcPerfVal08(PainterSvcPerfVal):
668 _num = 8
671 @painter_registry.register
672 class PainterSvcPerfVal09(PainterSvcPerfVal):
673 _num = 9
676 @painter_registry.register
677 class PainterSvcPerfVal10(PainterSvcPerfVal):
678 _num = 10
681 @painter_registry.register
682 class PainterSvcCheckCommand(Painter):
683 @property
684 def ident(self):
685 return "svc_check_command"
687 @property
688 def title(self):
689 return _("Service check command")
691 @property
692 def short_title(self):
693 return _("Check command")
695 @property
696 def columns(self):
697 return ['service_check_command']
699 def render(self, row, cell):
700 return (None, html.attrencode(row["service_check_command"]))
703 @painter_registry.register
704 class PainterSvcCheckCommandExpanded(Painter):
705 @property
706 def ident(self):
707 return "svc_check_command_expanded"
709 @property
710 def title(self):
711 return _("Service check command expanded")
713 @property
714 def short_title(self):
715 return _("Check command expanded")
717 @property
718 def columns(self):
719 return ['service_check_command_expanded']
721 def render(self, row, cell):
722 return html.attrencode(row["service_check_command_expanded"])
725 @painter_registry.register
726 class PainterSvcContacts(Painter):
727 @property
728 def ident(self):
729 return "svc_contacts"
731 @property
732 def title(self):
733 return _("Service contacts")
735 @property
736 def short_title(self):
737 return _("Contacts")
739 @property
740 def columns(self):
741 return ['service_contacts']
743 def render(self, row, cell):
744 return (None, ", ".join(row["service_contacts"]))
747 @painter_registry.register
748 class PainterSvcContactGroups(Painter):
749 @property
750 def ident(self):
751 return "svc_contact_groups"
753 @property
754 def title(self):
755 return _("Service contact groups")
757 @property
758 def short_title(self):
759 return _("Contact groups")
761 @property
762 def columns(self):
763 return ['service_contact_groups']
765 def render(self, row, cell):
766 return (None, ", ".join(row["service_contact_groups"]))
769 @painter_registry.register
770 class PainterServiceDescription(Painter):
771 @property
772 def ident(self):
773 return "service_description"
775 @property
776 def title(self):
777 return _("Service description")
779 @property
780 def short_title(self):
781 return _("Service")
783 @property
784 def columns(self):
785 return ['service_description']
787 @property
788 def sorter(self):
789 return 'svcdescr'
791 def render(self, row, cell):
792 return (None, row["service_description"])
795 @painter_registry.register
796 class PainterServiceDisplayName(Painter):
797 @property
798 def ident(self):
799 return "service_display_name"
801 @property
802 def title(self):
803 return _("Service alternative display name")
805 @property
806 def short_title(self):
807 return _("Display name")
809 @property
810 def columns(self):
811 return ['service_display_name']
813 @property
814 def sorter(self):
815 return 'svcdispname'
817 def render(self, row, cell):
818 return (None, row["service_display_name"])
821 @painter_registry.register
822 class PainterSvcStateAge(Painter):
823 @property
824 def ident(self):
825 return "svc_state_age"
827 @property
828 def title(self):
829 return _("The age of the current service state")
831 @property
832 def short_title(self):
833 return _("Age")
835 @property
836 def columns(self):
837 return ['service_has_been_checked', 'service_last_state_change']
839 @property
840 def sorter(self):
841 return 'stateage'
843 @property
844 def painter_options(self):
845 return ['ts_format', 'ts_date']
847 def render(self, row, cell):
848 return paint_age(row["service_last_state_change"], row["service_has_been_checked"] == 1,
849 60 * 10)
852 def paint_checked(what, row):
853 age = row[what + "_last_check"]
854 if what == "service":
855 cached_at = row["service_cached_at"]
856 if cached_at:
857 age = cached_at
859 css, td = paint_age(age, row[what + "_has_been_checked"] == 1, 0)
860 if is_stale(row):
861 css += " staletime"
862 return css, td
865 @painter_registry.register
866 class PainterSvcCheckAge(Painter):
867 @property
868 def ident(self):
869 return "svc_check_age"
871 @property
872 def title(self):
873 return _("The time since the last check of the service")
875 @property
876 def short_title(self):
877 return _("Checked")
879 @property
880 def columns(self):
881 return ['service_has_been_checked', 'service_last_check', 'service_cached_at']
883 @property
884 def painter_options(self):
885 return ['ts_format', 'ts_date']
887 def render(self, row, cell):
888 return paint_checked("service", row)
891 @painter_registry.register
892 class PainterSvcCheckCacheInfo(Painter):
893 @property
894 def ident(self):
895 return "svc_check_cache_info"
897 @property
898 def title(self):
899 return _("Cached agent data")
901 @property
902 def short_title(self):
903 return _("Cached")
905 @property
906 def columns(self):
907 return ['service_last_check', 'service_cached_at', 'service_cache_interval']
909 @property
910 def painter_options(self):
911 return ['ts_format', 'ts_date']
913 def render(self, row, cell):
914 if not row["service_cached_at"]:
915 return "", ""
916 return "", render_cache_info("service", row)
919 @painter_registry.register
920 class PainterSvcNextCheck(Painter):
921 @property
922 def ident(self):
923 return "svc_next_check"
925 @property
926 def title(self):
927 return _("The time of the next scheduled service check")
929 @property
930 def short_title(self):
931 return _("Next check")
933 @property
934 def columns(self):
935 return ['service_next_check']
937 def render(self, row, cell):
938 return paint_future_time(row["service_next_check"])
941 @painter_registry.register
942 class PainterSvcLastTimeOk(Painter):
943 @property
944 def ident(self):
945 return "svc_last_time_ok"
947 @property
948 def title(self):
949 return _("The last time the service was OK")
951 @property
952 def short_title(self):
953 return _("Last OK")
955 @property
956 def columns(self):
957 return ['service_last_time_ok', 'service_has_been_checked']
959 def render(self, row, cell):
960 return paint_age(row["service_last_time_ok"], row["service_has_been_checked"] == 1, 60 * 10)
963 @painter_registry.register
964 class PainterSvcNextNotification(Painter):
965 @property
966 def ident(self):
967 return "svc_next_notification"
969 @property
970 def title(self):
971 return _("The time of the next service notification")
973 @property
974 def short_title(self):
975 return _("Next notification")
977 @property
978 def columns(self):
979 return ['service_next_notification']
981 def render(self, row, cell):
982 return paint_future_time(row["service_next_notification"])
985 def paint_notification_postponement_reason(what, row):
986 # Needs to be in sync with the possible reasons. Can not be translaated otherwise.
987 reasons = {
988 "delayed notification": _("Delay notification"),
989 "periodic notification": _("Periodic notification"),
990 "currently in downtime": _("In downtime"),
991 "host of this service is currently in downtime": _("Host is in downtime"),
992 "problem acknowledged and periodic notifications are enabled":
993 _("Problem is acknowledged, but is configured to be periodic"),
994 "notifications are disabled, but periodic notifications are enabled":
995 _("Notifications are disabled, but is configured to be periodic"),
996 "not in notification period": _("Is not in notification period"),
997 "host of this service is not up": _("Host is down"),
998 "last host check not recent enough": _("Last host check is not recent enough"),
999 "last service check not recent enough": _("Last service check is not recent enough"),
1000 "all parents are down": _("All parents are down"),
1001 "at least one parent is up, but no check is recent enough":
1002 _("Last service check is not recent enough"),
1005 return ("",
1006 reasons.get(row[what + "_notification_postponement_reason"],
1007 row[what + "_notification_postponement_reason"]))
1010 @painter_registry.register
1011 class PainterSvcNotificationPostponementReason(Painter):
1012 @property
1013 def ident(self):
1014 return "svc_notification_postponement_reason"
1016 @property
1017 def title(self):
1018 return _("Notification postponement reason")
1020 @property
1021 def short_title(self):
1022 return _("Notif. postponed")
1024 @property
1025 def columns(self):
1026 return ['service_notification_postponement_reason']
1028 def render(self, row, cell):
1029 return paint_notification_postponement_reason("service", row)
1032 @painter_registry.register
1033 class PainterSvcLastNotification(Painter):
1034 @property
1035 def ident(self):
1036 return "svc_last_notification"
1038 @property
1039 def title(self):
1040 return _("The time of the last service notification")
1042 @property
1043 def short_title(self):
1044 return _("last notification")
1046 @property
1047 def columns(self):
1048 return ['service_last_notification']
1050 @property
1051 def painter_options(self):
1052 return ['ts_format', 'ts_date']
1054 def render(self, row, cell):
1055 return paint_age(row["service_last_notification"], row["service_last_notification"], 0)
1058 @painter_registry.register
1059 class PainterSvcNotificationNumber(Painter):
1060 @property
1061 def ident(self):
1062 return "svc_notification_number"
1064 @property
1065 def title(self):
1066 return _("Service notification number")
1068 @property
1069 def short_title(self):
1070 return _("N#")
1072 @property
1073 def columns(self):
1074 return ['service_current_notification_number']
1076 def render(self, row, cell):
1077 return ("", str(row["service_current_notification_number"]))
1080 @painter_registry.register
1081 class PainterSvcCheckLatency(Painter):
1082 @property
1083 def ident(self):
1084 return "svc_check_latency"
1086 @property
1087 def title(self):
1088 return _("Service check latency")
1090 @property
1091 def short_title(self):
1092 return _("Latency")
1094 @property
1095 def columns(self):
1096 return ['service_latency']
1098 def render(self, row, cell):
1099 return ("", cmk.utils.render.approx_age(row["service_latency"]))
1102 @painter_registry.register
1103 class PainterSvcCheckDuration(Painter):
1104 @property
1105 def ident(self):
1106 return "svc_check_duration"
1108 @property
1109 def title(self):
1110 return _("Service check duration")
1112 @property
1113 def short_title(self):
1114 return _("Duration")
1116 @property
1117 def columns(self):
1118 return ['service_execution_time']
1120 def render(self, row, cell):
1121 return ("", cmk.utils.render.approx_age(row["service_execution_time"]))
1124 @painter_registry.register
1125 class PainterSvcAttempt(Painter):
1126 @property
1127 def ident(self):
1128 return "svc_attempt"
1130 @property
1131 def title(self):
1132 return _("Current check attempt")
1134 @property
1135 def short_title(self):
1136 return _("Att.")
1138 @property
1139 def columns(self):
1140 return ['service_current_attempt', 'service_max_check_attempts']
1142 def render(self, row, cell):
1143 return (None, "%d/%d" % (row["service_current_attempt"], row["service_max_check_attempts"]))
1146 @painter_registry.register
1147 class PainterSvcNormalInterval(Painter):
1148 @property
1149 def ident(self):
1150 return "svc_normal_interval"
1152 @property
1153 def title(self):
1154 return _("Service normal check interval")
1156 @property
1157 def short_title(self):
1158 return _("Check int.")
1160 @property
1161 def columns(self):
1162 return ['service_check_interval']
1164 def render(self, row, cell):
1165 return ("number", cmk.utils.render.approx_age(row["service_check_interval"] * 60.0))
1168 @painter_registry.register
1169 class PainterSvcRetryInterval(Painter):
1170 @property
1171 def ident(self):
1172 return "svc_retry_interval"
1174 @property
1175 def title(self):
1176 return _("Service retry check interval")
1178 @property
1179 def short_title(self):
1180 return _("Retry")
1182 @property
1183 def columns(self):
1184 return ['service_retry_interval']
1186 def render(self, row, cell):
1187 return ("number", cmk.utils.render.approx_age(row["service_retry_interval"] * 60.0))
1190 @painter_registry.register
1191 class PainterSvcCheckInterval(Painter):
1192 @property
1193 def ident(self):
1194 return "svc_check_interval"
1196 @property
1197 def title(self):
1198 return _("Service normal/retry check interval")
1200 @property
1201 def short_title(self):
1202 return _("Interval")
1204 @property
1205 def columns(self):
1206 return ['service_check_interval', 'service_retry_interval']
1208 def render(self, row, cell):
1209 return (
1210 None,
1211 "%s / %s" % (cmk.utils.render.approx_age(row["service_check_interval"] * 60.0),
1212 cmk.utils.render.approx_age(row["service_retry_interval"] * 60.0)),
1216 @painter_registry.register
1217 class PainterSvcCheckType(Painter):
1218 @property
1219 def ident(self):
1220 return "svc_check_type"
1222 @property
1223 def title(self):
1224 return _("Service check type")
1226 @property
1227 def short_title(self):
1228 return _("Type")
1230 @property
1231 def columns(self):
1232 return ['service_check_type']
1234 def render(self, row, cell):
1235 return (None, _("ACTIVE") if row["service_check_type"] == 0 else _("PASSIVE"))
1238 @painter_registry.register
1239 class PainterSvcInDowntime(Painter):
1240 @property
1241 def ident(self):
1242 return "svc_in_downtime"
1244 @property
1245 def title(self):
1246 return _("Currently in downtime")
1248 @property
1249 def short_title(self):
1250 return _("Dt.")
1252 @property
1253 def columns(self):
1254 return ['service_scheduled_downtime_depth']
1256 def render(self, row, cell):
1257 return paint_nagiosflag(row, "service_scheduled_downtime_depth", True)
1260 @painter_registry.register
1261 class PainterSvcInNotifper(Painter):
1262 @property
1263 def ident(self):
1264 return "svc_in_notifper"
1266 @property
1267 def title(self):
1268 return _("In notification period")
1270 @property
1271 def short_title(self):
1272 return _("in notif. p.")
1274 @property
1275 def columns(self):
1276 return ['service_in_notification_period']
1278 def render(self, row, cell):
1279 return paint_nagiosflag(row, "service_in_notification_period", False)
1282 @painter_registry.register
1283 class PainterSvcNotifper(Painter):
1284 @property
1285 def ident(self):
1286 return "svc_notifper"
1288 @property
1289 def title(self):
1290 return _("Service notification period")
1292 @property
1293 def short_title(self):
1294 return _("notif.")
1296 @property
1297 def columns(self):
1298 return ['service_notification_period']
1300 def render(self, row, cell):
1301 return (None, row["service_notification_period"])
1304 @painter_registry.register
1305 class PainterSvcCheckPeriod(Painter):
1306 @property
1307 def ident(self):
1308 return "svc_check_period"
1310 @property
1311 def title(self):
1312 return _("Service check period")
1314 @property
1315 def short_title(self):
1316 return _("check.")
1318 @property
1319 def columns(self):
1320 return ['service_check_period']
1322 def render(self, row, cell):
1323 return (None, row["service_check_period"])
1326 @painter_registry.register
1327 class PainterSvcFlapping(Painter):
1328 @property
1329 def ident(self):
1330 return "svc_flapping"
1332 @property
1333 def title(self):
1334 return _("Service is flapping")
1336 @property
1337 def short_title(self):
1338 return _("Flap")
1340 @property
1341 def columns(self):
1342 return ['service_is_flapping']
1344 def render(self, row, cell):
1345 return paint_nagiosflag(row, "service_is_flapping", True)
1348 @painter_registry.register
1349 class PainterSvcNotificationsEnabled(Painter):
1350 @property
1351 def ident(self):
1352 return "svc_notifications_enabled"
1354 @property
1355 def title(self):
1356 return _("Service notifications enabled")
1358 @property
1359 def short_title(self):
1360 return _("Notif.")
1362 @property
1363 def columns(self):
1364 return ['service_notifications_enabled']
1366 def render(self, row, cell):
1367 return paint_nagiosflag(row, "service_notifications_enabled", False)
1370 @painter_registry.register
1371 class PainterSvcIsActive(Painter):
1372 @property
1373 def ident(self):
1374 return "svc_is_active"
1376 @property
1377 def title(self):
1378 return _("Service is active")
1380 @property
1381 def short_title(self):
1382 return _("Active")
1384 @property
1385 def columns(self):
1386 return ['service_active_checks_enabled']
1388 def render(self, row, cell):
1389 return paint_nagiosflag(row, "service_active_checks_enabled", None)
1392 @painter_registry.register
1393 class PainterSvcGroupMemberlist(Painter):
1394 @property
1395 def ident(self):
1396 return "svc_group_memberlist"
1398 @property
1399 def title(self):
1400 return _("Service groups the service is member of")
1402 @property
1403 def short_title(self):
1404 return _("Groups")
1406 @property
1407 def columns(self):
1408 return ['service_groups']
1410 def render(self, row, cell):
1411 links = []
1412 for group in row["service_groups"]:
1413 link = "view.py?view_name=servicegroup&servicegroup=" + group
1414 links.append(html.render_a(group, link))
1415 return "", HTML(", ").join(links)
1418 def paint_time_graph(row, cell):
1419 if metrics.cmk_graphs_possible(row["site"]):
1420 import cmk.gui.cee.plugins.views.graphs # pylint: disable=redefined-outer-name
1421 return cmk.gui.cee.plugins.views.graphs.paint_time_graph_cmk(row, cell)
1422 return paint_time_graph_pnp(row)
1425 def paint_time_graph_pnp(row):
1426 sitename = row["site"]
1427 host = row["host_name"]
1428 service = row.get("service_description", "_HOST_")
1430 container_id = "%s_%s_%s_graph" % (sitename, host, service)
1431 url_prefix = config.site(sitename)["url_prefix"]
1432 pnp_url = url_prefix + "pnp4nagios/"
1433 if display_options.enabled(display_options.X):
1434 with_link = 'true'
1435 else:
1436 with_link = 'false'
1438 painter_options = PainterOptions.get_instance()
1439 pnp_timerange = painter_options.get("pnp_timerange")
1441 pnpview = '1'
1442 from_ts, to_ts = 'null', 'null'
1443 if pnp_timerange is not None:
1444 if pnp_timerange[0] != 'pnp_view':
1445 from_ts, to_ts = get_graph_timerange_from_painter_options()
1446 else:
1447 pnpview = pnp_timerange[1]
1449 pnp_theme = html.get_theme()
1450 if pnp_theme == "classic":
1451 pnp_theme = "multisite"
1453 return (
1454 "pnpgraph", "<div id=\"%s\"></div>"
1455 "<script>cmk.graph_integration.render_graphs('%s', '%s', '%s', '%s', '%s', '%s', '%s', %s, '%s', %s, %s, '%s')</script>"
1456 % (container_id, container_id, sitename, host, service, pnpview, config.url_prefix() +
1457 "check_mk/", pnp_url, with_link, _('Add this graph to...'), from_ts, to_ts, pnp_theme))
1460 def time_graph_params():
1461 if not metrics.cmk_graphs_possible():
1462 return # The method is only available in CEE
1464 import cmk.gui.cee.plugins.views.graphs # pylint: disable=redefined-outer-name
1465 return cmk.gui.cee.plugins.views.graphs.cmk_time_graph_params()
1468 @painter_registry.register
1469 class PainterSvcPnpgraph(Painter):
1470 @property
1471 def ident(self):
1472 return "svc_pnpgraph"
1474 @property
1475 def title(self):
1476 return _("Service Graphs")
1478 @property
1479 def columns(self):
1480 return [
1481 'host_name',
1482 'service_description',
1483 'service_perf_data',
1484 'service_metrics',
1485 'service_check_command',
1488 @property
1489 def printable(self):
1490 return 'time_graph'
1492 @property
1493 def painter_options(self):
1494 return ['pnp_timerange']
1496 @property
1497 def parameters(self):
1498 return time_graph_params()
1500 def render(self, row, cell):
1501 return paint_time_graph(row, cell)
1504 @painter_registry.register
1505 class PainterCheckManpage(Painter):
1506 @property
1507 def ident(self):
1508 return "check_manpage"
1510 @property
1511 def title(self):
1512 return _("Check manual (for Check_MK based checks)")
1514 @property
1515 def short_title(self):
1516 return _("Manual")
1518 @property
1519 def columns(self):
1520 return ['service_check_command']
1522 def render(self, row, cell):
1523 command = row["service_check_command"]
1524 if not command.startswith("check_mk-"):
1525 return "", ""
1526 checktype = command[9:]
1528 page = man_pages.load_man_page(checktype)
1529 if page is None:
1530 return "", _("Man page %s not found.") % checktype
1532 description = page["header"]["description"]
1533 return "", description.replace("<", "&lt;") \
1534 .replace(">", "&gt;") \
1535 .replace("{", "<b>") \
1536 .replace("}", "</b>") \
1537 .replace("&lt;br&gt;", "<br>")
1540 def paint_comments(prefix, row):
1541 comments = row[prefix + "comments_with_info"]
1542 text = ", ".join(["<i>%s</i>: %s" % (a, html.attrencode(c)) for _id, a, c in comments])
1543 return "", text
1546 @painter_registry.register
1547 class PainterSvcComments(Painter):
1548 @property
1549 def ident(self):
1550 return "svc_comments"
1552 @property
1553 def title(self):
1554 return _("Service Comments")
1556 @property
1557 def short_title(self):
1558 return _("Comments")
1560 @property
1561 def columns(self):
1562 return ['service_comments_with_info']
1564 def render(self, row, cell):
1565 return paint_comments("service_", row)
1568 @painter_registry.register
1569 class PainterSvcAcknowledged(Painter):
1570 @property
1571 def ident(self):
1572 return "svc_acknowledged"
1574 @property
1575 def title(self):
1576 return _("Service problem acknowledged")
1578 @property
1579 def short_title(self):
1580 return _("Ack")
1582 @property
1583 def columns(self):
1584 return ['service_acknowledged']
1586 def render(self, row, cell):
1587 return paint_nagiosflag(row, "service_acknowledged", False)
1590 def notes_matching_pattern_entries(dirs, item):
1591 from fnmatch import fnmatch
1592 matching = []
1593 for directory in dirs:
1594 if os.path.isdir(directory):
1595 entries = [d for d in os.listdir(directory) if d[0] != '.']
1596 entries.sort()
1597 entries.reverse()
1598 for pattern in entries:
1599 if pattern[0] == '.':
1600 continue
1601 if fnmatch(item, pattern):
1602 matching.append(directory + "/" + pattern)
1603 return matching
1606 def paint_custom_notes(what, row):
1607 host = row["host_name"]
1608 svc = row.get("service_description")
1609 if what == "service":
1610 notes_dir = cmk.utils.paths.default_config_dir + "/notes/services"
1611 dirs = notes_matching_pattern_entries([notes_dir], host)
1612 item = svc
1613 else:
1614 dirs = [cmk.utils.paths.default_config_dir + "/notes/hosts"]
1615 item = host
1617 files = notes_matching_pattern_entries(dirs, item)
1618 files.sort()
1619 files.reverse()
1620 contents = []
1622 def replace_tags(text):
1623 sitename = row["site"]
1624 url_prefix = config.site(sitename)["url_prefix"]
1625 return text\
1626 .replace('$URL_PREFIX$', url_prefix)\
1627 .replace('$SITE$', sitename)\
1628 .replace('$HOSTNAME$', host)\
1629 .replace('$HOSTNAME_LOWER$', host.lower())\
1630 .replace('$HOSTNAME_UPPER$', host.upper())\
1631 .replace('$HOSTNAME_TITLE$', host[0].upper() + host[1:].lower())\
1632 .replace('$HOSTADDRESS$', row["host_address"])\
1633 .replace('$SERVICEOUTPUT$', row.get("service_plugin_output", ""))\
1634 .replace('$HOSTOUTPUT$', row.get("host_plugin_output", ""))\
1635 .replace('$SERVICEDESC$', row.get("service_description", ""))
1637 for f in files:
1638 contents.append(replace_tags(unicode(file(f).read(), "utf-8").strip()))
1639 return "", "<hr>".join(contents)
1642 @painter_registry.register
1643 class PainterSvcCustomNotes(Painter):
1644 @property
1645 def ident(self):
1646 return "svc_custom_notes"
1648 @property
1649 def title(self):
1650 return _("Custom services notes")
1652 @property
1653 def short_title(self):
1654 return _("Notes")
1656 @property
1657 def columns(self):
1658 return ['host_name', 'host_address', 'service_description', 'service_plugin_output']
1660 def render(self, row, cell):
1661 return paint_custom_notes("service", row)
1664 @painter_registry.register
1665 class PainterSvcStaleness(Painter):
1666 @property
1667 def ident(self):
1668 return "svc_staleness"
1670 @property
1671 def title(self):
1672 return _("Service staleness value")
1674 @property
1675 def short_title(self):
1676 return _("Staleness")
1678 @property
1679 def columns(self):
1680 return ['service_staleness']
1682 def render(self, row, cell):
1683 return ('', '%0.2f' % row.get('service_staleness', 0))
1686 def paint_is_stale(row):
1687 if is_stale(row):
1688 return "badflag", _('yes')
1689 return "goodflag", _('no')
1692 @painter_registry.register
1693 class PainterSvcIsStale(Painter):
1694 @property
1695 def ident(self):
1696 return "svc_is_stale"
1698 @property
1699 def title(self):
1700 return _("Service is stale")
1702 @property
1703 def short_title(self):
1704 return _("Stale")
1706 @property
1707 def columns(self):
1708 return ['service_staleness']
1710 @property
1711 def sorter(self):
1712 return 'svc_staleness'
1714 def render(self, row, cell):
1715 return paint_is_stale(row)
1718 @painter_registry.register
1719 class PainterSvcServicelevel(Painter):
1720 @property
1721 def ident(self):
1722 return "svc_servicelevel"
1724 @property
1725 def title(self):
1726 return _("Service service level")
1728 @property
1729 def short_title(self):
1730 return _("Service Level")
1732 @property
1733 def columns(self):
1734 return ['service_custom_variable_names', 'service_custom_variable_values']
1736 @property
1737 def sorter(self):
1738 return 'servicelevel'
1740 def render(self, row, cell):
1741 return paint_custom_var('service', 'EC_SL', row, config.mkeventd_service_levels)
1744 def paint_custom_vars(what, row, blacklist=None):
1745 if blacklist is None:
1746 blacklist = []
1748 items = row[what + "_custom_variables"].items()
1749 items.sort()
1750 rows = []
1751 for varname, value in items:
1752 if varname not in blacklist:
1753 rows.append(html.render_tr(html.render_td(varname) + html.render_td(value)))
1754 return '', "%s" % html.render_table(HTML().join(rows))
1757 @painter_registry.register
1758 class PainterServiceCustomVariables(Painter):
1759 @property
1760 def ident(self):
1761 return "svc_custom_vars"
1763 @property
1764 def title(self):
1765 return _("Service custom attributes")
1767 @property
1768 def columns(self):
1769 return ['service_custom_variables']
1771 def group_by(self, row):
1772 return tuple(row["service_custom_variables"].items())
1774 def render(self, row, cell):
1775 return paint_custom_vars('service', row)
1778 class ABCPainterCustomVariable(Painter):
1779 __metaclass__ = abc.ABCMeta
1781 @property
1782 def title(self):
1783 return self._dynamic_title
1785 @property
1786 def short_title(self):
1787 return self._dynamic_title
1789 def _dynamic_title(self, params=None):
1790 if params is None:
1791 # Happens in view editor when adding a painter
1792 return self._default_title
1794 try:
1795 return config.custom_service_attributes[params["ident"]]["title"]
1796 except KeyError:
1797 return self._default_title
1799 @abc.abstractproperty
1800 def _default_title(self):
1801 raise NotImplementedError()
1803 @abc.abstractproperty
1804 def _object_type(self):
1805 raise NotImplementedError()
1807 @abc.abstractmethod
1808 def _custom_attribute_choices(self):
1809 raise NotImplementedError()
1811 @property
1812 def parameters(self):
1813 return Dictionary(
1814 elements=[
1815 ("ident", DropdownChoice(
1816 choices=self._custom_attribute_choices,
1817 title=_("ID"),
1820 title=_("Options"),
1821 optional_keys=[],
1824 def render(self, row, cell):
1825 params = cell.painter_parameters()
1826 return paint_custom_var(self._object_type, params["ident"].upper(), row)
1829 @painter_registry.register
1830 class PainterServiceCustomVariable(ABCPainterCustomVariable):
1831 @property
1832 def ident(self):
1833 return "service_custom_variable"
1835 @property
1836 def columns(self):
1837 return ['service_custom_variable_names', 'service_custom_variable_values']
1839 @property
1840 def _default_title(self):
1841 return _("Service custom attribute")
1843 @property
1844 def _object_type(self):
1845 return "service"
1847 def _custom_attribute_choices(self):
1848 choices = []
1849 for ident, attr_spec in config.custom_service_attributes.items():
1850 choices.append((ident, attr_spec["title"]))
1851 return sorted(choices, key=lambda x: x[1])
1854 @painter_registry.register
1855 class PainterHostCustomVariable(ABCPainterCustomVariable):
1856 @property
1857 def ident(self):
1858 return "host_custom_variable"
1860 @property
1861 def columns(self):
1862 return ['host_custom_variable_names', 'host_custom_variable_values']
1864 @property
1865 def _default_title(self):
1866 return _("Host custom attribute")
1868 @property
1869 def _object_type(self):
1870 return "host"
1872 def _custom_attribute_choices(self):
1873 choices = []
1874 for attr_spec in config.wato_host_attrs:
1875 choices.append((attr_spec["name"], attr_spec["title"]))
1876 return sorted(choices, key=lambda x: x[1])
1880 # .--Hosts---------------------------------------------------------------.
1881 # | _ _ _ |
1882 # | | | | | ___ ___| |_ ___ |
1883 # | | |_| |/ _ \/ __| __/ __| |
1884 # | | _ | (_) \__ \ |_\__ \ |
1885 # | |_| |_|\___/|___/\__|___/ |
1886 # | |
1887 # +----------------------------------------------------------------------+
1888 # | Painters for hosts |
1889 # '----------------------------------------------------------------------'
1892 @painter_registry.register
1893 class PainterHostState(Painter):
1894 @property
1895 def ident(self):
1896 return "host_state"
1898 @property
1899 def title(self):
1900 return _("Host state")
1902 @property
1903 def short_title(self):
1904 return _("state")
1906 @property
1907 def columns(self):
1908 return ['host_has_been_checked', 'host_state']
1910 @property
1911 def sorter(self):
1912 return 'hoststate'
1914 def render(self, row, cell):
1915 return paint_host_state_short(row)
1918 @painter_registry.register
1919 class PainterHostStateOnechar(Painter):
1920 @property
1921 def ident(self):
1922 return "host_state_onechar"
1924 @property
1925 def title(self):
1926 return _("Host state (first character)")
1928 @property
1929 def short_title(self):
1930 return _("S.")
1932 @property
1933 def columns(self):
1934 return ['host_has_been_checked', 'host_state']
1936 @property
1937 def sorter(self):
1938 return 'hoststate'
1940 def render(self, row, cell):
1941 return paint_host_state_short(row, short=True)
1944 @painter_registry.register
1945 class PainterHostPluginOutput(Painter):
1946 @property
1947 def ident(self):
1948 return "host_plugin_output"
1950 @property
1951 def title(self):
1952 return _("Output of host check plugin")
1954 @property
1955 def short_title(self):
1956 return _("Status detail")
1958 @property
1959 def columns(self):
1960 return ['host_plugin_output', 'host_custom_variables']
1962 def render(self, row, cell):
1963 return (None, format_plugin_output(row["host_plugin_output"], row))
1966 @painter_registry.register
1967 class PainterHostPerfData(Painter):
1968 @property
1969 def ident(self):
1970 return "host_perf_data"
1972 @property
1973 def title(self):
1974 return _("Host performance data")
1976 @property
1977 def short_title(self):
1978 return _("Performance data")
1980 @property
1981 def columns(self):
1982 return ['host_perf_data']
1984 def render(self, row, cell):
1985 return (None, row["host_perf_data"])
1988 @painter_registry.register
1989 class PainterHostCheckCommand(Painter):
1990 @property
1991 def ident(self):
1992 return "host_check_command"
1994 @property
1995 def title(self):
1996 return _("Host check command")
1998 @property
1999 def short_title(self):
2000 return _("Check command")
2002 @property
2003 def columns(self):
2004 return ['host_check_command']
2006 def render(self, row, cell):
2007 return (None, row["host_check_command"])
2010 @painter_registry.register
2011 class PainterHostCheckCommandExpanded(Painter):
2012 @property
2013 def ident(self):
2014 return "host_check_command_expanded"
2016 @property
2017 def title(self):
2018 return _("Host check command expanded")
2020 @property
2021 def short_title(self):
2022 return _("Check command expanded")
2024 @property
2025 def columns(self):
2026 return ['host_check_command_expanded']
2028 def render(self, row, cell):
2029 return (None, row["host_check_command_expanded"])
2032 @painter_registry.register
2033 class PainterHostStateAge(Painter):
2034 @property
2035 def ident(self):
2036 return "host_state_age"
2038 @property
2039 def title(self):
2040 return _("The age of the current host state")
2042 @property
2043 def short_title(self):
2044 return _("Age")
2046 @property
2047 def columns(self):
2048 return ['host_has_been_checked', 'host_last_state_change']
2050 @property
2051 def painter_options(self):
2052 return ['ts_format', 'ts_date']
2054 def render(self, row, cell):
2055 return paint_age(row["host_last_state_change"], row["host_has_been_checked"] == 1, 60 * 10)
2058 @painter_registry.register
2059 class PainterHostCheckAge(Painter):
2060 @property
2061 def ident(self):
2062 return "host_check_age"
2064 @property
2065 def title(self):
2066 return _("The time since the last check of the host")
2068 @property
2069 def short_title(self):
2070 return _("Checked")
2072 @property
2073 def columns(self):
2074 return ['host_has_been_checked', 'host_last_check']
2076 @property
2077 def painter_options(self):
2078 return ['ts_format', 'ts_date']
2080 def render(self, row, cell):
2081 return paint_checked("host", row)
2084 @painter_registry.register
2085 class PainterHostNextCheck(Painter):
2086 @property
2087 def ident(self):
2088 return "host_next_check"
2090 @property
2091 def title(self):
2092 return _("The time of the next scheduled host check")
2094 @property
2095 def short_title(self):
2096 return _("Next check")
2098 @property
2099 def columns(self):
2100 return ['host_next_check']
2102 def render(self, row, cell):
2103 return paint_future_time(row["host_next_check"])
2106 @painter_registry.register
2107 class PainterHostNextNotification(Painter):
2108 @property
2109 def ident(self):
2110 return "host_next_notification"
2112 @property
2113 def title(self):
2114 return _("The time of the next host notification")
2116 @property
2117 def short_title(self):
2118 return _("Next notification")
2120 @property
2121 def columns(self):
2122 return ['host_next_notification']
2124 def render(self, row, cell):
2125 return paint_future_time(row["host_next_notification"])
2128 @painter_registry.register
2129 class PainterHostNotificationPostponementReason(Painter):
2130 @property
2131 def ident(self):
2132 return "host_notification_postponement_reason"
2134 @property
2135 def title(self):
2136 return _("Notification postponement reason")
2138 @property
2139 def short_title(self):
2140 return _("Notif. postponed")
2142 @property
2143 def columns(self):
2144 return ['host_notification_postponement_reason']
2146 def render(self, row, cell):
2147 return paint_notification_postponement_reason("host", row)
2150 @painter_registry.register
2151 class PainterHostLastNotification(Painter):
2152 @property
2153 def ident(self):
2154 return "host_last_notification"
2156 @property
2157 def title(self):
2158 return _("The time of the last host notification")
2160 @property
2161 def short_title(self):
2162 return _("last notification")
2164 @property
2165 def columns(self):
2166 return ['host_last_notification']
2168 @property
2169 def painter_options(self):
2170 return ['ts_format', 'ts_date']
2172 def render(self, row, cell):
2173 return paint_age(row["host_last_notification"], row["host_last_notification"], 0)
2176 @painter_registry.register
2177 class PainterHostCheckLatency(Painter):
2178 @property
2179 def ident(self):
2180 return "host_check_latency"
2182 @property
2183 def title(self):
2184 return _("Host check latency")
2186 @property
2187 def short_title(self):
2188 return _("Latency")
2190 @property
2191 def columns(self):
2192 return ['host_latency']
2194 def render(self, row, cell):
2195 return ("", cmk.utils.render.approx_age(row["host_latency"]))
2198 @painter_registry.register
2199 class PainterHostCheckDuration(Painter):
2200 @property
2201 def ident(self):
2202 return "host_check_duration"
2204 @property
2205 def title(self):
2206 return _("Host check duration")
2208 @property
2209 def short_title(self):
2210 return _("Duration")
2212 @property
2213 def columns(self):
2214 return ['host_execution_time']
2216 def render(self, row, cell):
2217 return ("", cmk.utils.render.approx_age(row["host_execution_time"]))
2220 @painter_registry.register
2221 class PainterHostAttempt(Painter):
2222 @property
2223 def ident(self):
2224 return "host_attempt"
2226 @property
2227 def title(self):
2228 return _("Current host check attempt")
2230 @property
2231 def short_title(self):
2232 return _("Att.")
2234 @property
2235 def columns(self):
2236 return ['host_current_attempt', 'host_max_check_attempts']
2238 def render(self, row, cell):
2239 return (None, "%d/%d" % (row["host_current_attempt"], row["host_max_check_attempts"]))
2242 @painter_registry.register
2243 class PainterHostNormalInterval(Painter):
2244 @property
2245 def ident(self):
2246 return "host_normal_interval"
2248 @property
2249 def title(self):
2250 return _("Normal check interval")
2252 @property
2253 def short_title(self):
2254 return _("Check int.")
2256 @property
2257 def columns(self):
2258 return ['host_check_interval']
2260 def render(self, row, cell):
2261 return (None, cmk.utils.render.approx_age(row["host_check_interval"] * 60.0))
2264 @painter_registry.register
2265 class PainterHostRetryInterval(Painter):
2266 @property
2267 def ident(self):
2268 return "host_retry_interval"
2270 @property
2271 def title(self):
2272 return _("Retry check interval")
2274 @property
2275 def short_title(self):
2276 return _("Retry")
2278 @property
2279 def columns(self):
2280 return ['host_retry_interval']
2282 def render(self, row, cell):
2283 return (None, cmk.utils.render.approx_age(row["host_retry_interval"] * 60.0))
2286 @painter_registry.register
2287 class PainterHostCheckInterval(Painter):
2288 @property
2289 def ident(self):
2290 return "host_check_interval"
2292 @property
2293 def title(self):
2294 return _("Normal/retry check interval")
2296 @property
2297 def short_title(self):
2298 return _("Interval")
2300 @property
2301 def columns(self):
2302 return ['host_check_interval', 'host_retry_interval']
2304 def render(self, row, cell):
2305 return (
2306 None,
2307 "%s / %s" % (cmk.utils.render.approx_age(row["host_check_interval"] * 60.0),
2308 cmk.utils.render.approx_age(row["host_retry_interval"] * 60.0)),
2312 @painter_registry.register
2313 class PainterHostCheckType(Painter):
2314 @property
2315 def ident(self):
2316 return "host_check_type"
2318 @property
2319 def title(self):
2320 return _("Host check type")
2322 @property
2323 def short_title(self):
2324 return _("Type")
2326 @property
2327 def columns(self):
2328 return ['host_check_type']
2330 def render(self, row, cell):
2331 return (None, row["host_check_type"] == 0 and "ACTIVE" or "PASSIVE")
2334 @painter_registry.register
2335 class PainterHostInNotifper(Painter):
2336 @property
2337 def ident(self):
2338 return "host_in_notifper"
2340 @property
2341 def title(self):
2342 return _("Host in notif. period")
2344 @property
2345 def short_title(self):
2346 return _("in notif. p.")
2348 @property
2349 def columns(self):
2350 return ['host_in_notification_period']
2352 def render(self, row, cell):
2353 return paint_nagiosflag(row, "host_in_notification_period", False)
2356 @painter_registry.register
2357 class PainterHostNotifper(Painter):
2358 @property
2359 def ident(self):
2360 return "host_notifper"
2362 @property
2363 def title(self):
2364 return _("Host notification period")
2366 @property
2367 def short_title(self):
2368 return _("notif.")
2370 @property
2371 def columns(self):
2372 return ['host_notification_period']
2374 def render(self, row, cell):
2375 return (None, row["host_notification_period"])
2378 @painter_registry.register
2379 class PainterHostNotificationNumber(Painter):
2380 @property
2381 def ident(self):
2382 return "host_notification_number"
2384 @property
2385 def title(self):
2386 return _("Host notification number")
2388 @property
2389 def short_title(self):
2390 return _("N#")
2392 @property
2393 def columns(self):
2394 return ['host_current_notification_number']
2396 def render(self, row, cell):
2397 return ("", str(row["host_current_notification_number"]))
2400 @painter_registry.register
2401 class PainterHostFlapping(Painter):
2402 @property
2403 def ident(self):
2404 return "host_flapping"
2406 @property
2407 def title(self):
2408 return _("Host is flapping")
2410 @property
2411 def short_title(self):
2412 return _("Flap")
2414 @property
2415 def columns(self):
2416 return ['host_is_flapping']
2418 def render(self, row, cell):
2419 return paint_nagiosflag(row, "host_is_flapping", True)
2422 @painter_registry.register
2423 class PainterHostIsActive(Painter):
2424 @property
2425 def ident(self):
2426 return "host_is_active"
2428 @property
2429 def title(self):
2430 return _("Host is active")
2432 @property
2433 def short_title(self):
2434 return _("Active")
2436 @property
2437 def columns(self):
2438 return ['host_active_checks_enabled']
2440 def render(self, row, cell):
2441 return paint_nagiosflag(row, "host_active_checks_enabled", None)
2444 @painter_registry.register
2445 class PainterHostNotificationsEnabled(Painter):
2446 @property
2447 def ident(self):
2448 return "host_notifications_enabled"
2450 @property
2451 def title(self):
2452 return _("Host notifications enabled")
2454 @property
2455 def short_title(self):
2456 return _("Notif.")
2458 @property
2459 def columns(self):
2460 return ['host_notifications_enabled']
2462 def render(self, row, cell):
2463 return paint_nagiosflag(row, "host_notifications_enabled", False)
2466 @painter_registry.register
2467 class PainterHostPnpgraph(Painter):
2468 @property
2469 def ident(self):
2470 return "host_pnpgraph"
2472 @property
2473 def title(self):
2474 return _("Host graph")
2476 @property
2477 def short_title(self):
2478 return _("Graph")
2480 @property
2481 def columns(self):
2482 return ['host_name', 'host_perf_data', 'host_metrics', 'host_check_command']
2484 @property
2485 def printable(self):
2486 return 'time_graph'
2488 @property
2489 def painter_options(self):
2490 return ['pnp_timerange']
2492 @property
2493 def parameters(self):
2494 return time_graph_params()
2496 def render(self, row, cell):
2497 return paint_time_graph(row, cell)
2500 @painter_registry.register
2501 class PainterHostBlack(Painter):
2502 @property
2503 def ident(self):
2504 return "host_black"
2506 @property
2507 def title(self):
2508 return _("Hostname, red background if down or unreachable (Deprecated)")
2510 @property
2511 def short_title(self):
2512 return _("Host")
2514 @property
2515 def columns(self):
2516 return ['site', 'host_name', 'host_state']
2518 @property
2519 def sorter(self):
2520 return 'site_host'
2522 def render(self, row, cell):
2523 state = row["host_state"]
2524 if state != 0:
2525 return "nobr", "<div class=hostdown>%s</div>" % row["host_name"]
2526 return "nobr", row["host_name"]
2529 @painter_registry.register
2530 class PainterHostBlackNagios(Painter):
2531 @property
2532 def ident(self):
2533 return "host_black_nagios"
2535 @property
2536 def title(self):
2537 return _("Hostname, red background if down, link to Nagios services")
2539 @property
2540 def short_title(self):
2541 return _("Host")
2543 @property
2544 def columns(self):
2545 return ['site', 'host_name', 'host_state']
2547 @property
2548 def sorter(self):
2549 return 'site_host'
2551 def render(self, row, cell):
2552 host = row["host_name"]
2553 baseurl = config.site(row["site"])["url_prefix"] + "nagios/cgi-bin"
2554 url = baseurl + "/status.cgi?host=" + html.urlencode(host)
2555 state = row["host_state"]
2556 if state != 0:
2557 return None, html.render_div(html.render_a(host, url), class_="hostdown")
2558 return None, html.render_a(host, url)
2561 @painter_registry.register
2562 class PainterHostNagiosLink(Painter):
2563 @property
2564 def ident(self):
2565 return "host_nagios_link"
2567 @property
2568 def title(self):
2569 return _("Icon with link to host to Nagios GUI")
2571 @property
2572 def short_title(self):
2573 return u""
2575 @property
2576 def columns(self):
2577 return ['site', 'host_name']
2579 def render(self, row, cell):
2580 return paint_nagios_link(row)
2583 @painter_registry.register
2584 class PainterHostWithState(Painter):
2585 @property
2586 def ident(self):
2587 return "host_with_state"
2589 @property
2590 def title(self):
2591 return _("Hostname, marked red if down (Deprecated)")
2593 @property
2594 def short_title(self):
2595 return _("Host")
2597 @property
2598 def columns(self):
2599 return ['site', 'host_name', 'host_state', 'host_has_been_checked']
2601 @property
2602 def sorter(self):
2603 return 'site_host'
2605 def render(self, row, cell):
2606 if row["host_has_been_checked"]:
2607 state = row["host_state"]
2608 else:
2609 state = "p"
2610 if state != 0:
2611 return "state hstate hstate%s" % state, row["host_name"]
2612 return "nobr", row["host_name"]
2615 @painter_registry.register
2616 class PainterHost(Painter):
2617 @property
2618 def ident(self):
2619 return "host"
2621 @property
2622 def title(self):
2623 return _("Hostname")
2625 @property
2626 def short_title(self):
2627 return _("Host")
2629 @property
2630 def columns(self):
2631 return ['host_name', 'host_state', 'host_has_been_checked', 'host_scheduled_downtime_depth']
2633 @property
2634 def sorter(self):
2635 return 'site_host'
2637 @property
2638 def parameters(self):
2639 elements = [("color_choices",
2640 ListChoice(
2641 choices=[("colorize_up", _("Colorize background if host is up")),
2642 ("colorize_down", _("Colorize background if host is down")),
2643 ("colorize_unreachable",
2644 _("Colorize background if host unreachable")),
2645 ("colorize_pending", _("Colorize background if host is pending")),
2646 ("colorize_downtime",
2647 _("Colorize background if host is downtime"))],
2648 title=_("Coloring"),
2649 help=_("Here you can configure the background color for specific states. "
2650 "The coloring for host in dowtime overrules all other coloring.")))]
2652 return Dictionary(elements=elements, title=_("Options"), optional_keys=[])
2654 def render(self, row, cell):
2655 params = cell.painter_parameters()
2656 color_choices = params["color_choices"]
2658 if row["host_has_been_checked"]:
2659 state = row["host_state"]
2660 else:
2661 state = "p"
2663 css = ["nobr"]
2664 if "colorize_downtime" in color_choices and row["host_scheduled_downtime_depth"] > 0:
2665 css.extend(["hstate", "hstated"])
2667 # Also apply other css classes, even if its already in downtime
2668 for key, option_state in [
2669 ("colorize_up", 0),
2670 ("colorize_down", 1),
2671 ("colorize_unreachable", 2),
2672 ("colorize_pending", "p"),
2674 if key in color_choices and state == option_state:
2675 if "hstate" not in css:
2676 css.append("hstate")
2677 css.append("hstate%s" % option_state)
2678 break
2680 return " ".join(css), row["host_name"]
2683 @painter_registry.register
2684 class PainterAlias(Painter):
2685 @property
2686 def ident(self):
2687 return "alias"
2689 @property
2690 def title(self):
2691 return _("Host alias")
2693 @property
2694 def short_title(self):
2695 return _("Alias")
2697 @property
2698 def columns(self):
2699 return ['host_alias']
2701 def render(self, row, cell):
2702 return ("", html.attrencode(row["host_alias"]))
2705 @painter_registry.register
2706 class PainterHostAddress(Painter):
2707 @property
2708 def ident(self):
2709 return "host_address"
2711 @property
2712 def title(self):
2713 return _("Host address (Primary)")
2715 @property
2716 def short_title(self):
2717 return _("IP address")
2719 @property
2720 def columns(self):
2721 return ['host_address']
2723 def render(self, row, cell):
2724 return ("", row["host_address"])
2727 @painter_registry.register
2728 class PainterHostIpv4Address(Painter):
2729 @property
2730 def ident(self):
2731 return "host_ipv4_address"
2733 @property
2734 def title(self):
2735 return _("Host address (IPv4)")
2737 @property
2738 def short_title(self):
2739 return _("IPv4 address")
2741 @property
2742 def columns(self):
2743 return ['host_custom_variable_names', 'host_custom_variable_values']
2745 def render(self, row, cell):
2746 return paint_custom_var('host', 'ADDRESS_4', row)
2749 @painter_registry.register
2750 class PainterHostIpv6Address(Painter):
2751 @property
2752 def ident(self):
2753 return "host_ipv6_address"
2755 @property
2756 def title(self):
2757 return _("Host address (IPv6)")
2759 @property
2760 def short_title(self):
2761 return _("IPv6 address")
2763 @property
2764 def columns(self):
2765 return ['host_custom_variable_names', 'host_custom_variable_values']
2767 def render(self, row, cell):
2768 return paint_custom_var('host', 'ADDRESS_6', row)
2771 @painter_registry.register
2772 class PainterHostAddresses(Painter):
2773 @property
2774 def ident(self):
2775 return "host_addresses"
2777 @property
2778 def title(self):
2779 return _("Host addresses (IPv4/IPv6)")
2781 @property
2782 def short_title(self):
2783 return _("IP addresses")
2785 @property
2786 def columns(self):
2787 return ['host_address', 'host_custom_variable_names', 'host_custom_variable_values']
2789 def render(self, row, cell):
2790 custom_vars = dict(
2791 zip(row["host_custom_variable_names"], row["host_custom_variable_values"]))
2793 if custom_vars.get("ADDRESS_FAMILY", "4") == "4":
2794 primary = custom_vars.get("ADDRESS_4", "")
2795 secondary = custom_vars.get("ADDRESS_6", "")
2796 else:
2797 primary = custom_vars.get("ADDRESS_6", "")
2798 secondary = custom_vars.get("ADDRESS_4", "")
2800 if secondary:
2801 secondary = " (%s)" % secondary
2802 return "", primary + secondary
2805 @painter_registry.register
2806 class PainterHostAddressesAdditional(Painter):
2807 @property
2808 def ident(self):
2809 return "host_addresses_additional"
2811 @property
2812 def title(self):
2813 return _("Host addresses (additional)")
2815 @property
2816 def short_title(self):
2817 return _("Add. addresses")
2819 @property
2820 def columns(self):
2821 return ["host_custom_variable_names", "host_custom_variable_values"]
2823 def render(self, row, cell):
2824 custom_vars = dict(
2825 zip(row["host_custom_variable_names"], row["host_custom_variable_values"]))
2827 ipv4_addresses = custom_vars.get("ADDRESSES_4", "").strip()
2828 ipv6_addresses = custom_vars.get("ADDRESSES_6", "").strip()
2830 addresses = []
2831 if ipv4_addresses:
2832 addresses += ipv4_addresses.split(" ")
2833 if ipv6_addresses:
2834 addresses += ipv6_addresses.split(" ")
2836 return "", ", ".join(addresses)
2839 @painter_registry.register
2840 class PainterHostAddressFamily(Painter):
2841 @property
2842 def ident(self):
2843 return "host_address_family"
2845 @property
2846 def title(self):
2847 return _("Host address family (Primary)")
2849 @property
2850 def short_title(self):
2851 return _("Address family")
2853 @property
2854 def columns(self):
2855 return ['host_custom_variable_names', 'host_custom_variable_values']
2857 def render(self, row, cell):
2858 return paint_custom_var('host', 'ADDRESS_FAMILY', row)
2861 @painter_registry.register
2862 class PainterHostAddressFamilies(Painter):
2863 @property
2864 def ident(self):
2865 return "host_address_families"
2867 @property
2868 def title(self):
2869 return _("Host address families")
2871 @property
2872 def short_title(self):
2873 return _("Address families")
2875 @property
2876 def columns(self):
2877 return ['host_custom_variable_names', 'host_custom_variable_values']
2879 def render(self, row, cell):
2880 custom_vars = dict(
2881 zip(row["host_custom_variable_names"], row["host_custom_variable_values"]))
2883 primary = custom_vars.get("ADDRESS_FAMILY", "4")
2885 families = [primary]
2886 if primary == "6" and custom_vars.get("ADDRESS_4"):
2887 families.append("4")
2888 elif primary == "4" and custom_vars.get("ADDRESS_6"):
2889 families.append("6")
2891 return "", ", ".join(families)
2894 def paint_svc_count(id_, count):
2895 if count > 0:
2896 return "count svcstate state%s" % id_, str(count)
2897 return "count svcstate statex", "0"
2900 def paint_host_count(id_, count):
2901 if count > 0:
2902 if id_ is not None:
2903 return "count hstate hstate%s" % id_, str(count)
2904 # pending
2905 return "count hstate hstatep", str(count)
2907 return "count hstate hstatex", "0"
2910 @painter_registry.register
2911 class PainterNumServices(Painter):
2912 @property
2913 def ident(self):
2914 return "num_services"
2916 @property
2917 def title(self):
2918 return _("Number of services")
2920 @property
2921 def short_title(self):
2922 return u""
2924 @property
2925 def columns(self):
2926 return ['host_num_services']
2928 def render(self, row, cell):
2929 return (None, str(row["host_num_services"]))
2932 @painter_registry.register
2933 class PainterNumServicesOk(Painter):
2934 @property
2935 def ident(self):
2936 return "num_services_ok"
2938 @property
2939 def title(self):
2940 return _("Number of services in state OK")
2942 @property
2943 def short_title(self):
2944 return _("OK")
2946 @property
2947 def columns(self):
2948 return ['host_num_services_ok']
2950 def render(self, row, cell):
2951 return paint_svc_count(0, row["host_num_services_ok"])
2954 @painter_registry.register
2955 class PainterNumProblems(Painter):
2956 @property
2957 def ident(self):
2958 return "num_problems"
2960 @property
2961 def title(self):
2962 return _("Number of problems")
2964 @property
2965 def short_title(self):
2966 return _("Pro.")
2968 @property
2969 def columns(self):
2970 return ['host_num_services', 'host_num_services_ok', 'host_num_services_pending']
2972 def render(self, row, cell):
2973 return paint_svc_count(
2974 's', row["host_num_services"] - row["host_num_services_ok"] -
2975 row["host_num_services_pending"])
2978 @painter_registry.register
2979 class PainterNumServicesWarn(Painter):
2980 @property
2981 def ident(self):
2982 return "num_services_warn"
2984 @property
2985 def title(self):
2986 return _("Number of services in state WARN")
2988 @property
2989 def short_title(self):
2990 return _("Wa")
2992 @property
2993 def columns(self):
2994 return ['host_num_services_warn']
2996 def render(self, row, cell):
2997 return paint_svc_count(1, row["host_num_services_warn"])
3000 @painter_registry.register
3001 class PainterNumServicesCrit(Painter):
3002 @property
3003 def ident(self):
3004 return "num_services_crit"
3006 @property
3007 def title(self):
3008 return _("Number of services in state CRIT")
3010 @property
3011 def short_title(self):
3012 return _("Cr")
3014 @property
3015 def columns(self):
3016 return ['host_num_services_crit']
3018 def render(self, row, cell):
3019 return paint_svc_count(2, row["host_num_services_crit"])
3022 @painter_registry.register
3023 class PainterNumServicesUnknown(Painter):
3024 @property
3025 def ident(self):
3026 return "num_services_unknown"
3028 @property
3029 def title(self):
3030 return _("Number of services in state UNKNOWN")
3032 @property
3033 def short_title(self):
3034 return _("Un")
3036 @property
3037 def columns(self):
3038 return ['host_num_services_unknown']
3040 def render(self, row, cell):
3041 return paint_svc_count(3, row["host_num_services_unknown"])
3044 @painter_registry.register
3045 class PainterNumServicesPending(Painter):
3046 @property
3047 def ident(self):
3048 return "num_services_pending"
3050 @property
3051 def title(self):
3052 return _("Number of services in state PENDING")
3054 @property
3055 def short_title(self):
3056 return _("Pd")
3058 @property
3059 def columns(self):
3060 return ['host_num_services_pending']
3062 def render(self, row, cell):
3063 return paint_svc_count("p", row["host_num_services_pending"])
3066 def paint_service_list(row, columnname):
3067 def sort_key(entry):
3068 if columnname.startswith("servicegroup"):
3069 return entry[0].lower(), entry[1].lower()
3070 return entry[0].lower()
3072 h = ""
3073 for entry in sorted(row[columnname], key=sort_key):
3074 if columnname.startswith("servicegroup"):
3075 host, svc, state, checked = entry
3076 text = host + " ~ " + svc
3077 else:
3078 svc, state, checked = entry
3079 host = row["host_name"]
3080 text = svc
3081 link = "view.py?view_name=service&site=%s&host=%s&service=%s" % (html.urlencode(
3082 row["site"]), html.urlencode(host), html.urlencode(svc))
3083 if checked:
3084 css = "state%d" % state
3085 else:
3086 css = "statep"
3088 h += html.render_div(html.render_a(text, link), class_=css)
3090 return "", html.render_div(h, class_="objectlist")
3093 @painter_registry.register
3094 class PainterHostServices(Painter):
3095 @property
3096 def ident(self):
3097 return "host_services"
3099 @property
3100 def title(self):
3101 return _("Services colored according to state")
3103 @property
3104 def short_title(self):
3105 return _("Services")
3107 @property
3108 def columns(self):
3109 return ['host_name', 'host_services_with_state']
3111 def render(self, row, cell):
3112 return paint_service_list(row, "host_services_with_state")
3115 @painter_registry.register
3116 class PainterHostParents(Painter):
3117 @property
3118 def ident(self):
3119 return "host_parents"
3121 @property
3122 def title(self):
3123 return _("Host's parents")
3125 @property
3126 def short_title(self):
3127 return _("Parents")
3129 @property
3130 def columns(self):
3131 return ['host_parents']
3133 def render(self, row, cell):
3134 return paint_host_list(row["site"], row["host_parents"])
3137 @painter_registry.register
3138 class PainterHostChilds(Painter):
3139 @property
3140 def ident(self):
3141 return "host_childs"
3143 @property
3144 def title(self):
3145 return _("Host's children")
3147 @property
3148 def short_title(self):
3149 return _("children")
3151 @property
3152 def columns(self):
3153 return ['host_childs']
3155 def render(self, row, cell):
3156 return paint_host_list(row["site"], row["host_childs"])
3159 @painter_registry.register
3160 class PainterHostGroupMemberlist(Painter):
3161 @property
3162 def ident(self):
3163 return "host_group_memberlist"
3165 @property
3166 def title(self):
3167 return _("Host groups the host is member of")
3169 @property
3170 def short_title(self):
3171 return _("Groups")
3173 @property
3174 def columns(self):
3175 return ['host_groups']
3177 def group_by(self, row):
3178 return tuple(row["host_groups"])
3180 def render(self, row, cell):
3181 links = []
3182 for group in row["host_groups"]:
3183 link = "view.py?view_name=hostgroup&hostgroup=" + group
3184 if html.request.var("display_options"):
3185 link += "&display_options=%s" % html.attrencode(html.request.var("display_options"))
3186 links.append(html.render_a(group, link))
3187 return "", HTML(", ").join(links)
3190 @painter_registry.register
3191 class PainterHostContacts(Painter):
3192 @property
3193 def ident(self):
3194 return "host_contacts"
3196 @property
3197 def title(self):
3198 return _("Host contacts")
3200 @property
3201 def short_title(self):
3202 return _("Contacts")
3204 @property
3205 def columns(self):
3206 return ['host_contacts']
3208 def render(self, row, cell):
3209 return (None, ", ".join(row["host_contacts"]))
3212 @painter_registry.register
3213 class PainterHostContactGroups(Painter):
3214 @property
3215 def ident(self):
3216 return "host_contact_groups"
3218 @property
3219 def title(self):
3220 return _("Host contact groups")
3222 @property
3223 def short_title(self):
3224 return _("Contact groups")
3226 @property
3227 def columns(self):
3228 return ['host_contact_groups']
3230 def render(self, row, cell):
3231 return (None, ", ".join(row["host_contact_groups"]))
3234 @painter_registry.register
3235 class PainterHostCustomNotes(Painter):
3236 @property
3237 def ident(self):
3238 return "host_custom_notes"
3240 @property
3241 def title(self):
3242 return _("Custom host notes")
3244 @property
3245 def short_title(self):
3246 return _("Notes")
3248 @property
3249 def columns(self):
3250 return ['host_name', 'host_address', 'host_plugin_output']
3252 def render(self, row, cell):
3253 return paint_custom_notes("hosts", row)
3256 @painter_registry.register
3257 class PainterHostComments(Painter):
3258 @property
3259 def ident(self):
3260 return "host_comments"
3262 @property
3263 def title(self):
3264 return _("Host comments")
3266 @property
3267 def short_title(self):
3268 return _("Comments")
3270 @property
3271 def columns(self):
3272 return ['host_comments_with_info']
3274 def render(self, row, cell):
3275 return paint_comments("host_", row)
3278 @painter_registry.register
3279 class PainterHostInDowntime(Painter):
3280 @property
3281 def ident(self):
3282 return "host_in_downtime"
3284 @property
3285 def title(self):
3286 return _("Host in downtime")
3288 @property
3289 def short_title(self):
3290 return _("Downtime")
3292 @property
3293 def columns(self):
3294 return ['host_scheduled_downtime_depth']
3296 def render(self, row, cell):
3297 return paint_nagiosflag(row, "host_scheduled_downtime_depth", True)
3300 @painter_registry.register
3301 class PainterHostAcknowledged(Painter):
3302 @property
3303 def ident(self):
3304 return "host_acknowledged"
3306 @property
3307 def title(self):
3308 return _("Host problem acknowledged")
3310 @property
3311 def short_title(self):
3312 return _("Ack")
3314 @property
3315 def columns(self):
3316 return ['host_acknowledged']
3318 def render(self, row, cell):
3319 return paint_nagiosflag(row, "host_acknowledged", False)
3322 @painter_registry.register
3323 class PainterHostStaleness(Painter):
3324 @property
3325 def ident(self):
3326 return "host_staleness"
3328 @property
3329 def title(self):
3330 return _("Host staleness value")
3332 @property
3333 def short_title(self):
3334 return _("Staleness")
3336 @property
3337 def columns(self):
3338 return ['host_staleness']
3340 def render(self, row, cell):
3341 return ('', '%0.2f' % row.get('host_staleness', 0))
3344 @painter_registry.register
3345 class PainterHostIsStale(Painter):
3346 @property
3347 def ident(self):
3348 return "host_is_stale"
3350 @property
3351 def title(self):
3352 return _("Host is stale")
3354 @property
3355 def short_title(self):
3356 return _("Stale")
3358 @property
3359 def columns(self):
3360 return ['host_staleness']
3362 @property
3363 def sorter(self):
3364 return 'svc_staleness'
3366 def render(self, row, cell):
3367 return paint_is_stale(row)
3370 @painter_registry.register
3371 class PainterHostServicelevel(Painter):
3372 @property
3373 def ident(self):
3374 return "host_servicelevel"
3376 @property
3377 def title(self):
3378 return _("Host service level")
3380 @property
3381 def short_title(self):
3382 return _("Service Level")
3384 @property
3385 def columns(self):
3386 return ['host_custom_variable_names', 'host_custom_variable_values']
3388 @property
3389 def sorter(self):
3390 return 'servicelevel'
3392 def render(self, row, cell):
3393 return paint_custom_var('host', 'EC_SL', row, config.mkeventd_service_levels)
3396 @painter_registry.register
3397 class PainterHostCustomVariables(Painter):
3398 @property
3399 def ident(self):
3400 return "host_custom_vars"
3402 @property
3403 def title(self):
3404 return _("Host custom attributes")
3406 @property
3407 def columns(self):
3408 return ['host_custom_variables']
3410 def group_by(self, row):
3411 return tuple(row["host_custom_variables"].items())
3413 def render(self, row, cell):
3414 return paint_custom_vars('host', row, [
3415 'FILENAME',
3416 'TAGS',
3417 'ADDRESS_4',
3418 'ADDRESS_6',
3419 'ADDRESS_FAMILY',
3420 'NODEIPS',
3421 'NODEIPS_4',
3422 'NODEIPS_6',
3426 def paint_discovery_output(field, row):
3427 value = row[field]
3428 if field == "discovery_state":
3429 ruleset_url = "wato.py?mode=edit_ruleset&varname=ignored_services"
3430 discovery_url = "wato.py?mode=inventory&host=%s&mode=inventory" % row["host_name"]
3432 return None, {
3433 "ignored": html.render_icon_button(ruleset_url, 'Disabled (configured away by admin)',
3434 'rulesets') + "Disabled (configured away by admin)",
3435 "vanished": html.render_icon_button(
3436 discovery_url, 'Vanished (checked, but no longer exist)', 'services') +
3437 "Vanished (checked, but no longer exist)",
3438 "unmonitored": html.render_icon_button(discovery_url, 'Available (missing)', 'services')
3439 + "Available (missing)"
3440 }.get(value, value)
3441 elif field == "discovery_service" and row["discovery_state"] == "vanished":
3442 link = "view.py?view_name=service&site=%s&host=%s&service=%s" % (html.urlencode(
3443 row["site"]), html.urlencode(row["host_name"]), html.urlencode(value))
3444 return None, html.render_div(html.render_a(value, link))
3445 return None, value
3448 @painter_registry.register
3449 class PainterServiceDiscoveryState(Painter):
3450 @property
3451 def ident(self):
3452 return "service_discovery_state"
3454 @property
3455 def title(self):
3456 return _("Service discovery: State")
3458 @property
3459 def short_title(self):
3460 return _("State")
3462 @property
3463 def columns(self):
3464 return ['discovery_state']
3466 def render(self, row, cell):
3467 return paint_discovery_output("discovery_state", row)
3470 @painter_registry.register
3471 class PainterServiceDiscoveryCheck(Painter):
3472 @property
3473 def ident(self):
3474 return "service_discovery_check"
3476 @property
3477 def title(self):
3478 return _("Service discovery: Check type")
3480 @property
3481 def short_title(self):
3482 return _("Check type")
3484 @property
3485 def columns(self):
3486 return ['discovery_state', 'discovery_check', 'discovery_service']
3488 def render(self, row, cell):
3489 return paint_discovery_output("discovery_check", row)
3492 @painter_registry.register
3493 class PainterServiceDiscoveryService(Painter):
3494 @property
3495 def ident(self):
3496 return "service_discovery_service"
3498 @property
3499 def title(self):
3500 return _("Service discovery: Service description")
3502 @property
3503 def short_title(self):
3504 return _("Service description")
3506 @property
3507 def columns(self):
3508 return ['discovery_state', 'discovery_check', 'discovery_service']
3510 def render(self, row, cell):
3511 return paint_discovery_output("discovery_service", row)
3514 # _ _ _
3515 # | | | | ___ ___| |_ __ _ _ __ ___ _ _ _ __ ___
3516 # | |_| |/ _ \/ __| __/ _` | '__/ _ \| | | | '_ \/ __|
3517 # | _ | (_) \__ \ || (_| | | | (_) | |_| | |_) \__ \
3518 # |_| |_|\___/|___/\__\__, |_| \___/ \__,_| .__/|___/
3519 # |___/ |_|
3521 @painter_registry.register
3522 class PainterHostgroupHosts(Painter):
3523 @property
3524 def ident(self):
3525 return "hostgroup_hosts"
3527 @property
3528 def title(self):
3529 return _("Hosts colored according to state (Host Group)")
3531 @property
3532 def short_title(self):
3533 return _("Hosts")
3535 @property
3536 def columns(self):
3537 return ['hostgroup_members_with_state']
3539 def render(self, row, cell):
3540 h = ""
3541 for host, state, checked in row["hostgroup_members_with_state"]:
3542 link = "view.py?view_name=host&site=%s&host=%s" % (html.urlencode(row["site"]),
3543 html.urlencode(host))
3544 if checked:
3545 css = "hstate%d" % state
3546 else:
3547 css = "hstatep"
3548 h += html.render_div(html.render_a(host, link), class_=css)
3549 return "", html.render_div(h, class_="objectlist")
3552 @painter_registry.register
3553 class PainterHgNumServices(Painter):
3554 @property
3555 def ident(self):
3556 return "hg_num_services"
3558 @property
3559 def title(self):
3560 return _("Number of services (Host Group)")
3562 @property
3563 def short_title(self):
3564 return u""
3566 @property
3567 def columns(self):
3568 return ['hostgroup_num_services']
3570 def render(self, row, cell):
3571 return (None, str(row["hostgroup_num_services"]))
3574 @painter_registry.register
3575 class PainterHgNumServicesOk(Painter):
3576 @property
3577 def ident(self):
3578 return "hg_num_services_ok"
3580 @property
3581 def title(self):
3582 return _("Number of services in state OK (Host Group)")
3584 @property
3585 def short_title(self):
3586 return _("O")
3588 @property
3589 def columns(self):
3590 return ['hostgroup_num_services_ok']
3592 def render(self, row, cell):
3593 return paint_svc_count(0, row["hostgroup_num_services_ok"])
3596 @painter_registry.register
3597 class PainterHgNumServicesWarn(Painter):
3598 @property
3599 def ident(self):
3600 return "hg_num_services_warn"
3602 @property
3603 def title(self):
3604 return _("Number of services in state WARN (Host Group)")
3606 @property
3607 def short_title(self):
3608 return _("W")
3610 @property
3611 def columns(self):
3612 return ['hostgroup_num_services_warn']
3614 def render(self, row, cell):
3615 return paint_svc_count(1, row["hostgroup_num_services_warn"])
3618 @painter_registry.register
3619 class PainterHgNumServicesCrit(Painter):
3620 @property
3621 def ident(self):
3622 return "hg_num_services_crit"
3624 @property
3625 def title(self):
3626 return _("Number of services in state CRIT (Host Group)")
3628 @property
3629 def short_title(self):
3630 return _("C")
3632 @property
3633 def columns(self):
3634 return ['hostgroup_num_services_crit']
3636 def render(self, row, cell):
3637 return paint_svc_count(2, row["hostgroup_num_services_crit"])
3640 @painter_registry.register
3641 class PainterHgNumServicesUnknown(Painter):
3642 @property
3643 def ident(self):
3644 return "hg_num_services_unknown"
3646 @property
3647 def title(self):
3648 return _("Number of services in state UNKNOWN (Host Group)")
3650 @property
3651 def short_title(self):
3652 return _("U")
3654 @property
3655 def columns(self):
3656 return ['hostgroup_num_services_unknown']
3658 def render(self, row, cell):
3659 return paint_svc_count(3, row["hostgroup_num_services_unknown"])
3662 @painter_registry.register
3663 class PainterHgNumServicesPending(Painter):
3664 @property
3665 def ident(self):
3666 return "hg_num_services_pending"
3668 @property
3669 def title(self):
3670 return _("Number of services in state PENDING (Host Group)")
3672 @property
3673 def short_title(self):
3674 return _("P")
3676 @property
3677 def columns(self):
3678 return ['hostgroup_num_services_pending']
3680 def render(self, row, cell):
3681 return paint_svc_count("p", row["hostgroup_num_services_pending"])
3684 @painter_registry.register
3685 class PainterHgNumHostsUp(Painter):
3686 @property
3687 def ident(self):
3688 return "hg_num_hosts_up"
3690 @property
3691 def title(self):
3692 return _("Number of hosts in state UP (Host Group)")
3694 @property
3695 def short_title(self):
3696 return _("Up")
3698 @property
3699 def columns(self):
3700 return ['hostgroup_num_hosts_up']
3702 def render(self, row, cell):
3703 return paint_host_count(0, row["hostgroup_num_hosts_up"])
3706 @painter_registry.register
3707 class PainterHgNumHostsDown(Painter):
3708 @property
3709 def ident(self):
3710 return "hg_num_hosts_down"
3712 @property
3713 def title(self):
3714 return _("Number of hosts in state DOWN (Host Group)")
3716 @property
3717 def short_title(self):
3718 return _("Dw")
3720 @property
3721 def columns(self):
3722 return ['hostgroup_num_hosts_down']
3724 def render(self, row, cell):
3725 return paint_host_count(1, row["hostgroup_num_hosts_down"])
3728 @painter_registry.register
3729 class PainterHgNumHostsUnreach(Painter):
3730 @property
3731 def ident(self):
3732 return "hg_num_hosts_unreach"
3734 @property
3735 def title(self):
3736 return _("Number of hosts in state UNREACH (Host Group)")
3738 @property
3739 def short_title(self):
3740 return _("Un")
3742 @property
3743 def columns(self):
3744 return ['hostgroup_num_hosts_unreach']
3746 def render(self, row, cell):
3747 return paint_host_count(2, row["hostgroup_num_hosts_unreach"])
3750 @painter_registry.register
3751 class PainterHgNumHostsPending(Painter):
3752 @property
3753 def ident(self):
3754 return "hg_num_hosts_pending"
3756 @property
3757 def title(self):
3758 return _("Number of hosts in state PENDING (Host Group)")
3760 @property
3761 def short_title(self):
3762 return _("Pd")
3764 @property
3765 def columns(self):
3766 return ['hostgroup_num_hosts_pending']
3768 def render(self, row, cell):
3769 return paint_host_count(None, row["hostgroup_num_hosts_pending"])
3772 @painter_registry.register
3773 class PainterHgName(Painter):
3774 @property
3775 def ident(self):
3776 return "hg_name"
3778 @property
3779 def title(self):
3780 return _("Hostgroup name")
3782 @property
3783 def short_title(self):
3784 return _("Name")
3786 @property
3787 def columns(self):
3788 return ['hostgroup_name']
3790 def render(self, row, cell):
3791 return (None, row["hostgroup_name"])
3794 @painter_registry.register
3795 class PainterHgAlias(Painter):
3796 @property
3797 def ident(self):
3798 return "hg_alias"
3800 @property
3801 def title(self):
3802 return _("Hostgroup alias")
3804 @property
3805 def short_title(self):
3806 return _("Alias")
3808 @property
3809 def columns(self):
3810 return ['hostgroup_alias']
3812 def render(self, row, cell):
3813 return (None, html.attrencode(row["hostgroup_alias"]))
3816 # ____ _
3817 # / ___| ___ _ ____ _(_) ___ ___ __ _ _ __ ___ _ _ _ __ ___
3818 # \___ \ / _ \ '__\ \ / / |/ __/ _ \/ _` | '__/ _ \| | | | '_ \/ __|
3819 # ___) | __/ | \ V /| | (_| __/ (_| | | | (_) | |_| | |_) \__ \
3820 # |____/ \___|_| \_/ |_|\___\___|\__, |_| \___/ \__,_| .__/|___/
3821 # |___/ |_|
3824 @painter_registry.register
3825 class PainterSgServices(Painter):
3826 @property
3827 def ident(self):
3828 return "sg_services"
3830 @property
3831 def title(self):
3832 return _("Services colored according to state (Service Group)")
3834 @property
3835 def short_title(self):
3836 return _("Services")
3838 @property
3839 def columns(self):
3840 return ['servicegroup_members_with_state']
3842 def render(self, row, cell):
3843 return paint_service_list(row, "servicegroup_members_with_state")
3846 @painter_registry.register
3847 class PainterSgNumServices(Painter):
3848 @property
3849 def ident(self):
3850 return "sg_num_services"
3852 @property
3853 def title(self):
3854 return _("Number of services (Service Group)")
3856 @property
3857 def short_title(self):
3858 return u""
3860 @property
3861 def columns(self):
3862 return ['servicegroup_num_services']
3864 def render(self, row, cell):
3865 return (None, str(row["servicegroup_num_services"]))
3868 @painter_registry.register
3869 class PainterSgNumServicesOk(Painter):
3870 @property
3871 def ident(self):
3872 return "sg_num_services_ok"
3874 @property
3875 def title(self):
3876 return _("Number of services in state OK (Service Group)")
3878 @property
3879 def short_title(self):
3880 return _("O")
3882 @property
3883 def columns(self):
3884 return ['servicegroup_num_services_ok']
3886 def render(self, row, cell):
3887 return paint_svc_count(0, row["servicegroup_num_services_ok"])
3890 @painter_registry.register
3891 class PainterSgNumServicesWarn(Painter):
3892 @property
3893 def ident(self):
3894 return "sg_num_services_warn"
3896 @property
3897 def title(self):
3898 return _("Number of services in state WARN (Service Group)")
3900 @property
3901 def short_title(self):
3902 return _("W")
3904 @property
3905 def columns(self):
3906 return ['servicegroup_num_services_warn']
3908 def render(self, row, cell):
3909 return paint_svc_count(1, row["servicegroup_num_services_warn"])
3912 @painter_registry.register
3913 class PainterSgNumServicesCrit(Painter):
3914 @property
3915 def ident(self):
3916 return "sg_num_services_crit"
3918 @property
3919 def title(self):
3920 return _("Number of services in state CRIT (Service Group)")
3922 @property
3923 def short_title(self):
3924 return _("C")
3926 @property
3927 def columns(self):
3928 return ['servicegroup_num_services_crit']
3930 def render(self, row, cell):
3931 return paint_svc_count(2, row["servicegroup_num_services_crit"])
3934 @painter_registry.register
3935 class PainterSgNumServicesUnknown(Painter):
3936 @property
3937 def ident(self):
3938 return "sg_num_services_unknown"
3940 @property
3941 def title(self):
3942 return _("Number of services in state UNKNOWN (Service Group)")
3944 @property
3945 def short_title(self):
3946 return _("U")
3948 @property
3949 def columns(self):
3950 return ['servicegroup_num_services_unknown']
3952 def render(self, row, cell):
3953 return paint_svc_count(3, row["servicegroup_num_services_unknown"])
3956 @painter_registry.register
3957 class PainterSgNumServicesPending(Painter):
3958 @property
3959 def ident(self):
3960 return "sg_num_services_pending"
3962 @property
3963 def title(self):
3964 return _("Number of services in state PENDING (Service Group)")
3966 @property
3967 def short_title(self):
3968 return _("P")
3970 @property
3971 def columns(self):
3972 return ['servicegroup_num_services_pending']
3974 def render(self, row, cell):
3975 return paint_svc_count("p", row["servicegroup_num_services_pending"])
3978 @painter_registry.register
3979 class PainterSgName(Painter):
3980 @property
3981 def ident(self):
3982 return "sg_name"
3984 @property
3985 def title(self):
3986 return _("Servicegroup name")
3988 @property
3989 def short_title(self):
3990 return _("Name")
3992 @property
3993 def columns(self):
3994 return ['servicegroup_name']
3996 def render(self, row, cell):
3997 return (None, row["servicegroup_name"])
4000 @painter_registry.register
4001 class PainterSgAlias(Painter):
4002 @property
4003 def ident(self):
4004 return "sg_alias"
4006 @property
4007 def title(self):
4008 return _("Servicegroup alias")
4010 @property
4011 def short_title(self):
4012 return _("Alias")
4014 @property
4015 def columns(self):
4016 return ['servicegroup_alias']
4018 def render(self, row, cell):
4019 return (None, html.attrencode(row["servicegroup_alias"]))
4022 # ____ _
4023 # / ___|___ _ __ ___ _ __ ___ ___ _ __ | |_ ___
4024 # | | / _ \| '_ ` _ \| '_ ` _ \ / _ \ '_ \| __/ __|
4025 # | |__| (_) | | | | | | | | | | | __/ | | | |_\__ \
4026 # \____\___/|_| |_| |_|_| |_| |_|\___|_| |_|\__|___/
4030 @painter_registry.register
4031 class PainterCommentId(Painter):
4032 @property
4033 def ident(self):
4034 return "comment_id"
4036 @property
4037 def title(self):
4038 return _("Comment id")
4040 @property
4041 def short_title(self):
4042 return _("ID")
4044 @property
4045 def columns(self):
4046 return ['comment_id']
4048 def render(self, row, cell):
4049 return (None, str(row["comment_id"]))
4052 @painter_registry.register
4053 class PainterCommentAuthor(Painter):
4054 @property
4055 def ident(self):
4056 return "comment_author"
4058 @property
4059 def title(self):
4060 return _("Comment author")
4062 @property
4063 def short_title(self):
4064 return _("Author")
4066 @property
4067 def columns(self):
4068 return ['comment_author']
4070 def render(self, row, cell):
4071 return (None, row["comment_author"])
4074 @painter_registry.register
4075 class PainterCommentComment(Painter):
4076 @property
4077 def ident(self):
4078 return "comment_comment"
4080 @property
4081 def title(self):
4082 return _("Comment text")
4084 @property
4085 def columns(self):
4086 return ['comment_comment']
4088 def render(self, row, cell):
4089 return (None, format_plugin_output(row["comment_comment"], row))
4092 @painter_registry.register
4093 class PainterCommentWhat(Painter):
4094 @property
4095 def ident(self):
4096 return "comment_what"
4098 @property
4099 def title(self):
4100 return _("Comment type (host/service)")
4102 @property
4103 def short_title(self):
4104 return _("Type")
4106 @property
4107 def columns(self):
4108 return ['comment_type']
4110 def render(self, row, cell):
4111 return (None, row["comment_type"] == 1 and _("Host") or _("Service"))
4114 @painter_registry.register
4115 class PainterCommentTime(Painter):
4116 @property
4117 def ident(self):
4118 return "comment_time"
4120 @property
4121 def title(self):
4122 return _("Comment entry time")
4124 @property
4125 def short_title(self):
4126 return _("Time")
4128 @property
4129 def columns(self):
4130 return ['comment_entry_time']
4132 @property
4133 def painter_options(self):
4134 return ['ts_format', 'ts_date']
4136 def render(self, row, cell):
4137 return paint_age(row["comment_entry_time"], True, 3600)
4140 @painter_registry.register
4141 class PainterCommentExpires(Painter):
4142 @property
4143 def ident(self):
4144 return "comment_expires"
4146 @property
4147 def title(self):
4148 return _("Comment expiry time")
4150 @property
4151 def short_title(self):
4152 return _("Expires")
4154 @property
4155 def columns(self):
4156 return ['comment_expire_time']
4158 @property
4159 def painter_options(self):
4160 return ['ts_format', 'ts_date']
4162 def render(self, row, cell):
4163 return paint_age(
4164 row["comment_expire_time"], row["comment_expire_time"] != 0, 3600, what='future')
4167 @painter_registry.register
4168 class PainterCommentEntryType(Painter):
4169 @property
4170 def ident(self):
4171 return "comment_entry_type"
4173 @property
4174 def title(self):
4175 return _("Comment entry type (user/downtime/flapping/ack)")
4177 @property
4178 def short_title(self):
4179 return _("E.Type")
4181 @property
4182 def columns(self):
4183 return ['comment_entry_type', 'host_name', 'service_description']
4185 def render(self, row, cell):
4186 t = row["comment_entry_type"]
4187 linkview = None
4188 if t == 1:
4189 icon = "comment"
4190 help_txt = _("Comment")
4191 elif t == 2:
4192 icon = "downtime"
4193 help_txt = _("Downtime")
4194 if row["service_description"]:
4195 linkview = "downtimes_of_service"
4196 else:
4197 linkview = "downtimes_of_host"
4199 elif t == 3:
4200 icon = "flapping"
4201 help_txt = _("Flapping")
4202 elif t == 4:
4203 icon = "ack"
4204 help_txt = _("Acknowledgement")
4205 else:
4206 return "", ""
4207 code = html.render_icon(icon, help_txt)
4208 if linkview:
4209 code = link_to_view(code, row, linkview)
4210 return "icons", code
4213 # ____ _ _
4214 # | _ \ _____ ___ __ | |_(_)_ __ ___ ___ ___
4215 # | | | |/ _ \ \ /\ / / '_ \| __| | '_ ` _ \ / _ \/ __|
4216 # | |_| | (_) \ V V /| | | | |_| | | | | | | __/\__ \
4217 # |____/ \___/ \_/\_/ |_| |_|\__|_|_| |_| |_|\___||___/
4221 @painter_registry.register
4222 class PainterDowntimeId(Painter):
4223 @property
4224 def ident(self):
4225 return "downtime_id"
4227 @property
4228 def title(self):
4229 return _("Downtime id")
4231 @property
4232 def short_title(self):
4233 return _("ID")
4235 @property
4236 def columns(self):
4237 return ['downtime_id']
4239 def render(self, row, cell):
4240 return (None, "%d" % row["downtime_id"])
4243 @painter_registry.register
4244 class PainterDowntimeAuthor(Painter):
4245 @property
4246 def ident(self):
4247 return "downtime_author"
4249 @property
4250 def title(self):
4251 return _("Downtime author")
4253 @property
4254 def short_title(self):
4255 return _("Author")
4257 @property
4258 def columns(self):
4259 return ['downtime_author']
4261 def render(self, row, cell):
4262 return (None, row["downtime_author"])
4265 @painter_registry.register
4266 class PainterDowntimeComment(Painter):
4267 @property
4268 def ident(self):
4269 return "downtime_comment"
4271 @property
4272 def title(self):
4273 return _("Downtime comment")
4275 @property
4276 def short_title(self):
4277 return _("Comment")
4279 @property
4280 def columns(self):
4281 return ['downtime_comment']
4283 def render(self, row, cell):
4284 return (None, format_plugin_output(row["downtime_comment"], row))
4287 @painter_registry.register
4288 class PainterDowntimeFixed(Painter):
4289 @property
4290 def ident(self):
4291 return "downtime_fixed"
4293 @property
4294 def title(self):
4295 return _("Downtime start mode")
4297 @property
4298 def short_title(self):
4299 return _("Mode")
4301 @property
4302 def columns(self):
4303 return ['downtime_fixed']
4305 def render(self, row, cell):
4306 return (None, row["downtime_fixed"] == 0 and _("flexible") or _("fixed"))
4309 @painter_registry.register
4310 class PainterDowntimeOrigin(Painter):
4311 @property
4312 def ident(self):
4313 return "downtime_origin"
4315 @property
4316 def title(self):
4317 return _("Downtime origin")
4319 @property
4320 def short_title(self):
4321 return _("Origin")
4323 @property
4324 def columns(self):
4325 return ['downtime_origin']
4327 def render(self, row, cell):
4328 return (None, row["downtime_origin"] == 1 and _("configuration") or _("command"))
4331 @painter_registry.register
4332 class PainterDowntimeRecurring(Painter):
4333 @property
4334 def ident(self):
4335 return "downtime_recurring"
4337 @property
4338 def title(self):
4339 return _("Downtime recurring interval")
4341 @property
4342 def short_title(self):
4343 return _("Recurring")
4345 @property
4346 def columns(self):
4347 return ['downtime_recurring']
4349 def render(self, row, cell):
4350 try:
4351 from cmk.gui.cee.plugins.wato.cmc import recurring_downtimes_types
4352 except ImportError:
4353 return "", _("(not supported)")
4355 r = row["downtime_recurring"]
4356 if not r:
4357 return "", _("no")
4358 return "", recurring_downtimes_types().get(r, _("(unknown: %d)") % r)
4361 @painter_registry.register
4362 class PainterDowntimeWhat(Painter):
4363 @property
4364 def ident(self):
4365 return "downtime_what"
4367 @property
4368 def title(self):
4369 return _("Downtime for host/service")
4371 @property
4372 def short_title(self):
4373 return _("for")
4375 @property
4376 def columns(self):
4377 return ['downtime_is_service']
4379 def render(self, row, cell):
4380 return (None, row["downtime_is_service"] and _("Service") or _("Host"))
4383 @painter_registry.register
4384 class PainterDowntimeType(Painter):
4385 @property
4386 def ident(self):
4387 return "downtime_type"
4389 @property
4390 def title(self):
4391 return _("Downtime active or pending")
4393 @property
4394 def short_title(self):
4395 return _("act/pend")
4397 @property
4398 def columns(self):
4399 return ['downtime_type']
4401 def render(self, row, cell):
4402 return (None, row["downtime_type"] == 0 and _("active") or _("pending"))
4405 @painter_registry.register
4406 class PainterDowntimeEntryTime(Painter):
4407 @property
4408 def ident(self):
4409 return "downtime_entry_time"
4411 @property
4412 def title(self):
4413 return _("Downtime entry time")
4415 @property
4416 def short_title(self):
4417 return _("Entry")
4419 @property
4420 def columns(self):
4421 return ['downtime_entry_time']
4423 @property
4424 def painter_options(self):
4425 return ['ts_format', 'ts_date']
4427 def render(self, row, cell):
4428 return paint_age(row["downtime_entry_time"], True, 3600)
4431 @painter_registry.register
4432 class PainterDowntimeStartTime(Painter):
4433 @property
4434 def ident(self):
4435 return "downtime_start_time"
4437 @property
4438 def title(self):
4439 return _("Downtime start time")
4441 @property
4442 def short_title(self):
4443 return _("Start")
4445 @property
4446 def columns(self):
4447 return ['downtime_start_time']
4449 @property
4450 def painter_options(self):
4451 return ['ts_format', 'ts_date']
4453 def render(self, row, cell):
4454 return paint_age(row["downtime_start_time"], True, 3600, what="both")
4457 @painter_registry.register
4458 class PainterDowntimeEndTime(Painter):
4459 @property
4460 def ident(self):
4461 return "downtime_end_time"
4463 @property
4464 def title(self):
4465 return _("Downtime end time")
4467 @property
4468 def short_title(self):
4469 return _("End")
4471 @property
4472 def columns(self):
4473 return ['downtime_end_time']
4475 @property
4476 def painter_options(self):
4477 return ['ts_format', 'ts_date']
4479 def render(self, row, cell):
4480 return paint_age(row["downtime_end_time"], True, 3600, what="both")
4483 @painter_registry.register
4484 class PainterDowntimeDuration(Painter):
4485 @property
4486 def ident(self):
4487 return "downtime_duration"
4489 @property
4490 def title(self):
4491 return _("Downtime duration (if flexible)")
4493 @property
4494 def short_title(self):
4495 return _("Flex. Duration")
4497 @property
4498 def columns(self):
4499 return ['downtime_duration', 'downtime_fixed']
4501 def render(self, row, cell):
4502 if row["downtime_fixed"] == 0:
4503 return "number", "%02d:%02d:00" % divmod(row["downtime_duration"] / 60, 60)
4504 return "", ""
4508 # | | ___ __ _
4509 # | | / _ \ / _` |
4510 # | |__| (_) | (_| |
4511 # |_____\___/ \__, |
4512 # |___/
4515 @painter_registry.register
4516 class PainterLogMessage(Painter):
4517 @property
4518 def ident(self):
4519 return "log_message"
4521 @property
4522 def title(self):
4523 return _("Log: complete message")
4525 @property
4526 def short_title(self):
4527 return _("Message")
4529 @property
4530 def columns(self):
4531 return ['log_message']
4533 def render(self, row, cell):
4534 return ("", html.attrencode(row["log_message"]))
4537 @painter_registry.register
4538 class PainterLogPluginOutput(Painter):
4539 @property
4540 def ident(self):
4541 return "log_plugin_output"
4543 @property
4544 def title(self):
4545 return _("Log: Output")
4547 @property
4548 def short_title(self):
4549 return _("Output")
4551 @property
4552 def columns(self):
4553 return [
4554 'log_plugin_output', 'log_type', 'log_state_type', 'log_comment', 'custom_variables'
4557 def render(self, row, cell):
4558 output = row["log_plugin_output"]
4559 comment = row["log_comment"]
4561 if output:
4562 return "", format_plugin_output(output, row)
4564 elif comment:
4565 return "", html.attrencode(comment)
4567 else:
4568 log_type = row["log_type"]
4569 lst = row["log_state_type"]
4570 if "FLAPPING" in log_type:
4571 if "HOST" in log_type:
4572 what = _("host")
4573 else:
4574 what = _("service")
4575 if lst == "STOPPED":
4576 return "", _("The %s stopped flapping") % what
4577 return "", _("The %s started flapping") % what
4579 elif lst:
4580 return "", (lst + " - " + log_type)
4581 else:
4582 return "", ""
4585 @painter_registry.register
4586 class PainterLogWhat(Painter):
4587 @property
4588 def ident(self):
4589 return "log_what"
4591 @property
4592 def title(self):
4593 return _("Log: host or service")
4595 @property
4596 def short_title(self):
4597 return _("Host/Service")
4599 @property
4600 def columns(self):
4601 return ['log_type']
4603 def render(self, row, cell):
4604 lt = row["log_type"]
4605 if "HOST" in lt:
4606 return "", _("Host")
4607 elif "SERVICE" in lt or "SVC" in lt:
4608 return "", _("Service")
4609 return "", _("Program")
4612 @painter_registry.register
4613 class PainterLogAttempt(Painter):
4614 @property
4615 def ident(self):
4616 return "log_attempt"
4618 @property
4619 def title(self):
4620 return _("Log: number of check attempt")
4622 @property
4623 def short_title(self):
4624 return _("Att.")
4626 @property
4627 def columns(self):
4628 return ['log_attempt']
4630 def render(self, row, cell):
4631 return ("", str(row["log_attempt"]))
4634 @painter_registry.register
4635 class PainterLogStateType(Painter):
4636 @property
4637 def ident(self):
4638 return "log_state_type"
4640 @property
4641 def title(self):
4642 return _("Log: type of state (hard/soft/stopped/started)")
4644 @property
4645 def short_title(self):
4646 return _("Type")
4648 @property
4649 def columns(self):
4650 return ['log_state_type']
4652 def render(self, row, cell):
4653 return ("", row["log_state_type"])
4656 @painter_registry.register
4657 class PainterLogType(Painter):
4658 @property
4659 def ident(self):
4660 return "log_type"
4662 @property
4663 def title(self):
4664 return _("Log: event")
4666 @property
4667 def short_title(self):
4668 return _("Event")
4670 @property
4671 def columns(self):
4672 return ['log_type']
4674 def render(self, row, cell):
4675 return ("nowrap", row["log_type"])
4678 @painter_registry.register
4679 class PainterLogContactName(Painter):
4680 @property
4681 def ident(self):
4682 return "log_contact_name"
4684 @property
4685 def title(self):
4686 return _("Log: contact name")
4688 @property
4689 def short_title(self):
4690 return _("Contact")
4692 @property
4693 def columns(self):
4694 return ['log_contact_name']
4696 def render(self, row, cell):
4697 return ("nowrap", row["log_contact_name"])
4700 @painter_registry.register
4701 class PainterLogCommand(Painter):
4702 @property
4703 def ident(self):
4704 return "log_command"
4706 @property
4707 def title(self):
4708 return _("Log: command/plugin")
4710 @property
4711 def short_title(self):
4712 return _("Command")
4714 @property
4715 def columns(self):
4716 return ['log_command_name']
4718 def render(self, row, cell):
4719 return ("nowrap", row["log_command_name"])
4722 @painter_registry.register
4723 class PainterLogIcon(Painter):
4724 @property
4725 def ident(self):
4726 return "log_icon"
4728 @property
4729 def title(self):
4730 return _("Log: event icon")
4732 @property
4733 def short_title(self):
4734 return u""
4736 @property
4737 def columns(self):
4738 return ['log_type', 'log_state', 'log_state_type', 'log_command_name']
4740 def render(self, row, cell):
4741 img = None
4742 log_type = row["log_type"]
4743 log_state = row["log_state"]
4745 if log_type == "SERVICE ALERT":
4746 img = {0: "ok", 1: "warn", 2: "crit", 3: "unknown"}.get(row["log_state"])
4747 title = _("Service Alert")
4749 elif log_type == "HOST ALERT":
4750 img = {0: "up", 1: "down", 2: "unreach"}.get(row["log_state"])
4751 title = _("Host Alert")
4753 elif log_type.endswith("ALERT HANDLER STARTED"):
4754 img = "alert_handler_started"
4755 title = _("Alert Handler Started")
4757 elif log_type.endswith("ALERT HANDLER STOPPED"):
4758 if log_state == 0:
4759 img = "alert_handler_stopped"
4760 title = _("Alert handler Stopped")
4761 else:
4762 img = "alert_handler_failed"
4763 title = _("Alert handler failed")
4765 elif "DOWNTIME" in log_type:
4766 if row["log_state_type"] in ["END", "STOPPED"]:
4767 img = "downtimestop"
4768 title = _("Downtime stopped")
4769 else:
4770 img = "downtime"
4771 title = _("Downtime")
4773 elif log_type.endswith("NOTIFICATION"):
4774 if row["log_command_name"] == "check-mk-notify":
4775 img = "cmk_notify"
4776 title = _("Core produced a notification")
4777 else:
4778 img = "notify"
4779 title = _("User notification")
4781 elif log_type.endswith("NOTIFICATION RESULT"):
4782 img = "notify_result"
4783 title = _("Final notification result")
4785 elif log_type.endswith("NOTIFICATION PROGRESS"):
4786 img = "notify_progress"
4787 title = _("The notification is being processed")
4789 elif log_type == "EXTERNAL COMMAND":
4790 img = "command"
4791 title = _("External command")
4793 elif "restarting..." in log_type:
4794 img = "restart"
4795 title = _("Core restarted")
4797 elif "Reloading configuration" in log_type:
4798 img = "reload"
4799 title = _("Core configuration reloaded")
4801 elif "starting..." in log_type:
4802 img = "start"
4803 title = _("Core started")
4805 elif "shutdown..." in log_type or "shutting down" in log_type:
4806 img = "stop"
4807 title = _("Core stopped")
4809 elif " FLAPPING " in log_type:
4810 img = "flapping"
4811 title = _("Flapping")
4813 elif "ACKNOWLEDGE ALERT" in log_type:
4814 if row["log_state_type"] == "STARTED":
4815 img = "ack"
4816 title = _("Acknowledged")
4817 else:
4818 img = "ackstop"
4819 title = _("Stopped acknowledgement")
4821 if img:
4822 return "icon", html.render_icon("alert_" + img, title=title)
4823 return "icon", ""
4826 @painter_registry.register
4827 class PainterLogOptions(Painter):
4828 @property
4829 def ident(self):
4830 return "log_options"
4832 @property
4833 def title(self):
4834 return _("Log: informational part of message")
4836 @property
4837 def short_title(self):
4838 return _("Info")
4840 @property
4841 def columns(self):
4842 return ['log_options']
4844 def render(self, row, cell):
4845 return ("", html.attrencode(row["log_options"]))
4848 @painter_registry.register
4849 class PainterLogComment(Painter):
4850 @property
4851 def ident(self):
4852 return "log_comment"
4854 @property
4855 def title(self):
4856 return _("Log: comment")
4858 @property
4859 def short_title(self):
4860 return _("Comment")
4862 @property
4863 def columns(self):
4864 return ['log_options']
4866 def render(self, row, cell):
4867 msg = row['log_options']
4868 if ';' in msg:
4869 parts = msg.split(';')
4870 if len(parts) > 6:
4871 return ("", html.attrencode(parts[-1]))
4872 return ("", "")
4875 @painter_registry.register
4876 class PainterLogTime(Painter):
4877 @property
4878 def ident(self):
4879 return "log_time"
4881 @property
4882 def title(self):
4883 return _("Log: entry time")
4885 @property
4886 def short_title(self):
4887 return _("Time")
4889 @property
4890 def columns(self):
4891 return ['log_time']
4893 @property
4894 def painter_options(self):
4895 return ['ts_format', 'ts_date']
4897 def render(self, row, cell):
4898 return paint_age(row["log_time"], True, 3600 * 24)
4901 @painter_registry.register
4902 class PainterLogLineno(Painter):
4903 @property
4904 def ident(self):
4905 return "log_lineno"
4907 @property
4908 def title(self):
4909 return _("Log: line number in log file")
4911 @property
4912 def short_title(self):
4913 return _("Line")
4915 @property
4916 def columns(self):
4917 return ['log_lineno']
4919 def render(self, row, cell):
4920 return ("number", str(row["log_lineno"]))
4923 @painter_registry.register
4924 class PainterLogDate(Painter):
4925 @property
4926 def ident(self):
4927 return "log_date"
4929 @property
4930 def title(self):
4931 return _("Log: day of entry")
4933 @property
4934 def short_title(self):
4935 return _("Date")
4937 @property
4938 def columns(self):
4939 return ['log_time']
4941 def group_by(self, row):
4942 return paint_day(row["log_time"])[1]
4944 def render(self, row, cell):
4945 return paint_day(row["log_time"])
4948 @painter_registry.register
4949 class PainterLogState(Painter):
4950 @property
4951 def ident(self):
4952 return "log_state"
4954 @property
4955 def title(self):
4956 return _("Log: state of host/service at log time")
4958 @property
4959 def short_title(self):
4960 return _("State")
4962 @property
4963 def columns(self):
4964 return ['log_state', 'log_state_type', 'log_service_description', 'log_type']
4966 def render(self, row, cell):
4967 state = row["log_state"]
4969 # Notification result/progress lines don't hold real states. They hold notification plugin
4970 # exit results (0: ok, 1: temp issue, 2: perm issue). We display them as service states.
4971 if row["log_service_description"] \
4972 or row["log_type"].endswith("NOTIFICATION RESULT") \
4973 or row["log_type"].endswith("NOTIFICATION PROGRESS"):
4974 return paint_service_state_short({
4975 "service_has_been_checked": 1,
4976 "service_state": state
4978 return paint_host_state_short({"host_has_been_checked": 1, "host_state": state})
4981 # Alert statistics
4984 @painter_registry.register
4985 class PainterAlertStatsOk(Painter):
4986 @property
4987 def ident(self):
4988 return "alert_stats_ok"
4990 @property
4991 def title(self):
4992 return _("Alert Statistics: Number of recoveries")
4994 @property
4995 def short_title(self):
4996 return _("OK")
4998 @property
4999 def columns(self):
5000 return ['log_alerts_ok']
5002 def render(self, row, cell):
5003 return ("", str(row["log_alerts_ok"]))
5006 @painter_registry.register
5007 class PainterAlertStatsWarn(Painter):
5008 @property
5009 def ident(self):
5010 return "alert_stats_warn"
5012 @property
5013 def title(self):
5014 return _("Alert Statistics: Number of warnings")
5016 @property
5017 def short_title(self):
5018 return _("WARN")
5020 @property
5021 def columns(self):
5022 return ['log_alerts_warn']
5024 def render(self, row, cell):
5025 return paint_svc_count(1, row["log_alerts_warn"])
5028 @painter_registry.register
5029 class PainterAlertStatsCrit(Painter):
5030 @property
5031 def ident(self):
5032 return "alert_stats_crit"
5034 @property
5035 def title(self):
5036 return _("Alert Statistics: Number of critical alerts")
5038 @property
5039 def short_title(self):
5040 return _("CRIT")
5042 @property
5043 def columns(self):
5044 return ['log_alerts_crit']
5046 def render(self, row, cell):
5047 return paint_svc_count(2, row["log_alerts_crit"])
5050 @painter_registry.register
5051 class PainterAlertStatsUnknown(Painter):
5052 @property
5053 def ident(self):
5054 return "alert_stats_unknown"
5056 @property
5057 def title(self):
5058 return _("Alert Statistics: Number of unknown alerts")
5060 @property
5061 def short_title(self):
5062 return _("UNKN")
5064 @property
5065 def columns(self):
5066 return ['log_alerts_unknown']
5068 def render(self, row, cell):
5069 return paint_svc_count(3, row["log_alerts_unknown"])
5072 @painter_registry.register
5073 class PainterAlertStatsProblem(Painter):
5074 @property
5075 def ident(self):
5076 return "alert_stats_problem"
5078 @property
5079 def title(self):
5080 return _("Alert Statistics: Number of problem alerts")
5082 @property
5083 def short_title(self):
5084 return _("PROB")
5086 @property
5087 def columns(self):
5088 return ['log_alerts_problem']
5090 def render(self, row, cell):
5091 return paint_svc_count('s', row["log_alerts_problem"])
5095 # TAGS
5099 @painter_registry.register
5100 class PainterHostTags(Painter):
5101 @property
5102 def ident(self):
5103 return "host_tags"
5105 @property
5106 def title(self):
5107 return _("Host tags")
5109 @property
5110 def short_title(self):
5111 return _("Tags")
5113 @property
5114 def columns(self):
5115 return ["host_tags"]
5117 @property
5118 def sorter(self):
5119 return "host"
5121 def render(self, row, cell):
5122 return "", render_tag_groups(get_tag_groups(row, "host"), "host", with_links=True)
5125 class ABCPainterTagsWithTitles(Painter):
5126 __metaclass__ = abc.ABCMeta
5128 @abc.abstractproperty
5129 def object_type(self):
5130 raise NotImplementedError()
5132 def render(self, row, cell):
5133 entries = self._get_entries(row)
5134 return "", "<br>".join(["%s: %s" % e for e in sorted(entries)])
5136 def _get_entries(self, row):
5137 entries = []
5138 for tag_group_id, tag_id in get_tag_groups(row, self.object_type).items():
5139 tag_group = config.tags.get_tag_group(tag_group_id)
5140 if tag_group:
5141 entries.append((tag_group.title, dict(tag_group.get_tag_choices()).get(
5142 tag_id, tag_id)))
5143 continue
5145 aux_tag_title = dict(config.tags.aux_tag_list.get_choices()).get(tag_group_id)
5146 if aux_tag_title:
5147 entries.append((aux_tag_title, aux_tag_title))
5148 continue
5150 entries.append((tag_group_id, tag_id))
5151 return entries
5154 @painter_registry.register
5155 class PainterHostTagsWithTitles(ABCPainterTagsWithTitles):
5156 @property
5157 def object_type(self):
5158 return "host"
5160 @property
5161 def ident(self):
5162 return "host_tags_with_titles"
5164 @property
5165 def title(self):
5166 return _("Host tags (with titles)")
5168 @property
5169 def short_title(self):
5170 return _("Tags")
5172 @property
5173 def columns(self):
5174 return ["host_tags"]
5176 @property
5177 def sorter(self):
5178 return "host"
5181 @painter_registry.register
5182 class PainterServiceTags(Painter):
5183 @property
5184 def ident(self):
5185 return "service_tags"
5187 @property
5188 def title(self):
5189 return _("Tags")
5191 @property
5192 def short_title(self):
5193 return _("Tags")
5195 @property
5196 def columns(self):
5197 return ["service_tags"]
5199 @property
5200 def sorter(self):
5201 return "service_tags"
5203 def render(self, row, cell):
5204 return "", render_tag_groups(get_tag_groups(row, "service"), "service", with_links=True)
5207 @painter_registry.register
5208 class PainterServiceTagsWithTitles(ABCPainterTagsWithTitles):
5209 @property
5210 def object_type(self):
5211 return "service"
5213 @property
5214 def ident(self):
5215 return "service_tags_with_titles"
5217 @property
5218 def title(self):
5219 return _("Tags (with titles)")
5221 @property
5222 def short_title(self):
5223 return _("Tags")
5225 @property
5226 def columns(self):
5227 return ["service_tags"]
5229 @property
5230 def sorter(self):
5231 return "service_tags"
5234 @painter_registry.register
5235 class PainterHostLabels(Painter):
5236 @property
5237 def ident(self):
5238 return "host_labels"
5240 @property
5241 def title(self):
5242 return _("Labels")
5244 @property
5245 def short_title(self):
5246 return _("Labels")
5248 @property
5249 def columns(self):
5250 return ["host_labels", "host_sources"]
5252 @property
5253 def sorter(self):
5254 return "host_labels"
5256 def render(self, row, cell):
5257 return "", render_labels(
5258 get_labels(row, "host"),
5259 "host",
5260 with_links=True,
5261 label_sources=get_label_sources(row, "host"))
5264 @painter_registry.register
5265 class PainterServiceLabels(Painter):
5266 @property
5267 def ident(self):
5268 return "service_labels"
5270 @property
5271 def title(self):
5272 return _("Labels")
5274 @property
5275 def short_title(self):
5276 return _("Labels")
5278 @property
5279 def columns(self):
5280 return ["service_labels", "host_sources"]
5282 @property
5283 def sorter(self):
5284 return "service_labels"
5286 def render(self, row, cell):
5287 return "", render_labels(
5288 get_labels(row, "service"),
5289 "service",
5290 with_links=True,
5291 label_sources=get_label_sources(row, "service"))