From 5e38c81eb5d28b89ebc8828fa557098b2966d8b1 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 5 Apr 2014 12:56:56 +0200 Subject: [PATCH] Implement apply target types. Fixes #5924 --- etc/icinga2/conf.d/generic-host.conf | 8 ++ etc/icinga2/conf.d/generic-service.conf | 2 +- etc/icinga2/conf.d/localhost.conf | 2 +- lib/config/aexpression.cpp | 7 +- lib/config/applyrule.cpp | 62 ++++++++++++--- lib/config/applyrule.h | 14 ++-- lib/config/config_lexer.ll | 1 + lib/config/config_parser.yy | 48 +++++++++-- lib/icinga/dependency-apply.cpp | 99 +++++++++++++++-------- lib/icinga/dependency.h | 5 +- lib/icinga/notification-apply.cpp | 101 +++++++++++++++--------- lib/icinga/notification.h | 6 +- lib/icinga/scheduleddowntime-apply.cpp | 90 ++++++++++++--------- lib/icinga/scheduleddowntime.h | 6 +- lib/icinga/service-apply.cpp | 80 ++++++++++--------- lib/icinga/service.h | 4 +- 16 files changed, 358 insertions(+), 177 deletions(-) diff --git a/etc/icinga2/conf.d/generic-host.conf b/etc/icinga2/conf.d/generic-host.conf index 87ab00916..060e23572 100644 --- a/etc/icinga2/conf.d/generic-host.conf +++ b/etc/icinga2/conf.d/generic-host.conf @@ -6,6 +6,14 @@ template Host "generic-host" { check_command = "hostalive" } +apply Notification "mail-icingaadmin" to Host { + import "mail-notification" + + user_groups = [ "icingaadmins"] + + assign where "generic-host" in host.templates +} + template Host "linux-server" { import "generic-host" diff --git a/etc/icinga2/conf.d/generic-service.conf b/etc/icinga2/conf.d/generic-service.conf index 02dccc517..811750a82 100644 --- a/etc/icinga2/conf.d/generic-service.conf +++ b/etc/icinga2/conf.d/generic-service.conf @@ -9,7 +9,7 @@ template Service "generic-service" { enable_perfdata = true } -apply Notification "mail-icingaadmin" { +apply Notification "mail-icingaadmin" to Service { import "mail-notification" user_groups = [ "icingaadmins"] diff --git a/etc/icinga2/conf.d/localhost.conf b/etc/icinga2/conf.d/localhost.conf index b2b77f8cb..9a9507f98 100644 --- a/etc/icinga2/conf.d/localhost.conf +++ b/etc/icinga2/conf.d/localhost.conf @@ -42,7 +42,7 @@ apply Service "load" { assign where host.name == "localhost" } -apply ScheduledDowntime "backup-downtime" { +apply ScheduledDowntime "backup-downtime" to Service { import "backup-downtime" assign where host.name == "localhost" && service.name == "load" diff --git a/lib/config/aexpression.cpp b/lib/config/aexpression.cpp index cbecdb4c0..f8c877781 100644 --- a/lib/config/aexpression.cpp +++ b/lib/config/aexpression.cpp @@ -499,12 +499,13 @@ Value AExpression::OpApply(const AExpression* expr, const Dictionary::Ptr& local Array::Ptr left = expr->m_Operand1; AExpression::Ptr exprl = expr->m_Operand2; String type = left->Get(0); - AExpression::Ptr aname = left->Get(1); - AExpression::Ptr filter = left->Get(2); + String target = left->Get(1); + AExpression::Ptr aname = left->Get(2); + AExpression::Ptr filter = left->Get(3); String name = aname->Evaluate(locals); - ApplyRule::AddRule(type, name, exprl, filter, expr->m_DebugInfo, locals); + ApplyRule::AddRule(type, target, name, exprl, filter, expr->m_DebugInfo, locals); return Empty; } diff --git a/lib/config/applyrule.cpp b/lib/config/applyrule.cpp index 1602974a5..bc8851c3f 100644 --- a/lib/config/applyrule.cpp +++ b/lib/config/applyrule.cpp @@ -25,11 +25,16 @@ using namespace icinga; ApplyRule::RuleMap ApplyRule::m_Rules; ApplyRule::CallbackMap ApplyRule::m_Callbacks; -ApplyRule::ApplyRule(const String& name, const AExpression::Ptr& expression, +ApplyRule::ApplyRule(const String& targetType, 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) + : m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_DebugInfo(di), m_Scope(scope) { } +String ApplyRule::GetTargetType(void) const +{ + return m_TargetType; +} + String ApplyRule::GetName(void) const { return m_Name; @@ -55,11 +60,11 @@ Dictionary::Ptr ApplyRule::GetScope(void) const return m_Scope; } -void ApplyRule::AddRule(const String& sourceType, const String& name, +void ApplyRule::AddRule(const String& sourceType, const String& targetType, const String& name, const AExpression::Ptr& expression, const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope) { - m_Rules[sourceType].push_back(ApplyRule(name, expression, filter, di, scope)); + m_Rules[sourceType].push_back(ApplyRule(targetType, name, expression, filter, di, scope)); } bool ApplyRule::EvaluateFilter(const Dictionary::Ptr& scope) const @@ -75,7 +80,7 @@ void ApplyRule::EvaluateRules(void) std::set completedTypes; while (completedTypes.size() < m_Callbacks.size()) { - std::pair > kv; + std::pair > > kv; BOOST_FOREACH(kv, m_Callbacks) { const String& sourceType = kv.first; @@ -83,10 +88,16 @@ void ApplyRule::EvaluateRules(void) continue; const Callback& callback = kv.second.first; - const String& targetType = kv.second.second; + const std::vector& targetTypes = kv.second.second; - if (IsValidType(targetType) && completedTypes.find(targetType) == completedTypes.end()) - continue; + bool cont = false; + + BOOST_FOREACH(const String& targetType, targetTypes) { + if (IsValidSourceType(targetType) && completedTypes.find(targetType) == completedTypes.end()) { + cont = true; + break; + } + } completedTypes.insert(sourceType); @@ -102,12 +113,41 @@ void ApplyRule::EvaluateRules(void) m_Rules.clear(); } -void ApplyRule::RegisterType(const String& sourceType, const String& targetType, const ApplyRule::Callback& callback) +void ApplyRule::RegisterType(const String& sourceType, const std::vector& targetTypes, const ApplyRule::Callback& callback) { - m_Callbacks[sourceType] = make_pair(callback, targetType); + m_Callbacks[sourceType] = make_pair(callback, targetTypes); } -bool ApplyRule::IsValidType(const String& sourceType) +bool ApplyRule::IsValidSourceType(const String& sourceType) { return m_Callbacks.find(sourceType) != m_Callbacks.end(); } + +bool ApplyRule::IsValidTargetType(const String& sourceType, const String& targetType) +{ + CallbackMap::const_iterator it = m_Callbacks.find(sourceType); + + if (it == m_Callbacks.end()) + return false; + + if (it->second.second.size() == 1 && targetType == "") + return true; + + BOOST_FOREACH(const String& type, it->second.second) { + if (type == targetType) + return true; + } + + return false; +} + +std::vector ApplyRule::GetTargetTypes(const String& sourceType) +{ + CallbackMap::const_iterator it = m_Callbacks.find(sourceType); + + if (it == m_Callbacks.end()) + return std::vector(); + + return it->second.second; +} + diff --git a/lib/config/applyrule.h b/lib/config/applyrule.h index 90ebeecdf..10b4970c6 100644 --- a/lib/config/applyrule.h +++ b/lib/config/applyrule.h @@ -35,9 +35,10 @@ class I2_CONFIG_API ApplyRule { public: typedef boost::function& rules)> Callback; - typedef std::map > CallbackMap; + typedef std::map > > CallbackMap; typedef std::map > RuleMap; + String GetTargetType(void) const; String GetName(void) const; AExpression::Ptr GetExpression(void) const; AExpression::Ptr GetFilter(void) const; @@ -46,14 +47,17 @@ public: bool EvaluateFilter(const Dictionary::Ptr& scope) const; - static void AddRule(const String& sourceType, const String& name, const AExpression::Ptr& expression, + static void AddRule(const String& sourceType, const String& targetType, 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 String& targetType, const ApplyRule::Callback& callback); - static bool IsValidType(const String& sourceType); + static void RegisterType(const String& sourceType, const std::vector& targetTypes, const ApplyRule::Callback& callback); + static bool IsValidSourceType(const String& sourceType); + static bool IsValidTargetType(const String& sourceType, const String& targetType); + static std::vector GetTargetTypes(const String& sourceType); private: + String m_TargetType; String m_Name; AExpression::Ptr m_Expression; AExpression::Ptr m_Filter; @@ -63,7 +67,7 @@ private: static CallbackMap m_Callbacks; static RuleMap m_Rules; - ApplyRule(const String& tmpl, const AExpression::Ptr& expression, + ApplyRule(const String& targetType, const String& name, const AExpression::Ptr& expression, const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope); }; diff --git a/lib/config/config_lexer.ll b/lib/config/config_lexer.ll index d00ed6c40..a76968eca 100644 --- a/lib/config/config_lexer.ll +++ b/lib/config/config_lexer.ll @@ -222,6 +222,7 @@ true { yylval->num = 1; return T_NUMBER; } false { yylval->num = 0; return T_NUMBER; } const return T_CONST; apply return T_APPLY; +to return T_TO; where return T_WHERE; import return T_IMPORT; assign return T_ASSIGN; diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy index 7e3f520b6..87ecb942e 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -151,6 +151,7 @@ static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *le %token T_INHERITS "inherits (T_INHERITS)" %token T_PARTIAL "partial (T_PARTIAL)" %token T_APPLY "apply (T_APPLY)" +%token T_TO "to (T_TO)" %token T_WHERE "where (T_WHERE)" %token T_IMPORT "import (T_IMPORT)" %token T_ASSIGN "assign (T_ASSIGN)" @@ -174,6 +175,7 @@ static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *le %type lterm %type object %type apply +%type target_type_specifier %left T_LOGICAL_OR %left T_LOGICAL_AND @@ -792,26 +794,59 @@ rterm: T_STRING } ; +target_type_specifier: /* empty */ + { + $$ = strdup(""); + } + | T_TO identifier + { + $$ = $2; + } + ; + apply: { m_Apply = true; m_Assign = make_shared(&AExpression::OpLiteral, false, DebugInfo()); m_Ignore = make_shared(&AExpression::OpLiteral, false, DebugInfo()); } - T_APPLY identifier rterm rterm + T_APPLY identifier rterm target_type_specifier rterm { m_Apply = false; - AExpression::Ptr aname = static_cast(*$4); - delete $4; String type = $3; free($3); + AExpression::Ptr aname = static_cast(*$4); + delete $4; + String target = $5; + free($5); - if (!ApplyRule::IsValidType(type)) + if (!ApplyRule::IsValidSourceType(type)) BOOST_THROW_EXCEPTION(ConfigError("'apply' cannot be used with type '" + type + "'") << errinfo_debuginfo(DebugInfoRange(@2, @3))); - AExpression::Ptr exprl = static_cast(*$5); - delete $5; + if (!ApplyRule::IsValidTargetType(type, target)) { + if (target == "") { + std::vector types = ApplyRule::GetTargetTypes(type); + String typeNames; + + for (int i = 0; i < types.size(); i++) { + if (typeNames != "") { + if (i == types.size() - 1) + typeNames += " or "; + else + typeNames += ", "; + } + + typeNames += "'" + types[i] + "'"; + } + + BOOST_THROW_EXCEPTION(ConfigError("'apply' target type is ambiguous (can be one of " + typeNames + "): use 'to' to specify a type") << errinfo_debuginfo(DebugInfoRange(@2, @3))); + } else + BOOST_THROW_EXCEPTION(ConfigError("'apply' target type '" + target + "' is invalid") << errinfo_debuginfo(DebugInfoRange(@2, @5))); + } + + AExpression::Ptr exprl = static_cast(*$6); + delete $6; exprl->MakeInline(); @@ -821,6 +856,7 @@ apply: Array::Ptr args = make_shared(); args->Add(type); + args->Add(target); args->Add(aname); args->Add(filter); diff --git a/lib/icinga/dependency-apply.cpp b/lib/icinga/dependency-apply.cpp index 3a6249a47..9be15fe94 100644 --- a/lib/icinga/dependency-apply.cpp +++ b/lib/icinga/dependency-apply.cpp @@ -33,56 +33,85 @@ INITIALIZE_ONCE(&Dependency::RegisterApplyRuleHandler); void Dependency::RegisterApplyRuleHandler(void) { - ApplyRule::RegisterType("Dependency", "Service", &Dependency::EvaluateApplyRules); + std::vector targets; + targets.push_back("Host"); + targets.push_back("Service"); + ApplyRule::RegisterType("Dependency", targets, &Dependency::EvaluateApplyRules); } -void Dependency::EvaluateApplyRules(const std::vector& rules) +void Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule) { - BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects()) { - CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'"); + DebugInfo di = rule.GetDebugInfo(); - Dictionary::Ptr locals = make_shared(); - locals->Set("host", service->GetHost()); + std::ostringstream msgbuf; + msgbuf << "Evaluating 'apply' rule (" << di << ")"; + CONTEXT(msgbuf.str()); + + Host::Ptr host; + Service::Ptr service; + tie(host, service) = GetHostService(checkable); + + Dictionary::Ptr locals = make_shared(); + locals->Set("host", host); + if (service) locals->Set("service", service); - BOOST_FOREACH(const ApplyRule& rule, rules) { - DebugInfo di = rule.GetDebugInfo(); + if (!rule.EvaluateFilter(locals)) + return; - std::ostringstream msgbuf; - msgbuf << "Evaluating 'apply' rule (" << di << ")"; - CONTEXT(msgbuf.str()); + std::ostringstream msgbuf2; + msgbuf2 << "Applying dependency '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di; + Log(LogDebug, "icinga", msgbuf2.str()); - if (!rule.EvaluateFilter(locals)) - continue; + std::ostringstream namebuf; + namebuf << checkable->GetName() << "!" << rule.GetName(); + String name = namebuf.str(); + + ConfigItemBuilder::Ptr builder = make_shared(di); + builder->SetType("Dependency"); + builder->SetName(name); + builder->SetScope(rule.GetScope()); - std::ostringstream msgbuf2; - msgbuf2 << "Applying dependency '" << rule.GetName() << "' to service '" << service->GetName() << "' for rule " << di; - Log(LogDebug, "icinga", msgbuf2.str()); + builder->AddExpression(make_shared(&AExpression::OpSet, + make_shared(&AExpression::OpLiteral, "child_host_name", di), + make_shared(&AExpression::OpLiteral, host->GetName(), + di), di)); - std::ostringstream namebuf; - namebuf << service->GetName() << "!" << rule.GetName(); - String name = namebuf.str(); + if (service) { + builder->AddExpression(make_shared(&AExpression::OpSet, + make_shared(&AExpression::OpLiteral, "child_service_name", di), + make_shared(&AExpression::OpLiteral, service->GetShortName(), di), di)); + } - ConfigItemBuilder::Ptr builder = make_shared(di); - builder->SetType("Dependency"); - builder->SetName(name); - builder->SetScope(rule.GetScope()); + builder->AddExpression(rule.GetExpression()); - builder->AddExpression(make_shared(&AExpression::OpSet, - make_shared(&AExpression::OpLiteral, "child_host_name", di), - make_shared(&AExpression::OpLiteral, service->GetHost()->GetName(), - di), di)); + ConfigItem::Ptr dependencyItem = builder->Compile(); + dependencyItem->Register(); + DynamicObject::Ptr dobj = dependencyItem->Commit(); + dobj->OnConfigLoaded(); +} - builder->AddExpression(make_shared(&AExpression::OpSet, - make_shared(&AExpression::OpLiteral, "child_service_name", di), - make_shared(&AExpression::OpLiteral, service->GetShortName(), di), di)); +void Dependency::EvaluateApplyRules(const std::vector& rules) +{ + BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjects()) { + CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); - builder->AddExpression(rule.GetExpression()); + BOOST_FOREACH(const ApplyRule& rule, rules) { + if (rule.GetTargetType() != "Host") + continue; + + EvaluateApplyRule(host, rule); + } + } + + BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects()) { + CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'"); + + BOOST_FOREACH(const ApplyRule& rule, rules) { + if (rule.GetTargetType() != "Service") + continue; - ConfigItem::Ptr serviceItem = builder->Compile(); - serviceItem->Register(); - DynamicObject::Ptr dobj = serviceItem->Commit(); - dobj->OnConfigLoaded(); + EvaluateApplyRule(service, rule); } } } diff --git a/lib/icinga/dependency.h b/lib/icinga/dependency.h index da2dc54da..57b7000b4 100644 --- a/lib/icinga/dependency.h +++ b/lib/icinga/dependency.h @@ -48,11 +48,14 @@ public: bool IsAvailable(DependencyType dt) const; static void RegisterApplyRuleHandler(void); - static void EvaluateApplyRules(const std::vector& rules); protected: virtual void OnStateLoaded(void); virtual void Stop(void); + +private: + static void EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule); + static void EvaluateApplyRules(const std::vector& rules); }; } diff --git a/lib/icinga/notification-apply.cpp b/lib/icinga/notification-apply.cpp index 998f5ed15..5149a2aa1 100644 --- a/lib/icinga/notification-apply.cpp +++ b/lib/icinga/notification-apply.cpp @@ -32,57 +32,86 @@ INITIALIZE_ONCE(&Notification::RegisterApplyRuleHandler); void Notification::RegisterApplyRuleHandler(void) { - ApplyRule::RegisterType("Notification", "Service", &Notification::EvaluateApplyRules); + std::vector targets; + targets.push_back("Host"); + targets.push_back("Service"); + ApplyRule::RegisterType("Notification", targets, &Notification::EvaluateApplyRules); } -void Notification::EvaluateApplyRules(const std::vector& rules) +void Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule) { - BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects()) { - CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'"); + DebugInfo di = rule.GetDebugInfo(); - Dictionary::Ptr locals = make_shared(); - locals->Set("host", service->GetHost()); + std::ostringstream msgbuf; + msgbuf << "Evaluating 'apply' rule (" << di << ")"; + CONTEXT(msgbuf.str()); + + Host::Ptr host; + Service::Ptr service; + tie(host, service) = GetHostService(checkable); + + Dictionary::Ptr locals = make_shared(); + locals->Set("host", host); + if (service) locals->Set("service", service); - BOOST_FOREACH(const ApplyRule& rule, rules) { - DebugInfo di = rule.GetDebugInfo(); + if (!rule.EvaluateFilter(locals)) + return; - std::ostringstream msgbuf; - msgbuf << "Evaluating 'apply' rule (" << di << ")"; - CONTEXT(msgbuf.str()); + std::ostringstream msgbuf2; + msgbuf2 << "Applying notification '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di; + Log(LogDebug, "icinga", msgbuf2.str()); - if (!rule.EvaluateFilter(locals)) - continue; + std::ostringstream namebuf; + namebuf << checkable->GetName() << "!" << rule.GetName(); + String name = namebuf.str(); + + ConfigItemBuilder::Ptr builder = make_shared(di); + builder->SetType("Notification"); + builder->SetName(name); + builder->SetScope(rule.GetScope()); - std::ostringstream msgbuf2; - msgbuf2 << "Applying notification '" << rule.GetName() << "' to service '" << service->GetName() << "' for rule " << di; - Log(LogDebug, "icinga", msgbuf2.str()); + builder->AddExpression(make_shared(&AExpression::OpSet, + make_shared(&AExpression::OpLiteral, "host_name", di), + make_shared(&AExpression::OpLiteral, host->GetName(), di), + di)); - std::ostringstream namebuf; - namebuf << service->GetName() << "!" << rule.GetName(); - String name = namebuf.str(); + if (service) { + builder->AddExpression(make_shared(&AExpression::OpSet, + make_shared(&AExpression::OpLiteral, "service_name", di), + make_shared(&AExpression::OpLiteral, service->GetShortName(), di), + di)); + } - ConfigItemBuilder::Ptr builder = make_shared(di); - builder->SetType("Notification"); - builder->SetName(name); - builder->SetScope(rule.GetScope()); + builder->AddExpression(rule.GetExpression()); - builder->AddExpression(make_shared(&AExpression::OpSet, - make_shared(&AExpression::OpLiteral, "host_name", di), - make_shared(&AExpression::OpLiteral, service->GetHost()->GetName(), di), - di)); + ConfigItem::Ptr notificationItem = builder->Compile(); + notificationItem->Register(); + DynamicObject::Ptr dobj = notificationItem->Commit(); + dobj->OnConfigLoaded(); +} - builder->AddExpression(make_shared(&AExpression::OpSet, - make_shared(&AExpression::OpLiteral, "service_name", di), - make_shared(&AExpression::OpLiteral, service->GetShortName(), di), - di)); +void Notification::EvaluateApplyRules(const std::vector& rules) +{ + BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjects()) { + CONTEXT("Evaluating 'apply' rules for Host '" + host->GetName() + "'"); - builder->AddExpression(rule.GetExpression()); + BOOST_FOREACH(const ApplyRule& rule, rules) { + if (rule.GetTargetType() != "Host") + continue; + + EvaluateApplyRule(host, rule); + } + } + + BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects()) { + CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'"); + + BOOST_FOREACH(const ApplyRule& rule, rules) { + if (rule.GetTargetType() != "Service") + continue; - ConfigItem::Ptr serviceItem = builder->Compile(); - serviceItem->Register(); - DynamicObject::Ptr dobj = serviceItem->Commit(); - dobj->OnConfigLoaded(); + EvaluateApplyRule(service, rule); } } } diff --git a/lib/icinga/notification.h b/lib/icinga/notification.h index 2d7306cf8..d786f8927 100644 --- a/lib/icinga/notification.h +++ b/lib/icinga/notification.h @@ -88,14 +88,16 @@ public: static boost::signals2::signal OnNextNotificationChanged; static void RegisterApplyRuleHandler(void); - static void EvaluateApplyRules(const std::vector& rules); - + protected: virtual void Start(void); virtual void Stop(void); private: void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = ""); + + static void EvaluateApplyRule(const shared_ptr& checkable, const ApplyRule& rule); + static void EvaluateApplyRules(const std::vector& rules); }; } diff --git a/lib/icinga/scheduleddowntime-apply.cpp b/lib/icinga/scheduleddowntime-apply.cpp index 09085adaa..37d8e8882 100644 --- a/lib/icinga/scheduleddowntime-apply.cpp +++ b/lib/icinga/scheduleddowntime-apply.cpp @@ -32,57 +32,75 @@ INITIALIZE_ONCE(&ScheduledDowntime::RegisterApplyRuleHandler); void ScheduledDowntime::RegisterApplyRuleHandler(void) { - ApplyRule::RegisterType("ScheduledDowntime", "Service", &ScheduledDowntime::EvaluateApplyRules); + std::vector targets; + targets.push_back("Host"); + targets.push_back("Service"); + ApplyRule::RegisterType("ScheduledDowntime", targets, &ScheduledDowntime::EvaluateApplyRules); } -void ScheduledDowntime::EvaluateApplyRules(const std::vector& rules) +void ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule) { - BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects()) { - CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'"); + DebugInfo di = rule.GetDebugInfo(); - Dictionary::Ptr locals = make_shared(); - locals->Set("host", service->GetHost()); + std::ostringstream msgbuf; + msgbuf << "Evaluating 'apply' rule (" << di << ")"; + CONTEXT(msgbuf.str()); + + Host::Ptr host; + Service::Ptr service; + tie(host, service) = GetHostService(checkable); + + Dictionary::Ptr locals = make_shared(); + locals->Set("host", host); + if (service) locals->Set("service", service); - BOOST_FOREACH(const ApplyRule& rule, rules) { - DebugInfo di = rule.GetDebugInfo(); + if (!rule.EvaluateFilter(locals)) + return; - std::ostringstream msgbuf; - msgbuf << "Evaluating 'apply' rule (" << di << ")"; - CONTEXT(msgbuf.str()); + std::ostringstream msgbuf2; + msgbuf2 << "Applying scheduled downtime '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di; + Log(LogDebug, "icinga", msgbuf2.str()); - if (!rule.EvaluateFilter(locals)) - continue; + std::ostringstream namebuf; + namebuf << checkable->GetName() << "!" << rule.GetName(); + String name = namebuf.str(); - std::ostringstream msgbuf2; - msgbuf2 << "Applying scheduled downtime '" << rule.GetName() << "' to service '" << service->GetName() << "' for rule " << di; - Log(LogDebug, "icinga", msgbuf2.str()); + ConfigItemBuilder::Ptr builder = make_shared(di); + builder->SetType("ScheduledDowntime"); + builder->SetName(name); + builder->SetScope(rule.GetScope()); - std::ostringstream namebuf; - namebuf << service->GetName() << "!" << rule.GetName(); - String name = namebuf.str(); + builder->AddExpression(make_shared(&AExpression::OpSet, + make_shared(&AExpression::OpLiteral, "host_name", di), + make_shared(&AExpression::OpLiteral, host->GetName(), di), + di)); - ConfigItemBuilder::Ptr builder = make_shared(di); - builder->SetType("ScheduledDowntime"); - builder->SetName(name); - builder->SetScope(rule.GetScope()); + if (service) { + builder->AddExpression(make_shared(&AExpression::OpSet, + make_shared(&AExpression::OpLiteral, "service_name", di), + make_shared(&AExpression::OpLiteral, service->GetShortName(), di), + di)); + } - builder->AddExpression(make_shared(&AExpression::OpSet, - make_shared(&AExpression::OpLiteral, "host_name", di), - make_shared(&AExpression::OpLiteral, service->GetHost()->GetName(), di), - di)); + builder->AddExpression(rule.GetExpression()); - builder->AddExpression(make_shared(&AExpression::OpSet, - make_shared(&AExpression::OpLiteral, "service_name", di), - make_shared(&AExpression::OpLiteral, service->GetShortName(), di), - di)); + ConfigItem::Ptr downtimeItem = builder->Compile(); + downtimeItem->Register(); + DynamicObject::Ptr dobj = downtimeItem->Commit(); + dobj->OnConfigLoaded(); +} - builder->AddExpression(rule.GetExpression()); +void ScheduledDowntime::EvaluateApplyRules(const std::vector& rules) +{ + BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects()) { + CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'"); - ConfigItem::Ptr serviceItem = builder->Compile(); - serviceItem->Register(); - DynamicObject::Ptr dobj = serviceItem->Commit(); - dobj->OnConfigLoaded(); + Dictionary::Ptr locals = make_shared(); + locals->Set("host", service->GetHost()); + locals->Set("service", service); + + BOOST_FOREACH(const ApplyRule& rule, rules) { } } } diff --git a/lib/icinga/scheduleddowntime.h b/lib/icinga/scheduleddowntime.h index 41089ca42..4ee8d1149 100644 --- a/lib/icinga/scheduleddowntime.h +++ b/lib/icinga/scheduleddowntime.h @@ -45,8 +45,7 @@ public: Checkable::Ptr GetCheckable(void) const; static void RegisterApplyRuleHandler(void); - static void EvaluateApplyRules(const std::vector& rules); - + protected: virtual void Start(void); @@ -55,6 +54,9 @@ private: std::pair FindNextSegment(void); void CreateNextDowntime(void); + + static void EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule); + static void EvaluateApplyRules(const std::vector& rules); }; } diff --git a/lib/icinga/service-apply.cpp b/lib/icinga/service-apply.cpp index d41499070..068d53494 100644 --- a/lib/icinga/service-apply.cpp +++ b/lib/icinga/service-apply.cpp @@ -32,56 +32,62 @@ INITIALIZE_ONCE(&Service::RegisterApplyRuleHandler); void Service::RegisterApplyRuleHandler(void) { - ApplyRule::RegisterType("Service", "Host", &Service::EvaluateApplyRules); + std::vector targets; + targets.push_back("Host"); + ApplyRule::RegisterType("Service", targets, &Service::EvaluateApplyRules); } -void Service::EvaluateApplyRules(const std::vector& rules) +void Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule) { - BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjects()) { - CONTEXT("Evaluating 'apply' rules for Host '" + host->GetName() + "'"); + DebugInfo di = rule.GetDebugInfo(); - Dictionary::Ptr locals = make_shared(); - locals->Set("host", host); + std::ostringstream msgbuf; + msgbuf << "Evaluating 'apply' rule (" << di << ")"; + CONTEXT(msgbuf.str()); - BOOST_FOREACH(const ApplyRule& rule, rules) { - DebugInfo di = rule.GetDebugInfo(); + Dictionary::Ptr locals = make_shared(); + locals->Set("host", host); - std::ostringstream msgbuf; - msgbuf << "Evaluating 'apply' rule (" << di << ")"; - CONTEXT(msgbuf.str()); + if (!rule.EvaluateFilter(locals)) + return; - if (!rule.EvaluateFilter(locals)) - continue; + std::ostringstream msgbuf2; + msgbuf2 << "Applying service '" << rule.GetName() << "' to host '" << host->GetName() << "' for rule " << di; + Log(LogDebug, "icinga", msgbuf2.str()); - std::ostringstream msgbuf2; - msgbuf2 << "Applying service '" << rule.GetName() << "' to host '" << host->GetName() << "' for rule " << di; - Log(LogDebug, "icinga", msgbuf2.str()); + std::ostringstream namebuf; + namebuf << host->GetName() << "!" << rule.GetName(); + String name = namebuf.str(); - std::ostringstream namebuf; - namebuf << host->GetName() << "!" << rule.GetName(); - String name = namebuf.str(); + ConfigItemBuilder::Ptr builder = make_shared(di); + builder->SetType("Service"); + builder->SetName(name); + builder->SetScope(rule.GetScope()); - ConfigItemBuilder::Ptr builder = make_shared(di); - builder->SetType("Service"); - builder->SetName(name); - builder->SetScope(rule.GetScope()); + builder->AddExpression(make_shared(&AExpression::OpSet, + make_shared(&AExpression::OpLiteral, "host_name", di), + make_shared(&AExpression::OpLiteral, host->GetName(), di), + di)); - builder->AddExpression(make_shared(&AExpression::OpSet, - make_shared(&AExpression::OpLiteral, "host_name", di), - make_shared(&AExpression::OpLiteral, host->GetName(), di), - di)); + builder->AddExpression(make_shared(&AExpression::OpSet, + make_shared(&AExpression::OpLiteral, "name", di), + make_shared(&AExpression::OpLiteral, rule.GetName(), di), + di)); - builder->AddExpression(make_shared(&AExpression::OpSet, - make_shared(&AExpression::OpLiteral, "name", di), - make_shared(&AExpression::OpLiteral, rule.GetName(), di), - di)); + builder->AddExpression(rule.GetExpression()); + + ConfigItem::Ptr serviceItem = builder->Compile(); + serviceItem->Register(); + DynamicObject::Ptr dobj = serviceItem->Commit(); + dobj->OnConfigLoaded(); +} - builder->AddExpression(rule.GetExpression()); +void Service::EvaluateApplyRules(const std::vector& rules) +{ + BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjects()) { + CONTEXT("Evaluating 'apply' rules for Host '" + host->GetName() + "'"); - ConfigItem::Ptr serviceItem = builder->Compile(); - serviceItem->Register(); - DynamicObject::Ptr dobj = serviceItem->Commit(); - dobj->OnConfigLoaded(); - } + BOOST_FOREACH(const ApplyRule& rule, rules) + EvaluateApplyRule(host, rule); } } diff --git a/lib/icinga/service.h b/lib/icinga/service.h index cc3f46878..e5a12e1bc 100644 --- a/lib/icinga/service.h +++ b/lib/icinga/service.h @@ -60,13 +60,15 @@ public: static String StateTypeToString(StateType state); static void RegisterApplyRuleHandler(void); - static void EvaluateApplyRules(const std::vector& rules); protected: virtual void OnConfigLoaded(void); private: Host::Ptr m_Host; + + static void EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule); + static void EvaluateApplyRules(const std::vector& rules); }; I2_ICINGA_API boost::tuple GetHostService(const Checkable::Ptr& checkable); -- 2.40.0