]> granicus.if.org Git - icinga2/blob - components/compat/statusdatawriter.cpp
Refactor CompatUtility::* for DB IDO, Livestatus, StatusData.
[icinga2] / components / compat / statusdatawriter.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2013 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 "compat/statusdatawriter.h"
21 #include "icinga/icingaapplication.h"
22 #include "icinga/cib.h"
23 #include "icinga/hostgroup.h"
24 #include "icinga/servicegroup.h"
25 #include "icinga/checkcommand.h"
26 #include "icinga/eventcommand.h"
27 #include "icinga/timeperiod.h"
28 #include "icinga/notificationcommand.h"
29 #include "icinga/compatutility.h"
30 #include "base/dynamictype.h"
31 #include "base/objectlock.h"
32 #include "base/convert.h"
33 #include "base/logger_fwd.h"
34 #include "base/exception.h"
35 #include "base/application.h"
36 #include "base/context.h"
37 #include <boost/foreach.hpp>
38 #include <boost/tuple/tuple.hpp>
39 #include <boost/algorithm/string/replace.hpp>
40 #include <fstream>
41
42 using namespace icinga;
43
44 REGISTER_TYPE(StatusDataWriter);
45
46 /**
47  * Hint: The reason why we're using "\n" rather than std::endl is because
48  * std::endl also _flushes_ the output stream which severely degrades
49  * performance (see http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt11ch25s02.html).
50  */
51
52 /**
53  * Starts the component.
54  */
55 void StatusDataWriter::Start(void)
56 {
57         DynamicObject::Start();
58
59         m_StatusTimer = make_shared<Timer>();
60         m_StatusTimer->SetInterval(GetUpdateInterval());
61         m_StatusTimer->OnTimerExpired.connect(boost::bind(&StatusDataWriter::StatusTimerHandler, this));
62         m_StatusTimer->Start();
63         m_StatusTimer->Reschedule(0);
64
65         Utility::QueueAsyncCallback(boost::bind(&StatusDataWriter::UpdateObjectsCache, this));
66 }
67
68 void StatusDataWriter::DumpComments(std::ostream& fp, const Service::Ptr& owner, CompatObjectType type)
69 {
70         Service::Ptr service;
71         Dictionary::Ptr comments = owner->GetComments();
72
73         Host::Ptr host = owner->GetHost();
74
75         ObjectLock olock(comments);
76
77         BOOST_FOREACH(const Dictionary::Pair& kv, comments) {
78                 Comment::Ptr comment = kv.second;
79
80                 if (comment->IsExpired())
81                         continue;
82
83                 if (type == CompatTypeHost)
84                         fp << "hostcomment {" << "\n";
85                 else
86                         fp << "servicecomment {" << "\n"
87                            << "\t" << "service_description=" << owner->GetShortName() << "\n";
88
89                 fp << "\t" << "host_name=" << host->GetName() << "\n"
90                    << "\t" << "comment_id=" << comment->GetLegacyId() << "\n"
91                    << "\t" << "entry_time=" << comment->GetEntryTime() << "\n"
92                    << "\t" << "entry_type=" << comment->GetEntryType() << "\n"
93                    << "\t" << "persistent=" << 1 << "\n"
94                    << "\t" << "author=" << comment->GetAuthor() << "\n"
95                    << "\t" << "comment_data=" << comment->GetText() << "\n"
96                    << "\t" << "expires=" << (comment->GetExpireTime() != 0 ? 1 : 0) << "\n"
97                    << "\t" << "expire_time=" << comment->GetExpireTime() << "\n"
98                    << "\t" << "}" << "\n"
99                    << "\n";
100         }
101 }
102
103 void StatusDataWriter::DumpTimePeriod(std::ostream& fp, const TimePeriod::Ptr& tp)
104 {
105         fp << "define timeperiod {" << "\n"
106            << "\t" << "timeperiod_name" << "\t" << tp->GetName() << "\n"
107            << "\t" << "alias" << "\t" << tp->GetName() << "\n";
108
109         Dictionary::Ptr ranges = tp->GetRanges();
110
111         if (ranges) {
112                 ObjectLock olock(ranges);
113                 BOOST_FOREACH(const Dictionary::Pair& kv, ranges) {
114                         fp << "\t" << kv.first << "\t" << kv.second << "\n";
115                 }
116         }
117
118         fp << "\t" << "}" << "\n"
119            << "\n";
120 }
121
122 void StatusDataWriter::DumpCommand(std::ostream& fp, const Command::Ptr& command)
123 {
124         fp << "define command {" << "\n"
125            << "\t" << "command_name\t";
126
127
128         if (command->GetType() == DynamicType::GetByName("CheckCommand"))
129                 fp << "check_";
130         else if (command->GetType() == DynamicType::GetByName("NotificationCommand"))
131                 fp << "notification_";
132         else if (command->GetType() == DynamicType::GetByName("EventCommand"))
133                 fp << "event_";
134
135         fp << command->GetName() << "\n";
136
137         fp << "\t" << "command_line\t";
138
139         Value commandLine = command->GetCommandLine();
140
141         if (commandLine.IsObjectType<Array>()) {
142                 Array::Ptr args = commandLine;
143
144                 ObjectLock olock(args);
145                 String arg;
146                 BOOST_FOREACH(arg, args) {
147                         // This is obviously incorrect for non-trivial cases.
148                         fp << " \"" << CompatUtility::EscapeString(arg) << "\"";
149                 }
150         } else if (!commandLine.IsEmpty()) {
151                 fp << CompatUtility::EscapeString(commandLine);
152         } else {
153                 fp << "<internal>";
154         }
155
156         fp << "\n";
157
158         fp << "\t" << "}" << "\n"
159            << "\n";
160
161 }
162
163 void StatusDataWriter::DumpDowntimes(std::ostream& fp, const Service::Ptr& owner, CompatObjectType type)
164 {
165         Host::Ptr host = owner->GetHost();
166
167         Dictionary::Ptr downtimes = owner->GetDowntimes();
168
169         ObjectLock olock(downtimes);
170
171         BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
172                 Downtime::Ptr downtime = kv.second;
173
174                 if (downtime->IsExpired())
175                         continue;
176
177                 if (type == CompatTypeHost)
178                         fp << "hostdowntime {" << "\n";
179                 else
180                         fp << "servicedowntime {" << "\n"
181                            << "\t" << "service_description=" << owner->GetShortName() << "\n";
182
183                 Downtime::Ptr triggeredByObj = Service::GetDowntimeByID(downtime->GetTriggeredBy());
184                 int triggeredByLegacy = 0;
185                 if (triggeredByObj)
186                         triggeredByLegacy = triggeredByObj->GetLegacyId();
187
188                 fp << "\t" << "host_name=" << host->GetName() << "\n"
189                    << "\t" << "downtime_id=" << downtime->GetLegacyId() << "\n"
190                    << "\t" << "entry_time=" << downtime->GetEntryTime() << "\n"
191                    << "\t" << "start_time=" << downtime->GetStartTime() << "\n"
192                    << "\t" << "end_time=" << downtime->GetEndTime() << "\n"
193                    << "\t" << "triggered_by=" << triggeredByLegacy << "\n"
194                    << "\t" << "fixed=" << static_cast<long>(downtime->GetFixed()) << "\n"
195                    << "\t" << "duration=" << static_cast<long>(downtime->GetDuration()) << "\n"
196                    << "\t" << "is_in_effect=" << (downtime->IsActive() ? 1 : 0) << "\n"
197                    << "\t" << "author=" << downtime->GetAuthor() << "\n"
198                    << "\t" << "comment=" << downtime->GetComment() << "\n"
199                    << "\t" << "trigger_time=" << downtime->GetTriggerTime() << "\n"
200                    << "\t" << "}" << "\n"
201                    << "\n";
202         }
203 }
204
205 void StatusDataWriter::DumpHostStatus(std::ostream& fp, const Host::Ptr& host)
206 {
207         fp << "hoststatus {" << "\n"
208            << "\t" << "host_name=" << host->GetName() << "\n";
209
210         Service::Ptr hc = host->GetCheckService();
211         ObjectLock olock(hc);
212
213         if (hc)
214                 DumpServiceStatusAttrs(fp, hc, CompatTypeHost);
215
216         /* ugly but cgis parse only that */
217         fp << "\t" << "last_time_up=" << host->GetLastStateUp() << "\n"
218            << "\t" << "last_time_down=" << host->GetLastStateDown() << "\n"
219            << "\t" << "last_time_unreachable=" << host->GetLastStateUnreachable() << "\n";
220
221         fp << "\t" << "}" << "\n"
222            << "\n";
223
224         if (hc) {
225                 DumpDowntimes(fp, hc, CompatTypeHost);
226                 DumpComments(fp, hc, CompatTypeHost);
227         }
228 }
229
230 void StatusDataWriter::DumpHostObject(std::ostream& fp, const Host::Ptr& host)
231 {
232         fp << "define host {" << "\n"
233            << "\t" << "host_name" << "\t" << host->GetName() << "\n"
234            << "\t" << "display_name" << "\t" << host->GetDisplayName() << "\n"
235            << "\t" << "alias" << "\t" << host->GetDisplayName() << "\n"
236            << "\t" << "address" << "\t" << CompatUtility::GetHostAddress(host) << "\n"
237            << "\t" << "address6" << "\t" << CompatUtility::GetHostAddress6(host) << "\n"
238            << "\t" << "notes" << "\t" << CompatUtility::GetCustomAttributeConfig(host, "notes") << "\n"
239            << "\t" << "notes_url" << "\t" << CompatUtility::GetCustomAttributeConfig(host, "notes_url") << "\n"
240            << "\t" << "action_url" << "\t" << CompatUtility::GetCustomAttributeConfig(host, "action_url") << "\n"
241            << "\t" << "icon_image" << "\t" << CompatUtility::GetCustomAttributeConfig(host, "icon_image") << "\n"
242            << "\t" << "icon_image_alt" << "\t" << CompatUtility::GetCustomAttributeConfig(host, "icon_image_alt") << "\n"
243            << "\t" << "statusmap_image" << "\t" << CompatUtility::GetCustomAttributeConfig(host, "statusmap_image") << "\n";
244
245         std::set<Host::Ptr> parents = host->GetParentHosts();
246
247         if (!parents.empty()) {
248                 fp << "\t" << "parents" << "\t";
249                 DumpNameList(fp, parents);
250                 fp << "\n";
251         }
252
253         Service::Ptr hc = host->GetCheckService();
254         if (hc) {
255                 ObjectLock olock(hc);
256
257                 fp << "\t" << "check_interval" << "\t" << CompatUtility::GetServiceCheckInterval(hc) << "\n"
258                    << "\t" << "retry_interval" << "\t" << CompatUtility::GetServiceRetryInterval(hc) << "\n"
259                    << "\t" << "max_check_attempts" << "\t" << hc->GetMaxCheckAttempts() << "\n"
260                    << "\t" << "active_checks_enabled" << "\t" << (hc->GetEnableActiveChecks() ? 1 : 0) << "\n"
261                    << "\t" << "passive_checks_enabled" << "\t" << (hc->GetEnablePassiveChecks() ? 1 : 0) << "\n"
262                    << "\t" << "notifications_enabled" << "\t" << (hc->GetEnableNotifications() ? 1 : 0) << "\n"
263                    << "\t" << "notification_options" << "\t" << "d,u,r" << "\n"
264                    << "\t" << "notification_interval" << "\t" << CompatUtility::GetServiceNotificationNotificationInterval(hc) << "\n"
265                    << "\t" << "event_handler_enabled" << "\t" << (hc->GetEnableEventHandler() ? 1 : 0) << "\n";
266
267                 CheckCommand::Ptr checkcommand = hc->GetCheckCommand();
268                 if (checkcommand)
269                         fp << "\t" << "check_command" << "\t" << "check_" << checkcommand->GetName() << "\n";
270
271                 EventCommand::Ptr eventcommand = hc->GetEventCommand();
272                 if (eventcommand)
273                         fp << "\t" << "event_handler" << "\t" << "event_" << eventcommand->GetName() << "\n";
274
275                 fp << "\t" << "check_period" << "\t" << CompatUtility::GetServiceCheckPeriod(hc) << "\n";
276
277                 fp << "\t" << "contacts" << "\t";
278                 DumpNameList(fp, CompatUtility::GetServiceNotificationUsers(hc));
279                 fp << "\n";
280
281                 fp << "\t" << "contact_groups" << "\t";
282                 DumpNameList(fp, CompatUtility::GetServiceNotificationUserGroups(hc));
283                 fp << "\n";
284
285                 fp << "\t" << "initial_state" << "\t" << "o" << "\n"
286                    << "\t" << "low_flap_threshold" << "\t" << hc->GetFlappingThreshold() << "\n"
287                    << "\t" << "high_flap_threshold" << "\t" << hc->GetFlappingThreshold() << "\n"
288                    << "\t" << "process_perf_data" << "\t" << 1 << "\n"
289                    << "\t" << "check_freshness" << "\t" << 1 << "\n";
290
291         } else {
292                 fp << "\t" << "check_interval" << "\t" << 60 << "\n"
293                    << "\t" << "retry_interval" << "\t" << 60 << "\n"
294                    << "\t" << "max_check_attempts" << "\t" << 1 << "\n"
295                    << "\t" << "active_checks_enabled" << "\t" << 0 << "\n"
296                    << "\t" << "passive_checks_enabled" << "\t" << 0 << "\n"
297                    << "\t" << "notifications_enabled" << "\t" << 0 << "\n";
298
299         }
300
301         fp << "\t" << "host_groups" << "\t";
302         bool first = true;
303
304         Array::Ptr groups = host->GetGroups();
305
306         if (groups) {
307                 ObjectLock olock(groups);
308
309                 BOOST_FOREACH(const String& name, groups) {
310                         HostGroup::Ptr hg = HostGroup::GetByName(name);
311
312                         if (hg) {
313                                 if (!first)
314                                         fp << ",";
315                                 else
316                                         first = false;
317
318                                 fp << hg->GetName();
319                         }
320                 }
321         }
322
323         fp << "\n";
324
325         DumpCustomAttributes(fp, host);
326
327         fp << "\t" << "}" << "\n"
328            << "\n";
329 }
330
331 void StatusDataWriter::DumpServiceStatusAttrs(std::ostream& fp, const Service::Ptr& service, CompatObjectType type)
332 {
333         CheckResult::Ptr cr = service->GetLastCheckResult();
334
335         fp << "\t" << "check_command=check_" << CompatUtility::GetServiceCheckCommand(service) << "\n"
336            << "\t" << "event_handler=event_" << CompatUtility::GetServiceEventHandler(service) << "\n"
337            << "\t" << "check_period=" << CompatUtility::GetServiceCheckPeriod(service) << "\n"
338            << "\t" << "check_interval=" << CompatUtility::GetServiceCheckInterval(service) << "\n"
339            << "\t" << "retry_interval=" << CompatUtility::GetServiceRetryInterval(service) << "\n"
340            << "\t" << "has_been_checked=" << CompatUtility::GetServiceHasBeenChecked(service) << "\n"
341            << "\t" << "should_be_scheduled=" << CompatUtility::GetServiceShouldBeScheduled(service) << "\n";
342
343         if (cr) {
344            fp << "\t" << "check_execution_time=" << static_cast<double>(Service::CalculateExecutionTime(cr)) << "\n"
345               << "\t" << "check_latency=" << static_cast<double>(Service::CalculateLatency(cr)) << "\n";
346         }
347
348         fp << "\t" << "current_state=" << CompatUtility::GetServiceCurrentState(service) << "\n"
349            << "\t" << "state_type=" << service->GetStateType() << "\n"
350            << "\t" << "plugin_output=" << CompatUtility::GetCheckResultOutput(cr) << "\n"
351            << "\t" << "long_plugin_output=" << CompatUtility::GetCheckResultLongOutput(cr) << "\n"
352            << "\t" << "performance_data=" << CompatUtility::GetCheckResultPerfdata(cr) << "\n";
353
354         if (cr) {
355            fp << "\t" << "check_source=" << cr->GetCheckSource() << "\n"
356               << "\t" << "last_check=" << static_cast<long>(cr->GetScheduleEnd()) << "\n";
357         }
358
359         fp << "\t" << "next_check=" << static_cast<long>(service->GetNextCheck()) << "\n"
360            << "\t" << "current_attempt=" << service->GetCheckAttempt() << "\n"
361            << "\t" << "max_attempts=" << service->GetMaxCheckAttempts() << "\n"
362            << "\t" << "last_state_change=" << static_cast<long>(service->GetLastStateChange()) << "\n"
363            << "\t" << "last_hard_state_change=" << static_cast<long>(service->GetLastHardStateChange()) << "\n"
364            << "\t" << "last_time_ok=" << static_cast<int>(service->GetLastStateOK()) << "\n"
365            << "\t" << "last_time_warn=" << static_cast<int>(service->GetLastStateWarning()) << "\n"
366            << "\t" << "last_time_critical=" << static_cast<int>(service->GetLastStateCritical()) << "\n"
367            << "\t" << "last_time_unknown=" << static_cast<int>(service->GetLastStateUnknown()) << "\n"
368            << "\t" << "last_update=" << static_cast<long>(time(NULL)) << "\n"
369            << "\t" << "notifications_enabled=" << CompatUtility::GetServiceNotificationsEnabled(service) << "\n"
370            << "\t" << "active_checks_enabled=" << CompatUtility::GetServiceActiveChecksEnabled(service) << "\n"
371            << "\t" << "passive_checks_enabled=" << CompatUtility::GetServicePassiveChecksEnabled(service) << "\n"
372            << "\t" << "flap_detection_enabled=" << CompatUtility::GetServiceFlapDetectionEnabled(service) << "\n"
373            << "\t" << "is_flapping=" << CompatUtility::GetServiceIsFlapping(service) << "\n"
374            << "\t" << "percent_state_change=" << CompatUtility::GetServicePercentStateChange(service) << "\n"
375            << "\t" << "problem_has_been_acknowledged=" << CompatUtility::GetServiceProblemHasBeenAcknowledged(service) << "\n"
376            << "\t" << "acknowledgement_type=" << CompatUtility::GetServiceAcknowledgementType(service) << "\n"
377            << "\t" << "acknowledgement_end_time=" << service->GetAcknowledgementExpiry() << "\n"
378            << "\t" << "scheduled_downtime_depth=" << service->GetDowntimeDepth() << "\n"
379            << "\t" << "last_notification=" << CompatUtility::GetServiceNotificationLastNotification(service) << "\n"
380            << "\t" << "next_notification=" << CompatUtility::GetServiceNotificationNextNotification(service) << "\n"
381            << "\t" << "current_notification_number=" << CompatUtility::GetServiceNotificationNotificationNumber(service) << "\n"
382            << "\t" << "modified_attributes=" << service->GetModifiedAttributes() << "\n";
383 }
384
385 void StatusDataWriter::DumpServiceStatus(std::ostream& fp, const Service::Ptr& service)
386 {
387         Host::Ptr host = service->GetHost();
388
389         fp << "servicestatus {" << "\n"
390            << "\t" << "host_name=" << host->GetName() << "\n"
391            << "\t" << "service_description=" << service->GetShortName() << "\n";
392
393         {
394                 ObjectLock olock(service);
395                 DumpServiceStatusAttrs(fp, service, CompatTypeService);
396         }
397
398         fp << "\t" << "}" << "\n"
399            << "\n";
400
401         DumpDowntimes(fp, service, CompatTypeService);
402         DumpComments(fp, service, CompatTypeService);
403 }
404
405 void StatusDataWriter::DumpServiceObject(std::ostream& fp, const Service::Ptr& service)
406 {
407         Host::Ptr host = service->GetHost();
408
409         {
410                 ObjectLock olock(service);
411
412                 fp << "define service {" << "\n"
413                    << "\t" << "host_name" << "\t" << host->GetName() << "\n"
414                    << "\t" << "service_description" << "\t" << service->GetShortName() << "\n"
415                    << "\t" << "display_name" << "\t" << service->GetDisplayName() << "\n"
416                    << "\t" << "check_period" << "\t" << CompatUtility::GetServiceCheckPeriod(service) << "\n"
417                    << "\t" << "check_interval" << "\t" << CompatUtility::GetServiceCheckInterval(service) << "\n"
418                    << "\t" << "retry_interval" << "\t" << CompatUtility::GetServiceRetryInterval(service) << "\n"
419                    << "\t" << "max_check_attempts" << "\t" << service->GetMaxCheckAttempts() << "\n"
420                    << "\t" << "active_checks_enabled" << "\t" << (service->GetEnableActiveChecks() ? 1 : 0) << "\n"
421                    << "\t" << "passive_checks_enabled" << "\t" << (service->GetEnablePassiveChecks() ? 1 : 0) << "\n"
422                    << "\t" << "flap_detection_enabled" << "\t" << (service->GetEnableFlapping() ? 1 : 0) << "\n"
423                    << "\t" << "is_volatile" << "\t" << (service->GetVolatile() ? 1 : 0) << "\n"
424                    << "\t" << "notifications_enabled" << "\t" << (service->GetEnableNotifications() ? 1 : 0) << "\n"
425                    << "\t" << "notification_options" << "\t" << CompatUtility::GetServiceNotificationNotificationOptions(service) << "\n"
426                    << "\t" << "notification_interval" << "\t" << CompatUtility::GetServiceNotificationNotificationInterval(service) << "\n"
427                    << "\t" << "notification_period" << "\t" << CompatUtility::GetServiceNotificationNotificationPeriod(service) << "\n"
428                    << "\t" << "event_handler_enabled" << "\t" << (service->GetEnableEventHandler() ? 1 : 0) << "\n";
429
430                 CheckCommand::Ptr checkcommand = service->GetCheckCommand();
431                 if (checkcommand)
432                         fp << "\t" << "check_command" << "\t" << "check_" << checkcommand->GetName() << "\n";
433
434                 EventCommand::Ptr eventcommand = service->GetEventCommand();
435                 if (eventcommand)
436                         fp << "\t" << "event_handler" << "\t" << "event_" << eventcommand->GetName() << "\n";
437
438                 fp << "\t" << "contacts" << "\t";
439                 DumpNameList(fp, CompatUtility::GetServiceNotificationUsers(service));
440                 fp << "\n";
441
442                 fp << "\t" << "contact_groups" << "\t";
443                 DumpNameList(fp, CompatUtility::GetServiceNotificationUserGroups(service));
444                 fp << "\n";
445
446                 fp << "\t" << "initial_state" << "\t" << "o" << "\n"
447                    << "\t" << "low_flap_threshold" << "\t" << service->GetFlappingThreshold() << "\n"
448                    << "\t" << "high_flap_threshold" << "\t" << service->GetFlappingThreshold() << "\n"
449                    << "\t" << "process_perf_data" << "\t" << 1 << "\n"
450                    << "\t" << "check_freshness" << "\t" << 1 << "\n"
451                    << "\t" << "notes" << "\t" << CompatUtility::GetCustomAttributeConfig(service, "notes") << "\n"
452                    << "\t" << "notes_url" << "\t" << CompatUtility::GetCustomAttributeConfig(service, "notes_url") << "\n"
453                    << "\t" << "action_url" << "\t" << CompatUtility::GetCustomAttributeConfig(service, "action_url") << "\n"
454                    << "\t" << "icon_image" << "\t" << CompatUtility::GetCustomAttributeConfig(service, "icon_image") << "\n"
455                    << "\t" << "icon_image_alt" << "\t" << CompatUtility::GetCustomAttributeConfig(service, "icon_image_alt") << "\n";
456         }
457
458         fp << "\t" << "service_groups" << "\t";
459         bool first = true;
460
461         Array::Ptr groups = service->GetGroups();
462
463         if (groups) {
464                 ObjectLock olock(groups);
465
466                 BOOST_FOREACH(const String& name, groups) {
467                         ServiceGroup::Ptr sg = ServiceGroup::GetByName(name);
468
469                         if (sg) {
470                                 if (!first)
471                                         fp << ",";
472                                 else
473                                         first = false;
474
475                                 fp << sg->GetName();
476                         }
477                 }
478         }
479
480         fp << "\n";
481
482         DumpCustomAttributes(fp, service);
483
484         fp << "\t" << "}" << "\n"
485            << "\n";
486
487         BOOST_FOREACH(const Service::Ptr& parent, service->GetParentServices()) {
488                 Host::Ptr host = service->GetHost();
489
490                 Host::Ptr parent_host = parent->GetHost();
491
492                 if (!parent_host)
493                         continue;
494
495                 fp << "define servicedependency {" << "\n"
496                    << "\t" << "dependent_host_name" << "\t" << host->GetName() << "\n"
497                    << "\t" << "dependent_service_description" << "\t" << service->GetShortName() << "\n"
498                    << "\t" << "host_name" << "\t" << parent_host->GetName() << "\n"
499                    << "\t" << "service_description" << "\t" << parent->GetShortName() << "\n"
500                    << "\t" << "execution_failure_criteria" << "\t" << "n" << "\n"
501                    << "\t" << "notification_failure_criteria" << "\t" << "w,u,c" << "\n"
502                    << "\t" << "}" << "\n"
503                    << "\n";
504         }
505 }
506
507 void StatusDataWriter::DumpCustomAttributes(std::ostream& fp, const DynamicObject::Ptr& object)
508 {
509         Dictionary::Ptr custom = object->GetCustom();
510
511         if (!custom)
512                 return;
513
514         ObjectLock olock(custom);
515         BOOST_FOREACH(const Dictionary::Pair& kv, custom) {
516                 if (!kv.first.IsEmpty()) {
517                         fp << "\t";
518
519                         if (kv.first != "notes" && kv.first != "action_url" && kv.first != "notes_url" &&
520                             kv.first != "icon_image" && kv.first != "icon_image_alt" && kv.first != "statusmap_image" && kv.first != "2d_coords")
521                                 fp << "_";
522
523                         fp << kv.first << "\t" << kv.second << "\n";
524                 }
525         }
526 }
527
528 void StatusDataWriter::UpdateObjectsCache(void)
529 {
530         CONTEXT("Writing objects.cache file");
531
532         String objectspath = GetObjectsPath();
533         String objectspathtmp = objectspath + ".tmp";
534
535         std::ofstream objectfp;
536         objectfp.open(objectspathtmp.CStr(), std::ofstream::out | std::ofstream::trunc);
537
538         objectfp << std::fixed;
539
540         objectfp << "# Icinga objects cache file" << "\n"
541                  << "# This file is auto-generated. Do not modify this file." << "\n"
542                  << "\n";
543
544         BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjects<Host>()) {
545                 std::ostringstream tempobjectfp;
546                 tempobjectfp << std::fixed;
547                 DumpHostObject(tempobjectfp, host);
548                 objectfp << tempobjectfp.str();
549         }
550
551         BOOST_FOREACH(const HostGroup::Ptr& hg, DynamicType::GetObjects<HostGroup>()) {
552                 std::ostringstream tempobjectfp;
553                 tempobjectfp << std::fixed;
554
555                 tempobjectfp << "define hostgroup {" << "\n"
556                          << "\t" << "hostgroup_name" << "\t" << hg->GetName() << "\n";
557
558                 DumpCustomAttributes(tempobjectfp, hg);
559
560                 tempobjectfp << "\t" << "members" << "\t";
561                 DumpNameList(tempobjectfp, hg->GetMembers());
562                 tempobjectfp << "\n"
563                              << "\t" << "}" << "\n";
564
565                 objectfp << tempobjectfp.str();
566         }
567
568         BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects<Service>()) {
569                 std::ostringstream tempobjectfp;
570                 tempobjectfp << std::fixed;
571                 DumpServiceObject(tempobjectfp, service);
572                 objectfp << tempobjectfp.str();
573         }
574
575         BOOST_FOREACH(const ServiceGroup::Ptr& sg, DynamicType::GetObjects<ServiceGroup>()) {
576                 std::ostringstream tempobjectfp;
577                 tempobjectfp << std::fixed;
578
579                 tempobjectfp << "define servicegroup {" << "\n"
580                          << "\t" << "servicegroup_name" << "\t" << sg->GetName() << "\n";
581
582                 DumpCustomAttributes(tempobjectfp, sg);
583
584                 tempobjectfp << "\t" << "members" << "\t";
585
586                 std::vector<String> sglist;
587                 BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
588                         Host::Ptr host = service->GetHost();
589
590                         sglist.push_back(host->GetName());
591                         sglist.push_back(service->GetShortName());
592                 }
593
594                 DumpStringList(tempobjectfp, sglist);
595
596                 tempobjectfp << "\n"
597                          << "}" << "\n";
598
599                 objectfp << tempobjectfp.str();
600         }
601
602         BOOST_FOREACH(const User::Ptr& user, DynamicType::GetObjects<User>()) {
603                 std::ostringstream tempobjectfp;
604                 tempobjectfp << std::fixed;
605
606                 tempobjectfp << "define contact {" << "\n"
607                          << "\t" << "contact_name" << "\t" << user->GetName() << "\n"
608                          << "\t" << "alias" << "\t" << user->GetDisplayName() << "\n"
609                          << "\t" << "service_notification_options" << "\t" << "w,u,c,r,f,s" << "\n"
610                          << "\t" << "host_notification_options" << "\t" << "d,u,r,f,s" << "\n"
611                          << "\t" << "host_notifications_enabled" << "\t" << 1 << "\n"
612                          << "\t" << "service_notifications_enabled" << "\t" << 1 << "\n"
613                          << "\t" << "}" << "\n"
614                          << "\n";
615
616                 objectfp << tempobjectfp.str();
617         }
618
619         BOOST_FOREACH(const UserGroup::Ptr& ug, DynamicType::GetObjects<UserGroup>()) {
620                 std::ostringstream tempobjectfp;
621                 tempobjectfp << std::fixed;
622
623                 tempobjectfp << "define contactgroup {" << "\n"
624                          << "\t" << "contactgroup_name" << "\t" << ug->GetName() << "\n"
625                          << "\t" << "alias" << "\t" << ug->GetDisplayName() << "\n";
626
627                 tempobjectfp << "\t" << "members" << "\t";
628                 DumpNameList(tempobjectfp, ug->GetMembers());
629                 tempobjectfp << "\n"
630                              << "\t" << "}" << "\n";
631
632                 objectfp << tempobjectfp.str();
633         }
634
635         BOOST_FOREACH(const Command::Ptr& command, DynamicType::GetObjects<CheckCommand>()) {
636                 DumpCommand(objectfp, command);
637         }
638
639         BOOST_FOREACH(const Command::Ptr& command, DynamicType::GetObjects<NotificationCommand>()) {
640                 DumpCommand(objectfp, command);
641         }
642
643         BOOST_FOREACH(const Command::Ptr& command, DynamicType::GetObjects<EventCommand>()) {
644                 DumpCommand(objectfp, command);
645         }
646
647         BOOST_FOREACH(const TimePeriod::Ptr& tp, DynamicType::GetObjects<TimePeriod>()) {
648                 DumpTimePeriod(objectfp, tp);
649         }
650
651         objectfp.close();
652
653 #ifdef _WIN32
654         _unlink(objectspath.CStr());
655 #endif /* _WIN32 */
656
657         if (rename(objectspathtmp.CStr(), objectspath.CStr()) < 0) {
658                 BOOST_THROW_EXCEPTION(posix_error()
659                     << boost::errinfo_api_function("rename")
660                     << boost::errinfo_errno(errno)
661                     << boost::errinfo_file_name(objectspathtmp));
662         }
663 }
664
665 /**
666  * Periodically writes the status.dat and objects.cache files.
667  */
668 void StatusDataWriter::StatusTimerHandler(void)
669 {
670         Log(LogInformation, "compat", "Writing status.dat file");
671
672         String statuspath = GetStatusPath();
673         String statuspathtmp = statuspath + ".tmp"; /* XXX make this a global definition */
674
675         std::ofstream statusfp;
676         statusfp.open(statuspathtmp.CStr(), std::ofstream::out | std::ofstream::trunc);
677
678         statusfp << std::fixed;
679
680         statusfp << "# Icinga status file" << "\n"
681                  << "# This file is auto-generated. Do not modify this file." << "\n"
682                  << "\n";
683
684         statusfp << "info {" << "\n"
685                  << "\t" << "created=" << Utility::GetTime() << "\n"
686                  << "\t" << "version=" << Application::GetVersion() << "\n"
687                  << "\t" << "}" << "\n"
688                  << "\n";
689
690         statusfp << "programstatus {" << "\n"
691                  << "\t" << "icinga_pid=" << Utility::GetPid() << "\n"
692                  << "\t" << "daemon_mode=1" << "\n"
693                  << "\t" << "program_start=" << static_cast<long>(Application::GetStartTime()) << "\n"
694                  << "\t" << "active_service_checks_enabled=" << (IcingaApplication::GetInstance()->GetEnableChecks() ? 1 : 0) << "\n"
695                  << "\t" << "passive_service_checks_enabled=1" << "\n"
696                  << "\t" << "active_host_checks_enabled=1" << "\n"
697                  << "\t" << "passive_host_checks_enabled=1" << "\n"
698                  << "\t" << "check_service_freshness=1" << "\n"
699                  << "\t" << "check_host_freshness=1" << "\n"
700                  << "\t" << "enable_notifications=" << (IcingaApplication::GetInstance()->GetEnableNotifications() ? 1 : 0) << "\n"
701                  << "\t" << "enable_flap_detection=" << (IcingaApplication::GetInstance()->GetEnableFlapping() ? 1 : 0) << "\n"
702                  << "\t" << "enable_failure_prediction=0" << "\n"
703                  << "\t" << "process_performance_data=" << (IcingaApplication::GetInstance()->GetEnablePerfdata() ? 1 : 0) << "\n"
704                  << "\t" << "active_scheduled_service_check_stats=" << CIB::GetActiveChecksStatistics(60) << "," << CIB::GetActiveChecksStatistics(5 * 60) << "," << CIB::GetActiveChecksStatistics(15 * 60) << "\n"
705                  << "\t" << "passive_service_check_stats=" << CIB::GetPassiveChecksStatistics(60) << "," << CIB::GetPassiveChecksStatistics(5 * 60) << "," << CIB::GetPassiveChecksStatistics(15 * 60) << "\n"
706                  << "\t" << "next_downtime_id=" << Service::GetNextDowntimeID() << "\n"
707                  << "\t" << "next_comment_id=" << Service::GetNextCommentID() << "\n"
708                  << "\t" << "}" << "\n"
709                  << "\n";
710
711         BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjects<Host>()) {
712                 std::ostringstream tempstatusfp;
713                 tempstatusfp << std::fixed;
714                 DumpHostStatus(tempstatusfp, host);
715                 statusfp << tempstatusfp.str();
716         }
717
718         BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects<Service>()) {
719                 std::ostringstream tempstatusfp;
720                 tempstatusfp << std::fixed;
721                 DumpServiceStatus(tempstatusfp, service);
722                 statusfp << tempstatusfp.str();
723         }
724
725         statusfp.close();
726
727 #ifdef _WIN32
728         _unlink(statuspath.CStr());
729 #endif /* _WIN32 */
730
731         if (rename(statuspathtmp.CStr(), statuspath.CStr()) < 0) {
732                 BOOST_THROW_EXCEPTION(posix_error()
733                     << boost::errinfo_api_function("rename")
734                     << boost::errinfo_errno(errno)
735                     << boost::errinfo_file_name(statuspathtmp));
736         }
737
738         Log(LogInformation, "compat", "Finished writing status.dat file");
739 }
740