]> granicus.if.org Git - icinga2/commitdiff
Ensure that DowntimeStart notifications are not immediately sent
authorMichael Friedrich <michael.friedrich@icinga.com>
Fri, 11 Nov 2016 18:36:19 +0000 (19:36 +0100)
committerMichael Friedrich <michael.friedrich@icinga.com>
Fri, 11 Nov 2016 18:36:19 +0000 (19:36 +0100)
fixes #12549

doc/12-icinga2-api.md
lib/icinga/apievents.cpp
lib/icinga/apievents.hpp
lib/icinga/checkable.cpp
lib/icinga/downtime.cpp
lib/icinga/downtime.hpp

index 94a65ecede0596ca53e9e9873c00256c59cc7b9b..38b1ec69f9cd61631eebec759652dc2f8e48b54f 100644 (file)
@@ -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)
index 6c4e9cbd5e4587a773c17e434e7bc8bb6b4a811f..a512d6f54943f30cb74561a3b0b295d09da58086 100644 (file)
@@ -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<EventQueue::Ptr> 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<EventQueue::Ptr> queues = EventQueue::GetQueuesForType("DowntimeTriggered");
index dfbd64c3d7d0d56cedc5279108e0f1ad636b81ad..70ad46db3b8dda3ad3edbd23b57a929eaac56be0 100644 (file)
@@ -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);
 };
 
index 1ddb962ca9b134b8e2231086e6e0f6c8d1e5d1d1..7f6fa7bf4a45403235226526831b24d53736b02a 100644 (file)
@@ -36,7 +36,7 @@ boost::signals2::signal<void (const Checkable::Ptr&, const MessageOrigin::Ptr&)>
 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 */
index 8adf30c5fe3e3bf73ba44bdc53eeb8e42cf163f4..84cc5b9ab0d0c9e545e0b7a1c4899c90031f6279 100644 (file)
@@ -34,9 +34,11 @@ static int l_NextDowntimeID = 1;
 static boost::mutex l_DowntimeMutex;
 static std::map<int, String> l_LegacyDowntimesCache;
 static Timer::Ptr l_DowntimesExpireTimer;
+static Timer::Ptr l_DowntimesStartTimer;
 
 boost::signals2::signal<void (const Downtime::Ptr&)> Downtime::OnDowntimeAdded;
 boost::signals2::signal<void (const Downtime::Ptr&)> Downtime::OnDowntimeRemoved;
+boost::signals2::signal<void (const Downtime::Ptr&)> Downtime::OnDowntimeStarted;
 boost::signals2::signal<void (const Downtime::Ptr&)> 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<Downtime>()) {
+               if (downtime->IsActive() &&
+                   downtime->CanBeTriggered() &&
+                   downtime->GetFixed()) {
+                       /* Send notifications. */
+                       OnDowntimeStarted(downtime);
+
+                       /* Trigger fixed downtime immediately. */
+                       downtime->TriggerDowntime();
+               }
+       }
+}
+
 void Downtime::DowntimesExpireTimerHandler(void)
 {
        std::vector<Downtime::Ptr> downtimes;
index 8122ebe32b41e62e73fb41efc6a092325453313b..6ccf0c5253477808efd2b3c1f55d21da4d14c13e 100644 (file)
@@ -41,6 +41,7 @@ public:
 
        static boost::signals2::signal<void (const Downtime::Ptr&)> OnDowntimeAdded;
        static boost::signals2::signal<void (const Downtime::Ptr&)> OnDowntimeRemoved;
+       static boost::signals2::signal<void (const Downtime::Ptr&)> OnDowntimeStarted;
        static boost::signals2::signal<void (const Downtime::Ptr&)> OnDowntimeTriggered;
 
        intrusive_ptr<Checkable> GetCheckable(void) const;
@@ -77,6 +78,9 @@ protected:
 private:
        ObjectImpl<Checkable>::Ptr m_Checkable;
 
+       bool CanBeTriggered(void);
+
+       static void DowntimesStartTimerHandler(void);
        static void DowntimesExpireTimerHandler(void);
 };