]> granicus.if.org Git - icinga2/commitdiff
Improve config validation.
authorGunnar Beutner <gunnar.beutner@netways.de>
Tue, 24 Sep 2013 11:13:14 +0000 (13:13 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 24 Sep 2013 11:13:14 +0000 (13:13 +0200)
Fixes #4391

19 files changed:
components/compat/compatlog.cpp
icinga-app/icinga.cpp
lib/config/config_lexer.cc
lib/config/config_lexer.ll
lib/config/config_parser.cc
lib/config/config_parser.yy
lib/config/configcompilercontext.cpp
lib/config/configcompilercontext.h
lib/config/configitem.cpp
lib/config/configitem.h
lib/config/configtype.cpp
lib/config/expression.cpp
lib/config/expression.h
lib/config/expressionlist.cpp
lib/config/expressionlist.h
lib/icinga/host.cpp
lib/icinga/host.h
lib/icinga/icinga-type.conf
lib/icinga/service-notification.cpp

index af6394cde8b9c055ed32c6c7715a3100245d5853..27faf0b7c3dab3a2e75323d66c6157ea44a3e5b6 100644 (file)
@@ -577,7 +577,7 @@ void CompatLog::ValidateRotationMethod(const String& location, const Dictionary:
 
        if (!rotation_method.IsEmpty() && rotation_method != "HOURLY" && rotation_method != "DAILY" &&
            rotation_method != "WEEKLY" && rotation_method != "MONTHLY" && rotation_method != "NONE") {
-               ConfigCompilerContext::GetInstance()->AddError(false, "Validation failed for " +
+               ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
                    location + ": Rotation method '" + rotation_method + "' is invalid.");
        }
 }
index 90efd84d3f72af4cf5a0a72b20b72a39d08140a6..f85182433e7e72ffce34bffabb175766676c2429 100644 (file)
@@ -58,50 +58,23 @@ static bool LoadConfigFiles(bool validateOnly)
                ConfigCompiler::CompileText(name, fragment);
        }
 
-       bool hasError = false;
-
-       BOOST_FOREACH(const ConfigCompilerError& error, ConfigCompilerContext::GetInstance()->GetErrors()) {
-               if (!error.Warning) {
-                       hasError = true;
-                       break;
-               }
-       }
-
-       /* Don't link or validate if we have already encountered at least one error. */
-       if (!hasError) {
-               ConfigItem::LinkItems();
-               ConfigItem::ValidateItems();
-       }
-
-       hasError = false;
-
-       BOOST_FOREACH(const ConfigCompilerError& error, ConfigCompilerContext::GetInstance()->GetErrors()) {
-               if (error.Warning) {
-                       Log(LogWarning, "icinga-app", "Config warning: " + error.Message);
-               } else {
-                       hasError = true;
-                       Log(LogCritical, "icinga-app", "Config error: " + error.Message);
-               }
-       }
-
-       if (hasError)
-               return false;
-
-       if (validateOnly)
-               return true;
-
-       if (Application::GetInstance()) {
-               Log(LogCritical, "icinga-app", "You must not manually create an Application object.");
-               return false;
-       }
-
        ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>();
        builder->SetType(Application::GetApplicationType());
        builder->SetName("application");
        ConfigItem::Ptr item = builder->Compile();
        item->Register();
 
-       ConfigItem::ActivateItems();
+       bool result = ConfigItem::ActivateItems(validateOnly);
+
+       BOOST_FOREACH(const ConfigCompilerMessage& message, ConfigCompilerContext::GetInstance()->GetMessages()) {
+               if (message.Error)
+                       Log(LogCritical, "config", "Config error: " + message.Text);
+               else
+                       Log(LogWarning, "config", "Config warning: " + message.Text);
+       }
+
+       if (!result)
+               return false;
 
        ConfigItem::DiscardItems();
        ConfigType::DiscardTypes();
index b5bdcedba98ac35f1c21d5ce40e6818d7b9a627d..7492f11d501ea35fd5038aa5146dab57a506efd5 100644 (file)
@@ -1061,7 +1061,7 @@ YY_RULE_SETUP
 {
        std::ostringstream msgbuf;
        msgbuf << "Unterminated string found: " << *yylloc;
-       ConfigCompilerContext::GetInstance()->AddError(false, msgbuf.str());
+       ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
        BEGIN(INITIAL);
                                }
        YY_BREAK
