diff --git a/lib/compat/compatlogger.cpp b/lib/compat/compatlogger.cpp index 95ca830e1..60b47556e 100644 --- a/lib/compat/compatlogger.cpp +++ b/lib/compat/compatlogger.cpp @@ -130,7 +130,7 @@ void CompatLogger::CheckResultHandler(const Checkable::Ptr& checkable, const Che << host->GetName() << ";" << service->GetShortName() << ";" << Service::StateToString(service->GetState()) << ";" - << Service::StateTypeToString(service->GetStateType()) << ";" + << Checkable::StateTypeToString(service->GetStateType()) << ";" << attempt_after << ";" << output << "" << ""; @@ -140,7 +140,7 @@ void CompatLogger::CheckResultHandler(const Checkable::Ptr& checkable, const Che msgbuf << "HOST ALERT: " << host->GetName() << ";" << GetHostStateString(host) << ";" - << Host::StateTypeToString(host->GetStateType()) << ";" + << Checkable::StateTypeToString(host->GetStateType()) << ";" << attempt_after << ";" << output << "" << ""; @@ -413,14 +413,14 @@ void CompatLogger::EventCommandHandler(const Checkable::Ptr& checkable) << host->GetName() << ";" << service->GetShortName() << ";" << Service::StateToString(service->GetState()) << ";" - << Service::StateTypeToString(service->GetStateType()) << ";" + << Checkable::StateTypeToString(service->GetStateType()) << ";" << current_attempt << ";" << event_command_name; } else { msgbuf << "HOST EVENT HANDLER: " << host->GetName() << ";" << GetHostStateString(host) << ";" - << Host::StateTypeToString(host->GetStateType()) << ";" + << Checkable::StateTypeToString(host->GetStateType()) << ";" << current_attempt << ";" << event_command_name; } @@ -505,7 +505,7 @@ void CompatLogger::ReopenFile(bool rotate) msgbuf << "CURRENT HOST STATE: " << host->GetName() << ";" << GetHostStateString(host) << ";" - << Host::StateTypeToString(host->GetStateType()) << ";" + << Checkable::StateTypeToString(host->GetStateType()) << ";" << host->GetCheckAttempt() << ";" << output << ""; @@ -526,7 +526,7 @@ void CompatLogger::ReopenFile(bool rotate) << host->GetName() << ";" << service->GetShortName() << ";" << Service::StateToString(service->GetState()) << ";" - << Service::StateTypeToString(service->GetStateType()) << ";" + << Checkable::StateTypeToString(service->GetStateType()) << ";" << service->GetCheckAttempt() << ";" << output << ""; diff --git a/lib/db_ido/dbevents.cpp b/lib/db_ido/dbevents.cpp index 8358824e7..cf80a0226 100644 --- a/lib/db_ido/dbevents.cpp +++ b/lib/db_ido/dbevents.cpp @@ -994,7 +994,7 @@ void DbEvents::AddCheckResultLogHistory(const Checkable::Ptr& checkable, const C << host->GetName() << ";" << service->GetShortName() << ";" << Service::StateToString(service->GetState()) << ";" - << Service::StateTypeToString(service->GetStateType()) << ";" + << Checkable::StateTypeToString(service->GetStateType()) << ";" << service->GetCheckAttempt() << ";" << output << "" << ""; @@ -1021,7 +1021,7 @@ void DbEvents::AddCheckResultLogHistory(const Checkable::Ptr& checkable, const C msgbuf << "HOST ALERT: " << host->GetName() << ";" << GetHostStateString(host) << ";" - << Host::StateTypeToString(host->GetStateType()) << ";" + << Checkable::StateTypeToString(host->GetStateType()) << ";" << host->GetCheckAttempt() << ";" << output << "" << ""; diff --git a/lib/icinga/checkable.cpp b/lib/icinga/checkable.cpp index 13fd778a3..242139bc9 100644 --- a/lib/icinga/checkable.cpp +++ b/lib/icinga/checkable.cpp @@ -322,3 +322,9 @@ void Checkable::CleanDeadlinedExecutions(const Timer * const&) } } } + +String Checkable::StateTypeToString(StateType type) +{ + return type == StateTypeSoft ? "SOFT" : "HARD"; +} + diff --git a/lib/icinga/checkable.hpp b/lib/icinga/checkable.hpp index 310923ec8..e4403dadd 100644 --- a/lib/icinga/checkable.hpp +++ b/lib/icinga/checkable.hpp @@ -106,6 +106,8 @@ public: void UpdateNextCheck(const MessageOrigin::Ptr& origin = nullptr); + static String StateTypeToString(StateType type); + bool HasBeenChecked() const; virtual bool IsStateOK(ServiceState state) const = 0; diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index 10cd4b445..35fb25537 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -227,22 +227,6 @@ String Host::StateToString(HostState state) } } -StateType Host::StateTypeFromString(const String& type) -{ - if (type == "SOFT") - return StateTypeSoft; - else - return StateTypeHard; -} - -String Host::StateTypeToString(StateType type) -{ - if (type == StateTypeSoft) - return "SOFT"; - else - return "HARD"; -} - bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, Value *result) const { if (macro == "state") { diff --git a/lib/icinga/host.hpp b/lib/icinga/host.hpp index d0d6c1aa4..7cacd160f 100644 --- a/lib/icinga/host.hpp +++ b/lib/icinga/host.hpp @@ -45,9 +45,6 @@ public: static HostState StateFromString(const String& state); static String StateToString(HostState state); - static StateType StateTypeFromString(const String& state); - static String StateTypeToString(StateType state); - bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const override; void OnAllConfigLoaded() override; diff --git a/lib/icinga/notification.cpp b/lib/icinga/notification.cpp index 8c4cced1b..9bb0d05fa 100644 --- a/lib/icinga/notification.cpp +++ b/lib/icinga/notification.cpp @@ -100,12 +100,13 @@ void Notification::StaticInitialize() m_TypeFilterMap["FlappingEnd"] = NotificationFlappingEnd; } -void Notification::OnConfigLoaded() +Notification::Notification() { - ObjectImpl::OnConfigLoaded(); - - SetTypeFilter(FilterArrayToInt(GetTypes(), GetTypeFilterMap(), ~0)); - SetStateFilter(FilterArrayToInt(GetStates(), GetStateFilterMap(), ~0)); + // If a notification is created without specifying the "types/states" attribute, the Set* methods won't be called, + // consequently the filter bitset will also be 0. Thus, we need to ensure that the type/state filter are + // initialized to the default values, which are all types and states enabled. + SetTypes(nullptr, false, Empty); + SetStates(nullptr, false, Empty); } void Notification::OnAllConfigLoaded() @@ -751,6 +752,36 @@ String Notification::NotificationHostStateToString(HostState state) } } +Array::Ptr Notification::GetTypes() const +{ + return m_Types.load(); +} + +void Notification::SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie) +{ + m_Types.store(value); + // Ensure that the type filter is updated when the types attribute changes. + SetTypeFilter(FilterArrayToInt(value, GetTypeFilterMap(), ~0)); + if (!suppress_events) { + NotifyTypes(cookie); + } +} + +Array::Ptr Notification::GetStates() const +{ + return m_States.load(); +} + +void Notification::SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie) +{ + m_States.store(value); + // Ensure that the state filter is updated when the states attribute changes. + SetStateFilter(FilterArrayToInt(value, GetStateFilterMap(), ~0)); + if (!suppress_events) { + NotifyStates(cookie); + } +} + void Notification::Validate(int types, const ValidationUtils& utils) { ObjectImpl::Validate(types, utils); diff --git a/lib/icinga/notification.hpp b/lib/icinga/notification.hpp index 8c5a5f4b1..0e2f50c4c 100644 --- a/lib/icinga/notification.hpp +++ b/lib/icinga/notification.hpp @@ -29,7 +29,9 @@ enum NotificationFilter StateFilterUnknown = 8, StateFilterUp = 16, - StateFilterDown = 32 + StateFilterDown = 32, + + StateFilterAll = StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown | StateFilterUp | StateFilterDown, }; /** @@ -47,7 +49,11 @@ enum NotificationType NotificationProblem = 32, NotificationRecovery = 64, NotificationFlappingStart = 128, - NotificationFlappingEnd = 256 + NotificationFlappingEnd = 256, + + NotificationTypeAll = NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved | + NotificationCustom | NotificationAcknowledgement | NotificationProblem | NotificationRecovery | + NotificationFlappingStart | NotificationFlappingEnd, }; class NotificationCommand; @@ -68,6 +74,8 @@ public: DECLARE_OBJECT(Notification); DECLARE_OBJECTNAME(Notification); + Notification(); + static void StaticInitialize(); intrusive_ptr GetCheckable() const; @@ -109,13 +117,28 @@ public: static const std::map& GetStateFilterMap(); static const std::map& GetTypeFilterMap(); - void OnConfigLoaded() override; void OnAllConfigLoaded() override; void Start(bool runtimeCreated) override; void Stop(bool runtimeRemoved) override; + Array::Ptr GetTypes() const override; + void SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie) override; + + Array::Ptr GetStates() const override; + void SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie) override; + private: ObjectImpl::Ptr m_Checkable; + // These attributes represent the actual notification "types" and "states" attributes from the "notification.ti". + // However, since we want to ensure that the type and state bitsets are always in sync with those attributes, + // we need to override their setters, and this on the hand introduces another problem: The virtual setters are + // called from within the ObjectImpl constructor, which obviously violates the C++ standard [^1]. + // So, in order to avoid all this kind of mess, these two attributes have the "no_storage" flag set, and + // their getters/setters are pure virtual, which means this class has to provide the implementation of them. + // + // [^1]: https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctors + AtomicOrLocked m_Types; + AtomicOrLocked m_States; bool CheckNotificationUserFilters(NotificationType type, const User::Ptr& user, bool force, bool reminder); diff --git a/lib/icinga/notification.ti b/lib/icinga/notification.ti index a8121ff6b..e8c4418cd 100644 --- a/lib/icinga/notification.ti +++ b/lib/icinga/notification.ti @@ -41,9 +41,15 @@ class Notification : CustomVarObject < NotificationNameComposer [config, signal_with_old_value] array(name(User)) users (UsersRaw); [config, signal_with_old_value] array(name(UserGroup)) user_groups (UserGroupsRaw); [config] Dictionary::Ptr times; - [config] array(Value) types; + [config, no_storage] array(Value) types { + get; + set; + }; [no_user_view, no_user_modify] int type_filter_real (TypeFilter); - [config] array(Value) states; + [config, no_storage] array(Value) states { + get; + set; + }; [no_user_view, no_user_modify] int state_filter_real (StateFilter); [config, no_user_modify, protected, required, navigation(host)] name(Host) host_name { navigate {{{ diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index a26512b77..acc6c89e1 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -195,22 +195,6 @@ String Service::StateToString(ServiceState state) } } -StateType Service::StateTypeFromString(const String& type) -{ - if (type == "SOFT") - return StateTypeSoft; - else - return StateTypeHard; -} - -String Service::StateTypeToString(StateType type) -{ - if (type == StateTypeSoft) - return "SOFT"; - else - return "HARD"; -} - bool Service::ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const { if (macro == "state") { diff --git a/lib/icinga/service.hpp b/lib/icinga/service.hpp index ac27c3d93..558f73c03 100644 --- a/lib/icinga/service.hpp +++ b/lib/icinga/service.hpp @@ -39,9 +39,6 @@ public: static ServiceState StateFromString(const String& state); static String StateToString(ServiceState state); - static StateType StateTypeFromString(const String& state); - static String StateTypeToString(StateType state); - static void EvaluateApplyRules(const Host::Ptr& host); void OnAllConfigLoaded() override; diff --git a/lib/icinga/user.cpp b/lib/icinga/user.cpp index 5c646f656..ec72e9f8e 100644 --- a/lib/icinga/user.cpp +++ b/lib/icinga/user.cpp @@ -12,12 +12,13 @@ using namespace icinga; REGISTER_TYPE(User); -void User::OnConfigLoaded() +User::User() { - ObjectImpl::OnConfigLoaded(); - - SetTypeFilter(FilterArrayToInt(GetTypes(), Notification::GetTypeFilterMap(), ~0)); - SetStateFilter(FilterArrayToInt(GetStates(), Notification::GetStateFilterMap(), ~0)); + // If a User is created without specifying the "types/states" attribute, the Set* methods won't be called, + // consequently the filter bitset will also be 0. Thus, we need to ensure that the type/state filter are + // initialized to the default values, which are all types and states enabled. + SetTypes(nullptr, false, Empty); + SetStates(nullptr, false, Empty); } void User::OnAllConfigLoaded() @@ -80,6 +81,36 @@ TimePeriod::Ptr User::GetPeriod() const return TimePeriod::GetByName(GetPeriodRaw()); } +Array::Ptr User::GetTypes() const +{ + return m_Types.load(); +} + +void User::SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie) + { + m_Types.store(value); + // Ensure that the type filter is updated when the types attribute changes. + SetTypeFilter(FilterArrayToInt(value, Notification::GetTypeFilterMap(), ~0)); + if (!suppress_events) { + NotifyTypes(cookie); + } +} + +Array::Ptr User::GetStates() const +{ + return m_States.load(); +} + +void User::SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie) +{ + m_States.store(value); + // Ensure that the state filter is updated when the states attribute changes. + SetStateFilter(FilterArrayToInt(value, Notification::GetStateFilterMap(), ~0)); + if (!suppress_events) { + NotifyStates(cookie); + } +} + void User::ValidateStates(const Lazy& lvalue, const ValidationUtils& utils) { ObjectImpl::ValidateStates(lvalue, utils); diff --git a/lib/icinga/user.hpp b/lib/icinga/user.hpp index 14e59c2ce..5e87413cd 100644 --- a/lib/icinga/user.hpp +++ b/lib/icinga/user.hpp @@ -22,21 +22,38 @@ public: DECLARE_OBJECT(User); DECLARE_OBJECTNAME(User); + User(); + void AddGroup(const String& name); /* Notifications */ TimePeriod::Ptr GetPeriod() const; + Array::Ptr GetTypes() const override; + void SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie) override; + + Array::Ptr GetStates() const override; + void SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie) override; + void ValidateStates(const Lazy& lvalue, const ValidationUtils& utils) override; void ValidateTypes(const Lazy& lvalue, const ValidationUtils& utils) override; protected: void Stop(bool runtimeRemoved) override; - void OnConfigLoaded() override; void OnAllConfigLoaded() override; private: mutable std::mutex m_UserMutex; + // These attributes represent the actual User "types" and "states" attributes from the "user.ti". + // However, since we want to ensure that the type and state bitsets are always in sync with those attributes, + // we need to override their setters, and this on the hand introduces another problem: The virtual setters are + // called from within the ObjectImpl constructor, which obviously violates the C++ standard [^1]. + // So, in order to avoid al this kind of mess, these two attributes have the "no_storage" flag set, and + // their getters/setters are pure virtual, which means this class has to provide the implementation of them. + // + // [^1]: https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctors + AtomicOrLocked m_Types; + AtomicOrLocked m_States; }; } diff --git a/lib/icinga/user.ti b/lib/icinga/user.ti index 8b8c43a14..b42e1e826 100644 --- a/lib/icinga/user.ti +++ b/lib/icinga/user.ti @@ -29,9 +29,15 @@ class User : CustomVarObject }}} }; - [config] array(Value) types; + [config, no_storage] array(Value) types { + get; + set; + }; [no_user_view, no_user_modify] int type_filter_real (TypeFilter); - [config] array(Value) states; + [config, no_storage] array(Value) states { + get; + set; + }; [no_user_view, no_user_modify] int state_filter_real (StateFilter); [config] String email; diff --git a/lib/icingadb/icingadb-objects.cpp b/lib/icingadb/icingadb-objects.cpp index 56b74a3c1..594334658 100644 --- a/lib/icingadb/icingadb-objects.cpp +++ b/lib/icingadb/icingadb-objects.cpp @@ -1624,8 +1624,8 @@ bool IcingaDB::PrepareObject(const ConfigObject::Ptr& object, Dictionary::Ptr& a attributes->Set("email", user->GetEmail()); attributes->Set("pager", user->GetPager()); attributes->Set("notifications_enabled", user->GetEnableNotifications()); - attributes->Set("states", user->GetStates()); - attributes->Set("types", user->GetTypes()); + attributes->Set("states", StateFilterToRedisValue(user->GetStateFilter())); + attributes->Set("types", TypeFilterToRedisValue(user->GetTypeFilter())); if (user->GetPeriod()) attributes->Set("timeperiod_id", GetObjectIdentifier(user->GetPeriod())); @@ -1673,8 +1673,8 @@ bool IcingaDB::PrepareObject(const ConfigObject::Ptr& object, Dictionary::Ptr& a } attributes->Set("notification_interval", std::max(0.0, std::round(notification->GetInterval()))); - attributes->Set("states", notification->GetStates()); - attributes->Set("types", notification->GetTypes()); + attributes->Set("states", StateFilterToRedisValue(notification->GetStateFilter())); + attributes->Set("types", TypeFilterToRedisValue(notification->GetTypeFilter())); return true; } @@ -1684,7 +1684,7 @@ bool IcingaDB::PrepareObject(const ConfigObject::Ptr& object, Dictionary::Ptr& a attributes->Set("author", comment->GetAuthor()); attributes->Set("text", comment->GetText()); - attributes->Set("entry_type", comment->GetEntryType()); + attributes->Set("entry_type", IcingaDB::CommentTypeToString(comment->GetEntryType())); attributes->Set("entry_time", TimestampToMilliseconds(comment->GetEntryTime())); attributes->Set("is_persistent", comment->GetPersistent()); attributes->Set("is_sticky", comment->GetSticky()); @@ -1974,7 +1974,7 @@ void IcingaDB::SendStateChange(const ConfigObject::Ptr& object, const CheckResul "id", HashValue(rawId), "environment_id", m_EnvironmentId, "host_id", GetObjectIdentifier(host), - "state_type", Convert::ToString(type), + "state_type", Checkable::StateTypeToString(type).ToLower(), "soft_state", Convert::ToString(cr ? service ? Convert::ToLong(cr->GetState()) : Convert::ToLong(Host::CalculateState(cr->GetState())) : 99), "hard_state", Convert::ToString(hard_state), "check_attempt", Convert::ToString(checkable->GetCheckAttempt()), @@ -2047,8 +2047,9 @@ void IcingaDB::SendSentNotification( auto usersAmount (users.size()); auto sendTs (TimestampToMilliseconds(sendTime)); + auto notificationTypeStr(GetNotificationTypeByEnum(type)); Array::Ptr rawId = new Array({m_EnvironmentId, notification->GetName()}); - rawId->Add(GetNotificationTypeByEnum(type)); + rawId->Add(notificationTypeStr); rawId->Add(sendTs); auto notificationHistoryId (HashValue(rawId)); @@ -2059,7 +2060,7 @@ void IcingaDB::SendSentNotification( "environment_id", m_EnvironmentId, "notification_id", GetObjectIdentifier(notification), "host_id", GetObjectIdentifier(host), - "type", Convert::ToString(type), + "type", notificationTypeStr, "state", Convert::ToString(cr ? service ? Convert::ToLong(cr->GetState()) : Convert::ToLong(Host::CalculateState(cr->GetState())) : 99), "previous_hard_state", Convert::ToString(cr ? service ? Convert::ToLong(cr->GetPreviousHardState()) : Convert::ToLong(Host::CalculateState(cr->GetPreviousHardState())) : 99), "author", Utility::ValidateUTF8(author), @@ -2300,7 +2301,7 @@ void IcingaDB::SendAddedComment(const Comment::Ptr& comment) "entry_time", Convert::ToString(TimestampToMilliseconds(comment->GetEntryTime())), "author", Utility::ValidateUTF8(comment->GetAuthor()), "comment", Utility::ValidateUTF8(comment->GetText()), - "entry_type", Convert::ToString(comment->GetEntryType()), + "entry_type", IcingaDB::CommentTypeToString(comment->GetEntryType()), "is_persistent", Convert::ToString((unsigned short)comment->GetPersistent()), "is_sticky", Convert::ToString((unsigned short)comment->GetSticky()), "event_id", CalcEventID("comment_add", comment), @@ -2372,7 +2373,7 @@ void IcingaDB::SendRemovedComment(const Comment::Ptr& comment) "entry_time", Convert::ToString(TimestampToMilliseconds(comment->GetEntryTime())), "author", Utility::ValidateUTF8(comment->GetAuthor()), "comment", Utility::ValidateUTF8(comment->GetText()), - "entry_type", Convert::ToString(comment->GetEntryType()), + "entry_type", IcingaDB::CommentTypeToString(comment->GetEntryType()), "is_persistent", Convert::ToString((unsigned short)comment->GetPersistent()), "is_sticky", Convert::ToString((unsigned short)comment->GetSticky()), "event_id", CalcEventID("comment_remove", comment), @@ -2954,7 +2955,7 @@ Dictionary::Ptr IcingaDB::SerializeState(const Checkable::Ptr& checkable) */ attrs->Set("id", id); attrs->Set("environment_id", m_EnvironmentId); - attrs->Set("state_type", checkable->HasBeenChecked() ? checkable->GetStateType() : StateTypeHard); + attrs->Set("state_type", Checkable::StateTypeToString(checkable->HasBeenChecked() ? checkable->GetStateType() : StateTypeHard).ToLower()); // TODO: last_hard/soft_state should be "previous". if (service) { @@ -3017,7 +3018,9 @@ Dictionary::Ptr IcingaDB::SerializeState(const Checkable::Ptr& checkable) attrs->Set("is_reachable", checkable->IsReachable()); attrs->Set("is_flapping", checkable->IsFlapping()); - attrs->Set("is_acknowledged", checkable->GetAcknowledgement()); + attrs->Set("is_acknowledged", checkable->IsAcknowledged()); + attrs->Set("is_sticky_acknowledgement", checkable->GetAcknowledgement() == AcknowledgementSticky); + if (checkable->IsAcknowledged()) { Timestamp entry = 0; Comment::Ptr AckComment; diff --git a/lib/icingadb/icingadb-utility.cpp b/lib/icingadb/icingadb-utility.cpp index 89e5a5031..8fa0e338c 100644 --- a/lib/icingadb/icingadb-utility.cpp +++ b/lib/icingadb/icingadb-utility.cpp @@ -219,6 +219,35 @@ Dictionary::Ptr IcingaDB::SerializeRedundancyGroupState(const Checkable::Ptr& ch }; } +/** + * Converts the given filter to its Redis value representation. + * + * Within the Icinga 2 code base, if the states filter bitsets are set to -1, the filter will match on all states. + * However, since sending -1 to Redis would crash the Icinga DB daemon, as the "states" field is of type uint8, so + * the primary purpose of this function is to make sure that no values outside the valid range of 0-255 are sent to Redis. + * + * @param filter The filter to convert. + */ +int IcingaDB::StateFilterToRedisValue(int filter) +{ + return filter & StateFilterAll; +} + +/** + * Converts the given filter to its Redis value representation. + * + * Within the Icinga 2 code base, if the types filter bitsets are set to -1, the filter will match on all types. + * However, since sending -1 to Redis would crash the Icinga DB daemon, as the "types" field is of type uint16, so + * the primary purpose of this function is to make sure that no values outside the "types" field's valid range are + * sent to Redis. + * + * @param filter The filter to convert. + */ +int IcingaDB::TypeFilterToRedisValue(int filter) +{ + return filter & NotificationTypeAll; +} + const char* IcingaDB::GetNotificationTypeByEnum(NotificationType type) { switch (type) { @@ -240,9 +269,24 @@ const char* IcingaDB::GetNotificationTypeByEnum(NotificationType type) return "flapping_start"; case NotificationFlappingEnd: return "flapping_end"; + default: + VERIFY(!"Invalid notification type."); } +} - VERIFY(!"Invalid notification type."); +/** + * Converts the given comment type to its string representation. + * + * @ingroup icinga + */ +String IcingaDB::CommentTypeToString(CommentType type) +{ + switch (type) { + case CommentUser: return "comment"; + case CommentAcknowledgement: return "ack"; + default: + BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid comment type specified")); + } } static const std::set propertiesBlacklistEmpty; diff --git a/lib/icingadb/icingadb.hpp b/lib/icingadb/icingadb.hpp index af58a977d..33b6414c8 100644 --- a/lib/icingadb/icingadb.hpp +++ b/lib/icingadb/icingadb.hpp @@ -173,7 +173,10 @@ private: static String GetObjectIdentifier(const ConfigObject::Ptr& object); static String CalcEventID(const char* eventType, const ConfigObject::Ptr& object, double eventTime = 0, NotificationType nt = NotificationType(0)); + static int StateFilterToRedisValue(int filter); + static int TypeFilterToRedisValue(int filter); static const char* GetNotificationTypeByEnum(NotificationType type); + static String CommentTypeToString(CommentType type); static Dictionary::Ptr SerializeVars(const Dictionary::Ptr& vars); static Dictionary::Ptr SerializeDependencyEdgeState(const DependencyGroup::Ptr& dependencyGroup, const Dependency::Ptr& dep); static Dictionary::Ptr SerializeRedundancyGroupState(const Checkable::Ptr& child, const DependencyGroup::Ptr& redundancyGroup);