Implement global modified attributes for the IcingaApplication class

fixes #9859
This commit is contained in:
Michael Friedrich 2015-09-22 18:18:29 +02:00
parent 12cf90c67c
commit 84536da221
20 changed files with 155 additions and 208 deletions

View File

@ -368,16 +368,10 @@ ObjectsPath |**Read-write.** Contains the path of the Icinga 2 objects f
PidPath |**Read-write.** Contains the path of the Icinga 2 PID file. Defaults to RunDir + "/icinga2/icinga2.pid".
Vars |**Read-write.** Contains a dictionary with global custom attributes. Not set by default.
NodeName |**Read-write.** Contains the cluster node name. Set to the local hostname by default.
EnableNotifications |**Read-write.** Whether notifications are globally enabled. Defaults to true.
EnableEventHandlers |**Read-write.** Whether event handlers are globally enabled. Defaults to true.
EnableFlapping |**Read-write.** Whether flap detection is globally enabled. Defaults to true.
EnableHostChecks |**Read-write.** Whether active host checks are globally enabled. Defaults to true.
EnableServiceChecks |**Read-write.** Whether active service checks are globally enabled. Defaults to true.
EnablePerfdata |**Read-write.** Whether performance data processing is globally enabled. Defaults to true.
UseVfork |**Read-write.** Whether to use vfork(). Only available on *NIX. Defaults to true.
AttachDebugger |**Read-write.** Whether to attach a debugger when Icinga 2 crashes. Defaults to false.
RunAsUser |**Read-write.** Defines the user the Icinga 2 daemon is running as. Used in the `init.conf` configuration file.
RunAsGroup |**Read-write.** Defines the group the Icinga 2 daemon is running as. Used in the `init.conf` configuration file.
RunAsUser |**Read-write.** Defines the user the Icinga 2 daemon is running as. Used in the `init.conf` configuration file.
RunAsGroup |**Read-write.** Defines the group the Icinga 2 daemon is running as. Used in the `init.conf` configuration file.
## <a id="apply"></a> Apply

View File

@ -552,6 +552,30 @@ Configuration Attributes:
display_name |**Optional.** A short description of the host group.
groups |**Optional.** An array of nested group names.
## <a id="objecttype-icingaapplication"></a> IcingaApplication
The IcingaApplication object is required to start Icinga 2.
The object name must be `app`. If the object configuration
is missing Icinga 2 will automatically create an IcingaApplication
object.
Example:
object IcingaApplication "app" {
enable_perfdata = false
}
Configuration Attributes:
Name |Description
----------------------|--------------------------
enable_notifications |**Optional.** Whether notifications are globally enabled. Defaults to true.
enable_event_handlers |**Optional.** Whether event handlers are globally enabled. Defaults to true.
enable_flapping |**Optional.** Whether flap detection is globally enabled. Defaults to true.
enable_host_checks |**Optional.** Whether active host checks are globally enabled. Defaults to true.
enable_service_checks |**Optional.** Whether active service checks are globally enabled. Defaults to true.
enable_perfdata |**Optional.** Whether performance data processing is globally enabled. Defaults to true.
vars |**Optional.** A dictionary containing custom attributes that are available globally.
## <a id="objecttype-icingastatuswriter"></a> IcingaStatusWriter

View File

@ -37,6 +37,7 @@ else()
endif()
install_if_not_exists(icinga2/zones.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2)
install_if_not_exists(icinga2/conf.d/app.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d)
install_if_not_exists(icinga2/conf.d/commands.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d)
install_if_not_exists(icinga2/conf.d/downtimes.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d)
install_if_not_exists(icinga2/conf.d/groups.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d)

View File

@ -0,0 +1 @@
object IcingaApplication "app" { }

View File

@ -1449,3 +1449,11 @@ void Application::SetStartTime(double ts)
{
m_StartTime = ts;
}
void Application::ValidateName(const String& value, const ValidationUtils& utils)
{
ObjectImpl<Application>::ValidateName(value, utils);
if (value != "app")
BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("name"), "Application object must be named 'app'."));
}

View File

@ -146,6 +146,8 @@ protected:
virtual void OnShutdown(void);
virtual void ValidateName(const String& value, const ValidationUtils& utils) override;
private:
static Application::Ptr m_Instance; /**< The application instance. */

View File

@ -124,6 +124,16 @@ bool DaemonUtility::ValidateConfigFiles(const std::vector<std::string>& configs,
if (!success)
return false;
String appType = ScriptGlobal::Get("ApplicationType", &Empty);
if (ConfigItem::GetItems(appType).empty()) {
ConfigItemBuilder::Ptr builder = new ConfigItemBuilder();
builder->SetType(appType);
builder->SetName("app");
ConfigItem::Ptr item = builder->Compile();
item->Register();
}
return true;
}