@@ -1078,7 +1078,7 @@ YY_RULE_SETUP
                /* error, constant is out-of-bounds */
                std::ostringstream msgbuf;
                msgbuf << "Constant is out-of-bounds: " << yytext << " " << *yylloc;
-               ConfigCompilerContext::GetInstance()->AddError(false, msgbuf.str());
+               ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
        }
 
        lb_append_char(&string_buf, result);
@@ -1093,7 +1093,7 @@ YY_RULE_SETUP
         */
        std::ostringstream msgbuf;
        msgbuf << "Bad escape sequence found: " << yytext << " " << *yylloc;
-       ConfigCompilerContext::GetInstance()->AddError(false, msgbuf.str());
+       ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
                                }
        YY_BREAK
 case 6:
index f6ca1a65f010c9f7066c3a5e1c411b144bd9849a..b757b01e2cb5fff73e21acaa73ca0414f17a8a4c 100644 (file)
@@ -116,7 +116,7 @@ static char *lb_steal(lex_buf *lb)
 <STRING>\n                     {
        std::ostringstream msgbuf;
        msgbuf << "Unterminated string found: " << *yylloc;
-       ConfigCompilerContext::GetInstance()->AddError(false, msgbuf.str());
+       ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
        BEGIN(INITIAL);
                                }
 
@@ -130,7 +130,7 @@ static char *lb_steal(lex_buf *lb)
                /* error, constant is out-of-bounds */
                std::ostringstream msgbuf;
                msgbuf << "Constant is out-of-bounds: " << yytext << " " << *yylloc;
-               ConfigCompilerContext::GetInstance()->AddError(false, msgbuf.str());
+               ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
        }
 
        lb_append_char(&string_buf, result);
@@ -142,7 +142,7 @@ static char *lb_steal(lex_buf *lb)
         */
        std::ostringstream msgbuf;
        msgbuf << "Bad escape sequence found: " << yytext << " " << *yylloc;
-       ConfigCompilerContext::GetInstance()->AddError(false, msgbuf.str());
+       ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
                                }
 
 <STRING>\\n                    { lb_append_char(&string_buf, '\n'); }
index 3b88ea5cf0a612c5051e574b40353d988b5ef6e1..f734bdbcc4f7c991753241d7b9e82d4b26592ae2 100644 (file)
@@ -267,7 +267,7 @@ void yyerror(YYLTYPE *locp, ConfigCompiler *, const char *err)
 {
        std::ostringstream message;
        message << *locp << ": " << err;
-       ConfigCompilerContext::GetInstance()->AddError(false, message.str());
+       ConfigCompilerContext::GetInstance()->AddMessage(true, message.str());
 }
 
 int yyparse(ConfigCompiler *context);
@@ -283,7 +283,7 @@ void ConfigCompiler::Compile(void)
        try {
                yyparse(this);
        } catch (const std::exception& ex) {
-               ConfigCompilerContext::GetInstance()->AddError(false, boost::diagnostic_information(ex));
+               ConfigCompilerContext::GetInstance()->AddMessage(true, boost::diagnostic_information(ex));
        }
 }
 
index 55722013f54065415a27b4eacb44963a1c46464b..c1fc98ff6cc0b13f2588dc9ff6cc879afdcfb366 100644 (file)
@@ -124,7 +124,7 @@ void yyerror(YYLTYPE *locp, ConfigCompiler *, const char *err)
 {
        std::ostringstream message;
        message << *locp << ": " << err;
-       ConfigCompilerContext::GetInstance()->AddError(false, message.str());
+       ConfigCompilerContext::GetInstance()->AddMessage(true, message.str());
 }
 
 int yyparse(ConfigCompiler *context);
@@ -140,7 +140,7 @@ void ConfigCompiler::Compile(void)
        try {
                yyparse(this);
        } catch (const std::exception& ex) {
-               ConfigCompilerContext::GetInstance()->AddError(false, boost::diagnostic_information(ex));
+               ConfigCompilerContext::GetInstance()->AddMessage(true, boost::diagnostic_information(ex));
        }
 }
 
