]> granicus.if.org Git - icinga2/blobdiff - lib/icinga/notification-apply.cpp
Move the VMFrame class to libbase
[icinga2] / lib / icinga / notification-apply.cpp
index c5b48987ba488135f0c4e966f21178c39e45f68a..ed829f1e584507404d434fd6dddc29576e838b8c 100644 (file)
@@ -27,7 +27,7 @@
 #include "base/logger.hpp"
 #include "base/context.hpp"
 #include "base/workqueue.hpp"
-#include "base/configerror.hpp"
+#include "base/scripterror.hpp"
 #include <boost/foreach.hpp>
 
 using namespace icinga;
@@ -39,56 +39,42 @@ void Notification::RegisterApplyRuleHandler(void)
        std::vector<String> targets;
        targets.push_back("Host");
        targets.push_back("Service");
-       ApplyRule::RegisterType("Notification", targets, &Notification::EvaluateApplyRules);
+       ApplyRule::RegisterType("Notification", targets);
 }
 
-void Notification::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+void Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
        Log(LogDebug, "Notification")
            << "Applying notification '" << name << "' to object '" << checkable->GetName() << "' for rule " << di;
 
-       ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
+       ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
        builder->SetType("Notification");
        builder->SetName(name);
-       builder->SetScope(locals);
+       builder->SetScope(frame.Locals);
 
        Host::Ptr host;
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-               make_shared<Expression>(&Expression::OpLiteral, "host_name", di),
-               make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
-               di));
+       builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), false, di));
 
-       if (service) {
-               builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-                       make_shared<Expression>(&Expression::OpLiteral, "service_name", di),
-                       make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di),
-                       di));
-       }
+       if (service)
+               builder->AddExpression(new SetExpression(MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), false, di));
 
        String zone = checkable->GetZone();
 
-       if (!zone.IsEmpty()) {
-               builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-                       make_shared<Expression>(&Expression::OpLiteral, "zone", di),
-                       make_shared<Expression>(&Expression::OpLiteral, zone, di),
-                       di));
-       }
+       if (!zone.IsEmpty())
+               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), false, di));
 
-       builder->AddExpression(rule.GetExpression());
+       builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
        ConfigItem::Ptr notificationItem = builder->Compile();
-       notificationItem->Register();
-       DynamicObject::Ptr dobj = notificationItem->Commit();
-       dobj->OnConfigLoaded();
-       
+       notificationItem->Commit();
 }
 
-bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule)
+bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -100,28 +86,29 @@ bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const A
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       Dictionary::Ptr locals = make_shared<Dictionary>();
-       locals->Set("__parent", rule.GetScope());
-       locals->Set("host", host);
+       ScriptFrame frame;
+       if (rule.GetScope())
+               rule.GetScope()->CopyTo(frame.Locals);
+       frame.Locals->Set("host", host);
        if (service)
-               locals->Set("service", service);
+               frame.Locals->Set("service", service);
 
-       if (!rule.EvaluateFilter(locals))
+       if (!rule.EvaluateFilter(frame))
                return false;
 
        Value vinstances;
 
        if (rule.GetFTerm()) {
-               vinstances = rule.GetFTerm()->Evaluate(locals);
+               vinstances = rule.GetFTerm()->Evaluate(frame);
        } else {
-               Array::Ptr instances = make_shared<Array>();
+               Array::Ptr instances = new Array();
                instances->Add("");
                vinstances = instances;
        }
 
        if (vinstances.IsObjectType<Array>()) {
                if (!rule.GetFVVar().IsEmpty())
-                       BOOST_THROW_EXCEPTION(ConfigError("Array iterator requires value to be an array.") << errinfo_debuginfo(di));
+                       BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di));
 
                Array::Ptr arr = vinstances;
 
@@ -130,84 +117,61 @@ bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const A
                        String name = rule.GetName();
 
                        if (!rule.GetFKVar().IsEmpty()) {
-                               locals->Set(rule.GetFKVar(), instance);
+                               frame.Locals->Set(rule.GetFKVar(), instance);
                                name += instance;
                        }
 
-                       EvaluateApplyRuleOneInstance(checkable, name, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, name, frame, rule);
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
-                       BOOST_THROW_EXCEPTION(ConfigError("Dictionary iterator requires value to be a dictionary.") << errinfo_debuginfo(di));
+                       BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di));
        
                Dictionary::Ptr dict = vinstances;
 
                ObjectLock olock(dict);
                BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
-                       locals->Set(rule.GetFKVar(), kv.first);
-                       locals->Set(rule.GetFVVar(), kv.second);
+                       frame.Locals->Set(rule.GetFKVar(), kv.first);
+                       frame.Locals->Set(rule.GetFVVar(), kv.second);
 
-                       EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule);
                }
        }
 
        return true;
 }
 
-void Notification::EvaluateApplyRule(const ApplyRule& rule)
+void Notification::EvaluateApplyRules(const Host::Ptr& host)
 {
-       int apply_count = 0;
-
-       if (rule.GetTargetType() == "Host") {
-               apply_count = 0;
-
-               BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) {
-                       CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
-
-                       try {
-                               if (EvaluateApplyRuleOne(host, rule))
-                                       apply_count++;
-                       } catch (const ConfigError& ex) {
-                               const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
-                               ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
-                       }
+       CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
+
+       BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Notification"))
+       {
+               if (rule.GetTargetType() != "Host")
+                       continue;
+
+               try {
+                       if (EvaluateApplyRule(host, rule))
+                               rule.AddMatch();
+               } catch (const ScriptError& ex) {
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), ex.GetDebugInfo());
                }
-
-               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) {
-               upq.Enqueue(boost::bind(&Notification::EvaluateApplyRule, boost::cref(rule)));
-       }
+       BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Notification")) {
+               if (rule.GetTargetType() != "Service")
+                       continue;
 
-       upq.Join();
+               try {
+                       if (EvaluateApplyRule(service, rule))
+                               rule.AddMatch();
+               } catch (const ScriptError& ex) {
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), ex.GetDebugInfo());
+               }
+       }
 }