diff --git a/doc/12-icinga2-api.md b/doc/12-icinga2-api.md index ffc7df04faf..d8852f174d0 100644 --- a/doc/12-icinga2-api.md +++ b/doc/12-icinga2-api.md @@ -901,13 +901,14 @@ are disabled. Send a `POST` request to the URL endpoint `/v1/actions/acknowledge-problem`. - Parameter | Type | Description - ----------|-----------|-------------- - author | string | **Required.** Name of the author, may be empty. - comment | string | **Required.** Comment text, may be empty. - expiry | timestamp | **Optional.** Whether the acknowledgement will be removed at the timestamp. - sticky | boolean | **Optional.** Whether the acknowledgement will be set until the service or host fully recovers. Defaults to `false`. - notify | boolean | **Optional.** Whether a notification of the `Acknowledgement` type will be sent. Defaults to `false`. + Parameter | Type | Description + ---------------------|-----------|-------------- + author | string | **Required.** Name of the author, may be empty. + comment | string | **Required.** Comment text, may be empty. + expiry | timestamp | **Optional.** Whether the acknowledgement will be removed at the timestamp. + sticky | boolean | **Optional.** Whether the acknowledgement will be set until the service or host fully recovers. Defaults to `false`. + notify | boolean | **Optional.** Whether a notification of the `Acknowledgement` type will be sent. Defaults to `false`. + comment\_persistance | boolean | **Optional.** When the comment is of type `Acknowledgement` and this is set to `true`, the comment will remain after the acknowledgement recovers or expires. Defaults to `false`. In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`. diff --git a/lib/db_ido/dbevents.cpp b/lib/db_ido/dbevents.cpp index 32fdf04d179..0908359e06a 100644 --- a/lib/db_ido/dbevents.cpp +++ b/lib/db_ido/dbevents.cpp @@ -354,7 +354,7 @@ void DbEvents::AddCommentInternal(std::vector& queries, const Comment:: fields1->Set("comment_time", DbValue::FromTimestamp(entry_time)); /* same as entry_time */ fields1->Set("author_name", comment->GetAuthor()); fields1->Set("comment_data", comment->GetText()); - fields1->Set("is_persistent", 1); + fields1->Set("is_persistent", (comment->GetCommentPersistance() == true) ? 1 : 0); fields1->Set("comment_source", 1); /* external */ fields1->Set("expires", (comment->GetExpireTime() > 0) ? 1 : 0); fields1->Set("expiration_time", DbValue::FromTimestamp(comment->GetExpireTime())); diff --git a/lib/icinga/apiactions.cpp b/lib/icinga/apiactions.cpp index d4211357b50..a7a435b03cb 100644 --- a/lib/icinga/apiactions.cpp +++ b/lib/icinga/apiactions.cpp @@ -194,12 +194,15 @@ Dictionary::Ptr ApiActions::AcknowledgeProblem(const ConfigObject::Ptr& object, AcknowledgementType sticky = AcknowledgementNormal; bool notify = false; + bool comment_persistance = false; double timestamp = 0.0; if (params->Contains("sticky") && HttpUtility::GetLastParameter(params, "sticky")) sticky = AcknowledgementSticky; if (params->Contains("notify")) notify = HttpUtility::GetLastParameter(params, "notify"); + if (params->Contains("comment_persistance")) + comment_persistance = HttpUtility::GetLastParameter(params, "comment_persistance"); if (params->Contains("expiry")) timestamp = HttpUtility::GetLastParameter(params, "expiry"); else @@ -218,7 +221,7 @@ Dictionary::Ptr ApiActions::AcknowledgeProblem(const ConfigObject::Ptr& object, } Comment::AddComment(checkable, CommentAcknowledgement, HttpUtility::GetLastParameter(params, "author"), - HttpUtility::GetLastParameter(params, "comment"), timestamp); + HttpUtility::GetLastParameter(params, "comment"), comment_persistance, timestamp); checkable->AcknowledgeProblem(HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), sticky, notify, timestamp); @@ -254,7 +257,7 @@ Dictionary::Ptr ApiActions::AddComment(const ConfigObject::Ptr& object, String commentName = Comment::AddComment(checkable, CommentUser, HttpUtility::GetLastParameter(params, "author"), - HttpUtility::GetLastParameter(params, "comment"), 0); + HttpUtility::GetLastParameter(params, "comment"), false, 0); Comment::Ptr comment = Comment::GetByName(commentName); diff --git a/lib/icinga/apievents.cpp b/lib/icinga/apievents.cpp index cd69bfdd74b..c262889589d 100644 --- a/lib/icinga/apievents.cpp +++ b/lib/icinga/apievents.cpp @@ -178,7 +178,7 @@ void ApiEvents::FlappingChangedHandler(const Checkable::Ptr& checkable, const Me void ApiEvents::AcknowledgementSetHandler(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, - bool notify, double expiry, const MessageOrigin::Ptr& origin) + bool notify, bool comment_persistance, double expiry, const MessageOrigin::Ptr& origin) { std::vector queues = EventQueue::GetQueuesForType("AcknowledgementSet"); @@ -206,6 +206,7 @@ void ApiEvents::AcknowledgementSetHandler(const Checkable::Ptr& checkable, result->Set("comment", comment); result->Set("acknowledgement_type", type); result->Set("notify", notify); + result->Set("comment_persistance", comment_persistance); result->Set("expiry", expiry); for (const EventQueue::Ptr& queue : queues) { diff --git a/lib/icinga/apievents.hpp b/lib/icinga/apievents.hpp index 2ca07b4ee97..35dad151853 100644 --- a/lib/icinga/apievents.hpp +++ b/lib/icinga/apievents.hpp @@ -46,7 +46,7 @@ class I2_ICINGA_API ApiEvents static void AcknowledgementSetHandler(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, - bool notify, double expiry, const MessageOrigin::Ptr& origin); + bool notify, bool comment_persistance, double expiry, const MessageOrigin::Ptr& origin); static void AcknowledgementClearedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin); static void CommentAddedHandler(const Comment::Ptr& comment); diff --git a/lib/icinga/checkable-comment.cpp b/lib/icinga/checkable-comment.cpp index e91321b296f..da9ce71843b 100644 --- a/lib/icinga/checkable-comment.cpp +++ b/lib/icinga/checkable-comment.cpp @@ -38,6 +38,10 @@ void Checkable::RemoveAllComments(void) void Checkable::RemoveCommentsByType(int type) { for (const Comment::Ptr& comment : GetComments()) { + /* Do not remove comments set as true in comment_persistance when it originates from an Acknowledgement */ + if (comment->GetEntryType() == CommentAcknowledgement && comment->GetCommentPersistance()) + continue; + if (comment->GetEntryType() == type) Comment::RemoveComment(comment->GetName()); } diff --git a/lib/icinga/checkable.cpp b/lib/icinga/checkable.cpp index f2259d2b865..d51fd651dfe 100644 --- a/lib/icinga/checkable.cpp +++ b/lib/icinga/checkable.cpp @@ -30,7 +30,7 @@ using namespace icinga; REGISTER_TYPE_WITH_PROTOTYPE(Checkable, Checkable::GetPrototype()); INITIALIZE_ONCE(&Checkable::StaticInitialize); -boost::signals2::signal Checkable::OnAcknowledgementSet; +boost::signals2::signal Checkable::OnAcknowledgementSet; boost::signals2::signal Checkable::OnAcknowledgementCleared; void Checkable::StaticInitialize(void) @@ -122,7 +122,7 @@ bool Checkable::IsAcknowledged(void) return GetAcknowledgement() != AcknowledgementNone; } -void Checkable::AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify, double expiry, const MessageOrigin::Ptr& origin) +void Checkable::AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify, bool comment_persistance, double expiry, const MessageOrigin::Ptr& origin) { SetAcknowledgementRaw(type); SetAcknowledgementExpiry(expiry); @@ -130,7 +130,7 @@ void Checkable::AcknowledgeProblem(const String& author, const String& comment, if (notify && !IsPaused()) OnNotificationsRequested(this, NotificationAcknowledgement, GetLastCheckResult(), author, comment, MessageOrigin::Ptr()); - OnAcknowledgementSet(this, author, comment, type, notify, expiry, origin); + OnAcknowledgementSet(this, author, comment, type, notify, comment_persistance, expiry, origin); } void Checkable::ClearAcknowledgement(const MessageOrigin::Ptr& origin) diff --git a/lib/icinga/checkable.hpp b/lib/icinga/checkable.hpp index 49319f95d73..84896937a48 100644 --- a/lib/icinga/checkable.hpp +++ b/lib/icinga/checkable.hpp @@ -82,7 +82,7 @@ class I2_ICINGA_API Checkable : public ObjectImpl AcknowledgementType GetAcknowledgement(void); - void AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify = true, double expiry = 0, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); + void AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify = true, bool comment_persistance = false, double expiry = 0, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); void ClearAcknowledgement(const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); /* Checks */ @@ -121,7 +121,7 @@ class I2_ICINGA_API Checkable : public ObjectImpl const NotificationType&, const CheckResult::Ptr&, const String&, const String&, const MessageOrigin::Ptr&)> OnNotificationSentToAllUsers; static boost::signals2::signal OnAcknowledgementSet; + bool, bool, double, const MessageOrigin::Ptr&)> OnAcknowledgementSet; static boost::signals2::signal OnAcknowledgementCleared; static boost::signals2::signal OnNextCheckUpdated; static boost::signals2::signal OnEventCommandExecuted; diff --git a/lib/icinga/clusterevents.cpp b/lib/icinga/clusterevents.cpp index aa5ce9b43af..6df91dc14bb 100644 --- a/lib/icinga/clusterevents.cpp +++ b/lib/icinga/clusterevents.cpp @@ -445,7 +445,7 @@ Value ClusterEvents::ForceNextNotificationChangedAPIHandler(const MessageOrigin: void ClusterEvents::AcknowledgementSetHandler(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, - bool notify, double expiry, const MessageOrigin::Ptr& origin) + bool notify, bool comment_persistance, double expiry, const MessageOrigin::Ptr& origin) { ApiListener::Ptr listener = ApiListener::GetInstance(); @@ -510,7 +510,7 @@ Value ClusterEvents::AcknowledgementSetAPIHandler(const MessageOrigin::Ptr& orig checkable->AcknowledgeProblem(params->Get("author"), params->Get("comment"), static_cast(static_cast(params->Get("acktype"))), - params->Get("notify"), params->Get("expiry"), origin); + params->Get("notify"), params->Get("comment_persistance"), params->Get("expiry"), origin); return Empty; } diff --git a/lib/icinga/clusterevents.hpp b/lib/icinga/clusterevents.hpp index 6078af5d6ef..277b69f84ab 100644 --- a/lib/icinga/clusterevents.hpp +++ b/lib/icinga/clusterevents.hpp @@ -53,7 +53,7 @@ class I2_ICINGA_API ClusterEvents static Value ForceNextNotificationChangedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); static void AcknowledgementSetHandler(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, - bool notify, double expiry, const MessageOrigin::Ptr& origin); + bool notify, bool comment_persistance, double expiry, const MessageOrigin::Ptr& origin); static Value AcknowledgementSetAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); static void AcknowledgementClearedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin); diff --git a/lib/icinga/comment.cpp b/lib/icinga/comment.cpp index af7b2f16a6e..c6fafc56112 100644 --- a/lib/icinga/comment.cpp +++ b/lib/icinga/comment.cpp @@ -150,7 +150,7 @@ int Comment::GetNextCommentID(void) } String Comment::AddComment(const Checkable::Ptr& checkable, CommentType entryType, const String& author, - const String& text, double expireTime, const String& id, const MessageOrigin::Ptr& origin) + const String& text, bool comment_persistance, double expireTime, const String& id, const MessageOrigin::Ptr& origin) { String fullName; @@ -163,6 +163,7 @@ String Comment::AddComment(const Checkable::Ptr& checkable, CommentType entryTyp attrs->Set("author", author); attrs->Set("text", text); + attrs->Set("comment_persistance", comment_persistance); attrs->Set("expire_time", expireTime); attrs->Set("entry_type", entryType); attrs->Set("entry_time", Utility::GetTime()); @@ -247,6 +248,10 @@ void Comment::CommentsExpireTimerHandler(void) } for (const Comment::Ptr& comment : comments) { + /* Do not remove comments set as persistent when it originates from an Acknowledgement */ + if (comment->GetEntryType() == CommentAcknowledgement && comment->IsActive() && comment->IsExpired() && comment->GetCommentPersistance()) + continue; + /* Only remove comment which are activated after daemon start. */ if (comment->IsActive() && comment->IsExpired()) RemoveComment(comment->GetName()); diff --git a/lib/icinga/comment.hpp b/lib/icinga/comment.hpp index 078f64e30ff..6cf87335d1d 100644 --- a/lib/icinga/comment.hpp +++ b/lib/icinga/comment.hpp @@ -49,7 +49,7 @@ class I2_ICINGA_API Comment : public ObjectImpl static int GetNextCommentID(void); static String AddComment(const intrusive_ptr& checkable, CommentType entryType, - const String& author, const String& text, double expireTime, + const String& author, const String& text, bool comment_persistance, double expireTime, const String& id = String(), const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); static void RemoveComment(const String& id, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr()); diff --git a/lib/icinga/comment.ti b/lib/icinga/comment.ti index 0187b49fe16..85d57807052 100644 --- a/lib/icinga/comment.ti +++ b/lib/icinga/comment.ti @@ -87,6 +87,7 @@ class Comment : ConfigObject < CommentNameComposer }; [config, required] String author; [config, required] String text; + [config] bool comment_persistance; [config] Timestamp expire_time; [state] int legacy_id; }; diff --git a/lib/icinga/externalcommandprocessor.cpp b/lib/icinga/externalcommandprocessor.cpp index 75e21bf9187..74edbbc0b55 100644 --- a/lib/icinga/externalcommandprocessor.cpp +++ b/lib/icinga/externalcommandprocessor.cpp @@ -621,6 +621,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const std::vector 0 ? true : false); + bool comment_persistance = (Convert::ToLong(arguments[4]) > 0 ? true : false); Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]); @@ -633,14 +634,15 @@ void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const std::vectorGetName() << "'" << (notify ? "" : ". Disabled notification"); - Comment::AddComment(service, CommentAcknowledgement, arguments[5], arguments[6], 0); - service->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify); + Comment::AddComment(service, CommentAcknowledgement, arguments[5], arguments[6], comment_persistance, 0); + service->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, comment_persistance, notify); } void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const std::vector& arguments) { bool sticky = (Convert::ToLong(arguments[2]) == 2 ? true : false); bool notify = (Convert::ToLong(arguments[3]) > 0 ? true : false); + bool comment_persistance = (Convert::ToLong(arguments[4]) > 0 ? true : false); double timestamp = Convert::ToDouble(arguments[5]); Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]); @@ -654,8 +656,8 @@ void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const std::ve Log(LogNotice, "ExternalCommandProcessor") << "Setting timed acknowledgement for service '" << service->GetName() << "'" << (notify ? "" : ". Disabled notification"); - Comment::AddComment(service, CommentAcknowledgement, arguments[6], arguments[7], timestamp); - service->AcknowledgeProblem(arguments[6], arguments[7], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, timestamp); + Comment::AddComment(service, CommentAcknowledgement, arguments[6], arguments[7], comment_persistance, timestamp); + service->AcknowledgeProblem(arguments[6], arguments[7], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, comment_persistance, timestamp); } void ExternalCommandProcessor::RemoveSvcAcknowledgement(double, const std::vector& arguments) @@ -680,6 +682,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblem(double, const std::vector< { bool sticky = (Convert::ToLong(arguments[1]) == 2 ? true : false); bool notify = (Convert::ToLong(arguments[2]) > 0 ? true : false); + bool comment_persistance = (Convert::ToLong(arguments[3]) > 0 ? true : false); Host::Ptr host = Host::GetByName(arguments[0]); @@ -692,14 +695,15 @@ void ExternalCommandProcessor::AcknowledgeHostProblem(double, const std::vector< if (host->GetState() == HostUp) BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK.")); - Comment::AddComment(host, CommentAcknowledgement, arguments[4], arguments[5], 0); - host->AcknowledgeProblem(arguments[4], arguments[5], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify); + Comment::AddComment(host, CommentAcknowledgement, arguments[4], arguments[5], comment_persistance, 0); + host->AcknowledgeProblem(arguments[4], arguments[5], sticky ? AcknowledgementSticky : AcknowledgementNormal, comment_persistance, notify); } void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const std::vector& arguments) { bool sticky = (Convert::ToLong(arguments[1]) == 2 ? true : false); bool notify = (Convert::ToLong(arguments[2]) > 0 ? true : false); + bool comment_persistance = (Convert::ToLong(arguments[3]) > 0 ? true : false); double timestamp = Convert::ToDouble(arguments[4]); Host::Ptr host = Host::GetByName(arguments[0]); @@ -713,8 +717,8 @@ void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const std::v if (host->GetState() == HostUp) BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK.")); - Comment::AddComment(host, CommentAcknowledgement, arguments[5], arguments[6], timestamp); - host->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, timestamp); + Comment::AddComment(host, CommentAcknowledgement, arguments[5], arguments[6], comment_persistance, timestamp); + host->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, comment_persistance, timestamp); } void ExternalCommandProcessor::RemoveHostAcknowledgement(double, const std::vector& arguments) @@ -1286,7 +1290,7 @@ void ExternalCommandProcessor::AddHostComment(double, const std::vector& Log(LogNotice, "ExternalCommandProcessor") << "Creating comment for host " << host->GetName(); - (void) Comment::AddComment(host, CommentUser, arguments[2], arguments[3], 0); + (void) Comment::AddComment(host, CommentUser, arguments[2], arguments[3], false, 0); } void ExternalCommandProcessor::DelHostComment(double, const std::vector& arguments) @@ -1310,7 +1314,7 @@ void ExternalCommandProcessor::AddSvcComment(double, const std::vector& Log(LogNotice, "ExternalCommandProcessor") << "Creating comment for service " << service->GetName(); - (void) Comment::AddComment(service, CommentUser, arguments[3], arguments[4], 0); + (void) Comment::AddComment(service, CommentUser, arguments[3], arguments[4], false, 0); } void ExternalCommandProcessor::DelSvcComment(double, const std::vector& arguments)