View File

@ -15,12 +15,10 @@
# along with this program; if not, write to the Free Software Foundation
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
mkclass_target(hello.ti hello.tcpp hello.thpp)
mkembedconfig_target(hello-app.conf hello-app.cpp)
mkclass_target(helloapplication.ti helloapplication.tcpp helloapplication.thpp)
set(hello_SOURCES
hello.cpp hello.thpp hello-app.cpp
helloapplication.cpp helloapplication.thpp
)
if(ICINGA2_UNITY_BUILD)

View File

@ -1,20 +0,0 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2015 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. *
******************************************************************************/
object Hello "app" { }

View File

@ -17,22 +17,31 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "hello/hello.hpp"
#include "hello/hello.tcpp"
#include "hello/helloapplication.hpp"
#include "hello/helloapplication.tcpp"
#include "base/initialize.hpp"
#include "base/logger.hpp"
#include "base/scriptglobal.hpp"
using namespace icinga;
REGISTER_TYPE(Hello);
REGISTER_TYPE(HelloApplication);
INITIALIZE_ONCE(&HelloApplication::StaticInitialize);
void HelloApplication::StaticInitialize(void)
{
ScriptGlobal::Set("ApplicationType", "HelloApplication");
}
/**
* The entry point for the Hello application.
* The entry point for the hello application.
*
* @returns An exit status.
*/
int Hello::Main(void)
int HelloApplication::Main(void)
{
Log(LogInformation, "Hello", "Hello World!");
Log(LogInformation, "HelloApplication", "Hello World!");
return 0;
}

View File

@ -17,28 +17,30 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef HELLO_H
#define HELLO_H
#ifndef HELLOAPPLICATION_H
#define HELLOAPPLICATION_H
#include "hello/hello.thpp"
#include "hello/helloapplication.thpp"
namespace icinga
{
/**
* The Hello application.
* The hello application.
*
* @ingroup hello
*/
class Hello : public ObjectImpl<Hello>
class HelloApplication : public ObjectImpl<HelloApplication>
{
public:
DECLARE_OBJECT(Hello);
DECLARE_OBJECTNAME(Hello);
DECLARE_OBJECT(HelloApplication);
DECLARE_OBJECTNAME(HelloApplication);
static void StaticInitialize(void);
virtual int Main(void) override;
};
}
#endif /* HELLO_H */
#endif /* HELLOAPPLICATION_H */

View File

@ -24,7 +24,7 @@ library hello;
namespace icinga
{
class Hello : Application
class HelloApplication : Application
{
};

View File

@ -38,8 +38,6 @@ mkclass_target(timeperiod.ti timeperiod.tcpp timeperiod.thpp)
mkclass_target(usergroup.ti usergroup.tcpp usergroup.thpp)
mkclass_target(user.ti user.tcpp user.thpp)
mkembedconfig_target(icinga-app.conf icinga-app.cpp)
set(icinga_SOURCES
api.cpp apiactions.cpp apievents.cpp checkable.cpp checkable.thpp checkable-dependency.cpp checkable-downtime.cpp checkable-event.cpp
checkable-flapping.cpp checkcommand.cpp checkcommand.thpp checkresult.cpp checkresult.thpp
@ -51,7 +49,7 @@ set(icinga_SOURCES
notification-apply.cpp objectutils.cpp perfdatavalue.cpp perfdatavalue.thpp pluginutility.cpp scheduleddowntime.cpp scheduleddowntime.thpp
scheduleddowntime-apply.cpp service-apply.cpp checkable-check.cpp checkable-comment.cpp
service.cpp service.thpp servicegroup.cpp servicegroup.thpp checkable-notification.cpp timeperiod.cpp timeperiod.thpp
user.cpp user.thpp usergroup.cpp usergroup.thpp icinga-app.cpp
user.cpp user.thpp usergroup.cpp usergroup.thpp
)
if(ICINGA2_UNITY_BUILD)

View File

@ -24,7 +24,6 @@
#include "base/function.hpp"
#include "base/exception.hpp"
#include "base/objectlock.hpp"
#include <boost/foreach.hpp>
using namespace icinga;
@ -49,47 +48,5 @@ bool CustomVarObject::IsVarOverridden(const String& name) const
void CustomVarObject::ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils)
{
if (!value)
return;
/* string, array, dictionary */
ObjectLock olock(value);
BOOST_FOREACH(const Dictionary::Pair& kv, value) {
const Value& varval = kv.second;
if (varval.IsObjectType<Dictionary>()) {
/* only one dictonary level */
Dictionary::Ptr varval_dict = varval;
ObjectLock xlock(varval_dict);
BOOST_FOREACH(const Dictionary::Pair& kv_var, varval_dict) {
if (kv_var.second.IsEmpty())
continue;
if (!MacroProcessor::ValidateMacroString(kv_var.second))
BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("vars")(kv.first)(kv_var.first), "Closing $ not found in macro format string '" + kv_var.second + "'."));
}
} else if (varval.IsObjectType<Array>()) {
/* check all array entries */
Array::Ptr varval_arr = varval;
ObjectLock ylock (varval_arr);
BOOST_FOREACH(const Value& arrval, varval_arr) {
if (arrval.IsEmpty())
continue;
if (!MacroProcessor::ValidateMacroString(arrval)) {
BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("vars")(kv.first), "Closing $ not found in macro format string '" + arrval + "'."));
}
}
} else {
if (varval.IsEmpty())
continue;
String varstr = varval;
if (!MacroProcessor::ValidateMacroString(varstr))
BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("vars")(kv.first), "Closing $ not found in macro format string '" + varstr + "'."));
}
}
MacroProcessor::ValidateCustomVars(this, value);
}

