mirror of https://github.com/Icinga/icinga2.git
Fix object sync for modified attributes
refs #9851 refs #9927 refs #9081
This commit is contained in:
parent
487ef513cf
commit
bb3b724219
|
@ -24,6 +24,10 @@
|
|||
#include "base/configtype.hpp"
|
||||
#include "base/json.hpp"
|
||||
#include "base/convert.hpp"
|
||||
#include "config/vmops.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <fstream>
|
||||
|
||||
using namespace icinga;
|
||||
|
@ -109,11 +113,14 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
|
|||
|
||||
ConfigObject::Ptr object = dtype->GetObject(objName);
|
||||
|
||||
if (!object) {
|
||||
String config = params->Get("config");
|
||||
|
||||
if (!object && !config.IsEmpty()) {
|
||||
/* object does not exist, create it through the API */
|
||||
Array::Ptr errors = new Array();
|
||||
|
||||
if (!ConfigObjectUtility::CreateObject(Type::GetByName(objType),
|
||||
objName, params->Get("config"), errors)) {
|
||||
objName, config, errors)) {
|
||||
Log(LogCritical, "ApiListener")
|
||||
<< "Could not create object '" << objName << "':";
|
||||
|
||||
|
@ -121,15 +128,17 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
|
|||
BOOST_FOREACH(const String& error, errors) {
|
||||
Log(LogCritical, "ApiListener", error);
|
||||
}
|
||||
} else {
|
||||
/* object was created, update its version to its origin */
|
||||
ConfigObject::Ptr newObj = dtype->GetObject(objName);
|
||||
if (newObj)
|
||||
newObj->SetVersion(objVersion);
|
||||
|
||||
return Empty;
|
||||
}
|
||||
} else {
|
||||
/* object exists, update its attributes if version was changed */
|
||||
if (objVersion > object->GetVersion()) {
|
||||
|
||||
/* object was created, update its version to its origin */
|
||||
object = dtype->GetObject(objName);
|
||||
object->SetVersion(objVersion, false, origin);
|
||||
}
|
||||
|
||||
/* update object attributes if version was changed */
|
||||
if (object && objVersion > object->GetVersion()) {
|
||||
Log(LogInformation, "ApiListener")
|
||||
<< "Processing config update for object '" << object->GetName()
|
||||
<< "': Object version " << object->GetVersion()
|
||||
|
@ -149,7 +158,7 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
|
|||
}
|
||||
|
||||
/* keep the object version in sync with the sender */
|
||||
object->SetVersion(objVersion);
|
||||
object->SetVersion(objVersion, false, origin);
|
||||
} else {
|
||||
Log(LogNotice, "ApiListener")
|
||||
<< "Discarding config update for object '" << object->GetName()
|
||||
|
@ -157,7 +166,6 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
|
|||
<< " is more recent than the received version " << objVersion << ".";
|
||||
return Empty;
|
||||
}
|
||||
}
|
||||
|
||||
return Empty;
|
||||
}
|
||||
|
@ -211,7 +219,12 @@ Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin
|
|||
|
||||
ConfigObject::Ptr object = dtype->GetObject(params->Get("name"));
|
||||
|
||||
if (object) {
|
||||
if (!object) {
|
||||
Log(LogNotice, "ApiListener")
|
||||
<< "Could not delete non-existing object '" << params->Get("name") << "'.";
|
||||
return Empty;
|
||||
}
|
||||
|
||||
if (object->GetPackage() != "_api") {
|
||||
Log(LogCritical, "ApiListener")
|
||||
<< "Could not delete object '" << object->GetName() << "': Not created by the API.";
|
||||
|
@ -219,8 +232,8 @@ Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin
|
|||
}
|
||||
|
||||
Array::Ptr errors = new Array();
|
||||
bool cascade = true; //TODO pass that through the cluster
|
||||
if (!ConfigObjectUtility::DeleteObject(object, cascade, errors)) {
|
||||
|
||||
if (!ConfigObjectUtility::DeleteObject(object, true, errors)) {
|
||||
Log(LogCritical, "ApiListener", "Could not delete object:");
|
||||
|
||||
ObjectLock olock(errors);
|
||||
|
@ -228,10 +241,6 @@ Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin
|
|||
Log(LogCritical, "ApiListener", error);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log(LogNotice, "ApiListener")
|
||||
<< "Could not delete non-existing object '" << params->Get("name") << "'.";
|
||||
}
|
||||
|
||||
return Empty;
|
||||
}
|
||||
|
@ -239,9 +248,6 @@ Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin
|
|||
void ApiListener::UpdateConfigObject(const ConfigObject::Ptr& object, const MessageOrigin::Ptr& origin,
|
||||
const JsonRpcConnection::Ptr& client)
|
||||
{
|
||||
if (object->GetPackage() != "_api")
|
||||
return;
|
||||
|
||||
/* don't sync objects without a zone attribute */
|
||||
if (object->GetZoneName().IsEmpty())
|
||||
return;
|
||||
|
@ -257,6 +263,7 @@ void ApiListener::UpdateConfigObject(const ConfigObject::Ptr& object, const Mess
|
|||
/* required for acceptance criteria on the client */
|
||||
params->Set("zone", object->GetZoneName());
|
||||
|
||||
if (object->GetPackage() == "_api") {
|
||||
String file = ConfigObjectUtility::GetObjectConfigPath(object->GetReflectionType(), object->GetName());
|
||||
|
||||
std::ifstream fp(file.CStr(), std::ifstream::binary);
|
||||
|
@ -265,6 +272,7 @@ void ApiListener::UpdateConfigObject(const ConfigObject::Ptr& object, const Mess
|
|||
|
||||
String content((std::istreambuf_iterator<char>(fp)), std::istreambuf_iterator<char>());
|
||||
params->Set("config", content);
|
||||
}
|
||||
|
||||
Dictionary::Ptr original_attributes = object->GetOriginalAttributes();
|
||||
Dictionary::Ptr modified_attributes = new Dictionary();
|
||||
|
@ -272,9 +280,14 @@ void ApiListener::UpdateConfigObject(const ConfigObject::Ptr& object, const Mess
|
|||
if (original_attributes) {
|
||||
ObjectLock olock(original_attributes);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, original_attributes) {
|
||||
int fid = object->GetReflectionType()->GetFieldId(kv.first);
|
||||
//TODO-MA: vars.os
|
||||
Value value = static_cast<Object::Ptr>(object)->GetField(fid);
|
||||
std::vector<String> tokens;
|
||||
boost::algorithm::split(tokens, kv.first, boost::is_any_of("."));
|
||||
|
||||
Value value = object;
|
||||
BOOST_FOREACH(const String& token, tokens) {
|
||||
value = VMOps::GetField(value, token);
|
||||
}
|
||||
|
||||
modified_attributes->Set(kv.first, value);
|
||||
}
|
||||
}
|
||||
|
@ -343,9 +356,6 @@ void ApiListener::SendRuntimeConfigObjects(const JsonRpcConnection::Ptr& aclient
|
|||
|
||||
BOOST_FOREACH(const ConfigType::Ptr& dt, ConfigType::GetTypes()) {
|
||||
BOOST_FOREACH(const ConfigObject::Ptr& object, dt->GetObjects()) {
|
||||
if (object->GetPackage() != "_api")
|
||||
continue;
|
||||
|
||||
String objZone = object->GetZoneName();
|
||||
|
||||
/* don't sync objects without a zone attribute */
|
||||
|
|
Loading…
Reference in New Issue