Skip to content

Commit

Permalink
Introduce Endpoint#capabilities
Browse files Browse the repository at this point in the history
refs #8034
  • Loading branch information
Al2Klimov committed Oct 19, 2020
1 parent 9e29936 commit 40ac05c
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 6 deletions.
1 change: 1 addition & 0 deletions doc/19-technical-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,7 @@ params | Dictionary

Key | Type | Description
---------------------|-------------|------------------
capabilities | Number | Bitmask, see `lib/remote/apilistener.hpp`.
version | Number | Icinga 2 version, e.g. 21300 for v2.13.0.

##### Functions
Expand Down
4 changes: 2 additions & 2 deletions lib/icinga/apiactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,11 +821,11 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object,
std::set<Endpoint::Ptr> endpoints = zone->GetEndpoints();

for (const Endpoint::Ptr& childEndpoint : endpoints) {
if (childEndpoint->GetIcingaVersion() < 21300) {
if (!(childEndpoint->GetCapabilities() & (uint_fast64_t)ApiCapabilities::ExecuteArbitraryCommand)) {
/* Update execution */
double now = Utility::GetTime();
pending_execution->Set("exit", 126);
pending_execution->Set("output", "Endpoint '" + childEndpoint->GetName() + "' has version < 2.13.");
pending_execution->Set("output", "Endpoint '" + childEndpoint->GetName() + "' doesn't support executing arbitrary commands.");
pending_execution->Set("start", now);
pending_execution->Set("end", now);
pending_execution->Remove("pending");
Expand Down
4 changes: 2 additions & 2 deletions lib/icinga/clusterevents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ Value ClusterEvents::ExecuteCommandAPIHandler(const MessageOrigin::Ptr& origin,
std::set<Endpoint::Ptr> endpoints = zone->GetEndpoints();

for (const Endpoint::Ptr &childEndpoint : endpoints) {
if (childEndpoint->GetIcingaVersion() < 21300) {
if (!(childEndpoint->GetCapabilities() & (uint_fast64_t)ApiCapabilities::ExecuteArbitraryCommand)) {
double now = Utility::GetTime();
Dictionary::Ptr executedParams = new Dictionary();
executedParams->Set("execution", params->Get("source"));
Expand All @@ -650,7 +650,7 @@ Value ClusterEvents::ExecuteCommandAPIHandler(const MessageOrigin::Ptr& origin,
executedParams->Set("service", params->Get("service"));
executedParams->Set("exit", 126);
executedParams->Set("output",
"Endpoint '" + childEndpoint->GetName() + "' has version < 2.13.");
"Endpoint '" + childEndpoint->GetName() + "' doesn't support executing arbitrary commands.");
executedParams->Set("start", now);
executedParams->Set("end", now);

Expand Down
9 changes: 7 additions & 2 deletions lib/remote/apilistener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,8 @@ static const auto l_AppVersionInt (([]() -> unsigned long {
+ boost::lexical_cast<unsigned long>(match[3].str());
})());

static const auto l_MyCapabilities (ApiCapabilities::ExecuteArbitraryCommand);

/**
* Processes a new client connection.
*
Expand Down Expand Up @@ -667,7 +669,8 @@ void ApiListener::NewClientHandlerInternal(
{ "jsonrpc", "2.0" },
{ "method", "icinga::Hello" },
{ "params", new Dictionary({
{ "version", (double)l_AppVersionInt }
{ "version", (double)l_AppVersionInt },
{ "capabilities", (double)l_MyCapabilities }
}) }
}), yc);

Expand Down Expand Up @@ -705,7 +708,8 @@ void ApiListener::NewClientHandlerInternal(
{ "jsonrpc", "2.0" },
{ "method", "icinga::Hello" },
{ "params", new Dictionary({
{ "version", (double)l_AppVersionInt }
{ "version", (double)l_AppVersionInt },
{ "capabilities", (double)l_MyCapabilities }
}) }
}), yc);

Expand Down Expand Up @@ -1643,6 +1647,7 @@ Value ApiListener::HelloAPIHandler(const MessageOrigin::Ptr& origin, const Dicti

if (endpoint) {
endpoint->SetIcingaVersion((double)params->Get("version"));
endpoint->SetCapabilities((double)params->Get("capabilities"));
}
}
}
Expand Down
30 changes: 30 additions & 0 deletions lib/remote/apilistener.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/ssl/context.hpp>
#include <cstdint>
#include <set>

namespace icinga
Expand All @@ -38,6 +39,35 @@ struct ConfigDirInformation
Dictionary::Ptr Checksums;
};

/**
* If the version reported by icinga::Hello is not enough to tell whether
* the peer has a specific capability, add the latter to this bitmask.
*
* Note that due to the capability exchange via JSON-RPC and the state storage via JSON
* the bitmask numbers are stored in IEEE 754 64-bit floats.
* The latter have 53 digit bits which limit the bitmask.
* Not to run out of bits:
*
* Once all Icinga versions which don't have a specific capability are completely EOL,
* remove the respective capability checks and assume the peer has the capability.
* Once all Icinga versions which still check for the capability are completely EOL,
* remove the respective bit from icinga::Hello.
* Once all Icinga versions which still have the respective bit in icinga::Hello
* are completely EOL, remove the bit here.
* Once all Icinga versions which still have the respective bit here
* are completely EOL, feel free to re-use the bit.
*
* completely EOL = not supported, even if an important customer of us used it and
* not expected to appear in a multi-level cluster, e.g. a 4 level cluster with
* v2.11 -> v2.10 -> v2.9 -> v2.8 - v2.7 isn't here
*
* @ingroup remote
*/
enum class ApiCapabilities : uint_fast64_t
{
ExecuteArbitraryCommand = 1u
};

/**
* @ingroup remote
*/
Expand Down
4 changes: 4 additions & 0 deletions lib/remote/endpoint.ti
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#include "base/configobject.hpp"
#include <cstdint>

library remote;

Expand All @@ -24,6 +25,9 @@ class Endpoint : ConfigObject
[state] "unsigned long" icinga_version {
default {{{ return 0; }}}
};
[state] uint_fast64_t capabilities {
default {{{ return 0; }}}
};

[no_user_modify] bool connecting;
[no_user_modify] bool syncing;
Expand Down

0 comments on commit 40ac05c

Please sign in to comment.