]> granicus.if.org Git - icinga2/blob - lib/livestatus/servicestable.cpp
Merge pull request #7204 from episodeiv/master
[icinga2] / lib / livestatus / servicestable.cpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #include "livestatus/servicestable.hpp"
4 #include "livestatus/hoststable.hpp"
5 #include "livestatus/servicegroupstable.hpp"
6 #include "livestatus/hostgroupstable.hpp"
7 #include "livestatus/endpointstable.hpp"
8 #include "icinga/service.hpp"
9 #include "icinga/servicegroup.hpp"
10 #include "icinga/hostgroup.hpp"
11 #include "icinga/checkcommand.hpp"
12 #include "icinga/eventcommand.hpp"
13 #include "icinga/timeperiod.hpp"
14 #include "icinga/macroprocessor.hpp"
15 #include "icinga/icingaapplication.hpp"
16 #include "icinga/compatutility.hpp"
17 #include "icinga/pluginutility.hpp"
18 #include "base/configtype.hpp"
19 #include "base/objectlock.hpp"
20 #include "base/json.hpp"
21 #include "base/convert.hpp"
22 #include "base/utility.hpp"
23 #include <boost/algorithm/string/replace.hpp>
24
25 using namespace icinga;
26
27 ServicesTable::ServicesTable(LivestatusGroupByType type)
28         : Table(type)
29 {
30         AddColumns(this);
31 }
32
33
34 void ServicesTable::AddColumns(Table *table, const String& prefix,
35         const Column::ObjectAccessor& objectAccessor)
36 {
37         table->AddColumn(prefix + "description", Column(&ServicesTable::ShortNameAccessor, objectAccessor));
38         table->AddColumn(prefix + "service_description", Column(&ServicesTable::ShortNameAccessor, objectAccessor)); //ugly compatibility hack
39         table->AddColumn(prefix + "display_name", Column(&ServicesTable::DisplayNameAccessor, objectAccessor));
40         table->AddColumn(prefix + "check_command", Column(&ServicesTable::CheckCommandAccessor, objectAccessor));
41         table->AddColumn(prefix + "check_command_expanded", Column(&ServicesTable::CheckCommandExpandedAccessor, objectAccessor));
42         table->AddColumn(prefix + "event_handler", Column(&ServicesTable::EventHandlerAccessor, objectAccessor));
43         table->AddColumn(prefix + "plugin_output", Column(&ServicesTable::PluginOutputAccessor, objectAccessor));
44         table->AddColumn(prefix + "long_plugin_output", Column(&ServicesTable::LongPluginOutputAccessor, objectAccessor));
45         table->AddColumn(prefix + "perf_data", Column(&ServicesTable::PerfDataAccessor, objectAccessor));
46         table->AddColumn(prefix + "notification_period", Column(&Table::EmptyStringAccessor, objectAccessor));
47         table->AddColumn(prefix + "check_period", Column(&ServicesTable::CheckPeriodAccessor, objectAccessor));
48         table->AddColumn(prefix + "notes", Column(&ServicesTable::NotesAccessor, objectAccessor));
49         table->AddColumn(prefix + "notes_expanded", Column(&ServicesTable::NotesExpandedAccessor, objectAccessor));
50         table->AddColumn(prefix + "notes_url", Column(&ServicesTable::NotesUrlAccessor, objectAccessor));
51         table->AddColumn(prefix + "notes_url_expanded", Column(&ServicesTable::NotesUrlExpandedAccessor, objectAccessor));
52         table->AddColumn(prefix + "action_url", Column(&ServicesTable::ActionUrlAccessor, objectAccessor));
53         table->AddColumn(prefix + "action_url_expanded", Column(&ServicesTable::ActionUrlExpandedAccessor, objectAccessor));
54         table->AddColumn(prefix + "icon_image", Column(&ServicesTable::IconImageAccessor, objectAccessor));
55         table->AddColumn(prefix + "icon_image_expanded", Column(&ServicesTable::IconImageExpandedAccessor, objectAccessor));
56         table->AddColumn(prefix + "icon_image_alt", Column(&ServicesTable::IconImageAltAccessor, objectAccessor));
57         table->AddColumn(prefix + "initial_state", Column(&Table::EmptyStringAccessor, objectAccessor));
58         table->AddColumn(prefix + "max_check_attempts", Column(&ServicesTable::MaxCheckAttemptsAccessor, objectAccessor));
59         table->AddColumn(prefix + "current_attempt", Column(&ServicesTable::CurrentAttemptAccessor, objectAccessor));
60         table->AddColumn(prefix + "state", Column(&ServicesTable::StateAccessor, objectAccessor));
61         table->AddColumn(prefix + "has_been_checked", Column(&ServicesTable::HasBeenCheckedAccessor, objectAccessor));
62         table->AddColumn(prefix + "last_state", Column(&ServicesTable::LastStateAccessor, objectAccessor));
63         table->AddColumn(prefix + "last_hard_state", Column(&ServicesTable::LastHardStateAccessor, objectAccessor));
64         table->AddColumn(prefix + "state_type", Column(&ServicesTable::StateTypeAccessor, objectAccessor));
65         table->AddColumn(prefix + "check_type", Column(&ServicesTable::CheckTypeAccessor, objectAccessor));
66         table->AddColumn(prefix + "acknowledged", Column(&ServicesTable::AcknowledgedAccessor, objectAccessor));
67         table->AddColumn(prefix + "acknowledgement_type", Column(&ServicesTable::AcknowledgementTypeAccessor, objectAccessor));
68         table->AddColumn(prefix + "no_more_notifications", Column(&ServicesTable::NoMoreNotificationsAccessor, objectAccessor));
69         table->AddColumn(prefix + "last_time_ok", Column(&ServicesTable::LastTimeOkAccessor, objectAccessor));
70         table->AddColumn(prefix + "last_time_warning", Column(&ServicesTable::LastTimeWarningAccessor, objectAccessor));
71         table->AddColumn(prefix + "last_time_critical", Column(&ServicesTable::LastTimeCriticalAccessor, objectAccessor));
72         table->AddColumn(prefix + "last_time_unknown", Column(&ServicesTable::LastTimeUnknownAccessor, objectAccessor));
73         table->AddColumn(prefix + "last_check", Column(&ServicesTable::LastCheckAccessor, objectAccessor));
74         table->AddColumn(prefix + "next_check", Column(&ServicesTable::NextCheckAccessor, objectAccessor));
75         table->AddColumn(prefix + "last_notification", Column(&ServicesTable::LastNotificationAccessor, objectAccessor));
76         table->AddColumn(prefix + "next_notification", Column(&ServicesTable::NextNotificationAccessor, objectAccessor));
77         table->AddColumn(prefix + "current_notification_number", Column(&ServicesTable::CurrentNotificationNumberAccessor, objectAccessor));
78         table->AddColumn(prefix + "last_state_change", Column(&ServicesTable::LastStateChangeAccessor, objectAccessor));
79         table->AddColumn(prefix + "last_hard_state_change", Column(&ServicesTable::LastHardStateChangeAccessor, objectAccessor));
80         table->AddColumn(prefix + "scheduled_downtime_depth", Column(&ServicesTable::ScheduledDowntimeDepthAccessor, objectAccessor));
81         table->AddColumn(prefix + "is_flapping", Column(&ServicesTable::IsFlappingAccessor, objectAccessor));
82         table->AddColumn(prefix + "checks_enabled", Column(&ServicesTable::ChecksEnabledAccessor, objectAccessor));
83         table->AddColumn(prefix + "accept_passive_checks", Column(&ServicesTable::AcceptPassiveChecksAccessor, objectAccessor));
84         table->AddColumn(prefix + "event_handler_enabled", Column(&ServicesTable::EventHandlerEnabledAccessor, objectAccessor));
85         table->AddColumn(prefix + "notifications_enabled", Column(&ServicesTable::NotificationsEnabledAccessor, objectAccessor));
86         table->AddColumn(prefix + "process_performance_data", Column(&ServicesTable::ProcessPerformanceDataAccessor, objectAccessor));
87         table->AddColumn(prefix + "is_executing", Column(&Table::ZeroAccessor, objectAccessor));
88         table->AddColumn(prefix + "active_checks_enabled", Column(&ServicesTable::ActiveChecksEnabledAccessor, objectAccessor));
89         table->AddColumn(prefix + "check_options", Column(&Table::EmptyStringAccessor, objectAccessor));
90         table->AddColumn(prefix + "flap_detection_enabled", Column(&ServicesTable::FlapDetectionEnabledAccessor, objectAccessor));
91         table->AddColumn(prefix + "check_freshness", Column(&Table::OneAccessor, objectAccessor));
92         table->AddColumn(prefix + "obsess_over_service", Column(&Table::ZeroAccessor, objectAccessor));
93         table->AddColumn(prefix + "modified_attributes", Column(&Table::ZeroAccessor, objectAccessor));
94         table->AddColumn(prefix + "modified_attributes_list", Column(&Table::ZeroAccessor, objectAccessor));
95         table->AddColumn(prefix + "pnpgraph_present", Column(&Table::ZeroAccessor, objectAccessor));
96         table->AddColumn(prefix + "staleness", Column(&ServicesTable::StalenessAccessor, objectAccessor));
97         table->AddColumn(prefix + "check_interval", Column(&ServicesTable::CheckIntervalAccessor, objectAccessor));
98         table->AddColumn(prefix + "retry_interval", Column(&ServicesTable::RetryIntervalAccessor, objectAccessor));
99         table->AddColumn(prefix + "notification_interval", Column(&ServicesTable::NotificationIntervalAccessor, objectAccessor));
100         table->AddColumn(prefix + "first_notification_delay", Column(&Table::EmptyStringAccessor, objectAccessor));
101         table->AddColumn(prefix + "low_flap_threshold", Column(&ServicesTable::LowFlapThresholdAccessor, objectAccessor));
102         table->AddColumn(prefix + "high_flap_threshold", Column(&ServicesTable::HighFlapThresholdAccessor, objectAccessor));
103         table->AddColumn(prefix + "latency", Column(&ServicesTable::LatencyAccessor, objectAccessor));
104         table->AddColumn(prefix + "execution_time", Column(&ServicesTable::ExecutionTimeAccessor, objectAccessor));
105         table->AddColumn(prefix + "percent_state_change", Column(&ServicesTable::PercentStateChangeAccessor, objectAccessor));
106         table->AddColumn(prefix + "in_check_period", Column(&ServicesTable::InCheckPeriodAccessor, objectAccessor));
107         table->AddColumn(prefix + "in_notification_period", Column(&ServicesTable::InNotificationPeriodAccessor, objectAccessor));
108         table->AddColumn(prefix + "contacts", Column(&ServicesTable::ContactsAccessor, objectAccessor));
109         table->AddColumn(prefix + "downtimes", Column(&ServicesTable::DowntimesAccessor, objectAccessor));
110         table->AddColumn(prefix + "downtimes_with_info", Column(&ServicesTable::DowntimesWithInfoAccessor, objectAccessor));
111         table->AddColumn(prefix + "comments", Column(&ServicesTable::CommentsAccessor, objectAccessor));
112         table->AddColumn(prefix + "comments_with_info", Column(&ServicesTable::CommentsWithInfoAccessor, objectAccessor));
113         table->AddColumn(prefix + "comments_with_extra_info", Column(&ServicesTable::CommentsWithExtraInfoAccessor, objectAccessor));
114         table->AddColumn(prefix + "custom_variable_names", Column(&ServicesTable::CustomVariableNamesAccessor, objectAccessor));
115         table->AddColumn(prefix + "custom_variable_values", Column(&ServicesTable::CustomVariableValuesAccessor, objectAccessor));
116         table->AddColumn(prefix + "custom_variables", Column(&ServicesTable::CustomVariablesAccessor, objectAccessor));
117         table->AddColumn(prefix + "groups", Column(&ServicesTable::GroupsAccessor, objectAccessor));
118         table->AddColumn(prefix + "contact_groups", Column(&ServicesTable::ContactGroupsAccessor, objectAccessor));
119         table->AddColumn(prefix + "check_source", Column(&ServicesTable::CheckSourceAccessor, objectAccessor));
120         table->AddColumn(prefix + "is_reachable", Column(&ServicesTable::IsReachableAccessor, objectAccessor));
121         table->AddColumn(prefix + "cv_is_json", Column(&ServicesTable::CVIsJsonAccessor, objectAccessor));
122         table->AddColumn(prefix + "original_attributes", Column(&ServicesTable::OriginalAttributesAccessor, objectAccessor));
123
124         HostsTable::AddColumns(table, "host_", std::bind(&ServicesTable::HostAccessor, _1, objectAccessor));
125
126         /* add additional group by values received through the object accessor */
127         if (table->GetGroupByType() == LivestatusGroupByServiceGroup) {
128                 /* _1 = row, _2 = groupByType, _3 = groupByObject */
129                 Log(LogDebug, "Livestatus")
130                         << "Processing services group by servicegroup table.";
131                 ServiceGroupsTable::AddColumns(table, "servicegroup_", std::bind(&ServicesTable::ServiceGroupAccessor, _1, _2, _3));
132         } else if (table->GetGroupByType() == LivestatusGroupByHostGroup) {
133                 /* _1 = row, _2 = groupByType, _3 = groupByObject */
134                 Log(LogDebug, "Livestatus")
135                         << "Processing services group by hostgroup table.";
136                 HostGroupsTable::AddColumns(table, "hostgroup_", std::bind(&ServicesTable::HostGroupAccessor, _1, _2, _3));
137         }
138 }
139
140 String ServicesTable::GetName() const
141 {
142         return "services";
143 }
144
145 String ServicesTable::GetPrefix() const
146 {
147         return "service";
148 }
149
150 void ServicesTable::FetchRows(const AddRowFunction& addRowFn)
151 {
152         if (GetGroupByType() == LivestatusGroupByServiceGroup) {
153                 for (const ServiceGroup::Ptr& sg : ConfigType::GetObjectsByType<ServiceGroup>()) {
154                         for (const Service::Ptr& service : sg->GetMembers()) {
155                                 /* the caller must know which groupby type and value are set for this row */
156                                 if (!addRowFn(service, LivestatusGroupByServiceGroup, sg))
157                                         return;
158                         }
159                 }
160         } else if (GetGroupByType() == LivestatusGroupByHostGroup) {
161                 for (const HostGroup::Ptr& hg : ConfigType::GetObjectsByType<HostGroup>()) {
162                         ObjectLock ylock(hg);
163                         for (const Host::Ptr& host : hg->GetMembers()) {
164                                 ObjectLock ylock(host);
165                                 for (const Service::Ptr& service : host->GetServices()) {
166                                         /* the caller must know which groupby type and value are set for this row */
167                                         if (!addRowFn(service, LivestatusGroupByHostGroup, hg))
168                                                 return;
169                                 }
170                         }
171                 }
172         } else {
173                 for (const Service::Ptr& service : ConfigType::GetObjectsByType<Service>()) {
174                         if (!addRowFn(service, LivestatusGroupByNone, Empty))
175                                 return;
176                 }
177         }
178 }
179
180 Object::Ptr ServicesTable::HostAccessor(const Value& row, const Column::ObjectAccessor& parentObjectAccessor)
181 {
182         Value service;
183
184         if (parentObjectAccessor)
185                 service = parentObjectAccessor(row, LivestatusGroupByNone, Empty);
186         else
187                 service = row;
188
189         Service::Ptr svc = static_cast<Service::Ptr>(service);
190
191         if (!svc)
192                 return nullptr;
193
194         return svc->GetHost();
195 }
196
197 Object::Ptr ServicesTable::ServiceGroupAccessor(const Value& row, LivestatusGroupByType groupByType, const Object::Ptr& groupByObject)
198 {
199         /* return the current group by value set from within FetchRows()
200          * this is the servicegroup object used for the table join inside
201          * in AddColumns()
202          */
203         if (groupByType == LivestatusGroupByServiceGroup)
204                 return groupByObject;
205
206         return nullptr;
207 }
208
209 Object::Ptr ServicesTable::HostGroupAccessor(const Value& row, LivestatusGroupByType groupByType, const Object::Ptr& groupByObject)
210 {
211         /* return the current group by value set from within FetchRows()
212          * this is the servicegroup object used for the table join inside
213          * in AddColumns()
214          */
215         if (groupByType == LivestatusGroupByHostGroup)
216                 return groupByObject;
217
218         return nullptr;
219 }
220
221 Value ServicesTable::ShortNameAccessor(const Value& row)
222 {
223         Service::Ptr service = static_cast<Service::Ptr>(row);
224
225         if (!service)
226                 return Empty;
227
228         return service->GetShortName();
229 }
230
231 Value ServicesTable::DisplayNameAccessor(const Value& row)
232 {
233         Service::Ptr service = static_cast<Service::Ptr>(row);
234
235         if (!service)
236                 return Empty;
237
238         return service->GetDisplayName();
239 }
240
241 Value ServicesTable::CheckCommandAccessor(const Value& row)
242 {
243         Service::Ptr service = static_cast<Service::Ptr>(row);
244
245         if (!service)
246                 return Empty;
247
248         CheckCommand::Ptr checkcommand = service->GetCheckCommand();
249
250         if (checkcommand)
251                 return CompatUtility::GetCommandName(checkcommand) + "!" + CompatUtility::GetCheckableCommandArgs(service);
252
253         return Empty;
254 }
255
256 Value ServicesTable::CheckCommandExpandedAccessor(const Value& row)
257 {
258         Service::Ptr service = static_cast<Service::Ptr>(row);
259
260         if (!service)
261                 return Empty;
262
263         CheckCommand::Ptr checkcommand = service->GetCheckCommand();
264
265         if (checkcommand)
266                 return CompatUtility::GetCommandName(checkcommand) + "!" + CompatUtility::GetCheckableCommandArgs(service);
267
268         return Empty;
269 }
270
271 Value ServicesTable::EventHandlerAccessor(const Value& row)
272 {
273         Service::Ptr service = static_cast<Service::Ptr>(row);
274
275         if (!service)
276                 return Empty;
277
278         EventCommand::Ptr eventcommand = service->GetEventCommand();
279
280         if (eventcommand)
281                 return CompatUtility::GetCommandName(eventcommand);
282
283         return Empty;
284 }
285
286 Value ServicesTable::PluginOutputAccessor(const Value& row)
287 {
288         Service::Ptr service = static_cast<Service::Ptr>(row);
289
290         if (!service)
291                 return Empty;
292
293         String output;
294         CheckResult::Ptr cr = service->GetLastCheckResult();
295
296         if (cr)
297                 output = CompatUtility::GetCheckResultOutput(cr);
298
299         return output;
300 }
301
302 Value ServicesTable::LongPluginOutputAccessor(const Value& row)
303 {
304         Service::Ptr service = static_cast<Service::Ptr>(row);
305
306         if (!service)
307                 return Empty;
308
309         String long_output;
310         CheckResult::Ptr cr = service->GetLastCheckResult();
311
312         if (cr)
313                 long_output = CompatUtility::GetCheckResultLongOutput(cr);
314
315         return long_output;
316 }
317
318 Value ServicesTable::PerfDataAccessor(const Value& row)
319 {
320         Service::Ptr service = static_cast<Service::Ptr>(row);
321
322         if (!service)
323                 return Empty;
324
325         String perfdata;
326         CheckResult::Ptr cr = service->GetLastCheckResult();
327
328         if (!cr)
329                 return Empty;
330
331         return PluginUtility::FormatPerfdata(cr->GetPerformanceData());
332 }
333
334 Value ServicesTable::CheckPeriodAccessor(const Value& row)
335 {
336         Service::Ptr service = static_cast<Service::Ptr>(row);
337
338         if (!service)
339                 return Empty;
340
341         TimePeriod::Ptr checkPeriod = service->GetCheckPeriod();
342
343         if (!checkPeriod)
344                 return Empty;
345
346         return checkPeriod->GetName();
347 }
348
349 Value ServicesTable::NotesAccessor(const Value& row)
350 {
351         Service::Ptr service = static_cast<Service::Ptr>(row);
352
353         if (!service)
354                 return Empty;
355
356         return service->GetNotes();
357 }
358
359 Value ServicesTable::NotesExpandedAccessor(const Value& row)
360 {
361         Service::Ptr service = static_cast<Service::Ptr>(row);
362
363         if (!service)
364                 return Empty;
365
366         MacroProcessor::ResolverList resolvers {
367                 { "service", service },
368                 { "host", service->GetHost() },
369                 { "icinga", IcingaApplication::GetInstance() }
370         };
371
372         return MacroProcessor::ResolveMacros(service->GetNotes(), resolvers);
373 }
374
375 Value ServicesTable::NotesUrlAccessor(const Value& row)
376 {
377         Service::Ptr service = static_cast<Service::Ptr>(row);
378
379         if (!service)
380                 return Empty;
381
382         return service->GetNotesUrl();
383 }
384
385 Value ServicesTable::NotesUrlExpandedAccessor(const Value& row)
386 {
387         Service::Ptr service = static_cast<Service::Ptr>(row);
388
389         if (!service)
390                 return Empty;
391
392         MacroProcessor::ResolverList resolvers {
393                 { "service", service },
394                 { "host", service->GetHost() },
395                 { "icinga", IcingaApplication::GetInstance() }
396         };
397
398         return MacroProcessor::ResolveMacros(service->GetNotesUrl(), resolvers);
399 }
400
401 Value ServicesTable::ActionUrlAccessor(const Value& row)
402 {
403         Service::Ptr service = static_cast<Service::Ptr>(row);
404
405         if (!service)
406                 return Empty;
407
408         return service->GetActionUrl();
409 }
410
411 Value ServicesTable::ActionUrlExpandedAccessor(const Value& row)
412 {
413         Service::Ptr service = static_cast<Service::Ptr>(row);
414
415         if (!service)
416                 return Empty;
417
418         MacroProcessor::ResolverList resolvers {
419                 { "service", service },
420                 { "host", service->GetHost() },
421                 { "icinga", IcingaApplication::GetInstance() }
422         };
423
424         return MacroProcessor::ResolveMacros(service->GetActionUrl(), resolvers);
425 }
426
427 Value ServicesTable::IconImageAccessor(const Value& row)
428 {
429         Service::Ptr service = static_cast<Service::Ptr>(row);
430
431         if (!service)
432                 return Empty;
433
434         return service->GetIconImage();
435 }
436
437 Value ServicesTable::IconImageExpandedAccessor(const Value& row)
438 {
439         Service::Ptr service = static_cast<Service::Ptr>(row);
440
441         if (!service)
442                 return Empty;
443
444         MacroProcessor::ResolverList resolvers {
445                 { "service", service },
446                 { "host", service->GetHost() },
447                 { "icinga", IcingaApplication::GetInstance() }
448         };
449
450         return MacroProcessor::ResolveMacros(service->GetIconImage(), resolvers);
451 }
452
453 Value ServicesTable::IconImageAltAccessor(const Value& row)
454 {
455         Service::Ptr service = static_cast<Service::Ptr>(row);
456
457         if (!service)
458                 return Empty;
459
460         return service->GetIconImageAlt();
461 }
462
463 Value ServicesTable::MaxCheckAttemptsAccessor(const Value& row)
464 {
465         Service::Ptr service = static_cast<Service::Ptr>(row);
466
467         if (!service)
468                 return Empty;
469
470         return service->GetMaxCheckAttempts();
471 }
472
473 Value ServicesTable::CurrentAttemptAccessor(const Value& row)
474 {
475         Service::Ptr service = static_cast<Service::Ptr>(row);
476
477         if (!service)
478                 return Empty;
479
480         return service->GetCheckAttempt();
481 }
482
483 Value ServicesTable::StateAccessor(const Value& row)
484 {
485         Service::Ptr service = static_cast<Service::Ptr>(row);
486
487         if (!service)
488                 return Empty;
489
490         return service->GetState();
491 }
492
493 Value ServicesTable::HasBeenCheckedAccessor(const Value& row)
494 {
495         Service::Ptr service = static_cast<Service::Ptr>(row);
496
497         if (!service)
498                 return Empty;
499
500         return Convert::ToLong(service->HasBeenChecked());
501 }
502
503 Value ServicesTable::LastStateAccessor(const Value& row)
504 {
505         Service::Ptr service = static_cast<Service::Ptr>(row);
506
507         if (!service)
508                 return Empty;
509
510         return service->GetLastState();
511 }
512
513 Value ServicesTable::LastHardStateAccessor(const Value& row)
514 {
515         Service::Ptr service = static_cast<Service::Ptr>(row);
516
517         if (!service)
518                 return Empty;
519
520         return service->GetLastHardState();
521 }
522
523 Value ServicesTable::StateTypeAccessor(const Value& row)
524 {
525         Service::Ptr service = static_cast<Service::Ptr>(row);
526
527         if (!service)
528                 return Empty;
529
530         return service->GetStateType();
531 }
532
533 Value ServicesTable::CheckTypeAccessor(const Value& row)
534 {
535         Service::Ptr service = static_cast<Service::Ptr>(row);
536
537         if (!service)
538                 return Empty;
539
540         return (service->GetEnableActiveChecks() ? 0 : 1); /* 0 .. active, 1 .. passive */
541 }
542
543 Value ServicesTable::AcknowledgedAccessor(const Value& row)
544 {
545         Service::Ptr service = static_cast<Service::Ptr>(row);
546
547         if (!service)
548                 return Empty;
549
550         ObjectLock olock(service);
551         return service->IsAcknowledged();
552 }
553
554 Value ServicesTable::AcknowledgementTypeAccessor(const Value& row)
555 {
556         Service::Ptr service = static_cast<Service::Ptr>(row);
557
558         if (!service)
559                 return Empty;
560
561         ObjectLock olock(service);
562         return service->GetAcknowledgement();
563 }
564
565 Value ServicesTable::NoMoreNotificationsAccessor(const Value& row)
566 {
567         Service::Ptr service = static_cast<Service::Ptr>(row);
568
569         if (!service)
570                 return Empty;
571
572         return (CompatUtility::GetCheckableNotificationNotificationInterval(service) == 0 && !service->GetVolatile()) ? 1 : 0;
573 }
574
575 Value ServicesTable::LastTimeOkAccessor(const Value& row)
576 {
577         Service::Ptr service = static_cast<Service::Ptr>(row);
578
579         if (!service)
580                 return Empty;
581
582         return static_cast<int>(service->GetLastStateOK());
583 }
584
585 Value ServicesTable::LastTimeWarningAccessor(const Value& row)
586 {
587         Service::Ptr service = static_cast<Service::Ptr>(row);
588
589         if (!service)
590                 return Empty;
591
592         return static_cast<int>(service->GetLastStateWarning());
593 }
594
595 Value ServicesTable::LastTimeCriticalAccessor(const Value& row)
596 {
597         Service::Ptr service = static_cast<Service::Ptr>(row);
598
599         if (!service)
600                 return Empty;
601
602         return static_cast<int>(service->GetLastStateCritical());
603 }
604
605 Value ServicesTable::LastTimeUnknownAccessor(const Value& row)
606 {
607         Service::Ptr service = static_cast<Service::Ptr>(row);
608
609         if (!service)
610                 return Empty;
611
612         return static_cast<int>(service->GetLastStateUnknown());
613 }
614
615 Value ServicesTable::LastCheckAccessor(const Value& row)
616 {
617         Service::Ptr service = static_cast<Service::Ptr>(row);
618
619         if (!service)
620                 return Empty;
621
622         return static_cast<int>(service->GetLastCheck());
623 }
624
625 Value ServicesTable::NextCheckAccessor(const Value& row)
626 {
627         Service::Ptr service = static_cast<Service::Ptr>(row);
628
629         if (!service)
630                 return Empty;
631
632         return static_cast<int>(service->GetNextCheck());
633 }
634
635 Value ServicesTable::LastNotificationAccessor(const Value& row)
636 {
637         Service::Ptr service = static_cast<Service::Ptr>(row);
638
639         if (!service)
640                 return Empty;
641
642         return CompatUtility::GetCheckableNotificationLastNotification(service);
643 }
644
645 Value ServicesTable::NextNotificationAccessor(const Value& row)
646 {
647         Service::Ptr service = static_cast<Service::Ptr>(row);
648
649         if (!service)
650                 return Empty;
651
652         return CompatUtility::GetCheckableNotificationNextNotification(service);
653 }
654
655 Value ServicesTable::CurrentNotificationNumberAccessor(const Value& row)
656 {
657         Service::Ptr service = static_cast<Service::Ptr>(row);
658
659         if (!service)
660                 return Empty;
661
662         return CompatUtility::GetCheckableNotificationNotificationNumber(service);
663 }
664
665 Value ServicesTable::LastStateChangeAccessor(const Value& row)
666 {
667         Service::Ptr service = static_cast<Service::Ptr>(row);
668
669         if (!service)
670                 return Empty;
671
672         return static_cast<int>(service->GetLastStateChange());
673 }
674
675 Value ServicesTable::LastHardStateChangeAccessor(const Value& row)
676 {
677         Service::Ptr service = static_cast<Service::Ptr>(row);
678
679         if (!service)
680                 return Empty;
681
682         return static_cast<int>(service->GetLastHardStateChange());
683 }
684
685 Value ServicesTable::ScheduledDowntimeDepthAccessor(const Value& row)
686 {
687         Service::Ptr service = static_cast<Service::Ptr>(row);
688
689         if (!service)
690                 return Empty;
691
692         return service->GetDowntimeDepth();
693 }
694
695 Value ServicesTable::IsFlappingAccessor(const Value& row)
696 {
697         Service::Ptr service = static_cast<Service::Ptr>(row);
698
699         if (!service)
700                 return Empty;
701
702         return service->IsFlapping();
703 }
704
705 Value ServicesTable::ChecksEnabledAccessor(const Value& row)
706 {
707         Service::Ptr service = static_cast<Service::Ptr>(row);
708
709         if (!service)
710                 return Empty;
711
712         return Convert::ToLong(service->GetEnableActiveChecks());
713 }
714
715 Value ServicesTable::AcceptPassiveChecksAccessor(const Value& row)
716 {
717         Service::Ptr service = static_cast<Service::Ptr>(row);
718
719         if (!service)
720                 return Empty;
721
722         return Convert::ToLong(service->GetEnablePassiveChecks());
723 }
724
725 Value ServicesTable::EventHandlerEnabledAccessor(const Value& row)
726 {
727         Service::Ptr service = static_cast<Service::Ptr>(row);
728
729         if (!service)
730                 return Empty;
731
732         return Convert::ToLong(service->GetEnableEventHandler());
733 }
734
735 Value ServicesTable::NotificationsEnabledAccessor(const Value& row)
736 {
737         Service::Ptr service = static_cast<Service::Ptr>(row);
738
739         if (!service)
740                 return Empty;
741
742         return Convert::ToLong(service->GetEnableNotifications());
743 }
744
745 Value ServicesTable::ProcessPerformanceDataAccessor(const Value& row)
746 {
747         Service::Ptr service = static_cast<Service::Ptr>(row);
748
749         if (!service)
750                 return Empty;
751
752         return Convert::ToLong(service->GetEnablePerfdata());
753 }
754
755 Value ServicesTable::ActiveChecksEnabledAccessor(const Value& row)
756 {
757         Service::Ptr service = static_cast<Service::Ptr>(row);
758
759         if (!service)
760                 return Empty;
761
762         return Convert::ToLong(service->GetEnableActiveChecks());
763 }
764
765 Value ServicesTable::FlapDetectionEnabledAccessor(const Value& row)
766 {
767         Service::Ptr service = static_cast<Service::Ptr>(row);
768
769         if (!service)
770                 return Empty;
771
772         return Convert::ToLong(service->GetEnableFlapping());
773 }
774
775 Value ServicesTable::StalenessAccessor(const Value& row)
776 {
777         Service::Ptr service = static_cast<Service::Ptr>(row);
778
779         if (!service)
780                 return Empty;
781
782         if (service->HasBeenChecked() && service->GetLastCheck() > 0)
783                 return (Utility::GetTime() - service->GetLastCheck()) / (service->GetCheckInterval() * 3600);
784
785         return 0.0;
786 }
787
788 Value ServicesTable::CheckIntervalAccessor(const Value& row)
789 {
790         Service::Ptr service = static_cast<Service::Ptr>(row);
791
792         if (!service)
793                 return Empty;
794
795         return service->GetCheckInterval() / 60.0;
796 }
797
798 Value ServicesTable::RetryIntervalAccessor(const Value& row)
799 {
800         Service::Ptr service = static_cast<Service::Ptr>(row);
801
802         if (!service)
803                 return Empty;
804
805         return service->GetRetryInterval() / 60.0;
806 }
807
808 Value ServicesTable::NotificationIntervalAccessor(const Value& row)
809 {
810         Service::Ptr service = static_cast<Service::Ptr>(row);
811
812         if (!service)
813                 return Empty;
814
815         return CompatUtility::GetCheckableNotificationNotificationInterval(service);
816 }
817
818 Value ServicesTable::LowFlapThresholdAccessor(const Value& row)
819 {
820         Service::Ptr service = static_cast<Service::Ptr>(row);
821
822         if (!service)
823                 return Empty;
824
825         return service->GetFlappingThresholdLow();
826 }
827
828 Value ServicesTable::HighFlapThresholdAccessor(const Value& row)
829 {
830         Service::Ptr service = static_cast<Service::Ptr>(row);
831
832         if (!service)
833                 return Empty;
834
835         return service->GetFlappingThresholdHigh();
836 }
837
838 Value ServicesTable::LatencyAccessor(const Value& row)
839 {
840         Service::Ptr service = static_cast<Service::Ptr>(row);
841
842         if (!service)
843                 return Empty;
844
845         CheckResult::Ptr cr = service->GetLastCheckResult();
846
847         if (!cr)
848                 return Empty;
849
850         return cr->CalculateLatency();
851 }
852
853 Value ServicesTable::ExecutionTimeAccessor(const Value& row)
854 {
855         Service::Ptr service = static_cast<Service::Ptr>(row);
856
857         if (!service)
858                 return Empty;
859
860         CheckResult::Ptr cr = service->GetLastCheckResult();
861
862         if (!cr)
863                 return Empty;
864
865         return cr->CalculateExecutionTime();
866 }
867
868 Value ServicesTable::PercentStateChangeAccessor(const Value& row)
869 {
870         Service::Ptr service = static_cast<Service::Ptr>(row);
871
872         if (!service)
873                 return Empty;
874
875         return service->GetFlappingCurrent();
876 }
877
878 Value ServicesTable::InCheckPeriodAccessor(const Value& row)
879 {
880         Service::Ptr service = static_cast<Service::Ptr>(row);
881
882         if (!service)
883                 return Empty;
884
885         TimePeriod::Ptr timeperiod = service->GetCheckPeriod();
886
887         /* none set means always checked */
888         if (!timeperiod)
889                 return 1;
890
891         return Convert::ToLong(timeperiod->IsInside(Utility::GetTime()));
892 }
893
894 Value ServicesTable::InNotificationPeriodAccessor(const Value& row)
895 {
896         Service::Ptr service = static_cast<Service::Ptr>(row);
897
898         if (!service)
899                 return Empty;
900
901         for (const Notification::Ptr& notification : service->GetNotifications()) {
902                 TimePeriod::Ptr timeperiod = notification->GetPeriod();
903
904                 if (!timeperiod || timeperiod->IsInside(Utility::GetTime()))
905                         return 1;
906         }
907
908         return 0;
909 }
910
911 Value ServicesTable::ContactsAccessor(const Value& row)
912 {
913         Service::Ptr service = static_cast<Service::Ptr>(row);
914
915         if (!service)
916                 return Empty;
917
918         ArrayData result;
919
920         for (const User::Ptr& user : CompatUtility::GetCheckableNotificationUsers(service)) {
921                 result.push_back(user->GetName());
922         }
923
924         return new Array(std::move(result));
925 }
926
927 Value ServicesTable::DowntimesAccessor(const Value& row)
928 {
929         Service::Ptr service = static_cast<Service::Ptr>(row);
930
931         if (!service)
932                 return Empty;
933
934         ArrayData result;
935
936         for (const Downtime::Ptr& downtime : service->GetDowntimes()) {
937                 if (downtime->IsExpired())
938                         continue;
939
940                 result.push_back(downtime->GetLegacyId());
941         }
942
943         return new Array(std::move(result));
944 }
945
946 Value ServicesTable::DowntimesWithInfoAccessor(const Value& row)
947 {
948         Service::Ptr service = static_cast<Service::Ptr>(row);
949
950         if (!service)
951                 return Empty;
952
953         ArrayData result;
954
955         for (const Downtime::Ptr& downtime : service->GetDowntimes()) {
956                 if (downtime->IsExpired())
957                         continue;
958
959                 result.push_back(new Array({
960                         downtime->GetLegacyId(),
961                         downtime->GetAuthor(),
962                         downtime->GetComment()
963                 }));
964         }
965
966         return new Array(std::move(result));
967 }
968
969 Value ServicesTable::CommentsAccessor(const Value& row)
970 {
971         Service::Ptr service = static_cast<Service::Ptr>(row);
972
973         if (!service)
974                 return Empty;
975
976         ArrayData result;
977
978         for (const Comment::Ptr& comment : service->GetComments()) {
979                 if (comment->IsExpired())
980                         continue;
981
982                 result.push_back(comment->GetLegacyId());
983         }
984
985         return new Array(std::move(result));
986 }
987
988 Value ServicesTable::CommentsWithInfoAccessor(const Value& row)
989 {
990         Service::Ptr service = static_cast<Service::Ptr>(row);
991
992         if (!service)
993                 return Empty;
994
995         ArrayData result;
996
997         for (const Comment::Ptr& comment : service->GetComments()) {
998                 if (comment->IsExpired())
999                         continue;
1000
1001                 result.push_back(new Array({
1002                         comment->GetLegacyId(),
1003                         comment->GetAuthor(),
1004                         comment->GetText()
1005                 }));
1006         }
1007
1008         return new Array(std::move(result));
1009 }
1010
1011 Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row)
1012 {
1013         Service::Ptr service = static_cast<Service::Ptr>(row);
1014
1015         if (!service)
1016                 return Empty;
1017
1018         ArrayData result;
1019
1020         for (const Comment::Ptr& comment : service->GetComments()) {
1021                 if (comment->IsExpired())
1022                         continue;
1023
1024                 result.push_back(new Array({
1025                         comment->GetLegacyId(),
1026                         comment->GetAuthor(),
1027                         comment->GetText(),
1028                         comment->GetEntryType(),
1029                         static_cast<int>(comment->GetEntryTime())
1030                 }));
1031         }
1032
1033         return new Array(std::move(result));
1034 }
1035
1036 Value ServicesTable::CustomVariableNamesAccessor(const Value& row)
1037 {
1038         Service::Ptr service = static_cast<Service::Ptr>(row);
1039
1040         if (!service)
1041                 return Empty;
1042
1043         Dictionary::Ptr vars = service->GetVars();
1044
1045         ArrayData result;
1046
1047         if (vars) {
1048                 ObjectLock olock(vars);
1049                 for (const Dictionary::Pair& kv : vars) {
1050                         result.push_back(kv.first);
1051                 }
1052         }
1053
1054         return new Array(std::move(result));
1055 }
1056
1057 Value ServicesTable::CustomVariableValuesAccessor(const Value& row)
1058 {
1059         Service::Ptr service = static_cast<Service::Ptr>(row);
1060
1061         if (!service)
1062                 return Empty;
1063
1064         Dictionary::Ptr vars = service->GetVars();
1065
1066         ArrayData result;
1067
1068         if (vars) {
1069                 ObjectLock olock(vars);
1070                 for (const Dictionary::Pair& kv : vars) {
1071                         if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
1072                                 result.push_back(JsonEncode(kv.second));
1073                         else
1074                                 result.push_back(kv.second);
1075                 }
1076         }
1077
1078         return new Array(std::move(result));
1079 }
1080
1081 Value ServicesTable::CustomVariablesAccessor(const Value& row)
1082 {
1083         Service::Ptr service = static_cast<Service::Ptr>(row);
1084
1085         if (!service)
1086                 return Empty;
1087
1088         Dictionary::Ptr vars = service->GetVars();
1089
1090         ArrayData result;
1091
1092         if (vars) {
1093                 ObjectLock olock(vars);
1094                 for (const Dictionary::Pair& kv : vars) {
1095                         Value val;
1096
1097                         if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
1098                                 val = JsonEncode(kv.second);
1099                         else
1100                                 val = kv.second;
1101
1102                         result.push_back(new Array({
1103                                 kv.first,
1104                                 val
1105                         }));
1106                 }
1107         }
1108
1109         return new Array(std::move(result));
1110 }
1111
1112 Value ServicesTable::CVIsJsonAccessor(const Value& row)
1113 {
1114         Service::Ptr service = static_cast<Service::Ptr>(row);
1115
1116         if (!service)
1117                 return Empty;
1118
1119         Dictionary::Ptr vars = service->GetVars();
1120
1121         if (!vars)
1122                 return Empty;
1123
1124         bool cv_is_json = false;
1125
1126         ObjectLock olock(vars);
1127         for (const Dictionary::Pair& kv : vars) {
1128                 if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
1129                         cv_is_json = true;
1130         }
1131
1132         return cv_is_json;
1133 }
1134
1135 Value ServicesTable::GroupsAccessor(const Value& row)
1136 {
1137         Service::Ptr service = static_cast<Service::Ptr>(row);
1138
1139         if (!service)
1140                 return Empty;
1141
1142         Array::Ptr groups = service->GetGroups();
1143
1144         if (!groups)
1145                 return Empty;
1146
1147         return groups;
1148 }
1149
1150 Value ServicesTable::ContactGroupsAccessor(const Value& row)
1151 {
1152         Service::Ptr service = static_cast<Service::Ptr>(row);
1153
1154         if (!service)
1155                 return Empty;
1156
1157         ArrayData result;
1158
1159         for (const UserGroup::Ptr& usergroup : CompatUtility::GetCheckableNotificationUserGroups(service)) {
1160                 result.push_back(usergroup->GetName());
1161         }
1162
1163         return new Array(std::move(result));
1164 }
1165
1166 Value ServicesTable::CheckSourceAccessor(const Value& row)
1167 {
1168         Service::Ptr service = static_cast<Service::Ptr>(row);
1169
1170         if (!service)
1171                 return Empty;
1172
1173         CheckResult::Ptr cr = service->GetLastCheckResult();
1174
1175         if (cr)
1176                 return cr->GetCheckSource();
1177
1178         return Empty;
1179 }
1180
1181 Value ServicesTable::IsReachableAccessor(const Value& row)
1182 {
1183         Service::Ptr service = static_cast<Service::Ptr>(row);
1184
1185         if (!service)
1186                 return Empty;
1187
1188         return service->IsReachable();
1189 }
1190
1191 Value ServicesTable::OriginalAttributesAccessor(const Value& row)
1192 {
1193         Service::Ptr service = static_cast<Service::Ptr>(row);
1194
1195         if (!service)
1196                 return Empty;
1197
1198         return JsonEncode(service->GetOriginalAttributes());
1199 }