Refactor apply/object rules

fixes #7700
This commit is contained in:
Gunnar Beutner 2014-11-16 16:20:39 +01:00
parent ee89f54679
commit 0078e00c13
26 changed files with 374 additions and 491 deletions

View File

@ -25,13 +25,13 @@
using namespace icinga; using namespace icinga;
ApplyRule::RuleMap ApplyRule::m_Rules; 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>& expression, ApplyRule::ApplyRule(const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
const boost::shared_ptr<Expression>& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm, const boost::shared_ptr<Expression>& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm,
const DebugInfo& di, const Object::Ptr& scope) const DebugInfo& di, const Object::Ptr& scope)
: m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_FKVar(fkvar), : 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 String ApplyRule::GetTargetType(void) const
@ -91,69 +91,27 @@ bool ApplyRule::EvaluateFilter(const Object::Ptr& scope) const
return m_Filter->Evaluate(scope).ToBool(); return m_Filter->Evaluate(scope).ToBool();
} }
void ApplyRule::EvaluateRules(bool clear) void ApplyRule::RegisterType(const String& sourceType, const std::vector<String>& targetTypes)
{ {
std::set<String> completedTypes; m_Types[sourceType] = targetTypes;
while (completedTypes.size() < m_Callbacks.size()) {
std::pair<String, std::pair<Callback, std::vector<String> > > 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<String>& 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<String>& targetTypes, const ApplyRule::Callback& callback)
{
m_Callbacks[sourceType] = make_pair(callback, targetTypes);
} }
bool ApplyRule::IsValidSourceType(const String& sourceType) 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) 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; return false;
if (it->second.second.size() == 1 && targetType == "") if (it->second.size() == 1 && targetType == "")
return true; return true;
BOOST_FOREACH(const String& type, it->second.second) { BOOST_FOREACH(const String& type, it->second) {
if (type == targetType) if (type == targetType)
return true; return true;
} }
@ -163,11 +121,47 @@ bool ApplyRule::IsValidTargetType(const String& sourceType, const String& target
std::vector<String> ApplyRule::GetTargetTypes(const String& sourceType) std::vector<String> 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<String>(); return std::vector<String>();
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>& ApplyRule::GetRules(const String& type)
{
RuleMap::iterator it = m_Rules.find(type);
if (it == m_Rules.end()) {
static std::vector<ApplyRule> 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();
} }

View File

@ -34,8 +34,7 @@ namespace icinga
class I2_CONFIG_API ApplyRule class I2_CONFIG_API ApplyRule
{ {
public: public:
typedef boost::function<void (const std::vector<ApplyRule>& rules)> Callback; typedef std::map<String, std::vector<String> > TypeMap;
typedef std::map<String, std::pair<Callback, std::vector<String> > > CallbackMap;
typedef std::map<String, std::vector<ApplyRule> > RuleMap; typedef std::map<String, std::vector<ApplyRule> > RuleMap;
String GetTargetType(void) const; String GetTargetType(void) const;
@ -47,18 +46,23 @@ public:
boost::shared_ptr<Expression> GetFTerm(void) const; boost::shared_ptr<Expression> GetFTerm(void) const;
DebugInfo GetDebugInfo(void) const; DebugInfo GetDebugInfo(void) const;
Object::Ptr GetScope(void) const; Object::Ptr GetScope(void) const;
void AddMatch(void);
bool HasMatches(void) const;
bool EvaluateFilter(const Object::Ptr& scope) 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>& expression, static void AddRule(const String& sourceType, const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
const boost::shared_ptr<Expression>& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm, const DebugInfo& di, const Object::Ptr& scope); const boost::shared_ptr<Expression>& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm, const DebugInfo& di, const Object::Ptr& scope);
static void EvaluateRules(bool clear); static std::vector<ApplyRule>& GetRules(const String& type);
static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes, const ApplyRule::Callback& callback); static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes);
static bool IsValidSourceType(const String& sourceType); static bool IsValidSourceType(const String& sourceType);
static bool IsValidTargetType(const String& sourceType, const String& targetType); static bool IsValidTargetType(const String& sourceType, const String& targetType);
static std::vector<String> GetTargetTypes(const String& sourceType); static std::vector<String> GetTargetTypes(const String& sourceType);
static void CheckMatches(void);
static void DiscardRules(void);
private: private:
String m_TargetType; String m_TargetType;
String m_Name; String m_Name;
@ -69,8 +73,9 @@ private:
boost::shared_ptr<Expression> m_FTerm; boost::shared_ptr<Expression> m_FTerm;
DebugInfo m_DebugInfo; DebugInfo m_DebugInfo;
Object::Ptr m_Scope; Object::Ptr m_Scope;
bool m_HasMatches;
static CallbackMap m_Callbacks; static TypeMap m_Types;
static RuleMap m_Rules; static RuleMap m_Rules;
ApplyRule(const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression, ApplyRule(const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,

View File

@ -42,7 +42,7 @@
using namespace icinga; using namespace icinga;
boost::mutex ConfigItem::m_Mutex; boost::mutex ConfigItem::m_Mutex;
ConfigItem::ItemMap ConfigItem::m_Items; ConfigItem::TypeMap ConfigItem::m_Items;
ConfigItem::ItemList ConfigItem::m_UnnamedItems; ConfigItem::ItemList ConfigItem::m_UnnamedItems;
/** /**
@ -57,11 +57,12 @@ ConfigItem::ItemList ConfigItem::m_UnnamedItems;
*/ */
ConfigItem::ConfigItem(const String& type, const String& name, ConfigItem::ConfigItem(const String& type, const String& name,
bool abstract, const boost::shared_ptr<Expression>& exprl, bool abstract, const boost::shared_ptr<Expression>& exprl,
const boost::shared_ptr<Expression>& filter,
const DebugInfo& debuginfo, const Object::Ptr& scope, const DebugInfo& debuginfo, const Object::Ptr& scope,
const String& zone) const String& zone)
: m_Type(type), m_Name(name), m_Abstract(abstract), : m_Type(type), m_Name(name), m_Abstract(abstract),
m_Expression(exprl), m_DebugInfo(debuginfo), m_Expression(exprl), m_Filter(filter),
m_Scope(scope), m_Zone(zone) m_DebugInfo(debuginfo), m_Scope(scope), m_Zone(zone)
{ {
} }
@ -120,6 +121,16 @@ boost::shared_ptr<Expression> ConfigItem::GetExpression(void) const
return m_Expression; return m_Expression;
} }
/**
* Retrieves the object filter for the configuration item.
*
* @returns The filter expression.
*/
boost::shared_ptr<Expression> ConfigItem::GetFilter(void) const
{
return m_Filter;
}
/** /**
* Commits the configuration item by creating a DynamicObject * Commits the configuration item by creating a DynamicObject
* object. * object.
@ -150,7 +161,6 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard)
Dictionary::Ptr locals = new Dictionary(); Dictionary::Ptr locals = new Dictionary();
locals->Set("__parent", m_Scope); locals->Set("__parent", m_Scope);
m_Scope.reset();
dobj->SetParentScope(locals); dobj->SetParentScope(locals);
locals.reset(); locals.reset();
@ -238,10 +248,8 @@ void ConfigItem::Register(void)
boost::mutex::scoped_lock lock(m_Mutex); boost::mutex::scoped_lock lock(m_Mutex);
m_UnnamedItems.push_back(this); m_UnnamedItems.push_back(this);
} else { } else {
std::pair<String, String> key = std::make_pair(m_Type, m_Name);
boost::mutex::scoped_lock lock(m_Mutex); 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) ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name)
{ {
std::pair<String, String> key = std::make_pair(type, name);
ConfigItem::ItemMap::iterator it;
{ {
boost::mutex::scoped_lock lock(m_Mutex); 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 (it2 == it->second.end())
return ConfigItem::Ptr();
return it2->second;
} }
if (it != m_Items.end())
return it->second;
return ConfigItem::Ptr();
} }
bool ConfigItem::CommitNewItems(void) bool ConfigItem::CommitNewItems(ParallelWorkQueue& upq)
{ {
std::vector<ConfigItem::Ptr> items; typedef std::pair<ConfigItem::Ptr, bool> ItemPair;
std::vector<ItemPair> items;
do { do {
ParallelWorkQueue upq;
items.clear(); items.clear();
{ {
boost::mutex::scoped_lock lock(m_Mutex); boost::mutex::scoped_lock lock(m_Mutex);
BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) { BOOST_FOREACH(const TypeMap::value_type& kv, m_Items) {
if (!kv.second->m_Abstract && !kv.second->m_Object) { BOOST_FOREACH(const ItemMap::value_type& kv2, kv.second)
upq.Enqueue(boost::bind(&ConfigItem::Commit, kv.second, false)); {
items.push_back(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) { BOOST_FOREACH(const ConfigItem::Ptr& item, m_UnnamedItems) {
if (!item->m_Abstract && !item->m_Object) { if (!item->m_Abstract && !item->m_Object)
upq.Enqueue(boost::bind(&ConfigItem::Commit, item, true)); items.push_back(std::make_pair(item, true));
items.push_back(item);
}
} }
m_UnnamedItems.clear(); m_UnnamedItems.clear();
} }
BOOST_FOREACH(const ItemPair& ip, items) {
upq.Enqueue(boost::bind(&ConfigItem::Commit, ip.first, ip.second));
}
upq.Join(); upq.Join();
if (ConfigCompilerContext::GetInstance()->HasErrors()) if (ConfigCompilerContext::GetInstance()->HasErrors())
return false; return false;
BOOST_FOREACH(const ConfigItem::Ptr& item, items) { BOOST_FOREACH(const ItemPair& ip, items) {
upq.Enqueue(boost::bind(&DynamicObject::OnConfigLoaded, item->m_Object)); upq.Enqueue(boost::bind(&DynamicObject::OnConfigLoaded, ip.first->m_Object));
} }
upq.Join(); upq.Join();
@ -315,25 +327,18 @@ bool ConfigItem::CommitNewItems(void)
bool ConfigItem::ValidateItems(void) bool ConfigItem::ValidateItems(void)
{ {
ParallelWorkQueue upq;
if (ConfigCompilerContext::GetInstance()->HasErrors()) if (ConfigCompilerContext::GetInstance()->HasErrors())
return false; return false;
Log(LogInformation, "ConfigItem", "Committing config items"); Log(LogInformation, "ConfigItem", "Committing config items");
if (!CommitNewItems()) if (!CommitNewItems(upq))
return false; return false;
Log(LogInformation, "ConfigItem", "Evaluating 'object' rules (step 1)..."); ApplyRule::CheckMatches();
ObjectRule::EvaluateRules(false); ApplyRule::DiscardRules();
Log(LogInformation, "ConfigItem", "Evaluating 'apply' rules...");
ApplyRule::EvaluateRules(true);
if (!CommitNewItems())
return false;
Log(LogInformation, "ConfigItem", "Evaluating 'object' rules (step 2)...");
ObjectRule::EvaluateRules(true);
ConfigItem::DiscardItems(); ConfigItem::DiscardItems();
ConfigType::DiscardTypes(); ConfigType::DiscardTypes();
@ -400,3 +405,22 @@ void ConfigItem::DiscardItems(void)
m_Items.clear(); m_Items.clear();
} }
std::vector<ConfigItem::Ptr> ConfigItem::GetItems(const String& type)
{
std::vector<ConfigItem::Ptr> 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;
}

View File

@ -23,6 +23,7 @@
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "config/expression.hpp" #include "config/expression.hpp"
#include "base/dynamicobject.hpp" #include "base/dynamicobject.hpp"
#include "base/workqueue.hpp"
namespace icinga namespace icinga
{ {
@ -38,7 +39,9 @@ public:
DECLARE_PTR_TYPEDEFS(ConfigItem); DECLARE_PTR_TYPEDEFS(ConfigItem);
ConfigItem(const String& type, const String& name, bool abstract, ConfigItem(const String& type, const String& name, bool abstract,
const boost::shared_ptr<Expression>& exprl, const DebugInfo& debuginfo, const boost::shared_ptr<Expression>& exprl,
const boost::shared_ptr<Expression>& filter,
const DebugInfo& debuginfo,
const Object::Ptr& scope, const String& zone); const Object::Ptr& scope, const String& zone);
String GetType(void) const; String GetType(void) const;
@ -48,12 +51,12 @@ public:
std::vector<ConfigItem::Ptr> GetParents(void) const; std::vector<ConfigItem::Ptr> GetParents(void) const;
boost::shared_ptr<Expression> GetExpression(void) const; boost::shared_ptr<Expression> GetExpression(void) const;
boost::shared_ptr<Expression> GetFilter(void) const;
DynamicObject::Ptr Commit(bool discard = true); DynamicObject::Ptr Commit(bool discard = true);
void Register(void); void Register(void);
DebugInfo GetDebugInfo(void) const; DebugInfo GetDebugInfo(void) const;
Object::Ptr GetScope(void) const; Object::Ptr GetScope(void) const;
String GetZone(void) const; String GetZone(void) const;
@ -65,12 +68,15 @@ public:
static bool ActivateItems(void); static bool ActivateItems(void);
static void DiscardItems(void); static void DiscardItems(void);
static std::vector<ConfigItem::Ptr> GetItems(const String& type);
private: private:
String m_Type; /**< The object type. */ String m_Type; /**< The object type. */
String m_Name; /**< The name. */ String m_Name; /**< The name. */
bool m_Abstract; /**< Whether this is a template. */ bool m_Abstract; /**< Whether this is a template. */
boost::shared_ptr<Expression> m_Expression; boost::shared_ptr<Expression> m_Expression;
boost::shared_ptr<Expression> m_Filter;
DebugInfo m_DebugInfo; /**< Debug information. */ DebugInfo m_DebugInfo; /**< Debug information. */
Object::Ptr m_Scope; /**< variable scope. */ Object::Ptr m_Scope; /**< variable scope. */
String m_Zone; /**< The zone. */ String m_Zone; /**< The zone. */
@ -79,8 +85,9 @@ private:
static boost::mutex m_Mutex; static boost::mutex m_Mutex;
typedef std::map<std::pair<String, String>, ConfigItem::Ptr> ItemMap; typedef std::map<String, ConfigItem::Ptr> ItemMap;
static ItemMap m_Items; /**< All registered configuration items. */ typedef std::map<String, ItemMap> TypeMap;
static TypeMap m_Items; /**< All registered configuration items. */
typedef std::vector<ConfigItem::Ptr> ItemList; typedef std::vector<ConfigItem::Ptr> ItemList;
static ItemList m_UnnamedItems; static ItemList m_UnnamedItems;
@ -88,7 +95,7 @@ private:
static ConfigItem::Ptr GetObjectUnlocked(const String& type, static ConfigItem::Ptr GetObjectUnlocked(const String& type,
const String& name); const String& name);
static bool CommitNewItems(void); static bool CommitNewItems(ParallelWorkQueue& upq);
}; };
} }

