]> granicus.if.org Git - icinga2/blob - components/livestatus/servicestable.cpp
livestatus: add host/service staleness indicator
[icinga2] / components / livestatus / servicestable.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
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.h"
21 #include "livestatus/hoststable.h"
22 #include "icinga/service.h"
23 #include "icinga/checkcommand.h"
24 #include "icinga/eventcommand.h"
25 #include "icinga/timeperiod.h"
26 #include "icinga/macroprocessor.h"
27 #include "icinga/icingaapplication.h"
28 #include "base/dynamictype.h"
29 #include "base/objectlock.h"
30 #include "base/convert.h"
31 #include <boost/foreach.hpp>
32 #include <boost/tuple/tuple.hpp>
33
34 using namespace icinga;
35 using namespace livestatus;
36
37 ServicesTable::ServicesTable(void)
38 {
39         AddColumns(this);
40 }
41
42 void ServicesTable::AddColumns(Table *table, const String& prefix,
43     const Column::ObjectAccessor& objectAccessor)
44 {
45         table->AddColumn(prefix + "description", Column(&ServicesTable::ShortNameAccessor, objectAccessor));
46         table->AddColumn(prefix + "display_name", Column(&ServicesTable::DisplayNameAccessor, objectAccessor));
47         table->AddColumn(prefix + "check_command", Column(&ServicesTable::CheckCommandAccessor, objectAccessor));
48         table->AddColumn(prefix + "check_command_expanded", Column(&ServicesTable::CheckCommandExpandedAccessor, objectAccessor));
49         table->AddColumn(prefix + "event_handler", Column(&ServicesTable::EventHandlerAccessor, objectAccessor));
50         table->AddColumn(prefix + "plugin_output", Column(&ServicesTable::PluginOutputAccessor, objectAccessor));
51         table->AddColumn(prefix + "long_plugin_output", Column(&ServicesTable::LongPluginOutputAccessor, objectAccessor));
52         table->AddColumn(prefix + "perf_data", Column(&ServicesTable::PerfDataAccessor, objectAccessor));
53         table->AddColumn(prefix + "notification_period", Column(&ServicesTable::NotificationPeriodAccessor, objectAccessor));
54         table->AddColumn(prefix + "check_period", Column(&ServicesTable::CheckPeriodAccessor, objectAccessor));
55         table->AddColumn(prefix + "notes", Column(&ServicesTable::NotesAccessor, objectAccessor));
56         table->AddColumn(prefix + "notes_expanded", Column(&ServicesTable::NotesExpandedAccessor, objectAccessor));
57         table->AddColumn(prefix + "notes_url", Column(&ServicesTable::NotesUrlAccessor, objectAccessor));
58         table->AddColumn(prefix + "notes_url_expanded", Column(&ServicesTable::NotesUrlExpandedAccessor, objectAccessor));
59         table->AddColumn(prefix + "action_url", Column(&ServicesTable::ActionUrlAccessor, objectAccessor));
60         table->AddColumn(prefix + "action_url_expanded", Column(&ServicesTable::ActionUrlExpandedAccessor, objectAccessor));
61         table->AddColumn(prefix + "icon_image", Column(&ServicesTable::IconImageAccessor, objectAccessor));
62         table->AddColumn(prefix + "icon_image_expanded", Column(&ServicesTable::IconImageExpandedAccessor, objectAccessor));
63         table->AddColumn(prefix + "icon_image_alt", Column(&ServicesTable::IconImageAltAccessor, objectAccessor));
64         table->AddColumn(prefix + "initial_state", Column(&ServicesTable::InitialStateAccessor, objectAccessor));
65         table->AddColumn(prefix + "max_check_attempts", Column(&ServicesTable::MaxCheckAttemptsAccessor, objectAccessor));
66         table->AddColumn(prefix + "current_attempt", Column(&ServicesTable::CurrentAttemptAccessor, objectAccessor));
67         table->AddColumn(prefix + "state", Column(&ServicesTable::StateAccessor, objectAccessor));
68         table->AddColumn(prefix + "has_been_checked", Column(&ServicesTable::HasBeenCheckedAccessor, objectAccessor));
69         table->AddColumn(prefix + "last_state", Column(&ServicesTable::LastStateAccessor, objectAccessor));
70         table->AddColumn(prefix + "last_hard_state", Column(&ServicesTable::LastHardStateAccessor, objectAccessor));
71         table->AddColumn(prefix + "state_type", Column(&ServicesTable::StateTypeAccessor, objectAccessor));
72         table->AddColumn(prefix + "check_type", Column(&ServicesTable::CheckTypeAccessor, objectAccessor));
73         table->AddColumn(prefix + "acknowledged", Column(&ServicesTable::AcknowledgedAccessor, objectAccessor));
74         table->AddColumn(prefix + "acknowledgement_type", Column(&ServicesTable::AcknowledgementTypeAccessor, objectAccessor));
75         table->AddColumn(prefix + "no_more_notifications", Column(&ServicesTable::NoMoreNotificationsAccessor, objectAccessor));
76         table->AddColumn(prefix + "last_time_ok", Column(&ServicesTable::LastTimeOkAccessor, objectAccessor));
77         table->AddColumn(prefix + "last_time_warning", Column(&ServicesTable::LastTimeWarningAccessor, objectAccessor));
78         table->AddColumn(prefix + "last_time_critical", Column(&ServicesTable::LastTimeCriticalAccessor, objectAccessor));
79         table->AddColumn(prefix + "last_time_unknown", Column(&ServicesTable::LastTimeUnknownAccessor, objectAccessor));
80         table->AddColumn(prefix + "last_check", Column(&ServicesTable::LastCheckAccessor, objectAccessor));
81         table->AddColumn(prefix + "next_check", Column(&ServicesTable::NextCheckAccessor, objectAccessor));
82         table->AddColumn(prefix + "last_notification", Column(&ServicesTable::LastNotificationAccessor, objectAccessor));
83         table->AddColumn(prefix + "next_notification", Column(&ServicesTable::NextNotificationAccessor, objectAccessor));
84         table->AddColumn(prefix + "current_notification_number", Column(&ServicesTable::CurrentNotificationNumberAccessor, objectAccessor));
85         table->AddColumn(prefix + "last_state_change", Column(&ServicesTable::LastStateChangeAccessor, objectAccessor));
86         table->AddColumn(prefix + "last_hard_state_change", Column(&ServicesTable::LastHardStateChangeAccessor, objectAccessor));
87         table->AddColumn(prefix + "scheduled_downtime_depth", Column(&ServicesTable::ScheduledDowntimeDepthAccessor, objectAccessor));
88         table->AddColumn(prefix + "is_flapping", Column(&ServicesTable::IsFlappingAccessor, objectAccessor));
89         table->AddColumn(prefix + "checks_enabled", Column(&ServicesTable::ChecksEnabledAccessor, objectAccessor));
90         table->AddColumn(prefix + "accept_passive_checks", Column(&ServicesTable::AcceptPassiveChecksAccessor, objectAccessor));
91         table->AddColumn(prefix + "event_handler_enabled", Column(&ServicesTable::EventHandlerEnabledAccessor, objectAccessor));
92         table->AddColumn(prefix + "notifications_enabled", Column(&ServicesTable::NotificationsEnabledAccessor, objectAccessor));
93         table->AddColumn(prefix + "process_performance_data", Column(&ServicesTable::ProcessPerformanceDataAccessor, objectAccessor));
94         table->AddColumn(prefix + "is_executing", Column(&ServicesTable::IsExecutingAccessor, objectAccessor));
95         table->AddColumn(prefix + "active_checks_enabled", Column(&ServicesTable::ActiveChecksEnabledAccessor, objectAccessor));
96         table->AddColumn(prefix + "check_options", Column(&ServicesTable::CheckOptionsAccessor, objectAccessor));
97         table->AddColumn(prefix + "flap_detection_enabled", Column(&ServicesTable::FlapDetectionEnabledAccessor, objectAccessor));
98         table->AddColumn(prefix + "check_freshness", Column(&ServicesTable::CheckFreshnessAccessor, objectAccessor));
99         table->AddColumn(prefix + "obsess_over_service", Column(&ServicesTable::ObsessOverServiceAccessor, objectAccessor));
100         table->AddColumn(prefix + "modified_attributes", Column(&ServicesTable::ModifiedAttributesAccessor, objectAccessor));
101         table->AddColumn(prefix + "modified_attributes_list", Column(&ServicesTable::ModifiedAttributesListAccessor, objectAccessor));
102         table->AddColumn(prefix + "pnpgraph_present", Column(&ServicesTable::PnpgraphPresentAccessor, objectAccessor));
103         table->AddColumn(prefix + "staleness", Column(&ServicesTable::StalenessAccessor, objectAccessor));
104         table->AddColumn(prefix + "check_interval", Column(&ServicesTable::CheckIntervalAccessor, objectAccessor));
105         table->AddColumn(prefix + "retry_interval", Column(&ServicesTable::RetryIntervalAccessor, objectAccessor));
106         table->AddColumn(prefix + "notification_interval", Column(&ServicesTable::NotificationIntervalAccessor, objectAccessor));
107         table->AddColumn(prefix + "first_notification_delay", Column(&ServicesTable::FirstNotificationDelayAccessor, objectAccessor));
108         table->AddColumn(prefix + "low_flap_threshold", Column(&ServicesTable::LowFlapThresholdAccessor, objectAccessor));
109         table->AddColumn(prefix + "high_flap_threshold", Column(&ServicesTable::HighFlapThresholdAccessor, objectAccessor));
110         table->AddColumn(prefix + "latency", Column(&ServicesTable::LatencyAccessor, objectAccessor));
111         table->AddColumn(prefix + "execution_time", Column(&ServicesTable::ExecutionTimeAccessor, objectAccessor));
112         table->AddColumn(prefix + "percent_state_change", Column(&ServicesTable::PercentStateChangeAccessor, objectAccessor));
113         table->AddColumn(prefix + "in_check_period", Column(&ServicesTable::InCheckPeriodAccessor, objectAccessor));
114         table->AddColumn(prefix + "in_notification_period", Column(&ServicesTable::InNotificationPeriodAccessor, objectAccessor));
115         table->AddColumn(prefix + "contacts", Column(&ServicesTable::ContactsAccessor, objectAccessor));
116         table->AddColumn(prefix + "downtimes", Column(&ServicesTable::DowntimesAccessor, objectAccessor));
117         table->AddColumn(prefix + "downtimes_with_info", Column(&ServicesTable::DowntimesWithInfoAccessor, objectAccessor));
118         table->AddColumn(prefix + "comments", Column(&ServicesTable::CommentsAccessor, objectAccessor));
119         table->AddColumn(prefix + "comments_with_info", Column(&ServicesTable::CommentsWithInfoAccessor, objectAccessor));
120         table->AddColumn(prefix + "comments_with_extra_info", Column(&ServicesTable::CommentsWithExtraInfoAccessor, objectAccessor));
121         table->AddColumn(prefix + "custom_variable_names", Column(&ServicesTable::CustomVariableNamesAccessor, objectAccessor));
122         table->AddColumn(prefix + "custom_variable_values", Column(&ServicesTable::CustomVariableValuesAccessor, objectAccessor));
123         table->AddColumn(prefix + "custom_variables", Column(&ServicesTable::CustomVariablesAccessor, objectAccessor));
124         table->AddColumn(prefix + "groups", Column(&ServicesTable::GroupsAccessor, objectAccessor));
125         table->AddColumn(prefix + "contact_groups", Column(&ServicesTable::ContactGroupsAccessor, objectAccessor));
126
127         HostsTable::AddColumns(table, "host_", boost::bind(&ServicesTable::HostAccessor, _1, objectAccessor));
128 }
129
130 String ServicesTable::GetName(void) const
131 {
132         return "services";
133 }
134
135 void ServicesTable::FetchRows(const AddRowFunction& addRowFn)
136 {
137         BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
138                 addRowFn(object);
139         }
140 }
141
142 Object::Ptr ServicesTable::HostAccessor(const Value& row, const Column::ObjectAccessor& parentObjectAccessor)
143 {
144         Value service;
145
146         if (parentObjectAccessor)
147                 service = parentObjectAccessor(row);
148         else
149                 service = row;
150
151         return static_cast<Service::Ptr>(service)->GetHost();
152 }
153
154 Value ServicesTable::ShortNameAccessor(const Value& row)
155 {
156         return static_cast<Service::Ptr>(row)->GetShortName();
157 }
158
159 Value ServicesTable::DisplayNameAccessor(const Value& row)
160 {
161         return static_cast<Service::Ptr>(row)->GetDisplayName();
162 }
163
164 Value ServicesTable::CheckCommandAccessor(const Value& row)
165 {
166         CheckCommand::Ptr checkcommand = static_cast<Service::Ptr>(row)->GetCheckCommand();
167
168         if (checkcommand)
169                 return checkcommand->GetName(); /* this is the name without '!' args */
170
171         return Empty;
172 }
173
174 Value ServicesTable::CheckCommandExpandedAccessor(const Value& row)
175 {
176         Service::Ptr service = static_cast<Service::Ptr>(row);
177
178         CheckCommand::Ptr commandObj = service->GetCheckCommand();
179
180         if (!commandObj)
181                 return Empty;
182
183         Value raw_command = commandObj->GetCommandLine();
184
185         std::vector<MacroResolver::Ptr> resolvers;
186         resolvers.push_back(commandObj);
187         resolvers.push_back(service);
188         resolvers.push_back(service->GetHost());
189         resolvers.push_back(IcingaApplication::GetInstance());
190
191         Value commandLine = MacroProcessor::ResolveMacros(raw_command, resolvers, Dictionary::Ptr(), Utility::EscapeShellCmd);
192
193         String buf;
194         if (commandLine.IsObjectType<Array>()) {
195                 Array::Ptr args = commandLine;
196
197                 ObjectLock olock(args);
198                 String arg;
199                 BOOST_FOREACH(arg, args) {
200                         // This is obviously incorrect for non-trivial cases.
201                         String argitem = " \"" + arg + "\"";
202                         boost::algorithm::replace_all(argitem, "\n", "\\n");
203                         buf += argitem;
204                 }
205         } else if (!commandLine.IsEmpty()) {
206                 String args = Convert::ToString(commandLine);
207                 boost::algorithm::replace_all(args, "\n", "\\n");
208                 buf += args;
209         } else {
210                 buf += "<internal>";
211         }
212
213         return buf;
214 }
215
216 Value ServicesTable::EventHandlerAccessor(const Value& row)
217 {
218         EventCommand::Ptr eventcommand = static_cast<Service::Ptr>(row)->GetEventCommand();
219
220         if (eventcommand)
221                 return eventcommand->GetName();
222
223         return Empty;
224 }
225
226 Value ServicesTable::PluginOutputAccessor(const Value& row)
227 {
228         return static_cast<Service::Ptr>(row)->GetLastCheckOutput();
229 }
230
231 Value ServicesTable::LongPluginOutputAccessor(const Value& row)
232 {
233         return static_cast<Service::Ptr>(row)->GetLastCheckLongOutput();
234 }
235
236 Value ServicesTable::PerfDataAccessor(const Value& row)
237 {
238         return static_cast<Service::Ptr>(row)->GetLastCheckPerfData();
239 }
240
241 Value ServicesTable::NotificationPeriodAccessor(const Value& row)
242 {
243         BOOST_FOREACH(const Notification::Ptr& notification, static_cast<Service::Ptr>(row)->GetNotifications()) {
244                 ObjectLock olock(notification);
245
246                 TimePeriod::Ptr timeperiod = notification->GetNotificationPeriod();
247
248                 /* XXX first notification wins */
249                 if (timeperiod)
250                         return timeperiod->GetName();
251         }
252
253         return Empty;
254 }
255
256 Value ServicesTable::CheckPeriodAccessor(const Value& row)
257 {
258         TimePeriod::Ptr timeperiod = static_cast<Service::Ptr>(row)->GetCheckPeriod();
259
260         if (!timeperiod)
261                 return Empty;
262
263         return timeperiod->GetName();
264 }
265
266 Value ServicesTable::NotesAccessor(const Value& row)
267 {
268         Dictionary::Ptr custom = static_cast<Service::Ptr>(row)->GetCustom();
269
270         if (!custom)
271                 return Empty;
272
273         return custom->Get("notes");
274 }
275
276 Value ServicesTable::NotesExpandedAccessor(const Value& row)
277 {
278         Service::Ptr service = static_cast<Service::Ptr>(row);
279         Dictionary::Ptr custom = service->GetCustom();
280
281         if (!custom)
282                 return Empty;
283
284         std::vector<MacroResolver::Ptr> resolvers;
285         resolvers.push_back(service);
286         resolvers.push_back(service->GetHost());
287         resolvers.push_back(IcingaApplication::GetInstance());
288
289         Value value = custom->Get("notes");
290
291         Dictionary::Ptr cr;
292         Value value_expanded = MacroProcessor::ResolveMacros(value, resolvers, cr, Utility::EscapeShellCmd);
293
294         return value_expanded;
295 }
296
297 Value ServicesTable::NotesUrlAccessor(const Value& row)
298 {
299         Dictionary::Ptr custom = static_cast<Service::Ptr>(row)->GetCustom();
300
301         if (!custom)
302                 return Empty;
303
304         return custom->Get("notes_url");
305 }
306
307 Value ServicesTable::NotesUrlExpandedAccessor(const Value& row)
308 {
309         Service::Ptr service = static_cast<Service::Ptr>(row);
310         Dictionary::Ptr custom = service->GetCustom();
311
312         if (!custom)
313                 return Empty;
314
315         std::vector<MacroResolver::Ptr> resolvers;
316         resolvers.push_back(service);
317         resolvers.push_back(service->GetHost());
318         resolvers.push_back(IcingaApplication::GetInstance());
319
320         Value value = custom->Get("notes_url");
321
322         Dictionary::Ptr cr;
323         Value value_expanded = MacroProcessor::ResolveMacros(value, resolvers, cr, Utility::EscapeShellCmd);
324
325         return value_expanded;
326 }
327
328 Value ServicesTable::ActionUrlAccessor(const Value& row)
329 {
330         Dictionary::Ptr custom = static_cast<Service::Ptr>(row)->GetCustom();
331
332         if (!custom)
333                 return Empty;
334
335         return custom->Get("action_url");
336 }
337
338 Value ServicesTable::ActionUrlExpandedAccessor(const Value& row)
339 {
340         Service::Ptr service = static_cast<Service::Ptr>(row);
341         Dictionary::Ptr custom = service->GetCustom();
342
343         if (!custom)
344                 return Empty;
345
346         std::vector<MacroResolver::Ptr> resolvers;
347         resolvers.push_back(service);
348         resolvers.push_back(service->GetHost());
349         resolvers.push_back(IcingaApplication::GetInstance());
350
351         Value value = custom->Get("action_url");
352
353         Dictionary::Ptr cr;
354         Value value_expanded = MacroProcessor::ResolveMacros(value, resolvers, cr, Utility::EscapeShellCmd);
355
356         return value_expanded;
357 }
358
359 Value ServicesTable::IconImageAccessor(const Value& row)
360 {
361         Dictionary::Ptr custom = static_cast<Service::Ptr>(row)->GetCustom();
362
363         if (!custom)
364                 return Empty;
365
366         return custom->Get("icon_image");
367 }
368
369 Value ServicesTable::IconImageExpandedAccessor(const Value& row)
370 {
371         Service::Ptr service = static_cast<Service::Ptr>(row);
372         Dictionary::Ptr custom = service->GetCustom();
373
374         if (!custom)
375                 return Empty;
376
377         std::vector<MacroResolver::Ptr> resolvers;
378         resolvers.push_back(service);
379         resolvers.push_back(service->GetHost());
380         resolvers.push_back(IcingaApplication::GetInstance());
381
382         Value value = custom->Get("icon_image");
383
384         Dictionary::Ptr cr;
385         Value value_expanded = MacroProcessor::ResolveMacros(value, resolvers, cr, Utility::EscapeShellCmd);
386
387         return value_expanded;
388 }
389
390 Value ServicesTable::IconImageAltAccessor(const Value& row)
391 {
392         Dictionary::Ptr custom = static_cast<Service::Ptr>(row)->GetCustom();
393
394         if (!custom)
395                 return Empty;
396
397         return custom->Get("icon_image_alt");
398 }
399
400 Value ServicesTable::InitialStateAccessor(const Value& row)
401 {
402         /* not supported */
403         return Empty;
404 }
405
406 Value ServicesTable::MaxCheckAttemptsAccessor(const Value& row)
407 {
408         return static_cast<Service::Ptr>(row)->GetMaxCheckAttempts();
409 }
410
411 Value ServicesTable::CurrentAttemptAccessor(const Value& row)
412 {
413         return static_cast<Service::Ptr>(row)->GetCurrentCheckAttempt();
414 }
415
416 Value ServicesTable::StateAccessor(const Value& row)
417 {
418         return static_cast<Service::Ptr>(row)->GetState();
419 }
420
421 Value ServicesTable::HasBeenCheckedAccessor(const Value& row)
422 {
423         return (static_cast<Service::Ptr>(row)->HasBeenChecked() ? 1 : 0);
424 }
425
426 Value ServicesTable::LastStateAccessor(const Value& row)
427 {
428         return static_cast<Service::Ptr>(row)->GetLastState();
429 }
430
431 Value ServicesTable::LastHardStateAccessor(const Value& row)
432 {
433         return static_cast<Service::Ptr>(row)->GetLastHardState();
434 }
435
436 Value ServicesTable::StateTypeAccessor(const Value& row)
437 {
438         return static_cast<Service::Ptr>(row)->GetStateType();
439 }
440
441 Value ServicesTable::CheckTypeAccessor(const Value& row)
442 {
443         return (static_cast<Service::Ptr>(row)->GetEnableActiveChecks() ? 0 : 1);
444 }
445
446 Value ServicesTable::AcknowledgedAccessor(const Value& row)
447 {
448         Service::Ptr service = static_cast<Service::Ptr>(row);
449
450         /* important: lock acknowledgements */
451         ObjectLock olock(service);
452
453         return (service->IsAcknowledged() ? 1 : 0);
454 }
455
456 Value ServicesTable::AcknowledgementTypeAccessor(const Value& row)
457 {
458         Service::Ptr service = static_cast<Service::Ptr>(row);
459
460         /* important: lock acknowledgements */
461         ObjectLock olock(service);
462
463         return static_cast<int>(service->GetAcknowledgement());
464 }
465
466 Value ServicesTable::NoMoreNotificationsAccessor(const Value& row)
467 {
468         Service::Ptr service = static_cast<Service::Ptr>(row);
469
470         /* XXX take the smallest notification_interval */
471         double notification_interval = -1;
472         BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
473                 if (notification_interval == -1 || notification->GetNotificationInterval() < notification_interval)
474                         notification_interval = notification->GetNotificationInterval();
475         }
476
477         if (notification_interval == 0 && !service->IsVolatile())
478                 return 1;
479
480         return 0;
481 }
482
483 Value ServicesTable::LastTimeOkAccessor(const Value& row)
484 {
485         return static_cast<int>(static_cast<Service::Ptr>(row)->GetLastStateOK());
486 }
487
488 Value ServicesTable::LastTimeWarningAccessor(const Value& row)
489 {
490         return static_cast<int>(static_cast<Service::Ptr>(row)->GetLastStateWarning());
491 }
492
493 Value ServicesTable::LastTimeCriticalAccessor(const Value& row)
494 {
495         return static_cast<int>(static_cast<Service::Ptr>(row)->GetLastStateCritical());
496 }
497
498 Value ServicesTable::LastTimeUnknownAccessor(const Value& row)
499 {
500         return static_cast<int>(static_cast<Service::Ptr>(row)->GetLastStateUnknown());
501 }
502
503 Value ServicesTable::LastCheckAccessor(const Value& row)
504 {
505         return static_cast<int>(static_cast<Service::Ptr>(row)->GetLastCheck());
506 }
507
508 Value ServicesTable::NextCheckAccessor(const Value& row)
509 {
510         return static_cast<int>(static_cast<Service::Ptr>(row)->GetNextCheck());
511 }
512
513 Value ServicesTable::LastNotificationAccessor(const Value& row)
514 {
515         Service::Ptr service = static_cast<Service::Ptr>(row);
516
517         /* XXX Service -> Notifications, latest wins */
518         double last_notification = 0;
519         BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
520                 if (notification->GetLastNotification() > last_notification)
521                         last_notification = notification->GetLastNotification();
522         }
523
524         return static_cast<int>(last_notification);
525 }
526
527 Value ServicesTable::NextNotificationAccessor(const Value& row)
528 {
529         Service::Ptr service = static_cast<Service::Ptr>(row);
530
531         /* XXX Service -> Notifications, latest wins */
532         double next_notification = 0;
533         BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
534                 if (notification->GetNextNotification() < next_notification)
535                         next_notification = notification->GetNextNotification();
536         }
537
538         return static_cast<int>(next_notification);
539 }
540
541 Value ServicesTable::CurrentNotificationNumberAccessor(const Value& row)
542 {
543         Service::Ptr service = static_cast<Service::Ptr>(row);
544
545         /* XXX Service -> Notifications, biggest wins */
546         int notification_number = 0;
547         BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
548                 if (notification->GetNotificationNumber() > notification_number)
549                         notification_number = notification->GetNotificationNumber();
550         }
551
552         return notification_number;
553 }
554
555 Value ServicesTable::LastStateChangeAccessor(const Value& row)
556 {
557         return static_cast<int>(static_cast<Service::Ptr>(row)->GetLastStateChange());
558 }
559
560 Value ServicesTable::LastHardStateChangeAccessor(const Value& row)
561 {
562         return static_cast<int>(static_cast<Service::Ptr>(row)->GetLastHardStateChange());
563 }
564
565 Value ServicesTable::ScheduledDowntimeDepthAccessor(const Value& row)
566 {
567         return static_cast<Service::Ptr>(row)->GetDowntimeDepth();
568 }
569
570 Value ServicesTable::IsFlappingAccessor(const Value& row)
571 {
572         return static_cast<Service::Ptr>(row)->IsFlapping();
573 }
574
575 Value ServicesTable::ChecksEnabledAccessor(const Value& row)
576 {
577         return (static_cast<Service::Ptr>(row)->GetEnableActiveChecks() ? 1 : 0);
578 }
579
580 Value ServicesTable::AcceptPassiveChecksAccessor(const Value& row)
581 {
582         return (static_cast<Service::Ptr>(row)->GetEnablePassiveChecks() ? 1 : 0);
583 }
584
585 Value ServicesTable::EventHandlerEnabledAccessor(const Value& row)
586 {
587         /* always enabled */
588         return 1;
589 }
590
591 Value ServicesTable::NotificationsEnabledAccessor(const Value& row)
592 {
593         return (static_cast<Service::Ptr>(row)->GetEnableNotifications() ? 1 : 0);
594 }
595
596 Value ServicesTable::ProcessPerformanceDataAccessor(const Value& row)
597 {
598         /* always enabled */
599         return 1;
600 }
601
602 Value ServicesTable::IsExecutingAccessor(const Value& row)
603 {
604         /* not supported */
605         return Empty;
606 }
607
608 Value ServicesTable::ActiveChecksEnabledAccessor(const Value& row)
609 {
610         return (static_cast<Service::Ptr>(row)->GetEnableActiveChecks() ? 1 : 0);
611 }
612
613 Value ServicesTable::CheckOptionsAccessor(const Value& row)
614 {
615         /* TODO - forcexec, freshness, orphan, none */
616         return Empty;
617 }
618
619 Value ServicesTable::FlapDetectionEnabledAccessor(const Value& row)
620 {
621         return (static_cast<Service::Ptr>(row)->GetEnableFlapping() ? 1 : 0);
622 }
623
624 Value ServicesTable::CheckFreshnessAccessor(const Value& row)
625 {
626         /* always enabled */
627         return 1;
628 }
629
630 Value ServicesTable::ObsessOverServiceAccessor(const Value& row)
631 {
632         /* not supported */
633         return Empty;
634 }
635
636 Value ServicesTable::ModifiedAttributesAccessor(const Value& row)
637 {
638         /* not supported */
639         return Empty;
640 }
641
642 Value ServicesTable::ModifiedAttributesListAccessor(const Value& row)
643 {
644         /* not supported */
645         return Empty;
646 }
647
648 Value ServicesTable::PnpgraphPresentAccessor(const Value& row)
649 {
650         /* not supported */
651         return Empty;
652 }
653
654 Value ServicesTable::StalenessAccessor(const Value& row)
655 {
656         Service::Ptr service = static_cast<Service::Ptr>(row);
657
658         if (service->HasBeenChecked() && service->GetLastCheck() > 0)
659                 return (Utility::GetTime() - service->GetLastCheck()) / (service->GetCheckInterval() * 3600);
660
661         return Empty;
662 }
663
664 Value ServicesTable::CheckIntervalAccessor(const Value& row)
665 {
666         return (static_cast<Service::Ptr>(row)->GetCheckInterval() / 60.0);
667 }
668
669 Value ServicesTable::RetryIntervalAccessor(const Value& row)
670 {
671         return (static_cast<Service::Ptr>(row)->GetRetryInterval() / 60.0);
672 }
673
674 Value ServicesTable::NotificationIntervalAccessor(const Value& row)
675 {
676         Service::Ptr service = static_cast<Service::Ptr>(row);
677
678         /* XXX take the smallest notification_interval */
679         double notification_interval = -1;
680         BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
681                 if (notification_interval == -1 || notification->GetNotificationInterval() < notification_interval)
682                         notification_interval = notification->GetNotificationInterval();
683         }
684
685         if (notification_interval == -1)
686                 notification_interval = 60;
687
688         return (notification_interval / 60.0);
689 }
690
691 Value ServicesTable::FirstNotificationDelayAccessor(const Value& row)
692 {
693         /* not supported */
694         return Empty;
695 }
696
697 Value ServicesTable::LowFlapThresholdAccessor(const Value& row)
698 {
699         return static_cast<Service::Ptr>(row)->GetFlappingThreshold();
700 }
701
702 Value ServicesTable::HighFlapThresholdAccessor(const Value& row)
703 {
704         return static_cast<Service::Ptr>(row)->GetFlappingThreshold();
705 }
706
707 Value ServicesTable::LatencyAccessor(const Value& row)
708 {
709         return (Service::CalculateLatency(static_cast<Service::Ptr>(row)->GetLastCheckResult()));
710 }
711
712 Value ServicesTable::ExecutionTimeAccessor(const Value& row)
713 {
714         return (Service::CalculateExecutionTime(static_cast<Service::Ptr>(row)->GetLastCheckResult()));
715 }
716
717 Value ServicesTable::PercentStateChangeAccessor(const Value& row)
718 {
719         return static_cast<Service::Ptr>(row)->GetFlappingCurrent();
720 }
721
722 Value ServicesTable::InCheckPeriodAccessor(const Value& row)
723 {
724         TimePeriod::Ptr timeperiod = static_cast<Service::Ptr>(row)->GetCheckPeriod();
725
726         /* none set means always checked */
727         if (!timeperiod)
728                 return 1;
729
730         return (timeperiod->IsInside(Utility::GetTime()) ? 1 : 0);
731 }
732
733 Value ServicesTable::InNotificationPeriodAccessor(const Value& row)
734 {
735         BOOST_FOREACH(const Notification::Ptr& notification, static_cast<Service::Ptr>(row)->GetNotifications()) {
736                 ObjectLock olock(notification);
737
738                 TimePeriod::Ptr timeperiod = notification->GetNotificationPeriod();
739
740                 /* XXX first notification wins */
741                 if (timeperiod)
742                         return (timeperiod->IsInside(Utility::GetTime()) ? 1 : 0);
743         }
744
745         /* none set means always notified */
746         return 1;
747 }
748
749 Value ServicesTable::ContactsAccessor(const Value& row)
750 {
751         /* XXX Service -> Notifications -> (Users + UserGroups -> Users) */
752         std::set<User::Ptr> allUsers;
753         std::set<User::Ptr> users;
754         Array::Ptr contacts = boost::make_shared<Array>();
755
756         BOOST_FOREACH(const Notification::Ptr& notification, static_cast<Service::Ptr>(row)->GetNotifications()) {
757                 ObjectLock olock(notification);
758
759                 users = notification->GetUsers();
760
761                 std::copy(users.begin(), users.end(), std::inserter(allUsers, allUsers.begin()));
762
763                 BOOST_FOREACH(const UserGroup::Ptr& ug, notification->GetGroups()) {
764                         std::set<User::Ptr> members = ug->GetMembers();
765                         std::copy(members.begin(), members.end(), std::inserter(allUsers, allUsers.begin()));
766                 }
767         }
768
769         BOOST_FOREACH(const User::Ptr& user, allUsers) {
770                 contacts->Add(user->GetName());
771         }
772
773         return contacts;
774 }
775
776 Value ServicesTable::DowntimesAccessor(const Value& row)
777 {
778         Dictionary::Ptr downtimes = static_cast<Service::Ptr>(row)->GetDowntimes();
779
780         if (!downtimes)
781                 return Empty;
782
783         Array::Ptr ids = boost::make_shared<Array>();
784
785         ObjectLock olock(downtimes);
786
787         String id;
788         Dictionary::Ptr downtime;
789         BOOST_FOREACH(boost::tie(id, downtime), downtimes) {
790
791                 if (!downtime)
792                         continue;
793
794                 if (Service::IsDowntimeExpired(downtime))
795                         continue;
796
797                 ids->Add(downtime->Get("legacy_id"));
798         }
799
800         return ids;
801 }
802
803 Value ServicesTable::DowntimesWithInfoAccessor(const Value& row)
804 {
805         Dictionary::Ptr downtimes = static_cast<Service::Ptr>(row)->GetDowntimes();
806
807         if (!downtimes)
808                 return Empty;
809
810         Array::Ptr ids = boost::make_shared<Array>();
811
812         ObjectLock olock(downtimes);
813
814         String id;
815         Dictionary::Ptr downtime;
816         BOOST_FOREACH(boost::tie(id, downtime), downtimes) {
817
818                 if (!downtime)
819                         continue;
820
821                 if (Service::IsDowntimeExpired(downtime))
822                         continue;
823
824                 Array::Ptr downtime_info = boost::make_shared<Array>();
825                 downtime_info->Add(downtime->Get("legacy_id"));
826                 downtime_info->Add(downtime->Get("author"));
827                 downtime_info->Add(downtime->Get("comment"));
828                 ids->Add(downtime_info);
829         }
830
831         return ids;
832 }
833
834 Value ServicesTable::CommentsAccessor(const Value& row)
835 {
836         Dictionary::Ptr comments = static_cast<Service::Ptr>(row)->GetComments();
837
838         if (!comments)
839                 return Empty;
840
841         Array::Ptr ids = boost::make_shared<Array>();
842
843         ObjectLock olock(comments);
844
845         String id;
846         Dictionary::Ptr comment;
847         BOOST_FOREACH(boost::tie(id, comment), comments) {
848
849                 if (!comment)
850                         continue;
851
852                 if (Service::IsCommentExpired(comment))
853                         continue;
854
855                 ids->Add(comment->Get("legacy_id"));
856         }
857
858         return ids;
859 }
860
861 Value ServicesTable::CommentsWithInfoAccessor(const Value& row)
862 {
863         Dictionary::Ptr comments = static_cast<Service::Ptr>(row)->GetComments();
864
865         if (!comments)
866                 return Empty;
867
868         Array::Ptr ids = boost::make_shared<Array>();
869
870         ObjectLock olock(comments);
871
872         String id;
873         Dictionary::Ptr comment;
874         BOOST_FOREACH(boost::tie(id, comment), comments) {
875
876                 if (!comment)
877                         continue;
878
879                 if (Service::IsCommentExpired(comment))
880                         continue;
881
882                 Array::Ptr comment_info = boost::make_shared<Array>();
883                 comment_info->Add(comment->Get("legacy_id"));
884                 comment_info->Add(comment->Get("author"));
885                 comment_info->Add(comment->Get("text"));
886                 ids->Add(comment_info);
887         }
888
889         return ids;
890 }
891
892 Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row)
893 {
894         Dictionary::Ptr comments = static_cast<Service::Ptr>(row)->GetComments();
895
896         if (!comments)
897                 return Empty;
898
899         Array::Ptr ids = boost::make_shared<Array>();
900
901         ObjectLock olock(comments);
902
903         String id;
904         Dictionary::Ptr comment;
905         BOOST_FOREACH(boost::tie(id, comment), comments) {
906
907                 if (!comment)
908                         continue;
909
910                 if (Service::IsCommentExpired(comment))
911                         continue;
912
913                 Array::Ptr comment_info = boost::make_shared<Array>();
914                 comment_info->Add(comment->Get("legacy_id"));
915                 comment_info->Add(comment->Get("author"));
916                 comment_info->Add(comment->Get("text"));
917                 comment_info->Add(comment->Get("entry_type"));
918                 comment_info->Add(static_cast<int>(comment->Get("entry_time")));
919                 ids->Add(comment_info);
920         }
921
922         return ids;
923 }
924
925 Value ServicesTable::CustomVariableNamesAccessor(const Value& row)
926 {
927         Dictionary::Ptr custom = static_cast<Service::Ptr>(row)->GetCustom();
928
929         if (!custom)
930                 return Empty;
931
932         Array::Ptr cv = boost::make_shared<Array>();
933
934         ObjectLock olock(custom);
935         String key;
936         Value value;
937         BOOST_FOREACH(boost::tie(key, value), custom) {
938                 if (key == "notes" ||
939                     key == "action_url" ||
940                     key == "notes_url" ||
941                     key == "icon_image" ||
942                     key == "icon_image_alt" ||
943                     key == "statusmap_image" ||
944                     key == "2d_coords")
945                         continue;
946
947                 cv->Add(key);
948         }
949
950         return cv;
951 }
952
953 Value ServicesTable::CustomVariableValuesAccessor(const Value& row)
954 {
955         Dictionary::Ptr custom = static_cast<Service::Ptr>(row)->GetCustom();
956
957         if (!custom)
958                 return Empty;
959
960         Array::Ptr cv = boost::make_shared<Array>();
961
962         ObjectLock olock(custom);
963         String key;
964         Value value;
965         BOOST_FOREACH(boost::tie(key, value), custom) {
966                 if (key == "notes" ||
967                     key == "action_url" ||
968                     key == "notes_url" ||
969                     key == "icon_image" ||
970                     key == "icon_image_alt" ||
971                     key == "statusmap_image" ||
972                     key == "2d_coords")
973                         continue;
974
975                 cv->Add(value);
976         }
977
978         return cv;
979 }
980
981 Value ServicesTable::CustomVariablesAccessor(const Value& row)
982 {
983         Dictionary::Ptr custom = static_cast<Service::Ptr>(row)->GetCustom();
984
985         if (!custom)
986                 return Empty;
987
988         Array::Ptr cv = boost::make_shared<Array>();
989
990         ObjectLock olock(custom);
991         String key;
992         Value value;
993         BOOST_FOREACH(boost::tie(key, value), custom) {
994                 if (key == "notes" ||
995                     key == "action_url" ||
996                     key == "notes_url" ||
997                     key == "icon_image" ||
998                     key == "icon_image_alt" ||
999                     key == "statusmap_image" ||
1000                     key == "2d_coords")
1001                         continue;
1002
1003                 Array::Ptr key_val = boost::make_shared<Array>();
1004                 key_val->Add(key);
1005                 key_val->Add(value);
1006                 cv->Add(key_val);
1007         }
1008
1009         return cv;
1010 }
1011
1012 Value ServicesTable::GroupsAccessor(const Value& row)
1013 {
1014         Array::Ptr groups = static_cast<Service::Ptr>(row)->GetGroups();
1015
1016         if (!groups)
1017                 return Empty;
1018
1019         return groups;
1020 }
1021
1022 Value ServicesTable::ContactGroupsAccessor(const Value& row)
1023 {
1024         /* XXX Service -> Notifications -> UserGroups */
1025         Array::Ptr contactgroups = boost::make_shared<Array>();
1026
1027         BOOST_FOREACH(const Notification::Ptr& notification, static_cast<Service::Ptr>(row)->GetNotifications()) {
1028                 ObjectLock olock(notification);
1029
1030                 BOOST_FOREACH(const UserGroup::Ptr& ug, notification->GetGroups()) {
1031                         contactgroups->Add(ug->GetName());
1032                 }
1033         }
1034
1035         return contactgroups;
1036 }
1037
1038