From 1bfb91f0655ab0cdc6026b9068ac1a19216f3485 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Fri, 11 Nov 2016 19:36:19 +0100 Subject: [PATCH] Ensure that DowntimeStart notifications are not immediately sent fixes #12549 --- doc/12-icinga2-api.md | 1 + lib/icinga/apievents.cpp | 21 ++++++++++++++++ lib/icinga/apievents.hpp | 1 + lib/icinga/checkable.cpp | 2 +- lib/icinga/downtime.cpp | 52 ++++++++++++++++++++++++++++------------ lib/icinga/downtime.hpp | 4 ++++ 6 files changed, 65 insertions(+), 16 deletions(-) diff --git a/doc/12-icinga2-api.md b/doc/12-icinga2-api.md index 94a65eced..38b1ec69f 100644 --- a/doc/12-icinga2-api.md +++ b/doc/12-icinga2-api.md @@ -1186,6 +1186,7 @@ The following event stream types are available: CommentRemoved | Comment removed for hosts and services. DowntimeAdded | Downtime added for hosts and services. DowntimeRemoved | Downtime removed for hosts and services. + DowntimeStarted | Downtime started for hosts and services. DowntimeTriggered | Downtime triggered for hosts and services. Note: Each type requires [API permissions](12-icinga2-api.md#icinga2-api-permissions) diff --git a/lib/icinga/apievents.cpp b/lib/icinga/apievents.cpp index 6c4e9cbd5..a512d6f54 100644 --- a/lib/icinga/apievents.cpp +++ b/lib/icinga/apievents.cpp @@ -44,6 +44,7 @@ void ApiEvents::StaticInitialize(void) Downtime::OnDowntimeAdded.connect(&ApiEvents::DowntimeAddedHandler); Downtime::OnDowntimeRemoved.connect(&ApiEvents::DowntimeRemovedHandler); + Downtime::OnDowntimeStarted.connect(&ApiEvents::DowntimeStartedHandler); Downtime::OnDowntimeTriggered.connect(&ApiEvents::DowntimeTriggeredHandler); } @@ -323,6 +324,26 @@ void ApiEvents::DowntimeRemovedHandler(const Downtime::Ptr& downtime) } } +void ApiEvents::DowntimeStartedHandler(const Downtime::Ptr& downtime) +{ + std::vector queues = EventQueue::GetQueuesForType("DowntimeStarted"); + + if (queues.empty()) + return; + + Log(LogDebug, "ApiEvents", "Processing event type 'DowntimeStarted'."); + + Dictionary::Ptr result = new Dictionary(); + result->Set("type", "DowntimeStarted"); + result->Set("timestamp", Utility::GetTime()); + + result->Set("downtime", Serialize(downtime, FAConfig | FAState)); + + for (const EventQueue::Ptr& queue : queues) { + queue->ProcessEvent(result); + } +} + void ApiEvents::DowntimeTriggeredHandler(const Downtime::Ptr& downtime) { std::vector queues = EventQueue::GetQueuesForType("DowntimeTriggered"); diff --git a/lib/icinga/apievents.hpp b/lib/icinga/apievents.hpp index dfbd64c3d..70ad46db3 100644 --- a/lib/icinga/apievents.hpp +++ b/lib/icinga/apievents.hpp @@ -54,6 +54,7 @@ public: static void DowntimeAddedHandler(const Downtime::Ptr& downtime); static void DowntimeRemovedHandler(const Downtime::Ptr& downtime); + static void DowntimeStartedHandler(const Downtime::Ptr& downtime); static void DowntimeTriggeredHandler(const Downtime::Ptr& downtime); }; diff --git a/lib/icinga/checkable.cpp b/lib/icinga/checkable.cpp index 1ddb962ca..7f6fa7bf4 100644 --- a/lib/icinga/checkable.cpp +++ b/lib/icinga/checkable.cpp @@ -36,7 +36,7 @@ boost::signals2::signal void Checkable::StaticInitialize(void) { /* fixed downtime start */ - Downtime::OnDowntimeAdded.connect(boost::bind(&Checkable::NotifyFixedDowntimeStart, _1)); + Downtime::OnDowntimeStarted.connect(boost::bind(&Checkable::NotifyFixedDowntimeStart, _1)); /* flexible downtime start */ Downtime::OnDowntimeTriggered.connect(boost::bind(&Checkable::NotifyFlexibleDowntimeStart, _1)); /* fixed/flexible downtime end */ diff --git a/lib/icinga/downtime.cpp b/lib/icinga/downtime.cpp index 8adf30c5f..84cc5b9ab 100644 --- a/lib/icinga/downtime.cpp +++ b/lib/icinga/downtime.cpp @@ -34,9 +34,11 @@ static int l_NextDowntimeID = 1; static boost::mutex l_DowntimeMutex; static std::map l_LegacyDowntimesCache; static Timer::Ptr l_DowntimesExpireTimer; +static Timer::Ptr l_DowntimesStartTimer; boost::signals2::signal Downtime::OnDowntimeAdded; boost::signals2::signal Downtime::OnDowntimeRemoved; +boost::signals2::signal Downtime::OnDowntimeStarted; boost::signals2::signal Downtime::OnDowntimeTriggered; INITIALIZE_ONCE(&Downtime::StaticInitialize); @@ -45,6 +47,11 @@ REGISTER_TYPE(Downtime); void Downtime::StaticInitialize(void) { + l_DowntimesStartTimer = new Timer(); + l_DowntimesStartTimer->SetInterval(5); + l_DowntimesStartTimer->OnTimerExpired.connect(boost::bind(&Downtime::DowntimesStartTimerHandler)); + l_DowntimesStartTimer->Start(); + l_DowntimesExpireTimer = new Timer(); l_DowntimesExpireTimer->SetInterval(60); l_DowntimesExpireTimer->OnTimerExpired.connect(boost::bind(&Downtime::DowntimesExpireTimerHandler)); @@ -315,27 +322,26 @@ void Downtime::RemoveDowntime(const String& id, bool cancelled, bool expired, co } } -void Downtime::TriggerDowntime(void) +bool Downtime::CanBeTriggered(void) { - if (IsInEffect() && IsTriggered()) { - Log(LogDebug, "Downtime") - << "Not triggering downtime '" << GetName() << "': already triggered."; - return; - } + if (IsInEffect() && IsTriggered()) + return false; - if (IsExpired()) { - Log(LogDebug, "Downtime") - << "Not triggering downtime '" << GetName() << "': expired."; - return; - } + if (IsExpired()) + return false; double now = Utility::GetTime(); - if (now < GetStartTime() || now > GetEndTime()) { - Log(LogDebug, "Downtime") - << "Not triggering downtime '" << GetName() << "': current time is outside downtime window."; + if (now < GetStartTime() || now > GetEndTime()) + return false; + + return true; +} + +void Downtime::TriggerDowntime(void) +{ + if (!CanBeTriggered()) return; - } Log(LogNotice, "Downtime") << "Triggering downtime '" << GetName() << "'."; @@ -372,6 +378,22 @@ String Downtime::GetDowntimeIDFromLegacyID(int id) return it->second; } +void Downtime::DowntimesStartTimerHandler(void) +{ + /* Start fixed downtimes. Flexible downtimes will be triggered on-demand. */ + for (const Downtime::Ptr& downtime : ConfigType::GetObjectsByType()) { + if (downtime->IsActive() && + downtime->CanBeTriggered() && + downtime->GetFixed()) { + /* Send notifications. */ + OnDowntimeStarted(downtime); + + /* Trigger fixed downtime immediately. */ + downtime->TriggerDowntime(); + } + } +} + void Downtime::DowntimesExpireTimerHandler(void) { std::vector downtimes; diff --git a/lib/icinga/downtime.hpp b/lib/icinga/downtime.hpp index 8122ebe32..6ccf0c525 100644 --- a/lib/icinga/downtime.hpp +++ b/lib/icinga/downtime.hpp @@ -41,6 +41,7 @@ public: static boost::signals2::signal OnDowntimeAdded; static boost::signals2::signal OnDowntimeRemoved; + static boost::signals2::signal OnDowntimeStarted; static boost::signals2::signal OnDowntimeTriggered; intrusive_ptr GetCheckable(void) const; @@ -77,6 +78,9 @@ protected: private: ObjectImpl::Ptr m_Checkable; + bool CanBeTriggered(void); + + static void DowntimesStartTimerHandler(void); static void DowntimesExpireTimerHandler(void); }; -- 2.40.0