diff --git a/doc/4.1-configuration-syntax.md b/doc/4.1-configuration-syntax.md
index 0a4bfd611..b6a541e64 100644
--- a/doc/4.1-configuration-syntax.md
+++ b/doc/4.1-configuration-syntax.md
@@ -396,6 +396,29 @@ Any valid config attribute can be accessed using the `host` and `service`
variables. For example, `host.address` would return the value of the host's
"address" attribute - or null if that attribute isn't set.
+### Group Assign
+
+Group objects can be assigned to specific member objects using the `assign where`
+and `ignore where` conditions.
+
+ object HostGroup "linux-servers" {
+ display_name = "Linux Servers"
+
+ assign where host.vars.os == "linux"
+ }
+
+In this example the `assign where` condition is a boolean expression which is evaluated
+for all objects of the type `Host`. Each matching host is added as member to the host group
+with the name "linux-servers". Membership exclusion can be controlled using the `ignore where`
+condition.
+
+Source Type | Variables
+------------------|--------------
+HostGroup | host
+ServiceGroup | host, service
+UserGroup | user
+
+
### Boolean Values
The `assign where` and `ignore where` statements, the `!`, `&&` and `||`
diff --git a/etc/icinga2/conf.d/generic-host.conf b/etc/icinga2/conf.d/generic-host.conf
index cd61eff9f..f0740b636 100644
--- a/etc/icinga2/conf.d/generic-host.conf
+++ b/etc/icinga2/conf.d/generic-host.conf
@@ -3,6 +3,10 @@
* all hosts should import this template.
*/
template Host "generic-host" {
+ max_check_attempts = 5
+ check_interval = 5m
+ retry_interval = 1m
+
check_command = "hostalive"
}
@@ -31,23 +35,3 @@ apply Notification "mail-icingaadmin" to Host {
assign where "generic-host" in host.templates
}
-
-template Host "linux-server" {
- import "generic-host"
-
- groups += [ "linux-servers" ]
-}
-
-template Host "windows-server" {
- import "generic-host"
-
- groups += [ "windows-servers" ]
-}
-
-template Host "generic-printer" {
- import "generic-host"
-}
-
-template Host "generic-switch" {
- import "generic-host"
-}
diff --git a/etc/icinga2/conf.d/generic-service.conf b/etc/icinga2/conf.d/generic-service.conf
index 3912ab8f3..332216b1a 100644
--- a/etc/icinga2/conf.d/generic-service.conf
+++ b/etc/icinga2/conf.d/generic-service.conf
@@ -6,7 +6,6 @@ template Service "generic-service" {
max_check_attempts = 3
check_interval = 5m
retry_interval = 1m
- enable_perfdata = true
}
apply Notification "mail-icingaadmin" to Service {
diff --git a/etc/icinga2/conf.d/groups.conf b/etc/icinga2/conf.d/groups.conf
index 9bdc96256..94618eac9 100644
--- a/etc/icinga2/conf.d/groups.conf
+++ b/etc/icinga2/conf.d/groups.conf
@@ -1,11 +1,37 @@
/**
- * Host and service group examples.
+ * Host group examples.
*/
object HostGroup "linux-servers" {
display_name = "Linux Servers"
+
+ assign where host.vars.os == "Linux"
}
object HostGroup "windows-servers" {
display_name = "Windows Servers"
+
+ assign where host.vars.os == "Windows"
+}
+
+/**
+ * Service group examples.
+ */
+
+object ServiceGroup "ping" {
+ display_name = "Ping Checks"
+
+ assign where match("ping*", service.name)
+}
+
+object ServiceGroup "http" {
+ display_name = "HTTP Checks"
+
+ assign where match("http_*", service.check_command)
+}
+
+object ServiceGroup "disk" {
+ display_name = "Disk Checks"
+
+ assign where service.check_command == "disk"
}
diff --git a/etc/icinga2/conf.d/hosts/localhost.conf b/etc/icinga2/conf.d/hosts/localhost.conf
index 49e192606..7005d9ccf 100644
--- a/etc/icinga2/conf.d/hosts/localhost.conf
+++ b/etc/icinga2/conf.d/hosts/localhost.conf
@@ -4,8 +4,10 @@
* files in this directory are included.
*/
object Host "localhost" {
- import "linux-server"
+ import "generic-host"
address = "127.0.0.1"
address6 = "::1"
+
+ vars.os = "Linux"
}
diff --git a/lib/config/CMakeLists.txt b/lib/config/CMakeLists.txt
index 05f9990b0..30dafd5a2 100644
--- a/lib/config/CMakeLists.txt
+++ b/lib/config/CMakeLists.txt
@@ -30,7 +30,7 @@ add_library(config SHARED
aexpression.cpp applyrule.cpp base-type.conf base-type.cpp
configcompilercontext.cpp configcompiler.cpp configerror.cpp configitembuilder.cpp
configitem.cpp ${FLEX_config_lexer_OUTPUTS} ${BISON_config_parser_OUTPUTS}
- configtype.cpp debuginfo.cpp typerule.cpp typerulelist.cpp
+ configtype.cpp debuginfo.cpp objectrule.cpp typerule.cpp typerulelist.cpp
)
target_link_libraries(config ${Boost_LIBRARIES} base)
diff --git a/lib/config/aexpression.cpp b/lib/config/aexpression.cpp
index d557e2290..81ba0290f 100644
--- a/lib/config/aexpression.cpp
+++ b/lib/config/aexpression.cpp
@@ -22,6 +22,7 @@
#include "config/configitem.h"
#include "config/configitembuilder.h"
#include "config/applyrule.h"
+#include "config/objectrule.h"
#include "base/array.h"
#include "base/serializer.h"
#include "base/context.h"
@@ -521,6 +522,7 @@ Value AExpression::OpObject(const AExpression* expr, const Dictionary::Ptr& loca
bool abstract = left->Get(0);
String type = left->Get(1);
AExpression::Ptr aname = left->Get(2);
+ AExpression::Ptr filter = left->Get(3);
String name = aname->Evaluate(locals);
@@ -560,5 +562,7 @@ Value AExpression::OpObject(const AExpression* expr, const Dictionary::Ptr& loca
item->SetScope(locals);
item->Compile()->Register();
+ ObjectRule::AddRule(type, name, exprl, filter, expr->m_DebugInfo, locals);
+
return Empty;
}
diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy
index fe3e01eda..841105eb7 100644
--- a/lib/config/config_parser.yy
+++ b/lib/config/config_parser.yy
@@ -29,6 +29,7 @@
#include "config/typerulelist.h"
#include "config/aexpression.h"
#include "config/applyrule.h"
+#include "config/objectrule.h"
#include "base/value.h"
#include "base/utility.h"
#include "base/array.h"
@@ -214,6 +215,7 @@ static ConfigType::Ptr m_Type;
static Dictionary::Ptr m_ModuleScope;
static bool m_Apply;
+static bool m_ObjectAssign;
static bool m_SeenAssign;
static AExpression::Ptr m_Assign;
static AExpression::Ptr m_Ignore;
@@ -426,14 +428,21 @@ type: T_TYPE_DICTIONARY
object:
{
m_Abstract = false;
+ m_ObjectAssign = true;
+ m_SeenAssign = false;
+ m_Assign = make_shared(&AExpression::OpLiteral, false, DebugInfo());
+ m_Ignore = make_shared(&AExpression::OpLiteral, false, DebugInfo());
}
object_declaration identifier rterm rterm_scope sep
{
+ m_ObjectAssign = false;
+
Array::Ptr args = make_shared();
args->Add(m_Abstract);
- args->Add($3);
+ String type = $3;
+ args->Add(type);
free($3);
args->Add(*$4);
@@ -443,7 +452,18 @@ object:
delete $5;
exprl->MakeInline();
+ if (m_SeenAssign && !ObjectRule::IsValidSourceType(type))
+ BOOST_THROW_EXCEPTION(ConfigError("object rule 'assign' cannot be used for type '" + type + "'") << errinfo_debuginfo(DebugInfoRange(@2, @3)));
+
+ AExpression::Ptr rex = make_shared(&AExpression::OpLogicalNegate, m_Ignore, DebugInfoRange(@2, @5));
+ AExpression::Ptr filter = make_shared(&AExpression::OpLogicalAnd, m_Assign, rex, DebugInfoRange(@2, @5));
+
+ args->Add(filter);
+
$$ = new Value(make_shared(&AExpression::OpObject, args, exprl, DebugInfoRange(@2, @5)));
+
+ m_Assign.reset();
+ m_Ignore.reset();
}
;
@@ -573,7 +593,7 @@ lterm: identifier lbinary_op rterm
}
| T_ASSIGN T_WHERE rterm
{
- if (!m_Apply)
+ if (!(m_Apply || m_ObjectAssign))
BOOST_THROW_EXCEPTION(ConfigError("'assign' keyword not valid in this context."));
m_SeenAssign = true;
@@ -585,7 +605,7 @@ lterm: identifier lbinary_op rterm
}
| T_IGNORE T_WHERE rterm
{
- if (!m_Apply)
+ if (!(m_Apply || m_ObjectAssign))
BOOST_THROW_EXCEPTION(ConfigError("'ignore' keyword not valid in this context."));
m_Ignore = make_shared(&AExpression::OpLogicalOr, m_Ignore, *$3, DebugInfoRange(@1, @3));
diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp
index 9b976383c..c1fb97e72 100644
--- a/lib/config/configitem.cpp
+++ b/lib/config/configitem.cpp
@@ -20,6 +20,7 @@
#include "config/configitem.h"
#include "config/configcompilercontext.h"
#include "config/applyrule.h"
+#include "config/objectrule.h"
#include "base/application.h"
#include "base/dynamictype.h"
#include "base/objectlock.h"
@@ -324,6 +325,9 @@ bool ConfigItem::ActivateItems(ValidationType validate)
Log(LogInformation, "config", "Evaluating 'apply' rules...");
ApplyRule::EvaluateRules();
+ Log(LogInformation, "config", "Evaluating 'object' rules...");
+ ObjectRule::EvaluateRules();
+
if (validate != ValidateNone) {
Log(LogInformation, "config", "Validating config items (step 2)...");
diff --git a/lib/config/objectrule.cpp b/lib/config/objectrule.cpp
new file mode 100644
index 000000000..5c580e89d
--- /dev/null
+++ b/lib/config/objectrule.cpp
@@ -0,0 +1,99 @@
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-present Icinga Development Team (http://www.icinga.org) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "config/objectrule.h"
+#include "base/logger_fwd.h"
+
+using namespace icinga;
+
+ObjectRule::RuleMap ObjectRule::m_Rules;
+ObjectRule::CallbackMap ObjectRule::m_Callbacks;
+
+ObjectRule::ObjectRule(const String& name, const AExpression::Ptr& expression,
+ const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope)
+ : m_Name(name), m_Expression(expression), m_Filter(filter), m_DebugInfo(di), m_Scope(scope)
+{ }
+
+String ObjectRule::GetName(void) const
+{
+ return m_Name;
+}
+
+AExpression::Ptr ObjectRule::GetExpression(void) const
+{
+ return m_Expression;
+}
+
+AExpression::Ptr ObjectRule::GetFilter(void) const
+{
+ return m_Filter;
+}
+
+DebugInfo ObjectRule::GetDebugInfo(void) const
+{
+ return m_DebugInfo;
+}
+
+Dictionary::Ptr ObjectRule::GetScope(void) const
+{
+ return m_Scope;
+}
+
+void ObjectRule::AddRule(const String& sourceType, const String& name,
+ const AExpression::Ptr& expression, const AExpression::Ptr& filter,
+ const DebugInfo& di, const Dictionary::Ptr& scope)
+{
+ m_Rules[sourceType].push_back(ObjectRule(name, expression, filter, di, scope));
+}
+
+bool ObjectRule::EvaluateFilter(const Dictionary::Ptr& scope) const
+{
+ scope->Set("__parent", m_Scope);
+ bool result = m_Filter->Evaluate(scope);
+ scope->Remove("__parent");
+ return result;
+}
+
+void ObjectRule::EvaluateRules(void)
+{
+ 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);
+ }
+
+ m_Rules.clear();
+}
+
+void ObjectRule::RegisterType(const String& sourceType, const ObjectRule::Callback& callback)
+{
+ m_Callbacks[sourceType] = callback;
+}
+
+bool ObjectRule::IsValidSourceType(const String& sourceType)
+{
+ return m_Callbacks.find(sourceType) != m_Callbacks.end();
+}
+
diff --git a/lib/config/objectrule.h b/lib/config/objectrule.h
new file mode 100644
index 000000000..c0c9a3650
--- /dev/null
+++ b/lib/config/objectrule.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-present Icinga Development Team (http://www.icinga.org) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#ifndef OBJECTRULE_H
+#define OBJECTRULE_H
+
+#include "config/i2-config.h"
+#include "config/aexpression.h"
+#include "config/debuginfo.h"
+#include "base/dynamictype.h"
+
+namespace icinga
+{
+
+/**
+ * @ingroup config
+ */
+class I2_CONFIG_API ObjectRule
+{
+public:
+ typedef boost::function& rules)> Callback;
+ typedef std::map CallbackMap;
+ typedef std::map > RuleMap;
+
+ String GetName(void) const;
+ AExpression::Ptr GetExpression(void) const;
+ AExpression::Ptr GetFilter(void) const;
+ DebugInfo GetDebugInfo(void) const;
+ Dictionary::Ptr GetScope(void) const;
+
+ bool EvaluateFilter(const Dictionary::Ptr& scope) const;
+
+ static void AddRule(const String& sourceType, const String& name, const AExpression::Ptr& expression,
+ const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope);
+ static void EvaluateRules(void);
+
+ static void RegisterType(const String& sourceType, const ObjectRule::Callback& callback);
+ static bool IsValidSourceType(const String& sourceType);
+
+private:
+ String m_Name;
+ AExpression::Ptr m_Expression;
+ AExpression::Ptr m_Filter;
+ DebugInfo m_DebugInfo;
+ Dictionary::Ptr m_Scope;
+
+ static CallbackMap m_Callbacks;
+ static RuleMap m_Rules;
+
+ ObjectRule(const String& name, const AExpression::Ptr& expression,
+ const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope);
+};
+
+}
+
+#endif /* OBJECTRULE_H */
diff --git a/lib/icinga/hostgroup.cpp b/lib/icinga/hostgroup.cpp
index d24e18dab..cc6d2ac6e 100644
--- a/lib/icinga/hostgroup.cpp
+++ b/lib/icinga/hostgroup.cpp
@@ -23,12 +23,63 @@
#include "base/objectlock.h"
#include "base/utility.h"
#include "base/timer.h"
+#include "base/context.h"
#include
using namespace icinga;
REGISTER_TYPE(HostGroup);
+INITIALIZE_ONCE(&HostGroup::RegisterObjectRuleHandler);
+
+void HostGroup::RegisterObjectRuleHandler(void)
+{
+ ObjectRule::RegisterType("HostGroup", &HostGroup::EvaluateObjectRules);
+}
+
+bool HostGroup::EvaluateObjectRule(const Host::Ptr host, const ObjectRule& rule)
+{
+ DebugInfo di = rule.GetDebugInfo();
+
+ std::ostringstream msgbuf;
+ msgbuf << "Evaluating 'object' rule (" << di << ")";
+ CONTEXT(msgbuf.str());
+
+ Dictionary::Ptr locals = make_shared();
+ locals->Set("host", host);
+
+ if (!rule.EvaluateFilter(locals))
+ return false;
+
+ std::ostringstream msgbuf2;
+ msgbuf2 << "Assigning membership for group '" << rule.GetName() << "' to host '" << host->GetName() << "' for rule " << di;
+ Log(LogDebug, "icinga", msgbuf2.str());
+
+ String group_name = rule.GetName();
+ HostGroup::Ptr group = HostGroup::GetByName(group_name);
+
+ if (!group) {
+ Log(LogCritical, "icinga", "Invalid membership assignment. Group '" + group_name + "' does not exist.");
+ return false;
+ }
+
+ /* assign host group membership */
+ group->ResolveGroupMembership(host, true);
+
+ return true;
+}
+
+void HostGroup::EvaluateObjectRules(const std::vector& rules)
+{
+ BOOST_FOREACH(const ObjectRule& rule, rules) {
+ BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjects()) {
+ CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for host '" + host->GetName() + "'");
+
+ EvaluateObjectRule(host, rule);
+ }
+ }
+}
+
std::set HostGroup::GetMembers(void) const
{
boost::mutex::scoped_lock lock(m_HostGroupMutex);
diff --git a/lib/icinga/hostgroup.h b/lib/icinga/hostgroup.h
index c0187c7db..0ce0cbeea 100644
--- a/lib/icinga/hostgroup.h
+++ b/lib/icinga/hostgroup.h
@@ -23,6 +23,7 @@
#include "icinga/i2-icinga.h"
#include "icinga/hostgroup.th"
#include "icinga/host.h"
+#include "config/objectrule.h"
namespace icinga
{
@@ -44,9 +45,14 @@ public:
bool ResolveGroupMembership(Host::Ptr const& host, bool add = true, int rstack = 0);
+ static void RegisterObjectRuleHandler(void);
+
private:
mutable boost::mutex m_HostGroupMutex;
std::set m_Members;
+
+ static bool EvaluateObjectRule(const Host::Ptr host, const ObjectRule& rule);
+ static void EvaluateObjectRules(const std::vector& rules);
};
}
diff --git a/lib/icinga/servicegroup.cpp b/lib/icinga/servicegroup.cpp
index 9cf1b4042..09f82cc43 100644
--- a/lib/icinga/servicegroup.cpp
+++ b/lib/icinga/servicegroup.cpp
@@ -24,12 +24,66 @@
#include "base/logger_fwd.h"
#include "base/timer.h"
#include "base/utility.h"
+#include "base/context.h"
#include
using namespace icinga;
REGISTER_TYPE(ServiceGroup);
+INITIALIZE_ONCE(&ServiceGroup::RegisterObjectRuleHandler);
+
+void ServiceGroup::RegisterObjectRuleHandler(void)
+{
+ ObjectRule::RegisterType("ServiceGroup", &ServiceGroup::EvaluateObjectRules);
+}
+
+bool ServiceGroup::EvaluateObjectRule(const Service::Ptr service, const ObjectRule& rule)
+{
+ DebugInfo di = rule.GetDebugInfo();
+
+ std::ostringstream msgbuf;
+ msgbuf << "Evaluating 'object' rule (" << di << ")";
+ CONTEXT(msgbuf.str());
+
+ Host::Ptr host = service->GetHost();
+
+ Dictionary::Ptr locals = make_shared();
+ locals->Set("host", host);
+ locals->Set("service", service);
+
+ if (!rule.EvaluateFilter(locals))
+ return false;
+
+ std::ostringstream msgbuf2;
+ msgbuf2 << "Assigning membership for group '" << rule.GetName() << "' to service '" << service->GetName() << "' for rule " << di;
+ Log(LogDebug, "icinga", msgbuf2.str());
+
+ String group_name = rule.GetName();
+ ServiceGroup::Ptr group = ServiceGroup::GetByName(group_name);
+
+ if (!group) {
+ Log(LogCritical, "icinga", "Invalid membership assignment. Group '" + group_name + "' does not exist.");
+ return false;
+ }
+
+ /* assign service group membership */
+ group->ResolveGroupMembership(service, true);
+
+ return true;
+}
+
+void ServiceGroup::EvaluateObjectRules(const std::vector& rules)
+{
+ BOOST_FOREACH(const ObjectRule& rule, rules) {
+ BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects()) {
+ CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for service '" + service->GetName() + "'");
+
+ EvaluateObjectRule(service, rule);
+ }
+ }
+}
+
std::set ServiceGroup::GetMembers(void) const
{
boost::mutex::scoped_lock lock(m_ServiceGroupMutex);
diff --git a/lib/icinga/servicegroup.h b/lib/icinga/servicegroup.h
index 7e93ea5eb..580560623 100644
--- a/lib/icinga/servicegroup.h
+++ b/lib/icinga/servicegroup.h
@@ -23,6 +23,7 @@
#include "icinga/i2-icinga.h"
#include "icinga/servicegroup.th"
#include "icinga/service.h"
+#include "config/objectrule.h"
namespace icinga
{
@@ -44,9 +45,14 @@ public:
bool ResolveGroupMembership(Service::Ptr const& service, bool add = true, int rstack = 0);
+ static void RegisterObjectRuleHandler(void);
+
private:
mutable boost::mutex m_ServiceGroupMutex;
std::set m_Members;
+
+ static bool EvaluateObjectRule(const Service::Ptr service, const ObjectRule& rule);
+ static void EvaluateObjectRules(const std::vector& rules);
};
}
diff --git a/lib/icinga/usergroup.cpp b/lib/icinga/usergroup.cpp
index 8ff0a88fb..2ee963709 100644
--- a/lib/icinga/usergroup.cpp
+++ b/lib/icinga/usergroup.cpp
@@ -23,12 +23,63 @@
#include "base/logger_fwd.h"
#include "base/timer.h"
#include "base/utility.h"
+#include "base/context.h"
#include
using namespace icinga;
REGISTER_TYPE(UserGroup);
+INITIALIZE_ONCE(&UserGroup::RegisterObjectRuleHandler);
+
+void UserGroup::RegisterObjectRuleHandler(void)
+{
+ ObjectRule::RegisterType("UserGroup", &UserGroup::EvaluateObjectRules);
+}
+
+bool UserGroup::EvaluateObjectRule(const User::Ptr user, const ObjectRule& rule)
+{
+ DebugInfo di = rule.GetDebugInfo();
+
+ std::ostringstream msgbuf;
+ msgbuf << "Evaluating 'object' rule (" << di << ")";
+ CONTEXT(msgbuf.str());
+
+ Dictionary::Ptr locals = make_shared();
+ locals->Set("user", user);
+
+ if (!rule.EvaluateFilter(locals))
+ return false;
+
+ std::ostringstream msgbuf2;
+ msgbuf2 << "Assigning membership for group '" << rule.GetName() << "' to user '" << user->GetName() << "' for rule " << di;
+ Log(LogDebug, "icinga", msgbuf2.str());
+
+ String group_name = rule.GetName();
+ UserGroup::Ptr group = UserGroup::GetByName(group_name);
+
+ if (!group) {
+ Log(LogCritical, "icinga", "Invalid membership assignment. Group '" + group_name + "' does not exist.");
+ return false;
+ }
+
+ /* assign user group membership */
+ group->ResolveGroupMembership(user, true);
+
+ return true;
+}
+
+void UserGroup::EvaluateObjectRules(const std::vector& rules)
+{
+ BOOST_FOREACH(const ObjectRule& rule, rules) {
+ BOOST_FOREACH(const User::Ptr& user, DynamicType::GetObjects()) {
+ CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for user '" + user->GetName() + "'");
+
+ EvaluateObjectRule(user, rule);
+ }
+ }
+}
+
std::set UserGroup::GetMembers(void) const
{
boost::mutex::scoped_lock lock(m_UserGroupMutex);
diff --git a/lib/icinga/usergroup.h b/lib/icinga/usergroup.h
index 3338c6cda..60870fd4c 100644
--- a/lib/icinga/usergroup.h
+++ b/lib/icinga/usergroup.h
@@ -23,6 +23,7 @@
#include "icinga/i2-icinga.h"
#include "icinga/usergroup.th"
#include "icinga/user.h"
+#include "config/objectrule.h"
namespace icinga
{
@@ -44,9 +45,14 @@ public:
bool ResolveGroupMembership(User::Ptr const& user, bool add = true, int rstack = 0);
+ static void RegisterObjectRuleHandler(void);
+
private:
mutable boost::mutex m_UserGroupMutex;
std::set m_Members;
+
+ static bool EvaluateObjectRule(const User::Ptr user, const ObjectRule& rule);
+ static void EvaluateObjectRules(const std::vector& rules);
};
}