From 050c520b2a3df0477f2eec71ec2d874b6dd36aa5 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 20 Aug 2015 17:18:48 +0200 Subject: [PATCH] Convert Comment/Downtime to config objects fixes #9777 --- lib/base/application.cpp | 4 +- lib/base/application.hpp | 2 +- lib/base/configobject.cpp | 16 +- lib/base/configobject.hpp | 8 +- lib/base/configobject.ti | 4 +- lib/base/configwriter.cpp | 6 +- lib/base/configwriter.hpp | 2 +- lib/base/filelogger.cpp | 4 +- lib/base/filelogger.hpp | 2 +- lib/base/logger.cpp | 8 +- lib/base/logger.hpp | 4 +- lib/base/streamlogger.cpp | 4 +- lib/base/streamlogger.hpp | 2 +- lib/checker/checkercomponent.cpp | 8 +- lib/checker/checkercomponent.hpp | 4 +- lib/compat/checkresultreader.cpp | 4 +- lib/compat/checkresultreader.hpp | 2 +- lib/compat/compatlogger.cpp | 16 +- lib/compat/compatlogger.hpp | 6 +- lib/compat/externalcommandlistener.cpp | 4 +- lib/compat/externalcommandlistener.hpp | 2 +- lib/compat/statusdatawriter.cpp | 26 +- lib/compat/statusdatawriter.hpp | 2 +- lib/config/configitem.cpp | 41 ++- lib/config/configitem.hpp | 4 +- lib/db_ido/dbconnection.cpp | 4 +- lib/db_ido/dbconnection.hpp | 2 +- lib/db_ido/dbevents.cpp | 146 +++------ lib/db_ido/dbevents.hpp | 26 +- lib/demo/demo.cpp | 4 +- lib/demo/demo.hpp | 2 +- lib/icinga/apiactions.cpp | 30 +- lib/icinga/apievents.cpp | 64 +--- lib/icinga/apievents.hpp | 10 +- lib/icinga/checkable-comment.cpp | 213 +------------ lib/icinga/checkable-downtime.cpp | 349 ++------------------- lib/icinga/checkable-notification.cpp | 4 +- lib/icinga/checkable.cpp | 32 +- lib/icinga/checkable.hpp | 59 +--- lib/icinga/checkable.ti | 6 - lib/icinga/clusterevents.cpp | 275 ---------------- lib/icinga/clusterevents.hpp | 12 - lib/icinga/comment.cpp | 213 +++++++++++++ lib/icinga/comment.hpp | 33 +- lib/icinga/comment.ti | 59 +++- lib/icinga/dependency.cpp | 4 +- lib/icinga/dependency.hpp | 2 +- lib/icinga/downtime.cpp | 311 ++++++++++++++++++ lib/icinga/downtime.hpp | 40 ++- lib/icinga/downtime.ti | 74 ++++- lib/icinga/externalcommandprocessor.cpp | 96 +++--- lib/icinga/host.cpp | 4 +- lib/icinga/host.hpp | 2 +- lib/icinga/icingastatuswriter.cpp | 4 +- lib/icinga/icingastatuswriter.hpp | 2 +- lib/icinga/notification.cpp | 34 +- lib/icinga/notification.hpp | 6 +- lib/icinga/scheduleddowntime.cpp | 32 +- lib/icinga/scheduleddowntime.hpp | 2 +- lib/icinga/timeperiod.cpp | 4 +- lib/icinga/timeperiod.hpp | 2 +- lib/icinga/user.cpp | 4 +- lib/icinga/user.hpp | 2 +- lib/livestatus/commentstable.cpp | 39 +-- lib/livestatus/downtimestable.cpp | 46 +-- lib/livestatus/hoststable.cpp | 91 ++---- lib/livestatus/livestatuslistener.cpp | 8 +- lib/livestatus/livestatuslistener.hpp | 4 +- lib/livestatus/servicestable.cpp | 90 ++---- lib/notification/notificationcomponent.cpp | 4 +- lib/notification/notificationcomponent.hpp | 2 +- lib/perfdata/gelfwriter.cpp | 4 +- lib/perfdata/gelfwriter.hpp | 2 +- lib/perfdata/graphitewriter.cpp | 4 +- lib/perfdata/graphitewriter.hpp | 2 +- lib/perfdata/opentsdbwriter.cpp | 4 +- lib/perfdata/opentsdbwriter.hpp | 2 +- lib/perfdata/perfdatawriter.cpp | 4 +- lib/perfdata/perfdatawriter.hpp | 2 +- lib/remote/apilistener.cpp | 4 +- lib/remote/apilistener.hpp | 2 +- lib/remote/configobjectutility.cpp | 8 +- lib/remote/configobjectutility.hpp | 10 +- lib/remote/createobjecthandler.cpp | 18 +- tools/mkclass/classcompiler.cpp | 12 +- 85 files changed, 1173 insertions(+), 1542 deletions(-) diff --git a/lib/base/application.cpp b/lib/base/application.cpp index 0c8aef266..5cc81d3c0 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -78,7 +78,7 @@ void Application::OnConfigLoaded(void) /** * Destructor for the application class. */ -void Application::Stop(void) +void Application::Stop(bool runtimeRemoved) { m_ShuttingDown = true; @@ -102,7 +102,7 @@ void Application::Stop(void) } else ClosePidFile(true); - ObjectImpl::Stop(); + ObjectImpl::Stop(runtimeRemoved); } Application::~Application(void) diff --git a/lib/base/application.hpp b/lib/base/application.hpp index 3906f2efb..8f908dfac 100644 --- a/lib/base/application.hpp +++ b/lib/base/application.hpp @@ -138,7 +138,7 @@ public: protected: virtual void OnConfigLoaded(void) override; - virtual void Stop(void) override; + virtual void Stop(bool runtimeRemoved) override; void RunEventLoop(void); diff --git a/lib/base/configobject.cpp b/lib/base/configobject.cpp index 354a5eafa..deb746752 100644 --- a/lib/base/configobject.cpp +++ b/lib/base/configobject.cpp @@ -374,9 +374,9 @@ void ConfigObject::Unregister(void) dtype->UnregisterObject(this); } -void ConfigObject::Start(void) +void ConfigObject::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); ASSERT(!OwnsLock()); ObjectLock olock(this); @@ -384,13 +384,13 @@ void ConfigObject::Start(void) SetStartCalled(true); } -void ConfigObject::Activate(void) +void ConfigObject::Activate(bool runtimeCreated) { CONTEXT("Activating object '" + GetName() + "' of type '" + GetType()->GetName() + "'"); ASSERT(!OwnsLock()); - Start(); + Start(runtimeCreated); ASSERT(GetStartCalled()); @@ -405,9 +405,9 @@ void ConfigObject::Activate(void) NotifyActive(); } -void ConfigObject::Stop(void) +void ConfigObject::Stop(bool runtimeRemoved) { - ObjectImpl::Stop(); + ObjectImpl::Stop(runtimeRemoved); ASSERT(!OwnsLock()); ObjectLock olock(this); @@ -415,7 +415,7 @@ void ConfigObject::Stop(void) SetStopCalled(true); } -void ConfigObject::Deactivate(void) +void ConfigObject::Deactivate(bool runtimeRemoved) { CONTEXT("Deactivating object '" + GetName() + "' of type '" + GetType()->GetName() + "'"); @@ -432,7 +432,7 @@ void ConfigObject::Deactivate(void) SetActive(false, true); } - Stop(); + Stop(runtimeRemoved); ASSERT(GetStopCalled()); diff --git a/lib/base/configobject.hpp b/lib/base/configobject.hpp index ba2d04285..1991d5c6e 100644 --- a/lib/base/configobject.hpp +++ b/lib/base/configobject.hpp @@ -60,12 +60,12 @@ public: void Register(void); void Unregister(void); - void Activate(void); - void Deactivate(void); + void Activate(bool runtimeCreated = false); + void Deactivate(bool runtimeRemoved = false); void SetAuthority(bool authority); - virtual void Start(void) override; - virtual void Stop(void) override; + virtual void Start(bool runtimeCreated = false) override; + virtual void Stop(bool runtimeRemoved = false) override; virtual void Pause(void); virtual void Resume(void); diff --git a/lib/base/configobject.ti b/lib/base/configobject.ti index ba19b7bc1..fdb01fd27 100644 --- a/lib/base/configobject.ti +++ b/lib/base/configobject.ti @@ -55,10 +55,10 @@ public: m_DebugInfo = di; } - inline virtual void Start(void) + inline virtual void Start(bool runtimeCreated) { } - inline virtual void Stop(void) + inline virtual void Stop(bool runtimeRemoved) { } private: diff --git a/lib/base/configwriter.cpp b/lib/base/configwriter.cpp index ec5514636..cc58ecdee 100644 --- a/lib/base/configwriter.cpp +++ b/lib/base/configwriter.cpp @@ -165,7 +165,7 @@ void ConfigWriter::EmitIdentifier(std::ostream& fp, const String& identifier, bo } void ConfigWriter::EmitConfigItem(std::ostream& fp, const String& type, const String& name, bool isTemplate, - const Array::Ptr& imports, const Dictionary::Ptr& attrs) + bool ignoreOnError, const Array::Ptr& imports, const Dictionary::Ptr& attrs) { if (isTemplate) fp << "template "; @@ -175,6 +175,10 @@ void ConfigWriter::EmitConfigItem(std::ostream& fp, const String& type, const St EmitIdentifier(fp, type, false); fp << " "; EmitString(fp, name); + + if (ignoreOnError) + fp << " ignore_on_error"; + fp << " "; EmitScope(fp, 1, attrs, imports); } diff --git a/lib/base/configwriter.hpp b/lib/base/configwriter.hpp index fcee04ab9..9d933be3c 100644 --- a/lib/base/configwriter.hpp +++ b/lib/base/configwriter.hpp @@ -50,7 +50,7 @@ public: static void EmitIdentifier(std::ostream& fp, const String& identifier, bool inAssignment); static void EmitConfigItem(std::ostream& fp, const String& type, const String& name, bool isTemplate, - const Array::Ptr& imports, const Dictionary::Ptr& attrs); + bool ignoreOnError, const Array::Ptr& imports, const Dictionary::Ptr& attrs); static void EmitComment(std::ostream& fp, const String& text); static void EmitFunctionCall(std::ostream& fp, const String& name, const Array::Ptr& arguments); diff --git a/lib/base/filelogger.cpp b/lib/base/filelogger.cpp index 7fa3197f0..bad2b49fd 100644 --- a/lib/base/filelogger.cpp +++ b/lib/base/filelogger.cpp @@ -44,9 +44,9 @@ void FileLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&) /** * Constructor for the FileLogger class. */ -void FileLogger::Start(void) +void FileLogger::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); ReopenLogFile(); diff --git a/lib/base/filelogger.hpp b/lib/base/filelogger.hpp index 026e101b2..f6e5998c1 100644 --- a/lib/base/filelogger.hpp +++ b/lib/base/filelogger.hpp @@ -39,7 +39,7 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: void ReopenLogFile(void); diff --git a/lib/base/logger.cpp b/lib/base/logger.cpp index c7cf16169..eadb2c716 100644 --- a/lib/base/logger.cpp +++ b/lib/base/logger.cpp @@ -52,22 +52,22 @@ void Logger::StaticInitialize(void) /** * Constructor for the Logger class. */ -void Logger::Start(void) +void Logger::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); boost::mutex::scoped_lock lock(m_Mutex); m_Loggers.insert(this); } -void Logger::Stop(void) +void Logger::Stop(bool runtimeRemoved) { { boost::mutex::scoped_lock lock(m_Mutex); m_Loggers.erase(this); } - ObjectImpl::Stop(); + ObjectImpl::Stop(runtimeRemoved); } std::set Logger::GetLoggers(void) diff --git a/lib/base/logger.hpp b/lib/base/logger.hpp index 7877e1961..5ca5ef9a9 100644 --- a/lib/base/logger.hpp +++ b/lib/base/logger.hpp @@ -93,8 +93,8 @@ public: static void StaticInitialize(void); protected: - virtual void Start(void) override; - virtual void Stop(void) override; + virtual void Start(bool runtimeCreated) override; + virtual void Stop(bool runtimeRemoved) override; private: static boost::mutex m_Mutex; diff --git a/lib/base/streamlogger.cpp b/lib/base/streamlogger.cpp index 0791a2ad4..0839b19e9 100644 --- a/lib/base/streamlogger.cpp +++ b/lib/base/streamlogger.cpp @@ -37,9 +37,9 @@ StreamLogger::StreamLogger(void) : m_Stream(NULL), m_OwnsStream(false) { } -void StreamLogger::Stop(void) +void StreamLogger::Stop(bool runtimeRemoved) { - ObjectImpl::Stop(); + ObjectImpl::Stop(runtimeRemoved); // make sure we flush the log data on shutdown, even if we don't call the destructor if (m_Stream) diff --git a/lib/base/streamlogger.hpp b/lib/base/streamlogger.hpp index 68d70f9fb..70bcb809b 100644 --- a/lib/base/streamlogger.hpp +++ b/lib/base/streamlogger.hpp @@ -40,7 +40,7 @@ public: StreamLogger(void); - virtual void Stop(void) override; + virtual void Stop(bool runtimeRemoved) override; ~StreamLogger(void); void BindStream(std::ostream *stream, bool ownsStream); diff --git a/lib/checker/checkercomponent.cpp b/lib/checker/checkercomponent.cpp index dd7522562..416c9cfbf 100644 --- a/lib/checker/checkercomponent.cpp +++ b/lib/checker/checkercomponent.cpp @@ -72,9 +72,9 @@ void CheckerComponent::OnConfigLoaded(void) Checkable::OnNextCheckChanged.connect(bind(&CheckerComponent::NextCheckChangedHandler, this, _1)); } -void CheckerComponent::Start(void) +void CheckerComponent::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); m_Thread = boost::thread(boost::bind(&CheckerComponent::CheckThreadProc, this)); @@ -84,7 +84,7 @@ void CheckerComponent::Start(void) m_ResultTimer->Start(); } -void CheckerComponent::Stop(void) +void CheckerComponent::Stop(bool runtimeRemoved) { Log(LogInformation, "CheckerComponent", "Checker stopped."); @@ -97,7 +97,7 @@ void CheckerComponent::Stop(void) m_ResultTimer->Stop(); m_Thread.join(); - ObjectImpl::Stop(); + ObjectImpl::Stop(runtimeRemoved); } void CheckerComponent::CheckThreadProc(void) diff --git a/lib/checker/checkercomponent.hpp b/lib/checker/checkercomponent.hpp index 21389f8e7..8ccee6cb6 100644 --- a/lib/checker/checkercomponent.hpp +++ b/lib/checker/checkercomponent.hpp @@ -71,8 +71,8 @@ public: CheckerComponent(void); virtual void OnConfigLoaded(void) override; - virtual void Start(void) override; - virtual void Stop(void) override; + virtual void Start(bool runtimeCreated) override; + virtual void Stop(bool runtimeRemoved) override; static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); unsigned long GetIdleCheckables(void); diff --git a/lib/compat/checkresultreader.cpp b/lib/compat/checkresultreader.cpp index ba9c4ae86..423c891d1 100644 --- a/lib/compat/checkresultreader.cpp +++ b/lib/compat/checkresultreader.cpp @@ -54,9 +54,9 @@ void CheckResultReader::StatsFunc(const Dictionary::Ptr& status, const Array::Pt /** * @threadsafety Always. */ -void CheckResultReader::Start(void) +void CheckResultReader::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); m_ReadTimer = new Timer(); m_ReadTimer->OnTimerExpired.connect(boost::bind(&CheckResultReader::ReadTimerHandler, this)); diff --git a/lib/compat/checkresultreader.hpp b/lib/compat/checkresultreader.hpp index 15d6f52ef..ed66e598c 100644 --- a/lib/compat/checkresultreader.hpp +++ b/lib/compat/checkresultreader.hpp @@ -41,7 +41,7 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); protected: - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: Timer::Ptr m_ReadTimer; diff --git a/lib/compat/compatlogger.cpp b/lib/compat/compatlogger.cpp index 46692088e..3ac0e8698 100644 --- a/lib/compat/compatlogger.cpp +++ b/lib/compat/compatlogger.cpp @@ -57,14 +57,14 @@ void CompatLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&) /** * @threadsafety Always. */ -void CompatLogger::Start(void) +void CompatLogger::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); Checkable::OnNewCheckResult.connect(bind(&CompatLogger::CheckResultHandler, this, _1, _2)); Checkable::OnNotificationSentToUser.connect(bind(&CompatLogger::NotificationSentHandler, this, _1, _2, _3, _4, _5, _6, _7, _8)); - Checkable::OnDowntimeTriggered.connect(boost::bind(&CompatLogger::TriggerDowntimeHandler, this, _1, _2)); - Checkable::OnDowntimeRemoved.connect(boost::bind(&CompatLogger::RemoveDowntimeHandler, this, _1, _2)); + Downtime::OnDowntimeTriggered.connect(boost::bind(&CompatLogger::TriggerDowntimeHandler, this, _1)); + Downtime::OnDowntimeRemoved.connect(boost::bind(&CompatLogger::RemoveDowntimeHandler, this, _1)); Checkable::OnEventCommandExecuted.connect(bind(&CompatLogger::EventCommandHandler, this, _1)); Checkable::OnFlappingChanged.connect(boost::bind(&CompatLogger::FlappingChangedHandler, this, _1)); @@ -147,11 +147,11 @@ void CompatLogger::CheckResultHandler(const Checkable::Ptr& checkable, const Che /** * @threadsafety Always. */ -void CompatLogger::TriggerDowntimeHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime) +void CompatLogger::TriggerDowntimeHandler(const Downtime::Ptr& downtime) { Host::Ptr host; Service::Ptr service; - tie(host, service) = GetHostService(checkable); + tie(host, service) = GetHostService(downtime->GetCheckable()); if (!downtime) return; @@ -183,11 +183,11 @@ void CompatLogger::TriggerDowntimeHandler(const Checkable::Ptr& checkable, const /** * @threadsafety Always. */ -void CompatLogger::RemoveDowntimeHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime) +void CompatLogger::RemoveDowntimeHandler(const Downtime::Ptr& downtime) { Host::Ptr host; Service::Ptr service; - tie(host, service) = GetHostService(checkable); + tie(host, service) = GetHostService(downtime->GetCheckable()); if (!downtime) return; diff --git a/lib/compat/compatlogger.hpp b/lib/compat/compatlogger.hpp index 79d08acce..11801dac8 100644 --- a/lib/compat/compatlogger.hpp +++ b/lib/compat/compatlogger.hpp @@ -44,7 +44,7 @@ public: virtual void ValidateRotationMethod(const String& value, const ValidationUtils& utils) override; protected: - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: void WriteLine(const String& line); @@ -56,8 +56,8 @@ private: const String& author, const String& comment_text, const String& command_name); void FlappingChangedHandler(const Checkable::Ptr& checkable); void EnableFlappingChangedHandler(const Checkable::Ptr& checkable); - void TriggerDowntimeHandler(const Checkable::Ptr& service, const Downtime::Ptr& downtime); - void RemoveDowntimeHandler(const Checkable::Ptr& service, const Downtime::Ptr& downtime); + void TriggerDowntimeHandler(const Downtime::Ptr& downtime); + void RemoveDowntimeHandler(const Downtime::Ptr& downtime); void ExternalCommandHandler(const String& command, const std::vector& arguments); void EventCommandHandler(const Checkable::Ptr& service); diff --git a/lib/compat/externalcommandlistener.cpp b/lib/compat/externalcommandlistener.cpp index eefe4649f..8785ba524 100644 --- a/lib/compat/externalcommandlistener.cpp +++ b/lib/compat/externalcommandlistener.cpp @@ -46,9 +46,9 @@ void ExternalCommandListener::StatsFunc(const Dictionary::Ptr& status, const Arr /** * Starts the component. */ -void ExternalCommandListener::Start(void) +void ExternalCommandListener::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); #ifndef _WIN32 m_CommandThread = boost::thread(boost::bind(&ExternalCommandListener::CommandPipeThread, this, GetCommandPath())); diff --git a/lib/compat/externalcommandlistener.hpp b/lib/compat/externalcommandlistener.hpp index 41fba9673..7673b60f6 100644 --- a/lib/compat/externalcommandlistener.hpp +++ b/lib/compat/externalcommandlistener.hpp @@ -42,7 +42,7 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); protected: - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: #ifndef _WIN32 diff --git a/lib/compat/statusdatawriter.cpp b/lib/compat/statusdatawriter.cpp index c0a21c03c..d37c61355 100644 --- a/lib/compat/statusdatawriter.cpp +++ b/lib/compat/statusdatawriter.cpp @@ -70,9 +70,9 @@ void StatusDataWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr /** * Starts the component. */ -void StatusDataWriter::Start(void) +void StatusDataWriter::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); m_ObjectsCacheOutdated = true; @@ -88,17 +88,11 @@ void StatusDataWriter::Start(void) void StatusDataWriter::DumpComments(std::ostream& fp, const Checkable::Ptr& checkable) { - Dictionary::Ptr comments = checkable->GetComments(); - Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); - ObjectLock olock(comments); - - BOOST_FOREACH(const Dictionary::Pair& kv, comments) { - Comment::Ptr comment = kv.second; - + BOOST_FOREACH(const Comment::Ptr& comment, checkable->GetComments()) { if (comment->IsExpired()) continue; @@ -160,17 +154,11 @@ void StatusDataWriter::DumpCommand(std::ostream& fp, const Command::Ptr& command void StatusDataWriter::DumpDowntimes(std::ostream& fp, const Checkable::Ptr& checkable) { - Dictionary::Ptr downtimes = checkable->GetDowntimes(); - Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); - ObjectLock olock(downtimes); - - BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) { - Downtime::Ptr downtime = kv.second; - + BOOST_FOREACH(const Downtime::Ptr& downtime, checkable->GetDowntimes()) { if (downtime->IsExpired()) continue; @@ -180,7 +168,7 @@ void StatusDataWriter::DumpDowntimes(std::ostream& fp, const Checkable::Ptr& che else fp << "hostdowntime {" "\n"; - Downtime::Ptr triggeredByObj = Service::GetDowntimeByID(downtime->GetTriggeredBy()); + Downtime::Ptr triggeredByObj = Downtime::GetByName(downtime->GetTriggeredBy()); int triggeredByLegacy = 0; if (triggeredByObj) triggeredByLegacy = triggeredByObj->GetLegacyId(); @@ -830,8 +818,8 @@ void StatusDataWriter::StatusTimerHandler(void) "\t" "passive_host_check_stats=" << CIB::GetPassiveHostChecksStatistics(60) << "," << CIB::GetPassiveHostChecksStatistics(5 * 60) << "," << CIB::GetPassiveHostChecksStatistics(15 * 60) << "\n" "\t" "active_scheduled_service_check_stats=" << CIB::GetActiveServiceChecksStatistics(60) << "," << CIB::GetActiveServiceChecksStatistics(5 * 60) << "," << CIB::GetActiveServiceChecksStatistics(15 * 60) << "\n" "\t" "passive_service_check_stats=" << CIB::GetPassiveServiceChecksStatistics(60) << "," << CIB::GetPassiveServiceChecksStatistics(5 * 60) << "," << CIB::GetPassiveServiceChecksStatistics(15 * 60) << "\n" - "\t" "next_downtime_id=" << Service::GetNextDowntimeID() << "\n" - "\t" "next_comment_id=" << Service::GetNextCommentID() << "\n"; + "\t" "next_downtime_id=" << Downtime::GetNextDowntimeID() << "\n" + "\t" "next_comment_id=" << Comment::GetNextCommentID() << "\n"; statusfp << "\t" "}" "\n" "\n"; diff --git a/lib/compat/statusdatawriter.hpp b/lib/compat/statusdatawriter.hpp index c6ee85a9c..b8df2f2b7 100644 --- a/lib/compat/statusdatawriter.hpp +++ b/lib/compat/statusdatawriter.hpp @@ -47,7 +47,7 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); protected: - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: Timer::Ptr m_StatusTimer; diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 91bfbf164..535ae143a 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -224,7 +224,19 @@ ConfigObject::Ptr ConfigItem::Commit(bool discard) dobj->SetShortName(item_name); dobj->SetName(name); - dobj->OnConfigLoaded(); + + try { + dobj->OnConfigLoaded(); + } catch (const std::exception& ex) { + if (m_IgnoreOnError) { + Log(LogWarning, "ConfigObject") + << "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex); + + return ConfigObject::Ptr(); + } + + throw; + } { boost::mutex::scoped_lock lock(m_Mutex); @@ -342,6 +354,24 @@ ConfigItem::Ptr ConfigItem::GetByTypeAndName(const String& type, const String& n return it2->second; } +void ConfigItem::OnAllConfigLoadedWrapper(void) +{ + try { + m_Object->OnAllConfigLoaded(); + } catch (const std::exception& ex) { + if (m_IgnoreOnError) { + Log(LogWarning, "ConfigObject") + << "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex); + + Unregister(); + + return; + } + + throw; + } +} + bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector& newItems) { typedef std::pair ItemPair; @@ -429,7 +459,7 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector& ne continue; if (item->m_Type == type) - upq.Enqueue(boost::bind(&ConfigObject::OnAllConfigLoaded, item->m_Object)); + upq.Enqueue(boost::bind(&ConfigItem::OnAllConfigLoadedWrapper, item)); } completed_types.insert(type); @@ -498,8 +528,11 @@ bool ConfigItem::CommitItems(WorkQueue& upq) return true; } -bool ConfigItem::ActivateItems(WorkQueue& upq, bool restoreState) +bool ConfigItem::ActivateItems(WorkQueue& upq, bool restoreState, bool runtimeCreated) { + static boost::mutex mtx; + boost::mutex::scoped_lock lock(mtx); + if (restoreState) { /* restore the previous program state */ try { @@ -521,7 +554,7 @@ bool ConfigItem::ActivateItems(WorkQueue& upq, bool restoreState) Log(LogDebug, "ConfigItem") << "Activating object '" << object->GetName() << "' of type '" << object->GetType()->GetName() << "'"; #endif /* I2_DEBUG */ - upq.Enqueue(boost::bind(&ConfigObject::Activate, object)); + upq.Enqueue(boost::bind(&ConfigObject::Activate, object, runtimeCreated)); } } diff --git a/lib/config/configitem.hpp b/lib/config/configitem.hpp index 6439d428e..b53327e62 100644 --- a/lib/config/configitem.hpp +++ b/lib/config/configitem.hpp @@ -68,7 +68,7 @@ public: const String& name); static bool CommitItems(WorkQueue& upq); - static bool ActivateItems(WorkQueue& upq, bool restoreState); + static bool ActivateItems(WorkQueue& upq, bool restoreState, bool runtimeCreated = false); static bool CommitAndActivate(void); @@ -103,6 +103,8 @@ private: const String& name); static bool CommitNewItems(WorkQueue& upq, std::vector& newItems); + + void OnAllConfigLoadedWrapper(void); }; } diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp index c78065505..1bbcf71d8 100644 --- a/lib/db_ido/dbconnection.cpp +++ b/lib/db_ido/dbconnection.cpp @@ -56,9 +56,9 @@ void DbConnection::OnConfigLoaded(void) boost::call_once(m_OnceFlag, InitializeDbTimer); } -void DbConnection::Start(void) +void DbConnection::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); DbObject::OnQuery.connect(boost::bind(&DbConnection::ExecuteQuery, this, _1)); ConfigObject::OnActiveChanged.connect(boost::bind(&DbConnection::UpdateObject, this, _1)); diff --git a/lib/db_ido/dbconnection.hpp b/lib/db_ido/dbconnection.hpp index 43d215ae7..58fe2594f 100644 --- a/lib/db_ido/dbconnection.hpp +++ b/lib/db_ido/dbconnection.hpp @@ -78,7 +78,7 @@ public: protected: virtual void OnConfigLoaded(void) override; - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; virtual void Resume(void) override; virtual void Pause(void) override; diff --git a/lib/db_ido/dbevents.cpp b/lib/db_ido/dbevents.cpp index 10fe515dc..a0c5d5812 100644 --- a/lib/db_ido/dbevents.cpp +++ b/lib/db_ido/dbevents.cpp @@ -43,11 +43,11 @@ INITIALIZE_ONCE(&DbEvents::StaticInitialize); void DbEvents::StaticInitialize(void) { /* Status */ - Checkable::OnCommentAdded.connect(boost::bind(&DbEvents::AddComment, _1, _2)); - Checkable::OnCommentRemoved.connect(boost::bind(&DbEvents::RemoveComment, _1, _2)); - Checkable::OnDowntimeAdded.connect(boost::bind(&DbEvents::AddDowntime, _1, _2, true)); - Checkable::OnDowntimeRemoved.connect(boost::bind(&DbEvents::RemoveDowntime, _1, _2)); - Checkable::OnDowntimeTriggered.connect(boost::bind(&DbEvents::TriggerDowntime, _1, _2)); + Comment::OnCommentAdded.connect(boost::bind(&DbEvents::AddComment, _1)); + Comment::OnCommentRemoved.connect(boost::bind(&DbEvents::RemoveComment, _1)); + Downtime::OnDowntimeAdded.connect(boost::bind(&DbEvents::AddDowntime, _1, true)); + Downtime::OnDowntimeRemoved.connect(boost::bind(&DbEvents::RemoveDowntime, _1)); + Downtime::OnDowntimeTriggered.connect(boost::bind(&DbEvents::TriggerDowntime, _1)); Checkable::OnAcknowledgementSet.connect(boost::bind(&DbEvents::AddAcknowledgement, _1, _4)); Checkable::OnAcknowledgementCleared.connect(boost::bind(&DbEvents::RemoveAcknowledgement, _1)); @@ -64,8 +64,8 @@ void DbEvents::StaticInitialize(void) Checkable::OnReachabilityChanged.connect(boost::bind(&DbEvents::ReachabilityChangedHandler, _1, _2, _3)); /* History */ - Checkable::OnCommentAdded.connect(boost::bind(&DbEvents::AddCommentHistory, _1, _2)); - Checkable::OnDowntimeAdded.connect(boost::bind(&DbEvents::AddDowntimeHistory, _1, _2)); + Comment::OnCommentAdded.connect(boost::bind(&DbEvents::AddCommentHistory, _1)); + Downtime::OnDowntimeAdded.connect(boost::bind(&DbEvents::AddDowntimeHistory, _1)); Checkable::OnAcknowledgementSet.connect(boost::bind(&DbEvents::AddAcknowledgementHistory, _1, _2, _3, _4, _5, _6)); Checkable::OnNotificationSentToAllUsers.connect(boost::bind(&DbEvents::AddNotificationHistory, _1, _2, _3, _4, _5, _6, _7)); @@ -76,8 +76,8 @@ void DbEvents::StaticInitialize(void) Checkable::OnNotificationSentToUser.connect(boost::bind(&DbEvents::AddNotificationSentLogHistory, _1, _2, _3, _4, _5, _6, _7)); Checkable::OnFlappingChanged.connect(boost::bind(&DbEvents::AddFlappingChangedLogHistory, _1)); Checkable::OnEnableFlappingChanged.connect(boost::bind(&DbEvents::AddEnableFlappingChangedLogHistory, _1)); - Checkable::OnDowntimeTriggered.connect(boost::bind(&DbEvents::AddTriggerDowntimeLogHistory, _1, _2)); - Checkable::OnDowntimeRemoved.connect(boost::bind(&DbEvents::AddRemoveDowntimeLogHistory, _1, _2)); + Downtime::OnDowntimeTriggered.connect(boost::bind(&DbEvents::AddTriggerDowntimeLogHistory, _1)); + Downtime::OnDowntimeRemoved.connect(boost::bind(&DbEvents::AddRemoveDowntimeLogHistory, _1)); Checkable::OnFlappingChanged.connect(boost::bind(&DbEvents::AddFlappingChangedHistory, _1)); Checkable::OnEnableFlappingChanged.connect(boost::bind(&DbEvents::AddEnableFlappingChangedHistory, _1)); @@ -303,45 +303,30 @@ void DbEvents::EnableChangedHandlerInternal(const Checkable::Ptr& checkable, con /* comments */ void DbEvents::AddComments(const Checkable::Ptr& checkable) { - /* dump all comments */ - Dictionary::Ptr comments = checkable->GetComments(); - - if (comments->GetLength() > 0) - RemoveComments(checkable); - - ObjectLock olock(comments); - - BOOST_FOREACH(const Dictionary::Pair& kv, comments) { - AddComment(checkable, kv.second); + BOOST_FOREACH(const Comment::Ptr& comment, checkable->GetComments()) { + AddComment(comment); } } -void DbEvents::AddComment(const Checkable::Ptr& checkable, const Comment::Ptr& comment) +void DbEvents::AddComment(const Comment::Ptr& comment) { - AddCommentInternal(checkable, comment, false); + AddCommentInternal(comment, false); } -void DbEvents::AddCommentHistory(const Checkable::Ptr& checkable, const Comment::Ptr& comment) +void DbEvents::AddCommentHistory(const Comment::Ptr& comment) { - AddCommentInternal(checkable, comment, true); + AddCommentInternal(comment, true); } -void DbEvents::AddCommentInternal(const Checkable::Ptr& checkable, const Comment::Ptr& comment, bool historical) +void DbEvents::AddCommentInternal(const Comment::Ptr& comment, bool historical) { - if (!comment) { - Log(LogWarning, "DbEvents", "comment does not exist. not adding it."); - return; - } - - Log(LogDebug, "DbEvents") - << "adding service comment (id = " << comment->GetLegacyId() << ") for '" << checkable->GetName() << "'"; - - /* add the service comment */ - AddCommentByType(checkable, comment, historical); + AddCommentByType(comment, historical); } -void DbEvents::AddCommentByType(const ConfigObject::Ptr& object, const Comment::Ptr& comment, bool historical) +void DbEvents::AddCommentByType(const Comment::Ptr& comment, bool historical) { + Checkable::Ptr checkable = comment->GetCheckable(); + unsigned long entry_time = static_cast(comment->GetEntryTime()); unsigned long entry_time_usec = (comment->GetEntryTime() - entry_time) * 1000 * 1000; @@ -349,13 +334,13 @@ void DbEvents::AddCommentByType(const ConfigObject::Ptr& object, const Comment:: fields1->Set("entry_time", DbValue::FromTimestamp(entry_time)); fields1->Set("entry_time_usec", entry_time_usec); fields1->Set("entry_type", comment->GetEntryType()); - fields1->Set("object_id", object); + fields1->Set("object_id", checkable); - if (object->GetType() == ConfigType::GetByName("Host")) { + if (checkable->GetType() == ConfigType::GetByName("Host")) { fields1->Set("comment_type", 2); /* requires idoutils 1.10 schema fix */ fields1->Set("internal_comment_id", comment->GetLegacyId()); - } else if (object->GetType() == ConfigType::GetByName("Service")) { + } else if (checkable->GetType() == ConfigType::GetByName("Service")) { fields1->Set("comment_type", 1); fields1->Set("internal_comment_id", comment->GetLegacyId()); } else { @@ -404,15 +389,9 @@ void DbEvents::RemoveComments(const Checkable::Ptr& checkable) DbObject::OnQuery(query1); } -void DbEvents::RemoveComment(const Checkable::Ptr& checkable, const Comment::Ptr& comment) +void DbEvents::RemoveComment(const Comment::Ptr& comment) { - if (!comment) { - Log(LogWarning, "DbEvents", "comment does not exist. not deleting it."); - return; - } - - Log(LogDebug, "DbEvents") - << "removing service comment (id = " << comment->GetLegacyId() << ") for '" << checkable->GetName() << "'"; + Checkable::Ptr checkable = comment->GetCheckable(); /* Status */ DbQuery query1; @@ -451,51 +430,39 @@ void DbEvents::RemoveComment(const Checkable::Ptr& checkable, const Comment::Ptr /* downtimes */ void DbEvents::AddDowntimes(const Checkable::Ptr& checkable) { - /* dump all downtimes */ - Dictionary::Ptr downtimes = checkable->GetDowntimes(); - - if (downtimes->GetLength() > 0) - RemoveDowntimes(checkable); + RemoveDowntimes(checkable); - ObjectLock olock(downtimes); - - BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) { - AddDowntime(checkable, kv.second, false); + BOOST_FOREACH(const Downtime::Ptr& downtime, checkable->GetDowntimes()) { + AddDowntime(downtime, false); } } -void DbEvents::AddDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool remove_existing) +void DbEvents::AddDowntime(const Downtime::Ptr& downtime, bool remove_existing) { /* * make sure to delete any old downtime to avoid multiple inserts from * configured ScheduledDowntime dumps and CreateNextDowntime() calls */ if (remove_existing) - RemoveDowntime(checkable, downtime); - AddDowntimeInternal(checkable, downtime, false); + RemoveDowntime(downtime); + + AddDowntimeInternal(downtime, false); } -void DbEvents::AddDowntimeHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime) +void DbEvents::AddDowntimeHistory(const Downtime::Ptr& downtime) { - AddDowntimeInternal(checkable, downtime, true); + AddDowntimeInternal(downtime, true); } -void DbEvents::AddDowntimeInternal(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool historical) +void DbEvents::AddDowntimeInternal(const Downtime::Ptr& downtime, bool historical) { - if (!downtime) { - Log(LogWarning, "DbEvents", "downtime does not exist. not adding it."); - return; - } - - Log(LogDebug, "DbEvents") - << "adding service downtime (id = " << downtime->GetLegacyId() << ") for '" << checkable->GetName() << "'"; - - /* add the downtime */ - AddDowntimeByType(checkable, downtime, historical); + AddDowntimeByType(downtime, historical); } -void DbEvents::AddDowntimeByType(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool historical) +void DbEvents::AddDowntimeByType(const Downtime::Ptr& downtime, bool historical) { + Checkable::Ptr checkable = downtime->GetCheckable(); + Dictionary::Ptr fields1 = new Dictionary(); fields1->Set("entry_time", DbValue::FromTimestamp(downtime->GetEntryTime())); fields1->Set("object_id", checkable); @@ -514,7 +481,7 @@ void DbEvents::AddDowntimeByType(const Checkable::Ptr& checkable, const Downtime fields1->Set("author_name", downtime->GetAuthor()); fields1->Set("comment_data", downtime->GetComment()); - fields1->Set("triggered_by_id", Service::GetDowntimeByID(downtime->GetTriggeredBy())); + fields1->Set("triggered_by_id", Downtime::GetByName(downtime->GetTriggeredBy())); fields1->Set("is_fixed", downtime->GetFixed() ? 1 : 0); fields1->Set("duration", downtime->GetDuration()); fields1->Set("scheduled_start_time", DbValue::FromTimestamp(downtime->GetStartTime())); @@ -544,9 +511,6 @@ void DbEvents::AddDowntimeByType(const Checkable::Ptr& checkable, const Downtime void DbEvents::RemoveDowntimes(const Checkable::Ptr& checkable) { - Log(LogDebug, "DbEvents") - << "removing service downtimes for '" << checkable->GetName() << "'"; - DbQuery query1; query1.Table = "scheduleddowntime"; query1.Type = DbQueryDelete; @@ -556,15 +520,9 @@ void DbEvents::RemoveDowntimes(const Checkable::Ptr& checkable) DbObject::OnQuery(query1); } -void DbEvents::RemoveDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime) +void DbEvents::RemoveDowntime(const Downtime::Ptr& downtime) { - if (!downtime) { - Log(LogWarning, "DbEvents", "downtime does not exist. not adding it."); - return; - } - - Log(LogDebug, "DbEvents") - << "removing service downtime (id = " << downtime->GetLegacyId() << ") for '" << checkable->GetName() << "'"; + Checkable::Ptr checkable = downtime->GetCheckable(); /* Status */ DbQuery query1; @@ -632,15 +590,9 @@ void DbEvents::RemoveDowntime(const Checkable::Ptr& checkable, const Downtime::P DbObject::OnQuery(query4); } -void DbEvents::TriggerDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime) +void DbEvents::TriggerDowntime(const Downtime::Ptr& downtime) { - if (!downtime) { - Log(LogWarning, "DbEvents", "downtime does not exist. not updating it."); - return; - } - - Log(LogDebug, "DbEvents") - << "updating triggered service downtime (id = " << downtime->GetLegacyId() << ") for '" << checkable->GetName() << "'"; + Checkable::Ptr checkable = downtime->GetCheckable(); double now = Utility::GetTime(); std::pair time_bag = CompatUtility::ConvertTimestamp(now); @@ -1036,10 +988,9 @@ void DbEvents::AddCheckResultLogHistory(const Checkable::Ptr& checkable, const C AddLogHistory(checkable, msgbuf.str(), type); } -void DbEvents::AddTriggerDowntimeLogHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime) +void DbEvents::AddTriggerDowntimeLogHistory(const Downtime::Ptr& downtime) { - if (!downtime) - return; + Checkable::Ptr checkable = downtime->GetCheckable(); Host::Ptr host; Service::Ptr service; @@ -1065,10 +1016,9 @@ void DbEvents::AddTriggerDowntimeLogHistory(const Checkable::Ptr& checkable, con AddLogHistory(checkable, msgbuf.str(), LogEntryTypeInfoMessage); } -void DbEvents::AddRemoveDowntimeLogHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime) +void DbEvents::AddRemoveDowntimeLogHistory(const Downtime::Ptr& downtime) { - if (!downtime) - return; + Checkable::Ptr checkable = downtime->GetCheckable(); String downtime_output; String downtime_state_str; diff --git a/lib/db_ido/dbevents.hpp b/lib/db_ido/dbevents.hpp index c1c3b7b7d..1acaaf60e 100644 --- a/lib/db_ido/dbevents.hpp +++ b/lib/db_ido/dbevents.hpp @@ -61,11 +61,11 @@ class DbEvents public: static void StaticInitialize(void); - static void AddCommentByType(const ConfigObject::Ptr& object, const Comment::Ptr& comment, bool historical); + static void AddCommentByType(const Comment::Ptr& comment, bool historical); static void AddComments(const Checkable::Ptr& checkable); static void RemoveComments(const Checkable::Ptr& checkable); - static void AddDowntimeByType(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool historical); + static void AddDowntimeByType(const Downtime::Ptr& downtime, bool historical); static void AddDowntimes(const Checkable::Ptr& checkable); static void RemoveDowntimes(const Checkable::Ptr& checkable); @@ -82,12 +82,12 @@ public: static void EnablePerfdataChangedHandler(const Checkable::Ptr& checkable); static void EnableFlappingChangedHandler(const Checkable::Ptr& checkable); - static void AddComment(const Checkable::Ptr& checkable, const Comment::Ptr& comment); - static void RemoveComment(const Checkable::Ptr& checkable, const Comment::Ptr& comment); + static void AddComment(const Comment::Ptr& comment); + static void RemoveComment(const Comment::Ptr& comment); - static void AddDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool remove_existing); - static void RemoveDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime); - static void TriggerDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime); + static void AddDowntime(const Downtime::Ptr& downtime, bool remove_existing); + static void RemoveDowntime(const Downtime::Ptr& downtime); + static void TriggerDowntime(const Downtime::Ptr& downtime); static void AddAcknowledgement(const Checkable::Ptr& checkable, AcknowledgementType type); static void RemoveAcknowledgement(const Checkable::Ptr& checkable); @@ -96,8 +96,8 @@ public: static void ReachabilityChangedHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, std::set children); /* comment, downtime, acknowledgement history */ - static void AddCommentHistory(const Checkable::Ptr& checkable, const Comment::Ptr& comment); - static void AddDowntimeHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime); + static void AddCommentHistory(const Comment::Ptr& comment); + static void AddDowntimeHistory(const Downtime::Ptr& downtime); static void AddAcknowledgementHistory(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, bool notify, double expiry); @@ -111,8 +111,8 @@ public: /* logentries */ static void AddCheckResultLogHistory(const Checkable::Ptr& checkable, const CheckResult::Ptr &cr); - static void AddTriggerDowntimeLogHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime); - static void AddRemoveDowntimeLogHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime); + static void AddTriggerDowntimeLogHistory(const Downtime::Ptr& downtime); + static void AddRemoveDowntimeLogHistory(const Downtime::Ptr& downtime); static void AddNotificationSentLogHistory(const Notification::Ptr& notification, const Checkable::Ptr& checkable, const User::Ptr& user, NotificationType notification_type, const CheckResult::Ptr& cr, const String& author, const String& comment_text); @@ -130,8 +130,8 @@ public: private: DbEvents(void); - static void AddCommentInternal(const Checkable::Ptr& checkable, const Comment::Ptr& comment, bool historical); - static void AddDowntimeInternal(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool historical); + static void AddCommentInternal(const Comment::Ptr& comment, bool historical); + static void AddDowntimeInternal(const Downtime::Ptr& downtime, bool historical); static void EnableChangedHandlerInternal(const Checkable::Ptr& checkable, const String& fieldName, bool enabled); }; diff --git a/lib/demo/demo.cpp b/lib/demo/demo.cpp index f837546c2..0605a44e1 100644 --- a/lib/demo/demo.cpp +++ b/lib/demo/demo.cpp @@ -33,9 +33,9 @@ REGISTER_APIFUNCTION(HelloWorld, demo, &Demo::DemoMessageHandler); /** * Starts the component. */ -void Demo::Start(void) +void Demo::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); m_DemoTimer = new Timer(); m_DemoTimer->SetInterval(5); diff --git a/lib/demo/demo.hpp b/lib/demo/demo.hpp index c74927019..259c84dca 100644 --- a/lib/demo/demo.hpp +++ b/lib/demo/demo.hpp @@ -36,7 +36,7 @@ public: DECLARE_OBJECT(Demo); DECLARE_OBJECTNAME(Demo); - virtual void Start(void); + virtual void Start(bool runtimeCreated); static Value DemoMessageHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); diff --git a/lib/icinga/apiactions.cpp b/lib/icinga/apiactions.cpp index 1dc0c0bc0..6c6e8495d 100644 --- a/lib/icinga/apiactions.cpp +++ b/lib/icinga/apiactions.cpp @@ -215,7 +215,7 @@ Dictionary::Ptr ApiActions::AcknowledgeProblem(const ConfigObject::Ptr& object, return ApiActions::CreateResult(409, "Service " + checkable->GetName() + " is OK."); } - checkable->AddComment(CommentAcknowledgement, HttpUtility::GetLastParameter(params, "author"), + Comment::AddComment(checkable, CommentAcknowledgement, HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), timestamp); checkable->AcknowledgeProblem(HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), sticky, notify, timestamp); @@ -250,11 +250,11 @@ Dictionary::Ptr ApiActions::AddComment(const ConfigObject::Ptr& object, if (!params->Contains("author") || !params->Contains("comment")) return ApiActions::CreateResult(403, "Comments require author and comment."); - String comment_id = checkable->AddComment(CommentUser, + String comment_id = Comment::AddComment(checkable, CommentUser, HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), 0); - Comment::Ptr comment = Checkable::GetCommentByID(comment_id); + Comment::Ptr comment = Comment::GetByName(comment_id); int legacy_id = comment->GetLegacyId(); Dictionary::Ptr additional = new Dictionary(); @@ -287,7 +287,7 @@ Dictionary::Ptr ApiActions::RemoveCommentByID(const ConfigObject::Ptr& object, String comment_id = HttpUtility::GetLastParameter(params, "comment_id"); - Service::RemoveComment(comment_id); + Comment::RemoveComment(comment_id); return ApiActions::CreateResult(200, "Successfully removed comment '" + comment_id + "'."); } @@ -311,21 +311,15 @@ Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object, if (params->Contains("fixed")) fixed = HttpUtility::GetLastParameter(params, "fixed"); - int triggeredByLegacy = 0; - - if (params->Contains("trigger_id")) - triggeredByLegacy = HttpUtility::GetLastParameter(params, "trigger_id"); - - String triggeredBy; - if (triggeredByLegacy) - triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy); - - String downtime_id = checkable->AddDowntime(HttpUtility::GetLastParameter(params, "author"), - HttpUtility::GetLastParameter(params, "comment"), HttpUtility::GetLastParameter(params, "start_time"), - HttpUtility::GetLastParameter(params, "end_time"), fixed, triggeredBy, + String downtime_id = Downtime::AddDowntime(checkable, + HttpUtility::GetLastParameter(params, "author"), + HttpUtility::GetLastParameter(params, "comment"), + HttpUtility::GetLastParameter(params, "start_time"), + HttpUtility::GetLastParameter(params, "end_time"), fixed, + HttpUtility::GetLastParameter(params, "trigger_id"), HttpUtility::GetLastParameter(params, "duration")); - Downtime::Ptr downtime = Checkable::GetDowntimeByID(downtime_id); + Downtime::Ptr downtime = Downtime::GetByName(downtime_id); int legacy_id = downtime->GetLegacyId(); Dictionary::Ptr additional = new Dictionary(); @@ -357,7 +351,7 @@ Dictionary::Ptr ApiActions::RemoveDowntimeByID(const ConfigObject::Ptr& object, String downtime_id = HttpUtility::GetLastParameter(params, "downtime_id"); - Service::RemoveDowntime(downtime_id, true); + Downtime::RemoveDowntime(downtime_id, true); return ApiActions::CreateResult(200, "Successfully removed downtime '" + downtime_id + "'."); } diff --git a/lib/icinga/apievents.cpp b/lib/icinga/apievents.cpp index 121c9dd4e..80ea790b6 100644 --- a/lib/icinga/apievents.cpp +++ b/lib/icinga/apievents.cpp @@ -39,12 +39,12 @@ void ApiEvents::StaticInitialize(void) Checkable::OnAcknowledgementSet.connect(&ApiEvents::AcknowledgementSetHandler); Checkable::OnAcknowledgementCleared.connect(&ApiEvents::AcknowledgementClearedHandler); - Checkable::OnCommentAdded.connect(&ApiEvents::CommentAddedHandler); - Checkable::OnCommentRemoved.connect(&ApiEvents::CommentRemovedHandler); + Comment::OnCommentAdded.connect(&ApiEvents::CommentAddedHandler); + Comment::OnCommentRemoved.connect(&ApiEvents::CommentRemovedHandler); - Checkable::OnDowntimeAdded.connect(&ApiEvents::DowntimeAddedHandler); - Checkable::OnDowntimeRemoved.connect(&ApiEvents::DowntimeRemovedHandler); - Checkable::OnDowntimeTriggered.connect(&ApiEvents::DowntimeTriggeredHandler); + Downtime::OnDowntimeAdded.connect(&ApiEvents::DowntimeAddedHandler); + Downtime::OnDowntimeRemoved.connect(&ApiEvents::DowntimeRemovedHandler); + Downtime::OnDowntimeTriggered.connect(&ApiEvents::DowntimeTriggeredHandler); } void ApiEvents::CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, const MessageOrigin::Ptr& origin) @@ -243,7 +243,7 @@ void ApiEvents::AcknowledgementClearedHandler(const Checkable::Ptr& checkable, c result->Set("acknowledgement_type", AcknowledgementNone); } -void ApiEvents::CommentAddedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin) +void ApiEvents::CommentAddedHandler(const Comment::Ptr& comment) { std::vector queues = EventQueue::GetQueuesForType("CommentAdded"); @@ -256,22 +256,14 @@ void ApiEvents::CommentAddedHandler(const Checkable::Ptr& checkable, const Comme result->Set("type", "CommentAdded"); result->Set("timestamp", Utility::GetTime()); - Host::Ptr host; - Service::Ptr service; - tie(host, service) = GetHostService(checkable); - - result->Set("host", host->GetName()); - if (service) - result->Set("service", service->GetShortName()); - - result->Set("comment", Serialize(comment)); + result->Set("comment", Serialize(comment, FAConfig | FAState)); BOOST_FOREACH(const EventQueue::Ptr& queue, queues) { queue->ProcessEvent(result); } } -void ApiEvents::CommentRemovedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin) +void ApiEvents::CommentRemovedHandler(const Comment::Ptr& comment) { std::vector queues = EventQueue::GetQueuesForType("CommentRemoved"); @@ -284,20 +276,14 @@ void ApiEvents::CommentRemovedHandler(const Checkable::Ptr& checkable, const Com result->Set("type", "CommentRemoved"); result->Set("timestamp", Utility::GetTime()); - Host::Ptr host; - Service::Ptr service; - tie(host, service) = GetHostService(checkable); - - result->Set("host", host->GetName()); - if (service) - result->Set("service", service->GetShortName()); + result->Set("comment", Serialize(comment, FAConfig | FAState)); BOOST_FOREACH(const EventQueue::Ptr& queue, queues) { queue->ProcessEvent(result); } } -void ApiEvents::DowntimeAddedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin) +void ApiEvents::DowntimeAddedHandler(const Downtime::Ptr& downtime) { std::vector queues = EventQueue::GetQueuesForType("DowntimeAdded"); @@ -310,22 +296,14 @@ void ApiEvents::DowntimeAddedHandler(const Checkable::Ptr& checkable, const Down result->Set("type", "DowntimeAdded"); result->Set("timestamp", Utility::GetTime()); - Host::Ptr host; - Service::Ptr service; - tie(host, service) = GetHostService(checkable); - - result->Set("host", host->GetName()); - if (service) - result->Set("service", service->GetShortName()); - - result->Set("downtime", Serialize(downtime)); + result->Set("downtime", Serialize(downtime, FAConfig | FAState)); BOOST_FOREACH(const EventQueue::Ptr& queue, queues) { queue->ProcessEvent(result); } } -void ApiEvents::DowntimeRemovedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin) +void ApiEvents::DowntimeRemovedHandler(const Downtime::Ptr& downtime) { std::vector queues = EventQueue::GetQueuesForType("DowntimeRemoved"); @@ -338,20 +316,14 @@ void ApiEvents::DowntimeRemovedHandler(const Checkable::Ptr& checkable, const Do result->Set("type", "DowntimeRemoved"); result->Set("timestamp", Utility::GetTime()); - Host::Ptr host; - Service::Ptr service; - tie(host, service) = GetHostService(checkable); - - result->Set("host", host->GetName()); - if (service) - result->Set("service", service->GetShortName()); + result->Set("downtime", Serialize(downtime, FAConfig | FAState)); BOOST_FOREACH(const EventQueue::Ptr& queue, queues) { queue->ProcessEvent(result); } } -void ApiEvents::DowntimeTriggeredHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime) +void ApiEvents::DowntimeTriggeredHandler(const Downtime::Ptr& downtime) { std::vector queues = EventQueue::GetQueuesForType("DowntimeTriggered"); @@ -364,14 +336,6 @@ void ApiEvents::DowntimeTriggeredHandler(const Checkable::Ptr& checkable, const result->Set("type", "DowntimeTriggered"); result->Set("timestamp", Utility::GetTime()); - Host::Ptr host; - Service::Ptr service; - tie(host, service) = GetHostService(checkable); - - result->Set("host", host->GetName()); - if (service) - result->Set("service", service->GetShortName()); - result->Set("downtime", Serialize(downtime)); BOOST_FOREACH(const EventQueue::Ptr& queue, queues) { diff --git a/lib/icinga/apievents.hpp b/lib/icinga/apievents.hpp index 9e889ffed..e3fc31ba0 100644 --- a/lib/icinga/apievents.hpp +++ b/lib/icinga/apievents.hpp @@ -49,12 +49,12 @@ public: bool notify, double expiry, const MessageOrigin::Ptr& origin); static void AcknowledgementClearedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin); - static void CommentAddedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin); - static void CommentRemovedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin); + static void CommentAddedHandler(const Comment::Ptr& comment); + static void CommentRemovedHandler(const Comment::Ptr& comment); - static void DowntimeAddedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin); - static void DowntimeRemovedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin); - static void DowntimeTriggeredHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime); + static void DowntimeAddedHandler(const Downtime::Ptr& downtime); + static void DowntimeRemovedHandler(const Downtime::Ptr& downtime); + static void DowntimeTriggeredHandler(const Downtime::Ptr& downtime); }; } diff --git a/lib/icinga/checkable-comment.cpp b/lib/icinga/checkable-comment.cpp index 89ea47611..25f0038fd 100644 --- a/lib/icinga/checkable-comment.cpp +++ b/lib/icinga/checkable-comment.cpp @@ -18,6 +18,7 @@ ******************************************************************************/ #include "icinga/service.hpp" +#include "remote/configobjectutility.hpp" #include "base/configtype.hpp" #include "base/objectlock.hpp" #include "base/timer.hpp" @@ -27,218 +28,36 @@ using namespace icinga; -static int l_NextCommentID = 1; -static boost::mutex l_CommentMutex; -static std::map l_LegacyCommentsCache; -static std::map l_CommentsCache; -static Timer::Ptr l_CommentsExpireTimer; - -boost::signals2::signal Checkable::OnCommentAdded; -boost::signals2::signal Checkable::OnCommentRemoved; - -int Checkable::GetNextCommentID(void) -{ - boost::mutex::scoped_lock lock(l_CommentMutex); - - return l_NextCommentID; -} - -String Checkable::AddComment(CommentType entryType, const String& author, - const String& text, double expireTime, const String& id, const MessageOrigin::Ptr& origin) -{ - String uid; - - if (id.IsEmpty()) - uid = Utility::NewUniqueID(); - else - uid = id; - - Comment::Ptr comment = new Comment(); - comment->SetId(uid);; - comment->SetEntryTime(Utility::GetTime()); - comment->SetEntryType(entryType); - comment->SetAuthor(author); - comment->SetText(text); - comment->SetExpireTime(expireTime); - - int legacy_id; - - { - boost::mutex::scoped_lock lock(l_CommentMutex); - legacy_id = l_NextCommentID++; - } - - comment->SetLegacyId(legacy_id); - - GetComments()->Set(uid, comment); - - { - boost::mutex::scoped_lock lock(l_CommentMutex); - l_LegacyCommentsCache[legacy_id] = uid; - l_CommentsCache[uid] = this; - } - - OnCommentAdded(this, comment, origin); - - return uid; -} void Checkable::RemoveAllComments(void) { - std::vector ids; - Dictionary::Ptr comments = GetComments(); - - { - ObjectLock olock(comments); - BOOST_FOREACH(const Dictionary::Pair& kv, comments) { - ids.push_back(kv.first); - } + BOOST_FOREACH(const Comment::Ptr& comment, GetComments()) { + Comment::RemoveComment(comment->GetName()); } - - BOOST_FOREACH(const String& id, ids) { - RemoveComment(id); - } -} - -void Checkable::RemoveComment(const String& id, const MessageOrigin::Ptr& origin) -{ - Checkable::Ptr owner = GetOwnerByCommentID(id); - - if (!owner) - return; - - Dictionary::Ptr comments = owner->GetComments(); - - ObjectLock olock(owner); - - Comment::Ptr comment = comments->Get(id); - - if (!comment) - return; - - int legacy_id = comment->GetLegacyId(); - - comments->Remove(id); - - { - boost::mutex::scoped_lock lock(l_CommentMutex); - l_LegacyCommentsCache.erase(legacy_id); - l_CommentsCache.erase(id); - } - - OnCommentRemoved(owner, comment, origin); -} - -String Checkable::GetCommentIDFromLegacyID(int id) -{ - boost::mutex::scoped_lock lock(l_CommentMutex); - - std::map::iterator it = l_LegacyCommentsCache.find(id); - - if (it == l_LegacyCommentsCache.end()) - return Empty; - - return it->second; -} - -Checkable::Ptr Checkable::GetOwnerByCommentID(const String& id) -{ - boost::mutex::scoped_lock lock(l_CommentMutex); - - return l_CommentsCache[id]; -} - -Comment::Ptr Checkable::GetCommentByID(const String& id) -{ - Checkable::Ptr owner = GetOwnerByCommentID(id); - - if (!owner) - return Comment::Ptr(); - - Dictionary::Ptr comments = owner->GetComments(); - - if (comments) - return comments->Get(id); - - return Comment::Ptr(); } -void Checkable::AddCommentsToCache(void) +void Checkable::RemoveCommentsByType(int type) { -#ifdef I2_DEBUG - Log(LogDebug, "Checkable", "Updating Checkable comments cache."); -#endif /* I2_DEBUG */ - - Dictionary::Ptr comments = GetComments(); - - ObjectLock olock(comments); - - boost::mutex::scoped_lock lock(l_CommentMutex); - - BOOST_FOREACH(const Dictionary::Pair& kv, comments) { - Comment::Ptr comment = kv.second; - - int legacy_id = comment->GetLegacyId(); - - if (legacy_id >= l_NextCommentID) - l_NextCommentID = legacy_id + 1; - - l_LegacyCommentsCache[legacy_id] = kv.first; - l_CommentsCache[kv.first] = this; + BOOST_FOREACH(const Comment::Ptr& comment, GetComments()) { + if (comment->GetEntryType() == type) + Comment::RemoveComment(comment->GetName()); } } -void Checkable::RemoveCommentsByType(int type) +std::set Checkable::GetComments(void) const { - Dictionary::Ptr comments = GetComments(); - - std::vector removedComments; - - { - ObjectLock olock(comments); - - BOOST_FOREACH(const Dictionary::Pair& kv, comments) { - Comment::Ptr comment = kv.second; - - if (comment->GetEntryType() == type) - removedComments.push_back(kv.first); - } - } - - BOOST_FOREACH(const String& id, removedComments) { - RemoveComment(id); - } + boost::mutex::scoped_lock lock(m_CommentMutex); + return m_Comments; } -void Checkable::RemoveExpiredComments(void) +void Checkable::RegisterComment(const Comment::Ptr& comment) { - Dictionary::Ptr comments = GetComments(); - - std::vector expiredComments; - - { - ObjectLock olock(comments); - - BOOST_FOREACH(const Dictionary::Pair& kv, comments) { - Comment::Ptr comment = kv.second; - - if (comment->IsExpired()) - expiredComments.push_back(kv.first); - } - } - - BOOST_FOREACH(const String& id, expiredComments) { - RemoveComment(id); - } + boost::mutex::scoped_lock lock(m_CommentMutex); + m_Comments.insert(comment); } -void Checkable::CommentsExpireTimerHandler(void) +void Checkable::UnregisterComment(const Comment::Ptr& comment) { - BOOST_FOREACH(const Host::Ptr& host, ConfigType::GetObjectsByType()) { - host->RemoveExpiredComments(); - } - - BOOST_FOREACH(const Service::Ptr& service, ConfigType::GetObjectsByType()) { - service->RemoveExpiredComments(); - } + boost::mutex::scoped_lock lock(m_CommentMutex); + m_Comments.erase(comment); } diff --git a/lib/icinga/checkable-downtime.cpp b/lib/icinga/checkable-downtime.cpp index a56d71de9..e41b7a08d 100644 --- a/lib/icinga/checkable-downtime.cpp +++ b/lib/icinga/checkable-downtime.cpp @@ -21,344 +21,29 @@ #include "base/configtype.hpp" #include "base/objectlock.hpp" #include "base/logger.hpp" -#include "base/timer.hpp" #include "base/utility.hpp" #include "base/convert.hpp" #include using namespace icinga; -static int l_NextDowntimeID = 1; -static boost::mutex l_DowntimeMutex; -static std::map l_LegacyDowntimesCache; -static std::map l_DowntimesCache; -static Timer::Ptr l_DowntimesExpireTimer; - -boost::signals2::signal Checkable::OnDowntimeAdded; -boost::signals2::signal Checkable::OnDowntimeRemoved; -boost::signals2::signal Checkable::OnDowntimeTriggered; - -INITIALIZE_ONCE(&Checkable::StartDowntimesExpiredTimer); - -int Checkable::GetNextDowntimeID(void) -{ - boost::mutex::scoped_lock lock(l_DowntimeMutex); - - return l_NextDowntimeID; -} - -String Checkable::AddDowntime(const String& author, const String& comment, - double startTime, double endTime, bool fixed, - const String& triggeredBy, double duration, const String& scheduledBy, - const String& id, const MessageOrigin::Ptr& origin) -{ - String uid; - - if (id.IsEmpty()) - uid = Utility::NewUniqueID(); - else - uid = id; - - Downtime::Ptr downtime = new Downtime(); - downtime->SetId(uid); - downtime->SetEntryTime(Utility::GetTime()); - downtime->SetAuthor(author); - downtime->SetComment(comment); - downtime->SetStartTime(startTime); - downtime->SetEndTime(endTime); - downtime->SetFixed(fixed); - downtime->SetDuration(duration); - downtime->SetTriggeredBy(triggeredBy); - downtime->SetScheduledBy(scheduledBy); - - if (!triggeredBy.IsEmpty()) { - Downtime::Ptr triggerDowntime = GetDowntimeByID(triggeredBy); - - if (triggerDowntime) - downtime->SetTriggeredByLegacyId(triggerDowntime->GetLegacyId()); - } - - int legacy_id; - - { - boost::mutex::scoped_lock lock(l_DowntimeMutex); - legacy_id = l_NextDowntimeID++; - } - - downtime->SetLegacyId(legacy_id); - - if (!triggeredBy.IsEmpty()) { - Checkable::Ptr otherOwner = GetOwnerByDowntimeID(triggeredBy); - Dictionary::Ptr otherDowntimes = otherOwner->GetDowntimes(); - Downtime::Ptr otherDowntime = otherDowntimes->Get(triggeredBy); - Dictionary::Ptr triggers = otherDowntime->GetTriggers(); - - triggers->Set(triggeredBy, triggeredBy); - } - - GetDowntimes()->Set(uid, downtime); - - { - boost::mutex::scoped_lock lock(l_DowntimeMutex); - l_LegacyDowntimesCache[legacy_id] = uid; - l_DowntimesCache[uid] = this; - } - - Log(LogNotice, "Checkable") - << "Added downtime with ID '" << downtime->GetLegacyId() - << "' between '" << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", startTime) - << "' and '" << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", endTime) << "'."; - - OnDowntimeAdded(this, downtime, origin); - - /* if this object is already in a NOT-OK state trigger - * this downtime now *after* it has been added (important - * for DB IDO, etc.) - */ - if (GetStateRaw() != ServiceOK) { - Log(LogNotice, "Checkable") - << "Checkable '" << GetName() << "' already in a NOT-OK state." - << " Triggering downtime now."; - TriggerDowntime(uid); - } - - return uid; -} - -void Checkable::RemoveDowntime(const String& id, bool cancelled, const MessageOrigin::Ptr& origin) -{ - Checkable::Ptr owner = GetOwnerByDowntimeID(id); - - if (!owner) - return; - - Dictionary::Ptr downtimes = owner->GetDowntimes(); - - Downtime::Ptr downtime = downtimes->Get(id); - - if (!downtime) - return; - - int legacy_id = downtime->GetLegacyId(); - - String config_owner = downtime->GetConfigOwner(); - - if (!config_owner.IsEmpty()) { - Log(LogWarning, "Checkable") - << "Cannot remove downtime with ID '" << legacy_id << "'. It is owned by scheduled downtime object '" << config_owner << "'"; - return; - } - - downtimes->Remove(id); - - { - boost::mutex::scoped_lock lock(l_DowntimeMutex); - l_LegacyDowntimesCache.erase(legacy_id); - l_DowntimesCache.erase(id); - } - - downtime->SetWasCancelled(cancelled); - - Log(LogNotice, "Checkable") - << "Removed downtime with ID '" << downtime->GetLegacyId() << "' from service '" << owner->GetName() << "'."; - - OnDowntimeRemoved(owner, downtime, origin); -} - void Checkable::RemoveAllDowntimes(void) { - std::vector ids; - Dictionary::Ptr downtimes = GetDowntimes(); - - { - ObjectLock olock(downtimes); - BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) { - ids.push_back(kv.first); - } - } - - BOOST_FOREACH(const String& id, ids) { - RemoveDowntime(id, true); + BOOST_FOREACH(const Downtime::Ptr& downtime, GetDowntimes()) { + Downtime::RemoveDowntime(downtime->GetName(), true, true); } } void Checkable::TriggerDowntimes(void) { - Dictionary::Ptr downtimes = GetDowntimes(); - - std::vector ids; - - { - ObjectLock olock(downtimes); - - BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) { - ids.push_back(kv.first); - } - } - - BOOST_FOREACH(const String& id, ids) { - TriggerDowntime(id); - } -} - -void Checkable::TriggerDowntime(const String& id) -{ - Checkable::Ptr owner = GetOwnerByDowntimeID(id); - Downtime::Ptr downtime = GetDowntimeByID(id); - - if (!downtime) - return; - - if (downtime->IsActive() && downtime->IsTriggered()) { - Log(LogDebug, "Checkable") - << "Not triggering downtime with ID '" << downtime->GetLegacyId() << "': already triggered."; - return; - } - - if (downtime->IsExpired()) { - Log(LogDebug, "Checkable") - << "Not triggering downtime with ID '" << downtime->GetLegacyId() << "': expired."; - return; - } - - double now = Utility::GetTime(); - - if (now < downtime->GetStartTime() || now > downtime->GetEndTime()) { - Log(LogDebug, "Checkable") - << "Not triggering downtime with ID '" << downtime->GetLegacyId() << "': current time is outside downtime window."; - return; - } - - Log(LogNotice, "Checkable") - << "Triggering downtime with ID '" << downtime->GetLegacyId() << "'."; - - if (downtime->GetTriggerTime() == 0) - downtime->SetTriggerTime(Utility::GetTime()); - - Dictionary::Ptr triggers = downtime->GetTriggers(); - - { - ObjectLock olock(triggers); - BOOST_FOREACH(const Dictionary::Pair& kv, triggers) { - TriggerDowntime(kv.first); - } - } - - OnDowntimeTriggered(owner, downtime); -} - -String Checkable::GetDowntimeIDFromLegacyID(int id) -{ - boost::mutex::scoped_lock lock(l_DowntimeMutex); - - std::map::iterator it = l_LegacyDowntimesCache.find(id); - - if (it == l_LegacyDowntimesCache.end()) - return Empty; - - return it->second; -} - -Checkable::Ptr Checkable::GetOwnerByDowntimeID(const String& id) -{ - boost::mutex::scoped_lock lock(l_DowntimeMutex); - return l_DowntimesCache[id]; -} - -Downtime::Ptr Checkable::GetDowntimeByID(const String& id) -{ - Checkable::Ptr owner = GetOwnerByDowntimeID(id); - - if (!owner) - return Downtime::Ptr(); - - Dictionary::Ptr downtimes = owner->GetDowntimes(); - - if (downtimes) - return downtimes->Get(id); - - return Downtime::Ptr(); -} - -void Checkable::StartDowntimesExpiredTimer(void) -{ - l_DowntimesExpireTimer = new Timer(); - l_DowntimesExpireTimer->SetInterval(60); - l_DowntimesExpireTimer->OnTimerExpired.connect(boost::bind(&Checkable::DowntimesExpireTimerHandler)); - l_DowntimesExpireTimer->Start(); -} - -void Checkable::AddDowntimesToCache(void) -{ -#ifdef I2_DEBUG - Log(LogDebug, "Checkable", "Updating Checkable downtimes cache."); -#endif /* I2_DEBUG */ - - Dictionary::Ptr downtimes = GetDowntimes(); - - boost::mutex::scoped_lock lock(l_DowntimeMutex); - - ObjectLock olock(downtimes); - - BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) { - Downtime::Ptr downtime = kv.second; - - int legacy_id = downtime->GetLegacyId(); - - if (legacy_id >= l_NextDowntimeID) - l_NextDowntimeID = legacy_id + 1; - - l_LegacyDowntimesCache[legacy_id] = kv.first; - l_DowntimesCache[kv.first] = this; - } -} - -void Checkable::RemoveExpiredDowntimes(void) -{ - Dictionary::Ptr downtimes = GetDowntimes(); - - std::vector expiredDowntimes; - - { - ObjectLock olock(downtimes); - - BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) { - Downtime::Ptr downtime = kv.second; - - if (downtime->IsExpired()) - expiredDowntimes.push_back(kv.first); - } - } - - BOOST_FOREACH(const String& id, expiredDowntimes) { - /* override config owner to clear expired downtimes once */ - Downtime::Ptr downtime = GetDowntimeByID(id); - downtime->SetConfigOwner(Empty); - - RemoveDowntime(id, false); - } -} - -void Checkable::DowntimesExpireTimerHandler(void) -{ - BOOST_FOREACH(const Host::Ptr& host, ConfigType::GetObjectsByType()) { - host->RemoveExpiredDowntimes(); - } - - BOOST_FOREACH(const Service::Ptr& service, ConfigType::GetObjectsByType()) { - service->RemoveExpiredDowntimes(); + BOOST_FOREACH(const Downtime::Ptr& downtime, GetDowntimes()) { + downtime->TriggerDowntime(); } } bool Checkable::IsInDowntime(void) const { - Dictionary::Ptr downtimes = GetDowntimes(); - - ObjectLock olock(downtimes); - - BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) { - Downtime::Ptr downtime = kv.second; - + BOOST_FOREACH(const Downtime::Ptr& downtime, GetDowntimes()) { if (downtime->IsActive()) return true; } @@ -369,13 +54,8 @@ bool Checkable::IsInDowntime(void) const int Checkable::GetDowntimeDepth(void) const { int downtime_depth = 0; - Dictionary::Ptr downtimes = GetDowntimes(); - - ObjectLock olock(downtimes); - - BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) { - Downtime::Ptr downtime = kv.second; + BOOST_FOREACH(const Downtime::Ptr& downtime, GetDowntimes()) { if (downtime->IsActive()) downtime_depth++; } @@ -383,3 +63,20 @@ int Checkable::GetDowntimeDepth(void) const return downtime_depth; } +std::set Checkable::GetDowntimes(void) const +{ + boost::mutex::scoped_lock lock(m_DowntimeMutex); + return m_Downtimes; +} + +void Checkable::RegisterDowntime(const Downtime::Ptr& downtime) +{ + boost::mutex::scoped_lock lock(m_DowntimeMutex); + m_Downtimes.insert(downtime); +} + +void Checkable::UnregisterDowntime(const Downtime::Ptr& downtime) +{ + boost::mutex::scoped_lock lock(m_DowntimeMutex); + m_Downtimes.erase(downtime); +} diff --git a/lib/icinga/checkable-notification.cpp b/lib/icinga/checkable-notification.cpp index 160431f56..7e7cf370a 100644 --- a/lib/icinga/checkable-notification.cpp +++ b/lib/icinga/checkable-notification.cpp @@ -88,13 +88,13 @@ std::set Checkable::GetNotifications(void) const return m_Notifications; } -void Checkable::AddNotification(const Notification::Ptr& notification) +void Checkable::RegisterNotification(const Notification::Ptr& notification) { boost::mutex::scoped_lock lock(m_NotificationMutex); m_Notifications.insert(notification); } -void Checkable::RemoveNotification(const Notification::Ptr& notification) +void Checkable::UnregisterNotification(const Notification::Ptr& notification) { boost::mutex::scoped_lock lock(m_NotificationMutex); m_Notifications.erase(notification); diff --git a/lib/icinga/checkable.cpp b/lib/icinga/checkable.cpp index fd985e995..9ebf748f6 100644 --- a/lib/icinga/checkable.cpp +++ b/lib/icinga/checkable.cpp @@ -40,42 +40,14 @@ Checkable::Checkable(void) SetSchedulingOffset(Utility::Random()); } -void Checkable::Start(void) +void Checkable::Start(bool runtimeCreated) { double now = Utility::GetTime(); if (GetNextCheck() < now + 300) UpdateNextCheck(); - ObjectImpl::Start(); -} - -void Checkable::OnStateLoaded(void) -{ - AddDowntimesToCache(); - AddCommentsToCache(); - - std::vector ids; - Dictionary::Ptr downtimes = GetDowntimes(); - - { - ObjectLock dlock(downtimes); - BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) { - Downtime::Ptr downtime = kv.second; - - if (downtime->GetScheduledBy().IsEmpty()) - continue; - - ids.push_back(kv.first); - } - } - - BOOST_FOREACH(const String& id, ids) { - /* override config owner to clear downtimes once */ - Downtime::Ptr downtime = GetDowntimeByID(id); - downtime->SetConfigOwner(Empty); - RemoveDowntime(id, true); - } + ObjectImpl::Start(runtimeCreated); } void Checkable::AddGroup(const String& name) diff --git a/lib/icinga/checkable.hpp b/lib/icinga/checkable.hpp index cf828af93..58e90a9cb 100644 --- a/lib/icinga/checkable.hpp +++ b/lib/icinga/checkable.hpp @@ -75,8 +75,6 @@ public: void AddGroup(const String& name); - //bool IsHostCheck(void) const; - bool IsReachable(DependencyType dt = DependencyState, intrusive_ptr *failedDependency = NULL, int rstack = 0) const; AcknowledgementType GetAcknowledgement(void); @@ -124,62 +122,37 @@ public: static boost::signals2::signal&, const NotificationType&, const CheckResult::Ptr&, const String&, const String&)> OnNotificationSentToAllUsers; - static boost::signals2::signal OnCommentAdded; - static boost::signals2::signal OnCommentRemoved; - static boost::signals2::signal OnDowntimeAdded; - static boost::signals2::signal OnDowntimeRemoved; - static boost::signals2::signal OnDowntimeTriggered; static boost::signals2::signal OnAcknowledgementSet; static boost::signals2::signal OnAcknowledgementCleared; static boost::signals2::signal OnEventCommandExecuted; /* Downtimes */ - static int GetNextDowntimeID(void); - int GetDowntimeDepth(void) const; - String AddDowntime(const String& author, const String& comment, - double startTime, double endTime, bool fixed, - const String& triggeredBy, double duration, - const String& scheduledBy = String(), const String& id = String(), - const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); - void RemoveAllDowntimes(void); - static void RemoveDowntime(const String& id, bool cancelled, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); - void TriggerDowntimes(void); - static void TriggerDowntime(const String& id); - - static String GetDowntimeIDFromLegacyID(int id); - static Checkable::Ptr GetOwnerByDowntimeID(const String& id); - static Downtime::Ptr GetDowntimeByID(const String& id); - - static void StartDowntimesExpiredTimer(void); - bool IsInDowntime(void) const; bool IsAcknowledged(void); - /* Comments */ - static int GetNextCommentID(void); - - String AddComment(CommentType entryType, const String& author, - const String& text, double expireTime, const String& id = String(), const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); + std::set GetDowntimes(void) const; + void RegisterDowntime(const Downtime::Ptr& downtime); + void UnregisterDowntime(const Downtime::Ptr& downtime); + /* Comments */ void RemoveAllComments(void); void RemoveCommentsByType(int type); - static void RemoveComment(const String& id, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); - static String GetCommentIDFromLegacyID(int id); - static Checkable::Ptr GetOwnerByCommentID(const String& id); - static Comment::Ptr GetCommentByID(const String& id); + std::set GetComments(void) const; + void RegisterComment(const Comment::Ptr& comment); + void UnregisterComment(const Comment::Ptr& comment); /* Notifications */ void SendNotifications(NotificationType type, const CheckResult::Ptr& cr, const String& author = "", const String& text = ""); std::set GetNotifications(void) const; - void AddNotification(const Notification::Ptr& notification); - void RemoveNotification(const Notification::Ptr& notification); + void RegisterNotification(const Notification::Ptr& notification); + void UnregisterNotification(const Notification::Ptr& notification); void ResetNotificationNumbers(void); @@ -207,9 +180,7 @@ public: virtual void ValidateCheckInterval(double value, const ValidationUtils& utils) override; protected: - virtual void Start(void) override; - - virtual void OnStateLoaded(void) override; + virtual void Start(bool runtimeCreated) override; private: mutable boost::mutex m_CheckableMutex; @@ -217,14 +188,12 @@ private: long m_SchedulingOffset; /* Downtimes */ - static void DowntimesExpireTimerHandler(void); - void RemoveExpiredDowntimes(void); - void AddDowntimesToCache(void); + std::set m_Downtimes; + mutable boost::mutex m_DowntimeMutex; /* Comments */ - static void CommentsExpireTimerHandler(void); - void RemoveExpiredComments(void); - void AddCommentsToCache(void); + std::set m_Comments; + mutable boost::mutex m_CommentMutex; /* Notifications */ std::set m_Notifications; diff --git a/lib/icinga/checkable.ti b/lib/icinga/checkable.ti index d6ed943c2..433de6509 100644 --- a/lib/icinga/checkable.ti +++ b/lib/icinga/checkable.ti @@ -137,12 +137,6 @@ abstract class Checkable : CustomVarObject default {{{ return AcknowledgementNone; }}} }; [state] double acknowledgement_expiry; - [state, no_user_modify] Dictionary::Ptr comments { - default {{{ return new Dictionary(); }}} - }; - [state, no_user_modify] Dictionary::Ptr downtimes { - default {{{ return new Dictionary(); }}} - }; [state] bool force_next_notification; [state] int flapping_positive; [state] int flapping_negative; diff --git a/lib/icinga/clusterevents.cpp b/lib/icinga/clusterevents.cpp index 1228673d8..e90f5e553 100644 --- a/lib/icinga/clusterevents.cpp +++ b/lib/icinga/clusterevents.cpp @@ -44,10 +44,6 @@ REGISTER_APIFUNCTION(SetNextCheck, event, &ClusterEvents::NextCheckChangedAPIHan REGISTER_APIFUNCTION(SetNextNotification, event, &ClusterEvents::NextNotificationChangedAPIHandler); REGISTER_APIFUNCTION(SetForceNextCheck, event, &ClusterEvents::ForceNextCheckChangedAPIHandler); REGISTER_APIFUNCTION(SetForceNextNotification, event, &ClusterEvents::ForceNextNotificationChangedAPIHandler); -REGISTER_APIFUNCTION(AddComment, event, &ClusterEvents::CommentAddedAPIHandler); -REGISTER_APIFUNCTION(RemoveComment, event, &ClusterEvents::CommentRemovedAPIHandler); -REGISTER_APIFUNCTION(AddDowntime, event, &ClusterEvents::DowntimeAddedAPIHandler); -REGISTER_APIFUNCTION(RemoveDowntime, event, &ClusterEvents::DowntimeRemovedAPIHandler); REGISTER_APIFUNCTION(SetAcknowledgement, event, &ClusterEvents::AcknowledgementSetAPIHandler); REGISTER_APIFUNCTION(ClearAcknowledgement, event, &ClusterEvents::AcknowledgementClearedAPIHandler); REGISTER_APIFUNCTION(UpdateRepository, event, &ClusterEvents::UpdateRepositoryAPIHandler); @@ -63,10 +59,6 @@ void ClusterEvents::StaticInitialize(void) Checkable::OnForceNextCheckChanged.connect(&ClusterEvents::ForceNextCheckChangedHandler); Checkable::OnForceNextNotificationChanged.connect(&ClusterEvents::ForceNextNotificationChangedHandler); - Checkable::OnCommentAdded.connect(&ClusterEvents::CommentAddedHandler); - Checkable::OnCommentRemoved.connect(&ClusterEvents::CommentRemovedHandler); - Checkable::OnDowntimeAdded.connect(&ClusterEvents::DowntimeAddedHandler); - Checkable::OnDowntimeRemoved.connect(&ClusterEvents::DowntimeRemovedHandler); Checkable::OnAcknowledgementSet.connect(&ClusterEvents::AcknowledgementSetHandler); Checkable::OnAcknowledgementCleared.connect(&ClusterEvents::AcknowledgementClearedHandler); @@ -423,273 +415,6 @@ Value ClusterEvents::ForceNextNotificationChangedAPIHandler(const MessageOrigin: return Empty; } -void ClusterEvents::CommentAddedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin) -{ - ApiListener::Ptr listener = ApiListener::GetInstance(); - - if (!listener) - return; - - Host::Ptr host; - Service::Ptr service; - tie(host, service) = GetHostService(checkable); - - Dictionary::Ptr params = new Dictionary(); - params->Set("host", host->GetName()); - if (service) - params->Set("service", service->GetShortName()); - params->Set("comment", Serialize(comment)); - - Dictionary::Ptr message = new Dictionary(); - message->Set("jsonrpc", "2.0"); - message->Set("method", "event::AddComment"); - message->Set("params", params); - - listener->RelayMessage(origin, checkable, message, true); -} - -Value ClusterEvents::CommentAddedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) -{ - Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); - - if (!endpoint) { - Log(LogNotice, "ClusterEvents") - << "Discarding 'comment added' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed)."; - return Empty; - } - - if (!params) - return Empty; - - Host::Ptr host = Host::GetByName(params->Get("host")); - - if (!host) - return Empty; - - Checkable::Ptr checkable; - - if (params->Contains("service")) - checkable = host->GetServiceByShortName(params->Get("service")); - else - checkable = host; - - if (!checkable) - return Empty; - - if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) { - Log(LogNotice, "ClusterEvents") - << "Discarding 'comment added' message from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; - return Empty; - } - - Comment::Ptr comment = new Comment(); - Deserialize(comment, params->Get("comment"), true); - - checkable->AddComment(comment->GetEntryType(), comment->GetAuthor(), - comment->GetText(), comment->GetExpireTime(), comment->GetId(), origin); - - return Empty; -} - -void ClusterEvents::CommentRemovedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin) -{ - ApiListener::Ptr listener = ApiListener::GetInstance(); - - if (!listener) - return; - - Host::Ptr host; - Service::Ptr service; - tie(host, service) = GetHostService(checkable); - - Dictionary::Ptr params = new Dictionary(); - params->Set("host", host->GetName()); - if (service) - params->Set("service", service->GetShortName()); - params->Set("id", comment->GetId()); - - Dictionary::Ptr message = new Dictionary(); - message->Set("jsonrpc", "2.0"); - message->Set("method", "event::RemoveComment"); - message->Set("params", params); - - listener->RelayMessage(origin, checkable, message, true); -} - -Value ClusterEvents::CommentRemovedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) -{ - Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); - - if (!endpoint) { - Log(LogNotice, "ClusterEvents") - << "Discarding 'comment removed' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed)."; - return Empty; - } - - if (!params) - return Empty; - - Host::Ptr host = Host::GetByName(params->Get("host")); - - if (!host) - return Empty; - - Checkable::Ptr checkable; - - if (params->Contains("service")) - checkable = host->GetServiceByShortName(params->Get("service")); - else - checkable = host; - - if (!checkable) - return Empty; - - if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) { - Log(LogNotice, "ClusterEvents") - << "Discarding 'comment removed' message from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; - return Empty; - } - - checkable->RemoveComment(params->Get("id"), origin); - - return Empty; -} - -void ClusterEvents::DowntimeAddedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin) -{ - ApiListener::Ptr listener = ApiListener::GetInstance(); - - if (!listener) - return; - - Host::Ptr host; - Service::Ptr service; - tie(host, service) = GetHostService(checkable); - - Dictionary::Ptr params = new Dictionary(); - params->Set("host", host->GetName()); - if (service) - params->Set("service", service->GetShortName()); - params->Set("downtime", Serialize(downtime)); - - Dictionary::Ptr message = new Dictionary(); - message->Set("jsonrpc", "2.0"); - message->Set("method", "event::AddDowntime"); - message->Set("params", params); - - listener->RelayMessage(origin, checkable, message, true); -} - -Value ClusterEvents::DowntimeAddedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) -{ - Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); - - if (!endpoint) { - Log(LogNotice, "ClusterEvents") - << "Discarding 'downtime added' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed)."; - return Empty; - } - - if (!params) - return Empty; - - Host::Ptr host = Host::GetByName(params->Get("host")); - - if (!host) - return Empty; - - Checkable::Ptr checkable; - - if (params->Contains("service")) - checkable = host->GetServiceByShortName(params->Get("service")); - else - checkable = host; - - if (!checkable) - return Empty; - - if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) { - Log(LogNotice, "ClusterEvents") - << "Discarding 'downtime added' message from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; - return Empty; - } - - Downtime::Ptr downtime = new Downtime(); - Deserialize(downtime, params->Get("downtime"), true); - - checkable->AddDowntime(downtime->GetAuthor(), downtime->GetComment(), - downtime->GetStartTime(), downtime->GetEndTime(), - downtime->GetFixed(), downtime->GetTriggeredBy(), - downtime->GetDuration(), downtime->GetScheduledBy(), - downtime->GetId(), origin); - - return Empty; -} - -void ClusterEvents::DowntimeRemovedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin) -{ - ApiListener::Ptr listener = ApiListener::GetInstance(); - - if (!listener) - return; - - Host::Ptr host; - Service::Ptr service; - tie(host, service) = GetHostService(checkable); - - Dictionary::Ptr params = new Dictionary(); - params->Set("host", host->GetName()); - if (service) - params->Set("service", service->GetShortName()); - params->Set("id", downtime->GetId()); - - Dictionary::Ptr message = new Dictionary(); - message->Set("jsonrpc", "2.0"); - message->Set("method", "event::RemoveDowntime"); - message->Set("params", params); - - listener->RelayMessage(origin, checkable, message, true); -} - -Value ClusterEvents::DowntimeRemovedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) -{ - Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); - - if (!endpoint) { - Log(LogNotice, "ClusterEvents") - << "Discarding 'downtime removed' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed)."; - return Empty; - } - - if (!params) - return Empty; - - Host::Ptr host = Host::GetByName(params->Get("host")); - - if (!host) - return Empty; - - Checkable::Ptr checkable; - - if (params->Contains("service")) - checkable = host->GetServiceByShortName(params->Get("service")); - else - checkable = host; - - if (!checkable) - return Empty; - - if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) { - Log(LogNotice, "ClusterEvents") - << "Discarding 'downtime removed' message from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; - return Empty; - } - - checkable->RemoveDowntime(params->Get("id"), false, origin); - - return Empty; -} - void ClusterEvents::AcknowledgementSetHandler(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, bool notify, double expiry, const MessageOrigin::Ptr& origin) diff --git a/lib/icinga/clusterevents.hpp b/lib/icinga/clusterevents.hpp index ab6c9d166..4087a4262 100644 --- a/lib/icinga/clusterevents.hpp +++ b/lib/icinga/clusterevents.hpp @@ -52,18 +52,6 @@ public: static void ForceNextNotificationChangedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin); static Value ForceNextNotificationChangedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); - static void CommentAddedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin); - static Value CommentAddedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); - - static void CommentRemovedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin); - static Value CommentRemovedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); - - static void DowntimeAddedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin); - static Value DowntimeAddedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); - - static void DowntimeRemovedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin); - static Value DowntimeRemovedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); - static void AcknowledgementSetHandler(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, bool notify, double expiry, const MessageOrigin::Ptr& origin); static Value AcknowledgementSetAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); diff --git a/lib/icinga/comment.cpp b/lib/icinga/comment.cpp index bdbfcc50e..5f69e669e 100644 --- a/lib/icinga/comment.cpp +++ b/lib/icinga/comment.cpp @@ -19,16 +19,229 @@ #include "icinga/comment.hpp" #include "icinga/comment.tcpp" +#include "icinga/host.hpp" +#include "remote/configobjectutility.hpp" #include "base/utility.hpp" #include "base/configtype.hpp" +#include "base/timer.hpp" +#include +#include +#include using namespace icinga; +static int l_NextCommentID = 1; +static boost::mutex l_CommentMutex; +static std::map l_LegacyCommentsCache; +static Timer::Ptr l_CommentsExpireTimer; + +boost::signals2::signal Comment::OnCommentAdded; +boost::signals2::signal Comment::OnCommentRemoved; + +INITIALIZE_ONCE(&Comment::StaticInitialize); + REGISTER_TYPE(Comment); +void Comment::StaticInitialize(void) +{ + l_CommentsExpireTimer = new Timer(); + l_CommentsExpireTimer->SetInterval(60); + l_CommentsExpireTimer->OnTimerExpired.connect(boost::bind(&Comment::CommentsExpireTimerHandler)); + l_CommentsExpireTimer->Start(); +} + +String CommentNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const +{ + Comment::Ptr comment = dynamic_pointer_cast(context); + + if (!comment) + return ""; + + String name = comment->GetHostName(); + + if (!comment->GetServiceName().IsEmpty()) + name += "!" + comment->GetServiceName(); + + name += "!" + shortName; + + return name; +} + +Dictionary::Ptr CommentNameComposer::ParseName(const String& name) const +{ + std::vector tokens; + boost::algorithm::split(tokens, name, boost::is_any_of("!")); + + if (tokens.size() < 2) + BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid Comment name.")); + + Dictionary::Ptr result = new Dictionary(); + result->Set("host_name", tokens[0]); + + if (tokens.size() > 2) { + result->Set("service_name", tokens[1]); + result->Set("name", tokens[2]); + } else { + result->Set("name", tokens[1]); + } + + return result; +} + +void Comment::OnAllConfigLoaded(void) +{ + ConfigObject::OnAllConfigLoaded(); + + Host::Ptr host = Host::GetByName(GetHostName()); + + if (GetServiceName().IsEmpty()) + m_Checkable = host; + else + m_Checkable = host->GetServiceByShortName(GetServiceName()); + + if (!m_Checkable) + BOOST_THROW_EXCEPTION(ScriptError("Comment '" + GetName() + "' references a host/service which doesn't exist.", GetDebugInfo())); +} + +void Comment::Start(bool runtimeCreated) +{ + ObjectImpl::Start(runtimeCreated); + + { + boost::mutex::scoped_lock lock(l_CommentMutex); + + SetLegacyId(l_NextCommentID); + l_LegacyCommentsCache[l_NextCommentID] = GetName(); + l_NextCommentID++; + } + + GetCheckable()->RegisterComment(this); + + if (runtimeCreated) + OnCommentAdded(this); +} + +void Comment::Stop(bool runtimeRemoved) +{ + GetCheckable()->UnregisterComment(this); + + if (runtimeRemoved) + OnCommentRemoved(this); + + ObjectImpl::Stop(runtimeRemoved); +} + +Checkable::Ptr Comment::GetCheckable(void) const +{ + return m_Checkable; +} + bool Comment::IsExpired(void) const { double expire_time = GetExpireTime(); return (expire_time != 0 && expire_time < Utility::GetTime()); } + +int Comment::GetNextCommentID(void) +{ + boost::mutex::scoped_lock lock(l_CommentMutex); + + return l_NextCommentID; +} + +String Comment::AddComment(const Checkable::Ptr& checkable, CommentType entryType, const String& author, + const String& text, double expireTime, const String& id, const MessageOrigin::Ptr& origin) +{ + String fullName; + + if (id.IsEmpty()) + fullName = checkable->GetName() + "!" + Utility::NewUniqueID(); + else + fullName = id; + + Dictionary::Ptr attrs = new Dictionary(); + + attrs->Set("author", author); + attrs->Set("text", text); + attrs->Set("expire_time", expireTime); + attrs->Set("entry_type", entryType); + + Host::Ptr host; + Service::Ptr service; + tie(host, service) = GetHostService(checkable); + + attrs->Set("host_name", host->GetName()); + if (service) + attrs->Set("service_name", service->GetShortName()); + + String config = ConfigObjectUtility::CreateObjectConfig(Comment::TypeInstance, fullName, true, Array::Ptr(), attrs); + + Array::Ptr errors = new Array(); + + if (!ConfigObjectUtility::CreateObject(Comment::TypeInstance, fullName, config, errors)) { + ObjectLock olock(errors); + BOOST_FOREACH(const String& error, errors) { + Log(LogCritical, "Comment", error); + } + + BOOST_THROW_EXCEPTION(std::runtime_error("Could not create comment.")); + } + + Comment::Ptr comment = Comment::GetByName(fullName); + + Log(LogNotice, "Comment") + << "Added comment '" << comment->GetName() << "'."; + + return fullName; +} + +void Comment::RemoveComment(const String& id, const MessageOrigin::Ptr& origin) +{ + Comment::Ptr comment = Comment::GetByName(id); + + if (!comment) + return; + + int legacy_id = comment->GetLegacyId(); + + Log(LogNotice, "Comment") + << "Removed comment '" << comment->GetName() << "' from object '" << comment->GetCheckable()->GetName() << "'."; + + Array::Ptr errors = new Array(); + + if (!ConfigObjectUtility::DeleteObject(comment, false, errors)) { + ObjectLock olock(errors); + BOOST_FOREACH(const String& error, errors) { + Log(LogCritical, "Comment", error); + } + + BOOST_THROW_EXCEPTION(std::runtime_error("Could not remove comment.")); + } +} + +String Comment::GetCommentIDFromLegacyID(int id) +{ + boost::mutex::scoped_lock lock(l_CommentMutex); + + std::map::iterator it = l_LegacyCommentsCache.find(id); + + if (it == l_LegacyCommentsCache.end()) + return Empty; + + return it->second; +} + +void Comment::CommentsExpireTimerHandler(void) +{ + std::vector comments; + + BOOST_FOREACH(const Comment::Ptr& comment, ConfigType::GetObjectsByType()) { + comments.push_back(comment); + } + + BOOST_FOREACH(const Comment::Ptr& comment, comments) { + if (comment->IsExpired()) + RemoveComment(comment->GetName()); + } +} diff --git a/lib/icinga/comment.hpp b/lib/icinga/comment.hpp index cb6d65f09..052d8b353 100644 --- a/lib/icinga/comment.hpp +++ b/lib/icinga/comment.hpp @@ -22,12 +22,15 @@ #include "icinga/i2-icinga.hpp" #include "icinga/comment.thpp" +#include "remote/messageorigin.hpp" namespace icinga { +class Checkable; + /** - * A service comment. + * A comment. * * @ingroup icinga */ @@ -35,8 +38,36 @@ class I2_ICINGA_API Comment : public ObjectImpl { public: DECLARE_OBJECT(Comment); + DECLARE_OBJECTNAME(Comment); + + static boost::signals2::signal OnCommentAdded; + static boost::signals2::signal OnCommentRemoved; + + intrusive_ptr GetCheckable(void) const; bool IsExpired(void) const; + + static int GetNextCommentID(void); + + static String AddComment(const intrusive_ptr& checkable, CommentType entryType, + const String& author, const String& text, double expireTime, + const String& id = String(), const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); + + static void RemoveComment(const String& id, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); + + static String GetCommentIDFromLegacyID(int id); + + static void StaticInitialize(void); + +protected: + virtual void OnAllConfigLoaded(void) override; + virtual void Start(bool runtimeCreated) override; + virtual void Stop(bool runtimeRemoved) override; + +private: + intrusive_ptr m_Checkable; + + static void CommentsExpireTimerHandler(void); }; } diff --git a/lib/icinga/comment.ti b/lib/icinga/comment.ti index c05dc0d62..a3b711a59 100644 --- a/lib/icinga/comment.ti +++ b/lib/icinga/comment.ti @@ -17,6 +17,10 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ******************************************************************************/ +#include "base/configobject.hpp" +#include "base/utility.hpp" +#impl_include "icinga/service.hpp" + library icinga; namespace icinga @@ -35,17 +39,56 @@ enum CommentType CommentFlapping = 3, CommentAcknowledgement = 4 }; + +class I2_ICINGA_API CommentNameComposer : public NameComposer +{ +public: + virtual String MakeName(const String& shortName, const Object::Ptr& context) const; + virtual Dictionary::Ptr ParseName(const String& name) const; +}; }}} -class Comment +class Comment : ConfigObject < CommentNameComposer { - [state] String id; - [state] double entry_time; - [state, enum] CommentType entry_type; - [state] String author; - [state] String text; - [state] double expire_time; - [state] int legacy_id; + load_after Host; + load_after Service; + + [config, protected, required, navigation(host)] name(Host) host_name { + navigate {{{ + return Host::GetByName(GetHostName()); + }}} + }; + [config, protected, navigation(service)] String service_name { + track {{{ + if (!oldValue.IsEmpty()) { + Service::Ptr service = Service::GetByNamePair(GetHostName(), oldValue); + DependencyGraph::RemoveDependency(this, service.get()); + } + + if (!newValue.IsEmpty()) { + Service::Ptr service = Service::GetByNamePair(GetHostName(), newValue); + DependencyGraph::RemoveDependency(this, service.get()); + } + }}} + navigate {{{ + if (GetServiceName().IsEmpty()) + return Service::Ptr(); + + Host::Ptr host = Host::GetByName(GetHostName()); + return host->GetServiceByShortName(GetServiceName()); + }}} + }; + + [config] double entry_time { + default {{{ return Utility::GetTime(); }}} + }; + [config, enum] CommentType entry_type { + default {{{ return CommentUser; }}} + }; + [config, required] String author; + [config, required] String text; + [config] double expire_time; + int legacy_id; }; } diff --git a/lib/icinga/dependency.cpp b/lib/icinga/dependency.cpp index 45f275b49..b670cce6a 100644 --- a/lib/icinga/dependency.cpp +++ b/lib/icinga/dependency.cpp @@ -123,9 +123,9 @@ void Dependency::OnAllConfigLoaded(void) m_Parent->AddReverseDependency(this); } -void Dependency::Stop(void) +void Dependency::Stop(bool runtimeRemoved) { - ObjectImpl::Stop(); + ObjectImpl::Stop(runtimeRemoved); GetChild()->RemoveDependency(this); GetParent()->RemoveReverseDependency(this); diff --git a/lib/icinga/dependency.hpp b/lib/icinga/dependency.hpp index 8a85de173..3ed4b1458 100644 --- a/lib/icinga/dependency.hpp +++ b/lib/icinga/dependency.hpp @@ -59,7 +59,7 @@ public: protected: virtual void OnConfigLoaded(void) override; virtual void OnAllConfigLoaded(void) override; - virtual void Stop(void) override; + virtual void Stop(bool runtimeRemoved) override; private: Checkable::Ptr m_Parent; diff --git a/lib/icinga/downtime.cpp b/lib/icinga/downtime.cpp index 8c37a3d03..b418e9390 100644 --- a/lib/icinga/downtime.cpp +++ b/lib/icinga/downtime.cpp @@ -19,12 +19,137 @@ #include "icinga/downtime.hpp" #include "icinga/downtime.tcpp" +#include "icinga/host.hpp" +#include "remote/configobjectutility.hpp" +#include "base/configtype.hpp" #include "base/utility.hpp" +#include "base/timer.hpp" +#include +#include +#include using namespace icinga; +static int l_NextDowntimeID = 1; +static boost::mutex l_DowntimeMutex; +static std::map l_LegacyDowntimesCache; +static Timer::Ptr l_DowntimesExpireTimer; + +boost::signals2::signal Downtime::OnDowntimeAdded; +boost::signals2::signal Downtime::OnDowntimeRemoved; +boost::signals2::signal Downtime::OnDowntimeTriggered; + +INITIALIZE_ONCE(&Downtime::StaticInitialize); + REGISTER_TYPE(Downtime); +void Downtime::StaticInitialize(void) +{ + l_DowntimesExpireTimer = new Timer(); + l_DowntimesExpireTimer->SetInterval(60); + l_DowntimesExpireTimer->OnTimerExpired.connect(boost::bind(&Downtime::DowntimesExpireTimerHandler)); + l_DowntimesExpireTimer->Start(); +} + +String DowntimeNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const +{ + Downtime::Ptr downtime = dynamic_pointer_cast(context); + + if (!downtime) + return ""; + + String name = downtime->GetHostName(); + + if (!downtime->GetServiceName().IsEmpty()) + name += "!" + downtime->GetServiceName(); + + name += "!" + shortName; + + return name; +} + +Dictionary::Ptr DowntimeNameComposer::ParseName(const String& name) const +{ + std::vector tokens; + boost::algorithm::split(tokens, name, boost::is_any_of("!")); + + if (tokens.size() < 2) + BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid Downtime name.")); + + Dictionary::Ptr result = new Dictionary(); + result->Set("host_name", tokens[0]); + + if (tokens.size() > 2) { + result->Set("service_name", tokens[1]); + result->Set("name", tokens[2]); + } else { + result->Set("name", tokens[1]); + } + + return result; +} + +void Downtime::OnAllConfigLoaded(void) +{ + ObjectImpl::OnAllConfigLoaded(); + + Host::Ptr host = Host::GetByName(GetHostName()); + + if (GetServiceName().IsEmpty()) + m_Checkable = host; + else + m_Checkable = host->GetServiceByShortName(GetServiceName()); + + if (!m_Checkable) + BOOST_THROW_EXCEPTION(ScriptError("Downtime '" + GetName() + "' references a host/service which doesn't exist.", GetDebugInfo())); +} + +void Downtime::Start(bool runtimeCreated) +{ + ObjectImpl::Start(runtimeCreated); + + { + boost::mutex::scoped_lock lock(l_DowntimeMutex); + + SetLegacyId(l_NextDowntimeID); + l_LegacyDowntimesCache[l_NextDowntimeID] = GetName(); + l_NextDowntimeID++; + } + + Checkable::Ptr checkable = GetCheckable(); + + checkable->RegisterDowntime(this); + + if (runtimeCreated) + OnDowntimeAdded(this); + + /* if this object is already in a NOT-OK state trigger + * this downtime now *after* it has been added (important + * for DB IDO, etc.) + */ + if (checkable->GetStateRaw() != ServiceOK) { + Log(LogNotice, "Downtime") + << "Checkable '" << checkable->GetName() << "' already in a NOT-OK state." + << " Triggering downtime now."; + TriggerDowntime(); + } +} + +void Downtime::Stop(bool runtimeRemoved) +{ + GetCheckable()->UnregisterDowntime(this); + + if (runtimeRemoved) + OnDowntimeRemoved(this); + + ObjectImpl::Stop(runtimeRemoved); +} + +Checkable::Ptr Downtime::GetCheckable(void) const +{ + return m_Checkable; +} + bool Downtime::IsActive(void) const { double now = Utility::GetTime(); @@ -57,3 +182,189 @@ bool Downtime::IsExpired(void) const { return (GetEndTime() < Utility::GetTime()); } + +int Downtime::GetNextDowntimeID(void) +{ + boost::mutex::scoped_lock lock(l_DowntimeMutex); + + return l_NextDowntimeID; +} + +String Downtime::AddDowntime(const Checkable::Ptr& checkable, const String& author, + const String& comment, double startTime, double endTime, bool fixed, + const String& triggeredBy, double duration, + const String& scheduledDowntime, const String& scheduledBy, + const String& id, const MessageOrigin::Ptr& origin) +{ + String fullName; + + if (id.IsEmpty()) + fullName = checkable->GetName() + "!" + Utility::NewUniqueID(); + else + fullName = id; + + Dictionary::Ptr attrs = new Dictionary(); + + attrs->Set("author", author); + attrs->Set("comment", comment); + attrs->Set("start_time", startTime); + attrs->Set("end_time", endTime); + attrs->Set("fixed", fixed); + attrs->Set("duration", duration); + attrs->Set("triggered_by", triggeredBy); + attrs->Set("scheduled_by", scheduledBy); + attrs->Set("config_owner", scheduledDowntime); + + Host::Ptr host; + Service::Ptr service; + tie(host, service) = GetHostService(checkable); + + attrs->Set("host_name", host->GetName()); + if (service) + attrs->Set("service_name", service->GetShortName()); + + String config = ConfigObjectUtility::CreateObjectConfig(Downtime::TypeInstance, fullName, true, Array::Ptr(), attrs); + + Array::Ptr errors = new Array(); + + if (!ConfigObjectUtility::CreateObject(Downtime::TypeInstance, fullName, config, errors)) { + ObjectLock olock(errors); + BOOST_FOREACH(const String& error, errors) { + Log(LogCritical, "Downtime", error); + } + + BOOST_THROW_EXCEPTION(std::runtime_error("Could not create downtime.")); + } + + if (!triggeredBy.IsEmpty()) { + Downtime::Ptr triggerDowntime = Downtime::GetByName(triggeredBy); + Array::Ptr triggers = triggerDowntime->GetTriggers(); + + if (!triggers->Contains(triggeredBy)) + triggers->Add(triggeredBy); + } + + Downtime::Ptr downtime = Downtime::GetByName(fullName); + + Log(LogNotice, "Downtime") + << "Added downtime '" << downtime->GetName() + << "' between '" << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", startTime) + << "' and '" << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", endTime) << "'."; + + + return fullName; +} + +void Downtime::RemoveDowntime(const String& id, bool cancelled, bool expired, const MessageOrigin::Ptr& origin) +{ + Downtime::Ptr downtime = Downtime::GetByName(id); + + if (!downtime) + return; + + String config_owner = downtime->GetConfigOwner(); + + if (!config_owner.IsEmpty() && !expired) { + Log(LogWarning, "Downtime") + << "Cannot remove downtime '" << downtime->GetName() << "'. It is owned by scheduled downtime object '" << config_owner << "'"; + return; + } + + downtime->SetWasCancelled(cancelled); + + Log(LogNotice, "Downtime") + << "Removed downtime '" << downtime->GetName() << "' from object '" << downtime->GetCheckable()->GetName() << "'."; + + Array::Ptr errors = new Array(); + + if (!ConfigObjectUtility::DeleteObject(downtime, false, errors)) { + ObjectLock olock(errors); + BOOST_FOREACH(const String& error, errors) { + Log(LogCritical, "Downtime", error); + } + + BOOST_THROW_EXCEPTION(std::runtime_error("Could not remove downtime.")); + } +} + +void Downtime::TriggerDowntime(void) +{ + if (IsActive() && IsTriggered()) { + Log(LogDebug, "Downtime") + << "Not triggering downtime '" << GetName() << "': already triggered."; + return; + } + + if (IsExpired()) { + Log(LogDebug, "Downtime") + << "Not triggering downtime '" << GetName() << "': expired."; + return; + } + + double now = Utility::GetTime(); + + if (now < GetStartTime() || now > GetEndTime()) { + Log(LogDebug, "Downtime") + << "Not triggering downtime '" << GetName() << "': current time is outside downtime window."; + return; + } + + Log(LogNotice, "Downtime") + << "Triggering downtime '" << GetName() << "'."; + + if (GetTriggerTime() == 0) + SetTriggerTime(Utility::GetTime()); + + Array::Ptr triggers = GetTriggers(); + + { + ObjectLock olock(triggers); + BOOST_FOREACH(const String& id, triggers) { + Downtime::GetByName(id)->TriggerDowntime(); + } + } + + OnDowntimeTriggered(this); +} + +String Downtime::GetDowntimeIDFromLegacyID(int id) +{ + boost::mutex::scoped_lock lock(l_DowntimeMutex); + + std::map::iterator it = l_LegacyDowntimesCache.find(id); + + if (it == l_LegacyDowntimesCache.end()) + return Empty; + + return it->second; +} + +void Downtime::DowntimesExpireTimerHandler(void) +{ + std::vector downtimes; + + BOOST_FOREACH(const Downtime::Ptr& downtime, ConfigType::GetObjectsByType()) { + downtimes.push_back(downtime); + } + + BOOST_FOREACH(const Downtime::Ptr& downtime, downtimes) { + if (downtime->IsExpired()) + RemoveDowntime(downtime->GetName(), false, true); + } +} + +void Downtime::ValidateStartTime(double value, const ValidationUtils& utils) +{ + ObjectImpl::ValidateStartTime(value, utils); + + if (value <= 0) + BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("start_time"), "Start time must be greater than 0.")); +} + +void Downtime::ValidateEndTime(double value, const ValidationUtils& utils) +{ + ObjectImpl::ValidateEndTime(value, utils); + + if (value <= 0) + BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("end_time"), "End time must be greater than 0.")); +} diff --git a/lib/icinga/downtime.hpp b/lib/icinga/downtime.hpp index 2fb6337eb..25407a353 100644 --- a/lib/icinga/downtime.hpp +++ b/lib/icinga/downtime.hpp @@ -22,12 +22,15 @@ #include "icinga/i2-icinga.hpp" #include "icinga/downtime.thpp" +#include "remote/messageorigin.hpp" namespace icinga { +class Checkable; + /** - * A service downtime. + * A downtime. * * @ingroup icinga */ @@ -35,11 +38,46 @@ class I2_ICINGA_API Downtime : public ObjectImpl { public: DECLARE_OBJECT(Downtime); + DECLARE_OBJECTNAME(Downtime); + + static boost::signals2::signal OnDowntimeAdded; + static boost::signals2::signal OnDowntimeRemoved; + static boost::signals2::signal OnDowntimeTriggered; + + intrusive_ptr GetCheckable(void) const; bool IsActive(void) const; bool IsTriggered(void) const; bool IsExpired(void) const; + static int GetNextDowntimeID(void); + + static String AddDowntime(const intrusive_ptr& checkable, const String& author, + const String& comment, double startTime, double endTime, bool fixed, + const String& triggeredBy, double duration, const String& scheduledDowntime = String(), + const String& scheduledBy = String(), const String& id = String(), + const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); + + static void RemoveDowntime(const String& id, bool cancelled, bool expired = false, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); + + void TriggerDowntime(void); + + static String GetDowntimeIDFromLegacyID(int id); + + static void StaticInitialize(void); + +protected: + virtual void OnAllConfigLoaded(void) override; + virtual void Start(bool runtimeCreated) override; + virtual void Stop(bool runtimeRemoved) override; + + virtual void ValidateStartTime(double value, const ValidationUtils& utils) override; + virtual void ValidateEndTime(double value, const ValidationUtils& utils) override; + +private: + intrusive_ptr m_Checkable; + + static void DowntimesExpireTimerHandler(void); }; } diff --git a/lib/icinga/downtime.ti b/lib/icinga/downtime.ti index c41c03bea..e6be9d443 100644 --- a/lib/icinga/downtime.ti +++ b/lib/icinga/downtime.ti @@ -17,31 +17,73 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ******************************************************************************/ +#include "base/configobject.hpp" +#include "base/utility.hpp" +#impl_include "icinga/service.hpp" + library icinga; namespace icinga { -class Downtime +code {{{ +class I2_ICINGA_API DowntimeNameComposer : public NameComposer +{ +public: + virtual String MakeName(const String& shortName, const Object::Ptr& context) const; + virtual Dictionary::Ptr ParseName(const String& name) const; +}; +}}} + +class Downtime : ConfigObject < DowntimeNameComposer { - [state] String id; - [state] double entry_time; - [state] String author; - [state] String comment; - [state] double start_time; - [state] double end_time; + load_after Host; + load_after Service; + + [config, protected, required, navigation(host)] name(Host) host_name { + navigate {{{ + return Host::GetByName(GetHostName()); + }}} + }; + [config, protected, navigation(service)] String service_name { + track {{{ + if (!oldValue.IsEmpty()) { + Service::Ptr service = Service::GetByNamePair(GetHostName(), oldValue); + DependencyGraph::RemoveDependency(this, service.get()); + } + + if (!newValue.IsEmpty()) { + Service::Ptr service = Service::GetByNamePair(GetHostName(), newValue); + DependencyGraph::RemoveDependency(this, service.get()); + } + }}} + navigate {{{ + if (GetServiceName().IsEmpty()) + return Service::Ptr(); + + Host::Ptr host = Host::GetByName(GetHostName()); + return host->GetServiceByShortName(GetServiceName()); + }}} + }; + + [state] double entry_time { + default {{{ return Utility::GetTime(); }}} + }; + [config, required] String author; + [config, required] String comment; + [config] double start_time; + [config] double end_time; [state] double trigger_time; - [state] bool fixed; - [state] double duration; - [state] int triggered_by_legacy_id; - [state] String triggered_by; - [state] String scheduled_by; - [state] Dictionary::Ptr triggers { - default {{{ return new Dictionary(); }}} + [config] bool fixed; + [config] double duration; + [state] name(Downtime) triggered_by; + [config] String scheduled_by; + [config] Array::Ptr triggers { + default {{{ return new Array(); }}} }; - [state] int legacy_id; + int legacy_id; [state] bool was_cancelled; - [state] String config_owner; + [config] String config_owner; }; } diff --git a/lib/icinga/externalcommandprocessor.cpp b/lib/icinga/externalcommandprocessor.cpp index bb99d9da2..59f42353b 100644 --- a/lib/icinga/externalcommandprocessor.cpp +++ b/lib/icinga/externalcommandprocessor.cpp @@ -602,7 +602,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const std::vectorGetName() << "'" << (notify ? "" : ". Disabled notification"); - service->AddComment(CommentAcknowledgement, arguments[5], arguments[6], 0); + Comment::AddComment(service, CommentAcknowledgement, arguments[5], arguments[6], 0); service->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify); } @@ -623,7 +623,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const std::ve Log(LogNotice, "ExternalCommandProcessor") << "Setting timed acknowledgement for service '" << service->GetName() << "'" << (notify ? "" : ". Disabled notification"); - service->AddComment(CommentAcknowledgement, arguments[6], arguments[7], timestamp); + Comment::AddComment(service, CommentAcknowledgement, arguments[6], arguments[7], timestamp); service->AcknowledgeProblem(arguments[6], arguments[7], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, timestamp); } @@ -661,7 +661,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblem(double, const std::vector< if (host->GetState() == HostUp) BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK.")); - host->AddComment(CommentAcknowledgement, arguments[4], arguments[5], 0); + Comment::AddComment(host, CommentAcknowledgement, arguments[4], arguments[5], 0); host->AcknowledgeProblem(arguments[4], arguments[5], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify); } @@ -682,7 +682,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const std::v if (host->GetState() == HostUp) BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK.")); - host->AddComment(CommentAcknowledgement, arguments[5], arguments[6], timestamp); + Comment::AddComment(host, CommentAcknowledgement, arguments[5], arguments[6], timestamp); host->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, timestamp); } @@ -925,11 +925,11 @@ void ExternalCommandProcessor::ScheduleSvcDowntime(double, const std::vectorGetName(); - (void) service->AddDowntime(arguments[7], arguments[8], + (void) Downtime::AddDowntime(service, arguments[7], arguments[8], Convert::ToDouble(arguments[2]), Convert::ToDouble(arguments[3]), Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[6])); } @@ -939,8 +939,8 @@ void ExternalCommandProcessor::DelSvcDowntime(double, const std::vector& int id = Convert::ToLong(arguments[0]); Log(LogNotice, "ExternalCommandProcessor") << "Removing downtime ID " << arguments[0]; - String rid = Service::GetDowntimeIDFromLegacyID(id); - Service::RemoveDowntime(rid, true); + String rid = Downtime::GetDowntimeIDFromLegacyID(id); + Downtime::RemoveDowntime(rid, true); } void ExternalCommandProcessor::ScheduleHostDowntime(double, const std::vector& arguments) @@ -954,12 +954,12 @@ void ExternalCommandProcessor::ScheduleHostDowntime(double, const std::vectorGetName(); - (void) host->AddDowntime(arguments[6], arguments[7], + (void) Downtime::AddDowntime(host, arguments[6], arguments[7], Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]), Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5])); } @@ -969,8 +969,8 @@ void ExternalCommandProcessor::DelHostDowntime(double, const std::vector int id = Convert::ToLong(arguments[0]); Log(LogNotice, "ExternalCommandProcessor") << "Removing downtime ID " << arguments[0]; - String rid = Service::GetDowntimeIDFromLegacyID(id); - Service::RemoveDowntime(rid, true); + String rid = Downtime::GetDowntimeIDFromLegacyID(id); + Downtime::RemoveDowntime(rid, true); } void ExternalCommandProcessor::DelDowntimeByHostName(double, const std::vector& arguments) @@ -996,41 +996,29 @@ void ExternalCommandProcessor::DelDowntimeByHostName(double, const std::vector ids; + BOOST_FOREACH(const Downtime::Ptr& downtime, host->GetDowntimes()) { + Log(LogNotice, "ExternalCommandProcessor") + << "Removing downtime '" << downtime->GetName() << "'."; - Dictionary::Ptr hostDowntimes = host->GetDowntimes(); - { - ObjectLock dhlock(hostDowntimes); - BOOST_FOREACH(const Dictionary::Pair& kv, hostDowntimes) { - ids.push_back(kv.first); - } + Downtime::RemoveDowntime(downtime->GetName(), true); } BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) { if (!serviceName.IsEmpty() && serviceName != service->GetName()) continue; - Dictionary::Ptr serviceDowntimes = service->GetDowntimes(); - { - ObjectLock dslock(serviceDowntimes); - BOOST_FOREACH(const Dictionary::Pair& kv, serviceDowntimes) { - ids.push_back(kv.first); - } - } - } + BOOST_FOREACH(const Downtime::Ptr& downtime, service->GetDowntimes()) { + if (!startTime.IsEmpty() && downtime->GetStartTime() != Convert::ToDouble(startTime)) + continue; - BOOST_FOREACH(const String& id, ids) { - Downtime::Ptr downtime = Service::GetDowntimeByID(id); + if (!commentString.IsEmpty() && downtime->GetComment() != commentString) + continue; - if (!startTime.IsEmpty() && downtime->GetStartTime() != Convert::ToDouble(startTime)) - continue; - - if (!commentString.IsEmpty() && downtime->GetComment() != commentString) - continue; + Log(LogNotice, "ExternalCommandProcessor") + << "Removing downtime '" << downtime->GetName() << "'."; - Log(LogNotice, "ExternalCommandProcessor") - << "Removing downtime ID " << id; - Service::RemoveDowntime(id, true); + Downtime::RemoveDowntime(downtime->GetName(), true); + } } } @@ -1045,19 +1033,19 @@ void ExternalCommandProcessor::ScheduleHostSvcDowntime(double, const std::vector int triggeredByLegacy = Convert::ToLong(arguments[4]); int is_fixed = Convert::ToLong(arguments[3]); if (triggeredByLegacy != 0) - triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy); + triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy); Log(LogNotice, "ExternalCommandProcessor") << "Creating downtime for host " << host->GetName(); - (void) host->AddDowntime(arguments[6], arguments[7], + (void) Downtime::AddDowntime(host, arguments[6], arguments[7], Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]), Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5])); BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) { Log(LogNotice, "ExternalCommandProcessor") << "Creating downtime for service " << service->GetName(); - (void) service->AddDowntime(arguments[6], arguments[7], + (void) Downtime::AddDowntime(service, arguments[6], arguments[7], Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]), Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5])); } @@ -1074,13 +1062,13 @@ void ExternalCommandProcessor::ScheduleHostgroupHostDowntime(double, const std:: int triggeredByLegacy = Convert::ToLong(arguments[4]); int is_fixed = Convert::ToLong(arguments[3]); if (triggeredByLegacy != 0) - triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy); + triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy); BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) { Log(LogNotice, "ExternalCommandProcessor") << "Creating downtime for host " << host->GetName(); - (void) host->AddDowntime(arguments[6], arguments[7], + (void) Downtime::AddDowntime(host, arguments[6], arguments[7], Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]), Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5])); } @@ -1097,7 +1085,7 @@ void ExternalCommandProcessor::ScheduleHostgroupSvcDowntime(double, const std::v int triggeredByLegacy = Convert::ToLong(arguments[4]); int is_fixed = Convert::ToLong(arguments[3]); if (triggeredByLegacy != 0) - triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy); + triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy); /* Note: we can't just directly create downtimes for all the services by iterating * over all hosts in the host group - otherwise we might end up creating multiple @@ -1114,7 +1102,7 @@ void ExternalCommandProcessor::ScheduleHostgroupSvcDowntime(double, const std::v BOOST_FOREACH(const Service::Ptr& service, services) { Log(LogNotice, "ExternalCommandProcessor") << "Creating downtime for service " << service->GetName(); - (void) service->AddDowntime(arguments[6], arguments[7], + (void) Downtime::AddDowntime(service, arguments[6], arguments[7], Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]), Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5])); } @@ -1131,7 +1119,7 @@ void ExternalCommandProcessor::ScheduleServicegroupHostDowntime(double, const st int triggeredByLegacy = Convert::ToLong(arguments[4]); int is_fixed = Convert::ToLong(arguments[3]); if (triggeredByLegacy != 0) - triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy); + triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy); /* Note: we can't just directly create downtimes for all the hosts by iterating * over all services in the service group - otherwise we might end up creating multiple @@ -1147,7 +1135,7 @@ void ExternalCommandProcessor::ScheduleServicegroupHostDowntime(double, const st BOOST_FOREACH(const Host::Ptr& host, hosts) { Log(LogNotice, "ExternalCommandProcessor") << "Creating downtime for host " << host->GetName(); - (void) host->AddDowntime(arguments[6], arguments[7], + (void) Downtime::AddDowntime(host, arguments[6], arguments[7], Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]), Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5])); } @@ -1164,12 +1152,12 @@ void ExternalCommandProcessor::ScheduleServicegroupSvcDowntime(double, const std int triggeredByLegacy = Convert::ToLong(arguments[4]); int is_fixed = Convert::ToLong(arguments[3]); if (triggeredByLegacy != 0) - triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy); + triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy); BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) { Log(LogNotice, "ExternalCommandProcessor") << "Creating downtime for service " << service->GetName(); - (void) service->AddDowntime(arguments[6], arguments[7], + (void) Downtime::AddDowntime(service, arguments[6], arguments[7], Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]), Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5])); } @@ -1184,7 +1172,7 @@ void ExternalCommandProcessor::AddHostComment(double, const std::vector& Log(LogNotice, "ExternalCommandProcessor") << "Creating comment for host " << host->GetName(); - (void) host->AddComment(CommentUser, arguments[2], arguments[3], 0); + (void) Comment::AddComment(host, CommentUser, arguments[2], arguments[3], 0); } void ExternalCommandProcessor::DelHostComment(double, const std::vector& arguments) @@ -1192,8 +1180,8 @@ void ExternalCommandProcessor::DelHostComment(double, const std::vector& int id = Convert::ToLong(arguments[0]); Log(LogNotice, "ExternalCommandProcessor") << "Removing comment ID " << arguments[0]; - String rid = Service::GetCommentIDFromLegacyID(id); - Service::RemoveComment(rid); + String rid = Comment::GetCommentIDFromLegacyID(id); + Comment::RemoveComment(rid); } void ExternalCommandProcessor::AddSvcComment(double, const std::vector& arguments) @@ -1205,7 +1193,7 @@ void ExternalCommandProcessor::AddSvcComment(double, const std::vector& Log(LogNotice, "ExternalCommandProcessor") << "Creating comment for service " << service->GetName(); - (void) service->AddComment(CommentUser, arguments[3], arguments[4], 0); + (void) Comment::AddComment(service, CommentUser, arguments[3], arguments[4], 0); } void ExternalCommandProcessor::DelSvcComment(double, const std::vector& arguments) @@ -1214,8 +1202,8 @@ void ExternalCommandProcessor::DelSvcComment(double, const std::vector& Log(LogNotice, "ExternalCommandProcessor") << "Removing comment ID " << arguments[0]; - String rid = Service::GetCommentIDFromLegacyID(id); - Service::RemoveComment(rid); + String rid = Comment::GetCommentIDFromLegacyID(id); + Comment::RemoveComment(rid); } void ExternalCommandProcessor::DelAllHostComments(double, const std::vector& arguments) diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index 8b7dd25a0..7cecf285a 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -71,9 +71,9 @@ void Host::CreateChildObjects(const Type::Ptr& childType) Service::EvaluateApplyRules(this); } -void Host::Stop(void) +void Host::Stop(bool runtimeRemoved) { - ObjectImpl::Stop(); + ObjectImpl::Stop(runtimeRemoved); Array::Ptr groups = GetGroups(); diff --git a/lib/icinga/host.hpp b/lib/icinga/host.hpp index 8f64a52c7..8afa9dae5 100644 --- a/lib/icinga/host.hpp +++ b/lib/icinga/host.hpp @@ -66,7 +66,7 @@ public: virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const override; protected: - virtual void Stop(void) override; + virtual void Stop(bool runtimeRemoved) override; virtual void OnAllConfigLoaded(void) override; virtual void CreateChildObjects(const Type::Ptr& childType) override; diff --git a/lib/icinga/icingastatuswriter.cpp b/lib/icinga/icingastatuswriter.cpp index d9be27dfc..069dab852 100644 --- a/lib/icinga/icingastatuswriter.cpp +++ b/lib/icinga/icingastatuswriter.cpp @@ -56,9 +56,9 @@ void IcingaStatusWriter::StatsFunc(const Dictionary::Ptr& status, const Array::P /** * Starts the component. */ -void IcingaStatusWriter::Start(void) +void IcingaStatusWriter::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); /* TODO: remove in versions > 2.4 */ Log(LogWarning, "IcingaStatusWriter", "This feature was deprecated in 2.4 and will be removed in future Icinga 2 releases."); diff --git a/lib/icinga/icingastatuswriter.hpp b/lib/icinga/icingastatuswriter.hpp index e2a458640..90b1704b8 100644 --- a/lib/icinga/icingastatuswriter.hpp +++ b/lib/icinga/icingastatuswriter.hpp @@ -39,7 +39,7 @@ public: static Dictionary::Ptr GetStatusData(void); protected: - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: Timer::Ptr m_StatusTimer; diff --git a/lib/icinga/notification.cpp b/lib/icinga/notification.cpp index 5c25ffbbe..30e6cb1c9 100644 --- a/lib/icinga/notification.cpp +++ b/lib/icinga/notification.cpp @@ -99,48 +99,52 @@ void Notification::StaticInitialize(void) void Notification::OnConfigLoaded(void) { + ObjectImpl::OnConfigLoaded(); + SetTypeFilter(FilterArrayToInt(GetTypes(), ~0)); SetStateFilter(FilterArrayToInt(GetStates(), ~0)); } void Notification::OnAllConfigLoaded(void) { - Checkable::Ptr obj = GetCheckable(); + ObjectImpl::OnAllConfigLoaded(); + + Host::Ptr host = Host::GetByName(GetHostName()); - if (!obj) + if (GetServiceName().IsEmpty()) + m_Checkable = host; + else + m_Checkable = host->GetServiceByShortName(GetServiceName()); + + if (!m_Checkable) BOOST_THROW_EXCEPTION(ScriptError("Notification object refers to a host/service which doesn't exist.", GetDebugInfo())); - obj->AddNotification(this); + m_Checkable->RegisterNotification(this); } -void Notification::Start(void) +void Notification::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); Checkable::Ptr obj = GetCheckable(); if (obj) - obj->AddNotification(this); + obj->RegisterNotification(this); } -void Notification::Stop(void) +void Notification::Stop(bool runtimeRemoved) { - ObjectImpl::Stop(); + ObjectImpl::Stop(runtimeRemoved); Checkable::Ptr obj = GetCheckable(); if (obj) - obj->RemoveNotification(this); + obj->UnregisterNotification(this); } Checkable::Ptr Notification::GetCheckable(void) const { - Host::Ptr host = Host::GetByName(GetHostName()); - - if (GetServiceName().IsEmpty()) - return host; - else - return host->GetServiceByShortName(GetServiceName()); + return m_Checkable; } NotificationCommand::Ptr Notification::GetCommand(void) const diff --git a/lib/icinga/notification.hpp b/lib/icinga/notification.hpp index 4fa7538d8..6286fe884 100644 --- a/lib/icinga/notification.hpp +++ b/lib/icinga/notification.hpp @@ -118,10 +118,12 @@ public: protected: virtual void OnConfigLoaded(void) override; virtual void OnAllConfigLoaded(void) override; - virtual void Start(void) override; - virtual void Stop(void) override; + virtual void Start(bool runtimeCreated) override; + virtual void Stop(bool runtimeRemoved) override; private: + intrusive_ptr m_Checkable; + void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = ""); static bool EvaluateApplyRuleInstance(const intrusive_ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule); diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp index 763e9fa7e..d03734a54 100644 --- a/lib/icinga/scheduleddowntime.cpp +++ b/lib/icinga/scheduleddowntime.cpp @@ -96,11 +96,11 @@ void ScheduledDowntime::OnAllConfigLoaded(void) BOOST_THROW_EXCEPTION(ScriptError("ScheduledDowntime '" + GetName() + "' references a host/service which doesn't exist.", GetDebugInfo())); } -void ScheduledDowntime::Start(void) +void ScheduledDowntime::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); - CreateNextDowntime(); + Utility::QueueAsyncCallback(boost::bind(&ScheduledDowntime::CreateNextDowntime, this)); } void ScheduledDowntime::TimerProc(void) @@ -168,20 +168,13 @@ std::pair ScheduledDowntime::FindNextSegment(void) void ScheduledDowntime::CreateNextDowntime(void) { - Dictionary::Ptr downtimes = GetCheckable()->GetDowntimes(); - - { - ObjectLock dlock(downtimes); - BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) { - Downtime::Ptr downtime = kv.second; - - if (downtime->GetScheduledBy() != GetName() || - downtime->GetStartTime() < Utility::GetTime()) - continue; + BOOST_FOREACH(const Downtime::Ptr& downtime, GetCheckable()->GetDowntimes()) { + if (downtime->GetScheduledBy() != GetName() || + downtime->GetStartTime() < Utility::GetTime()) + continue; - /* We've found a downtime that is owned by us and that hasn't started yet - we're done. */ - return; - } + /* We've found a downtime that is owned by us and that hasn't started yet - we're done. */ + return; } std::pair segment = FindNextSegment(); @@ -196,12 +189,9 @@ void ScheduledDowntime::CreateNextDowntime(void) return; } - String uid = GetCheckable()->AddDowntime(GetAuthor(), GetComment(), + Downtime::AddDowntime(GetCheckable(), GetAuthor(), GetComment(), segment.first, segment.second, - GetFixed(), String(), GetDuration(), GetName()); - - Downtime::Ptr downtime = Checkable::GetDowntimeByID(uid); - downtime->SetConfigOwner(GetName()); + GetFixed(), String(), GetDuration(), GetName(), GetName()); } void ScheduledDowntime::ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils) diff --git a/lib/icinga/scheduleddowntime.hpp b/lib/icinga/scheduleddowntime.hpp index 592f23865..cdca82274 100644 --- a/lib/icinga/scheduleddowntime.hpp +++ b/lib/icinga/scheduleddowntime.hpp @@ -57,7 +57,7 @@ public: protected: virtual void OnAllConfigLoaded(void) override; - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: static void TimerProc(void); diff --git a/lib/icinga/timeperiod.cpp b/lib/icinga/timeperiod.cpp index 651a0d3f4..243eea62a 100644 --- a/lib/icinga/timeperiod.cpp +++ b/lib/icinga/timeperiod.cpp @@ -44,9 +44,9 @@ void TimePeriod::StaticInitialize(void) l_UpdateTimer->Start(); } -void TimePeriod::Start(void) +void TimePeriod::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); /* Pre-fill the time period for the next 24 hours. */ double now = Utility::GetTime(); diff --git a/lib/icinga/timeperiod.hpp b/lib/icinga/timeperiod.hpp index f7120c1f1..716c12cc6 100644 --- a/lib/icinga/timeperiod.hpp +++ b/lib/icinga/timeperiod.hpp @@ -39,7 +39,7 @@ public: static void StaticInitialize(void); - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; void UpdateRegion(double begin, double end, bool clearExisting); diff --git a/lib/icinga/user.cpp b/lib/icinga/user.cpp index 048109e6c..81795db41 100644 --- a/lib/icinga/user.cpp +++ b/lib/icinga/user.cpp @@ -60,9 +60,9 @@ void User::OnAllConfigLoaded(void) } } -void User::Stop(void) +void User::Stop(bool runtimeRemoved) { - ObjectImpl::Stop(); + ObjectImpl::Stop(runtimeRemoved); Array::Ptr groups = GetGroups(); diff --git a/lib/icinga/user.hpp b/lib/icinga/user.hpp index e86f71e81..378fae058 100644 --- a/lib/icinga/user.hpp +++ b/lib/icinga/user.hpp @@ -48,7 +48,7 @@ public: virtual void ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) override; protected: - virtual void Stop(void) override; + virtual void Stop(bool runtimeRemoved) override; virtual void OnConfigLoaded(void) override; virtual void OnAllConfigLoaded(void) override; diff --git a/lib/livestatus/commentstable.cpp b/lib/livestatus/commentstable.cpp index c182c84d4..283b2aa80 100644 --- a/lib/livestatus/commentstable.cpp +++ b/lib/livestatus/commentstable.cpp @@ -65,34 +65,9 @@ String CommentsTable::GetPrefix(void) const void CommentsTable::FetchRows(const AddRowFunction& addRowFn) { - BOOST_FOREACH(const Host::Ptr& host, ConfigType::GetObjectsByType()) { - Dictionary::Ptr comments = host->GetComments(); - - ObjectLock olock(comments); - - String id; - Comment::Ptr comment; - BOOST_FOREACH(tie(id, comment), comments) { - if (Host::GetOwnerByCommentID(id) == host) { - if (!addRowFn(comment, LivestatusGroupByNone, Empty)) - return; - } - } - } - - BOOST_FOREACH(const Service::Ptr& service, ConfigType::GetObjectsByType()) { - Dictionary::Ptr comments = service->GetComments(); - - ObjectLock olock(comments); - - String id; - Comment::Ptr comment; - BOOST_FOREACH(tie(id, comment), comments) { - if (Service::GetOwnerByCommentID(id) == service) { - if (!addRowFn(comment, LivestatusGroupByNone, Empty)) - return; - } - } + BOOST_FOREACH(const Comment::Ptr& comment, ConfigType::GetObjectsByType()) { + if (!addRowFn(comment, LivestatusGroupByNone, Empty)) + return; } } @@ -100,7 +75,7 @@ Object::Ptr CommentsTable::HostAccessor(const Value& row, const Column::ObjectAc { Comment::Ptr comment = static_cast(row); - Checkable::Ptr checkable = Checkable::GetOwnerByCommentID(comment->GetId()); + Checkable::Ptr checkable = comment->GetCheckable(); Host::Ptr host; Service::Ptr service; @@ -113,7 +88,7 @@ Object::Ptr CommentsTable::ServiceAccessor(const Value& row, const Column::Objec { Comment::Ptr comment = static_cast(row); - Checkable::Ptr checkable = Checkable::GetOwnerByCommentID(comment->GetId()); + Checkable::Ptr checkable = comment->GetCheckable(); Host::Ptr host; Service::Ptr service; @@ -165,7 +140,7 @@ Value CommentsTable::EntryTimeAccessor(const Value& row) Value CommentsTable::TypeAccessor(const Value& row) { Comment::Ptr comment = static_cast(row); - Checkable::Ptr checkable = Checkable::GetOwnerByCommentID(comment->GetId()); + Checkable::Ptr checkable = comment->GetCheckable(); if (!checkable) return Empty; @@ -179,7 +154,7 @@ Value CommentsTable::TypeAccessor(const Value& row) Value CommentsTable::IsServiceAccessor(const Value& row) { Comment::Ptr comment = static_cast(row); - Checkable::Ptr checkable = Checkable::GetOwnerByCommentID(comment->GetId()); + Checkable::Ptr checkable = comment->GetCheckable(); if (!checkable) return Empty; diff --git a/lib/livestatus/downtimestable.cpp b/lib/livestatus/downtimestable.cpp index 0bfc301e9..a081c22b2 100644 --- a/lib/livestatus/downtimestable.cpp +++ b/lib/livestatus/downtimestable.cpp @@ -65,34 +65,9 @@ String DowntimesTable::GetPrefix(void) const void DowntimesTable::FetchRows(const AddRowFunction& addRowFn) { - BOOST_FOREACH(const Host::Ptr& host, ConfigType::GetObjectsByType()) { - Dictionary::Ptr downtimes = host->GetDowntimes(); - - ObjectLock olock(downtimes); - - String id; - Downtime::Ptr downtime; - BOOST_FOREACH(boost::tie(id, downtime), downtimes) { - if (Host::GetOwnerByDowntimeID(id) == host) { - if (!addRowFn(downtime, LivestatusGroupByNone, Empty)) - return; - } - } - } - - BOOST_FOREACH(const Service::Ptr& service, ConfigType::GetObjectsByType()) { - Dictionary::Ptr downtimes = service->GetDowntimes(); - - ObjectLock olock(downtimes); - - String id; - Downtime::Ptr downtime; - BOOST_FOREACH(boost::tie(id, downtime), downtimes) { - if (Service::GetOwnerByDowntimeID(id) == service) { - if (!addRowFn(downtime, LivestatusGroupByNone, Empty)) - return; - } - } + BOOST_FOREACH(const Downtime::Ptr& downtime, ConfigType::GetObjectsByType()) { + if (!addRowFn(downtime, LivestatusGroupByNone, Empty)) + return; } } @@ -100,7 +75,7 @@ Object::Ptr DowntimesTable::HostAccessor(const Value& row, const Column::ObjectA { Downtime::Ptr downtime = static_cast(row); - Checkable::Ptr checkable = Checkable::GetOwnerByDowntimeID(downtime->GetId()); + Checkable::Ptr checkable = downtime->GetCheckable(); Host::Ptr host; Service::Ptr service; @@ -113,7 +88,7 @@ Object::Ptr DowntimesTable::ServiceAccessor(const Value& row, const Column::Obje { Downtime::Ptr downtime = static_cast(row); - Checkable::Ptr checkable = Checkable::GetOwnerByDowntimeID(downtime->GetId()); + Checkable::Ptr checkable = downtime->GetCheckable(); Host::Ptr host; Service::Ptr service; @@ -160,7 +135,7 @@ Value DowntimesTable::TypeAccessor(const Value& row) Value DowntimesTable::IsServiceAccessor(const Value& row) { Downtime::Ptr downtime = static_cast(row); - Checkable::Ptr checkable = Checkable::GetOwnerByDowntimeID(downtime->GetId()); + Checkable::Ptr checkable = downtime->GetCheckable(); return (dynamic_pointer_cast(checkable) ? 0 : 1); } @@ -197,5 +172,12 @@ Value DowntimesTable::TriggeredByAccessor(const Value& row) { Downtime::Ptr downtime = static_cast(row); - return downtime->GetTriggeredByLegacyId(); + String triggerDowntimeName = downtime->GetTriggeredBy(); + + Downtime::Ptr triggerDowntime = Downtime::GetByName(triggerDowntimeName); + + if (triggerDowntime) + return triggerDowntime->GetLegacyId(); + + return Empty; } diff --git a/lib/livestatus/hoststable.cpp b/lib/livestatus/hoststable.cpp index 50bb95b31..38e4c97af 100644 --- a/lib/livestatus/hoststable.cpp +++ b/lib/livestatus/hoststable.cpp @@ -902,26 +902,16 @@ Value HostsTable::DowntimesAccessor(const Value& row) if (!host) return Empty; - Dictionary::Ptr downtimes = host->GetDowntimes(); - - Array::Ptr ids = new Array(); - - ObjectLock olock(downtimes); - - String id; - Downtime::Ptr downtime; - BOOST_FOREACH(tie(id, downtime), downtimes) { - - if (!downtime) - continue; + Array::Ptr results = new Array(); + BOOST_FOREACH(const Downtime::Ptr& downtime, host->GetDowntimes()) { if (downtime->IsExpired()) continue; - ids->Add(downtime->GetLegacyId()); + results->Add(downtime->GetLegacyId()); } - return ids; + return results; } Value HostsTable::DowntimesWithInfoAccessor(const Value& row) @@ -931,19 +921,9 @@ Value HostsTable::DowntimesWithInfoAccessor(const Value& row) if (!host) return Empty; - Dictionary::Ptr downtimes = host->GetDowntimes(); - - Array::Ptr ids = new Array(); - - ObjectLock olock(downtimes); - - String id; - Downtime::Ptr downtime; - BOOST_FOREACH(tie(id, downtime), downtimes) { - - if (!downtime) - continue; + Array::Ptr results = new Array(); + BOOST_FOREACH(const Downtime::Ptr& downtime, host->GetDowntimes()) { if (downtime->IsExpired()) continue; @@ -951,10 +931,10 @@ Value HostsTable::DowntimesWithInfoAccessor(const Value& row) downtime_info->Add(downtime->GetLegacyId()); downtime_info->Add(downtime->GetAuthor()); downtime_info->Add(downtime->GetComment()); - ids->Add(downtime_info); + results->Add(downtime_info); } - return ids; + return results; } Value HostsTable::CommentsAccessor(const Value& row) @@ -964,26 +944,15 @@ Value HostsTable::CommentsAccessor(const Value& row) if (!host) return Empty; - Dictionary::Ptr comments = host->GetComments(); - - Array::Ptr ids = new Array(); - - ObjectLock olock(comments); - - String id; - Comment::Ptr comment; - BOOST_FOREACH(tie(id, comment), comments) { - - if (!comment) - continue; - + Array::Ptr results = new Array(); + BOOST_FOREACH(const Comment::Ptr& comment, host->GetComments()) { if (comment->IsExpired()) continue; - ids->Add(comment->GetLegacyId()); + results->Add(comment->GetLegacyId()); } - return ids; + return results; } Value HostsTable::CommentsWithInfoAccessor(const Value& row) @@ -993,19 +962,9 @@ Value HostsTable::CommentsWithInfoAccessor(const Value& row) if (!host) return Empty; - Dictionary::Ptr comments = host->GetComments(); - - Array::Ptr ids = new Array(); - - ObjectLock olock(comments); - - String id; - Comment::Ptr comment; - BOOST_FOREACH(tie(id, comment), comments) { - - if (!comment) - continue; + Array::Ptr results = new Array(); + BOOST_FOREACH(const Comment::Ptr& comment, host->GetComments()) { if (comment->IsExpired()) continue; @@ -1013,10 +972,10 @@ Value HostsTable::CommentsWithInfoAccessor(const Value& row) comment_info->Add(comment->GetLegacyId()); comment_info->Add(comment->GetAuthor()); comment_info->Add(comment->GetText()); - ids->Add(comment_info); + results->Add(comment_info); } - return ids; + return results; } Value HostsTable::CommentsWithExtraInfoAccessor(const Value& row) @@ -1026,19 +985,9 @@ Value HostsTable::CommentsWithExtraInfoAccessor(const Value& row) if (!host) return Empty; - Dictionary::Ptr comments = host->GetComments(); - - Array::Ptr ids = new Array(); - - ObjectLock olock(comments); - - String id; - Comment::Ptr comment; - BOOST_FOREACH(tie(id, comment), comments) { - - if (!comment) - continue; + Array::Ptr results = new Array(); + BOOST_FOREACH(const Comment::Ptr& comment, host->GetComments()) { if (comment->IsExpired()) continue; @@ -1048,10 +997,10 @@ Value HostsTable::CommentsWithExtraInfoAccessor(const Value& row) comment_info->Add(comment->GetText()); comment_info->Add(comment->GetEntryType()); comment_info->Add(static_cast(comment->GetEntryTime())); - ids->Add(comment_info); + results->Add(comment_info); } - return ids; + return results; } Value HostsTable::CustomVariableNamesAccessor(const Value& row) diff --git a/lib/livestatus/livestatuslistener.cpp b/lib/livestatus/livestatuslistener.cpp index b12a6b076..67547e561 100644 --- a/lib/livestatus/livestatuslistener.cpp +++ b/lib/livestatus/livestatuslistener.cpp @@ -62,9 +62,9 @@ void LivestatusListener::StatsFunc(const Dictionary::Ptr& status, const Array::P /** * Starts the component. */ -void LivestatusListener::Start(void) +void LivestatusListener::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); if (GetSocketType() == "tcp") { TcpSocket::Ptr socket = new TcpSocket(); @@ -119,9 +119,9 @@ void LivestatusListener::Start(void) } } -void LivestatusListener::Stop(void) +void LivestatusListener::Stop(bool runtimeRemoved) { - ObjectImpl::Stop(); + ObjectImpl::Stop(runtimeRemoved); m_Listener->Close(); diff --git a/lib/livestatus/livestatuslistener.hpp b/lib/livestatus/livestatuslistener.hpp index f0b1f12b5..21a5e390f 100644 --- a/lib/livestatus/livestatuslistener.hpp +++ b/lib/livestatus/livestatuslistener.hpp @@ -48,8 +48,8 @@ public: virtual void ValidateSocketType(const String& value, const ValidationUtils& utils) override; protected: - virtual void Start(void) override; - virtual void Stop(void) override; + virtual void Start(bool runtimeCreated) override; + virtual void Stop(bool runtimeRemoved) override; private: void ServerThreadProc(void); diff --git a/lib/livestatus/servicestable.cpp b/lib/livestatus/servicestable.cpp index 2043dda48..291c6eed6 100644 --- a/lib/livestatus/servicestable.cpp +++ b/lib/livestatus/servicestable.cpp @@ -940,26 +940,16 @@ Value ServicesTable::DowntimesAccessor(const Value& row) if (!service) return Empty; - Dictionary::Ptr downtimes = service->GetDowntimes(); - - Array::Ptr ids = new Array(); - - ObjectLock olock(downtimes); - - String id; - Downtime::Ptr downtime; - BOOST_FOREACH(tie(id, downtime), downtimes) { - - if (!downtime) - continue; + Array::Ptr results = new Array(); + BOOST_FOREACH(const Downtime::Ptr& downtime, service->GetDowntimes()) { if (downtime->IsExpired()) continue; - ids->Add(downtime->GetLegacyId()); + results->Add(downtime->GetLegacyId()); } - return ids; + return results; } Value ServicesTable::DowntimesWithInfoAccessor(const Value& row) @@ -969,19 +959,9 @@ Value ServicesTable::DowntimesWithInfoAccessor(const Value& row) if (!service) return Empty; - Dictionary::Ptr downtimes = service->GetDowntimes(); - - Array::Ptr ids = new Array(); - - ObjectLock olock(downtimes); - - String id; - Downtime::Ptr downtime; - BOOST_FOREACH(tie(id, downtime), downtimes) { - - if (!downtime) - continue; + Array::Ptr results = new Array(); + BOOST_FOREACH(const Downtime::Ptr& downtime, service->GetDowntimes()) { if (downtime->IsExpired()) continue; @@ -989,10 +969,10 @@ Value ServicesTable::DowntimesWithInfoAccessor(const Value& row) downtime_info->Add(downtime->GetLegacyId()); downtime_info->Add(downtime->GetAuthor()); downtime_info->Add(downtime->GetComment()); - ids->Add(downtime_info); + results->Add(downtime_info); } - return ids; + return results; } Value ServicesTable::CommentsAccessor(const Value& row) @@ -1002,26 +982,16 @@ Value ServicesTable::CommentsAccessor(const Value& row) if (!service) return Empty; - Dictionary::Ptr comments = service->GetComments(); - - Array::Ptr ids = new Array(); - - ObjectLock olock(comments); - - String id; - Comment::Ptr comment; - BOOST_FOREACH(tie(id, comment), comments) { - - if (!comment) - continue; + Array::Ptr results = new Array(); + BOOST_FOREACH(const Comment::Ptr& comment, service->GetComments()) { if (comment->IsExpired()) continue; - ids->Add(comment->GetLegacyId()); + results->Add(comment->GetLegacyId()); } - return ids; + return results; } Value ServicesTable::CommentsWithInfoAccessor(const Value& row) @@ -1031,19 +1001,9 @@ Value ServicesTable::CommentsWithInfoAccessor(const Value& row) if (!service) return Empty; - Dictionary::Ptr comments = service->GetComments(); - - Array::Ptr ids = new Array(); - - ObjectLock olock(comments); - - String id; - Comment::Ptr comment; - BOOST_FOREACH(tie(id, comment), comments) { - - if (!comment) - continue; + Array::Ptr results = new Array(); + BOOST_FOREACH(const Comment::Ptr& comment, service->GetComments()) { if (comment->IsExpired()) continue; @@ -1051,10 +1011,10 @@ Value ServicesTable::CommentsWithInfoAccessor(const Value& row) comment_info->Add(comment->GetLegacyId()); comment_info->Add(comment->GetAuthor()); comment_info->Add(comment->GetText()); - ids->Add(comment_info); + results->Add(comment_info); } - return ids; + return results; } Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row) @@ -1064,19 +1024,9 @@ Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row) if (!service) return Empty; - Dictionary::Ptr comments = service->GetComments(); - - Array::Ptr ids = new Array(); - - ObjectLock olock(comments); - - String id; - Comment::Ptr comment; - BOOST_FOREACH(tie(id, comment), comments) { - - if (!comment) - continue; + Array::Ptr results = new Array(); + BOOST_FOREACH(const Comment::Ptr& comment, service->GetComments()) { if (comment->IsExpired()) continue; @@ -1086,10 +1036,10 @@ Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row) comment_info->Add(comment->GetText()); comment_info->Add(comment->GetEntryType()); comment_info->Add(static_cast(comment->GetEntryTime())); - ids->Add(comment_info); + results->Add(comment_info); } - return ids; + return results; } Value ServicesTable::CustomVariableNamesAccessor(const Value& row) diff --git a/lib/notification/notificationcomponent.cpp b/lib/notification/notificationcomponent.cpp index 9660bfca1..1139faa80 100644 --- a/lib/notification/notificationcomponent.cpp +++ b/lib/notification/notificationcomponent.cpp @@ -49,9 +49,9 @@ void NotificationComponent::StatsFunc(const Dictionary::Ptr& status, const Array /** * Starts the component. */ -void NotificationComponent::Start(void) +void NotificationComponent::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); Checkable::OnNotificationsRequested.connect(boost::bind(&NotificationComponent::SendNotificationsHandler, this, _1, _2, _3, _4, _5)); diff --git a/lib/notification/notificationcomponent.hpp b/lib/notification/notificationcomponent.hpp index bc1dc1d9a..781168286 100644 --- a/lib/notification/notificationcomponent.hpp +++ b/lib/notification/notificationcomponent.hpp @@ -39,7 +39,7 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: Timer::Ptr m_NotificationTimer; diff --git a/lib/perfdata/gelfwriter.cpp b/lib/perfdata/gelfwriter.cpp index f3a2940ed..d883fe51c 100644 --- a/lib/perfdata/gelfwriter.cpp +++ b/lib/perfdata/gelfwriter.cpp @@ -38,9 +38,9 @@ using namespace icinga; REGISTER_TYPE(GelfWriter); -void GelfWriter::Start(void) +void GelfWriter::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); m_ReconnectTimer = new Timer(); m_ReconnectTimer->SetInterval(10); diff --git a/lib/perfdata/gelfwriter.hpp b/lib/perfdata/gelfwriter.hpp index 78af64d7e..7bbf7dab4 100644 --- a/lib/perfdata/gelfwriter.hpp +++ b/lib/perfdata/gelfwriter.hpp @@ -42,7 +42,7 @@ public: DECLARE_OBJECTNAME(GelfWriter); protected: - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: Stream::Ptr m_Stream; diff --git a/lib/perfdata/graphitewriter.cpp b/lib/perfdata/graphitewriter.cpp index 3e7640e5d..7602600a5 100644 --- a/lib/perfdata/graphitewriter.cpp +++ b/lib/perfdata/graphitewriter.cpp @@ -58,9 +58,9 @@ void GraphiteWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&) status->Set("graphitewriter", nodes); } -void GraphiteWriter::Start(void) +void GraphiteWriter::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); m_ReconnectTimer = new Timer(); m_ReconnectTimer->SetInterval(10); diff --git a/lib/perfdata/graphitewriter.hpp b/lib/perfdata/graphitewriter.hpp index e3dd6eede..0c6072428 100644 --- a/lib/perfdata/graphitewriter.hpp +++ b/lib/perfdata/graphitewriter.hpp @@ -47,7 +47,7 @@ public: virtual void ValidateServiceNameTemplate(const String& value, const ValidationUtils& utils) override; protected: - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: Stream::Ptr m_Stream; diff --git a/lib/perfdata/opentsdbwriter.cpp b/lib/perfdata/opentsdbwriter.cpp index 84607ab01..24557f34f 100644 --- a/lib/perfdata/opentsdbwriter.cpp +++ b/lib/perfdata/opentsdbwriter.cpp @@ -58,9 +58,9 @@ void OpenTsdbWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&) status->Set("opentsdbwriter", nodes); } -void OpenTsdbWriter::Start(void) +void OpenTsdbWriter::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); m_ReconnectTimer = new Timer(); m_ReconnectTimer->SetInterval(10); diff --git a/lib/perfdata/opentsdbwriter.hpp b/lib/perfdata/opentsdbwriter.hpp index 2ef0ef0e9..e1787ab50 100644 --- a/lib/perfdata/opentsdbwriter.hpp +++ b/lib/perfdata/opentsdbwriter.hpp @@ -44,7 +44,7 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); protected: - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: Stream::Ptr m_Stream; diff --git a/lib/perfdata/perfdatawriter.cpp b/lib/perfdata/perfdatawriter.cpp index 257b0e959..e2ca0d9ce 100644 --- a/lib/perfdata/perfdatawriter.cpp +++ b/lib/perfdata/perfdatawriter.cpp @@ -49,9 +49,9 @@ void PerfdataWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&) status->Set("perfdatawriter", nodes); } -void PerfdataWriter::Start(void) +void PerfdataWriter::Start(bool runtimeCreated) { - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); Checkable::OnNewCheckResult.connect(boost::bind(&PerfdataWriter::CheckResultHandler, this, _1, _2)); diff --git a/lib/perfdata/perfdatawriter.hpp b/lib/perfdata/perfdatawriter.hpp index 12999c406..aac43fe69 100644 --- a/lib/perfdata/perfdatawriter.hpp +++ b/lib/perfdata/perfdatawriter.hpp @@ -46,7 +46,7 @@ public: virtual void ValidateServiceFormatTemplate(const String& value, const ValidationUtils& utils) override; protected: - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: void CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr); diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp index 1e93632b1..653b7364b 100644 --- a/lib/remote/apilistener.cpp +++ b/lib/remote/apilistener.cpp @@ -97,7 +97,7 @@ void ApiListener::OnAllConfigLoaded(void) /** * Starts the component. */ -void ApiListener::Start(void) +void ApiListener::Start(bool runtimeCreated) { SyncZoneDirs(); @@ -107,7 +107,7 @@ void ApiListener::Start(void) return; } - ObjectImpl::Start(); + ObjectImpl::Start(runtimeCreated); { boost::mutex::scoped_lock(m_LogLock); diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index 203cdadc5..9cf8278f3 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -89,7 +89,7 @@ public: protected: virtual void OnConfigLoaded(void) override; virtual void OnAllConfigLoaded(void) override; - virtual void Start(void) override; + virtual void Start(bool runtimeCreated) override; private: boost::shared_ptr m_SSLContext; diff --git a/lib/remote/configobjectutility.cpp b/lib/remote/configobjectutility.cpp index 325451403..a114ef52c 100644 --- a/lib/remote/configobjectutility.cpp +++ b/lib/remote/configobjectutility.cpp @@ -52,7 +52,7 @@ String ConfigObjectUtility::EscapeName(const String& name) } String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const String& fullName, - const Array::Ptr& templates, const Dictionary::Ptr& attrs) + bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs) { NameComposer *nc = dynamic_cast(type.get()); Dictionary::Ptr nameParts; @@ -78,7 +78,7 @@ String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const Stri allAttrs->Set("version", Utility::GetTime()); std::ostringstream config; - ConfigWriter::EmitConfigItem(config, type->GetName(), name, false, templates, allAttrs); + ConfigWriter::EmitConfigItem(config, type->GetName(), name, false, ignoreOnError, templates, allAttrs); ConfigWriter::EmitRaw(config, "\n"); return config.str(); @@ -111,7 +111,7 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full WorkQueue upq; - if (!ConfigItem::CommitItems(upq) || !ConfigItem::ActivateItems(upq, false)) { + if (!ConfigItem::CommitItems(upq) || !ConfigItem::ActivateItems(upq, false, true)) { if (errors) { BOOST_FOREACH(const boost::exception_ptr& ex, upq.GetExceptions()) { errors->Add(DiagnosticInformation(ex)); @@ -161,7 +161,7 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo /* mark this object for cluster delete event */ object->SetExtension("ConfigObjectDeleted", true); /* triggers signal for DB IDO and other interfaces */ - object->Deactivate(); + object->Deactivate(true); if (item) item->Unregister(); diff --git a/lib/remote/configobjectutility.hpp b/lib/remote/configobjectutility.hpp index a8ff67922..8e310fa4f 100644 --- a/lib/remote/configobjectutility.hpp +++ b/lib/remote/configobjectutility.hpp @@ -40,15 +40,15 @@ class I2_REMOTE_API ConfigObjectUtility public: static String GetConfigDir(void); static String GetObjectConfigPath(const Type::Ptr& type, const String& fullName); - + static String CreateObjectConfig(const Type::Ptr& type, const String& fullName, - const Array::Ptr& templates, const Dictionary::Ptr& attrs); - + bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs); + static bool CreateObject(const Type::Ptr& type, const String& fullName, const String& config, const Array::Ptr& errors); - + static bool DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors); - + private: static String EscapeName(const String& name); static bool DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors); diff --git a/lib/remote/createobjecthandler.cpp b/lib/remote/createobjecthandler.cpp index b73b5f317..a7d6ec760 100644 --- a/lib/remote/createobjecthandler.cpp +++ b/lib/remote/createobjecthandler.cpp @@ -22,6 +22,7 @@ #include "remote/httputility.hpp" #include "remote/filterutility.hpp" #include "remote/apiaction.hpp" +#include "base/configtype.hpp" #include #include @@ -56,7 +57,12 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r String status; Array::Ptr errors = new Array(); - String config = ConfigObjectUtility::CreateObjectConfig(type, name, templates, attrs); + bool ignoreOnError = false; + + if (params->Contains("ignore_on_error")) + ignoreOnError = HttpUtility::GetLastParameter(params, "ignore_on_error"); + + String config = ConfigObjectUtility::CreateObjectConfig(type, name, ignoreOnError, templates, attrs); if (!ConfigObjectUtility::CreateObject(type, name, config, errors)) { result1->Set("errors", errors); @@ -64,8 +70,16 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r return true; } + ConfigType::Ptr dtype = ConfigType::GetByName(type->GetName()); + + ConfigObject::Ptr obj = dtype->GetObject(name); + result1->Set("code", 200); - result1->Set("status", "Object was created"); + + if (obj) + result1->Set("status", "Object was created"); + else if (!obj && ignoreOnError) + result1->Set("status", "Object was not created but 'ignore_on_error' was set to true"); Array::Ptr results = new Array(); results->Add(result1); diff --git a/tools/mkclass/classcompiler.cpp b/tools/mkclass/classcompiler.cpp index bc16add54..3621c5b27 100644 --- a/tools/mkclass/classcompiler.cpp +++ b/tools/mkclass/classcompiler.cpp @@ -874,12 +874,12 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) /* start/stop */ if (needs_tracking) { - m_Header << "virtual void Start(void) override;" << std::endl - << "virtual void Stop(void) override;" << std::endl; + m_Header << "virtual void Start(bool runtimeCreated = false) override;" << std::endl + << "virtual void Stop(bool runtimeRemoved = false) override;" << std::endl; - m_Impl << "void ObjectImpl<" << klass.Name << ">::Start(void)" << std::endl + m_Impl << "void ObjectImpl<" << klass.Name << ">::Start(bool runtimeCreated)" << std::endl << "{" << std::endl - << "\t" << klass.Parent << "::Start();" << std::endl << std::endl; + << "\t" << klass.Parent << "::Start(runtimeCreated);" << std::endl << std::endl; for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) { if (!(it->Type.IsName)) @@ -889,9 +889,9 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) } m_Impl << "}" << std::endl << std::endl - << "void ObjectImpl<" << klass.Name << ">::Stop(void)" << std::endl + << "void ObjectImpl<" << klass.Name << ">::Stop(bool runtimeRemoved)" << std::endl << "{" << std::endl - << "\t" << klass.Parent << "::Stop();" << std::endl << std::endl; + << "\t" << klass.Parent << "::Stop(runtimeRemoved);" << std::endl << std::endl; for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) { if (!(it->Type.IsName)) -- 2.40.0