]> granicus.if.org Git - icinga2/commitdiff
Implemented 'services' property for host definitions.
authorGunnar Beutner <gunnar.beutner@netways.de>
Fri, 6 Jul 2012 09:22:38 +0000 (11:22 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Fri, 6 Jul 2012 09:22:38 +0000 (11:22 +0200)
components/Makefile.am
components/convenience/Makefile.am [new file with mode: 0644]
components/convenience/conveniencecomponent.cpp [new file with mode: 0644]
components/convenience/conveniencecomponent.h [new file with mode: 0644]
components/convenience/i2-convenience.h [new file with mode: 0644]
configure.ac
dyn/configitem.cpp
dyn/configitem.h
dyn/expression.cpp
icinga/icingaapplication.cpp

index b54490e97c585533be39e381fcc732a3fccfa40b..422b8c10c8200f3fc6cdfa1577ee370e4d77413d 100644 (file)
@@ -6,6 +6,7 @@ SUBDIRS = \
        cibsync \
        compat \
        configfile \
+       convenience \
        delegation \
        demo \
        discovery
diff --git a/components/convenience/Makefile.am b/components/convenience/Makefile.am
new file mode 100644 (file)
index 0000000..919f6ab
--- /dev/null
@@ -0,0 +1,33 @@
+## Process this file with automake to produce Makefile.in
+
+pkglib_LTLIBRARIES = \
+       convenience.la
+
+convenience_la_SOURCES = \
+       conveniencecomponent.cpp \
+       conveniencecomponent.h \
+       i2-convenience.h
+
+convenience_la_CPPFLAGS = \
+       $(BOOST_CPPFLAGS) \
+       -I${top_srcdir}/base \
+       -I${top_srcdir}/dyn \
+       -I${top_srcdir}/jsonrpc \
+       -I${top_srcdir}/icinga \
+       -I${top_srcdir}/cib
+
+convenience_la_LDFLAGS = \
+       $(BOOST_LDFLAGS) \
+       -module \
+       -no-undefined \
+       @RELEASE_INFO@ \
+       @VERSION_INFO@
+
+convenience_la_LIBADD = \
+       $(BOOST_SIGNALS_LIB) \
+       $(BOOST_THREAD_LIB) \
+       ${top_builddir}/base/libbase.la \
+       ${top_builddir}/dyn/libdyn.la \
+       ${top_builddir}/jsonrpc/libjsonrpc.la \
+       ${top_builddir}/icinga/libicinga.la \
+       ${top_builddir}/cib/libcib.la
diff --git a/components/convenience/conveniencecomponent.cpp b/components/convenience/conveniencecomponent.cpp
new file mode 100644 (file)
index 0000000..644427c
--- /dev/null
@@ -0,0 +1,181 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 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 "i2-convenience.h"
+
+using namespace icinga;
+
+/**
+ * Returns the name of the component.
+ *
+ * @returns The name.
+ */
+string ConvenienceComponent::GetName(void) const
+{
+       return "convenience";
+}
+
+/**
+ * Starts the component.
+ */
+void ConvenienceComponent::Start(void)
+{
+       ConfigItem::Set::Ptr itemSet = ConfigItem::GetAllObjects();
+       itemSet->OnObjectAdded.connect(boost::bind(&ConvenienceComponent::HostAddedHandler, this, _2));
+       itemSet->OnObjectCommitted.connect(boost::bind(&ConvenienceComponent::HostCommittedHandler, this, _2));
+       itemSet->OnObjectRemoved.connect(boost::bind(&ConvenienceComponent::HostRemovedHandler, this, _2));
+}
+
+/**
+ * Stops the component.
+ */
+void ConvenienceComponent::Stop(void)
+{
+}
+
+void ConvenienceComponent::HostAddedHandler(const ConfigItem::Ptr& item)
+{
+       HostCommittedHandler(item);
+}
+
+void ConvenienceComponent::HostCommittedHandler(const ConfigItem::Ptr& item)
+{
+       if (item->GetType() != "host")
+               return;
+
+       ConfigObject::Ptr host = ConfigObject::GetObject("host", item->GetName());
+       Dictionary::Ptr oldServices;
+       host->GetTag("convenience-services", &oldServices);
+
+       Dictionary::Ptr newServices;
+       newServices = boost::make_shared<Dictionary>();
+
+       Dictionary::Ptr serviceDescs;
+       host->GetProperty("services", &serviceDescs);
+
+       if (serviceDescs) {
+               Dictionary::Iterator it;
+               for (it = serviceDescs->Begin(); it != serviceDescs->End(); it++) {
+                       Variant desc = it->second;
+                       ConfigItem::Ptr serviceItem;
+
+                       string name;
+
+                       if (desc.GetType() == VariantString) {
+                               stringstream namebuf;
+                               namebuf << item->GetName() << "-" << string(desc);
+                               name = namebuf.str();
+
+                               serviceItem = boost::make_shared<ConfigItem>("service", name, item->GetDebugInfo());
+                               serviceItem->AddParent(desc);
+
+                               ExpressionList::Ptr exprl = boost::make_shared<ExpressionList>();
+
+                               Expression localExpr("__local", OperatorSet, 1, item->GetDebugInfo());
+                               exprl->AddExpression(localExpr);
+
+                               Expression abstractExpr("__abstract", OperatorSet, 0, item->GetDebugInfo());
+                               exprl->AddExpression(abstractExpr);
+
+                               Expression typeExpr("__type", OperatorSet, "service", item->GetDebugInfo());
+                               exprl->AddExpression(typeExpr);
+
+                               Expression nameExpr("__name", OperatorSet, name, item->GetDebugInfo());
+                               exprl->AddExpression(nameExpr);
+
+                               Expression hostExpr("host_name", OperatorSet, item->GetName(), item->GetDebugInfo());
+                               exprl->AddExpression(hostExpr);
+
+                               Expression aliasExpr("alias", OperatorSet, string(desc), item->GetDebugInfo());
+                               exprl->AddExpression(aliasExpr);
+
+                               Dictionary::Ptr macros;
+                               if (host->GetProperty("macros", &macros)) {
+                                       Expression macrosExpr("macros", OperatorPlus, macros, item->GetDebugInfo());
+                                       exprl->AddExpression(macrosExpr);
+                               }
+
+                               long checkInterval;
+                               if (host->GetProperty("check_interval", &checkInterval)) {
+                                       Expression checkExpr("check_interval", OperatorSet, checkInterval, item->GetDebugInfo());
+                                       exprl->AddExpression(checkExpr);
+                               }
+
+                               long retryInterval;
+                               if (host->GetProperty("retry_interval", &retryInterval)) {
+                                       Expression retryExpr("retry_interval", OperatorSet, retryInterval, item->GetDebugInfo());
+                                       exprl->AddExpression(retryExpr);
+                               }
+
+                               Dictionary::Ptr sgroups;
+                               if (host->GetProperty("servicegroups", &sgroups)) {
+                                       Expression sgroupsExpr("servicegroups", OperatorPlus, sgroups, item->GetDebugInfo());
+                                       exprl->AddExpression(sgroupsExpr);
+                               }
+
+                               Dictionary::Ptr checkers;
+                               if (host->GetProperty("checkers", &checkers)) {
+                                       Expression checkersExpr("checkers", OperatorSet, checkers, item->GetDebugInfo());
+                                       exprl->AddExpression(checkersExpr);
+                               }
+
+                               serviceItem->SetExpressionList(exprl);
+                               ConfigObject::Ptr service = serviceItem->Commit();
+
+                               newServices->SetProperty(name, serviceItem);
+                       } else {
+                               throw runtime_error("Not supported.");
+                       }
+               }
+       }
+
+       if (oldServices) {
+               Dictionary::Iterator it;
+               for (it = oldServices->Begin(); it != oldServices->End(); it++) {
+                       ConfigItem::Ptr service = static_pointer_cast<ConfigItem>(it->second.GetObject());
+
+                       if (!newServices->Contains(service->GetName()))
+                               service->Unregister();
+               }
+       }
+
+       //host.GetConfigObject()->SetTag("convenience-services", newServices);
+}
+
+void ConvenienceComponent::HostRemovedHandler(const ConfigItem::Ptr& item)
+{
+       if (item->GetType() != "host")
+               return;
+
+       ConfigObject::Ptr host = item->GetConfigObject();
+
+       Dictionary::Ptr services;
+       host->GetTag("convenience-services", &services);
+
+       if (!services)
+               return;
+
+       Dictionary::Iterator it;
+       for (it = services->Begin(); it != services->End(); it++) {
+               ConfigItem::Ptr service = static_pointer_cast<ConfigItem>(it->second.GetObject());
+               service->Unregister();
+       }
+}
+
+EXPORT_COMPONENT(convenience, ConvenienceComponent);
diff --git a/components/convenience/conveniencecomponent.h b/components/convenience/conveniencecomponent.h
new file mode 100644 (file)
index 0000000..8eb73e4
--- /dev/null
@@ -0,0 +1,44 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 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 CONVENIENCECOMPONENT_H
+#define CONVENIENCECOMPONENT_H
+
+namespace icinga
+{
+
+/**
+ * @ingroup convenience
+ */
+class ConvenienceComponent : public Component
+{
+public:
+       virtual string GetName(void) const;
+       virtual void Start(void);
+       virtual void Stop(void);
+
+private:
+       void HostAddedHandler(const ConfigItem::Ptr& item);
+       void HostCommittedHandler(const ConfigItem::Ptr& item);
+       void HostRemovedHandler(const ConfigItem::Ptr& item);
+};
+
+}
+
+#endif /* CONVENIENCECOMPONENT_H */
diff --git a/components/convenience/i2-convenience.h b/components/convenience/i2-convenience.h
new file mode 100644 (file)
index 0000000..f65ffdc
--- /dev/null
@@ -0,0 +1,39 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 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 I2CONVENIENCE_H
+#define I2CONVENIENCE_H
+
+/**
+ * @defgroup convenience Convenience component
+ *
+ * The convenience component takes service definitions from host objects
+ * and creates service objects. Technically this isn't strictly necessary but
+ * makes defining services a lot easier for users.
+ */
+
+#include <i2-base.h>
+#include <i2-dyn.h>
+#include <i2-jsonrpc.h>
+#include <i2-icinga.h>
+#include <i2-cib.h>
+
+#include "conveniencecomponent.h"
+
+#endif /* I2CONVENIENCE_H */
index 1678990d79a66457f722807a98b14617a74b8e5b..f031657234181f401acd1ea39d630c20662e7cbb 100644 (file)
@@ -72,6 +72,7 @@ components/checker/Makefile
 components/cibsync/Makefile
 components/compat/Makefile
 components/configfile/Makefile
+components/convenience/Makefile
 components/delegation/Makefile
 components/demo/Makefile
 components/discovery/Makefile
index 5d45e73ca0891d46819ae8b1b9ca75389bc22970..37e693ea0916d048f658b24b54d0864857e1a8d5 100644 (file)
@@ -36,6 +36,11 @@ string ConfigItem::GetName(void) const
        return m_Name;
 }
 
