Skip to content

Commit

Permalink
Ensure that DowntimeStart notifications are not immediately sent
Browse files Browse the repository at this point in the history
fixes #12549
  • Loading branch information
Michael Friedrich committed Nov 11, 2016
1 parent e7a6124 commit 1bfb91f
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 16 deletions.
1 change: 1 addition & 0 deletions doc/12-icinga2-api.md
Expand Up @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions lib/icinga/apievents.cpp
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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");
Expand Down
1 change: 1 addition & 0 deletions lib/icinga/apievents.hpp
Expand Up @@ -54,6 +54,7 @@ class I2_ICINGA_API ApiEvents

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);
};

Expand Down
2 changes: 1 addition & 1 deletion lib/icinga/checkable.cpp
Expand Up @@ -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 */
Expand Down
52 changes: 37 additions & 15 deletions lib/icinga/downtime.cpp
Expand Up @@ -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);
Expand All @@ -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));
Expand Down Expand Up @@ -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() << "'.";
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions lib/icinga/downtime.hpp
Expand Up @@ -41,6 +41,7 @@ class I2_ICINGA_API Downtime : public ObjectImpl<Downtime>

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;
Expand Down Expand Up @@ -77,6 +78,9 @@ class I2_ICINGA_API Downtime : public ObjectImpl<Downtime>
private:
ObjectImpl<Checkable>::Ptr m_Checkable;

bool CanBeTriggered(void);

static void DowntimesStartTimerHandler(void);
static void DowntimesExpireTimerHandler(void);
};

Expand Down

0 comments on commit 1bfb91f

Please sign in to comment.