Fix custom notifications in a HA zone

fixes #9242
This commit is contained in:
Gunnar Beutner 2016-06-07 12:44:12 +02:00
parent ac3ae3194b
commit 0eb0992d5e
10 changed files with 98 additions and 18 deletions

View File

@ -1078,7 +1078,7 @@ Configuration Attributes:
Name |Description
----------------|----------------
enable\_ha |**Optional.** Enable the high availability functionality. Only valid in a [cluster setup](13-distributed-monitoring-ha.md#high-availability-notifications). Defaults to "true".
enable\_ha |**Optional.** Enable the high availability functionality. Only valid in a [cluster setup](13-distributed-monitoring-ha.md#high-availability-notifications). Disabling this currently only affects reminder notifications. Defaults to "true".
## <a id="objecttype-opentsdbwriter"></a> OpenTsdbWriter

View File

@ -156,7 +156,7 @@ Dictionary::Ptr ApiActions::SendCustomNotification(const ConfigObject::Ptr& obje
checkable->SetForceNextNotification(true);
Checkable::OnNotificationsRequested(checkable, NotificationCustom, checkable->GetLastCheckResult(),
HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"));
HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), MessageOrigin::Ptr());
return ApiActions::CreateResult(200, "Successfully sent custom notification for object '" + checkable->GetName() + "'.");
}

View File

@ -38,7 +38,7 @@ using namespace icinga;
boost::signals2::signal<void (const Checkable::Ptr&, const CheckResult::Ptr&, const MessageOrigin::Ptr&)> Checkable::OnNewCheckResult;
boost::signals2::signal<void (const Checkable::Ptr&, const CheckResult::Ptr&, StateType, const MessageOrigin::Ptr&)> Checkable::OnStateChange;
boost::signals2::signal<void (const Checkable::Ptr&, const CheckResult::Ptr&, std::set<Checkable::Ptr>, const MessageOrigin::Ptr&)> Checkable::OnReachabilityChanged;
boost::signals2::signal<void (const Checkable::Ptr&, NotificationType, const CheckResult::Ptr&, const String&, const String&)> Checkable::OnNotificationsRequested;
boost::signals2::signal<void (const Checkable::Ptr&, NotificationType, const CheckResult::Ptr&, const String&, const String&, const MessageOrigin::Ptr&)> Checkable::OnNotificationsRequested;
boost::signals2::signal<void (const Checkable::Ptr&)> Checkable::OnNextCheckUpdated;
boost::mutex Checkable::m_StatsMutex;
@ -368,26 +368,30 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig
(is_volatile && !(IsStateOK(old_state) && IsStateOK(new_state))))
ExecuteEventHandler();
if (send_downtime_notification)
OnNotificationsRequested(this, in_downtime ? NotificationDowntimeStart : NotificationDowntimeEnd, cr, "", "");
if (send_downtime_notification && !origin)
OnNotificationsRequested(this, in_downtime ? NotificationDowntimeStart : NotificationDowntimeEnd, cr, "", "", MessageOrigin::Ptr());
if (send_notification) {
if (!was_flapping && is_flapping) {
OnNotificationsRequested(this, NotificationFlappingStart, cr, "", "");
if (!IsPaused())
OnNotificationsRequested(this, NotificationFlappingStart, cr, "", "", MessageOrigin::Ptr());
Log(LogNotice, "Checkable")
<< "Flapping: Checkable " << GetName() << " started flapping (" << GetFlappingThreshold() << "% < " << GetFlappingCurrent() << "%).";
NotifyFlapping(origin);
} else if (was_flapping && !is_flapping) {
OnNotificationsRequested(this, NotificationFlappingEnd, cr, "", "");
if (!IsPaused())
OnNotificationsRequested(this, NotificationFlappingEnd, cr, "", "", MessageOrigin::Ptr());
Log(LogNotice, "Checkable")
<< "Flapping: Checkable " << GetName() << " stopped flapping (" << GetFlappingThreshold() << "% >= " << GetFlappingCurrent() << "%).";
NotifyFlapping(origin);
} else if (!was_flapping && !is_flapping)
OnNotificationsRequested(this, recovery ? NotificationRecovery : NotificationProblem, cr, "", "");
} else if (!was_flapping && !is_flapping) {
if (!IsPaused())
OnNotificationsRequested(this, recovery ? NotificationRecovery : NotificationProblem, cr, "", "", MessageOrigin::Ptr());
}
}
}

View File

