2019-02-25 14:48:22 +01:00
|
|
|
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
2015-07-30 17:50:17 +02:00
|
|
|
|
|
|
|
#include "icinga/apiactions.hpp"
|
|
|
|
#include "icinga/service.hpp"
|
2015-08-03 15:27:09 +02:00
|
|
|
#include "icinga/servicegroup.hpp"
|
|
|
|
#include "icinga/hostgroup.hpp"
|
2015-07-31 17:18:49 +02:00
|
|
|
#include "icinga/pluginutility.hpp"
|
2015-08-03 15:27:09 +02:00
|
|
|
#include "icinga/checkcommand.hpp"
|
|
|
|
#include "icinga/eventcommand.hpp"
|
|
|
|
#include "icinga/notificationcommand.hpp"
|
2020-06-30 13:43:00 +02:00
|
|
|
#include "icinga/clusterevents.hpp"
|
2015-07-30 17:50:17 +02:00
|
|
|
#include "remote/apiaction.hpp"
|
2016-08-15 14:32:41 +02:00
|
|
|
#include "remote/apilistener.hpp"
|
2017-09-05 14:44:56 +02:00
|
|
|
#include "remote/pkiutility.hpp"
|
2015-07-30 17:50:17 +02:00
|
|
|
#include "remote/httputility.hpp"
|
|
|
|
#include "base/utility.hpp"
|
|
|
|
#include "base/convert.hpp"
|
2015-08-21 15:50:40 +02:00
|
|
|
#include <fstream>
|
2015-07-30 17:50:17 +02:00
|
|
|
|
|
|
|
using namespace icinga;
|
|
|
|
|
2015-08-03 15:27:09 +02:00
|
|
|
REGISTER_APIACTION(process_check_result, "Service;Host", &ApiActions::ProcessCheckResult);
|
|
|
|
REGISTER_APIACTION(reschedule_check, "Service;Host", &ApiActions::RescheduleCheck);
|
2015-10-16 11:44:18 +02:00
|
|
|
REGISTER_APIACTION(send_custom_notification, "Service;Host", &ApiActions::SendCustomNotification);
|
|
|
|
REGISTER_APIACTION(delay_notification, "Service;Host", &ApiActions::DelayNotification);
|
2015-08-03 15:27:09 +02:00
|
|
|
REGISTER_APIACTION(acknowledge_problem, "Service;Host", &ApiActions::AcknowledgeProblem);
|
|
|
|
REGISTER_APIACTION(remove_acknowledgement, "Service;Host", &ApiActions::RemoveAcknowledgement);
|
|
|
|
REGISTER_APIACTION(add_comment, "Service;Host", &ApiActions::AddComment);
|
2015-11-08 12:41:47 +01:00
|
|
|
REGISTER_APIACTION(remove_comment, "Service;Host;Comment", &ApiActions::RemoveComment);
|
2015-08-21 12:47:49 +02:00
|
|
|
REGISTER_APIACTION(schedule_downtime, "Service;Host", &ApiActions::ScheduleDowntime);
|
2015-11-08 12:41:47 +01:00
|
|
|
REGISTER_APIACTION(remove_downtime, "Service;Host;Downtime", &ApiActions::RemoveDowntime);
|
2015-08-03 15:27:09 +02:00
|
|
|
REGISTER_APIACTION(shutdown_process, "", &ApiActions::ShutdownProcess);
|
|
|
|
REGISTER_APIACTION(restart_process, "", &ApiActions::RestartProcess);
|
2016-08-15 14:32:41 +02:00
|
|
|
REGISTER_APIACTION(generate_ticket, "", &ApiActions::GenerateTicket);
|
2020-06-02 11:43:32 +02:00
|
|
|
REGISTER_APIACTION(execute_command, "Service;Host", &ApiActions::ExecuteCommand);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::CreateResult(int code, const String& status,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& additional)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
2018-01-11 11:17:38 +01:00
|
|
|
Dictionary::Ptr result = new Dictionary({
|
|
|
|
{ "code", code },
|
|
|
|
{ "status", status }
|
|
|
|
});
|
2015-08-21 12:47:49 +02:00
|
|
|
|
|
|
|
if (additional)
|
|
|
|
additional->CopyTo(result);
|
|
|
|
|
2015-07-31 17:18:49 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::ProcessCheckResult(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-07-31 17:18:49 +02:00
|
|
|
{
|
|
|
|
Checkable::Ptr checkable = static_pointer_cast<Checkable>(object);
|
|
|
|
|
|
|
|
if (!checkable)
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(404,
|
2017-12-19 15:50:05 +01:00
|
|
|
"Cannot process passive check result for non-existent object.");
|
2015-07-31 17:18:49 +02:00
|
|
|
|
|
|
|
if (!checkable->GetEnablePassiveChecks())
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(403, "Passive checks are disabled for object '" + checkable->GetName() + "'.");
|
2015-07-31 17:18:49 +02:00
|
|
|
|
|
|
|
Host::Ptr host;
|
|
|
|
Service::Ptr service;
|
|
|
|
tie(host, service) = GetHostService(checkable);
|
|
|
|
|
|
|
|
if (!params->Contains("exit_status"))
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "Parameter 'exit_status' is required.");
|
2015-07-31 17:18:49 +02:00
|
|
|
|
|
|
|
int exitStatus = HttpUtility::GetLastParameter(params, "exit_status");
|
|
|
|
|
|
|
|
ServiceState state;
|
|
|
|
|
|
|
|
if (!service) {
|
|
|
|
if (exitStatus == 0)
|
|
|
|
state = ServiceOK;
|
|
|
|
else if (exitStatus == 1)
|
|
|
|
state = ServiceCritical;
|
|
|
|
else
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "Invalid 'exit_status' for Host "
|
2017-12-19 15:50:05 +01:00
|
|
|
+ checkable->GetName() + ".");
|
2015-07-31 17:18:49 +02:00
|
|
|
} else {
|
|
|
|
state = PluginUtility::ExitStatusToState(exitStatus);
|
|
|
|
}
|
|
|
|
|
2015-08-03 15:27:09 +02:00
|
|
|
if (!params->Contains("plugin_output"))
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "Parameter 'plugin_output' is required");
|
2015-07-31 17:18:49 +02:00
|
|
|
|
|
|
|
CheckResult::Ptr cr = new CheckResult();
|
2015-08-03 15:27:09 +02:00
|
|
|
cr->SetOutput(HttpUtility::GetLastParameter(params, "plugin_output"));
|
2015-07-31 17:18:49 +02:00
|
|
|
cr->SetState(state);
|
|
|
|
|
2017-08-21 17:20:56 +02:00
|
|
|
if (params->Contains("execution_start"))
|
|
|
|
cr->SetExecutionStart(HttpUtility::GetLastParameter(params, "execution_start"));
|
|
|
|
|
|
|
|
if (params->Contains("execution_end"))
|
|
|
|
cr->SetExecutionEnd(HttpUtility::GetLastParameter(params, "execution_end"));
|
|
|
|
|
2015-07-31 17:18:49 +02:00
|
|
|
cr->SetCheckSource(HttpUtility::GetLastParameter(params, "check_source"));
|
2018-02-06 15:25:55 +01:00
|
|
|
|
|
|
|
Value perfData = params->Get("performance_data");
|
|
|
|
|
|
|
|
/* Allow to pass a performance data string from Icinga Web 2 next to the new Array notation. */
|
|
|
|
if (perfData.IsString())
|
|
|
|
cr->SetPerformanceData(PluginUtility::SplitPerfdata(perfData));
|
|
|
|
else
|
|
|
|
cr->SetPerformanceData(perfData);
|
|
|
|
|
2015-08-03 15:27:09 +02:00
|
|
|
cr->SetCommand(params->Get("check_command"));
|
2016-03-11 10:30:50 +01:00
|
|
|
|
|
|
|
/* Mark this check result as passive. */
|
|
|
|
cr->SetActive(false);
|
|
|
|
|
2018-01-11 17:10:46 +01:00
|
|
|
/* Result TTL allows to overrule the next expected freshness check. */
|
|
|
|
if (params->Contains("ttl"))
|
|
|
|
cr->SetTtl(HttpUtility::GetLastParameter(params, "ttl"));
|
|
|
|
|
2015-07-31 17:18:49 +02:00
|
|
|
checkable->ProcessCheckResult(cr);
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(200, "Successfully processed check result for object '" + checkable->GetName() + "'.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::RescheduleCheck(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
|
|
|
Checkable::Ptr checkable = static_pointer_cast<Checkable>(object);
|
|
|
|
|
|
|
|
if (!checkable)
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(404, "Cannot reschedule check for non-existent object.");
|
|
|
|
|
|
|
|
if (Convert::ToBool(HttpUtility::GetLastParameter(params, "force")))
|
|
|
|
checkable->SetForceNextCheck(true);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
double nextCheck;
|
|
|
|
if (params->Contains("next_check"))
|
|
|
|
nextCheck = HttpUtility::GetLastParameter(params, "next_check");
|
|
|
|
else
|
|
|
|
nextCheck = Utility::GetTime();
|
|
|
|
|
|
|
|
checkable->SetNextCheck(nextCheck);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2016-01-22 18:42:15 +01:00
|
|
|
/* trigger update event for DB IDO */
|
|
|
|
Checkable::OnNextCheckUpdated(checkable);
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(200, "Successfully rescheduled check for object '" + checkable->GetName() + "'.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::SendCustomNotification(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
|
|
|
Checkable::Ptr checkable = static_pointer_cast<Checkable>(object);
|
|
|
|
|
|
|
|
if (!checkable)
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(404, "Cannot send notification for non-existent object.");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
if (!params->Contains("author"))
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "Parameter 'author' is required.");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
if (!params->Contains("comment"))
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "Parameter 'comment' is required.");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
if (Convert::ToBool(HttpUtility::GetLastParameter(params, "force")))
|
|
|
|
checkable->SetForceNextNotification(true);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Checkable::OnNotificationsRequested(checkable, NotificationCustom, checkable->GetLastCheckResult(),
|
2017-12-19 15:50:05 +01:00
|
|
|
HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), nullptr);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(200, "Successfully sent custom notification for object '" + checkable->GetName() + "'.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::DelayNotification(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
2015-08-21 12:47:49 +02:00
|
|
|
Checkable::Ptr checkable = static_pointer_cast<Checkable>(object);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-08-21 12:47:49 +02:00
|
|
|
if (!checkable)
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(404, "Cannot delay notifications for non-existent object");
|
|
|
|
|
|
|
|
if (!params->Contains("timestamp"))
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "A timestamp is required to delay notifications");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2016-08-25 06:19:44 +02:00
|
|
|
for (const Notification::Ptr& notification : checkable->GetNotifications()) {
|
2015-10-16 11:44:18 +02:00
|
|
|
notification->SetNextNotification(HttpUtility::GetLastParameter(params, "timestamp"));
|
|
|
|
}
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(200, "Successfully delayed notifications for object '" + checkable->GetName() + "'.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::AcknowledgeProblem(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
|
|
|
Checkable::Ptr checkable = static_pointer_cast<Checkable>(object);
|
|
|
|
|
|
|
|
if (!checkable)
|
2015-08-21 12:47:49 +02:00
|
|
|
return ApiActions::CreateResult(404, "Cannot acknowledge problem for non-existent object.");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
|
|
|
if (!params->Contains("author") || !params->Contains("comment"))
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "Acknowledgements require author and comment.");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
|
|
|
AcknowledgementType sticky = AcknowledgementNormal;
|
|
|
|
bool notify = false;
|
2017-01-25 21:21:22 +01:00
|
|
|
bool persistent = false;
|
2015-08-21 12:47:49 +02:00
|
|
|
double timestamp = 0.0;
|
2015-10-16 11:44:18 +02:00
|
|
|
|
2017-01-12 11:43:22 +01:00
|
|
|
if (params->Contains("sticky") && HttpUtility::GetLastParameter(params, "sticky"))
|
2015-08-03 15:27:09 +02:00
|
|
|
sticky = AcknowledgementSticky;
|
|
|
|
if (params->Contains("notify"))
|
2017-01-12 11:43:22 +01:00
|
|
|
notify = HttpUtility::GetLastParameter(params, "notify");
|
2017-01-25 21:21:22 +01:00
|
|
|
if (params->Contains("persistent"))
|
|
|
|
persistent = HttpUtility::GetLastParameter(params, "persistent");
|
2017-05-15 10:14:19 +02:00
|
|
|
if (params->Contains("expiry")) {
|
2015-10-16 11:44:18 +02:00
|
|
|
timestamp = HttpUtility::GetLastParameter(params, "expiry");
|
2017-05-15 10:14:19 +02:00
|
|
|
|
|
|
|
if (timestamp <= Utility::GetTime())
|
|
|
|
return ApiActions::CreateResult(409, "Acknowledgement 'expiry' timestamp must be in the future for object " + checkable->GetName());
|
|
|
|
} else
|
2015-10-16 11:44:18 +02:00
|
|
|
timestamp = 0;
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2019-12-05 11:08:16 +01:00
|
|
|
ObjectLock oLock (checkable);
|
|
|
|
|
2015-08-03 15:27:09 +02:00
|
|
|
Host::Ptr host;
|
|
|
|
Service::Ptr service;
|
|
|
|
tie(host, service) = GetHostService(checkable);
|
|
|
|
|
2015-07-31 17:18:49 +02:00
|
|
|
if (!service) {
|
2015-08-03 15:27:09 +02:00
|
|
|
if (host->GetState() == HostUp)
|
2015-08-21 12:47:49 +02:00
|
|
|
return ApiActions::CreateResult(409, "Host " + checkable->GetName() + " is UP.");
|
2015-08-03 15:27:09 +02:00
|
|
|
} else {
|
|
|
|
if (service->GetState() == ServiceOK)
|
2015-08-21 12:47:49 +02:00
|
|
|
return ApiActions::CreateResult(409, "Service " + checkable->GetName() + " is OK.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2019-12-05 11:08:16 +01:00
|
|
|
if (checkable->IsAcknowledged()) {
|
|
|
|
return ApiActions::CreateResult(409, (service ? "Service " : "Host ") + checkable->GetName() + " is already acknowledged.");
|
|
|
|
}
|
|
|
|
|
2015-08-20 17:18:48 +02:00
|
|
|
Comment::AddComment(checkable, CommentAcknowledgement, HttpUtility::GetLastParameter(params, "author"),
|
2017-12-19 15:50:05 +01:00
|
|
|
HttpUtility::GetLastParameter(params, "comment"), persistent, timestamp);
|
2015-08-03 15:27:09 +02:00
|
|
|
checkable->AcknowledgeProblem(HttpUtility::GetLastParameter(params, "author"),
|
2019-12-04 15:19:03 +01:00
|
|
|
HttpUtility::GetLastParameter(params, "comment"), sticky, notify, persistent, Utility::GetTime(), timestamp);
|
2015-08-21 12:47:49 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(200, "Successfully acknowledged problem for object '" + checkable->GetName() + "'.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::RemoveAcknowledgement(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
|
|
|
Checkable::Ptr checkable = static_pointer_cast<Checkable>(object);
|
|
|
|
|
|
|
|
if (!checkable)
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(404,
|
2018-10-22 14:19:16 +02:00
|
|
|
"Cannot remove acknowledgement for non-existent checkable object "
|
2017-12-19 15:50:05 +01:00
|
|
|
+ object->GetName() + ".");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2019-11-28 17:46:12 +01:00
|
|
|
String removedBy (HttpUtility::GetLastParameter(params, "author"));
|
|
|
|
|
|
|
|
checkable->ClearAcknowledgement(removedBy);
|
|
|
|
checkable->RemoveCommentsByType(CommentAcknowledgement, removedBy);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(200, "Successfully removed acknowledgement for object '" + checkable->GetName() + "'.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::AddComment(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
|
|
|
Checkable::Ptr checkable = static_pointer_cast<Checkable>(object);
|
|
|
|
|
|
|
|
if (!checkable)
|
|
|
|
return ApiActions::CreateResult(404, "Cannot add comment for non-existent object");
|
|
|
|
|
|
|
|
if (!params->Contains("author") || !params->Contains("comment"))
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "Comments require author and comment.");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
String commentName = Comment::AddComment(checkable, CommentUser,
|
2017-12-19 15:50:05 +01:00
|
|
|
HttpUtility::GetLastParameter(params, "author"),
|
|
|
|
HttpUtility::GetLastParameter(params, "comment"), false, 0);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
Comment::Ptr comment = Comment::GetByName(commentName);
|
2015-08-21 12:47:49 +02:00
|
|
|
|
2018-01-11 11:17:38 +01:00
|
|
|
Dictionary::Ptr additional = new Dictionary({
|
|
|
|
{ "name", commentName },
|
|
|
|
{ "legacy_id", comment->GetLegacyId() }
|
|
|
|
});
|
2015-08-21 12:47:49 +02:00
|
|
|
|
2015-11-06 16:45:09 +01:00
|
|
|
return ApiActions::CreateResult(200, "Successfully added comment '"
|
2017-12-19 15:50:05 +01:00
|
|
|
+ commentName + "' for object '" + checkable->GetName()
|
|
|
|
+ "'.", additional);
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
Dictionary::Ptr ApiActions::RemoveComment(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
2019-11-21 15:53:40 +01:00
|
|
|
auto author (HttpUtility::GetLastParameter(params, "author"));
|
2015-11-08 12:41:47 +01:00
|
|
|
Checkable::Ptr checkable = dynamic_pointer_cast<Checkable>(object);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
if (checkable) {
|
|
|
|
std::set<Comment::Ptr> comments = checkable->GetComments();
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2016-08-25 06:19:44 +02:00
|
|
|
for (const Comment::Ptr& comment : comments) {
|
2019-11-21 15:53:40 +01:00
|
|
|
{
|
|
|
|
ObjectLock oLock (comment);
|
|
|
|
comment->SetRemovedBy(author);
|
|
|
|
}
|
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
Comment::RemoveComment(comment->GetName());
|
|
|
|
}
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
return ApiActions::CreateResult(200, "Successfully removed all comments for object '" + checkable->GetName() + "'.");
|
|
|
|
}
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
Comment::Ptr comment = static_pointer_cast<Comment>(object);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
if (!comment)
|
|
|
|
return ApiActions::CreateResult(404, "Cannot remove non-existent comment object.");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2019-11-21 15:53:40 +01:00
|
|
|
{
|
|
|
|
ObjectLock oLock (comment);
|
|
|
|
comment->SetRemovedBy(author);
|
|
|
|
}
|
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
String commentName = comment->GetName();
|
2015-08-21 12:47:49 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
Comment::RemoveComment(commentName);
|
2015-11-01 16:33:43 +01:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
return ApiActions::CreateResult(200, "Successfully removed comment '" + commentName + "'.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
|
|
|
Checkable::Ptr checkable = static_pointer_cast<Checkable>(object);
|
|
|
|
|
|
|
|
if (!checkable)
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(404, "Can't schedule downtime for non-existent object.");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
if (!params->Contains("start_time") || !params->Contains("end_time") ||
|
2017-12-19 15:50:05 +01:00
|
|
|
!params->Contains("author") || !params->Contains("comment")) {
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "Options 'start_time', 'end_time', 'author' and 'comment' are required");
|
2015-10-16 11:44:18 +02:00
|
|
|
}
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2016-02-08 16:04:41 +01:00
|
|
|
bool fixed = true;
|
2015-08-03 15:27:09 +02:00
|
|
|
if (params->Contains("fixed"))
|
2015-08-21 12:47:49 +02:00
|
|
|
fixed = HttpUtility::GetLastParameter(params, "fixed");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2016-08-16 17:08:41 +02:00
|
|
|
if (!fixed && !params->Contains("duration"))
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "Option 'duration' is required for flexible downtime");
|
2016-08-16 17:08:41 +02:00
|
|
|
|
2016-10-05 17:36:43 +02:00
|
|
|
double duration = 0.0;
|
|
|
|
if (params->Contains("duration"))
|
|
|
|
duration = HttpUtility::GetLastParameter(params, "duration");
|
|
|
|
|
|
|
|
String triggerName;
|
|
|
|
if (params->Contains("trigger_name"))
|
|
|
|
triggerName = HttpUtility::GetLastParameter(params, "trigger_name");
|
|
|
|
|
|
|
|
String author = HttpUtility::GetLastParameter(params, "author");
|
|
|
|
String comment = HttpUtility::GetLastParameter(params, "comment");
|
|
|
|
double startTime = HttpUtility::GetLastParameter(params, "start_time");
|
|
|
|
double endTime = HttpUtility::GetLastParameter(params, "end_time");
|
|
|
|
|
2019-06-03 16:01:10 +02:00
|
|
|
Host::Ptr host;
|
|
|
|
Service::Ptr service;
|
|
|
|
tie(host, service) = GetHostService(checkable);
|
|
|
|
|
2018-10-24 11:00:24 +02:00
|
|
|
DowntimeChildOptions childOptions = DowntimeNoChildren;
|
|
|
|
if (params->Contains("child_options")) {
|
|
|
|
try {
|
|
|
|
childOptions = Downtime::ChildOptionsFromValue(HttpUtility::GetLastParameter(params, "child_options"));
|
|
|
|
} catch (const std::exception&) {
|
|
|
|
return ApiActions::CreateResult(400, "Option 'child_options' provided an invalid value.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-05 17:36:43 +02:00
|
|
|
String downtimeName = Downtime::AddDowntime(checkable, author, comment, startTime, endTime,
|
2017-12-19 15:50:05 +01:00
|
|
|
fixed, triggerName, duration);
|
2015-08-21 12:47:49 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
Downtime::Ptr downtime = Downtime::GetByName(downtimeName);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2018-01-11 11:17:38 +01:00
|
|
|
Dictionary::Ptr additional = new Dictionary({
|
|
|
|
{ "name", downtimeName },
|
|
|
|
{ "legacy_id", downtime->GetLegacyId() }
|
|
|
|
});
|
2015-08-21 12:47:49 +02:00
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
/* Schedule downtime for all services for the host type. */
|
|
|
|
bool allServices = false;
|
|
|
|
|
|
|
|
if (params->Contains("all_services"))
|
|
|
|
allServices = HttpUtility::GetLastParameter(params, "all_services");
|
|
|
|
|
|
|
|
if (allServices && !service) {
|
|
|
|
ArrayData serviceDowntimes;
|
|
|
|
|
|
|
|
for (const Service::Ptr& hostService : host->GetServices()) {
|
|
|
|
Log(LogNotice, "ApiActions")
|
|
|
|
<< "Creating downtime for service " << hostService->GetName() << " on host " << host->GetName();
|
|
|
|
|
|
|
|
String serviceDowntimeName = Downtime::AddDowntime(hostService, author, comment, startTime, endTime,
|
|
|
|
fixed, triggerName, duration);
|
|
|
|
|
|
|
|
Downtime::Ptr serviceDowntime = Downtime::GetByName(serviceDowntimeName);
|
|
|
|
|
|
|
|
serviceDowntimes.push_back(new Dictionary({
|
|
|
|
{ "name", serviceDowntimeName },
|
|
|
|
{ "legacy_id", serviceDowntime->GetLegacyId() }
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
additional->Set("service_downtimes", new Array(std::move(serviceDowntimes)));
|
|
|
|
}
|
|
|
|
|
2016-10-05 17:36:43 +02:00
|
|
|
/* Schedule downtime for all child objects. */
|
2018-08-08 14:42:18 +02:00
|
|
|
if (childOptions != DowntimeNoChildren) {
|
|
|
|
/* 'DowntimeTriggeredChildren' schedules child downtimes triggered by the parent downtime.
|
|
|
|
* 'DowntimeNonTriggeredChildren' schedules non-triggered downtimes for all children.
|
2016-10-05 17:36:43 +02:00
|
|
|
*/
|
2018-08-08 14:42:18 +02:00
|
|
|
if (childOptions == DowntimeTriggeredChildren)
|
2016-10-05 17:36:43 +02:00
|
|
|
triggerName = downtimeName;
|
|
|
|
|
2018-08-08 14:42:18 +02:00
|
|
|
Log(LogNotice, "ApiActions")
|
2017-12-19 15:50:05 +01:00
|
|
|
<< "Processing child options " << childOptions << " for downtime " << downtimeName;
|
2016-10-05 17:36:43 +02:00
|
|
|
|
2018-01-11 11:17:38 +01:00
|
|
|
ArrayData childDowntimes;
|
|
|
|
|
2016-10-05 17:36:43 +02:00
|
|
|
for (const Checkable::Ptr& child : checkable->GetAllChildren()) {
|
2018-08-08 14:42:18 +02:00
|
|
|
Log(LogNotice, "ApiActions")
|
2017-12-19 15:50:05 +01:00
|
|
|
<< "Scheduling downtime for child object " << child->GetName();
|
2016-10-05 17:36:43 +02:00
|
|
|
|
|
|
|
String childDowntimeName = Downtime::AddDowntime(child, author, comment, startTime, endTime,
|
2017-12-19 15:50:05 +01:00
|
|
|
fixed, triggerName, duration);
|
2016-10-05 17:36:43 +02:00
|
|
|
|
2018-08-08 14:42:18 +02:00
|
|
|
Log(LogNotice, "ApiActions")
|
2017-12-19 15:50:05 +01:00
|
|
|
<< "Add child downtime '" << childDowntimeName << "'.";
|
2016-10-05 17:36:43 +02:00
|
|
|
|
|
|
|
Downtime::Ptr childDowntime = Downtime::GetByName(childDowntimeName);
|
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
Dictionary::Ptr childAdditional = new Dictionary({
|
2018-01-11 11:17:38 +01:00
|
|
|
{ "name", childDowntimeName },
|
|
|
|
{ "legacy_id", childDowntime->GetLegacyId() }
|
2019-06-04 10:04:54 +02:00
|
|
|
});
|
2016-10-05 17:36:43 +02:00
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
/* For a host, also schedule all service downtimes if requested. */
|
|
|
|
Host::Ptr childHost;
|
|
|
|
Service::Ptr childService;
|
|
|
|
tie(childHost, childService) = GetHostService(child);
|
2016-10-05 17:36:43 +02:00
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
if (allServices && !childService) {
|
|
|
|
ArrayData childServiceDowntimes;
|
2019-06-03 16:01:10 +02:00
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
for (const Service::Ptr& hostService : host->GetServices()) {
|
|
|
|
Log(LogNotice, "ApiActions")
|
|
|
|
<< "Creating downtime for service " << hostService->GetName() << " on child host " << host->GetName();
|
2019-06-03 16:01:10 +02:00
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
String serviceDowntimeName = Downtime::AddDowntime(hostService, author, comment, startTime, endTime,
|
|
|
|
fixed, triggerName, duration);
|
2019-06-03 16:01:10 +02:00
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
Downtime::Ptr serviceDowntime = Downtime::GetByName(serviceDowntimeName);
|
2019-06-03 16:01:10 +02:00
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
childServiceDowntimes.push_back(new Dictionary({
|
|
|
|
{ "name", serviceDowntimeName },
|
|
|
|
{ "legacy_id", serviceDowntime->GetLegacyId() }
|
|
|
|
}));
|
|
|
|
}
|
2019-06-03 16:01:10 +02:00
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
childAdditional->Set("service_downtimes", new Array(std::move(childServiceDowntimes)));
|
|
|
|
}
|
2019-06-03 16:01:10 +02:00
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
childDowntimes.push_back(childAdditional);
|
2019-06-03 16:01:10 +02:00
|
|
|
}
|
|
|
|
|
2019-06-04 10:04:54 +02:00
|
|
|
additional->Set("child_downtimes", new Array(std::move(childDowntimes)));
|
2019-06-03 16:01:10 +02:00
|
|
|
}
|
|
|
|
|
2015-11-06 16:45:09 +01:00
|
|
|
return ApiActions::CreateResult(200, "Successfully scheduled downtime '" +
|
2017-12-19 15:50:05 +01:00
|
|
|
downtimeName + "' for object '" + checkable->GetName() + "'.", additional);
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
Dictionary::Ptr ApiActions::RemoveDowntime(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
2019-11-21 15:28:25 +01:00
|
|
|
auto author (HttpUtility::GetLastParameter(params, "author"));
|
2015-11-08 12:41:47 +01:00
|
|
|
Checkable::Ptr checkable = dynamic_pointer_cast<Checkable>(object);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
if (checkable) {
|
|
|
|
std::set<Downtime::Ptr> downtimes = checkable->GetDowntimes();
|
2015-08-21 15:50:40 +02:00
|
|
|
|
2016-08-25 06:19:44 +02:00
|
|
|
for (const Downtime::Ptr& downtime : downtimes) {
|
2019-11-21 15:28:25 +01:00
|
|
|
{
|
|
|
|
ObjectLock oLock (downtime);
|
|
|
|
downtime->SetRemovedBy(author);
|
|
|
|
}
|
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
Downtime::RemoveDowntime(downtime->GetName(), true);
|
|
|
|
}
|
2015-08-21 15:50:40 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
return ApiActions::CreateResult(200, "Successfully removed all downtimes for object '" + checkable->GetName() + "'.");
|
|
|
|
}
|
2015-08-21 15:50:40 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
Downtime::Ptr downtime = static_pointer_cast<Downtime>(object);
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
if (!downtime)
|
|
|
|
return ApiActions::CreateResult(404, "Cannot remove non-existent downtime object.");
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2019-11-21 15:28:25 +01:00
|
|
|
{
|
|
|
|
ObjectLock oLock (downtime);
|
|
|
|
downtime->SetRemovedBy(author);
|
|
|
|
}
|
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
String downtimeName = downtime->GetName();
|
2015-08-03 15:27:09 +02:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
Downtime::RemoveDowntime(downtimeName, true);
|
2015-11-01 16:33:43 +01:00
|
|
|
|
2015-11-08 12:41:47 +01:00
|
|
|
return ApiActions::CreateResult(200, "Successfully removed downtime '" + downtimeName + "'.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::ShutdownProcess(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
|
|
|
Application::RequestShutdown();
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(200, "Shutting down Icinga 2.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
Dictionary::Ptr ApiActions::RestartProcess(const ConfigObject::Ptr& object,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2015-08-03 15:27:09 +02:00
|
|
|
{
|
|
|
|
Application::RequestRestart();
|
|
|
|
|
2015-10-16 11:44:18 +02:00
|
|
|
return ApiActions::CreateResult(200, "Restarting Icinga 2.");
|
2015-08-03 15:27:09 +02:00
|
|
|
}
|
|
|
|
|
2016-08-15 14:32:41 +02:00
|
|
|
Dictionary::Ptr ApiActions::GenerateTicket(const ConfigObject::Ptr&,
|
2017-12-19 15:50:05 +01:00
|
|
|
const Dictionary::Ptr& params)
|
2016-08-15 14:32:41 +02:00
|
|
|
{
|
|
|
|
if (!params->Contains("cn"))
|
2017-11-03 13:29:24 +01:00
|
|
|
return ApiActions::CreateResult(400, "Option 'cn' is required");
|
2016-08-15 14:32:41 +02:00
|
|
|
|
|
|
|
String cn = HttpUtility::GetLastParameter(params, "cn");
|
|
|
|
|
|
|
|
ApiListener::Ptr listener = ApiListener::GetInstance();
|
|
|
|
String salt = listener->GetTicketSalt();
|
|
|
|
|
|
|
|
if (salt.IsEmpty())
|
|
|
|
return ApiActions::CreateResult(500, "Ticket salt is not configured in ApiListener object");
|
|
|
|
|
|
|
|
String ticket = PBKDF2_SHA1(cn, salt, 50000);
|
|
|
|
|
2018-01-11 11:17:38 +01:00
|
|
|
Dictionary::Ptr additional = new Dictionary({
|
|
|
|
{ "ticket", ticket }
|
|
|
|
});
|
2016-08-15 14:32:41 +02:00
|
|
|
|
|
|
|
return ApiActions::CreateResult(200, "Generated PKI ticket '" + ticket + "' for common name '"
|
2017-12-19 15:50:05 +01:00
|
|
|
+ cn + "'.", additional);
|
2016-08-15 14:32:41 +02:00
|
|
|
}
|
2020-06-02 11:43:32 +02:00
|
|
|
|
|
|
|
Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object,
|
|
|
|
const Dictionary::Ptr& params)
|
|
|
|
{
|
2020-07-01 14:27:00 +02:00
|
|
|
ApiListener::Ptr listener = ApiListener::GetInstance();
|
|
|
|
if (!listener)
|
|
|
|
BOOST_THROW_EXCEPTION(std::invalid_argument("No ApiListener instance configured."));
|
|
|
|
|
|
|
|
/* Get command_type */
|
|
|
|
String command_type = "EventCommand";
|
|
|
|
if (params->Contains("command_type"))
|
|
|
|
command_type = HttpUtility::GetLastParameter(params, "command_type");
|
|
|
|
|
|
|
|
/* Validate command_type */
|
|
|
|
if (command_type != "EventCommand" && command_type != "CheckCommand" && command_type != "NotificationCommand")
|
|
|
|
return ApiActions::CreateResult(400, "Invalid command_type '" + command_type + "'.");
|
|
|
|
|
2020-06-30 15:41:47 +02:00
|
|
|
Checkable::Ptr checkable = dynamic_pointer_cast<Checkable>(object);
|
|
|
|
if (!checkable)
|
2020-06-30 15:48:29 +02:00
|
|
|
return ApiActions::CreateResult(404, "Can't start a command execution for a non-existent object.");
|
2020-06-23 11:44:26 +02:00
|
|
|
|
2020-07-01 14:27:00 +02:00
|
|
|
/* Get TTL param */
|
|
|
|
if (!params->Contains("ttl"))
|
|
|
|
return ApiActions::CreateResult(400, "Parameter ttl is required.");
|
|
|
|
|
|
|
|
double ttl = HttpUtility::GetLastParameter(params, "ttl");
|
|
|
|
if (ttl <= 0)
|
|
|
|
return ApiActions::CreateResult(400, "Parameter ttl must be greater than 0.");
|
|
|
|
|
2020-06-23 11:44:26 +02:00
|
|
|
ObjectLock oLock (checkable);
|
|
|
|
|
|
|
|
Host::Ptr host;
|
|
|
|
Service::Ptr service;
|
|
|
|
tie(host, service) = GetHostService(checkable);
|
|
|
|
|
|
|
|
String endpoint = "$command_endpoint$";
|
|
|
|
if (params->Contains("endpoint"))
|
2020-06-30 15:51:15 +02:00
|
|
|
endpoint = HttpUtility::GetLastParameter(params, "endpoint");
|
2020-06-23 11:44:26 +02:00
|
|
|
|
|
|
|
MacroProcessor::ResolverList resolvers;
|
2020-06-26 12:32:12 +02:00
|
|
|
if (params->Contains("macros")) {
|
2020-07-02 10:31:24 +02:00
|
|
|
Value macros = HttpUtility::GetLastParameter(params, "macros");
|
|
|
|
if (macros.IsObjectType<Dictionary>()) {
|
|
|
|
resolvers.emplace_back("override", macros);
|
2020-07-01 14:27:00 +02:00
|
|
|
}
|
2020-06-26 12:32:12 +02:00
|
|
|
else
|
2020-06-26 15:39:42 +02:00
|
|
|
return ApiActions::CreateResult(400, "Parameter macros must be a dictionary.");
|
2020-06-26 12:32:12 +02:00
|
|
|
}
|
|
|
|
|
2020-06-23 11:44:26 +02:00
|
|
|
if (service)
|
|
|
|
resolvers.emplace_back("service", service);
|
|
|
|
resolvers.emplace_back("host", host);
|
|
|
|
resolvers.emplace_back("icinga", IcingaApplication::GetInstance());
|
|
|
|
|
|
|
|
String resolved_endpoint = MacroProcessor::ResolveMacros(
|
|
|
|
endpoint, resolvers, checkable->GetLastCheckResult(),
|
2020-06-26 14:29:03 +02:00
|
|
|
nullptr, MacroProcessor::EscapeCallback(), nullptr, false
|
2020-06-23 11:44:26 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
/* Check if endpoint exists */
|
2020-06-26 16:38:40 +02:00
|
|
|
Endpoint::Ptr endpointPtr = Endpoint::GetByName(resolved_endpoint);
|
|
|
|
if (!endpointPtr)
|
2020-06-23 11:44:26 +02:00
|
|
|
return ApiActions::CreateResult(404, "Can't find a valid endpoint for '" + resolved_endpoint + "'.");
|
|
|
|
|
|
|
|
/* Get command */
|
|
|
|
String command;
|
|
|
|
if (!params->Contains("command")) {
|
|
|
|
if (command_type == "CheckCommand" ) {
|
|
|
|
command = "$check_command$";
|
|
|
|
} else if (command_type == "EventCommand") {
|
|
|
|
command = "$event_command$";
|
|
|
|
} else if (command_type == "NotificationCommand") {
|
|
|
|
command = "$notification_command$";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
command = HttpUtility::GetLastParameter(params, "command");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Resolve command macro */
|
|
|
|
String resolved_command = MacroProcessor::ResolveMacros(
|
2020-06-26 12:32:12 +02:00
|
|
|
command, resolvers, checkable->GetLastCheckResult(), nullptr,
|
|
|
|
MacroProcessor::EscapeCallback(), nullptr, false
|
2020-06-23 11:44:26 +02:00
|
|
|
);
|
|
|
|
|
2020-07-03 08:43:50 +02:00
|
|
|
CheckResult::Ptr cr = checkable->GetLastCheckResult();
|
2020-07-02 12:20:16 +02:00
|
|
|
|
2020-06-23 11:44:26 +02:00
|
|
|
/* Check if resolved_command exists and it is of type command_type */
|
2020-07-02 12:20:16 +02:00
|
|
|
Dictionary::Ptr execMacros = new Dictionary();
|
2020-06-23 11:44:26 +02:00
|
|
|
if (command_type == "CheckCommand") {
|
2020-07-02 12:20:16 +02:00
|
|
|
CheckCommand::Ptr cmd = CheckCommand::GetByName(resolved_command);
|
|
|
|
if (!cmd)
|
2020-07-01 08:19:35 +02:00
|
|
|
return ApiActions::CreateResult(404, "Can't find a valid " + command_type + " for '" + resolved_command + "'.");
|
2020-07-02 12:20:16 +02:00
|
|
|
else
|
|
|
|
cmd->Execute(checkable, cr, execMacros, false);
|
2020-06-23 11:44:26 +02:00
|
|
|
} else if (command_type == "EventCommand") {
|
2020-07-02 12:20:16 +02:00
|
|
|
EventCommand::Ptr cmd = EventCommand::GetByName(resolved_command);
|
|
|
|
if (!cmd)
|
2020-07-01 08:19:35 +02:00
|
|
|
return ApiActions::CreateResult(404, "Can't find a valid " + command_type + " for '" + resolved_command + "'.");
|
2020-07-02 12:20:16 +02:00
|
|
|
else
|
|
|
|
cmd->Execute(checkable, execMacros, false);
|
2020-06-23 11:44:26 +02:00
|
|
|
} else if (command_type == "NotificationCommand") {
|
2020-07-02 12:20:16 +02:00
|
|
|
NotificationCommand::Ptr cmd = NotificationCommand::GetByName(resolved_command);
|
|
|
|
if (!cmd)
|
2020-07-01 08:19:35 +02:00
|
|
|
return ApiActions::CreateResult(404, "Can't find a valid " + command_type + " for '" + resolved_command + "'.");
|
2020-07-02 12:20:16 +02:00
|
|
|
else {
|
|
|
|
/* Get user */
|
|
|
|
String user_string = "";
|
|
|
|
if (params->Contains("user"))
|
|
|
|
user_string = HttpUtility::GetLastParameter(params, "user");
|
|
|
|
|
|
|
|
/* Resolve user macro */
|
|
|
|
String resolved_user = MacroProcessor::ResolveMacros(
|
2020-07-03 08:38:39 +02:00
|
|
|
user_string, resolvers, checkable->GetLastCheckResult(), nullptr,
|
|
|
|
MacroProcessor::EscapeCallback(), nullptr, false
|
2020-07-02 12:20:16 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
User::Ptr user = User::GetByName(resolved_user);
|
|
|
|
if (!user)
|
|
|
|
return ApiActions::CreateResult(404, "Can't find a valid user for '" + resolved_user + "'.");
|
|
|
|
|
|
|
|
/* Get notification */
|
|
|
|
String notification_string = "";
|
|
|
|
if (params->Contains("notification"))
|
|
|
|
notification_string = HttpUtility::GetLastParameter(params, "notification");
|
|
|
|
|
|
|
|
/* Resolve notification macro */
|
|
|
|
String resolved_notification = MacroProcessor::ResolveMacros(
|
2020-07-03 08:38:39 +02:00
|
|
|
notification_string, resolvers, checkable->GetLastCheckResult(), nullptr,
|
|
|
|
MacroProcessor::EscapeCallback(), nullptr, false
|
2020-07-02 12:20:16 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
Notification::Ptr notification = Notification::GetByName(resolved_notification);
|
|
|
|
if (!user)
|
|
|
|
return ApiActions::CreateResult(404, "Can't find a valid notification for '" + resolved_notification + "'.");
|
|
|
|
|
|
|
|
/* Get author */
|
|
|
|
String author = "";
|
|
|
|
if (params->Contains("author"))
|
|
|
|
author = HttpUtility::GetLastParameter(params, "author");
|
|
|
|
|
|
|
|
cmd->Execute(notification, user, cr, NotificationType::NotificationCustom, author, "", execMacros, false);
|
|
|
|
}
|
2020-06-26 09:33:23 +02:00
|
|
|
}
|
2020-06-23 11:44:26 +02:00
|
|
|
|
|
|
|
/* This generates a UUID */
|
|
|
|
String uuid = Utility::NewUniqueID();
|
|
|
|
|
|
|
|
/* Create the deadline */
|
|
|
|
double deadline = Utility::GetTime() + ttl;
|
|
|
|
|
|
|
|
/* Update executions */
|
|
|
|
Dictionary::Ptr pending_execution = new Dictionary();
|
|
|
|
pending_execution->Set("pending", true);
|
|
|
|
pending_execution->Set("deadline", deadline);
|
|
|
|
Dictionary::Ptr executions = checkable->GetExecutions();
|
|
|
|
if (!executions)
|
|
|
|
executions = new Dictionary();
|
|
|
|
executions->Set(uuid, pending_execution);
|
|
|
|
checkable->SetExecutions(executions);
|
|
|
|
|
2020-06-30 17:50:08 +02:00
|
|
|
/* Broadcast the update */
|
2020-07-01 14:27:00 +02:00
|
|
|
Dictionary::Ptr executionsToBroadcast = new Dictionary();
|
|
|
|
executionsToBroadcast->Set(uuid, pending_execution);
|
2020-06-30 17:50:08 +02:00
|
|
|
Dictionary::Ptr updateParams = new Dictionary();
|
|
|
|
updateParams->Set("host", host->GetName());
|
|
|
|
if (service)
|
|
|
|
updateParams->Set("service", service->GetShortName());
|
2020-07-01 14:27:00 +02:00
|
|
|
updateParams->Set("executions", executionsToBroadcast);
|
2020-06-30 17:50:08 +02:00
|
|
|
|
|
|
|
Dictionary::Ptr updateMessage = new Dictionary();
|
|
|
|
updateMessage->Set("jsonrpc", "2.0");
|
|
|
|
updateMessage->Set("method", "event::UpdateExecutions");
|
|
|
|
updateMessage->Set("params", updateParams);
|
|
|
|
|
|
|
|
MessageOrigin::Ptr origin = new MessageOrigin();
|
|
|
|
listener->RelayMessage(origin, checkable, updateMessage, true);
|
|
|
|
|
2020-06-30 13:43:00 +02:00
|
|
|
/* Create execution parameters */
|
|
|
|
Dictionary::Ptr execParams = new Dictionary();
|
|
|
|
execParams->Set("command_type", command_type);
|
|
|
|
execParams->Set("command", resolved_command);
|
|
|
|
execParams->Set("host", host->GetName());
|
|
|
|
if (service)
|
|
|
|
execParams->Set("service", service->GetShortName());
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the host/service object specifies the 'check_timeout' attribute,
|
|
|
|
* forward this to the remote endpoint to limit the command execution time.
|
|
|
|
*/
|
|
|
|
if (!checkable->GetCheckTimeout().IsEmpty())
|
|
|
|
execParams->Set("check_timeout", checkable->GetCheckTimeout());
|
|
|
|
|
|
|
|
execParams->Set("source", uuid);
|
|
|
|
execParams->Set("deadline", deadline);
|
2020-07-02 10:31:24 +02:00
|
|
|
execParams->Set("macros", execMacros);
|
2020-06-30 13:43:00 +02:00
|
|
|
|
2020-06-30 17:50:08 +02:00
|
|
|
/* Execute command */
|
2020-06-26 16:38:40 +02:00
|
|
|
bool local = endpointPtr == Endpoint::GetLocalEndpoint();
|
2020-06-26 12:32:12 +02:00
|
|
|
if (local) {
|
2020-06-30 13:43:00 +02:00
|
|
|
ClusterEvents::ExecuteCommandAPIHandler(origin, execParams);
|
2020-06-26 12:32:12 +02:00
|
|
|
} else {
|
|
|
|
Dictionary::Ptr execMessage = new Dictionary();
|
|
|
|
execMessage->Set("jsonrpc", "2.0");
|
|
|
|
execMessage->Set("method", "event::ExecuteCommand");
|
|
|
|
execMessage->Set("params", execParams);
|
2020-06-23 11:44:26 +02:00
|
|
|
|
2020-06-30 13:43:00 +02:00
|
|
|
listener->SyncSendMessage(endpointPtr, execMessage);
|
2020-06-26 12:32:12 +02:00
|
|
|
}
|
2020-06-23 11:44:26 +02:00
|
|
|
|
|
|
|
Dictionary::Ptr result = new Dictionary();
|
|
|
|
result->Set(checkable->GetName(), uuid);
|
2020-06-16 14:18:11 +02:00
|
|
|
return ApiActions::CreateResult(202, "Accepted", result);
|
2020-06-26 16:36:57 +02:00
|
|
|
}
|