Implemented 'services' property for host definitions.

This commit is contained in:
Gunnar Beutner 2012-07-06 11:22:38 +02:00
parent a11a36154f
commit 9b7251abb9
10 changed files with 360 additions and 25 deletions

View File

@ -6,6 +6,7 @@ SUBDIRS = \
cibsync \
compat \
configfile \
convenience \
delegation \
demo \
discovery

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View 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

View 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;

View 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);

View 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 << ")";

View 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);