Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
Next: API handler

refs #8140
  • Loading branch information
Al2Klimov committed Oct 29, 2020
1 parent 40ac05c commit 4451b2e
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 4 deletions.
1 change: 1 addition & 0 deletions doc/09-object-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ Configuration Attributes:
user\_groups | Array of object names | **Required.** A list of user group names who should be notified. **Optional.** if the `users` attribute is set.
times | Dictionary | **Optional.** A dictionary containing `begin` and `end` attributes for the notification.
command | Object name | **Required.** The name of the notification command which should be executed when the notification is triggered.
command\_endpoint | Object name | **Optional.** The endpoint where commands are executed on.
interval | Duration | **Optional.** The notification interval (in seconds). This interval is used for active notifications. Defaults to 30 minutes. If set to 0, [re-notifications](03-monitoring-basics.md#disable-renotification) are disabled.
period | Object name | **Optional.** The name of a time period which determines when this notification should be triggered. Not set by default (effectively 24x7).
zone | Object name | **Optional.** The zone this object is a member of. Please read the [distributed monitoring](06-distributed-monitoring.md#distributed-monitoring) chapter for details.
Expand Down
67 changes: 65 additions & 2 deletions lib/icinga/notification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,24 @@ void Notification::OnAllConfigLoaded()
if (!m_Checkable)
BOOST_THROW_EXCEPTION(ScriptError("Notification object refers to a host/service which doesn't exist.", GetDebugInfo()));

Endpoint::Ptr endpoint = GetCommandEndpoint();

if (endpoint) {
Zone::Ptr myZone = static_pointer_cast<Zone>(GetZone());

if (myZone) {
Zone::Ptr cmdZone = endpoint->GetZone();

if (cmdZone != myZone && cmdZone->GetParent() != myZone) {
BOOST_THROW_EXCEPTION(ValidationError(this, { "command_endpoint" },
"Command endpoint must be in zone '" + myZone->GetName() + "' or in a direct child zone thereof."));
}
} else {
BOOST_THROW_EXCEPTION(ValidationError(this, { "command_endpoint" },
"Notification with command endpoint requires a zone. Please check the troubleshooting documentation."));
}
}

GetCheckable()->RegisterNotification(this);
}

Expand Down Expand Up @@ -495,7 +513,8 @@ void Notification::ExecuteNotificationHelper(NotificationType type, const User::
{
String notificationName = GetName();
String userName = user->GetName();
String checkableName = GetCheckable()->GetName();
auto checkable (GetCheckable());
String checkableName = checkable->GetName();

NotificationCommand::Ptr command = GetCommand();

Expand All @@ -506,9 +525,53 @@ void Notification::ExecuteNotificationHelper(NotificationType type, const User::
}

String commandName = command->GetName();
ApiListener::Ptr listener = ApiListener::GetInstance();
Endpoint::Ptr endpoint = GetCommandEndpoint();
bool local = !endpoint || endpoint == Endpoint::GetLocalEndpoint();

if (!local && !(endpoint->GetCapabilities() & (uint_fast64_t)ApiCapabilities::ExecuteNotificationCommand)) {
Log(LogWarning, "Notification")
<< "Sending notification '" << GetName() << "' locally as its command endpoint '"
<< endpoint->GetName() << "' doesn't support executing notification commands. Consider upgrading it.";
local = true;
}

if (!local && (!endpoint->GetConnected() || !listener)) {
Log(LogWarning, "Notification")
<< "Sending notification '" << GetName() << "' locally as its command endpoint '"
<< endpoint->GetName() << "' is not connected.";
local = true;
}

try {
command->Execute(this, user, cr, type, author, text);
if (local) {
command->Execute(this, user, cr, type, author, text);
} else {
Dictionary::Ptr macros = new Dictionary();
Host::Ptr host;
Service::Ptr service;
Dictionary::Ptr params = new Dictionary();
Dictionary::Ptr message = new Dictionary();

command->Execute(this, user, cr, type, author, text, macros, false);
tie(host, service) = GetHostService(checkable);

params->Set("command_type", "notification_command");
params->Set("command", command->GetName());
params->Set("macros", macros);
params->Set("notification", GetName());
params->Set("user", user->GetName());
params->Set("host", host->GetName());

if (service)
params->Set("service", service->GetShortName());

message->Set("jsonrpc", "2.0");
message->Set("method", "event::ExecuteCommand");
message->Set("params", params);

listener->SyncSendMessage(endpoint, message);
}

/* required by compatlogger */
Service::OnNotificationSentToUser(this, GetCheckable(), user, type, cr, author, text, commandName, nullptr);
Expand Down
5 changes: 4 additions & 1 deletion lib/remote/apilistener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,10 @@ static const auto l_AppVersionInt (([]() -> unsigned long {
+ boost::lexical_cast<unsigned long>(match[3].str());
})());

static const auto l_MyCapabilities (ApiCapabilities::ExecuteArbitraryCommand);
static const auto l_MyCapabilities (
(uint_fast64_t)ApiCapabilities::ExecuteArbitraryCommand
| (uint_fast64_t)ApiCapabilities::ExecuteNotificationCommand
);

/**
* Processes a new client connection.
Expand Down
3 changes: 2 additions & 1 deletion lib/remote/apilistener.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ struct ConfigDirInformation
*/
enum class ApiCapabilities : uint_fast64_t
{
ExecuteArbitraryCommand = 1u
ExecuteArbitraryCommand = 1u,
ExecuteNotificationCommand = 2u
};

/**
Expand Down

0 comments on commit 4451b2e

Please sign in to comment.