index 953ab2af5a7df94c3c26df7e48e3aa8e564c6878..2f1093c54cde4792a20473f4a6f1fb9f14fa2b21 100644 (file)
 
 using namespace icinga;
 
-void ConfigCompilerContext::AddError(bool warning, const String& message)
+void ConfigCompilerContext::AddMessage(bool error, const String& message)
 {
-       m_Errors.push_back(ConfigCompilerError(warning, message));
+       m_Messages.push_back(ConfigCompilerMessage(error, message));
 }
 
-std::vector<ConfigCompilerError> ConfigCompilerContext::GetErrors(void) const
+std::vector<ConfigCompilerMessage> ConfigCompilerContext::GetMessages(void) const
 {
-       return m_Errors;
+       return m_Messages;
+}
+
+bool ConfigCompilerContext::HasErrors(void) const
+{
+       BOOST_FOREACH(const ConfigCompilerMessage& message, m_Messages) {
+               if (message.Error)
+                       return true;
+       }
+
+       return false;
 }
 
 void ConfigCompilerContext::Reset(void)
 {
-       m_Errors.clear();
+       m_Messages.clear();
 }
 
 ConfigCompilerContext *ConfigCompilerContext::GetInstance(void)
index 8c9adecfa235fb533984ef9e6faf3b4b9d7a879f..1ebe5e968976956f55e375200b2548d23b7638ed 100644 (file)
 namespace icinga
 {
 
-struct I2_CONFIG_API ConfigCompilerError
+struct I2_CONFIG_API ConfigCompilerMessage
 {
-       bool Warning;
-       String Message;
+       bool Error;
+       String Text;
 
-       ConfigCompilerError(bool warning, const String& message)
-               : Warning(warning), Message(message)
+       ConfigCompilerMessage(bool error, const String& text)
+               : Error(error), Text(text)
        { }
 };
 
@@ -43,15 +43,16 @@ struct I2_CONFIG_API ConfigCompilerError
 class I2_CONFIG_API ConfigCompilerContext
 {
 public:
-       void AddError(bool warning, const String& message);
-       std::vector<ConfigCompilerError> GetErrors(void) const;
+       void AddMessage(bool error, const String& message);
+       std::vector<ConfigCompilerMessage> GetMessages(void) const;
+       bool HasErrors(void) const;
 
        void Reset(void);
 
        static ConfigCompilerContext *GetInstance(void);
 
 private:
-        std::vector<ConfigCompilerError> m_Errors;
+        std::vector<ConfigCompilerMessage> m_Messages;
 };
 
 }
index cfba85cc74ed9f41435eeaf672f10a51997346cb..0f42ab91bee81874fe5980c746fcdbc8686badd1 100644 (file)
@@ -116,13 +116,13 @@ void ConfigItem::Link(void)
                        std::ostringstream message;
                        message << "Parent object '" << name << "' does not"
                            " exist (" << m_DebugInfo << ")";
-                       BOOST_THROW_EXCEPTION(std::invalid_argument(message.str()));
-               }
-
-               parent->Link();
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, message.str());
+               } else {
+                       parent->Link();
 
-               ExpressionList::Ptr pexprl = parent->GetLinkedExpressionList();
-               m_LinkedExpressionList->AddExpression(Expression("", OperatorExecute, pexprl, m_DebugInfo));
+                       ExpressionList::Ptr pexprl = parent->GetLinkedExpressionList();
+                       m_LinkedExpressionList->AddExpression(Expression("", OperatorExecute, pexprl, m_DebugInfo));
+               }
        }
 
        m_LinkedExpressionList->AddExpression(Expression("", OperatorExecute, m_ExpressionList, m_DebugInfo));
@@ -233,41 +233,38 @@ ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name)
        return ConfigItem::Ptr();
 }
 
