diff --git a/lib/db_ido/userdbobject.cpp b/lib/db_ido/userdbobject.cpp index bb61f4251..5adfd099e 100644 --- a/lib/db_ido/userdbobject.cpp +++ b/lib/db_ido/userdbobject.cpp @@ -53,16 +53,16 @@ Dictionary::Ptr UserDbObject::GetConfigFields(void) const int typeFilter = user->GetTypeFilter(); int stateFilter = user->GetStateFilter(); - fields->Set("notify_service_recovery", (typeFilter & (1 << NotificationRecovery)) != 0); + fields->Set("notify_service_recovery", (typeFilter & NotificationRecovery) != 0); fields->Set("notify_service_warning", (stateFilter & StateFilterWarning) != 0); fields->Set("notify_service_unknown", (stateFilter & StateFilterUnknown) != 0); fields->Set("notify_service_critical", (stateFilter & StateFilterCritical) != 0); - fields->Set("notify_service_flapping", (typeFilter & ((1 << NotificationFlappingStart) | (1 << NotificationFlappingEnd))) != 0); - fields->Set("notify_service_downtime", (typeFilter & ((1 << NotificationDowntimeStart) | (1 << NotificationDowntimeEnd) | (1 << NotificationDowntimeRemoved))) != 0); - fields->Set("notify_host_recovery", (typeFilter & (1 << NotificationRecovery)) != 0); + fields->Set("notify_service_flapping", (typeFilter & (NotificationFlappingStart | NotificationFlappingEnd)) != 0); + fields->Set("notify_service_downtime", (typeFilter & (NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved)) != 0); + fields->Set("notify_host_recovery", (typeFilter & NotificationRecovery) != 0); fields->Set("notify_host_down", (stateFilter & StateFilterDown) != 0); - fields->Set("notify_host_flapping", (typeFilter & ((1 << NotificationFlappingStart) | (1 << NotificationFlappingEnd))) != 0); - fields->Set("notify_host_downtime", (typeFilter & ((1 << NotificationDowntimeStart) | (1 << NotificationDowntimeEnd) | (1 << NotificationDowntimeRemoved))) != 0); + fields->Set("notify_host_flapping", (typeFilter & (NotificationFlappingStart | NotificationFlappingEnd)) != 0); + fields->Set("notify_host_downtime", (typeFilter & (NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved)) != 0); return fields; } diff --git a/lib/icinga/compatutility.cpp b/lib/icinga/compatutility.cpp index 6b62f5981..6166691b0 100644 --- a/lib/icinga/compatutility.cpp +++ b/lib/icinga/compatutility.cpp @@ -109,8 +109,8 @@ int CompatUtility::GetHostNotifyOnDown(const Host::Ptr& host) { unsigned long notification_state_filter = GetCheckableNotificationStateFilter(host); - if (notification_state_filter & (1<& filterMap, int defaultValue) +{ + Value resultTypeFilter; + + if (!typeFilters) + return defaultValue; + + resultTypeFilter = 0; + + ObjectLock olock(typeFilters); + BOOST_FOREACH(const Value& typeFilter, typeFilters) { + if (typeFilter.IsNumber()) { + resultTypeFilter = resultTypeFilter | typeFilter; + continue; + } + + if (!typeFilter.IsString()) + return -1; + + std::map::const_iterator it = filterMap.find(typeFilter); + + if (it == filterMap.end()) + return -1; + + resultTypeFilter = resultTypeFilter | it->second; + } + + return resultTypeFilter; +} + diff --git a/lib/icinga/customvarobject.hpp b/lib/icinga/customvarobject.hpp index 28ad5a02a..710e68f06 100644 --- a/lib/icinga/customvarobject.hpp +++ b/lib/icinga/customvarobject.hpp @@ -41,6 +41,8 @@ public: virtual void ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils) override; }; +I2_ICINGA_API int FilterArrayToInt(const Array::Ptr& typeFilters, const std::map& filterMap, int defaultValue); + } #endif /* CUSTOMVAROBJECT_H */ diff --git a/lib/icinga/dependency.cpp b/lib/icinga/dependency.cpp index 094e29b1b..2369a63a9 100644 --- a/lib/icinga/dependency.cpp +++ b/lib/icinga/dependency.cpp @@ -77,7 +77,7 @@ void Dependency::OnConfigLoaded(void) else defaultFilter = StateFilterOK | StateFilterWarning; - SetStateFilter(FilterArrayToInt(GetStates(), defaultFilter)); + SetStateFilter(FilterArrayToInt(GetStates(), Notification::GetStateFilterMap(), defaultFilter)); } void Dependency::OnAllConfigLoaded(void) @@ -224,7 +224,7 @@ void Dependency::ValidateStates(const Array::Ptr& value, const ValidationUtils& { ObjectImpl::ValidateStates(value, utils); - int sfilter = FilterArrayToInt(value, 0); + int sfilter = FilterArrayToInt(value, Notification::GetStateFilterMap(), 0); if (GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("states"), "State filter is invalid for host dependency.")); diff --git a/lib/icinga/notification.cpp b/lib/icinga/notification.cpp index 98b67676e..06413a4c5 100644 --- a/lib/icinga/notification.cpp +++ b/lib/icinga/notification.cpp @@ -37,6 +37,9 @@ using namespace icinga; REGISTER_TYPE(Notification); INITIALIZE_ONCE(&Notification::StaticInitialize); +std::map Notification::m_StateFilterMap; +std::map Notification::m_TypeFilterMap; + boost::signals2::signal Notification::OnNextNotificationChanged; String NotificationNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const @@ -79,30 +82,47 @@ Dictionary::Ptr NotificationNameComposer::ParseName(const String& name) const void Notification::StaticInitialize(void) { - ScriptGlobal::Set("OK", StateFilterOK); - ScriptGlobal::Set("Warning", StateFilterWarning); - ScriptGlobal::Set("Critical", StateFilterCritical); - ScriptGlobal::Set("Unknown", StateFilterUnknown); - ScriptGlobal::Set("Up", StateFilterUp); - ScriptGlobal::Set("Down", StateFilterDown); + ScriptGlobal::Set("OK", "OK"); + ScriptGlobal::Set("Warning", "Warning"); + ScriptGlobal::Set("Critical", "Critical"); + ScriptGlobal::Set("Unknown", "Unknown"); + ScriptGlobal::Set("Up", "Up"); + ScriptGlobal::Set("Down", "Down"); - ScriptGlobal::Set("DowntimeStart", 1 << NotificationDowntimeStart); - ScriptGlobal::Set("DowntimeEnd", 1 << NotificationDowntimeEnd); - ScriptGlobal::Set("DowntimeRemoved", 1 << NotificationDowntimeRemoved); - ScriptGlobal::Set("Custom", 1 << NotificationCustom); - ScriptGlobal::Set("Acknowledgement", 1 << NotificationAcknowledgement); - ScriptGlobal::Set("Problem", 1 << NotificationProblem); - ScriptGlobal::Set("Recovery", 1 << NotificationRecovery); - ScriptGlobal::Set("FlappingStart", 1 << NotificationFlappingStart); - ScriptGlobal::Set("FlappingEnd", 1 << NotificationFlappingEnd); + ScriptGlobal::Set("DowntimeStart", "DowntimeStart"); + ScriptGlobal::Set("DowntimeEnd", "DowntimeEnd"); + ScriptGlobal::Set("DowntimeRemoved", "DowntimeRemoved"); + ScriptGlobal::Set("Custom", "Custom"); + ScriptGlobal::Set("Acknowledgement", "Acknowledgement"); + ScriptGlobal::Set("Problem", "Problem"); + ScriptGlobal::Set("Recovery", "Recovery"); + ScriptGlobal::Set("FlappingStart", "FlappingStart"); + ScriptGlobal::Set("FlappingEnd", "FlappingEnd"); + + m_StateFilterMap["OK"] = StateFilterOK; + m_StateFilterMap["Warning"] = StateFilterWarning; + m_StateFilterMap["Critical"] = StateFilterCritical; + m_StateFilterMap["Unknown"] = StateFilterUnknown; + m_StateFilterMap["Up"] = StateFilterUp; + m_StateFilterMap["Down"] = StateFilterDown; + + m_TypeFilterMap["DowntimeStart"] = NotificationDowntimeStart; + m_TypeFilterMap["DowntimeEnd"] = NotificationDowntimeEnd; + m_TypeFilterMap["DowntimeRemoved"] = NotificationDowntimeRemoved; + m_TypeFilterMap["Custom"] = NotificationCustom; + m_TypeFilterMap["Acknowledgement"] = NotificationAcknowledgement; + m_TypeFilterMap["Problem"] = NotificationProblem; + m_TypeFilterMap["Recovery"] = NotificationRecovery; + m_TypeFilterMap["FlappingStart"] = NotificationFlappingStart; + m_TypeFilterMap["FlappingEnd"] = NotificationFlappingEnd; } void Notification::OnConfigLoaded(void) { ObjectImpl::OnConfigLoaded(); - SetTypeFilter(FilterArrayToInt(GetTypes(), ~0)); - SetStateFilter(FilterArrayToInt(GetStates(), ~0)); + SetTypeFilter(FilterArrayToInt(GetTypes(), GetTypeFilterMap(), ~0)); + SetStateFilter(FilterArrayToInt(GetStates(), GetStateFilterMap(), ~0)); } void Notification::OnAllConfigLoaded(void) @@ -280,18 +300,18 @@ void Notification::BeginExecuteNotification(NotificationType type, const CheckRe } } - unsigned long ftype = 1 << type; + unsigned long ftype = type; Log(LogDebug, "Notification") << "Type '" << NotificationTypeToStringInternal(type) - << "', TypeFilter " << NotificationFilterToString(GetTypeFilter()) + << "', TypeFilter: " << NotificationFilterToString(GetTypeFilter(), GetTypeFilterMap()) << " (FType=" << ftype << ", TypeFilter=" << GetTypeFilter() << ")"; if (!(ftype & GetTypeFilter())) { Log(LogNotice, "Notification") << "Not sending notifications for notification object '" << GetName() << "': type '" - << NotificationTypeToStringInternal(type) << "' does not match type filter '" - << NotificationFilterToString(GetTypeFilter()) << "."; + << NotificationTypeToStringInternal(type) << "' does not match type filter: " + << NotificationFilterToString(GetTypeFilter(), GetTypeFilterMap()) << "."; return; } @@ -313,13 +333,13 @@ void Notification::BeginExecuteNotification(NotificationType type, const CheckRe } Log(LogDebug, "Notification") - << "State '" << stateStr << "', StateFilter " << NotificationFilterToString(GetStateFilter()) + << "State '" << stateStr << "', StateFilter: " << NotificationFilterToString(GetStateFilter(), GetStateFilterMap()) << " (FState=" << fstate << ", StateFilter=" << GetStateFilter() << ")"; if (!(fstate & GetStateFilter())) { Log(LogNotice, "Notification") << "Not sending notifications for notification object '" << GetName() << "': state '" << stateStr - << "' does not match state filter " << NotificationFilterToString(GetStateFilter()) << "."; + << "' does not match state filter: " << NotificationFilterToString(GetStateFilter(), GetStateFilterMap()) << "."; return; } } @@ -412,11 +432,11 @@ bool Notification::CheckNotificationUserFilters(NotificationType type, const Use return false; } - unsigned long ftype = 1 << type; + unsigned long ftype = type; Log(LogDebug, "Notification") << "User notification, Type '" << NotificationTypeToStringInternal(type) - << "', TypeFilter " << NotificationFilterToString(user->GetTypeFilter()) + << "', TypeFilter: " << NotificationFilterToString(user->GetTypeFilter(), GetTypeFilterMap()) << " (FType=" << ftype << ", TypeFilter=" << GetTypeFilter() << ")"; @@ -424,8 +444,8 @@ bool Notification::CheckNotificationUserFilters(NotificationType type, const Use Log(LogNotice, "Notification") << "Not sending notifications for notification object '" << GetName() << " and user '" << user->GetName() << "': type '" - << NotificationTypeToStringInternal(type) << "' does not match type filter " - << NotificationFilterToString(user->GetTypeFilter()) << "."; + << NotificationTypeToStringInternal(type) << "' does not match type filter: " + << NotificationFilterToString(user->GetTypeFilter(), GetTypeFilterMap()) << "."; return false; } @@ -448,15 +468,15 @@ bool Notification::CheckNotificationUserFilters(NotificationType type, const Use } Log(LogDebug, "Notification") - << "User notification, State '" << stateStr << "', StateFilter " - << NotificationFilterToString(user->GetStateFilter()) + << "User notification, State '" << stateStr << "', StateFilter: " + << NotificationFilterToString(user->GetStateFilter(), GetStateFilterMap()) << " (FState=" << fstate << ", StateFilter=" << user->GetStateFilter() << ")"; if (!(fstate & user->GetStateFilter())) { Log(LogNotice, "Notification") << "Not sending notifications for notification object '" << GetName() << " and user '" << user->GetName() << "': state '" << stateStr - << "' does not match state filter " << NotificationFilterToString(user->GetStateFilter()) << "."; + << "' does not match state filter: " << NotificationFilterToString(user->GetStateFilter(), GetStateFilterMap()) << "."; return false; } } @@ -520,62 +540,17 @@ int icinga::HostStateToFilter(HostState state) } } -int icinga::FilterArrayToInt(const Array::Ptr& typeFilters, int defaultValue) +String Notification::NotificationFilterToString(int filter, const std::map& filterMap) { - Value resultTypeFilter; + std::vector sFilters; - if (!typeFilters) - return defaultValue; - - resultTypeFilter = 0; - - ObjectLock olock(typeFilters); - BOOST_FOREACH(const Value& typeFilter, typeFilters) { - resultTypeFilter = resultTypeFilter | typeFilter; + typedef std::pair kv_pair; + BOOST_FOREACH(const kv_pair& kv, filterMap) { + if (filter & kv.second) + sFilters.push_back(kv.first); } - return resultTypeFilter; -} - -std::vector icinga::FilterIntToArray(int iFilter) -{ - std::vector filter; - - if (iFilter & StateFilterOK) - filter.push_back("OK"); - if (iFilter & StateFilterWarning) - filter.push_back("Warning"); - if (iFilter & StateFilterUnknown) - filter.push_back("Unknown"); - if (iFilter & StateFilterUp) - filter.push_back("Up"); - if (iFilter & StateFilterDown) - filter.push_back("Down"); - if (iFilter & NotificationDowntimeStart) - filter.push_back("DowntimeStart"); - if (iFilter & NotificationDowntimeEnd) - filter.push_back("DowntimeEnd"); - if (iFilter & NotificationDowntimeRemoved) - filter.push_back("DowntimeRemoved"); - if (iFilter & NotificationCustom) - filter.push_back("Custom"); - if (iFilter & NotificationAcknowledgement) - filter.push_back("Acknowledgement"); - if (iFilter & NotificationProblem) - filter.push_back("Problem"); - if (iFilter & NotificationRecovery) - filter.push_back("Recovery"); - if (iFilter & NotificationFlappingStart) - filter.push_back("FlappingStart"); - if (iFilter & NotificationFlappingEnd) - filter.push_back("FlappingEnd"); - - return filter; -} - -String Notification::NotificationFilterToString(int filter) -{ - return Utility::NaturalJoin(FilterIntToArray(filter)); + return Utility::NaturalJoin(sFilters); } /* internal for logging */ @@ -651,12 +626,12 @@ void Notification::ValidateStates(const Array::Ptr& value, const ValidationUtils { ObjectImpl::ValidateStates(value, utils); - int sfilter = FilterArrayToInt(value, 0); + int filter = FilterArrayToInt(value, GetStateFilterMap(), 0); - if (GetServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) + if (GetServiceName().IsEmpty() && (filter == -1 || (filter & ~(StateFilterUp | StateFilterDown)) != 0)) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("states"), "State filter is invalid.")); - if (!GetServiceName().IsEmpty() && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) + if (!GetServiceName().IsEmpty() && (filter == -1 || (filter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0)) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("types"), "State filter is invalid.")); } @@ -664,11 +639,11 @@ void Notification::ValidateTypes(const Array::Ptr& value, const ValidationUtils& { ObjectImpl::ValidateTypes(value, utils); - int tfilter = FilterArrayToInt(value, 0); + int filter = FilterArrayToInt(value, GetTypeFilterMap(), 0); - if ((tfilter & ~(1 << NotificationDowntimeStart | 1 << NotificationDowntimeEnd | 1 << NotificationDowntimeRemoved | - 1 << NotificationCustom | 1 << NotificationAcknowledgement | 1 << NotificationProblem | 1 << NotificationRecovery | - 1 << NotificationFlappingStart | 1 << NotificationFlappingEnd)) != 0) + if (filter == -1 || (filter & ~(NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved | + NotificationCustom | NotificationAcknowledgement | NotificationProblem | NotificationRecovery | + NotificationFlappingStart | NotificationFlappingEnd)) != 0) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("types"), "Type filter is invalid.")); } @@ -677,3 +652,12 @@ Endpoint::Ptr Notification::GetCommandEndpoint(void) const return Endpoint::GetByName(GetCommandEndpointRaw()); } +const std::map& Notification::GetStateFilterMap(void) +{ + return m_StateFilterMap; +} + +const std::map& Notification::GetTypeFilterMap(void) +{ + return m_TypeFilterMap; +} diff --git a/lib/icinga/notification.hpp b/lib/icinga/notification.hpp index 73b30a127..37145c8fa 100644 --- a/lib/icinga/notification.hpp +++ b/lib/icinga/notification.hpp @@ -55,15 +55,15 @@ enum NotificationFilter */ enum NotificationType { - NotificationDowntimeStart = 0, - NotificationDowntimeEnd = 1, - NotificationDowntimeRemoved = 2, - NotificationCustom = 3, - NotificationAcknowledgement = 4, - NotificationProblem = 5, - NotificationRecovery = 6, - NotificationFlappingStart = 7 , - NotificationFlappingEnd = 8, + NotificationDowntimeStart = 1, + NotificationDowntimeEnd = 2, + NotificationDowntimeRemoved = 4, + NotificationCustom = 8, + NotificationAcknowledgement = 16, + NotificationProblem = 32, + NotificationRecovery = 64, + NotificationFlappingStart = 128, + NotificationFlappingEnd = 256 }; class NotificationCommand; @@ -101,7 +101,7 @@ public: Endpoint::Ptr GetCommandEndpoint(void) const; static String NotificationTypeToString(NotificationType type); - static String NotificationFilterToString(int filter); + static String NotificationFilterToString(int filter, const std::map& filterMap); static boost::signals2::signal OnNextNotificationChanged; @@ -115,6 +115,9 @@ public: static void EvaluateApplyRules(const intrusive_ptr& host); static void EvaluateApplyRules(const intrusive_ptr& service); + static const std::map& GetStateFilterMap(void); + static const std::map& GetTypeFilterMap(void); + protected: virtual void OnConfigLoaded(void) override; virtual void OnAllConfigLoaded(void) override; @@ -132,12 +135,13 @@ private: static String NotificationTypeToStringInternal(NotificationType type); static String NotificationServiceStateToString(ServiceState state); static String NotificationHostStateToString(HostState state); + + static std::map m_StateFilterMap; + static std::map m_TypeFilterMap; }; I2_ICINGA_API int ServiceStateToFilter(ServiceState state); I2_ICINGA_API int HostStateToFilter(HostState state); -I2_ICINGA_API int FilterArrayToInt(const Array::Ptr& typeFilters, int defaultValue); -I2_ICINGA_API std::vector FilterIntToArray(int iFilter); } diff --git a/lib/icinga/notification.ti b/lib/icinga/notification.ti index f7ef8639c..2f39b3630 100644 --- a/lib/icinga/notification.ti +++ b/lib/icinga/notification.ti @@ -56,9 +56,9 @@ class Notification : CustomVarObject < NotificationNameComposer [config, protected] array(name(User)) users (UsersRaw); [config, protected] array(name(UserGroup)) user_groups (UserGroupsRaw); [config] Dictionary::Ptr times; - [config] array(double) types; + [config] array(Value) types; int type_filter_real (TypeFilter); - [config] array(double) states; + [config] array(Value) states; int state_filter_real (StateFilter); [config, protected, required, navigation(host)] name(Host) host_name { navigate {{{ diff --git a/lib/icinga/user.cpp b/lib/icinga/user.cpp index eb232fc84..e99513531 100644 --- a/lib/icinga/user.cpp +++ b/lib/icinga/user.cpp @@ -34,8 +34,8 @@ void User::OnConfigLoaded(void) { ObjectImpl::OnConfigLoaded(); - SetTypeFilter(FilterArrayToInt(GetTypes(), ~0)); - SetStateFilter(FilterArrayToInt(GetStates(), ~0)); + SetTypeFilter(FilterArrayToInt(GetTypes(), Notification::GetTypeFilterMap(), ~0)); + SetStateFilter(FilterArrayToInt(GetStates(), Notification::GetStateFilterMap(), ~0)); } void User::OnAllConfigLoaded(void) @@ -102,22 +102,20 @@ void User::ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) { ObjectImpl::ValidateStates(value, utils); - int sfilter = FilterArrayToInt(value, 0); + int filter = FilterArrayToInt(value, Notification::GetStateFilterMap(), 0); - if ((sfilter & ~(StateFilterUp | StateFilterDown | StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) { + if (filter == -1 || (filter & ~(StateFilterUp | StateFilterDown | StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("states"), "State filter is invalid.")); - } } void User::ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) { ObjectImpl::ValidateTypes(value, utils); - int tfilter = FilterArrayToInt(value, 0); + int filter = FilterArrayToInt(value, Notification::GetTypeFilterMap(), 0); - if ((tfilter & ~(1 << NotificationDowntimeStart | 1 << NotificationDowntimeEnd | 1 << NotificationDowntimeRemoved | - 1 << NotificationCustom | 1 << NotificationAcknowledgement | 1 << NotificationProblem | 1 << NotificationRecovery | - 1 << NotificationFlappingStart | 1 << NotificationFlappingEnd)) != 0) { + if (filter == -1 || (filter & ~(NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved | + NotificationCustom | NotificationAcknowledgement | NotificationProblem | NotificationRecovery | + NotificationFlappingStart | NotificationFlappingEnd)) != 0) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("types"), "Type filter is invalid.")); - } } diff --git a/lib/icinga/user.ti b/lib/icinga/user.ti index e7028ea78..14faee10a 100644 --- a/lib/icinga/user.ti +++ b/lib/icinga/user.ti @@ -44,9 +44,9 @@ class User : CustomVarObject }}} }; - [config] array(double) types; + [config] array(Value) types; int type_filter_real (TypeFilter); - [config] array(double) states; + [config] array(Value) states; int state_filter_real (StateFilter); [config] String email;