2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
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.
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 (
49 from cmk
.gui
.plugins
.views
.icons
import (
54 from cmk
.gui
.plugins
.views
import (
57 painter_option_registry
,
67 get_perfdata_nth_value
,
68 get_graph_timerange_from_painter_options
,
71 replace_action_url_macros
,
80 # .--Painter Options-----------------------------------------------------.
82 # | | _ \ __ _(_)_ __ | |_ ___ _ __ |
83 # | | |_) / _` | | '_ \| __/ _ \ '__| |
84 # | | __/ (_| | | | | | || __/ | |
85 # | |_| \__,_|_|_| |_|\__\___|_| |
88 # | / _ \ _ __ | |_(_) ___ _ __ ___ |
89 # | | | | | '_ \| __| |/ _ \| '_ \/ __| |
90 # | | |_| | |_) | |_| | (_) | | | \__ \ |
91 # | \___/| .__/ \__|_|\___/|_| |_|___/ |
93 # +----------------------------------------------------------------------+
94 # | Painter options influence how painters render their data. Painter |
95 # | options are stored together with "refresh" and "columns" as "View |
97 # '----------------------------------------------------------------------'
100 @painter_option_registry.register
101 class PainterOptionPNPTimerange(PainterOption
):
104 return "pnp_timerange"
109 title
=_("Graph time range"),
115 @painter_option_registry.register
116 class PainterOptionTimestampFormat(PainterOption
):
123 return DropdownChoice(
124 title
=_("Time stamp format"),
125 default_value
=config
.default_ts_format
,
127 ("mixed", _("Mixed")),
128 ("abs", _("Absolute")),
129 ("rel", _("Relative")),
131 ("epoch", _("Unix Timestamp (Epoch)")),
136 @painter_option_registry.register
137 class PainterOptionTimestampDate(PainterOption
):
147 @painter_option_registry.register
148 class PainterOptionMatrixOmitUniform(PainterOption
):
151 return "matrix_omit_uniform"
155 return DropdownChoice(
156 title
=_("Find differences..."),
158 (False, _("Always show all rows")),
159 (True, _("Omit rows where all columns are identical")),
164 # .--Helpers-------------------------------------------------------------.
166 # | | | | | ___| |_ __ ___ _ __ ___ |
167 # | | |_| |/ _ \ | '_ \ / _ \ '__/ __| |
168 # | | _ | __/ | |_) | __/ | \__ \ |
169 # | |_| |_|\___|_| .__/ \___|_| |___/ |
171 # '----------------------------------------------------------------------'
174 # This helper function returns the value of the given custom var
175 def paint_custom_var(what
, key
, row
, choices
=None):
183 zip(row
[what
+ "custom_variable_names"], row
[what
+ "custom_variable_values"]))
185 if key
in custom_vars
:
186 custom_val
= custom_vars
[key
]
188 custom_val
= dict(choices
).get(int(custom_val
), custom_val
)
189 return key
, html
.attrencode(custom_val
)
194 def paint_nagios_link(row
):
195 # We need to use the Nagios-URL as configured
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")
201 url
+= "&type=2&service=" + html
.urlencode(svc
)
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
):
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
])
241 for icon
in toplevel_icons
:
243 icon_name
, title
, url_spec
= icon
[1:]
245 url
, target_frame
= transform_action_url(url_spec
)
246 url
= replace_action_url_macros(url
, what
, row
)
249 if url
.startswith('onclick:'):
251 url
= 'javascript:void(0)'
253 output
+= html
.render_icon_button(
254 url
, title
, icon_name
, onclick
=onclick
, target
=target_frame
)
256 output
+= html
.render_icon(icon_name
, title
)
260 return "icons", output
263 # TODO: Refactor to one icon base class
264 @painter_registry.register
265 class PainterServiceIcons(Painter
):
268 return "service_icons"
272 return _("Service icons")
275 def short_title(self
):
280 return iconpainter_columns("service", toplevel
=None)
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
):
301 return _("Host icons")
304 def short_title(self
):
309 return iconpainter_columns("host", toplevel
=None)
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----------------------------------------------------------------.
325 # | / ___|(_) |_ ___ |
326 # | \___ \| | __/ _ \ |
327 # | ___) | | || __/ |
328 # | |____/|_|\__\___| |
330 # +----------------------------------------------------------------------+
331 # | Column painters showing information about a site. |
332 # '----------------------------------------------------------------------'
335 @painter_registry.register
336 class PainterSiteIcon(Painter
):
343 return _("Site icon")
346 def short_title(self
):
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"]
363 @painter_registry.register
364 class PainterSitenamePlain(Painter
):
367 return "sitename_plain"
374 def short_title(self
):
385 def render(self
, row
, cell
):
386 return (None, row
["site"])
389 @painter_registry.register
390 class PainterSitealias(Painter
):
397 return _("Site alias")
403 def render(self
, row
, cell
):
404 return (None, html
.attrencode(config
.site(row
["site"])["alias"]))
408 # .--Services------------------------------------------------------------.
410 # | / ___| ___ _ ____ _(_) ___ ___ ___ |
411 # | \___ \ / _ \ '__\ \ / / |/ __/ _ \/ __| |
412 # | ___) | __/ | \ V /| | (_| __/\__ \ |
413 # | |____/ \___|_| \_/ |_|\___\___||___/ |
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"], "")
426 name
= short_service_state_name(-1, "")
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"], "")
445 state
= str(state
) + " stale"
450 return "state hstate hstate%s" % state
, name
453 @painter_registry.register
454 class PainterServiceNagiosLink(Painter
):
457 return "service_nagios_link"
461 return _("Icon with link to service in Nagios GUI")
464 def short_title(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
):
479 return "service_state"
483 return _("Service state")
486 def short_title(self
):
491 return ['service_has_been_checked', 'service_state']
497 def render(self
, row
, cell
):
498 return paint_service_state_short(row
)
501 @painter_registry.register
502 class PainterSvcPluginOutput(Painter
):
505 return "svc_plugin_output"
509 return _("Output of check plugin")
512 def short_title(self
):
513 return _("Status detail")
517 return ['service_plugin_output', 'service_custom_variables']
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
):
531 return "svc_long_plugin_output"
535 return _("Long output of check plugin (multiline)")
538 def short_title(self
):
539 return _("Status detail")
543 return ['service_long_plugin_output', 'service_custom_variables']
545 def render(self
, row
, cell
):
546 return paint_stalified(
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
):
556 return "svc_perf_data"
560 return _("Service performance data (source code)")
563 def short_title(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
):
582 return _("Service Metrics")
585 def short_title(self
):
590 return ['service_check_command', 'service_perf_data']
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
):
613 return "svc_perf_val%02d" % self
._num
617 return _("Service performance data - value number %2d") % self
._num
620 def short_title(self
):
621 return _("Val. %d") % self
._num
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
):
636 @painter_registry.register
637 class PainterSvcPerfVal02(PainterSvcPerfVal
):
641 @painter_registry.register
642 class PainterSvcPerfVal03(PainterSvcPerfVal
):
646 @painter_registry.register
647 class PainterSvcPerfVal04(PainterSvcPerfVal
):
651 @painter_registry.register
652 class PainterSvcPerfVal05(PainterSvcPerfVal
):
656 @painter_registry.register
657 class PainterSvcPerfVal06(PainterSvcPerfVal
):
661 @painter_registry.register
662 class PainterSvcPerfVal07(PainterSvcPerfVal
):
666 @painter_registry.register
667 class PainterSvcPerfVal08(PainterSvcPerfVal
):
671 @painter_registry.register
672 class PainterSvcPerfVal09(PainterSvcPerfVal
):
676 @painter_registry.register
677 class PainterSvcPerfVal10(PainterSvcPerfVal
):
681 @painter_registry.register
682 class PainterSvcCheckCommand(Painter
):
685 return "svc_check_command"
689 return _("Service check command")
692 def short_title(self
):
693 return _("Check command")
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
):
707 return "svc_check_command_expanded"
711 return _("Service check command expanded")
714 def short_title(self
):
715 return _("Check command expanded")
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
):
729 return "svc_contacts"
733 return _("Service contacts")
736 def short_title(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
):
751 return "svc_contact_groups"
755 return _("Service contact groups")
758 def short_title(self
):
759 return _("Contact groups")
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
):
773 return "service_description"
777 return _("Service description")
780 def short_title(self
):
785 return ['service_description']
791 def render(self
, row
, cell
):
792 return (None, row
["service_description"])
795 @painter_registry.register
796 class PainterServiceDisplayName(Painter
):
799 return "service_display_name"
803 return _("Service alternative display name")
806 def short_title(self
):
807 return _("Display name")
811 return ['service_display_name']
817 def render(self
, row
, cell
):
818 return (None, row
["service_display_name"])
821 @painter_registry.register
822 class PainterSvcStateAge(Painter
):
825 return "svc_state_age"
829 return _("The age of the current service state")
832 def short_title(self
):
837 return ['service_has_been_checked', 'service_last_state_change']
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,
852 def paint_checked(what
, row
):
853 age
= row
[what
+ "_last_check"]
854 if what
== "service":
855 cached_at
= row
["service_cached_at"]
859 css
, td
= paint_age(age
, row
[what
+ "_has_been_checked"] == 1, 0)
865 @painter_registry.register
866 class PainterSvcCheckAge(Painter
):
869 return "svc_check_age"
873 return _("The time since the last check of the service")
876 def short_title(self
):
881 return ['service_has_been_checked', 'service_last_check', 'service_cached_at']
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
):
895 return "svc_check_cache_info"
899 return _("Cached agent data")
902 def short_title(self
):
907 return ['service_last_check', 'service_cached_at', 'service_cache_interval']
910 def painter_options(self
):
911 return ['ts_format', 'ts_date']
913 def render(self
, row
, cell
):
914 if not row
["service_cached_at"]:
916 return "", render_cache_info("service", row
)
919 @painter_registry.register
920 class PainterSvcNextCheck(Painter
):
923 return "svc_next_check"
927 return _("The time of the next scheduled service check")
930 def short_title(self
):
931 return _("Next check")
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
):
945 return "svc_last_time_ok"
949 return _("The last time the service was OK")
952 def short_title(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
):
967 return "svc_next_notification"
971 return _("The time of the next service notification")
974 def short_title(self
):
975 return _("Next notification")
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.
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"),
1006 reasons
.get(row
[what
+ "_notification_postponement_reason"],
1007 row
[what
+ "_notification_postponement_reason"]))
1010 @painter_registry.register
1011 class PainterSvcNotificationPostponementReason(Painter
):
1014 return "svc_notification_postponement_reason"
1018 return _("Notification postponement reason")
1021 def short_title(self
):
1022 return _("Notif. postponed")
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
):
1036 return "svc_last_notification"
1040 return _("The time of the last service notification")
1043 def short_title(self
):
1044 return _("last notification")
1048 return ['service_last_notification']
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
):
1062 return "svc_notification_number"
1066 return _("Service notification number")
1069 def short_title(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
):
1084 return "svc_check_latency"
1088 return _("Service check latency")
1091 def short_title(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
):
1106 return "svc_check_duration"
1110 return _("Service check duration")
1113 def short_title(self
):
1114 return _("Duration")
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
):
1128 return "svc_attempt"
1132 return _("Current check attempt")
1135 def short_title(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
):
1150 return "svc_normal_interval"
1154 return _("Service normal check interval")
1157 def short_title(self
):
1158 return _("Check int.")
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
):
1172 return "svc_retry_interval"
1176 return _("Service retry check interval")
1179 def short_title(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
):
1194 return "svc_check_interval"
1198 return _("Service normal/retry check interval")
1201 def short_title(self
):
1202 return _("Interval")
1206 return ['service_check_interval', 'service_retry_interval']
1208 def render(self
, row
, cell
):
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
):
1220 return "svc_check_type"
1224 return _("Service check type")
1227 def short_title(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
):
1242 return "svc_in_downtime"
1246 return _("Currently in downtime")
1249 def short_title(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
):
1264 return "svc_in_notifper"
1268 return _("In notification period")
1271 def short_title(self
):
1272 return _("in notif. p.")
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
):
1286 return "svc_notifper"
1290 return _("Service notification period")
1293 def short_title(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
):
1308 return "svc_check_period"
1312 return _("Service check period")
1315 def short_title(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
):
1330 return "svc_flapping"
1334 return _("Service is flapping")
1337 def short_title(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
):
1352 return "svc_notifications_enabled"
1356 return _("Service notifications enabled")
1359 def short_title(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
):
1374 return "svc_is_active"
1378 return _("Service is active")
1381 def short_title(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
):
1396 return "svc_group_memberlist"
1400 return _("Service groups the service is member of")
1403 def short_title(self
):
1408 return ['service_groups']
1410 def render(self
, row
, cell
):
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
):
1438 painter_options
= PainterOptions
.get_instance()
1439 pnp_timerange
= painter_options
.get("pnp_timerange")
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()
1447 pnpview
= pnp_timerange
[1]
1449 pnp_theme
= html
.get_theme()
1450 if pnp_theme
== "classic":
1451 pnp_theme
= "multisite"
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
):
1472 return "svc_pnpgraph"
1476 return _("Service Graphs")
1482 'service_description',
1483 'service_perf_data',
1485 'service_check_command',
1489 def printable(self
):
1493 def painter_options(self
):
1494 return ['pnp_timerange']
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
):
1508 return "check_manpage"
1512 return _("Check manual (for Check_MK based checks)")
1515 def short_title(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-"):
1526 checktype
= command
[9:]
1528 page
= man_pages
.load_man_page(checktype
)
1530 return "", _("Man page %s not found.") % checktype
1532 description
= page
["header"]["description"]
1533 return "", description
.replace("<", "<") \
1534 .replace(">", ">") \
1535 .replace("{", "<b>") \
1536 .replace("}", "</b>") \
1537 .replace("<br>", "<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
])
1546 @painter_registry.register
1547 class PainterSvcComments(Painter
):
1550 return "svc_comments"
1554 return _("Service Comments")
1557 def short_title(self
):
1558 return _("Comments")
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
):
1572 return "svc_acknowledged"
1576 return _("Service problem acknowledged")
1579 def short_title(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
1593 for directory
in dirs
:
1594 if os
.path
.isdir(directory
):
1595 entries
= [d
for d
in os
.listdir(directory
) if d
[0] != '.']
1598 for pattern
in entries
:
1599 if pattern
[0] == '.':
1601 if fnmatch(item
, pattern
):
1602 matching
.append(directory
+ "/" + pattern
)
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
)
1614 dirs
= [cmk
.utils
.paths
.default_config_dir
+ "/notes/hosts"]
1617 files
= notes_matching_pattern_entries(dirs
, item
)
1622 def replace_tags(text
):
1623 sitename
= row
["site"]
1624 url_prefix
= config
.site(sitename
)["url_prefix"]
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", ""))
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
):
1646 return "svc_custom_notes"
1650 return _("Custom services notes")
1653 def short_title(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
):
1668 return "svc_staleness"
1672 return _("Service staleness value")
1675 def short_title(self
):
1676 return _("Staleness")
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
):
1688 return "badflag", _('yes')
1689 return "goodflag", _('no')
1692 @painter_registry.register
1693 class PainterSvcIsStale(Painter
):
1696 return "svc_is_stale"
1700 return _("Service is stale")
1703 def short_title(self
):
1708 return ['service_staleness']
1712 return 'svc_staleness'
1714 def render(self
, row
, cell
):
1715 return paint_is_stale(row
)
1718 @painter_registry.register
1719 class PainterSvcServicelevel(Painter
):
1722 return "svc_servicelevel"
1726 return _("Service service level")
1729 def short_title(self
):
1730 return _("Service Level")
1734 return ['service_custom_variable_names', 'service_custom_variable_values']
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:
1748 items
= row
[what
+ "_custom_variables"].items()
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
):
1761 return "svc_custom_vars"
1765 return _("Service custom attributes")
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
1783 return self
._dynamic
_title
1786 def short_title(self
):
1787 return self
._dynamic
_title
1789 def _dynamic_title(self
, params
=None):
1791 # Happens in view editor when adding a painter
1792 return self
._default
_title
1795 return config
.custom_service_attributes
[params
["ident"]]["title"]
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()
1808 def _custom_attribute_choices(self
):
1809 raise NotImplementedError()
1812 def parameters(self
):
1815 ("ident", DropdownChoice(
1816 choices
=self
._custom
_attribute
_choices
,
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
):
1833 return "service_custom_variable"
1837 return ['service_custom_variable_names', 'service_custom_variable_values']
1840 def _default_title(self
):
1841 return _("Service custom attribute")
1844 def _object_type(self
):
1847 def _custom_attribute_choices(self
):
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
):
1858 return "host_custom_variable"
1862 return ['host_custom_variable_names', 'host_custom_variable_values']
1865 def _default_title(self
):
1866 return _("Host custom attribute")
1869 def _object_type(self
):
1872 def _custom_attribute_choices(self
):
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---------------------------------------------------------------.
1882 # | | | | | ___ ___| |_ ___ |
1883 # | | |_| |/ _ \/ __| __/ __| |
1884 # | | _ | (_) \__ \ |_\__ \ |
1885 # | |_| |_|\___/|___/\__|___/ |
1887 # +----------------------------------------------------------------------+
1888 # | Painters for hosts |
1889 # '----------------------------------------------------------------------'
1892 @painter_registry.register
1893 class PainterHostState(Painter
):
1900 return _("Host state")
1903 def short_title(self
):
1908 return ['host_has_been_checked', 'host_state']
1914 def render(self
, row
, cell
):
1915 return paint_host_state_short(row
)
1918 @painter_registry.register
1919 class PainterHostStateOnechar(Painter
):
1922 return "host_state_onechar"
1926 return _("Host state (first character)")
1929 def short_title(self
):
1934 return ['host_has_been_checked', 'host_state']
1940 def render(self
, row
, cell
):
1941 return paint_host_state_short(row
, short
=True)
1944 @painter_registry.register
1945 class PainterHostPluginOutput(Painter
):
1948 return "host_plugin_output"
1952 return _("Output of host check plugin")
1955 def short_title(self
):
1956 return _("Status detail")
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
):
1970 return "host_perf_data"
1974 return _("Host performance data")
1977 def short_title(self
):
1978 return _("Performance data")
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
):
1992 return "host_check_command"
1996 return _("Host check command")
1999 def short_title(self
):
2000 return _("Check command")
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
):
2014 return "host_check_command_expanded"
2018 return _("Host check command expanded")
2021 def short_title(self
):
2022 return _("Check command expanded")
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
):
2036 return "host_state_age"
2040 return _("The age of the current host state")
2043 def short_title(self
):
2048 return ['host_has_been_checked', 'host_last_state_change']
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
):
2062 return "host_check_age"
2066 return _("The time since the last check of the host")
2069 def short_title(self
):
2074 return ['host_has_been_checked', 'host_last_check']
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
):
2088 return "host_next_check"
2092 return _("The time of the next scheduled host check")
2095 def short_title(self
):
2096 return _("Next check")
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
):
2110 return "host_next_notification"
2114 return _("The time of the next host notification")
2117 def short_title(self
):
2118 return _("Next notification")
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
):
2132 return "host_notification_postponement_reason"
2136 return _("Notification postponement reason")
2139 def short_title(self
):
2140 return _("Notif. postponed")
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
):
2154 return "host_last_notification"
2158 return _("The time of the last host notification")
2161 def short_title(self
):
2162 return _("last notification")
2166 return ['host_last_notification']
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
):
2180 return "host_check_latency"
2184 return _("Host check latency")
2187 def short_title(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
):
2202 return "host_check_duration"
2206 return _("Host check duration")
2209 def short_title(self
):
2210 return _("Duration")
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
):
2224 return "host_attempt"
2228 return _("Current host check attempt")
2231 def short_title(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
):
2246 return "host_normal_interval"
2250 return _("Normal check interval")
2253 def short_title(self
):
2254 return _("Check int.")
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
):
2268 return "host_retry_interval"
2272 return _("Retry check interval")
2275 def short_title(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
):
2290 return "host_check_interval"
2294 return _("Normal/retry check interval")
2297 def short_title(self
):
2298 return _("Interval")
2302 return ['host_check_interval', 'host_retry_interval']
2304 def render(self
, row
, cell
):
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
):
2316 return "host_check_type"
2320 return _("Host check type")
2323 def short_title(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
):
2338 return "host_in_notifper"
2342 return _("Host in notif. period")
2345 def short_title(self
):
2346 return _("in notif. p.")
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
):
2360 return "host_notifper"
2364 return _("Host notification period")
2367 def short_title(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
):
2382 return "host_notification_number"
2386 return _("Host notification number")
2389 def short_title(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
):
2404 return "host_flapping"
2408 return _("Host is flapping")
2411 def short_title(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
):
2426 return "host_is_active"
2430 return _("Host is active")
2433 def short_title(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
):
2448 return "host_notifications_enabled"
2452 return _("Host notifications enabled")
2455 def short_title(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
):
2470 return "host_pnpgraph"
2474 return _("Host graph")
2477 def short_title(self
):
2482 return ['host_name', 'host_perf_data', 'host_metrics', 'host_check_command']
2485 def printable(self
):
2489 def painter_options(self
):
2490 return ['pnp_timerange']
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
):
2508 return _("Hostname, red background if down or unreachable (Deprecated)")
2511 def short_title(self
):
2516 return ['site', 'host_name', 'host_state']
2522 def render(self
, row
, cell
):
2523 state
= row
["host_state"]
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
):
2533 return "host_black_nagios"
2537 return _("Hostname, red background if down, link to Nagios services")
2540 def short_title(self
):
2545 return ['site', 'host_name', 'host_state']
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"]
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
):
2565 return "host_nagios_link"
2569 return _("Icon with link to host to Nagios GUI")
2572 def short_title(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
):
2587 return "host_with_state"
2591 return _("Hostname, marked red if down (Deprecated)")
2594 def short_title(self
):
2599 return ['site', 'host_name', 'host_state', 'host_has_been_checked']
2605 def render(self
, row
, cell
):
2606 if row
["host_has_been_checked"]:
2607 state
= row
["host_state"]
2611 return "state hstate hstate%s" % state
, row
["host_name"]
2612 return "nobr", row
["host_name"]
2615 @painter_registry.register
2616 class PainterHost(Painter
):
2623 return _("Hostname")
2626 def short_title(self
):
2631 return ['host_name', 'host_state', 'host_has_been_checked', 'host_scheduled_downtime_depth']
2638 def parameters(self
):
2639 elements
= [("color_choices",
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"]
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 [
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
)
2680 return " ".join(css
), row
["host_name"]
2683 @painter_registry.register
2684 class PainterAlias(Painter
):
2691 return _("Host alias")
2694 def short_title(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
):
2709 return "host_address"
2713 return _("Host address (Primary)")
2716 def short_title(self
):
2717 return _("IP address")
2721 return ['host_address']
2723 def render(self
, row
, cell
):
2724 return ("", row
["host_address"])
2727 @painter_registry.register
2728 class PainterHostIpv4Address(Painter
):
2731 return "host_ipv4_address"
2735 return _("Host address (IPv4)")
2738 def short_title(self
):
2739 return _("IPv4 address")
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
):
2753 return "host_ipv6_address"
2757 return _("Host address (IPv6)")
2760 def short_title(self
):
2761 return _("IPv6 address")
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
):
2775 return "host_addresses"
2779 return _("Host addresses (IPv4/IPv6)")
2782 def short_title(self
):
2783 return _("IP addresses")
2787 return ['host_address', 'host_custom_variable_names', 'host_custom_variable_values']
2789 def render(self
, row
, cell
):
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", "")
2797 primary
= custom_vars
.get("ADDRESS_6", "")
2798 secondary
= custom_vars
.get("ADDRESS_4", "")
2801 secondary
= " (%s)" % secondary
2802 return "", primary
+ secondary
2805 @painter_registry.register
2806 class PainterHostAddressesAdditional(Painter
):
2809 return "host_addresses_additional"
2813 return _("Host addresses (additional)")
2816 def short_title(self
):
2817 return _("Add. addresses")
2821 return ["host_custom_variable_names", "host_custom_variable_values"]
2823 def render(self
, row
, cell
):
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()
2832 addresses
+= ipv4_addresses
.split(" ")
2834 addresses
+= ipv6_addresses
.split(" ")
2836 return "", ", ".join(addresses
)
2839 @painter_registry.register
2840 class PainterHostAddressFamily(Painter
):
2843 return "host_address_family"
2847 return _("Host address family (Primary)")
2850 def short_title(self
):
2851 return _("Address family")
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
):
2865 return "host_address_families"
2869 return _("Host address families")
2872 def short_title(self
):
2873 return _("Address families")
2877 return ['host_custom_variable_names', 'host_custom_variable_values']
2879 def render(self
, row
, cell
):
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
):
2896 return "count svcstate state%s" % id_
, str(count
)
2897 return "count svcstate statex", "0"
2900 def paint_host_count(id_
, count
):
2903 return "count hstate hstate%s" % id_
, str(count
)
2905 return "count hstate hstatep", str(count
)
2907 return "count hstate hstatex", "0"
2910 @painter_registry.register
2911 class PainterNumServices(Painter
):
2914 return "num_services"
2918 return _("Number of services")
2921 def short_title(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
):
2936 return "num_services_ok"
2940 return _("Number of services in state OK")
2943 def short_title(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
):
2958 return "num_problems"
2962 return _("Number of problems")
2965 def short_title(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
):
2982 return "num_services_warn"
2986 return _("Number of services in state WARN")
2989 def short_title(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
):
3004 return "num_services_crit"
3008 return _("Number of services in state CRIT")
3011 def short_title(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
):
3026 return "num_services_unknown"
3030 return _("Number of services in state UNKNOWN")
3033 def short_title(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
):
3048 return "num_services_pending"
3052 return _("Number of services in state PENDING")
3055 def short_title(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()
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
3078 svc
, state
, checked
= entry
3079 host
= row
["host_name"]
3081 link
= "view.py?view_name=service&site=%s&host=%s&service=%s" % (html
.urlencode(
3082 row
["site"]), html
.urlencode(host
), html
.urlencode(svc
))
3084 css
= "state%d" % state
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
):
3097 return "host_services"
3101 return _("Services colored according to state")
3104 def short_title(self
):
3105 return _("Services")
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
):
3119 return "host_parents"
3123 return _("Host's parents")
3126 def short_title(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
):
3141 return "host_childs"
3145 return _("Host's children")
3148 def short_title(self
):
3149 return _("children")
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
):
3163 return "host_group_memberlist"
3167 return _("Host groups the host is member of")
3170 def short_title(self
):
3175 return ['host_groups']
3177 def group_by(self
, row
):
3178 return tuple(row
["host_groups"])
3180 def render(self
, row
, cell
):
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
):
3194 return "host_contacts"
3198 return _("Host contacts")
3201 def short_title(self
):
3202 return _("Contacts")
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
):
3216 return "host_contact_groups"
3220 return _("Host contact groups")
3223 def short_title(self
):
3224 return _("Contact groups")
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
):
3238 return "host_custom_notes"
3242 return _("Custom host notes")
3245 def short_title(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
):
3260 return "host_comments"
3264 return _("Host comments")
3267 def short_title(self
):
3268 return _("Comments")
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
):
3282 return "host_in_downtime"
3286 return _("Host in downtime")
3289 def short_title(self
):
3290 return _("Downtime")
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
):
3304 return "host_acknowledged"
3308 return _("Host problem acknowledged")
3311 def short_title(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
):
3326 return "host_staleness"
3330 return _("Host staleness value")
3333 def short_title(self
):
3334 return _("Staleness")
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
):
3348 return "host_is_stale"
3352 return _("Host is stale")
3355 def short_title(self
):
3360 return ['host_staleness']
3364 return 'svc_staleness'
3366 def render(self
, row
, cell
):
3367 return paint_is_stale(row
)
3370 @painter_registry.register
3371 class PainterHostServicelevel(Painter
):
3374 return "host_servicelevel"
3378 return _("Host service level")
3381 def short_title(self
):
3382 return _("Service Level")
3386 return ['host_custom_variable_names', 'host_custom_variable_values']
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
):
3400 return "host_custom_vars"
3404 return _("Host custom attributes")
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
, [
3426 def paint_discovery_output(field
, row
):
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"]
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)"
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
))
3448 @painter_registry.register
3449 class PainterServiceDiscoveryState(Painter
):
3452 return "service_discovery_state"
3456 return _("Service discovery: State")
3459 def short_title(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
):
3474 return "service_discovery_check"
3478 return _("Service discovery: Check type")
3481 def short_title(self
):
3482 return _("Check type")
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
):
3496 return "service_discovery_service"
3500 return _("Service discovery: Service description")
3503 def short_title(self
):
3504 return _("Service description")
3508 return ['discovery_state', 'discovery_check', 'discovery_service']
3510 def render(self
, row
, cell
):
3511 return paint_discovery_output("discovery_service", row
)
3515 # | | | | ___ ___| |_ __ _ _ __ ___ _ _ _ __ ___
3516 # | |_| |/ _ \/ __| __/ _` | '__/ _ \| | | | '_ \/ __|
3517 # | _ | (_) \__ \ || (_| | | | (_) | |_| | |_) \__ \
3518 # |_| |_|\___/|___/\__\__, |_| \___/ \__,_| .__/|___/
3521 @painter_registry.register
3522 class PainterHostgroupHosts(Painter
):
3525 return "hostgroup_hosts"
3529 return _("Hosts colored according to state (Host Group)")
3532 def short_title(self
):
3537 return ['hostgroup_members_with_state']
3539 def render(self
, row
, cell
):
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
))
3545 css
= "hstate%d" % state
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
):
3556 return "hg_num_services"
3560 return _("Number of services (Host Group)")
3563 def short_title(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
):
3578 return "hg_num_services_ok"
3582 return _("Number of services in state OK (Host Group)")
3585 def short_title(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
):
3600 return "hg_num_services_warn"
3604 return _("Number of services in state WARN (Host Group)")
3607 def short_title(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
):
3622 return "hg_num_services_crit"
3626 return _("Number of services in state CRIT (Host Group)")
3629 def short_title(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
):
3644 return "hg_num_services_unknown"
3648 return _("Number of services in state UNKNOWN (Host Group)")
3651 def short_title(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
):
3666 return "hg_num_services_pending"
3670 return _("Number of services in state PENDING (Host Group)")
3673 def short_title(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
):
3688 return "hg_num_hosts_up"
3692 return _("Number of hosts in state UP (Host Group)")
3695 def short_title(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
):
3710 return "hg_num_hosts_down"
3714 return _("Number of hosts in state DOWN (Host Group)")
3717 def short_title(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
):
3732 return "hg_num_hosts_unreach"
3736 return _("Number of hosts in state UNREACH (Host Group)")
3739 def short_title(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
):
3754 return "hg_num_hosts_pending"
3758 return _("Number of hosts in state PENDING (Host Group)")
3761 def short_title(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
):
3780 return _("Hostgroup name")
3783 def short_title(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
):
3802 return _("Hostgroup alias")
3805 def short_title(self
):
3810 return ['hostgroup_alias']
3812 def render(self
, row
, cell
):
3813 return (None, html
.attrencode(row
["hostgroup_alias"]))
3817 # / ___| ___ _ ____ _(_) ___ ___ __ _ _ __ ___ _ _ _ __ ___
3818 # \___ \ / _ \ '__\ \ / / |/ __/ _ \/ _` | '__/ _ \| | | | '_ \/ __|
3819 # ___) | __/ | \ V /| | (_| __/ (_| | | | (_) | |_| | |_) \__ \
3820 # |____/ \___|_| \_/ |_|\___\___|\__, |_| \___/ \__,_| .__/|___/
3824 @painter_registry.register
3825 class PainterSgServices(Painter
):
3828 return "sg_services"
3832 return _("Services colored according to state (Service Group)")
3835 def short_title(self
):
3836 return _("Services")
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
):
3850 return "sg_num_services"
3854 return _("Number of services (Service Group)")
3857 def short_title(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
):
3872 return "sg_num_services_ok"
3876 return _("Number of services in state OK (Service Group)")
3879 def short_title(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
):
3894 return "sg_num_services_warn"
3898 return _("Number of services in state WARN (Service Group)")
3901 def short_title(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
):
3916 return "sg_num_services_crit"
3920 return _("Number of services in state CRIT (Service Group)")
3923 def short_title(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
):
3938 return "sg_num_services_unknown"
3942 return _("Number of services in state UNKNOWN (Service Group)")
3945 def short_title(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
):
3960 return "sg_num_services_pending"
3964 return _("Number of services in state PENDING (Service Group)")
3967 def short_title(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
):
3986 return _("Servicegroup name")
3989 def short_title(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
):
4008 return _("Servicegroup alias")
4011 def short_title(self
):
4016 return ['servicegroup_alias']
4018 def render(self
, row
, cell
):
4019 return (None, html
.attrencode(row
["servicegroup_alias"]))
4023 # / ___|___ _ __ ___ _ __ ___ ___ _ __ | |_ ___
4024 # | | / _ \| '_ ` _ \| '_ ` _ \ / _ \ '_ \| __/ __|
4025 # | |__| (_) | | | | | | | | | | | __/ | | | |_\__ \
4026 # \____\___/|_| |_| |_|_| |_| |_|\___|_| |_|\__|___/
4030 @painter_registry.register
4031 class PainterCommentId(Painter
):
4038 return _("Comment id")
4041 def short_title(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
):
4056 return "comment_author"
4060 return _("Comment author")
4063 def short_title(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
):
4078 return "comment_comment"
4082 return _("Comment text")
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
):
4096 return "comment_what"
4100 return _("Comment type (host/service)")
4103 def short_title(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
):
4118 return "comment_time"
4122 return _("Comment entry time")
4125 def short_title(self
):
4130 return ['comment_entry_time']
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
):
4144 return "comment_expires"
4148 return _("Comment expiry time")
4151 def short_title(self
):
4156 return ['comment_expire_time']
4159 def painter_options(self
):
4160 return ['ts_format', 'ts_date']
4162 def render(self
, row
, cell
):
4164 row
["comment_expire_time"], row
["comment_expire_time"] != 0, 3600, what
='future')
4167 @painter_registry.register
4168 class PainterCommentEntryType(Painter
):
4171 return "comment_entry_type"
4175 return _("Comment entry type (user/downtime/flapping/ack)")
4178 def short_title(self
):
4183 return ['comment_entry_type', 'host_name', 'service_description']
4185 def render(self
, row
, cell
):
4186 t
= row
["comment_entry_type"]
4190 help_txt
= _("Comment")
4193 help_txt
= _("Downtime")
4194 if row
["service_description"]:
4195 linkview
= "downtimes_of_service"
4197 linkview
= "downtimes_of_host"
4201 help_txt
= _("Flapping")
4204 help_txt
= _("Acknowledgement")
4207 code
= html
.render_icon(icon
, help_txt
)
4209 code
= link_to_view(code
, row
, linkview
)
4210 return "icons", code
4214 # | _ \ _____ ___ __ | |_(_)_ __ ___ ___ ___
4215 # | | | |/ _ \ \ /\ / / '_ \| __| | '_ ` _ \ / _ \/ __|
4216 # | |_| | (_) \ V V /| | | | |_| | | | | | | __/\__ \
4217 # |____/ \___/ \_/\_/ |_| |_|\__|_|_| |_| |_|\___||___/
4221 @painter_registry.register
4222 class PainterDowntimeId(Painter
):
4225 return "downtime_id"
4229 return _("Downtime id")
4232 def short_title(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
):
4247 return "downtime_author"
4251 return _("Downtime author")
4254 def short_title(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
):
4269 return "downtime_comment"
4273 return _("Downtime comment")
4276 def short_title(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
):
4291 return "downtime_fixed"
4295 return _("Downtime start mode")
4298 def short_title(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
):
4313 return "downtime_origin"
4317 return _("Downtime origin")
4320 def short_title(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
):
4335 return "downtime_recurring"
4339 return _("Downtime recurring interval")
4342 def short_title(self
):
4343 return _("Recurring")
4347 return ['downtime_recurring']
4349 def render(self
, row
, cell
):
4351 from cmk
.gui
.cee
.plugins
.wato
.cmc
import recurring_downtimes_types
4353 return "", _("(not supported)")
4355 r
= row
["downtime_recurring"]
4358 return "", recurring_downtimes_types().get(r
, _("(unknown: %d)") % r
)
4361 @painter_registry.register
4362 class PainterDowntimeWhat(Painter
):
4365 return "downtime_what"
4369 return _("Downtime for host/service")
4372 def short_title(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
):
4387 return "downtime_type"
4391 return _("Downtime active or pending")
4394 def short_title(self
):
4395 return _("act/pend")
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
):
4409 return "downtime_entry_time"
4413 return _("Downtime entry time")
4416 def short_title(self
):
4421 return ['downtime_entry_time']
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
):
4435 return "downtime_start_time"
4439 return _("Downtime start time")
4442 def short_title(self
):
4447 return ['downtime_start_time']
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
):
4461 return "downtime_end_time"
4465 return _("Downtime end time")
4468 def short_title(self
):
4473 return ['downtime_end_time']
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
):
4487 return "downtime_duration"
4491 return _("Downtime duration (if flexible)")
4494 def short_title(self
):
4495 return _("Flex. Duration")
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)
4510 # | |__| (_) | (_| |
4511 # |_____\___/ \__, |
4515 @painter_registry.register
4516 class PainterLogMessage(Painter
):
4519 return "log_message"
4523 return _("Log: complete message")
4526 def short_title(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
):
4541 return "log_plugin_output"
4545 return _("Log: Output")
4548 def short_title(self
):
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"]
4562 return "", format_plugin_output(output
, row
)
4565 return "", html
.attrencode(comment
)
4568 log_type
= row
["log_type"]
4569 lst
= row
["log_state_type"]
4570 if "FLAPPING" in log_type
:
4571 if "HOST" in log_type
:
4575 if lst
== "STOPPED":
4576 return "", _("The %s stopped flapping") % what
4577 return "", _("The %s started flapping") % what
4580 return "", (lst
+ " - " + log_type
)
4585 @painter_registry.register
4586 class PainterLogWhat(Painter
):
4593 return _("Log: host or service")
4596 def short_title(self
):
4597 return _("Host/Service")
4603 def render(self
, row
, cell
):
4604 lt
= row
["log_type"]
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
):
4616 return "log_attempt"
4620 return _("Log: number of check attempt")
4623 def short_title(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
):
4638 return "log_state_type"
4642 return _("Log: type of state (hard/soft/stopped/started)")
4645 def short_title(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
):
4664 return _("Log: event")
4667 def short_title(self
):
4674 def render(self
, row
, cell
):
4675 return ("nowrap", row
["log_type"])
4678 @painter_registry.register
4679 class PainterLogContactName(Painter
):
4682 return "log_contact_name"
4686 return _("Log: contact name")
4689 def short_title(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
):
4704 return "log_command"
4708 return _("Log: command/plugin")
4711 def short_title(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
):
4730 return _("Log: event icon")
4733 def short_title(self
):
4738 return ['log_type', 'log_state', 'log_state_type', 'log_command_name']
4740 def render(self
, row
, cell
):
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"):
4759 img
= "alert_handler_stopped"
4760 title
= _("Alert handler Stopped")
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")
4771 title
= _("Downtime")
4773 elif log_type
.endswith("NOTIFICATION"):
4774 if row
["log_command_name"] == "check-mk-notify":
4776 title
= _("Core produced a notification")
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":
4791 title
= _("External command")
4793 elif "restarting..." in log_type
:
4795 title
= _("Core restarted")
4797 elif "Reloading configuration" in log_type
:
4799 title
= _("Core configuration reloaded")
4801 elif "starting..." in log_type
:
4803 title
= _("Core started")
4805 elif "shutdown..." in log_type
or "shutting down" in log_type
:
4807 title
= _("Core stopped")
4809 elif " FLAPPING " in log_type
:
4811 title
= _("Flapping")
4813 elif "ACKNOWLEDGE ALERT" in log_type
:
4814 if row
["log_state_type"] == "STARTED":
4816 title
= _("Acknowledged")
4819 title
= _("Stopped acknowledgement")
4822 return "icon", html
.render_icon("alert_" + img
, title
=title
)
4826 @painter_registry.register
4827 class PainterLogOptions(Painter
):
4830 return "log_options"
4834 return _("Log: informational part of message")
4837 def short_title(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
):
4852 return "log_comment"
4856 return _("Log: comment")
4859 def short_title(self
):
4864 return ['log_options']
4866 def render(self
, row
, cell
):
4867 msg
= row
['log_options']
4869 parts
= msg
.split(';')
4871 return ("", html
.attrencode(parts
[-1]))
4875 @painter_registry.register
4876 class PainterLogTime(Painter
):
4883 return _("Log: entry time")
4886 def short_title(self
):
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
):
4909 return _("Log: line number in log file")
4912 def short_title(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
):
4931 return _("Log: day of entry")
4934 def short_title(self
):
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
):
4956 return _("Log: state of host/service at log time")
4959 def short_title(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
})
4984 @painter_registry.register
4985 class PainterAlertStatsOk(Painter
):
4988 return "alert_stats_ok"
4992 return _("Alert Statistics: Number of recoveries")
4995 def short_title(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
):
5010 return "alert_stats_warn"
5014 return _("Alert Statistics: Number of warnings")
5017 def short_title(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
):
5032 return "alert_stats_crit"
5036 return _("Alert Statistics: Number of critical alerts")
5039 def short_title(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
):
5054 return "alert_stats_unknown"
5058 return _("Alert Statistics: Number of unknown alerts")
5061 def short_title(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
):
5076 return "alert_stats_problem"
5080 return _("Alert Statistics: Number of problem alerts")
5083 def short_title(self
):
5088 return ['log_alerts_problem']
5090 def render(self
, row
, cell
):
5091 return paint_svc_count('s', row
["log_alerts_problem"])
5099 @painter_registry.register
5100 class PainterHostTags(Painter
):
5107 return _("Host tags")
5110 def short_title(self
):
5115 return ["host_tags"]
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
):
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
)
5141 entries
.append((tag_group
.title
, dict(tag_group
.get_tag_choices()).get(
5145 aux_tag_title
= dict(config
.tags
.aux_tag_list
.get_choices()).get(tag_group_id
)
5147 entries
.append((aux_tag_title
, aux_tag_title
))
5150 entries
.append((tag_group_id
, tag_id
))
5154 @painter_registry.register
5155 class PainterHostTagsWithTitles(ABCPainterTagsWithTitles
):
5157 def object_type(self
):
5162 return "host_tags_with_titles"
5166 return _("Host tags (with titles)")
5169 def short_title(self
):
5174 return ["host_tags"]
5181 @painter_registry.register
5182 class PainterServiceTags(Painter
):
5185 return "service_tags"
5192 def short_title(self
):
5197 return ["service_tags"]
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
):
5210 def object_type(self
):
5215 return "service_tags_with_titles"
5219 return _("Tags (with titles)")
5222 def short_title(self
):
5227 return ["service_tags"]
5231 return "service_tags"
5234 @painter_registry.register
5235 class PainterHostLabels(Painter
):
5238 return "host_labels"
5245 def short_title(self
):
5250 return ["host_labels", "host_sources"]
5254 return "host_labels"
5256 def render(self
, row
, cell
):
5257 return "", render_labels(
5258 get_labels(row
, "host"),
5261 label_sources
=get_label_sources(row
, "host"))
5264 @painter_registry.register
5265 class PainterServiceLabels(Painter
):
5268 return "service_labels"
5275 def short_title(self
):
5280 return ["service_labels", "host_sources"]
5284 return "service_labels"
5286 def render(self
, row
, cell
):
5287 return "", render_labels(
5288 get_labels(row
, "service"),
5291 label_sources
=get_label_sources(row
, "service"))