Fix message origin for runtime created config object (create/delete events)

This commit is contained in:
Michael Friedrich 2019-08-13 14:53:06 +02:00
parent fcca9643bc
commit c30edd0a34
7 changed files with 67 additions and 24 deletions

View File

@ -357,7 +357,7 @@ void ConfigObject::PreActivate()
SetActive(true, true); SetActive(true, true);
} }
void ConfigObject::Activate(bool runtimeCreated) void ConfigObject::Activate(bool runtimeCreated, const Value& cookie)
{ {
CONTEXT("Activating object '" + GetName() + "' of type '" + GetReflectionType()->GetName() + "'"); CONTEXT("Activating object '" + GetName() + "' of type '" + GetReflectionType()->GetName() + "'");
@ -372,7 +372,7 @@ void ConfigObject::Activate(bool runtimeCreated)
SetAuthority(true); SetAuthority(true);
} }
NotifyActive(); NotifyActive(cookie);
} }
void ConfigObject::Stop(bool runtimeRemoved) void ConfigObject::Stop(bool runtimeRemoved)
@ -384,7 +384,7 @@ void ConfigObject::Stop(bool runtimeRemoved)
SetStopCalled(true); SetStopCalled(true);
} }
void ConfigObject::Deactivate(bool runtimeRemoved) void ConfigObject::Deactivate(bool runtimeRemoved, const Value& cookie)
{ {
CONTEXT("Deactivating object '" + GetName() + "' of type '" + GetReflectionType()->GetName() + "'"); CONTEXT("Deactivating object '" + GetName() + "' of type '" + GetReflectionType()->GetName() + "'");
@ -403,7 +403,7 @@ void ConfigObject::Deactivate(bool runtimeRemoved)
ASSERT(GetStopCalled()); ASSERT(GetStopCalled());
NotifyActive(); NotifyActive(cookie);
} }
void ConfigObject::OnConfigLoaded() void ConfigObject::OnConfigLoaded()

View File

@ -44,8 +44,8 @@ public:
void Unregister(); void Unregister();
void PreActivate(); void PreActivate();
void Activate(bool runtimeCreated = false); void Activate(bool runtimeCreated = false, const Value& cookie = Empty);
void Deactivate(bool runtimeRemoved = false); void Deactivate(bool runtimeRemoved = false, const Value& cookie = Empty);
void SetAuthority(bool authority); void SetAuthority(bool authority);
void Start(bool runtimeCreated = false) override; void Start(bool runtimeCreated = false) override;

View File

@ -624,7 +624,8 @@ bool ConfigItem::CommitItems(const ActivationContext::Ptr& context, WorkQueue& u
return true; return true;
} }
bool ConfigItem::ActivateItems(WorkQueue& upq, const std::vector<ConfigItem::Ptr>& newItems, bool runtimeCreated, bool silent, bool withModAttrs) bool ConfigItem::ActivateItems(WorkQueue& upq, const std::vector<ConfigItem::Ptr>& newItems, bool runtimeCreated,
bool silent, bool withModAttrs, const Value& cookie)
{ {
static boost::mutex mtx; static boost::mutex mtx;
boost::mutex::scoped_lock lock(mtx); boost::mutex::scoped_lock lock(mtx);
@ -692,7 +693,7 @@ bool ConfigItem::ActivateItems(WorkQueue& upq, const std::vector<ConfigItem::Ptr
<< objectType->GetActivationPriority(); << objectType->GetActivationPriority();
#endif /* I2_DEBUG */ #endif /* I2_DEBUG */
object->Activate(runtimeCreated); object->Activate(runtimeCreated, cookie);
} }
} }

View File

@ -53,7 +53,8 @@ public:
const String& name); const String& name);
static bool CommitItems(const ActivationContext::Ptr& context, WorkQueue& upq, std::vector<ConfigItem::Ptr>& newItems, bool silent = false); static bool CommitItems(const ActivationContext::Ptr& context, WorkQueue& upq, std::vector<ConfigItem::Ptr>& newItems, bool silent = false);
static bool ActivateItems(WorkQueue& upq, const std::vector<ConfigItem::Ptr>& newItems, bool runtimeCreated = false, bool silent = false, bool withModAttrs = false); static bool ActivateItems(WorkQueue& upq, const std::vector<ConfigItem::Ptr>& newItems, bool runtimeCreated = false,
bool silent = false, bool withModAttrs = false, const Value& cookie = Empty);
static bool RunWithActivationContext(const Function::Ptr& function); static bool RunWithActivationContext(const Function::Ptr& function);

View File