View File

@ -1,20 +0,0 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2015 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. *
******************************************************************************/
object IcingaApplication "app" { }

View File

@ -20,6 +20,7 @@
#include "icinga/icingaapplication.hpp"
#include "icinga/icingaapplication.tcpp"
#include "icinga/cib.hpp"
#include "icinga/macroprocessor.hpp"
#include "config/configwriter.hpp"
#include "config/configcompiler.hpp"
#include "base/configtype.hpp"
@ -42,13 +43,6 @@ INITIALIZE_ONCE(&IcingaApplication::StaticInitialize);
void IcingaApplication::StaticInitialize(void)
{
ScriptGlobal::Set("EnableNotifications", true);
ScriptGlobal::Set("EnableEventHandlers", true);
ScriptGlobal::Set("EnableFlapping", true);
ScriptGlobal::Set("EnableHostChecks", true);
ScriptGlobal::Set("EnableServiceChecks", true);
ScriptGlobal::Set("EnablePerfdata", true);
String node_name = Utility::GetFQDN();
if (node_name.IsEmpty()) {
@ -62,6 +56,8 @@ void IcingaApplication::StaticInitialize(void)
}
ScriptGlobal::Set("NodeName", node_name);
ScriptGlobal::Set("ApplicationType", "IcingaApplication");
}
REGISTER_STATSFUNCTION(IcingaApplicationStats, &IcingaApplication::StatsFunc);
@ -191,16 +187,6 @@ IcingaApplication::Ptr IcingaApplication::GetInstance(void)
return static_pointer_cast<IcingaApplication>(Application::GetInstance());
}
Dictionary::Ptr IcingaApplication::GetVars(void) const
{
return ScriptGlobal::Get("Vars", &Empty);
}
String IcingaApplication::GetNodeName(void) const
{
return ScriptGlobal::Get("NodeName");
}
bool IcingaApplication::ResolveMacro(const String& macro, const CheckResult::Ptr&, Value *result) const
{
double now = Utility::GetTime();
@ -291,62 +277,12 @@ bool IcingaApplication::ResolveMacro(const String& macro, const CheckResult::Ptr
return false;
}
bool IcingaApplication::GetEnableNotifications(void) const
String IcingaApplication::GetNodeName(void) const
{
return ScriptGlobal::Get("EnableNotifications");
return ScriptGlobal::Get("NodeName");
}
void IcingaApplication::SetEnableNotifications(bool enabled)
void IcingaApplication::ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils)
{
ScriptGlobal::Set("EnableNotifications", enabled);
}
bool IcingaApplication::GetEnableEventHandlers(void) const
{
return ScriptGlobal::Get("EnableEventHandlers");
}
void IcingaApplication::SetEnableEventHandlers(bool enabled)
{
ScriptGlobal::Set("EnableEventHandlers", enabled);
}
bool IcingaApplication::GetEnableFlapping(void) const
{
return ScriptGlobal::Get("EnableFlapping");
}
void IcingaApplication::SetEnableFlapping(bool enabled)
{
ScriptGlobal::Set("EnableFlapping", enabled);
}
bool IcingaApplication::GetEnableHostChecks(void) const
{
return ScriptGlobal::Get("EnableHostChecks");
}
void IcingaApplication::SetEnableHostChecks(bool enabled)
{
ScriptGlobal::Set("EnableHostChecks", enabled);
}
bool IcingaApplication::GetEnableServiceChecks(void) const
{
return ScriptGlobal::Get("EnableServiceChecks");
}
void IcingaApplication::SetEnableServiceChecks(bool enabled)
{
ScriptGlobal::Set("EnableServiceChecks", enabled);
}
bool IcingaApplication::GetEnablePerfdata(void) const
{
return ScriptGlobal::Get("EnablePerfdata");
}
void IcingaApplication::SetEnablePerfdata(bool enabled)
{
ScriptGlobal::Set("EnablePerfdata", enabled);
MacroProcessor::ValidateCustomVars(this, value);
}

