Merge pull request #7695 from Icinga/bugfix/double-ack

Refuse acking an already acked checkable
This commit is contained in:
Michael Friedrich 2019-12-09 19:23:41 +01:00 committed by GitHub
commit ce1a71cfec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 1 deletions

View File

@ -8,6 +8,13 @@ Specific version upgrades are described below. Please note that version
updates are incremental. An upgrade from v2.6 to v2.8 requires to updates are incremental. An upgrade from v2.6 to v2.8 requires to
follow the instructions for v2.7 too. follow the instructions for v2.7 too.
## Upgrading to v2.12 <a id="upgrading-to-2-12"></a>
### Breaking changes <a id="upgrading-to-2-12-breaking-changes"></a>
As of v2.12 our [API](12-icinga2-api.md) URL endpoint [`/v1/actions/acknowledge-problem`](12-icinga2-api.md#icinga2-api-actions-acknowledge-problem) refuses acknowledging an already acknowledged checkable by overwriting the acknowledgement.
To replace an acknowledgement you have to remove the old one before adding the new one.
## Upgrading to v2.11 <a id="upgrading-to-2-11"></a> ## Upgrading to v2.11 <a id="upgrading-to-2-11"></a>
### Bugfixes for 2.11 <a id="upgrading-to-2-11-bugfixes"></a> ### Bugfixes for 2.11 <a id="upgrading-to-2-11-bugfixes"></a>

View File

@ -214,6 +214,8 @@ Dictionary::Ptr ApiActions::AcknowledgeProblem(const ConfigObject::Ptr& object,
} else } else
timestamp = 0; timestamp = 0;
ObjectLock oLock (checkable);
Host::Ptr host; Host::Ptr host;
Service::Ptr service; Service::Ptr service;
tie(host, service) = GetHostService(checkable); tie(host, service) = GetHostService(checkable);
@ -226,6 +228,10 @@ Dictionary::Ptr ApiActions::AcknowledgeProblem(const ConfigObject::Ptr& object,
return ApiActions::CreateResult(409, "Service " + checkable->GetName() + " is OK."); return ApiActions::CreateResult(409, "Service " + checkable->GetName() + " is OK.");
} }
if (checkable->IsAcknowledged()) {
return ApiActions::CreateResult(409, (service ? "Service " : "Host ") + checkable->GetName() + " is already acknowledged.");
}
Comment::AddComment(checkable, CommentAcknowledgement, HttpUtility::GetLastParameter(params, "author"), Comment::AddComment(checkable, CommentAcknowledgement, HttpUtility::GetLastParameter(params, "author"),
HttpUtility::GetLastParameter(params, "comment"), persistent, timestamp); HttpUtility::GetLastParameter(params, "comment"), persistent, timestamp);
checkable->AcknowledgeProblem(HttpUtility::GetLastParameter(params, "author"), checkable->AcknowledgeProblem(HttpUtility::GetLastParameter(params, "author"),

View File

@ -138,13 +138,27 @@ void Checkable::AcknowledgeProblem(const String& author, const String& comment,
void Checkable::ClearAcknowledgement(const String& removedBy, const MessageOrigin::Ptr& origin) void Checkable::ClearAcknowledgement(const String& removedBy, const MessageOrigin::Ptr& origin)
{ {
ObjectLock oLock (this);
bool wasAcked;
if (GetAcknowledgementRaw() == AcknowledgementNone) {
wasAcked = false;
} else {
double expiry = GetAcknowledgementExpiry();
wasAcked = expiry == 0 || expiry >= Utility::GetTime();
}
SetAcknowledgementRaw(AcknowledgementNone); SetAcknowledgementRaw(AcknowledgementNone);
SetAcknowledgementExpiry(0); SetAcknowledgementExpiry(0);
Log(LogInformation, "Checkable") Log(LogInformation, "Checkable")
<< "Acknowledgement cleared for checkable '" << GetName() << "'."; << "Acknowledgement cleared for checkable '" << GetName() << "'.";
OnAcknowledgementCleared(this, removedBy, origin); if (wasAcked) {
OnAcknowledgementCleared(this, removedBy, origin);
}
} }
Endpoint::Ptr Checkable::GetCommandEndpoint() const Endpoint::Ptr Checkable::GetCommandEndpoint() const

View File

@ -535,6 +535,15 @@ Value ClusterEvents::AcknowledgementSetAPIHandler(const MessageOrigin::Ptr& orig
return Empty; return Empty;
} }
ObjectLock oLock (checkable);
if (checkable->IsAcknowledged()) {
Log(LogWarning, "ClusterEvents")
<< "Discarding 'acknowledgement set' message for checkable '" << checkable->GetName()
<< "' from '" << origin->FromClient->GetIdentity() << "': Checkable is already acknowledged.";
return Empty;
}
checkable->AcknowledgeProblem(params->Get("author"), params->Get("comment"), checkable->AcknowledgeProblem(params->Get("author"), params->Get("comment"),
static_cast<AcknowledgementType>(static_cast<int>(params->Get("acktype"))), static_cast<AcknowledgementType>(static_cast<int>(params->Get("acktype"))),
params->Get("notify"), params->Get("persistent"), params->Get("expiry"), origin); params->Get("notify"), params->Get("persistent"), params->Get("expiry"), origin);

View File

@ -588,6 +588,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const std::vector<S
bool persistent = (Convert::ToLong(arguments[4]) > 0 ? true : false); bool persistent = (Convert::ToLong(arguments[4]) > 0 ? true : false);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]); Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
ObjectLock oLock (service);
if (!service) if (!service)
BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge service problem for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'")); BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge service problem for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
@ -595,6 +596,10 @@ void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const std::vector<S
if (service->GetState() == ServiceOK) if (service->GetState() == ServiceOK)
BOOST_THROW_EXCEPTION(std::invalid_argument("The service '" + arguments[1] + "' is OK.")); BOOST_THROW_EXCEPTION(std::invalid_argument("The service '" + arguments[1] + "' is OK."));
if (service->IsAcknowledged()) {
BOOST_THROW_EXCEPTION(std::invalid_argument("The service '" + arguments[1] + "' is already acknowledged."));
}
Log(LogNotice, "ExternalCommandProcessor") Log(LogNotice, "ExternalCommandProcessor")
<< "Setting acknowledgement for service '" << service->GetName() << "'" << (notify ? "" : ". Disabled notification"); << "Setting acknowledgement for service '" << service->GetName() << "'" << (notify ? "" : ". Disabled notification");
@ -610,6 +615,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const std::ve
double timestamp = Convert::ToDouble(arguments[5]); double timestamp = Convert::ToDouble(arguments[5]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]); Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
ObjectLock oLock (service);
if (!service) if (!service)
BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge service problem with expire time for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'")); BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge service problem with expire time for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
@ -620,6 +626,10 @@ void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const std::ve
if (timestamp != 0 && timestamp <= Utility::GetTime()) if (timestamp != 0 && timestamp <= Utility::GetTime())
BOOST_THROW_EXCEPTION(std::invalid_argument("Acknowledgement expire time must be in the future for service '" + arguments[1] + "' on host '" + arguments[0] + "'")); BOOST_THROW_EXCEPTION(std::invalid_argument("Acknowledgement expire time must be in the future for service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
if (service->IsAcknowledged()) {
BOOST_THROW_EXCEPTION(std::invalid_argument("The service '" + arguments[1] + "' is already acknowledged."));
}
Log(LogNotice, "ExternalCommandProcessor") Log(LogNotice, "ExternalCommandProcessor")
<< "Setting timed acknowledgement for service '" << service->GetName() << "'" << (notify ? "" : ". Disabled notification"); << "Setting timed acknowledgement for service '" << service->GetName() << "'" << (notify ? "" : ". Disabled notification");
@ -652,6 +662,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblem(double, const std::vector<
bool persistent = (Convert::ToLong(arguments[3]) > 0 ? true : false); bool persistent = (Convert::ToLong(arguments[3]) > 0 ? true : false);
Host::Ptr host = Host::GetByName(arguments[0]); Host::Ptr host = Host::GetByName(arguments[0]);
ObjectLock oLock (host);
if (!host) if (!host)
BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge host problem for non-existent host '" + arguments[0] + "'")); BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge host problem for non-existent host '" + arguments[0] + "'"));
@ -662,6 +673,10 @@ void ExternalCommandProcessor::AcknowledgeHostProblem(double, const std::vector<
if (host->GetState() == HostUp) if (host->GetState() == HostUp)
BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK.")); BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK."));
if (host->IsAcknowledged()) {
BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[1] + "' is already acknowledged."));
}
Comment::AddComment(host, CommentAcknowledgement, arguments[4], arguments[5], persistent, 0); Comment::AddComment(host, CommentAcknowledgement, arguments[4], arguments[5], persistent, 0);
host->AcknowledgeProblem(arguments[4], arguments[5], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, persistent); host->AcknowledgeProblem(arguments[4], arguments[5], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, persistent);
} }
@ -674,6 +689,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const std::v
double timestamp = Convert::ToDouble(arguments[4]); double timestamp = Convert::ToDouble(arguments[4]);
Host::Ptr host = Host::GetByName(arguments[0]); Host::Ptr host = Host::GetByName(arguments[0]);
ObjectLock oLock (host);
if (!host) if (!host)
BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge host problem with expire time for non-existent host '" + arguments[0] + "'")); BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge host problem with expire time for non-existent host '" + arguments[0] + "'"));
@ -687,6 +703,10 @@ void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const std::v
if (timestamp != 0 && timestamp <= Utility::GetTime()) if (timestamp != 0 && timestamp <= Utility::GetTime())
BOOST_THROW_EXCEPTION(std::invalid_argument("Acknowledgement expire time must be in the future for host '" + arguments[0] + "'")); BOOST_THROW_EXCEPTION(std::invalid_argument("Acknowledgement expire time must be in the future for host '" + arguments[0] + "'"));
if (host->IsAcknowledged()) {
BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[1] + "' is already acknowledged."));
}
Comment::AddComment(host, CommentAcknowledgement, arguments[5], arguments[6], persistent, timestamp); Comment::AddComment(host, CommentAcknowledgement, arguments[5], arguments[6], persistent, timestamp);
host->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, persistent, timestamp); host->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, persistent, timestamp);
} }