-void ConfigItem::LinkItems(void)
+void ConfigItem::ValidateItem(void)
 {
-       Log(LogInformation, "config", "Linking config items...");
+       ConfigType::Ptr ctype = ConfigType::GetByName(GetType());
 
-       ConfigItem::Ptr item;
-       BOOST_FOREACH(boost::tie(boost::tuples::ignore, item), m_Items) {
-               item->Link();
+       if (!ctype) {
+               ConfigCompilerContext::GetInstance()->AddMessage(false, "No validation type found for object '" + GetName() + "' of type '" + GetType() + "'");
+
+               return;
        }
+
+       ctype->ValidateItem(GetSelf());
 }
 
-void ConfigItem::ValidateItems(void)
+bool ConfigItem::ActivateItems(bool validateOnly)
 {
-       Log(LogInformation, "config", "Validating config items...");
+       if (ConfigCompilerContext::GetInstance()->HasErrors())
+               return false;
+
+       Log(LogInformation, "config", "Linking config items...");
 
        ConfigItem::Ptr item;
        BOOST_FOREACH(boost::tie(boost::tuples::ignore, item), m_Items) {
-               ConfigType::Ptr ctype = ConfigType::GetByName(item->GetType());
-
-               if (!ctype) {
-                       ConfigCompilerContext::GetInstance()->AddError(true, "No validation type found for object '" + item->GetName() + "' of type '" + item->GetType() + "'");
-
-                       continue;
-               }
-
-               ctype->ValidateItem(item);
+               item->Link();
        }
-}
 
-void ConfigItem::ActivateItems(void)
-{
+       if (ConfigCompilerContext::GetInstance()->HasErrors())
+               return false;
+
        Log(LogInformation, "config", "Activating config items");
 
        std::vector<DynamicObject::Ptr> objects;
 
-       ConfigItem::Ptr item;
        BOOST_FOREACH(boost::tie(boost::tuples::ignore, item), m_Items) {
                DynamicObject::Ptr object = item->Commit();
 
@@ -279,6 +276,16 @@ void ConfigItem::ActivateItems(void)
                object->OnConfigLoaded();
        }
 
+       BOOST_FOREACH(boost::tie(boost::tuples::ignore, item), m_Items) {
+               item->ValidateItem();
+       }
+
+       if (ConfigCompilerContext::GetInstance()->HasErrors())
+               return false;
+
+       if (validateOnly)
+               return true;
+
        /* restore the previous program state */
        DynamicObject::RestoreObjects(Application::GetStatePath());
 
@@ -293,6 +300,8 @@ void ConfigItem::ActivateItems(void)
                        ASSERT(object->IsActive());
                }
        }
+
+       return true;
 }
 
 void ConfigItem::DiscardItems(void)
index e85cb91a6e141d3c8b05993e0d5737d3fd059e1f..f6de74ce1921c4e4e91b5f8a95ed73507cb19085 100644 (file)
@@ -62,9 +62,9 @@ public:
        static ConfigItem::Ptr GetObject(const String& type,
            const String& name);
 
-       static void LinkItems(void);
-       static void ValidateItems(void);
-       static void ActivateItems(void);
+       void ValidateItem(void);
+
+       static bool ActivateItems(bool validateOnly);
        static void DiscardItems(void);
 
 private:
index 9c7f3966aef0e3622ad94355315704d02e468bf8..5baa17a4157505796b205cb2b307e1effda95fdd 100644 (file)
@@ -121,7 +121,7 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,
                        Value value = dictionary->Get(require);
 
                        if (value.IsEmpty()) {
-                               ConfigCompilerContext::GetInstance()->AddError(false,
+                               ConfigCompilerContext::GetInstance()->AddMessage(true,
                                    "Required attribute is missing: " + LocationToString(locations));
                        }
 
@@ -175,14 +175,14 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,
                }
 
                if (overallResult == ValidationUnknownField)
-                       ConfigCompilerContext::GetInstance()->AddError(true, "Unknown attribute: " + LocationToString(locations));
+                       ConfigCompilerContext::GetInstance()->AddMessage(false, "Unknown attribute: " + LocationToString(locations));
                else if (overallResult == ValidationInvalidType) {
                        String message = "Invalid value for attribute: " + LocationToString(locations);
 
                        if (!hint.IsEmpty())
                                message += ": " + hint;
 
-                       ConfigCompilerContext::GetInstance()->AddError(false, message);
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, message);
                }
 
                if (!subRuleLists.empty() && value.IsObjectType<Dictionary>())