@ -99,7 +99,11 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
/* object does not exist, create it through the API */ /* object does not exist, create it through the API */
Array::Ptr errors = new Array(); Array::Ptr errors = new Array();
if (!ConfigObjectUtility::CreateObject(ptype, objName, config, errors, nullptr)) { /*
* Create the config object through our internal API.
* IMPORTANT: Pass the origin to prevent cluster sync loops.
*/
if (!ConfigObjectUtility::CreateObject(ptype, objName, config, errors, nullptr, origin)) {
Log(LogCritical, "ApiListener") Log(LogCritical, "ApiListener")
<< "Could not create object '" << objName << "':"; << "Could not create object '" << objName << "':";
@ -238,7 +242,11 @@ Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin
Array::Ptr errors = new Array(); Array::Ptr errors = new Array();
if (!ConfigObjectUtility::DeleteObject(object, true, errors, nullptr)) { /*
* Delete the config object through our internal API.
* IMPORTANT: Pass the origin to prevent cluster sync loops.
*/
if (!ConfigObjectUtility::DeleteObject(object, true, errors, nullptr, origin)) {
Log(LogCritical, "ApiListener", "Could not delete object:"); Log(LogCritical, "ApiListener", "Could not delete object:");
ObjectLock olock(errors); ObjectLock olock(errors);

View File

@ -148,7 +148,7 @@ String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const Stri
} }
bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& fullName, bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& fullName,
const String& config, const Array::Ptr& errors, const Array::Ptr& diagnosticInformation) const String& config, const Array::Ptr& errors, const Array::Ptr& diagnosticInformation, const Value& cookie)
{ {
CreateStorage(); CreateStorage();
@ -188,9 +188,37 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
std::vector<ConfigItem::Ptr> newItems; std::vector<ConfigItem::Ptr> newItems;
/* Disable logging for object creation, but do so ourselves later on. */ /*
if (!ConfigItem::CommitItems(ascope.GetContext(), upq, newItems, true) || !ConfigItem::ActivateItems(upq, newItems, true, true)) { * Disable logging for object creation, but do so ourselves later on.
* Duplicate the error handling for better logging and debugging here.
*/
if (!ConfigItem::CommitItems(ascope.GetContext(), upq, newItems, true)) {
if (errors) { if (errors) {
Log(LogNotice, "ConfigObjectUtility")
<< "Failed to commit config item '" << fullName << "'. Aborting and emoving config path '" << path << "'.";
Utility::Remove(path);
for (const boost::exception_ptr& ex : upq.GetExceptions()) {
errors->Add(DiagnosticInformation(ex, false));
if (diagnosticInformation)
diagnosticInformation->Add(DiagnosticInformation(ex));
}
}
return false;
}
/*
* Activate the config object.
* IMPORTANT: Forward the cookie aka origin in order to prevent sync loops in the same zone!
*/
if (!ConfigItem::ActivateItems(upq, newItems, true, true, cookie)) {
if (errors) {
Log(LogNotice, "ConfigObjectUtility")
<< "Failed to activate config object '" << fullName << "'. Aborting and emoving config path '" << path << "'.";
Utility::Remove(path); Utility::Remove(path);
for (const boost::exception_ptr& ex : upq.GetExceptions()) { for (const boost::exception_ptr& ex : upq.GetExceptions()) {
@ -211,7 +239,6 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
if (type->GetName() != "Comment" && type->GetName() != "Downtime") if (type->GetName() != "Comment" && type->GetName() != "Downtime")
ApiListener::UpdateObjectAuthority(); ApiListener::UpdateObjectAuthority();
Log(LogInformation, "ConfigObjectUtility") Log(LogInformation, "ConfigObjectUtility")
<< "Created and activated object '" << fullName << "' of type '" << type->GetName() << "'."; << "Created and activated object '" << fullName << "' of type '" << type->GetName() << "'.";
@ -231,7 +258,7 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
} }
bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade,
const Array::Ptr& errors, const Array::Ptr& diagnosticInformation) const Array::Ptr& errors, const Array::Ptr& diagnosticInformation, const Value& cookie)
{ {
std::vector<Object::Ptr> parents = DependencyGraph::GetParents(object); std::vector<Object::Ptr> parents = DependencyGraph::GetParents(object);
@ -255,7 +282,7 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
if (!parentObj) if (!parentObj)
continue; continue;
DeleteObjectHelper(parentObj, cascade, errors, diagnosticInformation); DeleteObjectHelper(parentObj, cascade, errors, diagnosticInformation, cookie);
} }
ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(type, name); ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(type, name);
@ -263,8 +290,13 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
try { try {
/* mark this object for cluster delete event */ /* mark this object for cluster delete event */
object->SetExtension("ConfigObjectDeleted", true); object->SetExtension("ConfigObjectDeleted", true);
/* triggers signal for DB IDO and other interfaces */
object->Deactivate(true); /*
* Trigger deactivation signal for DB IDO and runtime object delections.
* IMPORTANT: Specify the cookie aka origin in order to prevent sync loops
* in the same zone!
*/
object->Deactivate(true, cookie);
if (item) if (item)
item->Unregister(); item->Unregister();
@ -298,7 +330,8 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
return true; return true;
} }
bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors, const Array::Ptr& diagnosticInformation) bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors,
const Array::Ptr& diagnosticInformation, const Value& cookie)
{ {
if (object->GetPackage() != "_api") { if (object->GetPackage() != "_api") {
if (errors) if (errors)
@ -307,5 +340,5 @@ bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, bool cas
return false; return false;
} }
return DeleteObjectHelper(object, cascade, errors, diagnosticInformation); return DeleteObjectHelper(object, cascade, errors, diagnosticInformation, cookie);
} }

View File

@ -30,15 +30,15 @@ public:
bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs); bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs);
static bool CreateObject(const Type::Ptr& type, const String& fullName, static bool CreateObject(const Type::Ptr& type, const String& fullName,
const String& config, const Array::Ptr& errors, const Array::Ptr& diagnosticInformation); const String& config, const Array::Ptr& errors, const Array::Ptr& diagnosticInformation, const Value& cookie = Empty);
static bool DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors, static bool DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors,
const Array::Ptr& diagnosticInformation); const Array::Ptr& diagnosticInformation, const Value& cookie = Empty);
private: private:
static String EscapeName(const String& name); static String EscapeName(const String& name);
static bool DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors, static bool DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors,
const Array::Ptr& diagnosticInformation); const Array::Ptr& diagnosticInformation, const Value& cookie = Empty);
}; };
} }