View File

@ -21,6 +21,7 @@
#include "base/dynamictype.hpp" #include "base/dynamictype.hpp"
#include <sstream> #include <sstream>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/smart_ptr/make_shared.hpp>
using namespace icinga; using namespace icinga;
@ -69,6 +70,11 @@ void ConfigItemBuilder::AddExpression(Expression *expr)
m_Expressions.push_back(expr); m_Expressions.push_back(expr);
} }
void ConfigItemBuilder::SetFilter(const boost::shared_ptr<Expression>& filter)
{
m_Filter = filter;
}
ConfigItem::Ptr ConfigItemBuilder::Compile(void) ConfigItem::Ptr ConfigItemBuilder::Compile(void)
{ {
if (m_Type.IsEmpty()) { if (m_Type.IsEmpty()) {
@ -104,10 +110,10 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
dexpr->MakeInline(); dexpr->MakeInline();
exprs.push_back(dexpr); exprs.push_back(dexpr);
DictExpression *exprl = new DictExpression(exprs, m_DebugInfo); boost::shared_ptr<DictExpression> exprl = boost::make_shared<DictExpression>(exprs, m_DebugInfo);
exprl->MakeInline(); exprl->MakeInline();
return new ConfigItem(m_Type, m_Name, m_Abstract, boost::shared_ptr<Expression>(exprl), return new ConfigItem(m_Type, m_Name, m_Abstract, exprl, m_Filter,
m_DebugInfo, m_Scope, m_Zone); m_DebugInfo, m_Scope, m_Zone);
} }

View File

@ -49,6 +49,7 @@ public:
void SetZone(const String& zone); void SetZone(const String& zone);
void AddExpression(Expression *expr); void AddExpression(Expression *expr);
void SetFilter(const boost::shared_ptr<Expression>& filter);
ConfigItem::Ptr Compile(void); ConfigItem::Ptr Compile(void);
@ -57,6 +58,7 @@ private:
String m_Name; /**< The name. */ String m_Name; /**< The name. */
bool m_Abstract; /**< Whether the item is abstract. */ bool m_Abstract; /**< Whether the item is abstract. */
std::vector<Expression *> m_Expressions; /**< Expressions for this item. */ std::vector<Expression *> m_Expressions; /**< Expressions for this item. */
boost::shared_ptr<Expression> m_Filter; /**< Filter expression. */
DebugInfo m_DebugInfo; /**< Debug information. */ DebugInfo m_DebugInfo; /**< Debug information. */
Object::Ptr m_Scope; /**< variable scope. */ Object::Ptr m_Scope; /**< variable scope. */
String m_Zone; /**< The zone. */ String m_Zone; /**< The zone. */

View File

@ -46,10 +46,10 @@ Value Expression::Evaluate(const Object::Ptr& context, DebugHint *dhint) const
{ {
try { try {
#ifdef _DEBUG #ifdef _DEBUG
std::ostringstream msgbuf; /* std::ostringstream msgbuf;
ShowCodeFragment(msgbuf, GetDebugInfo(), false); ShowCodeFragment(msgbuf, GetDebugInfo(), false);
Log(LogDebug, "Expression") Log(LogDebug, "Expression")
<< "Executing:\n" << msgbuf.str(); << "Executing:\n" << msgbuf.str();*/
#endif /* _DEBUG */ #endif /* _DEBUG */
return DoEvaluate(context, dhint); return DoEvaluate(context, dhint);
@ -508,10 +508,9 @@ Value ObjectExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint)
item->SetAbstract(m_Abstract); item->SetAbstract(m_Abstract);
item->SetScope(context); item->SetScope(context);
item->SetZone(m_Zone); item->SetZone(m_Zone);
item->Compile()->Register(); item->SetFilter(m_Filter);
if (m_Filter) item->Compile()->Register();
ObjectRule::AddRule(m_Type, name, m_Filter, m_DebugInfo, context);
return Empty; return Empty;
} }

View File

@ -23,70 +23,14 @@
using namespace icinga; using namespace icinga;
ObjectRule::RuleMap ObjectRule::m_Rules; ObjectRule::TypeSet ObjectRule::m_Types;
ObjectRule::CallbackMap ObjectRule::m_Callbacks;
ObjectRule::ObjectRule(const String& name, const boost::shared_ptr<Expression>& filter, void ObjectRule::RegisterType(const String& sourceType)
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; m_Types.insert(sourceType);
}
boost::shared_ptr<Expression> ObjectRule::GetFilter(void) const
{
return m_Filter;
}
DebugInfo ObjectRule::GetDebugInfo(void) const
{
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<Expression>& 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<String, Callback> 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;
} }
bool ObjectRule::IsValidSourceType(const String& sourceType) bool ObjectRule::IsValidSourceType(const String& sourceType)
{ {
return m_Callbacks.find(sourceType) != m_Callbacks.end(); return m_Types.find(sourceType) != m_Types.end();
} }

View File

@ -23,7 +23,7 @@
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "config/expression.hpp" #include "config/expression.hpp"
#include "base/debuginfo.hpp" #include "base/debuginfo.hpp"
#include "base/dynamictype.hpp" #include <set>
namespace icinga namespace icinga
{ {
@ -34,34 +34,15 @@ namespace icinga
class I2_CONFIG_API ObjectRule class I2_CONFIG_API ObjectRule
{ {
public: public:
typedef boost::function<void (const std::vector<ObjectRule>& rules)> Callback; typedef std::set<String> TypeSet;
typedef std::map<String, Callback> CallbackMap;
typedef std::map<String, std::vector<ObjectRule> > RuleMap;
String GetName(void) const; static void RegisterType(const String& sourceType);
boost::shared_ptr<Expression> 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<Expression>& filter, const DebugInfo& di, const Object::Ptr& scope);
static void EvaluateRules(bool clear);
static void RegisterType(const String& sourceType, const ObjectRule::Callback& callback);
static bool IsValidSourceType(const String& sourceType); static bool IsValidSourceType(const String& sourceType);
private: private:
String m_Name; ObjectRule(void);
boost::shared_ptr<Expression> m_Filter;
DebugInfo m_DebugInfo;
Object::Ptr m_Scope;
static CallbackMap m_Callbacks; static TypeSet m_Types;
static RuleMap m_Rules;
ObjectRule(const String& name, const boost::shared_ptr<Expression>& filter, const DebugInfo& di, const Object::Ptr& scope);
}; };
} }

View File

@ -39,10 +39,10 @@ void Dependency::RegisterApplyRuleHandler(void)
std::vector<String> targets; std::vector<String> targets;
targets.push_back("Host"); targets.push_back("Host");
targets.push_back("Service"); 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(); 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(); DebugInfo di = rule.GetDebugInfo();
@ -123,7 +123,7 @@ bool Dependency::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const App
name += instance; name += instance;
} }
EvaluateApplyRuleOneInstance(checkable, name, locals, rule); EvaluateApplyRuleInstance(checkable, name, locals, rule);
} }
} else if (vinstances.IsObjectType<Dictionary>()) { } else if (vinstances.IsObjectType<Dictionary>()) {
if (rule.GetFVVar().IsEmpty()) 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.GetFKVar(), kv.first);
locals->Set(rule.GetFVVar(), kv.second); locals->Set(rule.GetFVVar(), kv.second);
EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule); EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule);
} }
} }
return true; return true;
} }
void Dependency::EvaluateApplyRule(const ApplyRule& rule) void Dependency::EvaluateApplyRules(const Host::Ptr& host)
{ {
int apply_count = 0; CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
if (rule.GetTargetType() == "Host") { BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Dependency"))
apply_count = 0; {
if (rule.GetTargetType() != "Host")
continue;
BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) { try {
CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); if (EvaluateApplyRule(host, rule))
rule.AddMatch();
try { } catch (const ConfigError& ex) {
if (EvaluateApplyRuleOne(host, rule)) const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
apply_count++; ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
} catch (const ConfigError& ex) {
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(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<Service>()) {
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<errinfo_debuginfo>(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<ApplyRule>& rules) void Dependency::EvaluateApplyRules(const Service::Ptr& service)
{ {
ParallelWorkQueue upq; CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'");
BOOST_FOREACH(const ApplyRule& rule, rules) { BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Dependency"))
upq.Enqueue(boost::bind(&Dependency::EvaluateApplyRule, boost::cref(rule))); {
if (rule.GetTargetType() != "Service")
continue;
try {
if (EvaluateApplyRule(service, rule))
rule.AddMatch();
} catch (const ConfigError& ex) {
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
}
} }
upq.Join();
} }

View File

@ -28,6 +28,8 @@ namespace icinga
{ {
class ApplyRule; class ApplyRule;
class Host;
class Service;
/** /**
* A service dependency.. * A service dependency..
@ -51,6 +53,9 @@ public:
static void ValidateFilters(const String& location, const Dependency::Ptr& object); static void ValidateFilters(const String& location, const Dependency::Ptr& object);
static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
protected: protected:
virtual void OnConfigLoaded(void); virtual void OnConfigLoaded(void);
virtual void OnStateLoaded(void); virtual void OnStateLoaded(void);
@ -60,10 +65,8 @@ private:
Checkable::Ptr m_Parent; Checkable::Ptr m_Parent;
Checkable::Ptr m_Child; Checkable::Ptr m_Child;
static void EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); static void EvaluateApplyRuleInstance(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 bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule);
static void EvaluateApplyRule(const ApplyRule& rule);
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
}; };
} }

View File

@ -21,6 +21,9 @@
#include "icinga/service.hpp" #include "icinga/service.hpp"
#include "icinga/hostgroup.hpp" #include "icinga/hostgroup.hpp"
#include "icinga/pluginutility.hpp" #include "icinga/pluginutility.hpp"
#include "icinga/scheduleddowntime.hpp"
#include "config/configcompilercontext.hpp"
#include "base/configerror.hpp"
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
#include "base/convert.hpp" #include "base/convert.hpp"
#include "base/utility.hpp" #include "base/utility.hpp"
@ -52,6 +55,12 @@ void Host::OnConfigLoaded(void)
hg->ResolveGroupMembership(this, true); hg->ResolveGroupMembership(this, true);
} }
} }
HostGroup::EvaluateObjectRules(this);
ScheduledDowntime::EvaluateApplyRules(this);
Notification::EvaluateApplyRules(this);
Dependency::EvaluateApplyRules(this);
Service::EvaluateApplyRules(this);
} }
void Host::Stop(void) void Host::Stop(void)

View File

@ -19,6 +19,7 @@
#include "icinga/hostgroup.hpp" #include "icinga/hostgroup.hpp"
#include "config/objectrule.hpp" #include "config/objectrule.hpp"
#include "config/configitem.hpp"
#include "base/dynamictype.hpp" #include "base/dynamictype.hpp"
#include "base/logger.hpp" #include "base/logger.hpp"
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
@ -34,62 +35,52 @@ INITIALIZE_ONCE(&HostGroup::RegisterObjectRuleHandler);
void HostGroup::RegisterObjectRuleHandler(void) 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; CONTEXT("Evaluating rule for group '" + group_name + "'");
msgbuf << "Evaluating 'object' rule (" << di << ")";
CONTEXT(msgbuf.str());
Dictionary::Ptr locals = new Dictionary(); Dictionary::Ptr locals = new Dictionary();
locals->Set("__parent", rule.GetScope()); locals->Set("__parent", group->GetScope());
locals->Set("host", host); locals->Set("host", host);
if (!rule.EvaluateFilter(locals)) if (!group->GetFilter()->Evaluate(locals))
return false; return false;
Log(LogDebug, "HostGroup") 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 groupObject = HostGroup::GetByName(group_name);
HostGroup::Ptr group = HostGroup::GetByName(group_name);
if (!group) { if (!groupObject) {
Log(LogCritical, "HostGroup") Log(LogCritical, "HostGroup")
<< "Invalid membership assignment. Group '" << group_name << "' does not exist."; << "Invalid membership assignment. Group '" << group_name << "' does not exist.";
return false; return false;
} }
/* assign host group membership */ /* assign host group membership */
group->ResolveGroupMembership(host, true); groupObject->ResolveGroupMembership(host, true);
return true; return true;
} }
void HostGroup::EvaluateObjectRule(const ObjectRule& rule) void HostGroup::EvaluateObjectRules(const Host::Ptr& host)
{ {
BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) { CONTEXT("Evaluating group memberships for host '" + host->GetName() + "'");
CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for host '" + host->GetName() + "'");
EvaluateObjectRuleOne(host, rule); BOOST_FOREACH(const ConfigItem::Ptr& group, ConfigItem::GetItems("HostGroup"))
{
if (!group->GetFilter())
continue;
EvaluateObjectRule(host, group);
} }
} }
void HostGroup::EvaluateObjectRules(const std::vector<ObjectRule>& rules)
{
ParallelWorkQueue upq;
BOOST_FOREACH(const ObjectRule& rule, rules) {
upq.Enqueue(boost::bind(HostGroup::EvaluateObjectRule, boost::cref(rule)));
}
upq.Join();
}
std::set<Host::Ptr> HostGroup::GetMembers(void) const std::set<Host::Ptr> HostGroup::GetMembers(void) const
{ {
boost::mutex::scoped_lock lock(m_HostGroupMutex); boost::mutex::scoped_lock lock(m_HostGroupMutex);

View File

@ -27,7 +27,7 @@
namespace icinga namespace icinga
{ {
class ObjectRule; class ConfigItem;
/** /**
* An Icinga host group. * An Icinga host group.
@ -48,13 +48,13 @@ public:
static void RegisterObjectRuleHandler(void); static void RegisterObjectRuleHandler(void);
static void EvaluateObjectRules(const Host::Ptr& host);
private: private:
mutable boost::mutex m_HostGroupMutex; mutable boost::mutex m_HostGroupMutex;
std::set<Host::Ptr> m_Members; std::set<Host::Ptr> m_Members;
static bool EvaluateObjectRuleOne(const Host::Ptr& host, const ObjectRule& rule); static bool EvaluateObjectRule(const Host::Ptr& host, const intrusive_ptr<ConfigItem>& item);
static void EvaluateObjectRule(const ObjectRule& rule);
static void EvaluateObjectRules(const std::vector<ObjectRule>& rules);
}; };
} }

View File

@ -39,10 +39,10 @@ void Notification::RegisterApplyRuleHandler(void)
std::vector<String> targets; std::vector<String> targets;
targets.push_back("Host"); targets.push_back("Host");
targets.push_back("Service"); 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(); 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(); DebugInfo di = rule.GetDebugInfo();
@ -122,7 +122,7 @@ bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const A
name += instance; name += instance;
} }
EvaluateApplyRuleOneInstance(checkable, name, locals, rule); EvaluateApplyRuleInstance(checkable, name, locals, rule);
} }
} else if (vinstances.IsObjectType<Dictionary>()) { } else if (vinstances.IsObjectType<Dictionary>()) {
if (rule.GetFVVar().IsEmpty()) 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.GetFKVar(), kv.first);
locals->Set(rule.GetFVVar(), kv.second); locals->Set(rule.GetFVVar(), kv.second);
EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule); EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule);
} }
} }
return true; return true;
} }
void Notification::EvaluateApplyRule(const ApplyRule& rule) void Notification::EvaluateApplyRules(const Host::Ptr& host)
{ {
int apply_count = 0; CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
if (rule.GetTargetType() == "Host") { BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Notification"))
apply_count = 0; {
if (rule.GetTargetType() != "Host")
continue;
BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) { try {
CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); if (EvaluateApplyRule(host, rule))
rule.AddMatch();
try { } catch (const ConfigError& ex) {
if (EvaluateApplyRuleOne(host, rule)) const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
apply_count++; ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
} catch (const ConfigError& ex) {
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(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<Service>()) {
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<errinfo_debuginfo>(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<ApplyRule>& rules)
void Notification::EvaluateApplyRules(const Service::Ptr& service)
{ {
ParallelWorkQueue upq; CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'");
BOOST_FOREACH(const ApplyRule& rule, rules) { BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Notification"))
upq.Enqueue(boost::bind(&Notification::EvaluateApplyRule, boost::cref(rule))); {
if (rule.GetTargetType() != "Service")
continue;
try {
if (EvaluateApplyRule(service, rule))
rule.AddMatch();
} catch (const ConfigError& ex) {
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
}
} }
upq.Join();
} }

View File

@ -68,6 +68,8 @@ enum NotificationType
class NotificationCommand; class NotificationCommand;
class Checkable; class Checkable;
class ApplyRule; class ApplyRule;
class Host;
class Service;
/** /**
* An Icinga notification specification. * An Icinga notification specification.
@ -108,6 +110,9 @@ public:
static void ValidateFilters(const String& location, const Notification::Ptr& object); static void ValidateFilters(const String& location, const Notification::Ptr& object);
static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
protected: protected:
virtual void OnConfigLoaded(void); virtual void OnConfigLoaded(void);
virtual void Start(void); virtual void Start(void);
@ -116,10 +121,8 @@ protected:
private: private:
void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = ""); 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>& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); static void EvaluateApplyRuleInstance(const intrusive_ptr<Checkable>& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
static bool EvaluateApplyRuleOne(const intrusive_ptr<Checkable>& checkable, const ApplyRule& rule); static bool EvaluateApplyRule(const intrusive_ptr<Checkable>& checkable, const ApplyRule& rule);
static void EvaluateApplyRule(const ApplyRule& rule);
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
}; };
I2_ICINGA_API int ServiceStateToFilter(ServiceState state); I2_ICINGA_API int ServiceStateToFilter(ServiceState state);

View File

@ -38,10 +38,10 @@ void ScheduledDowntime::RegisterApplyRuleHandler(void)
std::vector<String> targets; std::vector<String> targets;
targets.push_back("Host"); targets.push_back("Host");
targets.push_back("Service"); 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(); DebugInfo di = rule.GetDebugInfo();
@ -75,7 +75,7 @@ void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& check
dobj->OnConfigLoaded(); 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(); DebugInfo di = rule.GetDebugInfo();
@ -121,7 +121,7 @@ bool ScheduledDowntime::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, co
name += instance; name += instance;
} }
EvaluateApplyRuleOneInstance(checkable, name, locals, rule); EvaluateApplyRuleInstance(checkable, name, locals, rule);
} }
} else if (vinstances.IsObjectType<Dictionary>()) { } else if (vinstances.IsObjectType<Dictionary>()) {
if (rule.GetFVVar().IsEmpty()) 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.GetFKVar(), kv.first);
locals->Set(rule.GetFVVar(), kv.second); locals->Set(rule.GetFVVar(), kv.second);
EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule); EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule);
} }
} }
return true; return true;
} }
void ScheduledDowntime::EvaluateApplyRule(const ApplyRule& rule) void ScheduledDowntime::EvaluateApplyRules(const Host::Ptr& host)
{ {
int apply_count = 0; CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
if (rule.GetTargetType() == "Host") { BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("ScheduledDowntime"))
apply_count = 0; {
if (rule.GetTargetType() != "Host")
continue;
BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) { try {
CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); if (EvaluateApplyRule(host, rule))
rule.AddMatch();
try { } catch (const ConfigError& ex) {
if (EvaluateApplyRuleOne(host, rule)) const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
apply_count++; ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
} catch (const ConfigError& ex) {
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(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<Service>()) {
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<errinfo_debuginfo>(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<ApplyRule>& rules) void ScheduledDowntime::EvaluateApplyRules(const Service::Ptr& service)
{ {
ParallelWorkQueue upq; CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'");
BOOST_FOREACH(const ApplyRule& rule, rules) { BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("ScheduledDowntime"))
upq.Enqueue(boost::bind(&ScheduledDowntime::EvaluateApplyRule, boost::cref(rule))); {
if (rule.GetTargetType() != "Service")
continue;
try {
if (EvaluateApplyRule(service, rule))
rule.AddMatch();
} catch (const ConfigError& ex) {
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
}
} }
upq.Join();
} }

View File

@ -29,6 +29,8 @@ namespace icinga
{ {
class ApplyRule; class ApplyRule;
class Host;
class Service;
/** /**
* An Icinga scheduled downtime specification. * An Icinga scheduled downtime specification.
@ -47,6 +49,9 @@ public:
static void RegisterApplyRuleHandler(void); static void RegisterApplyRuleHandler(void);
static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
protected: protected:
virtual void Start(void); virtual void Start(void);
@ -56,10 +61,8 @@ private:
std::pair<double, double> FindNextSegment(void); std::pair<double, double> FindNextSegment(void);
void CreateNextDowntime(void); void CreateNextDowntime(void);
static void EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); static void EvaluateApplyRuleInstance(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 bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule);
static void EvaluateApplyRule(const ApplyRule& rule);
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
}; };
} }

View File

@ -37,10 +37,10 @@ void Service::RegisterApplyRuleHandler(void)
{ {
std::vector<String> targets; std::vector<String> targets;
targets.push_back("Host"); 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(); DebugInfo di = rule.GetDebugInfo();
@ -68,7 +68,7 @@ void Service::EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String&
dobj->OnConfigLoaded(); 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(); DebugInfo di = rule.GetDebugInfo();
@ -108,7 +108,7 @@ bool Service::EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule)
name += instance; name += instance;
} }
EvaluateApplyRuleOneInstance(host, name, locals, rule); EvaluateApplyRuleInstance(host, name, locals, rule);
} }
} else if (vinstances.IsObjectType<Dictionary>()) { } else if (vinstances.IsObjectType<Dictionary>()) {
if (rule.GetFVVar().IsEmpty()) 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.GetFKVar(), kv.first);
locals->Set(rule.GetFVVar(), kv.second); locals->Set(rule.GetFVVar(), kv.second);
EvaluateApplyRuleOneInstance(host, rule.GetName() + kv.first, locals, rule); EvaluateApplyRuleInstance(host, rule.GetName() + kv.first, locals, rule);
} }
} }
return true; return true;
} }
void Service::EvaluateApplyRule(const ApplyRule& rule) void Service::EvaluateApplyRules(const Host::Ptr& host)
{ {
int apply_count = 0; BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Service")) {
BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) {
CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
try { try {
if (EvaluateApplyRuleOne(host, rule)) if (EvaluateApplyRule(host, rule))
apply_count++; rule.AddMatch();
} catch (const ConfigError& ex) { } catch (const ConfigError& ex) {
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex); const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); 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<ApplyRule>& rules)
{
ParallelWorkQueue upq;
BOOST_FOREACH(const ApplyRule& rule, rules) {
upq.Enqueue(boost::bind(&Service::EvaluateApplyRule, boost::cref(rule)));
}
upq.Join();
} }

View File

@ -19,6 +19,7 @@
#include "icinga/service.hpp" #include "icinga/service.hpp"
#include "icinga/servicegroup.hpp" #include "icinga/servicegroup.hpp"
#include "icinga/scheduleddowntime.hpp"
#include "icinga/pluginutility.hpp" #include "icinga/pluginutility.hpp"
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
#include "base/convert.hpp" #include "base/convert.hpp"
@ -65,6 +66,11 @@ void Service::OnConfigLoaded(void)
SetSchedulingOffset(Utility::Random()); SetSchedulingOffset(Utility::Random());
Checkable::OnConfigLoaded(); Checkable::OnConfigLoaded();
ServiceGroup::EvaluateObjectRules(this);
ScheduledDowntime::EvaluateApplyRules(this);
Notification::EvaluateApplyRules(this);
Dependency::EvaluateApplyRules(this);
} }
Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName) Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName)

View File

@ -53,16 +53,16 @@ public:
static void RegisterApplyRuleHandler(void); static void RegisterApplyRuleHandler(void);
static void EvaluateApplyRules(const Host::Ptr& host);
protected: protected:
virtual void OnConfigLoaded(void); virtual void OnConfigLoaded(void);
private: private:
Host::Ptr m_Host; Host::Ptr m_Host;
static void EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); static void EvaluateApplyRuleInstance(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 bool EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule);
static void EvaluateApplyRule(const ApplyRule& rule);
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
}; };
I2_ICINGA_API boost::tuple<Host::Ptr, Service::Ptr> GetHostService(const Checkable::Ptr& checkable); I2_ICINGA_API boost::tuple<Host::Ptr, Service::Ptr> GetHostService(const Checkable::Ptr& checkable);

View File

@ -19,6 +19,7 @@
#include "icinga/servicegroup.hpp" #include "icinga/servicegroup.hpp"
#include "config/objectrule.hpp" #include "config/objectrule.hpp"
#include "config/configitem.hpp"
#include "base/dynamictype.hpp" #include "base/dynamictype.hpp"
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
#include "base/logger.hpp" #include "base/logger.hpp"
@ -34,65 +35,55 @@ INITIALIZE_ONCE(&ServiceGroup::RegisterObjectRuleHandler);
void ServiceGroup::RegisterObjectRuleHandler(void) 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; CONTEXT("Evaluating rule for group '" + group_name + "'");
msgbuf << "Evaluating 'object' rule (" << di << ")";
CONTEXT(msgbuf.str());
Host::Ptr host = service->GetHost(); Host::Ptr host = service->GetHost();
Dictionary::Ptr locals = new Dictionary(); Dictionary::Ptr locals = new Dictionary();
locals->Set("__parent", rule.GetScope()); locals->Set("__parent", group->GetScope());
locals->Set("host", host); locals->Set("host", host);
locals->Set("service", service); locals->Set("service", service);
if (!rule.EvaluateFilter(locals)) if (!group->GetFilter()->Evaluate(locals))
return false; return false;
Log(LogDebug, "ServiceGroup") 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 groupObject = ServiceGroup::GetByName(group_name);
ServiceGroup::Ptr group = ServiceGroup::GetByName(group_name);
if (!group) { if (!groupObject) {
Log(LogCritical, "ServiceGroup") Log(LogCritical, "ServiceGroup")
<< "Invalid membership assignment. Group '" << group_name << "' does not exist."; << "Invalid membership assignment. Group '" << group_name << "' does not exist.";
return false; return false;
} }
/* assign service group membership */ /* assign service group membership */
group->ResolveGroupMembership(service, true); groupObject->ResolveGroupMembership(service, true);
return true; return true;
} }
void ServiceGroup::EvaluateObjectRule(const ObjectRule& rule) void ServiceGroup::EvaluateObjectRules(const Service::Ptr& service)
{ {
BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType<Service>()) { CONTEXT("Evaluating group membership for service '" + service->GetName() + "'");
CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for service '" + service->GetName() + "'");
EvaluateObjectRuleOne(service, rule); BOOST_FOREACH(const ConfigItem::Ptr& group, ConfigItem::GetItems("ServiceGroup"))
{
if (!group->GetFilter())
continue;
EvaluateObjectRule(service, group);
} }
} }
void ServiceGroup::EvaluateObjectRules(const std::vector<ObjectRule>& rules)
{
ParallelWorkQueue upq;
BOOST_FOREACH(const ObjectRule& rule, rules) {
upq.Enqueue(boost::bind(ServiceGroup::EvaluateObjectRule, boost::cref(rule)));
}
upq.Join();
}
std::set<Service::Ptr> ServiceGroup::GetMembers(void) const std::set<Service::Ptr> ServiceGroup::GetMembers(void) const
{ {
boost::mutex::scoped_lock lock(m_ServiceGroupMutex); boost::mutex::scoped_lock lock(m_ServiceGroupMutex);

View File

@ -27,7 +27,7 @@
namespace icinga namespace icinga
{ {
class ObjectRule; class ConfigItem;
/** /**
* An Icinga service group. * An Icinga service group.
@ -48,13 +48,13 @@ public:
static void RegisterObjectRuleHandler(void); static void RegisterObjectRuleHandler(void);
static void EvaluateObjectRules(const Service::Ptr& service);
private: private:
mutable boost::mutex m_ServiceGroupMutex; mutable boost::mutex m_ServiceGroupMutex;
std::set<Service::Ptr> m_Members; std::set<Service::Ptr> m_Members;
static bool EvaluateObjectRuleOne(const Service::Ptr& service, const ObjectRule& rule); static bool EvaluateObjectRule(const Service::Ptr& service, const intrusive_ptr<ConfigItem>& group);
static void EvaluateObjectRule(const ObjectRule& rule);
static void EvaluateObjectRules(const std::vector<ObjectRule>& rules);
}; };
} }

View File

@ -18,6 +18,7 @@
******************************************************************************/ ******************************************************************************/
#include "icinga/user.hpp" #include "icinga/user.hpp"
#include "icinga/usergroup.hpp"
#include "icinga/notification.hpp" #include "icinga/notification.hpp"
#include "icinga/usergroup.hpp" #include "icinga/usergroup.hpp"
#include "config/configcompilercontext.hpp" #include "config/configcompilercontext.hpp"
@ -51,6 +52,8 @@ void User::OnConfigLoaded(void)
ug->ResolveGroupMembership(this, true); ug->ResolveGroupMembership(this, true);
} }
} }
UserGroup::EvaluateObjectRules(this);
} }
void User::Stop(void) void User::Stop(void)

View File

@ -19,6 +19,7 @@
#include "icinga/usergroup.hpp" #include "icinga/usergroup.hpp"
#include "config/objectrule.hpp" #include "config/objectrule.hpp"
#include "config/configitem.hpp"
#include "base/dynamictype.hpp" #include "base/dynamictype.hpp"
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
#include "base/logger.hpp" #include "base/logger.hpp"
@ -34,62 +35,52 @@ INITIALIZE_ONCE(&UserGroup::RegisterObjectRuleHandler);
void UserGroup::RegisterObjectRuleHandler(void) 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; CONTEXT("Evaluating rule for group '" + group_name + "'");
msgbuf << "Evaluating 'object' rule (" << di << ")";
CONTEXT(msgbuf.str());
Dictionary::Ptr locals = new Dictionary(); Dictionary::Ptr locals = new Dictionary();
locals->Set("__parent", rule.GetScope()); locals->Set("__parent", group->GetScope());
locals->Set("user", user); locals->Set("user", user);
if (!rule.EvaluateFilter(locals)) if (!group->GetFilter()->Evaluate(locals))
return false; return false;
Log(LogDebug, "UserGroup") 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 groupObject = UserGroup::GetByName(group_name);
UserGroup::Ptr group = UserGroup::GetByName(group_name);
if (!group) { if (!groupObject) {
Log(LogCritical, "UserGroup") Log(LogCritical, "UserGroup")
<< "Invalid membership assignment. Group '" << group_name << "' does not exist."; << "Invalid membership assignment. Group '" << group_name << "' does not exist.";
return false; return false;
} }
/* assign user group membership */ /* assign user group membership */
group->ResolveGroupMembership(user, true); groupObject->ResolveGroupMembership(user, true);
return true; return true;
} }
void UserGroup::EvaluateObjectRule(const ObjectRule& rule) void UserGroup::EvaluateObjectRules(const User::Ptr& user)
{ {
BOOST_FOREACH(const User::Ptr& user, DynamicType::GetObjectsByType<User>()) { CONTEXT("Evaluating group membership for user '" + user->GetName() + "'");
CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for user '" + user->GetName() + "'");
EvaluateObjectRuleOne(user, rule); BOOST_FOREACH(const ConfigItem::Ptr& group, ConfigItem::GetItems("UserGroup"))
{
if (!group->GetFilter())
continue;
EvaluateObjectRule(user, group);
} }
} }
void UserGroup::EvaluateObjectRules(const std::vector<ObjectRule>& rules)
{
ParallelWorkQueue upq;
BOOST_FOREACH(const ObjectRule& rule, rules) {
upq.Enqueue(boost::bind(UserGroup::EvaluateObjectRule, boost::cref(rule)));
}
upq.Join();
}
std::set<User::Ptr> UserGroup::GetMembers(void) const std::set<User::Ptr> UserGroup::GetMembers(void) const
{ {
boost::mutex::scoped_lock lock(m_UserGroupMutex); boost::mutex::scoped_lock lock(m_UserGroupMutex);

View File

@ -27,7 +27,7 @@
namespace icinga namespace icinga
{ {
class ObjectRule; class ConfigItem;
/** /**
* An Icinga user group. * An Icinga user group.
@ -48,13 +48,13 @@ public:
static void RegisterObjectRuleHandler(void); static void RegisterObjectRuleHandler(void);
static void EvaluateObjectRules(const User::Ptr& user);
private: private:
mutable boost::mutex m_UserGroupMutex; mutable boost::mutex m_UserGroupMutex;
std::set<User::Ptr> m_Members; std::set<User::Ptr> m_Members;
static bool EvaluateObjectRuleOne(const User::Ptr& user, const ObjectRule& rule); static bool EvaluateObjectRule(const User::Ptr& user, const intrusive_ptr<ConfigItem>& group);
static void EvaluateObjectRule(const ObjectRule& rule);
static void EvaluateObjectRules(const std::vector<ObjectRule>& rules);
}; };
} }