@@ -204,7 +204,7 @@ void ConfigType::ValidateArray(const Array::Ptr& array,
                        locations.push_back("Attribute '" + require + "'");
 
                        if (array->GetLength() < index) {
-                               ConfigCompilerContext::GetInstance()->AddError(false,
+                               ConfigCompilerContext::GetInstance()->AddMessage(true,
                                    "Required array index is missing: " + LocationToString(locations));
                        }
 
@@ -261,14 +261,14 @@ void ConfigType::ValidateArray(const Array::Ptr& array,
                }
 
                if (overallResult == ValidationUnknownField)
-                       ConfigCompilerContext::GetInstance()->AddError(true, "Unknown attribute: " + LocationToString(locations));
+                       ConfigCompilerContext::GetInstance()->AddMessage(false, "Unknown attribute: " + LocationToString(locations));
                else if (overallResult == ValidationInvalidType) {
                        String message = "Invalid value for array index: " + LocationToString(locations);
 
                        if (!hint.IsEmpty())
                                message += ": " + hint;
 
-                       ConfigCompilerContext::GetInstance()->AddError(false, message);
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, message);
                }
 
                if (!subRuleLists.empty() && value.IsObjectType<Dictionary>())
index 1e42fbcd2ac5478b4c28f656948f2a663522dd6f..964267c6cc3f25c9d6ce1f40df430219dc129583 100644 (file)
@@ -58,6 +58,11 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const
        Array::Ptr array;
 
        switch (m_Operator) {
+               case OperatorNop:
+                       /* Nothing to do here. */
+
+                       return;
+
                case OperatorExecute:
                        if (!valueExprl)
                                BOOST_THROW_EXCEPTION(std::invalid_argument("Operand for OperatorExecute must be an ExpressionList."));
@@ -165,3 +170,41 @@ void Expression::ExtractFiltered(const std::set<String, string_iless>& keys, con
                exprl->ExtractFiltered(keys, result);
        }
 }
+
+void Expression::ErasePath(const std::vector<String>& path)
+{
+       ASSERT(!path.empty());
+
+       if (path[0] == m_Key) {
+               if (path.size() == 1) {
+                       m_Operator = OperatorNop;
+               } else if (m_Value.IsObjectType<ExpressionList>()) {
+                       ExpressionList::Ptr exprl = m_Value;
+
+                       std::vector<String> sub_path(path.begin() + 1, path.end());
+                       exprl->ErasePath(sub_path);
+               }
+       } else if (m_Operator == OperatorExecute) {
+               ExpressionList::Ptr exprl = m_Value;
+               exprl->ErasePath(path);
+       }
+}
+
+void Expression::FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const
+{
+       ASSERT(!path.empty());
+
+       if (path[0] == m_Key) {
+               if (path.size() == 1) {
+                       result = m_DebugInfo;
+               } else if (m_Value.IsObjectType<ExpressionList>()) {
+                       ExpressionList::Ptr exprl = m_Value;
+
+                       std::vector<String> sub_path(path.begin() + 1, path.end());
+                       exprl->FindDebugInfoPath(sub_path, result);
+               }
+       } else if (m_Operator == OperatorExecute) {
+               ExpressionList::Ptr exprl = m_Value;
+               exprl->FindDebugInfoPath(path, result);
+       }
+}
index b9cd012dcd0624bf298b4e32a7db747db3bd86a7..1e60f66c8553c9d7101235dde878cf61ca842189 100644 (file)
@@ -37,6 +37,7 @@ namespace icinga
  */
 enum ExpressionOperator
 {
+       OperatorNop,
        OperatorExecute,
        OperatorSet,
        OperatorPlus,
@@ -63,6 +64,10 @@ public:
        void ExtractPath(const std::vector<String>& path, const shared_ptr<ExpressionList>& result) const;
        void ExtractFiltered(const std::set<String, string_iless>& keys, const shared_ptr<ExpressionList>& result) const;
 
+       void ErasePath(const std::vector<String>& path);
+
+       void FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const;
+
 private:
        String m_Key;
        ExpressionOperator m_Operator;
index feebaaff7ee78c710b3d22cd8238ea7bd6a69f40..edab1fdb320c3d5b563e7f3a42d5a30c42d7615f 100644 (file)
@@ -68,3 +68,17 @@ void ExpressionList::ExtractFiltered(const std::set<String, string_iless>& keys,
                expression.ExtractFiltered(keys, result);
        }
 }
+
+void ExpressionList::ErasePath(const std::vector<String>& path)
+{
+       BOOST_FOREACH(Expression& expression, m_Expressions) {
+               expression.ErasePath(path);
+       }
+}
+
+void ExpressionList::FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const
+{
+       BOOST_FOREACH(const Expression& expression, m_Expressions) {
+               expression.FindDebugInfoPath(path, result);
+       }
+}
index 51e77aa4a2a6dc7d66e42ee8a80230c40a05d6d0..ec0e63e4c89bacd6455a525a5e578fa4ce2fa649 100644 (file)
@@ -47,6 +47,10 @@ public:
        void ExtractPath(const std::vector<String>& path, const ExpressionList::Ptr& result) const;
        void ExtractFiltered(const std::set<String, string_iless>& keys, const ExpressionList::Ptr& result) const;
 
+       void ErasePath(const std::vector<String>& path);
+
+       void FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const;
+
 private:
        std::vector<Expression> m_Expressions;
 };