+DebugInfo ConfigItem::GetDebugInfo(void) const
+{
+       return m_DebugInfo;
+}
+
 ExpressionList::Ptr ConfigItem::GetExpressionList(void) const
 {
        return m_ExpressionList;
@@ -74,7 +79,7 @@ void ConfigItem::CalculateProperties(Dictionary::Ptr dictionary) const
        m_ExpressionList->Execute(dictionary);
 }
 
-ObjectSet<ConfigItem::Ptr>::Ptr ConfigItem::GetAllObjects(void)
+ConfigItem::Set::Ptr ConfigItem::GetAllObjects(void)
 {
        static ObjectSet<ConfigItem::Ptr>::Ptr allObjects;
 
@@ -105,7 +110,7 @@ ConfigItem::TNMap::Ptr ConfigItem::GetObjectsByTypeAndName(void)
        return tnmap;
 }
 
-void ConfigItem::Commit(void)
+ConfigObject::Ptr ConfigItem::Commit(void)
 {
        ConfigObject::Ptr dobj = m_ConfigObject.lock();
 
@@ -127,6 +132,9 @@ void ConfigItem::Commit(void)
        else
                dobj->Commit();
 
+       /* TODO: Figure out whether there are any child objects which inherit
+        * from this config item and Commit() them as well */
+
        ConfigItem::Ptr ci = GetObject(GetType(), GetName());
        ConfigItem::Ptr self = GetSelf();
        if (ci && ci != self) {
@@ -134,6 +142,8 @@ void ConfigItem::Commit(void)
                GetAllObjects()->RemoveObject(ci);
        }
        GetAllObjects()->CheckObject(self);
+
+       return dobj;
 }
 
 void ConfigItem::Unregister(void)
