From 0078e00c1366a80a5fe9adb0b2e7b9e19aba67af Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sun, 16 Nov 2014 16:20:39 +0100 Subject: [PATCH] Refactor apply/object rules fixes #7700 --- lib/config/applyrule.cpp | 102 +++++++++++------------- lib/config/applyrule.hpp | 15 ++-- lib/config/configitem.cpp | 106 +++++++++++++++---------- lib/config/configitem.hpp | 17 ++-- lib/config/configitembuilder.cpp | 10 ++- lib/config/configitembuilder.hpp | 2 + lib/config/expression.cpp | 9 +-- lib/config/objectrule.cpp | 64 +-------------- lib/config/objectrule.hpp | 29 ++----- lib/icinga/dependency-apply.cpp | 89 ++++++++------------- lib/icinga/dependency.hpp | 11 ++- lib/icinga/host.cpp | 9 +++ lib/icinga/hostgroup.cpp | 45 +++++------ lib/icinga/hostgroup.hpp | 8 +- lib/icinga/notification-apply.cpp | 90 ++++++++------------- lib/icinga/notification.hpp | 11 ++- lib/icinga/scheduleddowntime-apply.cpp | 89 ++++++++------------- lib/icinga/scheduleddowntime.hpp | 11 ++- lib/icinga/service-apply.cpp | 35 +++----- lib/icinga/service.cpp | 6 ++ lib/icinga/service.hpp | 8 +- lib/icinga/servicegroup.cpp | 45 +++++------ lib/icinga/servicegroup.hpp | 8 +- lib/icinga/user.cpp | 3 + lib/icinga/usergroup.cpp | 45 +++++------ lib/icinga/usergroup.hpp | 8 +- 26 files changed, 379 insertions(+), 496 deletions(-) diff --git a/lib/config/applyrule.cpp b/lib/config/applyrule.cpp index f542cb63a..4e192cd57 100644 --- a/lib/config/applyrule.cpp +++ b/lib/config/applyrule.cpp @@ -25,13 +25,13 @@ using namespace icinga; ApplyRule::RuleMap ApplyRule::m_Rules; -ApplyRule::CallbackMap ApplyRule::m_Callbacks; +ApplyRule::TypeMap ApplyRule::m_Types; ApplyRule::ApplyRule(const String& targetType, const String& name, const boost::shared_ptr& expression, const boost::shared_ptr& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr& fterm, const DebugInfo& di, const Object::Ptr& scope) : m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_FKVar(fkvar), - m_FVVar(fvvar), m_FTerm(fterm), m_DebugInfo(di), m_Scope(scope) + m_FVVar(fvvar), m_FTerm(fterm), m_DebugInfo(di), m_Scope(scope), m_HasMatches(false) { } String ApplyRule::GetTargetType(void) const @@ -91,69 +91,27 @@ bool ApplyRule::EvaluateFilter(const Object::Ptr& scope) const return m_Filter->Evaluate(scope).ToBool(); } -void ApplyRule::EvaluateRules(bool clear) +void ApplyRule::RegisterType(const String& sourceType, const std::vector& targetTypes) { - std::set completedTypes; - - while (completedTypes.size() < m_Callbacks.size()) { - std::pair > > kv; - BOOST_FOREACH(kv, m_Callbacks) { - const String& sourceType = kv.first; - - if (completedTypes.find(sourceType) != completedTypes.end()) - continue; - - const Callback& callback = kv.second.first; - const std::vector& targetTypes = kv.second.second; - - bool cont = false; - - BOOST_FOREACH(const String& targetType, targetTypes) { - if (IsValidSourceType(targetType) && completedTypes.find(targetType) == completedTypes.end()) { - cont = true; - break; - } - } - - if (cont) - continue; - - completedTypes.insert(sourceType); - - RuleMap::const_iterator it = m_Rules.find(kv.first); - - if (it == m_Rules.end()) - continue; - - callback(it->second); - } - } - - if (clear) - m_Rules.clear(); -} - -void ApplyRule::RegisterType(const String& sourceType, const std::vector& targetTypes, const ApplyRule::Callback& callback) -{ - m_Callbacks[sourceType] = make_pair(callback, targetTypes); + m_Types[sourceType] = targetTypes; } bool ApplyRule::IsValidSourceType(const String& sourceType) { - return m_Callbacks.find(sourceType) != m_Callbacks.end(); + return m_Types.find(sourceType) != m_Types.end(); } bool ApplyRule::IsValidTargetType(const String& sourceType, const String& targetType) { - CallbackMap::const_iterator it = m_Callbacks.find(sourceType); + TypeMap::const_iterator it = m_Types.find(sourceType); - if (it == m_Callbacks.end()) + if (it == m_Types.end()) return false; - if (it->second.second.size() == 1 && targetType == "") + if (it->second.size() == 1 && targetType == "") return true; - BOOST_FOREACH(const String& type, it->second.second) { + BOOST_FOREACH(const String& type, it->second) { if (type == targetType) return true; } @@ -163,11 +121,47 @@ bool ApplyRule::IsValidTargetType(const String& sourceType, const String& target std::vector ApplyRule::GetTargetTypes(const String& sourceType) { - CallbackMap::const_iterator it = m_Callbacks.find(sourceType); + TypeMap::const_iterator it = m_Types.find(sourceType); - if (it == m_Callbacks.end()) + if (it == m_Types.end()) return std::vector(); - return it->second.second; + return it->second; +} + +void ApplyRule::AddMatch(void) +{ + m_HasMatches = true; +} + +bool ApplyRule::HasMatches(void) const +{ + return m_HasMatches; +} + +std::vector& ApplyRule::GetRules(const String& type) +{ + RuleMap::iterator it = m_Rules.find(type); + if (it == m_Rules.end()) { + static std::vector emptyList; + return emptyList; + } + return it->second; +} + +void ApplyRule::CheckMatches(void) +{ + BOOST_FOREACH(const RuleMap::value_type& kv, m_Rules) { + BOOST_FOREACH(const ApplyRule& rule, kv.second) { + if (!rule.HasMatches()) + Log(LogWarning, "ApplyRule") + << "Apply rule '" + rule.GetName() + "' for type '" + kv.first + "' does not match anywhere!"; + } + } +} + +void ApplyRule::DiscardRules(void) +{ + m_Rules.clear(); } diff --git a/lib/config/applyrule.hpp b/lib/config/applyrule.hpp index 015556672..b85357aa8 100644 --- a/lib/config/applyrule.hpp +++ b/lib/config/applyrule.hpp @@ -34,8 +34,7 @@ namespace icinga class I2_CONFIG_API ApplyRule { public: - typedef boost::function& rules)> Callback; - typedef std::map > > CallbackMap; + typedef std::map > TypeMap; typedef std::map > RuleMap; String GetTargetType(void) const; @@ -47,18 +46,23 @@ public: boost::shared_ptr GetFTerm(void) const; DebugInfo GetDebugInfo(void) const; Object::Ptr GetScope(void) const; + void AddMatch(void); + bool HasMatches(void) const; bool EvaluateFilter(const Object::Ptr& scope) const; static void AddRule(const String& sourceType, const String& targetType, const String& name, const boost::shared_ptr& expression, const boost::shared_ptr& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr& fterm, const DebugInfo& di, const Object::Ptr& scope); - static void EvaluateRules(bool clear); + static std::vector& GetRules(const String& type); - static void RegisterType(const String& sourceType, const std::vector& targetTypes, const ApplyRule::Callback& callback); + static void RegisterType(const String& sourceType, const std::vector& targetTypes); static bool IsValidSourceType(const String& sourceType); static bool IsValidTargetType(const String& sourceType, const String& targetType); static std::vector GetTargetTypes(const String& sourceType); + static void CheckMatches(void); + static void DiscardRules(void); + private: String m_TargetType; String m_Name; @@ -69,8 +73,9 @@ private: boost::shared_ptr m_FTerm; DebugInfo m_DebugInfo; Object::Ptr m_Scope; + bool m_HasMatches; - static CallbackMap m_Callbacks; + static TypeMap m_Types; static RuleMap m_Rules; ApplyRule(const String& targetType, const String& name, const boost::shared_ptr& expression, diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 00beca8bf..0d920eb1a 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -42,7 +42,7 @@ using namespace icinga; boost::mutex ConfigItem::m_Mutex; -ConfigItem::ItemMap ConfigItem::m_Items; +ConfigItem::TypeMap ConfigItem::m_Items; ConfigItem::ItemList ConfigItem::m_UnnamedItems; /** @@ -57,11 +57,12 @@ ConfigItem::ItemList ConfigItem::m_UnnamedItems; */ ConfigItem::ConfigItem(const String& type, const String& name, bool abstract, const boost::shared_ptr& exprl, + const boost::shared_ptr& filter, const DebugInfo& debuginfo, const Object::Ptr& scope, const String& zone) : m_Type(type), m_Name(name), m_Abstract(abstract), - m_Expression(exprl), m_DebugInfo(debuginfo), - m_Scope(scope), m_Zone(zone) + m_Expression(exprl), m_Filter(filter), + m_DebugInfo(debuginfo), m_Scope(scope), m_Zone(zone) { } @@ -120,6 +121,16 @@ boost::shared_ptr ConfigItem::GetExpression(void) const return m_Expression; } +/** +* Retrieves the object filter for the configuration item. +* +* @returns The filter expression. +*/ +boost::shared_ptr ConfigItem::GetFilter(void) const +{ + return m_Filter; +} + /** * Commits the configuration item by creating a DynamicObject * object. @@ -150,7 +161,6 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard) Dictionary::Ptr locals = new Dictionary(); locals->Set("__parent", m_Scope); - m_Scope.reset(); dobj->SetParentScope(locals); locals.reset(); @@ -238,10 +248,8 @@ void ConfigItem::Register(void) boost::mutex::scoped_lock lock(m_Mutex); m_UnnamedItems.push_back(this); } else { - std::pair key = std::make_pair(m_Type, m_Name); - boost::mutex::scoped_lock lock(m_Mutex); - m_Items[key] = this; + m_Items[m_Type][m_Name] = this; } } @@ -254,57 +262,61 @@ void ConfigItem::Register(void) */ ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name) { - std::pair key = std::make_pair(type, name); - ConfigItem::ItemMap::iterator it; - { boost::mutex::scoped_lock lock(m_Mutex); - it = m_Items.find(key); - } + ConfigItem::TypeMap::const_iterator it = m_Items.find(type); + + if (it == m_Items.end()) + return ConfigItem::Ptr(); + + ConfigItem::ItemMap::const_iterator it2 = it->second.find(name); - if (it != m_Items.end()) - return it->second; + if (it2 == it->second.end()) + return ConfigItem::Ptr(); - return ConfigItem::Ptr(); + return it2->second; + } } -bool ConfigItem::CommitNewItems(void) +bool ConfigItem::CommitNewItems(ParallelWorkQueue& upq) { - std::vector items; + typedef std::pair ItemPair; + std::vector items; do { - ParallelWorkQueue upq; - items.clear(); { boost::mutex::scoped_lock lock(m_Mutex); - BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) { - if (!kv.second->m_Abstract && !kv.second->m_Object) { - upq.Enqueue(boost::bind(&ConfigItem::Commit, kv.second, false)); - items.push_back(kv.second); + BOOST_FOREACH(const TypeMap::value_type& kv, m_Items) { + BOOST_FOREACH(const ItemMap::value_type& kv2, kv.second) + { + if (!kv2.second->m_Abstract && !kv2.second->m_Object) + items.push_back(std::make_pair(kv2.second, false)); } } BOOST_FOREACH(const ConfigItem::Ptr& item, m_UnnamedItems) { - if (!item->m_Abstract && !item->m_Object) { - upq.Enqueue(boost::bind(&ConfigItem::Commit, item, true)); - items.push_back(item); - } + if (!item->m_Abstract && !item->m_Object) + items.push_back(std::make_pair(item, true)); } m_UnnamedItems.clear(); } + BOOST_FOREACH(const ItemPair& ip, items) { + upq.Enqueue(boost::bind(&ConfigItem::Commit, ip.first, ip.second)); + } + upq.Join(); if (ConfigCompilerContext::GetInstance()->HasErrors()) return false; - BOOST_FOREACH(const ConfigItem::Ptr& item, items) { - upq.Enqueue(boost::bind(&DynamicObject::OnConfigLoaded, item->m_Object)); + BOOST_FOREACH(const ItemPair& ip, items) { + upq.Enqueue(boost::bind(&DynamicObject::OnConfigLoaded, ip.first->m_Object)); } upq.Join(); @@ -315,25 +327,18 @@ bool ConfigItem::CommitNewItems(void) bool ConfigItem::ValidateItems(void) { + ParallelWorkQueue upq; + if (ConfigCompilerContext::GetInstance()->HasErrors()) return false; Log(LogInformation, "ConfigItem", "Committing config items"); - if (!CommitNewItems()) + if (!CommitNewItems(upq)) return false; - Log(LogInformation, "ConfigItem", "Evaluating 'object' rules (step 1)..."); - ObjectRule::EvaluateRules(false); - - Log(LogInformation, "ConfigItem", "Evaluating 'apply' rules..."); - ApplyRule::EvaluateRules(true); - - if (!CommitNewItems()) - return false; - - Log(LogInformation, "ConfigItem", "Evaluating 'object' rules (step 2)..."); - ObjectRule::EvaluateRules(true); + ApplyRule::CheckMatches(); + ApplyRule::DiscardRules(); ConfigItem::DiscardItems(); ConfigType::DiscardTypes(); @@ -400,3 +405,22 @@ void ConfigItem::DiscardItems(void) m_Items.clear(); } + +std::vector ConfigItem::GetItems(const String& type) +{ + std::vector items; + + boost::mutex::scoped_lock lock(m_Mutex); + + TypeMap::const_iterator it = m_Items.find(type); + + if (it == m_Items.end()) + return items; + + BOOST_FOREACH(const ItemMap::value_type& kv, it->second) + { + items.push_back(kv.second); + } + + return items; +} diff --git a/lib/config/configitem.hpp b/lib/config/configitem.hpp index 390f8ce72..f79c066bc 100644 --- a/lib/config/configitem.hpp +++ b/lib/config/configitem.hpp @@ -23,6 +23,7 @@ #include "config/i2-config.hpp" #include "config/expression.hpp" #include "base/dynamicobject.hpp" +#include "base/workqueue.hpp" namespace icinga { @@ -38,7 +39,9 @@ public: DECLARE_PTR_TYPEDEFS(ConfigItem); ConfigItem(const String& type, const String& name, bool abstract, - const boost::shared_ptr& exprl, const DebugInfo& debuginfo, + const boost::shared_ptr& exprl, + const boost::shared_ptr& filter, + const DebugInfo& debuginfo, const Object::Ptr& scope, const String& zone); String GetType(void) const; @@ -48,12 +51,12 @@ public: std::vector GetParents(void) const; boost::shared_ptr GetExpression(void) const; + boost::shared_ptr GetFilter(void) const; DynamicObject::Ptr Commit(bool discard = true); void Register(void); DebugInfo GetDebugInfo(void) const; - Object::Ptr GetScope(void) const; String GetZone(void) const; @@ -65,12 +68,15 @@ public: static bool ActivateItems(void); static void DiscardItems(void); + static std::vector GetItems(const String& type); + private: String m_Type; /**< The object type. */ String m_Name; /**< The name. */ bool m_Abstract; /**< Whether this is a template. */ boost::shared_ptr m_Expression; + boost::shared_ptr m_Filter; DebugInfo m_DebugInfo; /**< Debug information. */ Object::Ptr m_Scope; /**< variable scope. */ String m_Zone; /**< The zone. */ @@ -79,8 +85,9 @@ private: static boost::mutex m_Mutex; - typedef std::map, ConfigItem::Ptr> ItemMap; - static ItemMap m_Items; /**< All registered configuration items. */ + typedef std::map ItemMap; + typedef std::map TypeMap; + static TypeMap m_Items; /**< All registered configuration items. */ typedef std::vector ItemList; static ItemList m_UnnamedItems; @@ -88,7 +95,7 @@ private: static ConfigItem::Ptr GetObjectUnlocked(const String& type, const String& name); - static bool CommitNewItems(void); + static bool CommitNewItems(ParallelWorkQueue& upq); }; } diff --git a/lib/config/configitembuilder.cpp b/lib/config/configitembuilder.cpp index 994a9dac2..89d016801 100644 --- a/lib/config/configitembuilder.cpp +++ b/lib/config/configitembuilder.cpp @@ -21,6 +21,7 @@ #include "base/dynamictype.hpp" #include #include +#include using namespace icinga; @@ -69,6 +70,11 @@ void ConfigItemBuilder::AddExpression(Expression *expr) m_Expressions.push_back(expr); } +void ConfigItemBuilder::SetFilter(const boost::shared_ptr& filter) +{ + m_Filter = filter; +} + ConfigItem::Ptr ConfigItemBuilder::Compile(void) { if (m_Type.IsEmpty()) { @@ -104,10 +110,10 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void) dexpr->MakeInline(); exprs.push_back(dexpr); - DictExpression *exprl = new DictExpression(exprs, m_DebugInfo); + boost::shared_ptr exprl = boost::make_shared(exprs, m_DebugInfo); exprl->MakeInline(); - return new ConfigItem(m_Type, m_Name, m_Abstract, boost::shared_ptr(exprl), + return new ConfigItem(m_Type, m_Name, m_Abstract, exprl, m_Filter, m_DebugInfo, m_Scope, m_Zone); } diff --git a/lib/config/configitembuilder.hpp b/lib/config/configitembuilder.hpp index b9795c6cc..d44007ff8 100644 --- a/lib/config/configitembuilder.hpp +++ b/lib/config/configitembuilder.hpp @@ -49,6 +49,7 @@ public: void SetZone(const String& zone); void AddExpression(Expression *expr); + void SetFilter(const boost::shared_ptr& filter); ConfigItem::Ptr Compile(void); @@ -57,6 +58,7 @@ private: String m_Name; /**< The name. */ bool m_Abstract; /**< Whether the item is abstract. */ std::vector m_Expressions; /**< Expressions for this item. */ + boost::shared_ptr m_Filter; /**< Filter expression. */ DebugInfo m_DebugInfo; /**< Debug information. */ Object::Ptr m_Scope; /**< variable scope. */ String m_Zone; /**< The zone. */ diff --git a/lib/config/expression.cpp b/lib/config/expression.cpp index f37e353f6..5bc4ecc39 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -46,10 +46,10 @@ Value Expression::Evaluate(const Object::Ptr& context, DebugHint *dhint) const { try { #ifdef _DEBUG - std::ostringstream msgbuf; +/* std::ostringstream msgbuf; ShowCodeFragment(msgbuf, GetDebugInfo(), false); Log(LogDebug, "Expression") - << "Executing:\n" << msgbuf.str(); + << "Executing:\n" << msgbuf.str();*/ #endif /* _DEBUG */ return DoEvaluate(context, dhint); @@ -508,10 +508,9 @@ Value ObjectExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) item->SetAbstract(m_Abstract); item->SetScope(context); item->SetZone(m_Zone); - item->Compile()->Register(); + item->SetFilter(m_Filter); - if (m_Filter) - ObjectRule::AddRule(m_Type, name, m_Filter, m_DebugInfo, context); + item->Compile()->Register(); return Empty; } diff --git a/lib/config/objectrule.cpp b/lib/config/objectrule.cpp index 37818cb41..26975d19c 100644 --- a/lib/config/objectrule.cpp +++ b/lib/config/objectrule.cpp @@ -23,70 +23,14 @@ using namespace icinga; -ObjectRule::RuleMap ObjectRule::m_Rules; -ObjectRule::CallbackMap ObjectRule::m_Callbacks; +ObjectRule::TypeSet ObjectRule::m_Types; -ObjectRule::ObjectRule(const String& name, const boost::shared_ptr& filter, - const DebugInfo& di, const Object::Ptr& scope) - : m_Name(name), m_Filter(filter), m_DebugInfo(di), m_Scope(scope) -{ } - -String ObjectRule::GetName(void) const -{ - return m_Name; -} - -boost::shared_ptr ObjectRule::GetFilter(void) const -{ - return m_Filter; -} - -DebugInfo ObjectRule::GetDebugInfo(void) const +void ObjectRule::RegisterType(const String& sourceType) { - return m_DebugInfo; -} - -Object::Ptr ObjectRule::GetScope(void) const -{ - return m_Scope; -} - -void ObjectRule::AddRule(const String& sourceType, const String& name, - const boost::shared_ptr& filter, const DebugInfo& di, const Object::Ptr& scope) -{ - m_Rules[sourceType].push_back(ObjectRule(name, filter, di, scope)); -} - -bool ObjectRule::EvaluateFilter(const Object::Ptr& scope) const -{ - return m_Filter->Evaluate(scope).ToBool(); -} - -void ObjectRule::EvaluateRules(bool clear) -{ - std::pair kv; - BOOST_FOREACH(kv, m_Callbacks) { - const Callback& callback = kv.second; - - RuleMap::const_iterator it = m_Rules.find(kv.first); - - if (it == m_Rules.end()) - continue; - - callback(it->second); - } - - if (clear) - m_Rules.clear(); -} - -void ObjectRule::RegisterType(const String& sourceType, const ObjectRule::Callback& callback) -{ - m_Callbacks[sourceType] = callback; + m_Types.insert(sourceType); } bool ObjectRule::IsValidSourceType(const String& sourceType) { - return m_Callbacks.find(sourceType) != m_Callbacks.end(); + return m_Types.find(sourceType) != m_Types.end(); } - diff --git a/lib/config/objectrule.hpp b/lib/config/objectrule.hpp index 42bf19cb3..732aa4858 100644 --- a/lib/config/objectrule.hpp +++ b/lib/config/objectrule.hpp @@ -23,7 +23,7 @@ #include "config/i2-config.hpp" #include "config/expression.hpp" #include "base/debuginfo.hpp" -#include "base/dynamictype.hpp" +#include namespace icinga { @@ -34,34 +34,15 @@ namespace icinga class I2_CONFIG_API ObjectRule { public: - typedef boost::function& rules)> Callback; - typedef std::map CallbackMap; - typedef std::map > RuleMap; + typedef std::set TypeSet; - String GetName(void) const; - boost::shared_ptr GetFilter(void) const; - DebugInfo GetDebugInfo(void) const; - Object::Ptr GetScope(void) const; - - bool EvaluateFilter(const Object::Ptr& scope) const; - - static void AddRule(const String& sourceType, const String& name, - const boost::shared_ptr& filter, const DebugInfo& di, const Object::Ptr& scope); - static void EvaluateRules(bool clear); - - static void RegisterType(const String& sourceType, const ObjectRule::Callback& callback); + static void RegisterType(const String& sourceType); static bool IsValidSourceType(const String& sourceType); private: - String m_Name; - boost::shared_ptr m_Filter; - DebugInfo m_DebugInfo; - Object::Ptr m_Scope; - - static CallbackMap m_Callbacks; - static RuleMap m_Rules; + ObjectRule(void); - ObjectRule(const String& name, const boost::shared_ptr& filter, const DebugInfo& di, const Object::Ptr& scope); + static TypeSet m_Types; }; } diff --git a/lib/icinga/dependency-apply.cpp b/lib/icinga/dependency-apply.cpp index 386861523..e7ffc327e 100644 --- a/lib/icinga/dependency-apply.cpp +++ b/lib/icinga/dependency-apply.cpp @@ -39,10 +39,10 @@ void Dependency::RegisterApplyRuleHandler(void) std::vector targets; targets.push_back("Host"); targets.push_back("Service"); - ApplyRule::RegisterType("Dependency", targets, &Dependency::EvaluateApplyRules); + ApplyRule::RegisterType("Dependency", targets); } -void Dependency::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule) +void Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule) { DebugInfo di = rule.GetDebugInfo(); @@ -77,7 +77,7 @@ void Dependency::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, c } -bool Dependency::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule) +bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule) { DebugInfo di = rule.GetDebugInfo(); @@ -123,7 +123,7 @@ bool Dependency::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const App name += instance; } - EvaluateApplyRuleOneInstance(checkable, name, locals, rule); + EvaluateApplyRuleInstance(checkable, name, locals, rule); } } else if (vinstances.IsObjectType()) { if (rule.GetFVVar().IsEmpty()) @@ -136,68 +136,47 @@ bool Dependency::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const App locals->Set(rule.GetFKVar(), kv.first); locals->Set(rule.GetFVVar(), kv.second); - EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule); + EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule); } } return true; } -void Dependency::EvaluateApplyRule(const ApplyRule& rule) +void Dependency::EvaluateApplyRules(const Host::Ptr& host) { - int apply_count = 0; - - if (rule.GetTargetType() == "Host") { - apply_count = 0; - - BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType()) { - CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); - - try { - if (EvaluateApplyRuleOne(host, rule)) - apply_count++; - } catch (const ConfigError& ex) { - const DebugInfo *di = boost::get_error_info(ex); - ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); - } - } - - if (apply_count == 0) - Log(LogWarning, "Dependency") - << "Apply rule '" << rule.GetName() << "' for host does not match anywhere!"; - - } else if (rule.GetTargetType() == "Service") { - apply_count = 0; - - BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType()) { - CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'"); - - try { - if (EvaluateApplyRuleOne(service, rule)) - apply_count++; - } catch (const ConfigError& ex) { - const DebugInfo *di = boost::get_error_info(ex); - ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); - } + CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); + + BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Dependency")) + { + if (rule.GetTargetType() != "Host") + continue; + + try { + if (EvaluateApplyRule(host, rule)) + rule.AddMatch(); + } catch (const ConfigError& ex) { + const DebugInfo *di = boost::get_error_info(ex); + ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); } - - if (apply_count == 0) - Log(LogWarning, "Dependency") - << "Apply rule '" << rule.GetName() << "' for service does not match anywhere!"; - - } else { - Log(LogWarning, "Dependency") - << "Wrong target type for apply rule '" << rule.GetName() << "'!"; } } -void Dependency::EvaluateApplyRules(const std::vector& rules) +void Dependency::EvaluateApplyRules(const Service::Ptr& service) { - ParallelWorkQueue upq; - - BOOST_FOREACH(const ApplyRule& rule, rules) { - upq.Enqueue(boost::bind(&Dependency::EvaluateApplyRule, boost::cref(rule))); + CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'"); + + BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Dependency")) + { + if (rule.GetTargetType() != "Service") + continue; + + try { + if (EvaluateApplyRule(service, rule)) + rule.AddMatch(); + } catch (const ConfigError& ex) { + const DebugInfo *di = boost::get_error_info(ex); + ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); + } } - - upq.Join(); } diff --git a/lib/icinga/dependency.hpp b/lib/icinga/dependency.hpp index a3d9b8a71..f8aeeccc5 100644 --- a/lib/icinga/dependency.hpp +++ b/lib/icinga/dependency.hpp @@ -28,6 +28,8 @@ namespace icinga { class ApplyRule; +class Host; +class Service; /** * A service dependency.. @@ -51,6 +53,9 @@ public: static void ValidateFilters(const String& location, const Dependency::Ptr& object); + static void EvaluateApplyRules(const intrusive_ptr& host); + static void EvaluateApplyRules(const intrusive_ptr& service); + protected: virtual void OnConfigLoaded(void); virtual void OnStateLoaded(void); @@ -60,10 +65,8 @@ private: Checkable::Ptr m_Parent; Checkable::Ptr m_Child; - static void EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); - static bool EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule); - static void EvaluateApplyRule(const ApplyRule& rule); - static void EvaluateApplyRules(const std::vector& rules); + static void EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); + static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule); }; } diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index 84a61a6b5..e612788d6 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -21,6 +21,9 @@ #include "icinga/service.hpp" #include "icinga/hostgroup.hpp" #include "icinga/pluginutility.hpp" +#include "icinga/scheduleddowntime.hpp" +#include "config/configcompilercontext.hpp" +#include "base/configerror.hpp" #include "base/objectlock.hpp" #include "base/convert.hpp" #include "base/utility.hpp" @@ -52,6 +55,12 @@ void Host::OnConfigLoaded(void) hg->ResolveGroupMembership(this, true); } } + + HostGroup::EvaluateObjectRules(this); + ScheduledDowntime::EvaluateApplyRules(this); + Notification::EvaluateApplyRules(this); + Dependency::EvaluateApplyRules(this); + Service::EvaluateApplyRules(this); } void Host::Stop(void) diff --git a/lib/icinga/hostgroup.cpp b/lib/icinga/hostgroup.cpp index 05c63275a..ff84cde31 100644 --- a/lib/icinga/hostgroup.cpp +++ b/lib/icinga/hostgroup.cpp @@ -19,6 +19,7 @@ #include "icinga/hostgroup.hpp" #include "config/objectrule.hpp" +#include "config/configitem.hpp" #include "base/dynamictype.hpp" #include "base/logger.hpp" #include "base/objectlock.hpp" @@ -34,60 +35,50 @@ INITIALIZE_ONCE(&HostGroup::RegisterObjectRuleHandler); void HostGroup::RegisterObjectRuleHandler(void) { - ObjectRule::RegisterType("HostGroup", &HostGroup::EvaluateObjectRules); + ObjectRule::RegisterType("HostGroup"); } -bool HostGroup::EvaluateObjectRuleOne(const Host::Ptr& host, const ObjectRule& rule) +bool HostGroup::EvaluateObjectRule(const Host::Ptr& host, const ConfigItem::Ptr& group) { - DebugInfo di = rule.GetDebugInfo(); + String group_name = group->GetName(); - std::ostringstream msgbuf; - msgbuf << "Evaluating 'object' rule (" << di << ")"; - CONTEXT(msgbuf.str()); + CONTEXT("Evaluating rule for group '" + group_name + "'"); Dictionary::Ptr locals = new Dictionary(); - locals->Set("__parent", rule.GetScope()); + locals->Set("__parent", group->GetScope()); locals->Set("host", host); - if (!rule.EvaluateFilter(locals)) + if (!group->GetFilter()->Evaluate(locals)) return false; Log(LogDebug, "HostGroup") - << "Assigning membership for group '" << rule.GetName() << "' to host '" << host->GetName() << "' for rule " << di; + << "Assigning membership for group '" << group_name << "' to host '" << host->GetName() << "'"; - String group_name = rule.GetName(); - HostGroup::Ptr group = HostGroup::GetByName(group_name); + HostGroup::Ptr groupObject = HostGroup::GetByName(group_name); - if (!group) { + if (!groupObject) { Log(LogCritical, "HostGroup") << "Invalid membership assignment. Group '" << group_name << "' does not exist."; return false; } /* assign host group membership */ - group->ResolveGroupMembership(host, true); + groupObject->ResolveGroupMembership(host, true); return true; } -void HostGroup::EvaluateObjectRule(const ObjectRule& rule) +void HostGroup::EvaluateObjectRules(const Host::Ptr& host) { - BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType()) { - CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for host '" + host->GetName() + "'"); + CONTEXT("Evaluating group memberships for host '" + host->GetName() + "'"); - EvaluateObjectRuleOne(host, rule); - } -} + BOOST_FOREACH(const ConfigItem::Ptr& group, ConfigItem::GetItems("HostGroup")) + { + if (!group->GetFilter()) + continue; -void HostGroup::EvaluateObjectRules(const std::vector& rules) -{ - ParallelWorkQueue upq; - - BOOST_FOREACH(const ObjectRule& rule, rules) { - upq.Enqueue(boost::bind(HostGroup::EvaluateObjectRule, boost::cref(rule))); + EvaluateObjectRule(host, group); } - - upq.Join(); } std::set HostGroup::GetMembers(void) const diff --git a/lib/icinga/hostgroup.hpp b/lib/icinga/hostgroup.hpp index 1aa667a0e..0c0194646 100644 --- a/lib/icinga/hostgroup.hpp +++ b/lib/icinga/hostgroup.hpp @@ -27,7 +27,7 @@ namespace icinga { -class ObjectRule; +class ConfigItem; /** * An Icinga host group. @@ -48,13 +48,13 @@ public: static void RegisterObjectRuleHandler(void); + static void EvaluateObjectRules(const Host::Ptr& host); + private: mutable boost::mutex m_HostGroupMutex; std::set m_Members; - static bool EvaluateObjectRuleOne(const Host::Ptr& host, const ObjectRule& rule); - static void EvaluateObjectRule(const ObjectRule& rule); - static void EvaluateObjectRules(const std::vector& rules); + static bool EvaluateObjectRule(const Host::Ptr& host, const intrusive_ptr& item); }; } diff --git a/lib/icinga/notification-apply.cpp b/lib/icinga/notification-apply.cpp index 160933cc4..7af35260c 100644 --- a/lib/icinga/notification-apply.cpp +++ b/lib/icinga/notification-apply.cpp @@ -39,10 +39,10 @@ void Notification::RegisterApplyRuleHandler(void) std::vector targets; targets.push_back("Host"); targets.push_back("Service"); - ApplyRule::RegisterType("Notification", targets, &Notification::EvaluateApplyRules); + ApplyRule::RegisterType("Notification", targets); } -void Notification::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule) +void Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule) { DebugInfo di = rule.GetDebugInfo(); @@ -76,7 +76,7 @@ void Notification::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, } -bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule) +bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule) { DebugInfo di = rule.GetDebugInfo(); @@ -122,7 +122,7 @@ bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const A name += instance; } - EvaluateApplyRuleOneInstance(checkable, name, locals, rule); + EvaluateApplyRuleInstance(checkable, name, locals, rule); } } else if (vinstances.IsObjectType()) { if (rule.GetFVVar().IsEmpty()) @@ -135,67 +135,47 @@ bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const A locals->Set(rule.GetFKVar(), kv.first); locals->Set(rule.GetFVVar(), kv.second); - EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule); + EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule); } } return true; } -void Notification::EvaluateApplyRule(const ApplyRule& rule) +void Notification::EvaluateApplyRules(const Host::Ptr& host) { - int apply_count = 0; - - if (rule.GetTargetType() == "Host") { - apply_count = 0; - - BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType()) { - CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); - - try { - if (EvaluateApplyRuleOne(host, rule)) - apply_count++; - } catch (const ConfigError& ex) { - const DebugInfo *di = boost::get_error_info(ex); - ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); - } + CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); + + BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Notification")) + { + if (rule.GetTargetType() != "Host") + continue; + + try { + if (EvaluateApplyRule(host, rule)) + rule.AddMatch(); + } catch (const ConfigError& ex) { + const DebugInfo *di = boost::get_error_info(ex); + ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); } - - if (apply_count == 0) - Log(LogWarning, "Notification") - << "Apply rule '" << rule.GetName() << "' for host does not match anywhere!"; - - } else if (rule.GetTargetType() == "Service") { - apply_count = 0; - - BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType()) { - CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'"); - - try { - if (EvaluateApplyRuleOne(service, rule)) - apply_count++; - } catch (const ConfigError& ex) { - const DebugInfo *di = boost::get_error_info(ex); - ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); - } - } - - if (apply_count == 0) - Log(LogWarning, "Notification") - << "Apply rule '" << rule.GetName() << "' for service does not match anywhere!"; - - } else { - Log(LogWarning, "Notification") - << "Wrong target type for apply rule '" << rule.GetName() << "'!"; } } -void Notification::EvaluateApplyRules(const std::vector& rules) -{ - ParallelWorkQueue upq; - BOOST_FOREACH(const ApplyRule& rule, rules) { - upq.Enqueue(boost::bind(&Notification::EvaluateApplyRule, boost::cref(rule))); +void Notification::EvaluateApplyRules(const Service::Ptr& service) +{ + CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'"); + + BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Notification")) + { + if (rule.GetTargetType() != "Service") + continue; + + try { + if (EvaluateApplyRule(service, rule)) + rule.AddMatch(); + } catch (const ConfigError& ex) { + const DebugInfo *di = boost::get_error_info(ex); + ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); + } } - - upq.Join(); } diff --git a/lib/icinga/notification.hpp b/lib/icinga/notification.hpp index 6e27e8fd4..80f2b05dd 100644 --- a/lib/icinga/notification.hpp +++ b/lib/icinga/notification.hpp @@ -68,6 +68,8 @@ enum NotificationType class NotificationCommand; class Checkable; class ApplyRule; +class Host; +class Service; /** * An Icinga notification specification. @@ -108,6 +110,9 @@ public: static void ValidateFilters(const String& location, const Notification::Ptr& object); + static void EvaluateApplyRules(const intrusive_ptr& host); + static void EvaluateApplyRules(const intrusive_ptr& service); + protected: virtual void OnConfigLoaded(void); virtual void Start(void); @@ -116,10 +121,8 @@ protected: private: void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = ""); - static void EvaluateApplyRuleOneInstance(const intrusive_ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); - static bool EvaluateApplyRuleOne(const intrusive_ptr& checkable, const ApplyRule& rule); - static void EvaluateApplyRule(const ApplyRule& rule); - static void EvaluateApplyRules(const std::vector& rules); + static void EvaluateApplyRuleInstance(const intrusive_ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); + static bool EvaluateApplyRule(const intrusive_ptr& checkable, const ApplyRule& rule); }; I2_ICINGA_API int ServiceStateToFilter(ServiceState state); diff --git a/lib/icinga/scheduleddowntime-apply.cpp b/lib/icinga/scheduleddowntime-apply.cpp index 27b3ba5ae..1e82677dd 100644 --- a/lib/icinga/scheduleddowntime-apply.cpp +++ b/lib/icinga/scheduleddowntime-apply.cpp @@ -38,10 +38,10 @@ void ScheduledDowntime::RegisterApplyRuleHandler(void) std::vector targets; targets.push_back("Host"); targets.push_back("Service"); - ApplyRule::RegisterType("ScheduledDowntime", targets, &ScheduledDowntime::EvaluateApplyRules); + ApplyRule::RegisterType("ScheduledDowntime", targets); } -void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule) +void ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule) { DebugInfo di = rule.GetDebugInfo(); @@ -75,7 +75,7 @@ void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& check dobj->OnConfigLoaded(); } -bool ScheduledDowntime::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule) +bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule) { DebugInfo di = rule.GetDebugInfo(); @@ -121,7 +121,7 @@ bool ScheduledDowntime::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, co name += instance; } - EvaluateApplyRuleOneInstance(checkable, name, locals, rule); + EvaluateApplyRuleInstance(checkable, name, locals, rule); } } else if (vinstances.IsObjectType()) { if (rule.GetFVVar().IsEmpty()) @@ -134,68 +134,47 @@ bool ScheduledDowntime::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, co locals->Set(rule.GetFKVar(), kv.first); locals->Set(rule.GetFVVar(), kv.second); - EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule); + EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule); } } return true; } -void ScheduledDowntime::EvaluateApplyRule(const ApplyRule& rule) +void ScheduledDowntime::EvaluateApplyRules(const Host::Ptr& host) { - int apply_count = 0; - - if (rule.GetTargetType() == "Host") { - apply_count = 0; - - BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType()) { - CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); - - try { - if (EvaluateApplyRuleOne(host, rule)) - apply_count++; - } catch (const ConfigError& ex) { - const DebugInfo *di = boost::get_error_info(ex); - ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); - } - } - - if (apply_count == 0) - Log(LogWarning, "ScheduledDowntime") - << "Apply rule '" << rule.GetName() << "' for host does not match anywhere!"; - - } else if (rule.GetTargetType() == "Service") { - apply_count = 0; - - BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType()) { - CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'"); - - try { - if(EvaluateApplyRuleOne(service, rule)) - apply_count++; - } catch (const ConfigError& ex) { - const DebugInfo *di = boost::get_error_info(ex); - ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); - } + CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); + + BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("ScheduledDowntime")) + { + if (rule.GetTargetType() != "Host") + continue; + + try { + if (EvaluateApplyRule(host, rule)) + rule.AddMatch(); + } catch (const ConfigError& ex) { + const DebugInfo *di = boost::get_error_info(ex); + ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); } - - if (apply_count == 0) - Log(LogWarning, "ScheduledDowntime") - << "Apply rule '" << rule.GetName() << "' for service does not match anywhere!"; - - } else { - Log(LogWarning, "ScheduledDowntime") - << "Wrong target type for apply rule '" << rule.GetName() << "'!"; } } -void ScheduledDowntime::EvaluateApplyRules(const std::vector& rules) +void ScheduledDowntime::EvaluateApplyRules(const Service::Ptr& service) { - ParallelWorkQueue upq; - - BOOST_FOREACH(const ApplyRule& rule, rules) { - upq.Enqueue(boost::bind(&ScheduledDowntime::EvaluateApplyRule, boost::cref(rule))); + CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'"); + + BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("ScheduledDowntime")) + { + if (rule.GetTargetType() != "Service") + continue; + + try { + if (EvaluateApplyRule(service, rule)) + rule.AddMatch(); + } catch (const ConfigError& ex) { + const DebugInfo *di = boost::get_error_info(ex); + ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); + } } - - upq.Join(); } diff --git a/lib/icinga/scheduleddowntime.hpp b/lib/icinga/scheduleddowntime.hpp index 7683f445b..d0d15ea13 100644 --- a/lib/icinga/scheduleddowntime.hpp +++ b/lib/icinga/scheduleddowntime.hpp @@ -29,6 +29,8 @@ namespace icinga { class ApplyRule; +class Host; +class Service; /** * An Icinga scheduled downtime specification. @@ -47,6 +49,9 @@ public: static void RegisterApplyRuleHandler(void); + static void EvaluateApplyRules(const intrusive_ptr& host); + static void EvaluateApplyRules(const intrusive_ptr& service); + protected: virtual void Start(void); @@ -56,10 +61,8 @@ private: std::pair FindNextSegment(void); void CreateNextDowntime(void); - static void EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); - static bool EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule); - static void EvaluateApplyRule(const ApplyRule& rule); - static void EvaluateApplyRules(const std::vector& rules); + static void EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); + static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule); }; } diff --git a/lib/icinga/service-apply.cpp b/lib/icinga/service-apply.cpp index 7b24b58a8..35ca575f7 100644 --- a/lib/icinga/service-apply.cpp +++ b/lib/icinga/service-apply.cpp @@ -37,10 +37,10 @@ void Service::RegisterApplyRuleHandler(void) { std::vector targets; targets.push_back("Host"); - ApplyRule::RegisterType("Service", targets, &Service::EvaluateApplyRules); + ApplyRule::RegisterType("Service", targets); } -void Service::EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule) +void Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule) { DebugInfo di = rule.GetDebugInfo(); @@ -68,7 +68,7 @@ void Service::EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String& dobj->OnConfigLoaded(); } -bool Service::EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule) +bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule) { DebugInfo di = rule.GetDebugInfo(); @@ -108,7 +108,7 @@ bool Service::EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule) name += instance; } - EvaluateApplyRuleOneInstance(host, name, locals, rule); + EvaluateApplyRuleInstance(host, name, locals, rule); } } else if (vinstances.IsObjectType()) { if (rule.GetFVVar().IsEmpty()) @@ -121,41 +121,24 @@ bool Service::EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule) locals->Set(rule.GetFKVar(), kv.first); locals->Set(rule.GetFVVar(), kv.second); - EvaluateApplyRuleOneInstance(host, rule.GetName() + kv.first, locals, rule); + EvaluateApplyRuleInstance(host, rule.GetName() + kv.first, locals, rule); } } return true; } -void Service::EvaluateApplyRule(const ApplyRule& rule) +void Service::EvaluateApplyRules(const Host::Ptr& host) { - int apply_count = 0; - - BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType()) { + BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Service")) { CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); try { - if (EvaluateApplyRuleOne(host, rule)) - apply_count++; + if (EvaluateApplyRule(host, rule)) + rule.AddMatch(); } catch (const ConfigError& ex) { const DebugInfo *di = boost::get_error_info(ex); ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); } } - - if (apply_count == 0) - Log(LogWarning, "Service") - << "Apply rule '" << rule.GetName() << "' for host does not match anywhere!"; -} - -void Service::EvaluateApplyRules(const std::vector& rules) -{ - ParallelWorkQueue upq; - - BOOST_FOREACH(const ApplyRule& rule, rules) { - upq.Enqueue(boost::bind(&Service::EvaluateApplyRule, boost::cref(rule))); - } - - upq.Join(); } diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index 9a27c1e1f..34fb67c52 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -19,6 +19,7 @@ #include "icinga/service.hpp" #include "icinga/servicegroup.hpp" +#include "icinga/scheduleddowntime.hpp" #include "icinga/pluginutility.hpp" #include "base/objectlock.hpp" #include "base/convert.hpp" @@ -65,6 +66,11 @@ void Service::OnConfigLoaded(void) SetSchedulingOffset(Utility::Random()); Checkable::OnConfigLoaded(); + + ServiceGroup::EvaluateObjectRules(this); + ScheduledDowntime::EvaluateApplyRules(this); + Notification::EvaluateApplyRules(this); + Dependency::EvaluateApplyRules(this); } Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName) diff --git a/lib/icinga/service.hpp b/lib/icinga/service.hpp index 36fb1ea6e..81f3b3ed8 100644 --- a/lib/icinga/service.hpp +++ b/lib/icinga/service.hpp @@ -53,16 +53,16 @@ public: static void RegisterApplyRuleHandler(void); + static void EvaluateApplyRules(const Host::Ptr& host); + protected: virtual void OnConfigLoaded(void); private: Host::Ptr m_Host; - static void EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); - static bool EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule); - static void EvaluateApplyRule(const ApplyRule& rule); - static void EvaluateApplyRules(const std::vector& rules); + static void EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); + static bool EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule); }; I2_ICINGA_API boost::tuple GetHostService(const Checkable::Ptr& checkable); diff --git a/lib/icinga/servicegroup.cpp b/lib/icinga/servicegroup.cpp index af59b0d19..1feb23b0b 100644 --- a/lib/icinga/servicegroup.cpp +++ b/lib/icinga/servicegroup.cpp @@ -19,6 +19,7 @@ #include "icinga/servicegroup.hpp" #include "config/objectrule.hpp" +#include "config/configitem.hpp" #include "base/dynamictype.hpp" #include "base/objectlock.hpp" #include "base/logger.hpp" @@ -34,63 +35,53 @@ INITIALIZE_ONCE(&ServiceGroup::RegisterObjectRuleHandler); void ServiceGroup::RegisterObjectRuleHandler(void) { - ObjectRule::RegisterType("ServiceGroup", &ServiceGroup::EvaluateObjectRules); + ObjectRule::RegisterType("ServiceGroup"); } -bool ServiceGroup::EvaluateObjectRuleOne(const Service::Ptr& service, const ObjectRule& rule) +bool ServiceGroup::EvaluateObjectRule(const Service::Ptr& service, const ConfigItem::Ptr& group) { - DebugInfo di = rule.GetDebugInfo(); + String group_name = group->GetName(); - std::ostringstream msgbuf; - msgbuf << "Evaluating 'object' rule (" << di << ")"; - CONTEXT(msgbuf.str()); + CONTEXT("Evaluating rule for group '" + group_name + "'"); Host::Ptr host = service->GetHost(); Dictionary::Ptr locals = new Dictionary(); - locals->Set("__parent", rule.GetScope()); + locals->Set("__parent", group->GetScope()); locals->Set("host", host); locals->Set("service", service); - if (!rule.EvaluateFilter(locals)) + if (!group->GetFilter()->Evaluate(locals)) return false; Log(LogDebug, "ServiceGroup") - << "Assigning membership for group '" << rule.GetName() << "' to service '" << service->GetName() << "' for rule " << di; + << "Assigning membership for group '" << group_name << "' to service '" << service->GetName() << "'"; - String group_name = rule.GetName(); - ServiceGroup::Ptr group = ServiceGroup::GetByName(group_name); + ServiceGroup::Ptr groupObject = ServiceGroup::GetByName(group_name); - if (!group) { + if (!groupObject) { Log(LogCritical, "ServiceGroup") << "Invalid membership assignment. Group '" << group_name << "' does not exist."; return false; } /* assign service group membership */ - group->ResolveGroupMembership(service, true); + groupObject->ResolveGroupMembership(service, true); return true; } -void ServiceGroup::EvaluateObjectRule(const ObjectRule& rule) +void ServiceGroup::EvaluateObjectRules(const Service::Ptr& service) { - BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType()) { - CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for service '" + service->GetName() + "'"); + CONTEXT("Evaluating group membership for service '" + service->GetName() + "'"); - EvaluateObjectRuleOne(service, rule); - } -} + BOOST_FOREACH(const ConfigItem::Ptr& group, ConfigItem::GetItems("ServiceGroup")) + { + if (!group->GetFilter()) + continue; -void ServiceGroup::EvaluateObjectRules(const std::vector& rules) -{ - ParallelWorkQueue upq; - - BOOST_FOREACH(const ObjectRule& rule, rules) { - upq.Enqueue(boost::bind(ServiceGroup::EvaluateObjectRule, boost::cref(rule))); + EvaluateObjectRule(service, group); } - - upq.Join(); } std::set ServiceGroup::GetMembers(void) const diff --git a/lib/icinga/servicegroup.hpp b/lib/icinga/servicegroup.hpp index 016dc38a3..e6a82bcba 100644 --- a/lib/icinga/servicegroup.hpp +++ b/lib/icinga/servicegroup.hpp @@ -27,7 +27,7 @@ namespace icinga { -class ObjectRule; +class ConfigItem; /** * An Icinga service group. @@ -48,13 +48,13 @@ public: static void RegisterObjectRuleHandler(void); + static void EvaluateObjectRules(const Service::Ptr& service); + private: mutable boost::mutex m_ServiceGroupMutex; std::set m_Members; - static bool EvaluateObjectRuleOne(const Service::Ptr& service, const ObjectRule& rule); - static void EvaluateObjectRule(const ObjectRule& rule); - static void EvaluateObjectRules(const std::vector& rules); + static bool EvaluateObjectRule(const Service::Ptr& service, const intrusive_ptr& group); }; } diff --git a/lib/icinga/user.cpp b/lib/icinga/user.cpp index 4691b7437..40a7cddd1 100644 --- a/lib/icinga/user.cpp +++ b/lib/icinga/user.cpp @@ -18,6 +18,7 @@ ******************************************************************************/ #include "icinga/user.hpp" +#include "icinga/usergroup.hpp" #include "icinga/notification.hpp" #include "icinga/usergroup.hpp" #include "config/configcompilercontext.hpp" @@ -51,6 +52,8 @@ void User::OnConfigLoaded(void) ug->ResolveGroupMembership(this, true); } } + + UserGroup::EvaluateObjectRules(this); } void User::Stop(void) diff --git a/lib/icinga/usergroup.cpp b/lib/icinga/usergroup.cpp index aaaf3df31..32e57e0b6 100644 --- a/lib/icinga/usergroup.cpp +++ b/lib/icinga/usergroup.cpp @@ -19,6 +19,7 @@ #include "icinga/usergroup.hpp" #include "config/objectrule.hpp" +#include "config/configitem.hpp" #include "base/dynamictype.hpp" #include "base/objectlock.hpp" #include "base/logger.hpp" @@ -34,60 +35,50 @@ INITIALIZE_ONCE(&UserGroup::RegisterObjectRuleHandler); void UserGroup::RegisterObjectRuleHandler(void) { - ObjectRule::RegisterType("UserGroup", &UserGroup::EvaluateObjectRules); + ObjectRule::RegisterType("UserGroup"); } -bool UserGroup::EvaluateObjectRuleOne(const User::Ptr& user, const ObjectRule& rule) +bool UserGroup::EvaluateObjectRule(const User::Ptr& user, const ConfigItem::Ptr& group) { - DebugInfo di = rule.GetDebugInfo(); + String group_name = group->GetName(); - std::ostringstream msgbuf; - msgbuf << "Evaluating 'object' rule (" << di << ")"; - CONTEXT(msgbuf.str()); + CONTEXT("Evaluating rule for group '" + group_name + "'"); Dictionary::Ptr locals = new Dictionary(); - locals->Set("__parent", rule.GetScope()); + locals->Set("__parent", group->GetScope()); locals->Set("user", user); - if (!rule.EvaluateFilter(locals)) + if (!group->GetFilter()->Evaluate(locals)) return false; Log(LogDebug, "UserGroup") - << "Assigning membership for group '" << rule.GetName() << "' to user '" << user->GetName() << "' for rule " << di; + << "Assigning membership for group '" << group_name << "' to user '" << user->GetName() << "'"; - String group_name = rule.GetName(); - UserGroup::Ptr group = UserGroup::GetByName(group_name); + UserGroup::Ptr groupObject = UserGroup::GetByName(group_name); - if (!group) { + if (!groupObject) { Log(LogCritical, "UserGroup") << "Invalid membership assignment. Group '" << group_name << "' does not exist."; return false; } /* assign user group membership */ - group->ResolveGroupMembership(user, true); + groupObject->ResolveGroupMembership(user, true); return true; } -void UserGroup::EvaluateObjectRule(const ObjectRule& rule) +void UserGroup::EvaluateObjectRules(const User::Ptr& user) { - BOOST_FOREACH(const User::Ptr& user, DynamicType::GetObjectsByType()) { - CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for user '" + user->GetName() + "'"); + CONTEXT("Evaluating group membership for user '" + user->GetName() + "'"); - EvaluateObjectRuleOne(user, rule); - } -} + BOOST_FOREACH(const ConfigItem::Ptr& group, ConfigItem::GetItems("UserGroup")) + { + if (!group->GetFilter()) + continue; -void UserGroup::EvaluateObjectRules(const std::vector& rules) -{ - ParallelWorkQueue upq; - - BOOST_FOREACH(const ObjectRule& rule, rules) { - upq.Enqueue(boost::bind(UserGroup::EvaluateObjectRule, boost::cref(rule))); + EvaluateObjectRule(user, group); } - - upq.Join(); } std::set UserGroup::GetMembers(void) const diff --git a/lib/icinga/usergroup.hpp b/lib/icinga/usergroup.hpp index 981e385b2..7f5c999c2 100644 --- a/lib/icinga/usergroup.hpp +++ b/lib/icinga/usergroup.hpp @@ -27,7 +27,7 @@ namespace icinga { -class ObjectRule; +class ConfigItem; /** * An Icinga user group. @@ -48,13 +48,13 @@ public: static void RegisterObjectRuleHandler(void); + static void EvaluateObjectRules(const User::Ptr& user); + private: mutable boost::mutex m_UserGroupMutex; std::set m_Members; - static bool EvaluateObjectRuleOne(const User::Ptr& user, const ObjectRule& rule); - static void EvaluateObjectRule(const ObjectRule& rule); - static void EvaluateObjectRules(const std::vector& rules); + static bool EvaluateObjectRule(const User::Ptr& user, const intrusive_ptr& group); }; } -- 2.40.0