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