From ee211daf766c2ef59f4865b41e17cc5991c83480 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Fri, 4 Sep 2020 15:48:05 +0200 Subject: [PATCH] Runtime objects: send config::HaveObjects to v2.13+ on connect refs #8210 --- lib/remote/apilistener-configsync.cpp | 58 ++++++++++++++++++++++++++- lib/remote/apilistener.cpp | 8 +++- lib/remote/apilistener.hpp | 1 + 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/lib/remote/apilistener-configsync.cpp b/lib/remote/apilistener-configsync.cpp index 4a55c2883..c34cdf42e 100644 --- a/lib/remote/apilistener-configsync.cpp +++ b/lib/remote/apilistener-configsync.cpp @@ -427,7 +427,7 @@ void ApiListener::DeleteConfigObject(const ConfigObject::Ptr& object, const Mess } } -/* Initial sync on connect for new endpoints */ +/* Initial sync on connect for new endpoints < v2.13 */ void ApiListener::SendRuntimeConfigObjects(const JsonRpcConnection::Ptr& aclient) { Endpoint::Ptr endpoint = aclient->GetEndpoint(); @@ -457,3 +457,59 @@ void ApiListener::SendRuntimeConfigObjects(const JsonRpcConnection::Ptr& aclient Log(LogInformation, "ApiListener") << "Finished syncing runtime objects to endpoint '" << endpoint->GetName() << "'."; } + +/* Initial sync on connect for new endpoints >= v2.13 */ +void ApiListener::DeclareRuntimeConfigObjects(const JsonRpcConnection::Ptr& aclient) +{ + Endpoint::Ptr endpoint = aclient->GetEndpoint(); + ASSERT(endpoint); + + Zone::Ptr azone = endpoint->GetZone(); + + Log(LogInformation, "ApiListener") + << "Informing endpoint '" << endpoint->GetName() << "' about runtime objects."; + + Dictionary::Ptr versions = new Dictionary(); + + for (auto& type : Type::GetAllTypes()) { + auto ctype (dynamic_cast(type.get())); + + if (!ctype) { + continue; + } + + for (auto& object : ctype->GetObjects()) { + if (object->GetPackage() != "_api" && object->GetVersion() == 0) { + continue; + } + + /* don't sync objects for non-matching parent-child zones */ + if (!azone->CanAccessObject(object)) { + continue; + } + + auto type (object->GetReflectionType()->GetName()); + Dictionary::Ptr perType = versions->Get(type); + + if (!perType) { + perType = new Dictionary(); + versions->Set(type, perType); + } + + perType->Set(object->GetName(), object->GetVersion()); + } + } + + if (versions->GetLength()) { + aclient->SendMessage(new Dictionary({ + { "jsonrpc", "2.0" }, + { "method", "config::HaveObjects" }, + { "params", new Dictionary({ + { "versions", versions } + }) } + })); + } + + Log(LogInformation, "ApiListener") + << "Finished informing endpoint '" << endpoint->GetName() << "' about runtime objects."; +} diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp index 49ed29198..e13ce231d 100644 --- a/lib/remote/apilistener.cpp +++ b/lib/remote/apilistener.cpp @@ -787,6 +787,8 @@ void ApiListener::SyncClient(const JsonRpcConnection::Ptr& aclient, const Endpoi Log(LogInformation, "ApiListener") << "Sending config updates for endpoint '" << endpoint->GetName() << "' in zone '" << eZone->GetName() << "'."; + bool negotiate = endpoint->GetVersion() >= 21300; + /* sync zone file config */ SendConfigUpdate(aclient); @@ -794,7 +796,11 @@ void ApiListener::SyncClient(const JsonRpcConnection::Ptr& aclient, const Endpoi << "Finished sending config file updates for endpoint '" << endpoint->GetName() << "' in zone '" << eZone->GetName() << "'."; /* sync runtime config */ - SendRuntimeConfigObjects(aclient); + if (negotiate) { + DeclareRuntimeConfigObjects(aclient); + } else { + SendRuntimeConfigObjects(aclient); + } Log(LogInformation, "ApiListener") << "Finished sending runtime config updates for endpoint '" << endpoint->GetName() << "' in zone '" << eZone->GetName() << "'."; diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index 4a3623a68..ad957093a 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -214,6 +214,7 @@ private: void DeleteConfigObject(const ConfigObject::Ptr& object, const MessageOrigin::Ptr& origin, const JsonRpcConnection::Ptr& client = nullptr); void SendRuntimeConfigObjects(const JsonRpcConnection::Ptr& aclient); + void DeclareRuntimeConfigObjects(const JsonRpcConnection::Ptr& client); void SyncClient(const JsonRpcConnection::Ptr& aclient, const Endpoint::Ptr& endpoint, bool needSync);