Skip to content

Commit

Permalink
Fix host recovery notifications for warning states
Browse files Browse the repository at this point in the history
refs #10225
  • Loading branch information
Michael Friedrich committed Mar 10, 2016
1 parent 68449c2 commit c0e175d
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 20 deletions.
65 changes: 45 additions & 20 deletions lib/icinga/checkable-check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@ double Checkable::GetLastCheck(void) const
return schedule_end;
}

bool Checkable::IsOK(CheckableType type, ServiceState state)
{
if (type == CheckableHost) {
if (state == ServiceOK || state == ServiceWarning)
return true;
else
return false;
} else {
if (state == ServiceOK)
return true;
else
return false;
}
}

void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrigin::Ptr& origin)
{
{
Expand Down Expand Up @@ -150,6 +165,7 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig
long old_attempt = GetCheckAttempt();
bool recovery = false;

/* Ignore check results older than the current one. */
if (old_cr && cr->GetExecutionStart() < old_cr->GetExecutionStart())
return;

Expand All @@ -159,19 +175,27 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig
SetLastStateType(old_stateType);
SetLastReachable(reachable);

Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(this);

CheckableType checkableType = CheckableHost;
if (service)
checkableType = CheckableService;

long attempt = 1;

std::set<Checkable::Ptr> children = GetChildren();

if (!old_cr) {
SetStateType(StateTypeHard);
} else if (cr->GetState() == ServiceOK) {
if (old_state == ServiceOK && old_stateType == StateTypeSoft) {
} else if (IsOK(checkableType, cr->GetState())) {
if (IsOK(checkableType, old_state) && old_stateType == StateTypeSoft) {
SetStateType(StateTypeHard); // SOFT OK -> HARD OK
recovery = true;
}

if (old_state != ServiceOK)
if (!IsOK(checkableType, old_state))
recovery = true; // NOT OK -> SOFT/HARD OK

ResetNotificationNumbers();
Expand All @@ -183,17 +207,17 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig
} else {
if (old_attempt >= GetMaxCheckAttempts()) {
SetStateType(StateTypeHard);
} else if (old_stateType == StateTypeSoft && old_state != ServiceOK) {
} else if (old_stateType == StateTypeSoft && !IsOK(checkableType, old_state)) {
SetStateType(StateTypeSoft);
attempt = old_attempt + 1; //NOT-OK -> NOT-OK counter
} else if (old_state == ServiceOK) {
} else if (IsOK(checkableType, old_state)) {
SetStateType(StateTypeSoft);
attempt = 1; //OK -> NOT-OK transition, reset the counter
} else {
attempt = old_attempt;
}

if (cr->GetState() != ServiceOK) {
if (!IsOK(checkableType, cr->GetState())) {
SaveLastState(cr->GetState(), Utility::GetTime());
}

Expand All @@ -210,13 +234,20 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig
ServiceState new_state = cr->GetState();
SetStateRaw(new_state);

bool stateChange = (old_state != new_state);
bool stateChange;

/* Exception on state change calculation for hosts. */
if (checkableType == CheckableService)
stateChange = (old_state != new_state);
else
stateChange = (Host::CalculateState(old_state) != Host::CalculateState(new_state));

if (stateChange) {
SetLastStateChange(now);

/* remove acknowledgements */
if (GetAcknowledgement() == AcknowledgementNormal ||
(GetAcknowledgement() == AcknowledgementSticky && new_state == ServiceOK)) {
(GetAcknowledgement() == AcknowledgementSticky && IsOK(checkableType, new_state))) {
ClearAcknowledgement();
}

Expand Down Expand Up @@ -247,30 +278,22 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig
SetLastHardStateChange(now);
}

if (new_state != ServiceOK)
if (!IsOK(checkableType, new_state))
TriggerDowntimes();

Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(this);

CheckableType checkable_type = CheckableHost;
if (service)
checkable_type = CheckableService;

/* statistics for external tools */
Checkable::UpdateStatistics(cr, checkable_type);
Checkable::UpdateStatistics(cr, checkableType);

bool in_downtime = IsInDowntime();
bool send_notification = hardChange && notification_reachable && !in_downtime && !IsAcknowledged();

if (!old_cr)
send_notification = false; /* Don't send notifications for the initial state change */

if (old_state == ServiceOK && old_stateType == StateTypeSoft)
if (IsOK(checkableType, old_state) && old_stateType == StateTypeSoft)
send_notification = false; /* Don't send notifications for SOFT-OK -> HARD-OK. */

if (is_volatile && old_state == ServiceOK && new_state == ServiceOK)
if (is_volatile && IsOK(checkableType, old_state) && IsOK(checkableType, new_state))
send_notification = false; /* Don't send notifications for volatile OK -> OK changes. */

bool send_downtime_notification = (GetLastInDowntime() != in_downtime);
Expand Down Expand Up @@ -298,8 +321,10 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig
bool was_flapping, is_flapping;

was_flapping = IsFlapping();

if (GetStateType() == StateTypeHard)
UpdateFlappingStatus(stateChange);

is_flapping = IsFlapping();

olock.Unlock();
Expand Down
2 changes: 2 additions & 0 deletions lib/icinga/checkable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class I2_ICINGA_API Checkable : public ObjectImpl<Checkable>
void UpdateNextCheck(void);

bool HasBeenChecked(void) const;
bool IsOK(CheckableType type, ServiceState state);

virtual double GetLastCheck(void) const override;

virtual void SaveLastState(ServiceState state, double timestamp) = 0;
Expand Down

0 comments on commit c0e175d

Please sign in to comment.