diff --git a/components/compat/compatcomponent.cpp b/components/compat/compatcomponent.cpp index 7d00e3888..a461818b6 100644 --- a/components/compat/compatcomponent.cpp +++ b/components/compat/compatcomponent.cpp @@ -296,6 +296,9 @@ void CompatComponent::DumpServiceStatus(ofstream& fp, const Service::Ptr& servic << "\t" << "last_update=" << time(NULL) << "\n" << "\t" << "active_checks_enabled=" << (service->GetEnableChecks() ? 1 : 0) <<"\n" << "\t" << "passive_checks_enabled=1" << "\n" + << "\t" << "problem_has_been_acknowledged=" << (service->GetAcknowledgement() != AcknowledgementNone ? 1 : 0) << "\n" + << "\t" << "acknowledgement_type=" << static_cast(service->GetAcknowledgement()) << "\n" + << "\t" << "acknowledgement_end_time=" << service->GetAcknowledgementExpiry() << "\n" << "\t" << "}" << "\n" << "\n"; } diff --git a/lib/icinga/externalcommand.cpp b/lib/icinga/externalcommand.cpp index 8c4764d34..d7f7496fc 100644 --- a/lib/icinga/externalcommand.cpp +++ b/lib/icinga/externalcommand.cpp @@ -38,6 +38,10 @@ void ExternalCommand::Execute(double time, const String& command, const vector& ar } } +void ExternalCommand::AcknowledgeSvcProblem(double time, const vector& arguments) +{ + if (arguments.size() < 7) + throw_exception(invalid_argument("Expected 7 arguments.")); + + if (!Service::Exists(arguments[1])) + throw_exception(invalid_argument("The service '" + arguments[1] + "' does not exist.")); + + int sticky = arguments[2].ToDouble(); + + Service::Ptr service = Service::GetByName(arguments[1]); + + service->SetAcknowledgement(sticky ? AcknowledgementSticky : AcknowledgementNormal); + service->SetAcknowledgementExpiry(0); +} + +void ExternalCommand::AcknowledgeSvcProblemExpire(double time, const vector& arguments) +{ + if (arguments.size() < 8) + throw_exception(invalid_argument("Expected 8 arguments.")); + + if (!Service::Exists(arguments[1])) + throw_exception(invalid_argument("The service '" + arguments[1] + "' does not exist.")); + + int sticky = arguments[2].ToDouble(); + double timestamp = arguments[4].ToDouble(); + + Service::Ptr service = Service::GetByName(arguments[1]); + + service->SetAcknowledgement(sticky ? AcknowledgementSticky : AcknowledgementNormal); + service->SetAcknowledgementExpiry(timestamp); +} + +void ExternalCommand::RemoveSvcAcknowledgement(double time, const vector& arguments) +{ + if (arguments.size() < 2) + throw_exception(invalid_argument("Expected 2 arguments.")); + + if (!Service::Exists(arguments[1])) + throw_exception(invalid_argument("The service '" + arguments[1] + "' does not exist.")); + + Service::Ptr service = Service::GetByName(arguments[1]); + + service->SetAcknowledgement(AcknowledgementNone); + service->SetAcknowledgementExpiry(0); +} + diff --git a/lib/icinga/externalcommand.h b/lib/icinga/externalcommand.h index adb7eb555..346c6041b 100644 --- a/lib/icinga/externalcommand.h +++ b/lib/icinga/externalcommand.h @@ -39,6 +39,9 @@ public: static void ScheduleHostSvcChecks(double time, const vector& arguments); static void EnableHostSvcChecks(double time, const vector& arguments); static void DisableHostSvcChecks(double time, const vector& arguments); + static void AcknowledgeSvcProblem(double time, const vector& arguments); + static void AcknowledgeSvcProblemExpire(double time, const vector& arguments); + static void RemoveSvcAcknowledgement(double time, const vector& arguments); private: typedef function& arguments)> Callback; diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index ef9b94dbd..d9d49ec5c 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -43,7 +43,9 @@ static AttributeDescription serviceAttributes[] = { { "last_state_change", Attribute_Replicated }, { "last_hard_state_change", Attribute_Replicated }, { "enable_checks", Attribute_Replicated }, - { "force_next_check", Attribute_Replicated } + { "force_next_check", Attribute_Replicated }, + { "acknowledgement", Attribute_Replicated }, + { "acknowledgement_expiry", Attribute_Replicated } }; REGISTER_TYPE(Service, serviceAttributes); @@ -385,6 +387,48 @@ void Service::SetForceNextCheck(bool forced) Set("force_next_check", forced ? 1 : 0); } +AcknowledgementType Service::GetAcknowledgement(void) +{ + Value value = Get("acknowledgement"); + + if (value.IsEmpty()) + return AcknowledgementNone; + + int ivalue = static_cast(value); + AcknowledgementType avalue = static_cast(ivalue); + + if (avalue != AcknowledgementNone) { + double expiry = GetAcknowledgementExpiry(); + + if (expiry != 0 && expiry < Utility::GetTime()) { + avalue = AcknowledgementNone; + SetAcknowledgementExpiry(avalue); + } + } + + return avalue; +} + +void Service::SetAcknowledgement(AcknowledgementType acknowledgement) +{ + Set("acknowledgement", static_cast(acknowledgement)); +} + +double Service::GetAcknowledgementExpiry(void) const +{ + Value value = Get("acknowledgement_expiry"); + + if (value.IsEmpty()) + return 0; + + return static_cast(value); +} + +void Service::SetAcknowledgementExpiry(double timestamp) +{ + Set("acknowledgement_expiry", timestamp); +} + void Service::ApplyCheckResult(const Dictionary::Ptr& cr) { ServiceState old_state = GetState(); @@ -421,6 +465,13 @@ void Service::ApplyCheckResult(const Dictionary::Ptr& cr) if (old_stateType != GetStateType()) SetLastHardStateChange(now); + + /* remove acknowledgements */ + if (GetAcknowledgement() == AcknowledgementNormal || + (GetAcknowledgement() == AcknowledgementSticky && GetStateType() == StateTypeHard && GetState() == StateOK)) { + SetAcknowledgement(AcknowledgementNone); + SetAcknowledgementExpiry(0); + } } } diff --git a/lib/icinga/service.h b/lib/icinga/service.h index 99b143950..91bbc92b0 100644 --- a/lib/icinga/service.h +++ b/lib/icinga/service.h @@ -48,6 +48,18 @@ enum ServiceStateType StateTypeHard }; +/** + * The acknowledgement type of a service. + * + * @ingroup icinga + */ +enum AcknowledgementType +{ + AcknowledgementNone = 0, + AcknowledgementNormal = 1, + AcknowledgementSticky = 2 +}; + class CheckResultMessage; class ServiceStatusMessage; @@ -122,6 +134,12 @@ public: bool GetForceNextCheck(void) const; void SetForceNextCheck(bool forced); + AcknowledgementType GetAcknowledgement(void); + void SetAcknowledgement(AcknowledgementType acknowledgement); + + double GetAcknowledgementExpiry(void) const; + void SetAcknowledgementExpiry(double timestamp); + void ApplyCheckResult(const Dictionary::Ptr& cr); void BeginExecuteCheck(const function& callback);