1 /******************************************************************************
3 * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
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. *
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. *
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 ******************************************************************************/
20 #include "compat/statusdatawriter.hpp"
21 #include "compat/statusdatawriter.tcpp"
22 #include "icinga/icingaapplication.hpp"
23 #include "icinga/cib.hpp"
24 #include "icinga/hostgroup.hpp"
25 #include "icinga/servicegroup.hpp"
26 #include "icinga/checkcommand.hpp"
27 #include "icinga/eventcommand.hpp"
28 #include "icinga/timeperiod.hpp"
29 #include "icinga/notificationcommand.hpp"
30 #include "icinga/compatutility.hpp"
31 #include "icinga/dependency.hpp"
32 #include "base/configtype.hpp"
33 #include "base/objectlock.hpp"
34 #include "base/json.hpp"
35 #include "base/convert.hpp"
36 #include "base/logger.hpp"
37 #include "base/exception.hpp"
38 #include "base/application.hpp"
39 #include "base/context.hpp"
40 #include "base/statsfunction.hpp"
41 #include <boost/tuple/tuple.hpp>
42 #include <boost/algorithm/string.hpp>
43 #include <boost/algorithm/string/replace.hpp>
46 using namespace icinga;
48 REGISTER_TYPE(StatusDataWriter);
50 REGISTER_STATSFUNCTION(StatusDataWriter, &StatusDataWriter::StatsFunc);
52 void StatusDataWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
54 Dictionary::Ptr nodes = new Dictionary();
56 for (const StatusDataWriter::Ptr& statusdatawriter : ConfigType::GetObjectsByType<StatusDataWriter>()) {
57 nodes->Set(statusdatawriter->GetName(), 1); //add more stats
60 status->Set("statusdatawriter", nodes);
64 * Hint: The reason why we're using "\n" rather than std::endl is because
65 * std::endl also _flushes_ the output stream which severely degrades
66 * performance (see https://stackoverflow.com/questions/213907/c-stdendl-vs-n).
70 * Starts the component.
72 void StatusDataWriter::Start(bool runtimeCreated)
74 ObjectImpl<StatusDataWriter>::Start(runtimeCreated);
76 Log(LogInformation, "StatusDataWriter")
77 << "'" << GetName() << "' started.";
79 m_ObjectsCacheOutdated = true;
81 m_StatusTimer = new Timer();
82 m_StatusTimer->SetInterval(GetUpdateInterval());
83 m_StatusTimer->OnTimerExpired.connect(std::bind(&StatusDataWriter::StatusTimerHandler, this));
84 m_StatusTimer->Start();
85 m_StatusTimer->Reschedule(0);
87 ConfigObject::OnVersionChanged.connect(std::bind(&StatusDataWriter::ObjectHandler, this));
88 ConfigObject::OnActiveChanged.connect(std::bind(&StatusDataWriter::ObjectHandler, this));
92 * Stops the component.
94 void StatusDataWriter::Stop(bool runtimeRemoved)
96 Log(LogInformation, "StatusDataWriter")
97 << "'" << GetName() << "' stopped.";
99 ObjectImpl<StatusDataWriter>::Stop(runtimeRemoved);
102 void StatusDataWriter::DumpComments(std::ostream& fp, const Checkable::Ptr& checkable)
105 Service::Ptr service;
106 tie(host, service) = GetHostService(checkable);
108 for (const Comment::Ptr& comment : checkable->GetComments()) {
109 if (comment->IsExpired())
113 fp << "servicecomment {" << "\n"
114 << "\t" << "service_description=" << service->GetShortName() << "\n";
116 fp << "hostcomment {" << "\n";
118 fp << "\t" "host_name=" << host->GetName() << "\n"
119 "\t" "comment_id=" << comment->GetLegacyId() << "\n"
120 "\t" "entry_time=" << comment->GetEntryTime() << "\n"
121 "\t" "entry_type=" << comment->GetEntryType() << "\n"
122 "\t" "persistent=" "1" "\n"
123 "\t" "author=" << comment->GetAuthor() << "\n"
124 "\t" "comment_data=" << comment->GetText() << "\n"
125 "\t" "expires=" << (comment->GetExpireTime() != 0 ? 1 : 0) << "\n"
126 "\t" "expire_time=" << comment->GetExpireTime() << "\n"
132 void StatusDataWriter::DumpTimePeriod(std::ostream& fp, const TimePeriod::Ptr& tp)
134 fp << "define timeperiod {" "\n"
135 "\t" "timeperiod_name" "\t" << tp->GetName() << "\n"
136 "\t" "alias" "\t" << tp->GetName() << "\n";
138 Dictionary::Ptr ranges = tp->GetRanges();
141 ObjectLock olock(ranges);
142 for (const Dictionary::Pair& kv : ranges) {
143 fp << "\t" << kv.first << "\t" << kv.second << "\n";
147 fp << "\t" "}" "\n" "\n";
150 void StatusDataWriter::DumpCommand(std::ostream& fp, const Command::Ptr& command)
152 fp << "define command {" "\n"
153 "\t" "command_name\t";
155 fp << CompatUtility::GetCommandName(command) << "\n";
157 fp << "\t" "command_line" "\t" << CompatUtility::GetCommandLine(command);
161 DumpCustomAttributes(fp, command);
163 fp << "\n" "\t" "}" "\n" "\n";
166 void StatusDataWriter::DumpDowntimes(std::ostream& fp, const Checkable::Ptr& checkable)
169 Service::Ptr service;
170 tie(host, service) = GetHostService(checkable);
172 for (const Downtime::Ptr& downtime : checkable->GetDowntimes()) {
173 if (downtime->IsExpired())
177 fp << "servicedowntime {" << "\n"
178 "\t" "service_description=" << service->GetShortName() << "\n";
180 fp << "hostdowntime {" "\n";
182 Downtime::Ptr triggeredByObj = Downtime::GetByName(downtime->GetTriggeredBy());
183 int triggeredByLegacy = 0;
185 triggeredByLegacy = triggeredByObj->GetLegacyId();
187 fp << "\t" << "host_name=" << host->GetName() << "\n"
188 "\t" "downtime_id=" << downtime->GetLegacyId() << "\n"
189 "\t" "entry_time=" << downtime->GetEntryTime() << "\n"
190 "\t" "start_time=" << downtime->GetStartTime() << "\n"
191 "\t" "end_time=" << downtime->GetEndTime() << "\n"
192 "\t" "triggered_by=" << triggeredByLegacy << "\n"
193 "\t" "fixed=" << static_cast<long>(downtime->GetFixed()) << "\n"
194 "\t" "duration=" << static_cast<long>(downtime->GetDuration()) << "\n"
195 "\t" "is_in_effect=" << (downtime->IsInEffect() ? 1 : 0) << "\n"
196 "\t" "author=" << downtime->GetAuthor() << "\n"
197 "\t" "comment=" << downtime->GetComment() << "\n"
198 "\t" "trigger_time=" << downtime->GetTriggerTime() << "\n"
204 void StatusDataWriter::DumpHostStatus(std::ostream& fp, const Host::Ptr& host)
206 fp << "hoststatus {" "\n" "\t" "host_name=" << host->GetName() << "\n";
209 ObjectLock olock(host);
210 DumpCheckableStatusAttrs(fp, host);
213 /* ugly but cgis parse only that */
214 fp << "\t" "last_time_up=" << host->GetLastStateUp() << "\n"
215 "\t" "last_time_down=" << host->GetLastStateDown() << "\n"
216 "\t" "last_time_unreachable=" << host->GetLastStateUnreachable() << "\n";
218 fp << "\t" "}" "\n" "\n";
220 DumpDowntimes(fp, host);
221 DumpComments(fp, host);
224 void StatusDataWriter::DumpHostObject(std::ostream& fp, const Host::Ptr& host)
226 String notes = host->GetNotes();
227 String notes_url = host->GetNotesUrl();
228 String action_url = host->GetActionUrl();
229 String icon_image = host->GetIconImage();
230 String icon_image_alt = host->GetIconImageAlt();
231 String display_name = host->GetDisplayName();
232 String address = host->GetAddress();
233 String address6 = host->GetAddress6();
235 fp << "define host {" "\n"
236 "\t" "host_name" "\t" << host->GetName() << "\n";
237 if (!display_name.IsEmpty()) {
238 fp << "\t" "display_name" "\t" << host->GetDisplayName() << "\n"
239 "\t" "alias" "\t" << host->GetDisplayName() << "\n";
241 if (!address.IsEmpty())
242 fp << "\t" "address" "\t" << address << "\n";
243 if (!address6.IsEmpty())
244 fp << "\t" "address6" "\t" << address6 << "\n";
245 if (!notes.IsEmpty())
246 fp << "\t" "notes" "\t" << notes << "\n";
247 if (!notes_url.IsEmpty())
248 fp << "\t" "notes_url" "\t" << notes_url << "\n";
249 if (!action_url.IsEmpty())
250 fp << "\t" "action_url" "\t" << action_url << "\n";
251 if (!icon_image.IsEmpty())
252 fp << "\t" "icon_image" "\t" << icon_image << "\n";
253 if (!icon_image_alt.IsEmpty())
254 fp << "\t" "icon_image_alt" "\t" << icon_image_alt << "\n";
256 std::set<Checkable::Ptr> parents = host->GetParents();
258 if (!parents.empty()) {
259 fp << "\t" "parents" "\t";
260 DumpNameList(fp, parents);
264 ObjectLock olock(host);
266 fp << "\t" "check_interval" "\t" << CompatUtility::GetCheckableCheckInterval(host) << "\n"
267 "\t" "retry_interval" "\t" << CompatUtility::GetCheckableRetryInterval(host) << "\n"
268 "\t" "max_check_attempts" "\t" << host->GetMaxCheckAttempts() << "\n"
269 "\t" "active_checks_enabled" "\t" << CompatUtility::GetCheckableActiveChecksEnabled(host) << "\n"
270 "\t" "passive_checks_enabled" "\t" << CompatUtility::GetCheckablePassiveChecksEnabled(host) << "\n"
271 "\t" "notifications_enabled" "\t" << CompatUtility::GetCheckableNotificationsEnabled(host) << "\n"
272 "\t" "notification_options" "\t" << CompatUtility::GetCheckableNotificationNotificationOptions(host) << "\n"
273 "\t" "notification_interval" "\t" << CompatUtility::GetCheckableNotificationNotificationInterval(host) << "\n"
274 "\t" "event_handler_enabled" "\t" << CompatUtility::GetCheckableEventHandlerEnabled(host) << "\n";
276 CheckCommand::Ptr checkcommand = host->GetCheckCommand();
278 fp << "\t" "check_command" "\t" << CompatUtility::GetCommandName(checkcommand) << "!" << CompatUtility::GetCheckableCommandArgs(host) << "\n";
280 EventCommand::Ptr eventcommand = host->GetEventCommand();
281 if (eventcommand && host->GetEnableEventHandler())
282 fp << "\t" "event_handler" "\t" << CompatUtility::GetCommandName(eventcommand) << "\n";
284 fp << "\t" "check_period" "\t" << CompatUtility::GetCheckableCheckPeriod(host) << "\n";
286 fp << "\t" "contacts" "\t";
287 DumpNameList(fp, CompatUtility::GetCheckableNotificationUsers(host));
290 fp << "\t" "contact_groups" "\t";
291 DumpNameList(fp, CompatUtility::GetCheckableNotificationUserGroups(host));
294 fp << "\t" << "initial_state" "\t" "o" "\n"
295 "\t" "low_flap_threshold" "\t" << host->GetFlappingThresholdLow() << "\n"
296 "\t" "high_flap_threshold" "\t" << host->GetFlappingThresholdHigh() << "\n"
297 "\t" "process_perf_data" "\t" << CompatUtility::GetCheckableProcessPerformanceData(host) << "\n"
298 "\t" "check_freshness" "\t" "1" "\n";
300 fp << "\t" "host_groups" "\t";
303 Array::Ptr groups = host->GetGroups();
306 ObjectLock olock(groups);
308 for (const String& name : groups) {
309 HostGroup::Ptr hg = HostGroup::GetByName(name);
324 DumpCustomAttributes(fp, host);
326 fp << "\t" "}" "\n" "\n";
329 void StatusDataWriter::DumpCheckableStatusAttrs(std::ostream& fp, const Checkable::Ptr& checkable)
331 CheckResult::Ptr cr = checkable->GetLastCheckResult();
333 EventCommand::Ptr eventcommand = checkable->GetEventCommand();
334 CheckCommand::Ptr checkcommand = checkable->GetCheckCommand();
336 fp << "\t" << "check_command=" << CompatUtility::GetCommandName(checkcommand) << "!" << CompatUtility::GetCheckableCommandArgs(checkable) << "\n"
337 "\t" "event_handler=" << CompatUtility::GetCommandName(eventcommand) << "\n"
338 "\t" "check_period=" << CompatUtility::GetCheckableCheckPeriod(checkable) << "\n"
339 "\t" "check_interval=" << CompatUtility::GetCheckableCheckInterval(checkable) << "\n"
340 "\t" "retry_interval=" << CompatUtility::GetCheckableRetryInterval(checkable) << "\n"
341 "\t" "has_been_checked=" << CompatUtility::GetCheckableHasBeenChecked(checkable) << "\n"
342 "\t" "should_be_scheduled=" << checkable->GetEnableActiveChecks() << "\n"
343 "\t" "event_handler_enabled=" << CompatUtility::GetCheckableEventHandlerEnabled(checkable) << "\n";
346 fp << "\t" << "check_execution_time=" << Convert::ToString(cr->CalculateExecutionTime()) << "\n"
347 "\t" "check_latency=" << Convert::ToString(cr->CalculateLatency()) << "\n";
351 Service::Ptr service;
352 tie(host, service) = GetHostService(checkable);
355 fp << "\t" "current_state=" << service->GetState() << "\n"
356 "\t" "last_hard_state=" << service->GetLastHardState() << "\n"
357 "\t" "last_time_ok=" << static_cast<int>(service->GetLastStateOK()) << "\n"
358 "\t" "last_time_warn=" << static_cast<int>(service->GetLastStateWarning()) << "\n"
359 "\t" "last_time_critical=" << static_cast<int>(service->GetLastStateCritical()) << "\n"
360 "\t" "last_time_unknown=" << static_cast<int>(service->GetLastStateUnknown()) << "\n";
362 fp << "\t" "current_state=" << CompatUtility::GetHostCurrentState(host) << "\n"
363 "\t" "last_hard_state=" << host->GetLastHardState() << "\n"
364 "\t" "last_time_up=" << static_cast<int>(host->GetLastStateUp()) << "\n"
365 "\t" "last_time_down=" << static_cast<int>(host->GetLastStateDown()) << "\n";
368 fp << "\t" "state_type=" << checkable->GetStateType() << "\n"
369 "\t" "plugin_output=" << CompatUtility::GetCheckResultOutput(cr) << "\n"
370 "\t" "long_plugin_output=" << CompatUtility::GetCheckResultLongOutput(cr) << "\n"
371 "\t" "performance_data=" << CompatUtility::GetCheckResultPerfdata(cr) << "\n";
374 fp << "\t" << "check_source=" << cr->GetCheckSource() << "\n"
375 "\t" "last_check=" << static_cast<long>(cr->GetScheduleEnd()) << "\n";
378 fp << "\t" << "next_check=" << static_cast<long>(checkable->GetNextCheck()) << "\n"
379 "\t" "current_attempt=" << checkable->GetCheckAttempt() << "\n"
380 "\t" "max_attempts=" << checkable->GetMaxCheckAttempts() << "\n"
381 "\t" "last_state_change=" << static_cast<long>(checkable->GetLastStateChange()) << "\n"
382 "\t" "last_hard_state_change=" << static_cast<long>(checkable->GetLastHardStateChange()) << "\n"
383 "\t" "last_update=" << static_cast<long>(time(nullptr)) << "\n"
384 "\t" "notifications_enabled=" << CompatUtility::GetCheckableNotificationsEnabled(checkable) << "\n"
385 "\t" "active_checks_enabled=" << CompatUtility::GetCheckableActiveChecksEnabled(checkable) << "\n"
386 "\t" "passive_checks_enabled=" << CompatUtility::GetCheckablePassiveChecksEnabled(checkable) << "\n"
387 "\t" "flap_detection_enabled=" << CompatUtility::GetCheckableFlapDetectionEnabled(checkable) << "\n"
388 "\t" "is_flapping=" << CompatUtility::GetCheckableIsFlapping(checkable) << "\n"
389 "\t" "percent_state_change=" << CompatUtility::GetCheckablePercentStateChange(checkable) << "\n"
390 "\t" "problem_has_been_acknowledged=" << CompatUtility::GetCheckableProblemHasBeenAcknowledged(checkable) << "\n"
391 "\t" "acknowledgement_type=" << CompatUtility::GetCheckableAcknowledgementType(checkable) << "\n"
392 "\t" "acknowledgement_end_time=" << checkable->GetAcknowledgementExpiry() << "\n"
393 "\t" "scheduled_downtime_depth=" << checkable->GetDowntimeDepth() << "\n"
394 "\t" "last_notification=" << CompatUtility::GetCheckableNotificationLastNotification(checkable) << "\n"
395 "\t" "next_notification=" << CompatUtility::GetCheckableNotificationNextNotification(checkable) << "\n"
396 "\t" "current_notification_number=" << CompatUtility::GetCheckableNotificationNotificationNumber(checkable) << "\n"
397 "\t" "is_reachable=" << CompatUtility::GetCheckableIsReachable(checkable) << "\n";
400 void StatusDataWriter::DumpServiceStatus(std::ostream& fp, const Service::Ptr& service)
402 Host::Ptr host = service->GetHost();
404 fp << "servicestatus {" "\n"
405 "\t" "host_name=" << host->GetName() << "\n"
406 "\t" "service_description=" << service->GetShortName() << "\n";
409 ObjectLock olock(service);
410 DumpCheckableStatusAttrs(fp, service);
413 fp << "\t" "}" "\n" "\n";
415 DumpDowntimes(fp, service);
416 DumpComments(fp, service);
419 void StatusDataWriter::DumpServiceObject(std::ostream& fp, const Service::Ptr& service)
421 Host::Ptr host = service->GetHost();
424 ObjectLock olock(service);
426 fp << "define service {" "\n"
427 "\t" "host_name" "\t" << host->GetName() << "\n"
428 "\t" "service_description" "\t" << service->GetShortName() << "\n"
429 "\t" "display_name" "\t" << service->GetDisplayName() << "\n"
430 "\t" "check_period" "\t" << CompatUtility::GetCheckableCheckPeriod(service) << "\n"
431 "\t" "check_interval" "\t" << CompatUtility::GetCheckableCheckInterval(service) << "\n"
432 "\t" "retry_interval" "\t" << CompatUtility::GetCheckableRetryInterval(service) << "\n"
433 "\t" "max_check_attempts" "\t" << service->GetMaxCheckAttempts() << "\n"
434 "\t" "active_checks_enabled" "\t" << CompatUtility::GetCheckableActiveChecksEnabled(service) << "\n"
435 "\t" "passive_checks_enabled" "\t" << CompatUtility::GetCheckablePassiveChecksEnabled(service) << "\n"
436 "\t" "flap_detection_enabled" "\t" << CompatUtility::GetCheckableFlapDetectionEnabled(service) << "\n"
437 "\t" "is_volatile" "\t" << CompatUtility::GetCheckableIsVolatile(service) << "\n"
438 "\t" "notifications_enabled" "\t" << CompatUtility::GetCheckableNotificationsEnabled(service) << "\n"
439 "\t" "notification_options" "\t" << CompatUtility::GetCheckableNotificationNotificationOptions(service) << "\n"
440 "\t" "notification_interval" "\t" << CompatUtility::GetCheckableNotificationNotificationInterval(service) << "\n"
441 "\t" "notification_period" "\t" << "" << "\n"
442 "\t" "event_handler_enabled" "\t" << CompatUtility::GetCheckableEventHandlerEnabled(service) << "\n";
444 CheckCommand::Ptr checkcommand = service->GetCheckCommand();
446 fp << "\t" "check_command" "\t" << CompatUtility::GetCommandName(checkcommand) << "!" << CompatUtility::GetCheckableCommandArgs(service)<< "\n";
448 EventCommand::Ptr eventcommand = service->GetEventCommand();
449 if (eventcommand && service->GetEnableEventHandler())
450 fp << "\t" "event_handler" "\t" << CompatUtility::GetCommandName(eventcommand) << "\n";
452 fp << "\t" "contacts" "\t";
453 DumpNameList(fp, CompatUtility::GetCheckableNotificationUsers(service));
456 fp << "\t" "contact_groups" "\t";
457 DumpNameList(fp, CompatUtility::GetCheckableNotificationUserGroups(service));
460 String notes = service->GetNotes();
461 String notes_url = service->GetNotesUrl();
462 String action_url = service->GetActionUrl();
463 String icon_image = service->GetIconImage();
464 String icon_image_alt = service->GetIconImageAlt();
466 fp << "\t" "initial_state" "\t" "o" "\n"
467 "\t" "low_flap_threshold" "\t" << service->GetFlappingThresholdLow() << "\n"
468 "\t" "high_flap_threshold" "\t" << service->GetFlappingThresholdHigh() << "\n"
469 "\t" "process_perf_data" "\t" << CompatUtility::GetCheckableProcessPerformanceData(service) << "\n"
470 "\t" "check_freshness" << "\t" "1" "\n";
471 if (!notes.IsEmpty())
472 fp << "\t" "notes" "\t" << notes << "\n";
473 if (!notes_url.IsEmpty())
474 fp << "\t" "notes_url" "\t" << notes_url << "\n";
475 if (!action_url.IsEmpty())
476 fp << "\t" "action_url" "\t" << action_url << "\n";
477 if (!icon_image.IsEmpty())
478 fp << "\t" "icon_image" "\t" << icon_image << "\n";
479 if (!icon_image_alt.IsEmpty())
480 fp << "\t" "icon_image_alt" "\t" << icon_image_alt << "\n";
483 fp << "\t" "service_groups" "\t";
486 Array::Ptr groups = service->GetGroups();
489 ObjectLock olock(groups);
491 for (const String& name : groups) {
492 ServiceGroup::Ptr sg = ServiceGroup::GetByName(name);
507 DumpCustomAttributes(fp, service);
509 fp << "\t" "}" "\n" "\n";
512 void StatusDataWriter::DumpCustomAttributes(std::ostream& fp, const CustomVarObject::Ptr& object)
514 Dictionary::Ptr vars = object->GetVars();
519 bool is_json = false;
521 ObjectLock olock(vars);
522 for (const Dictionary::Pair& kv : vars) {
523 if (kv.first.IsEmpty())
528 if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>()) {
529 value = JsonEncode(kv.second);
532 value = CompatUtility::EscapeString(kv.second);
534 fp << "\t" "_" << kv.first << "\t" << value << "\n";
538 fp << "\t" "_is_json" "\t" "1" "\n";
541 void StatusDataWriter::UpdateObjectsCache()
543 CONTEXT("Writing objects.cache file");
545 String objectsPath = GetObjectsPath();
547 std::fstream objectfp;
548 String tempObjectsPath = Utility::CreateTempFile(objectsPath + ".XXXXXX", 0644, objectfp);
550 objectfp << std::fixed;
552 objectfp << "# Icinga objects cache file" "\n"
553 "# This file is auto-generated. Do not modify this file." "\n"
556 for (const Host::Ptr& host : ConfigType::GetObjectsByType<Host>()) {
557 std::ostringstream tempobjectfp;
558 tempobjectfp << std::fixed;
559 DumpHostObject(tempobjectfp, host);
560 objectfp << tempobjectfp.str();
562 for (const Service::Ptr& service : host->GetServices()) {
563 std::ostringstream tempobjectfp;
564 tempobjectfp << std::fixed;
565 DumpServiceObject(tempobjectfp, service);
566 objectfp << tempobjectfp.str();
570 for (const HostGroup::Ptr& hg : ConfigType::GetObjectsByType<HostGroup>()) {
571 std::ostringstream tempobjectfp;
572 tempobjectfp << std::fixed;
574 String display_name = hg->GetDisplayName();
575 String notes = hg->GetNotes();
576 String notes_url = hg->GetNotesUrl();
577 String action_url = hg->GetActionUrl();
579 tempobjectfp << "define hostgroup {" "\n"
580 "\t" "hostgroup_name" "\t" << hg->GetName() << "\n";
582 if (!display_name.IsEmpty())
583 tempobjectfp << "\t" "alias" "\t" << display_name << "\n";
584 if (!notes.IsEmpty())
585 tempobjectfp << "\t" "notes" "\t" << notes << "\n";
586 if (!notes_url.IsEmpty())
587 tempobjectfp << "\t" "notes_url" "\t" << notes_url << "\n";
588 if (!action_url.IsEmpty())
589 tempobjectfp << "\t" "action_url" "\t" << action_url << "\n";
591 DumpCustomAttributes(tempobjectfp, hg);
593 tempobjectfp << "\t" "members" "\t";
594 DumpNameList(tempobjectfp, hg->GetMembers());
595 tempobjectfp << "\n" "\t" "}" "\n";
597 objectfp << tempobjectfp.str();
600 for (const ServiceGroup::Ptr& sg : ConfigType::GetObjectsByType<ServiceGroup>()) {
601 std::ostringstream tempobjectfp;
602 tempobjectfp << std::fixed;
604 String display_name = sg->GetDisplayName();
605 String notes = sg->GetNotes();
606 String notes_url = sg->GetNotesUrl();
607 String action_url = sg->GetActionUrl();
609 tempobjectfp << "define servicegroup {" "\n"
610 "\t" "servicegroup_name" "\t" << sg->GetName() << "\n";
612 if (!display_name.IsEmpty())
613 tempobjectfp << "\t" "alias" "\t" << display_name << "\n";
614 if (!notes.IsEmpty())
615 tempobjectfp << "\t" "notes" "\t" << notes << "\n";
616 if (!notes_url.IsEmpty())
617 tempobjectfp << "\t" "notes_url" "\t" << notes_url << "\n";
618 if (!action_url.IsEmpty())
619 tempobjectfp << "\t" "action_url" "\t" << action_url << "\n";
621 DumpCustomAttributes(tempobjectfp, sg);
623 tempobjectfp << "\t" "members" "\t";
625 std::vector<String> sglist;
626 for (const Service::Ptr& service : sg->GetMembers()) {
627 Host::Ptr host = service->GetHost();
629 sglist.emplace_back(host->GetName());
630 sglist.emplace_back(service->GetShortName());
633 DumpStringList(tempobjectfp, sglist);
635 tempobjectfp << "\n" "}" "\n";
637 objectfp << tempobjectfp.str();
640 for (const User::Ptr& user : ConfigType::GetObjectsByType<User>()) {
641 std::ostringstream tempobjectfp;
642 tempobjectfp << std::fixed;
644 String email = user->GetEmail();
645 String pager = user->GetPager();
646 String alias = user->GetDisplayName();
648 tempobjectfp << "define contact {" "\n"
649 "\t" "contact_name" "\t" << user->GetName() << "\n";
651 if (!alias.IsEmpty())
652 tempobjectfp << "\t" "alias" "\t" << alias << "\n";
653 if (!email.IsEmpty())
654 tempobjectfp << "\t" "email" "\t" << email << "\n";
655 if (!pager.IsEmpty())
656 tempobjectfp << "\t" "pager" "\t" << pager << "\n";
658 tempobjectfp << "\t" "service_notification_options" "\t" "w,u,c,r,f,s" "\n"
659 "\t" "host_notification_options""\t" "d,u,r,f,s" "\n"
660 "\t" "host_notifications_enabled" "\t" "1" "\n"
661 "\t" "service_notifications_enabled" "\t" "1" "\n"
665 objectfp << tempobjectfp.str();
668 for (const UserGroup::Ptr& ug : ConfigType::GetObjectsByType<UserGroup>()) {
669 std::ostringstream tempobjectfp;
670 tempobjectfp << std::fixed;
672 tempobjectfp << "define contactgroup {" "\n"
673 "\t" "contactgroup_name" "\t" << ug->GetName() << "\n"
674 "\t" "alias" "\t" << ug->GetDisplayName() << "\n";
676 tempobjectfp << "\t" "members" "\t";
677 DumpNameList(tempobjectfp, ug->GetMembers());
681 objectfp << tempobjectfp.str();
684 for (const Command::Ptr& command : ConfigType::GetObjectsByType<CheckCommand>()) {
685 DumpCommand(objectfp, command);
688 for (const Command::Ptr& command : ConfigType::GetObjectsByType<NotificationCommand>()) {
689 DumpCommand(objectfp, command);
692 for (const Command::Ptr& command : ConfigType::GetObjectsByType<EventCommand>()) {
693 DumpCommand(objectfp, command);
696 for (const TimePeriod::Ptr& tp : ConfigType::GetObjectsByType<TimePeriod>()) {
697 DumpTimePeriod(objectfp, tp);
700 for (const Dependency::Ptr& dep : ConfigType::GetObjectsByType<Dependency>()) {
701 Checkable::Ptr parent = dep->GetParent();
704 Log(LogDebug, "StatusDataWriter")
705 << "Missing parent for dependency '" << dep->GetName() << "'.";
709 Host::Ptr parent_host;
710 Service::Ptr parent_service;
711 tie(parent_host, parent_service) = GetHostService(parent);
713 Checkable::Ptr child = dep->GetChild();
716 Log(LogDebug, "StatusDataWriter")
717 << "Missing child for dependency '" << dep->GetName() << "'.";
721 Host::Ptr child_host;
722 Service::Ptr child_service;
723 tie(child_host, child_service) = GetHostService(child);
725 int state_filter = dep->GetStateFilter();
726 std::vector<String> failure_criteria;
727 if (state_filter & StateFilterOK || state_filter & StateFilterUp)
728 failure_criteria.emplace_back("o");
729 if (state_filter & StateFilterWarning)
730 failure_criteria.emplace_back("w");
731 if (state_filter & StateFilterCritical)
732 failure_criteria.emplace_back("c");
733 if (state_filter & StateFilterUnknown)
734 failure_criteria.emplace_back("u");
735 if (state_filter & StateFilterDown)
736 failure_criteria.emplace_back("d");
738 String criteria = boost::algorithm::join(failure_criteria, ",");
740 /* Icinga 1.x only allows host->host, service->service dependencies */
741 if (!child_service && !parent_service) {
742 objectfp << "define hostdependency {" "\n"
743 "\t" "dependent_host_name" "\t" << child_host->GetName() << "\n"
744 "\t" "host_name" "\t" << parent_host->GetName() << "\n"
745 "\t" "execution_failure_criteria" "\t" << criteria << "\n"
746 "\t" "notification_failure_criteria" "\t" << criteria << "\n"
749 } else if (child_service && parent_service){
751 objectfp << "define servicedependency {" "\n"
752 "\t" "dependent_host_name" "\t" << child_service->GetHost()->GetName() << "\n"
753 "\t" "dependent_service_description" "\t" << child_service->GetShortName() << "\n"
754 "\t" "host_name" "\t" << parent_service->GetHost()->GetName() << "\n"
755 "\t" "service_description" "\t" << parent_service->GetShortName() << "\n"
756 "\t" "execution_failure_criteria" "\t" << criteria << "\n"
757 "\t" "notification_failure_criteria" "\t" << criteria << "\n"
766 _unlink(objectsPath.CStr());
769 if (rename(tempObjectsPath.CStr(), objectsPath.CStr()) < 0) {
770 BOOST_THROW_EXCEPTION(posix_error()
771 << boost::errinfo_api_function("rename")
772 << boost::errinfo_errno(errno)
773 << boost::errinfo_file_name(tempObjectsPath));
778 * Periodically writes the status.dat and objects.cache files.
780 void StatusDataWriter::StatusTimerHandler()
782 if (m_ObjectsCacheOutdated) {
783 UpdateObjectsCache();
784 m_ObjectsCacheOutdated = false;
787 double start = Utility::GetTime();
789 String statusPath = GetStatusPath();
791 std::fstream statusfp;
792 String tempStatusPath = Utility::CreateTempFile(statusPath + ".XXXXXX", 0644, statusfp);
794 statusfp << std::fixed;
796 statusfp << "# Icinga status file" "\n"
797 "# This file is auto-generated. Do not modify this file." "\n"
800 statusfp << "info {" "\n"
801 "\t" "created=" << Utility::GetTime() << "\n"
802 "\t" "version=" << Application::GetAppVersion() << "\n"
806 statusfp << "programstatus {" "\n"
807 "\t" "icinga_pid=" << Utility::GetPid() << "\n"
808 "\t" "daemon_mode=1" "\n"
809 "\t" "program_start=" << static_cast<long>(Application::GetStartTime()) << "\n"
810 "\t" "active_host_checks_enabled=" << (IcingaApplication::GetInstance()->GetEnableHostChecks() ? 1 : 0) << "\n"
811 "\t" "passive_host_checks_enabled=1" "\n"
812 "\t" "active_service_checks_enabled=" << (IcingaApplication::GetInstance()->GetEnableServiceChecks() ? 1 : 0) << "\n"
813 "\t" "passive_service_checks_enabled=1" "\n"
814 "\t" "check_service_freshness=1" "\n"
815 "\t" "check_host_freshness=1" "\n"
816 "\t" "enable_notifications=" << (IcingaApplication::GetInstance()->GetEnableNotifications() ? 1 : 0) << "\n"
817 "\t" "enable_event_handlers=" << (IcingaApplication::GetInstance()->GetEnableEventHandlers() ? 1 : 0) << "\n"
818 "\t" "enable_flap_detection=" << (IcingaApplication::GetInstance()->GetEnableFlapping() ? 1 : 0) << "\n"
819 "\t" "enable_failure_prediction=0" "\n"
820 "\t" "process_performance_data=" << (IcingaApplication::GetInstance()->GetEnablePerfdata() ? 1 : 0) << "\n"
821 "\t" "active_scheduled_host_check_stats=" << CIB::GetActiveHostChecksStatistics(60) << "," << CIB::GetActiveHostChecksStatistics(5 * 60) << "," << CIB::GetActiveHostChecksStatistics(15 * 60) << "\n"
822 "\t" "passive_host_check_stats=" << CIB::GetPassiveHostChecksStatistics(60) << "," << CIB::GetPassiveHostChecksStatistics(5 * 60) << "," << CIB::GetPassiveHostChecksStatistics(15 * 60) << "\n"
823 "\t" "active_scheduled_service_check_stats=" << CIB::GetActiveServiceChecksStatistics(60) << "," << CIB::GetActiveServiceChecksStatistics(5 * 60) << "," << CIB::GetActiveServiceChecksStatistics(15 * 60) << "\n"
824 "\t" "passive_service_check_stats=" << CIB::GetPassiveServiceChecksStatistics(60) << "," << CIB::GetPassiveServiceChecksStatistics(5 * 60) << "," << CIB::GetPassiveServiceChecksStatistics(15 * 60) << "\n"
825 "\t" "next_downtime_id=" << Downtime::GetNextDowntimeID() << "\n"
826 "\t" "next_comment_id=" << Comment::GetNextCommentID() << "\n";
828 statusfp << "\t" "}" "\n"
831 for (const Host::Ptr& host : ConfigType::GetObjectsByType<Host>()) {
832 std::ostringstream tempstatusfp;
833 tempstatusfp << std::fixed;
834 DumpHostStatus(tempstatusfp, host);
835 statusfp << tempstatusfp.str();
837 for (const Service::Ptr& service : host->GetServices()) {
838 std::ostringstream tempstatusfp;
839 tempstatusfp << std::fixed;
840 DumpServiceStatus(tempstatusfp, service);
841 statusfp << tempstatusfp.str();
848 _unlink(statusPath.CStr());
851 if (rename(tempStatusPath.CStr(), statusPath.CStr()) < 0) {
852 BOOST_THROW_EXCEPTION(posix_error()
853 << boost::errinfo_api_function("rename")
854 << boost::errinfo_errno(errno)
855 << boost::errinfo_file_name(tempStatusPath));
858 Log(LogNotice, "StatusDataWriter")
859 << "Writing status.dat file took " << Utility::FormatDuration(Utility::GetTime() - start);
862 void StatusDataWriter::ObjectHandler()
864 m_ObjectsCacheOutdated = true;