View File

@ -47,33 +47,12 @@ public:
static IcingaApplication::Ptr GetInstance(void);
String GetPidPath(void) const;
Dictionary::Ptr GetVars(void) const;
String GetNodeName(void) const;
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const override;
bool GetEnableNotifications(void) const;
void SetEnableNotifications(bool enabled);
void ClearEnableNotifications(void);
String GetNodeName(void) const;
bool GetEnableEventHandlers(void) const;
void SetEnableEventHandlers(bool enabled);
void ClearEnableEventHandlers(void);
bool GetEnableFlapping(void) const;
void SetEnableFlapping(bool enabled);
void ClearEnableFlapping(void);
bool GetEnableHostChecks(void) const;
void SetEnableHostChecks(bool enabled);
void ClearEnableHostChecks(void);
bool GetEnableServiceChecks(void) const;
void SetEnableServiceChecks(bool enabled);
void ClearEnableServiceChecks(void);
bool GetEnablePerfdata(void) const;
void SetEnablePerfdata(bool enabled);
void ClearEnablePerfdata(void);
virtual void ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils) override;
private:
void DumpProgramState(void);

View File

@ -26,6 +26,25 @@ namespace icinga
class IcingaApplication : Application
{
[config] bool enable_notifications {
default {{{ return true; }}}
};
[config] bool enable_event_handlers {
default {{{ return true; }}}
};
[config] bool enable_flapping {
default {{{ return true; }}}
};
[config] bool enable_host_checks {
default {{{ return true; }}}
};
[config] bool enable_service_checks {
default {{{ return true; }}}
};
[config] bool enable_perfdata {
default {{{ return true; }}}
};
[config] Dictionary::Ptr vars;
};
}

View File

@ -28,6 +28,7 @@
#include "base/scriptframe.hpp"
#include "base/convert.hpp"
#include "base/exception.hpp"
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/join.hpp>
@ -351,6 +352,53 @@ bool MacroProcessor::ValidateMacroString(const String& macro)
return true;
}
void MacroProcessor::ValidateCustomVars(const ConfigObject::Ptr& object, const Dictionary::Ptr& value)
{
if (!value)
return;
/* string, array, dictionary */
ObjectLock olock(value);
BOOST_FOREACH(const Dictionary::Pair& kv, value) {
const Value& varval = kv.second;
if (varval.IsObjectType<Dictionary>()) {
/* only one dictonary level */
Dictionary::Ptr varval_dict = varval;
ObjectLock xlock(varval_dict);
BOOST_FOREACH(const Dictionary::Pair& kv_var, varval_dict) {
if (kv_var.second.IsEmpty())
continue;
if (!ValidateMacroString(kv_var.second))
BOOST_THROW_EXCEPTION(ValidationError(object.get(), boost::assign::list_of<String>("vars")(kv.first)(kv_var.first), "Closing $ not found in macro format string '" + kv_var.second + "'."));
}
} else if (varval.IsObjectType<Array>()) {
/* check all array entries */
Array::Ptr varval_arr = varval;
ObjectLock ylock (varval_arr);
BOOST_FOREACH(const Value& arrval, varval_arr) {
if (arrval.IsEmpty())
continue;
if (!ValidateMacroString(arrval)) {
BOOST_THROW_EXCEPTION(ValidationError(object.get(), boost::assign::list_of<String>("vars")(kv.first), "Closing $ not found in macro format string '" + arrval + "'."));
}
}
} else {
if (varval.IsEmpty())
continue;
String varstr = varval;
if (!ValidateMacroString(varstr))
BOOST_THROW_EXCEPTION(ValidationError(object.get(), boost::assign::list_of<String>("vars")(kv.first), "Closing $ not found in macro format string '" + varstr + "'."));
}
}
}
void MacroProcessor::AddArgumentHelper(const Array::Ptr& args, const String& key, const String& value,
bool add_key, bool add_value)
{

View File

@ -52,6 +52,7 @@ public:
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel = 0);
static bool ValidateMacroString(const String& macro);
static void ValidateCustomVars(const ConfigObject::Ptr& object, const Dictionary::Ptr& value);
private:
MacroProcessor(void);