mirror of
https://github.com/Icinga/icinga2.git
synced 2025-09-24 18:28:00 +02:00
config::HaveObjects: send config::WantObjects if not up-to-date
refs #8210
This commit is contained in:
parent
ee211daf76
commit
61586ed6f2
@ -14,6 +14,7 @@ using namespace icinga;
|
||||
|
||||
REGISTER_APIFUNCTION(UpdateObject, config, &ApiListener::ConfigUpdateObjectAPIHandler);
|
||||
REGISTER_APIFUNCTION(DeleteObject, config, &ApiListener::ConfigDeleteObjectAPIHandler);
|
||||
REGISTER_APIFUNCTION(HaveObjects, config, &ApiListener::ConfigHaveObjectsAPIHandler);
|
||||
|
||||
INITIALIZE_ONCE([]() {
|
||||
ConfigObject::OnActiveChanged.connect(&ApiListener::ConfigUpdateObjectHandler);
|
||||
@ -194,6 +195,133 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
|
||||
return Empty;
|
||||
}
|
||||
|
||||
Value ApiListener::ConfigHaveObjectsAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
|
||||
{
|
||||
Log(LogNotice, "ApiListener")
|
||||
<< "Received information about runtime objects: " << JsonEncode(params);
|
||||
|
||||
/* check permissions */
|
||||
ApiListener::Ptr listener = ApiListener::GetInstance();
|
||||
|
||||
if (!listener)
|
||||
return Empty;
|
||||
|
||||
Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
|
||||
String identity = origin->FromClient->GetIdentity();
|
||||
|
||||
/* discard messages if the client is not configured on this node */
|
||||
if (!endpoint) {
|
||||
Log(LogNotice, "ApiListener")
|
||||
<< "Discarding 'config have objects' message from '" << identity << "': Invalid endpoint origin (client not allowed).";
|
||||
return Empty;
|
||||
}
|
||||
|
||||
Zone::Ptr endpointZone = endpoint->GetZone();
|
||||
|
||||
/* discard messages if the sender is in a child zone */
|
||||
if (!Zone::GetLocalZone()->IsChildOf(endpointZone)) {
|
||||
Log(LogNotice, "ApiListener")
|
||||
<< "Discarding 'config have objects' message"
|
||||
<< " from '" << identity << "' (endpoint: '" << endpoint->GetName() << "', zone: '" << endpointZone->GetName()
|
||||
<< "'). Sender is in a child zone.";
|
||||
return Empty;
|
||||
}
|
||||
|
||||
/* ignore messages if the endpoint does not accept config */
|
||||
if (!listener->GetAcceptConfig()) {
|
||||
Log(LogWarning, "ApiListener")
|
||||
<< "Ignoring information about runtime objects"
|
||||
<< " from '" << identity << "' (endpoint: '" << endpoint->GetName() << "', zone: '" << endpointZone->GetName()
|
||||
<< "'). '" << listener->GetName() << "' does not accept config.";
|
||||
return Empty;
|
||||
}
|
||||
|
||||
Dictionary::Ptr versions (params->Get("versions"));
|
||||
Dictionary::Ptr want = new Dictionary();
|
||||
ObjectLock oLock (versions);
|
||||
|
||||
for (auto& kv : versions) {
|
||||
auto type (Type::GetByName(kv.first));
|
||||
|
||||
if (!type) {
|
||||
Log(LogWarning, "ApiListener")
|
||||
<< "Bad object type in information about runtime objects from '"
|
||||
<< identity << "': '" << kv.first << "'";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto ctype (dynamic_cast<ConfigType*>(type.get()));
|
||||
|
||||
if (!ctype) {
|
||||
Log(LogWarning, "ApiListener")
|
||||
<< "Bad object type in information about runtime objects from '"
|
||||
<< identity << "': '" << kv.first << "'";
|
||||
continue;
|
||||
}
|
||||
|
||||
Dictionary::Ptr perType (kv.second);
|
||||
ObjectLock oLock (perType);
|
||||
|
||||
for (auto& kv : perType) {
|
||||
auto object (ctype->GetObject(kv.first));
|
||||
|
||||
if (object && object->GetVersion() >= (double)kv.second) {
|
||||
Log(LogNotice, "ApiListener")
|
||||
<< "Compared to the information about runtime objects from '" << identity << "' the "
|
||||
<< type->GetName() << " '" << object->GetName() << "' is up-to-date.";
|
||||
continue;
|
||||
}
|
||||
|
||||
Log(LogNotice, "ApiListener")
|
||||
<< "Compared to the information about runtime objects from '" << identity << "' the " << type->GetName()
|
||||
<< " '" << kv.first << "' is " << (object ? "outdated" : "missing") << ".";
|
||||
|
||||
Array::Ptr perType = want->Get(type->GetName());
|
||||
|
||||
if (!perType) {
|
||||
perType = new Array();
|
||||
want->Set(type->GetName(), perType);
|
||||
}
|
||||
|
||||
perType->Add(kv.first);
|
||||
}
|
||||
}
|
||||
|
||||
if (!want->GetLength()) {
|
||||
Log(LogNotice, "ApiListener")
|
||||
<< "Compared to the information about runtime objects from '" << identity << "' everything is up-to-date.";
|
||||
return Empty;
|
||||
}
|
||||
|
||||
JsonRpcConnection::Ptr client;
|
||||
|
||||
for (auto& conn : endpoint->GetClients()) {
|
||||
client = conn;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!client) {
|
||||
Log(LogNotice, "ApiListener")
|
||||
<< "Compared to the information about runtime objects from '" << identity
|
||||
<< "' not everything is up-to-date, but '" << identity << "' is not connected.";
|
||||
return Empty;
|
||||
}
|
||||
|
||||
Log(LogInformation, "ApiListener")
|
||||
<< "Compared to the information about runtime objects from '" << identity
|
||||
<< "' not everything is up-to-date. Requesting updates.";
|
||||
|
||||
client->SendMessage(new Dictionary({
|
||||
{ "jsonrpc", "2.0" },
|
||||
{ "method", "config::WantObjects" },
|
||||
{ "params", new Dictionary({
|
||||
{ "objects", want }
|
||||
}) }
|
||||
}));
|
||||
|
||||
return Empty;
|
||||
}
|
||||
|
||||
Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
|
||||
{
|
||||
Log(LogNotice, "ApiListener")
|
||||
|
@ -91,6 +91,7 @@ public:
|
||||
static void ConfigUpdateObjectHandler(const ConfigObject::Ptr& object, const Value& cookie);
|
||||
static Value ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);
|
||||
static Value ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);
|
||||
static Value ConfigHaveObjectsAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);
|
||||
|
||||
/* API config packages */
|
||||
void SetActivePackageStage(const String& package, const String& stage);
|
||||
|
Loading…
x
Reference in New Issue
Block a user