index 6f9a765c9785d568194b9daa291b7c9f206d8f57..5afadccb64024e40f264fe9e1d0d7b13ee89a0b7 100644 (file)
@@ -36,8 +36,6 @@
 
 using namespace icinga;
 
-REGISTER_SCRIPTFUNCTION(ValidateServiceDictionary, &Host::ValidateServiceDictionary);
-
 REGISTER_TYPE(Host);
 
 void Host::Start(void)
@@ -197,7 +195,17 @@ void Host::UpdateSlaveServices(void)
                namebuf << GetName() << ":" << svcname;
                String name = namebuf.str();
 
-               ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(item->GetDebugInfo());
+               std::vector<String> path;
+               path.push_back("services");
+               path.push_back(svcname);
+
+               DebugInfo di;
+               item->GetLinkedExpressionList()->FindDebugInfoPath(path, di);
+
+               if (di.Path.IsEmpty())
+                       di = item->GetDebugInfo();
+
+               ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(di);
                builder->SetType("Service");
                builder->SetName(name);
                builder->AddExpression("host_name", OperatorSet, GetName());
@@ -238,12 +246,13 @@ void Host::UpdateSlaveServices(void)
                builder->AddExpressionList(host_exprl);
 
                /* Clone attributes from the service expression list. */
-               std::vector<String> path;
-               path.push_back("services");
-               path.push_back(svcname);
-
                ExpressionList::Ptr svc_exprl = boost::make_shared<ExpressionList>();
                item->GetLinkedExpressionList()->ExtractPath(path, svc_exprl);
+
+               std::vector<String> dpath;
+               dpath.push_back("templates");
+               svc_exprl->ErasePath(dpath);
+
                builder->AddExpressionList(svc_exprl);
 
                ConfigItem::Ptr serviceItem = builder->Compile();
@@ -290,42 +299,6 @@ int Host::GetTotalServices(void) const
        return GetServices().size();
 }
 
