Implement support for persisting modified attributes

fixes #9093
This commit is contained in:
Gunnar Beutner 2015-08-12 09:52:29 +02:00
parent d7970f5bb1
commit a092c13ace
6 changed files with 96 additions and 0 deletions

View File

@ -263,6 +263,7 @@ int Main(void)
}
Application::DeclareStatePath(Application::GetLocalStateDir() + "/lib/icinga2/icinga2.state");
Application::DeclareModAttrPath(Application::GetLocalStateDir() + "/lib/icinga2/modified-attributes.conf");
Application::DeclareObjectsPath(Application::GetLocalStateDir() + "/cache/icinga2/icinga2.debug");
Application::DeclareVarsPath(Application::GetLocalStateDir() + "/cache/icinga2/icinga2.vars");
Application::DeclarePidPath(Application::GetRunDir() + "/icinga2/icinga2.pid");

View File

@ -600,6 +600,7 @@ void Application::DisplayInfoMessage(std::ostream& os, bool skipVersion)
<< " Local state directory: " << GetLocalStateDir() << "\n"
<< " Package data directory: " << GetPkgDataDir() << "\n"
<< " State path: " << GetStatePath() << "\n"
<< " Modified attributes path: " << GetModAttrPath() << "\n"
<< " Objects path: " << GetObjectsPath() << "\n"
<< " Vars path: " << GetVarsPath() << "\n"
<< " PID path: " << GetPidPath() << "\n";
@ -1281,6 +1282,27 @@ void Application::DeclareStatePath(const String& path)
ScriptGlobal::Set("StatePath", path);
}
/**
* Retrieves the path for the modified attributes file.
*
* @returns The path.
*/
String Application::GetModAttrPath(void)
{
return ScriptGlobal::Get("ModAttrPath", &Empty);
}
/**
* Sets the path for the modified attributes file.
*
* @param path The new path.
*/
void Application::DeclareModAttrPath(const String& path)
{
if (!ScriptGlobal::Exists("ModAttrPath"))
ScriptGlobal::Set("ModAttrPath", path);
}
/**
* Retrieves the path for the objects file.
*

View File

@ -106,6 +106,9 @@ public:
static String GetStatePath(void);
static void DeclareStatePath(const String& path);
static String GetModAttrPath(void);
static void DeclareModAttrPath(const String& path);
static String GetObjectsPath(void);
static void DeclareObjectsPath(const String& path);

View File

@ -404,6 +404,27 @@ void DynamicObject::StopObjects(void)
}
}
void DynamicObject::DumpModifiedAttributes(const boost::function<void(const DynamicObject::Ptr&, const String&, const Value&)>& callback)
{
BOOST_FOREACH(const DynamicType::Ptr& dt, DynamicType::GetTypes()) {
BOOST_FOREACH(const DynamicObject::Ptr& object, dt->GetObjects()) {
Dictionary::Ptr originalAttributes = object->GetOriginalAttributes();
if (!originalAttributes)
continue;
ObjectLock olock(originalAttributes);
BOOST_FOREACH(const Dictionary::Pair& kv, originalAttributes) {
// TODO-MA: vars.os
int fid = object->GetReflectionType()->GetFieldId(kv.first);
Value value = object->GetField(fid);
callback(object, kv.first, value);
}
}
}
}
DynamicObject::Ptr DynamicObject::GetObject(const String& type, const String& name)
{
DynamicType::Ptr dtype = DynamicType::GetByName(type);

View File

@ -86,6 +86,8 @@ public:
static void RestoreObjects(const String& filename, int attributeTypes = FAState);
static void StopObjects(void);
static void DumpModifiedAttributes(const boost::function<void(const DynamicObject::Ptr&, const String&, const Value&)>& callback);
static Object::Ptr GetPrototype(void);
protected:

View File

@ -20,6 +20,7 @@
#include "icinga/icingaapplication.hpp"
#include "icinga/icingaapplication.tcpp"
#include "icinga/cib.hpp"
#include "config/configwriter.cpp"
#include "base/dynamictype.hpp"
#include "base/logger.hpp"
#include "base/objectlock.hpp"
@ -102,6 +103,18 @@ int IcingaApplication::Main(void)
l_RetentionTimer->OnTimerExpired.connect(boost::bind(&IcingaApplication::DumpProgramState, this));
l_RetentionTimer->Start();
/* restore modified attributes */
Expression *expression = ConfigCompiler::CompileFile(GetModAttrPath());
if (expression) {
try {
ScriptFrame frame;
expression->Evaluate(frame);
} catch (const std::exception& ex) {
Log(LogCritical, "config", DiagnosticInformation(ex));
}
}
RunEventLoop();
Log(LogInformation, "IcingaApplication", "Icinga has shut down.");
@ -121,9 +134,43 @@ void IcingaApplication::OnShutdown(void)
DumpProgramState();
}
static void PersistModAttrHelper(const ConfigWriter::Ptr& cw, DynamicObject::Ptr& previousObject, const DynamicObject::Ptr& object, const String& attr, const Value& value)
{
if (object != previousObject) {
if (previousObject)
cw->EmitRaw("}\n\n");
cw->EmitRaw("var obj = get_object(");
cw->EmitIdentifier(object->GetReflectionType()->GetName(), 0);
cw->EmitRaw(", ");
cw->EmitString(object->GetName());
cw->EmitRaw(")\n");
cw->EmitRaw("if (obj) {\n");
}
cw->EmitRaw("\tobj.");
Array::Ptr args2 = new Array();
args2->Add(attr);
args2->Add(value);
cw->EmitFunctionCall("modify_attribute", args2);
cw->EmitRaw("\n");
previousObject = object;
}
void IcingaApplication::DumpProgramState(void)
{
DynamicObject::DumpObjects(GetStatePath());
ConfigWriter::Ptr cw = new ConfigWriter(GetModAttrPath());
DynamicObject::Ptr previousObject;
DynamicObject::DumpModifiedAttributes(boost::bind(&PersistModAttrHelper, cw, boost::ref(previousObject), _1, _2, _3));
if (previousObject)
cw->EmitRaw("\n}\n");
}
IcingaApplication::Ptr IcingaApplication::GetInstance(void)