@ -73,7 +73,8 @@ void Checkable::SendNotifications(NotificationType type, const CheckResult::Ptr&
BOOST_FOREACH(const Notification::Ptr& notification, notifications) {
try {
notification->BeginExecuteNotification(type, cr, force, author, text);
if (!notification->IsPaused())
notification->BeginExecuteNotification(type, cr, force, author, text);
} catch (const std::exception& ex) {
Log(LogWarning, "Checkable")
<< "Exception occured during notification for service '"

View File

@ -97,8 +97,8 @@ void Checkable::AcknowledgeProblem(const String& author, const String& comment,
SetAcknowledgementRaw(type);
SetAcknowledgementExpiry(expiry);
if (notify)
OnNotificationsRequested(this, NotificationAcknowledgement, GetLastCheckResult(), author, comment);
if (notify && !IsPaused())
OnNotificationsRequested(this, NotificationAcknowledgement, GetLastCheckResult(), author, comment, MessageOrigin::Ptr());
OnAcknowledgementSet(this, author, comment, type, notify, expiry, origin);
}

View File

@ -110,7 +110,7 @@ public:
static boost::signals2::signal<void (const Checkable::Ptr&, const CheckResult::Ptr&, StateType, const MessageOrigin::Ptr&)> OnStateChange;
static boost::signals2::signal<void (const Checkable::Ptr&, const CheckResult::Ptr&, std::set<Checkable::Ptr>, const MessageOrigin::Ptr&)> OnReachabilityChanged;
static boost::signals2::signal<void (const Checkable::Ptr&, NotificationType, const CheckResult::Ptr&,
const String&, const String&)> OnNotificationsRequested;
const String&, const String&, const MessageOrigin::Ptr&)> OnNotificationsRequested;
static boost::signals2::signal<void (const Notification::Ptr&, const Checkable::Ptr&, const std::set<User::Ptr>&,
const NotificationType&, const CheckResult::Ptr&, const String&,
const String&)> OnNotificationSendStart;

View File

@ -48,6 +48,7 @@ REGISTER_APIFUNCTION(SetAcknowledgement, event, &ClusterEvents::AcknowledgementS
REGISTER_APIFUNCTION(ClearAcknowledgement, event, &ClusterEvents::AcknowledgementClearedAPIHandler);
REGISTER_APIFUNCTION(UpdateRepository, event, &ClusterEvents::UpdateRepositoryAPIHandler);
REGISTER_APIFUNCTION(ExecuteCommand, event, &ClusterEvents::ExecuteCommandAPIHandler);
REGISTER_APIFUNCTION(SendNotifications, event, &ClusterEvents::SendNotificationsAPIHandler);
static Timer::Ptr l_RepositoryTimer;
@ -58,6 +59,7 @@ void ClusterEvents::StaticInitialize(void)
Notification::OnNextNotificationChanged.connect(&ClusterEvents::NextNotificationChangedHandler);
Checkable::OnForceNextCheckChanged.connect(&ClusterEvents::ForceNextCheckChangedHandler);
Checkable::OnForceNextNotificationChanged.connect(&ClusterEvents::ForceNextNotificationChangedHandler);
Checkable::OnNotificationsRequested.connect(&ClusterEvents::SendNotificationsHandler);
Checkable::OnAcknowledgementSet.connect(&ClusterEvents::AcknowledgementSetHandler);
Checkable::OnAcknowledgementCleared.connect(&ClusterEvents::AcknowledgementClearedHandler);
@ -756,3 +758,73 @@ Value ClusterEvents::UpdateRepositoryAPIHandler(const MessageOrigin::Ptr& origin
return Empty;
}
void ClusterEvents::SendNotificationsHandler(const Checkable::Ptr& checkable, NotificationType type,
const CheckResult::Ptr& cr, const String& author, const String& text, const MessageOrigin::Ptr& origin)
{
ApiListener::Ptr listener = ApiListener::GetInstance();
if (!listener)
return;
Dictionary::Ptr message = MakeCheckResultMessage(checkable, cr);
message->Set("method", "event::SendNotifications");
Dictionary::Ptr params = message->Get("params");
params->Set("type", type);
params->Set("author", author);
params->Set("text", text);
listener->RelayMessage(origin, checkable, message, true);
}
Value ClusterEvents::SendNotificationsAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
{
Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
if (!endpoint) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'send notification' 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 'send custom notification' message from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
return Empty;
}
CheckResult::Ptr cr = new CheckResult();
Dictionary::Ptr vcr = params->Get("cr");
Array::Ptr vperf = vcr->Get("performance_data");
vcr->Remove("performance_data");
Deserialize(cr, params->Get("cr"), true);
NotificationType type = static_cast<NotificationType>(static_cast<int>(params->Get("type")));
String author = params->Get("author");
String text = params->Get("text");
Checkable::OnNotificationsRequested(checkable, type, cr, author, text, origin);
return Empty;
}

View File

@ -66,6 +66,10 @@ public:
static Value UpdateRepositoryAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);
static Dictionary::Ptr MakeCheckResultMessage(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr);
static void SendNotificationsHandler(const Checkable::Ptr& checkable, NotificationType type,
const CheckResult::Ptr& cr, const String& author, const String& text, const MessageOrigin::Ptr& origin);
static Value SendNotificationsAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);
};
}

View File

@ -1290,7 +1290,8 @@ void ExternalCommandProcessor::SendCustomHostNotification(double, const std::vec
host->SetForceNextNotification(true);
}
Checkable::OnNotificationsRequested(host, NotificationCustom, host->GetLastCheckResult(), arguments[2], arguments[3]);
Checkable::OnNotificationsRequested(host, NotificationCustom,
host->GetLastCheckResult(), arguments[2], arguments[3], MessageOrigin::Ptr());
}
void ExternalCommandProcessor::SendCustomSvcNotification(double, const std::vector<String>& arguments)
@ -1309,7 +1310,8 @@ void ExternalCommandProcessor::SendCustomSvcNotification(double, const std::vect
service->SetForceNextNotification(true);
}
Service::OnNotificationsRequested(service, NotificationCustom, service->GetLastCheckResult(), arguments[3], arguments[4]);
Service::OnNotificationsRequested(service, NotificationCustom,
service->GetLastCheckResult(), arguments[3], arguments[4], MessageOrigin::Ptr());
}
void ExternalCommandProcessor::DelayHostNotification(double, const std::vector<String>& arguments)

View File

@ -131,8 +131,5 @@ void NotificationComponent::NotificationTimerHandler(void)
void NotificationComponent::SendNotificationsHandler(const Checkable::Ptr& checkable, NotificationType type,
const CheckResult::Ptr& cr, const String& author, const String& text)
{
if (checkable->IsPaused() && GetEnableHA())
return;
checkable->SendNotifications(type, cr, author, text);
}