-Value Host::ValidateServiceDictionary(const String& location, const Dictionary::Ptr& attrs)
-{
-       ObjectLock olock(attrs);
-
-       String key;
-       Value value;
-       BOOST_FOREACH(boost::tie(key, value), attrs) {
-               std::vector<String> templates;
-
-               if (!value.IsObjectType<Dictionary>())
-                       BOOST_THROW_EXCEPTION(std::invalid_argument("Service description must be a dictionary."));
-
-               Dictionary::Ptr serviceDesc = value;
-
-               Array::Ptr templatesArray = serviceDesc->Get("templates");
-
-               if (templatesArray) {
-                       ObjectLock tlock(templatesArray);
-
-                       BOOST_FOREACH(const Value& tmpl, templatesArray) {
-                               templates.push_back(tmpl);
-                       }
-               }
-
-               BOOST_FOREACH(const String& name, templates) {
-                       ConfigItem::Ptr item = ConfigItem::GetObject("Service", name);
-
-                       if (!item)
-                               ConfigCompilerContext::GetInstance()->AddError(false, "Validation failed for " +
-                                           location + ": Template '" + name + "' not found.");
-               }
-       }
-
-       return Empty;
-}
-
 Service::Ptr Host::GetServiceByShortName(const Value& name) const
 {
        if (name.IsScalar()) {
index 68011d1f54b627b794f0b669d3f94e1a1b169487..c4d1fce8bea7610558c918f320a51ec504663f88 100644 (file)
@@ -104,8 +104,6 @@ public:
 
        int GetTotalServices(void) const;
 
-       static Value ValidateServiceDictionary(const String& location, const Dictionary::Ptr& attrs);
-
        static HostState CalculateState(ServiceState state, bool reachable);
 
        HostState GetState(void) const;
index ade463095254d8f9fabd699a54a33a35236d1e85..33c67e03d8dd5dbc1cf7354cec2d5bd3b9ebc098 100644 (file)
@@ -36,14 +36,12 @@ type Host {
                }
        },
        %attribute dictionary "services" {
-               %validator "ValidateServiceDictionary",
-
                %attribute dictionary "*" {
                        %attribute array "templates" {
                                %attribute name(Service) "*"
                        },
 
-                       %attribute string "short_name",
+/*                     %attribute string "short_name",
                        %attribute string "display_name",
 
                        %attribute dictionary "macros" {
@@ -112,11 +110,11 @@ type Host {
                                        %attribute number "notification_state_filter",
                                        %attribute name(TimePeriod) "notification_period"
                                }
-                       },
+                       },*/
                }
        },
 
-       %attribute dictionary "notifications" {
+/*     %attribute dictionary "notifications" {
                %attribute dictionary "*" {
                        %attribute array "templates" {
                                %attribute name(Notification) "*"
@@ -142,7 +140,7 @@ type Host {
                        %attribute number "notification_state_filter",
                        %attribute name(TimePeriod) "notification_period"
                }
-       },
+       },*/
 
        /* service attributes */
        %attribute number "max_check_attempts",
@@ -244,7 +242,7 @@ type Service {
                                %attribute name(Notification) "*"
                        },
 
-                       %attribute dictionary "macros" {
+/*                     %attribute dictionary "macros" {
                                %attribute string "*"
                        },
 
@@ -262,7 +260,7 @@ type Service {
 
                        %attribute number "notification_type_filter",
                        %attribute number "notification_state_filter",
-                       %attribute name(TimePeriod) "notification_period"
+                       %attribute name(TimePeriod) "notification_period"*/
                }
        }
 }
index 5ccfe28a2a7249f08d0804eabc1c865731adecb8..05e656e99143367cb36c1609fdcd1a783143b906 100644 (file)
@@ -147,7 +147,17 @@ void Service::UpdateSlaveNotifications(void)
                        namebuf << GetName() << ":" << nfcname;
                        String name = namebuf.str();
 
-                       ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(item->GetDebugInfo());
+                       std::vector<String> path;
+                       path.push_back("notifications");
+                       path.push_back(nfcname);
+
+                       DebugInfo di;
+                       item->GetLinkedExpressionList()->FindDebugInfoPath(path, di);
+
+                       if (di.Path.IsEmpty())
+                               di = item->GetDebugInfo();
+
+                       ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(di);
                        builder->SetType("Notification");
                        builder->SetName(name);
                        builder->AddExpression("host_name", OperatorSet, host->GetName());
@@ -183,12 +193,13 @@ void Service::UpdateSlaveNotifications(void)
                        builder->AddExpressionList(svc_exprl);
 
                        /* Clone attributes from the notification expression list. */
-                       std::vector<String> path;
-                       path.push_back("notifications");
-                       path.push_back(nfcname);
-
                        ExpressionList::Ptr nfc_exprl = boost::make_shared<ExpressionList>();
                        item->GetLinkedExpressionList()->ExtractPath(path, nfc_exprl);
+
+                       std::vector<String> dpath;
+                       dpath.push_back("templates");
+                       nfc_exprl->ErasePath(dpath);
+
                        builder->AddExpressionList(nfc_exprl);
 
                        ConfigItem::Ptr notificationItem = builder->Compile();