@@ -146,6 +156,11 @@ void ConfigItem::Unregister(void)
        GetAllObjects()->RemoveObject(GetSelf());
 }
 
+ConfigObject::Ptr ConfigItem::GetConfigObject(void) const
+{
+       return m_ConfigObject.lock();
+}
+
 ConfigItem::Ptr ConfigItem::GetObject(const string& type, const string& name)
 {
        ConfigItem::TNMap::Range range;
index 4358ce93fec07f8c7e217ca4863af911bda77c4d..fd93590b823c1842d9c2af367afae1ef6e7378b0 100644 (file)
@@ -28,6 +28,8 @@ public:
        typedef shared_ptr<ConfigItem> Ptr;
        typedef weak_ptr<ConfigItem> WeakPtr;
 
+       typedef ObjectSet<ConfigItem::Ptr> Set;
+
        typedef ObjectMap<pair<string, string>, ConfigItem::Ptr> TNMap;
 
        ConfigItem(const string& type, const string& name, const DebugInfo& debuginfo);
@@ -43,10 +45,14 @@ public:
 
        void CalculateProperties(Dictionary::Ptr dictionary) const;
 
-       void Commit(void);
+       ConfigObject::Ptr Commit(void);
        void Unregister(void);
 
-       static ObjectSet<ConfigItem::Ptr>::Ptr GetAllObjects(void);
+       ConfigObject::Ptr GetConfigObject(void) const;
+
+       DebugInfo GetDebugInfo(void) const;
+
+       static Set::Ptr GetAllObjects(void);
        static TNMap::Ptr GetObjectsByTypeAndName(void);
        static ConfigItem::Ptr GetObject(const string& type, const string& name);
 
index 64413f1dc0fc0e4fcd6f6c75b5c98a1ac82203ce..0096aa4e2b1ccdfa09a864483fac8cc7551a0bf8 100644 (file)
@@ -30,42 +30,52 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const
 {
        Variant oldValue, newValue;
 
-       ExpressionList::Ptr exprl;
-       if (m_Value.GetType() == VariantObject)
-               exprl = dynamic_pointer_cast<ExpressionList>(m_Value.GetObject());
+       ExpressionList::Ptr valueExprl;
+       Dictionary::Ptr valueDict;
+       if (m_Value.GetType() == VariantObject) {
+               valueExprl = dynamic_pointer_cast<ExpressionList>(m_Value.GetObject());
+               valueDict = dynamic_pointer_cast<Dictionary>(m_Value.GetObject());
+       }
 
        newValue = m_Value;
 
+       Dictionary::Ptr dict;
+
        switch (m_Operator) {
                case OperatorSet:
-                       if (exprl) {
-                               Dictionary::Ptr dict = boost::make_shared<Dictionary>();
-                               exprl->Execute(dict);
+                       if (valueExprl) {
+                               dict = boost::make_shared<Dictionary>();
+                               valueExprl->Execute(dict);
                                newValue = dict;
                        }
 
                        break;
 
                case OperatorPlus:
-                       if (exprl) {
-                               dictionary->GetProperty(m_Key, &oldValue);
+                       dictionary->GetProperty(m_Key, &oldValue);
 
-                               Dictionary::Ptr dict;
-                               if (oldValue.GetType() == VariantObject)
-                                       dict = dynamic_pointer_cast<Dictionary>(oldValue.GetObject());
+                       if (oldValue.GetType() == VariantObject)
+                               dict = dynamic_pointer_cast<Dictionary>(oldValue.GetObject());
 
-                               if (!dict) {
-                                       if (!oldValue.IsEmpty()) {
-                                               stringstream message;
-                                               message << "Wrong argument types for += (non-dictionary and dictionary) (" << m_DebugInfo << ")";
-                                               throw domain_error(message.str());
-                                       }
-
-                                       dict = boost::make_shared<Dictionary>();
+                       if (!dict) {
+                               if (!oldValue.IsEmpty()) {
+                                       stringstream message;
+                                       message << "Wrong argument types for += (non-dictionary and dictionary) (" << m_DebugInfo << ")";
+                                       throw domain_error(message.str());
                                }
 
-                               exprl->Execute(dict);
-                               newValue = dict;
+                               dict = boost::make_shared<Dictionary>();
+                       }
+
+                       newValue = dict;
+
+                       if (valueExprl) {
+                               valueExprl->Execute(dict);
+                       } else if (valueDict) {
+                               Dictionary::Iterator it;
+                               for (it = valueDict->Begin(); it != valueDict->End(); it++) {
+                                       dict->SetProperty(it->first, it->second);
+                               }
                        } else {
                                stringstream message;
                                message << "+= only works for dictionaries (" << m_DebugInfo << ")";
index 16b9f9e3f5ce9414f6fe0beb00b67aa297305724..562ea95292792c3a1402651556f4a3f2e82b46d4 100644 (file)
@@ -61,6 +61,11 @@ int IcingaApplication::Main(const vector<string>& args)
        componentObjects->OnObjectRemoved.connect(boost::bind(&IcingaApplication::DeletedComponentHandler, this, _2));
        componentObjects->Start();
 
+       /* load convenience config component */
+       ConfigObject::Ptr convenienceComponentConfig = boost::make_shared<ConfigObject>("component", "convenience");
+       convenienceComponentConfig->SetLocal(true);
+       convenienceComponentConfig->Commit();
+
        /* load config file */
        ConfigObject::Ptr fileComponentConfig = boost::make_shared<ConfigObject>("component", "configfile");
        fileComponentConfig->SetLocal(true);