return GetPaused();
}
-void DynamicObject::SetExtension(const String& key, const Object::Ptr& object)
+void DynamicObject::SetExtension(const String& key, const Value& value)
{
Dictionary::Ptr extensions = GetExtensions();
SetExtensions(extensions);
}
- extensions->Set(key, object);
+ extensions->Set(key, value);
}
-Object::Ptr DynamicObject::GetExtension(const String& key)
+Value DynamicObject::GetExtension(const String& key)
{
Dictionary::Ptr extensions = GetExtensions();
if (!extensions)
- return Object::Ptr();
+ return Empty;
return extensions->Get(key);
}
bool IsActive(void) const;
bool IsPaused(void) const;
- void SetExtension(const String& key, const Object::Ptr& object);
- Object::Ptr GetExtension(const String& key);
+ void SetExtension(const String& key, const Value& value);
+ Value GetExtension(const String& key);
void ClearExtension(const String& key);
void Register(void);
return boost::bind(&ScriptFunctionWrapperR<TR, T0, T1, T2, T3, T4, T5>, function, _1);
}
+template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+Value ScriptFunctionWrapperV(void (*function)(T0, T1, T2, T3, T4, T5, T6), const std::vector<Value>& arguments)
+{
+ if (arguments.size() < 7)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
+
+ function(static_cast<T0>(arguments[0]),
+ static_cast<T1>(arguments[1]),
+ static_cast<T2>(arguments[2]),
+ static_cast<T3>(arguments[3]),
+ static_cast<T4>(arguments[4]),
+ static_cast<T5>(arguments[5]),
+ static_cast<T6>(arguments[6]));
+
+ return Empty;
+}
+
+template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(void (*function)(T0, T1, T2, T3, T4, T5, T6))
+{
+ return boost::bind(&ScriptFunctionWrapperV<T0, T1, T2, T3, T4, T5, T6>, function, _1);
+}
+
+template<typename TR, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+Value ScriptFunctionWrapperR(TR (*function)(T0, T1, T2, T3, T4, T5, T6), const std::vector<Value>& arguments)
+{
+ if (arguments.size() < 7)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
+
+ return function(static_cast<T0>(arguments[0]),
+ static_cast<T1>(arguments[1]),
+ static_cast<T2>(arguments[2]),
+ static_cast<T3>(arguments[3]),
+ static_cast<T4>(arguments[4]),
+ static_cast<T5>(arguments[5]),
+ static_cast<T6>(arguments[6]));
+}
+
+template<typename TR, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(TR (*function)(T0, T1, T2, T3, T4, T5, T6))
+{
+ return boost::bind(&ScriptFunctionWrapperR<TR, T0, T1, T2, T3, T4, T5, T6>, function, _1);
+}
+
+template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+Value ScriptFunctionWrapperV(void (*function)(T0, T1, T2, T3, T4, T5, T6, T7), const std::vector<Value>& arguments)
+{
+ if (arguments.size() < 8)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
+
+ function(static_cast<T0>(arguments[0]),
+ static_cast<T1>(arguments[1]),
+ static_cast<T2>(arguments[2]),
+ static_cast<T3>(arguments[3]),
+ static_cast<T4>(arguments[4]),
+ static_cast<T5>(arguments[5]),
+ static_cast<T6>(arguments[6]),
+ static_cast<T7>(arguments[7]));
+
+ return Empty;
+}
+
+template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(void (*function)(T0, T1, T2, T3, T4, T5, T6, T7))
+{
+ return boost::bind(&ScriptFunctionWrapperV<T0, T1, T2, T3, T4, T5, T6, T7>, function, _1);
+}
+
+template<typename TR, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+Value ScriptFunctionWrapperR(TR (*function)(T0, T1, T2, T3, T4, T5, T6, T7), const std::vector<Value>& arguments)
+{
+ if (arguments.size() < 8)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function."));
+
+ return function(static_cast<T0>(arguments[0]),
+ static_cast<T1>(arguments[1]),
+ static_cast<T2>(arguments[2]),
+ static_cast<T3>(arguments[3]),
+ static_cast<T4>(arguments[4]),
+ static_cast<T5>(arguments[5]),
+ static_cast<T6>(arguments[6]),
+ static_cast<T7>(arguments[7]));
+}
+
+template<typename TR, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(TR (*function)(T0, T1, T2, T3, T4, T5, T6, T7))
+{
+ return boost::bind(&ScriptFunctionWrapperR<TR, T0, T1, T2, T3, T4, T5, T6, T7>, function, _1);
+}
+
template<typename TR>
boost::function<TR (const std::vector<Value>& arguments)> WrapScriptFunction(TR (*function)(const std::vector<Value>&))
{
for (size_t i = 0; i < sizeof(m_Queues) / sizeof(m_Queues[0]); i++)
m_Queues[i].SpawnWorker(m_ThreadGroup);
- m_MgmtThread = boost::move(boost::thread(boost::bind(&ThreadPool::ManagerThreadProc, this)));
+ m_MgmtThread = boost::thread(boost::bind(&ThreadPool::ManagerThreadProc, this));
}
void ThreadPool::Stop(void)
<< "\n"
<< "We'll guide you through all required configuration details.\n"
<< "\n"
- << "If you have questions, please consult the documentation at http://docs.icinga.org\n"
- << "or join the community support channels at https://support.icinga.org\n"
<< "\n\n" << ConsoleColorTag(Console_Normal);
//TODO: Add sort of bash completion to path input?
wizard_ticket:
std::cout << ConsoleColorTag(Console_Bold) << "Please specify the request ticket generated on your Icinga 2 master." << ConsoleColorTag(Console_Normal) << "\n"
- << " (Hint: '# icinga2 pki ticket --cn " << cn << "'):\n";
+ << " (Hint: '# icinga2 pki ticket --cn '" << cn << "'): ";
std::getline(std::cin, answer);
boost::algorithm::to_lower(answer);
std::cout << "Now restart your Icinga 2 daemon to finish the installation!\n\n";
- std::cout << "If you encounter problems or bugs, please do not hesitate to\n"
- << "get in touch with the community at https://support.icinga.org" << std::endl;
-
return 0;
}
DbObject::Ptr DbObject::GetOrCreateByObject(const DynamicObject::Ptr& object)
{
- DbObject::Ptr dbobj = static_pointer_cast<DbObject>(object->GetExtension("DbObject"));
+ DbObject::Ptr dbobj = object->GetExtension("DbObject");
if (dbobj)
return dbobj;
add_library(hello SHARED ${hello_SOURCES})
-target_link_libraries(hello ${Boost_LIBRARIES} base config)
+target_link_libraries(hello ${Boost_LIBRARIES} base config icinga)
set_target_properties (
hello PROPERTIES
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/icinga2
)
-
-
******************************************************************************/
#include "hello/hello.hpp"
+#include "icinga/host.hpp"
+#include "icinga/checkcommand.hpp"
#include "base/dynamictype.hpp"
#include "base/logger.hpp"
+#include "base/json.hpp"
+#include "base/serializer.hpp"
+#include <iostream>
using namespace icinga;
{
Log(LogInformation, "Hello", "Hello World!");
+ Host::Ptr host = Host::GetByName("test");
+ CheckCommand::Ptr command = host->GetCheckCommand();
+
+ Dictionary::Ptr macros = new Dictionary();
+
+ command->Execute(host, CheckResult::Ptr(), macros);
+
+ std::cout << JsonEncode(macros) << std::endl;
+
+ Host::Ptr host2 = new Host();
+ Dictionary::Ptr attrs = new Dictionary();
+
+ attrs->Set("__name", "keks");
+ attrs->Set("type", "Host");
+ attrs->Set("check_command", "http");
+ attrs->Set("command_endpoint", "test");
+
+ Deserialize(host2, attrs, false, FAConfig);
+
+ host2->SetExtension("agent_service_name", "foobar");
+
+ static_pointer_cast<DynamicObject>(host2)->OnStateLoaded();
+ static_pointer_cast<DynamicObject>(host2)->OnConfigLoaded();
+
+ std::cout << host2->GetName() << std::endl;
+
+ host2->ExecuteCheck(macros, true);
+
+ Utility::Sleep(30);
+
return 0;
}
REGISTER_APIFUNCTION(SetAcknowledgement, event, &ApiEvents::AcknowledgementSetAPIHandler);
REGISTER_APIFUNCTION(ClearAcknowledgement, event, &ApiEvents::AcknowledgementClearedAPIHandler);
REGISTER_APIFUNCTION(UpdateRepository, event, &ApiEvents::UpdateRepositoryAPIHandler);
+REGISTER_APIFUNCTION(ExecuteCommand, event, &ApiEvents::ExecuteCommandAPIHandler);
static Timer::Ptr l_RepositoryTimer;
l_RepositoryTimer->Reschedule(0);
}
-void ApiEvents::CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, const MessageOrigin& origin)
+Dictionary::Ptr ApiEvents::MakeCheckResultMessage(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
{
- ApiListener::Ptr listener = ApiListener::GetInstance();
-
- if (!listener)
- return;
-
Dictionary::Ptr message = new Dictionary();
message->Set("jsonrpc", "2.0");
message->Set("method", "event::CheckResult");
params->Set("host", host->GetName());
if (service)
params->Set("service", service->GetShortName());
+ else {
+ Value agent_service_name = checkable->GetExtension("agent_service_name");
+
+ if (!agent_service_name.IsEmpty())
+ params->Set("service", agent_service_name);
+ }
params->Set("cr", Serialize(cr));
message->Set("params", params);
+ return message;
+}
+
+void ApiEvents::CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, const MessageOrigin& origin)
+{
+ ApiListener::Ptr listener = ApiListener::GetInstance();
+
+ if (!listener)
+ return;
+
+ Dictionary::Ptr message = MakeCheckResultMessage(checkable, cr);
listener->RelayMessage(origin, checkable, message, true);
}
Value ApiEvents::CheckResultAPIHandler(const MessageOrigin& origin, const Dictionary::Ptr& params)
{
- if (!origin.FromClient->GetEndpoint())
+ Endpoint::Ptr endpoint = origin.FromClient->GetEndpoint();
+
+ if (!endpoint)
return Empty;
if (!params)
if (!checkable)
return Empty;
- if (origin.FromZone && !origin.FromZone->CanAccessObject(checkable))
+ if (origin.FromZone && !origin.FromZone->CanAccessObject(checkable) && endpoint != checkable->GetCommandEndpoint())
return Empty;
checkable->ProcessCheckResult(cr, origin);
return Empty;
}
+Value ApiEvents::ExecuteCommandAPIHandler(const MessageOrigin& origin, const Dictionary::Ptr& params)
+{
+ Endpoint::Ptr endpoint = origin.FromClient->GetEndpoint();
+
+ if (!endpoint || (origin.FromZone && !Zone::GetLocalZone()->IsChildOf(origin.FromZone)))
+ return Empty;
+
+ ApiListener::Ptr listener = ApiListener::GetInstance();
+
+ if (!listener) {
+ Log(LogCritical, "ApiListener", "No instance available.");
+ return Empty;
+ }
+
+ if (!listener->GetAcceptCommands()) {
+ Log(LogWarning, "ApiListener")
+ << "Ignoring command. '" << listener->GetName() << "' does not accept commands.";
+ return Empty;
+ }
+
+ Host::Ptr host = new Host();
+ Dictionary::Ptr attrs = new Dictionary();
+
+ attrs->Set("__name", params->Get("host"));
+ attrs->Set("type", "Host");
+
+ String command = params->Get("command");
+ String command_type = params->Get("command_type");
+
+ if (command_type == "check_command") {
+ if (!CheckCommand::GetByName(command)) {
+ CheckResult::Ptr cr = new CheckResult();
+ cr->SetState(ServiceUnknown);
+ cr->SetOutput("Check command '" + command + "' does not exist.");
+ Dictionary::Ptr message = MakeCheckResultMessage(host, cr);
+ listener->SyncSendMessage(endpoint, message);
+ return Empty;
+ }
+ } else if (command_type == "event_command") {
+ if (!EventCommand::GetByName(command))
+ return Empty;
+ } else
+ return Empty;
+
+ attrs->Set(command_type, params->Get("command"));
+ attrs->Set("command_endpoint", endpoint->GetName());
+
+ Deserialize(host, attrs, false, FAConfig);
+
+ if (params->Contains("service"))
+ host->SetExtension("agent_service_name", params->Get("service"));
+
+ host->SetExtension("agent_check", true);
+
+ static_pointer_cast<DynamicObject>(host)->OnStateLoaded();
+ static_pointer_cast<DynamicObject>(host)->OnConfigLoaded();
+
+ Dictionary::Ptr macros = params->Get("macros");
+
+ if (command_type == "check_command")
+ host->ExecuteCheck(macros, true);
+ else if (command_type == "event_command")
+ host->ExecuteEventHandler(macros, true);
+
+ return Empty;
+}
+
void ApiEvents::RepositoryTimerHandler(void)
{
ApiListener::Ptr listener = ApiListener::GetInstance();
static void AcknowledgementClearedHandler(const Checkable::Ptr& checkable, const MessageOrigin& origin);
static Value AcknowledgementClearedAPIHandler(const MessageOrigin& origin, const Dictionary::Ptr& params);
+ static Value ExecuteCommandAPIHandler(const MessageOrigin& origin, const Dictionary::Ptr& params);
+
static String GetRepositoryDir(void);
static void RepositoryTimerHandler(void);
static Value UpdateRepositoryAPIHandler(const MessageOrigin& origin, const Dictionary::Ptr& params);
+
+ static Dictionary::Ptr MakeCheckResultMessage(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr);
};
}
#include "icinga/checkcommand.hpp"
#include "icinga/icingaapplication.hpp"
#include "icinga/cib.hpp"
+#include "icinga/apievents.hpp"
#include "remote/messageorigin.hpp"
+#include "remote/apilistener.hpp"
#include "base/objectlock.hpp"
#include "base/logger.hpp"
#include "base/convert.hpp"
if (origin.IsLocal())
cr->SetCheckSource(IcingaApplication::GetInstance()->GetNodeName());
+ Endpoint::Ptr command_endpoint = GetCommandEndpoint();
+
+ if (command_endpoint && GetExtension("agent_check")) {
+ ApiListener::Ptr listener = ApiListener::GetInstance();
+
+ if (listener) {
+ Dictionary::Ptr message = ApiEvents::MakeCheckResultMessage(this, cr);
+ listener->SyncSendMessage(command_endpoint, message);
+ }
+
+ return;
+ }
+
bool reachable = IsReachable();
bool notification_reachable = IsReachable(DependencyNotification);
return m_CheckRunning;
}
-void Checkable::ExecuteCheck(void)
+void Checkable::ExecuteCheck(const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
CONTEXT("Executing check for object '" + GetName() + "'");
result->SetScheduleStart(scheduled_start);
result->SetExecutionStart(before_check);
- GetCheckCommand()->Execute(this, result);
+ Dictionary::Ptr macros;
+ Endpoint::Ptr endpoint = GetCommandEndpoint();
+
+ if (endpoint && !useResolvedMacros)
+ macros = new Dictionary();
+ else
+ macros = resolvedMacros;
+
+ GetCheckCommand()->Execute(this, result, macros, useResolvedMacros);
+
+ if (endpoint && !useResolvedMacros) {
+ if (endpoint->IsConnected()) {
+ Dictionary::Ptr message = new Dictionary();
+ message->Set("jsonrpc", "2.0");
+ message->Set("method", "event::ExecuteCommand");
+
+ Host::Ptr host;
+ Service::Ptr service;
+ tie(host, service) = GetHostService(this);
+
+ Dictionary::Ptr params = new Dictionary();
+ message->Set("params", params);
+ params->Set("command_type", "check_command");
+ params->Set("command", GetCheckCommand()->GetName());
+ params->Set("host", host->GetName());
+
+ if (service)
+ params->Set("service", service->GetShortName());
+
+ params->Set("macros", macros);
+
+ ApiListener::Ptr listener = ApiListener::GetInstance();
+
+ if (listener)
+ listener->SyncSendMessage(endpoint, message);
+ } else if (Application::GetInstance()->GetStartTime() < Utility::GetTime() - 30) {
+ result->SetState(ServiceUnknown);
+ result->SetOutput("Remote Icinga instance '" + endpoint->GetName() + "' is not connected.");
+ ProcessCheckResult(result);
+ }
+
+ {
+ ObjectLock olock(this);
+ m_CheckRunning = false;
+ }
+ }
}
void Checkable::UpdateStatistics(const CheckResult::Ptr& cr, CheckableType type)
#include "icinga/checkable.hpp"
#include "icinga/eventcommand.hpp"
#include "icinga/icingaapplication.hpp"
+#include "icinga/service.hpp"
+#include "remote/apilistener.hpp"
#include "base/logger.hpp"
#include "base/context.hpp"
OnEventCommandChanged(this, command, origin);
}
-void Checkable::ExecuteEventHandler(void)
+void Checkable::ExecuteEventHandler(const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
CONTEXT("Executing event handler for object '" + GetName() + "'");
Log(LogNotice, "Checkable")
<< "Executing event handler '" << ec->GetName() << "' for service '" << GetName() << "'";
- ec->Execute(this);
+ Dictionary::Ptr macros;
+ Endpoint::Ptr endpoint = GetCommandEndpoint();
+
+ if (endpoint && !useResolvedMacros)
+ macros = new Dictionary();
+ else
+ macros = resolvedMacros;
+
+ ec->Execute(this, macros, useResolvedMacros);
+
+ if (endpoint) {
+ Dictionary::Ptr message = new Dictionary();
+ message->Set("jsonrpc", "2.0");
+ message->Set("method", "event::ExecuteCommand");
+
+ Host::Ptr host;
+ Service::Ptr service;
+ tie(host, service) = GetHostService(this);
+
+ Dictionary::Ptr params = new Dictionary();
+ message->Set("params", params);
+ params->Set("command_type", "event_command");
+ params->Set("command", GetEventCommand()->GetName());
+ params->Set("host", host->GetName());
+
+ if (service)
+ params->Set("service", service->GetShortName());
+
+ params->Set("macros", macros);
+
+ ApiListener::Ptr listener = ApiListener::GetInstance();
+
+ if (listener)
+ listener->SyncSendMessage(endpoint, message);
+
+ return;
+ }
OnEventCommandExecuted(this);
}
OnVarsChanged(this, GetVars(), origin);
}
}
+
+Endpoint::Ptr Checkable::GetCommandEndpoint(void) const
+{
+ return Endpoint::GetByName(GetCommandEndpointRaw());
+}
#include "icinga/notification.hpp"
#include "icinga/comment.hpp"
#include "icinga/downtime.hpp"
+#include "remote/endpoint.hpp"
#include "remote/messageorigin.hpp"
namespace icinga
static void UpdateStatistics(const CheckResult::Ptr& cr, CheckableType type);
- void ExecuteCheck(void);
+ void ExecuteCheck(const Dictionary::Ptr& resolvedMacros = Dictionary::Ptr(),
+ bool useResolvedMacros = false);
void ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrigin& origin = MessageOrigin());
int GetModifiedAttributes(void) const;
void SetModifiedAttributes(int flags, const MessageOrigin& origin = MessageOrigin());
+ Endpoint::Ptr GetCommandEndpoint(void) const;
+
bool IsCheckPending(void) const;
static double CalculateExecutionTime(const CheckResult::Ptr& cr);
void ResetNotificationNumbers(void);
/* Event Handler */
- void ExecuteEventHandler(void);
+ void ExecuteEventHandler(const Dictionary::Ptr& resolvedMacros = Dictionary::Ptr(),
+ bool useResolvedMacros = false);
intrusive_ptr<EventCommand> GetEventCommand(void) const;
void SetEventCommand(const intrusive_ptr<EventCommand>& command, const MessageOrigin& origin = MessageOrigin());
[state] Value override_check_command;
[state] Value override_max_check_attempts;
[state] Value override_check_period;
+
+ [config] String command_endpoint (CommandEndpointRaw);
};
}
REGISTER_TYPE(CheckCommand);
-void CheckCommand::Execute(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
+void CheckCommand::Execute(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
std::vector<Value> arguments;
arguments.push_back(checkable);
arguments.push_back(cr);
+ arguments.push_back(resolvedMacros);
+ arguments.push_back(useResolvedMacros);
InvokeMethod("execute", arguments);
}
DECLARE_OBJECT(CheckCommand);
DECLARE_OBJECTNAME(CheckCommand);
- virtual void Execute(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr);
+ virtual void Execute(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros = Dictionary::Ptr(),
+ bool useResolvedMacros = false);
};
}
REGISTER_TYPE(EventCommand);
-void EventCommand::Execute(const Checkable::Ptr& checkable)
+void EventCommand::Execute(const Checkable::Ptr& checkable,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
std::vector<Value> arguments;
arguments.push_back(checkable);
+ arguments.push_back(resolvedMacros);
+ arguments.push_back(useResolvedMacros);
InvokeMethod("execute", arguments);
}
DECLARE_OBJECT(EventCommand);
DECLARE_OBJECTNAME(EventCommand);
- virtual void Execute(const Checkable::Ptr& checkable);
+ virtual void Execute(const Checkable::Ptr& checkable,
+ const Dictionary::Ptr& resolvedMacros = Dictionary::Ptr(),
+ bool useResolvedMacros = false);
};
}
%attribute %string "action_url",
%attribute %string "icon_image",
%attribute %string "icon_image_alt",
+
+ %attribute %name(Endpoint) "command_endpoint",
}
%type Host %inherits Checkable {
%attribute %array "states" {
%attribute %number "*"
},
+
+ %attribute %name(Endpoint) "command_endpoint",
}
%type User {
Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolvers,
const CheckResult::Ptr& cr, String *missingMacro,
- const MacroProcessor::EscapeCallback& escapeFn)
+ const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros,
+ bool useResolvedMacros)
{
Value result;
return Empty;
if (str.IsScalar()) {
- result = InternalResolveMacros(str, resolvers, cr, missingMacro, escapeFn);
+ result = InternalResolveMacros(str, resolvers, cr, missingMacro, escapeFn,
+ resolvedMacros, useResolvedMacros);
} else if (str.IsObjectType<Array>()) {
Array::Ptr resultArr = new Array();
Array::Ptr arr = str;
BOOST_FOREACH(const Value& arg, arr) {
/* Note: don't escape macros here. */
- resultArr->Add(InternalResolveMacros(arg, resolvers, cr, missingMacro, EscapeCallback()));
+ resultArr->Add(InternalResolveMacros(arg, resolvers, cr, missingMacro,
+ EscapeCallback(), resolvedMacros, useResolvedMacros));
}
result = resultArr;
String MacroProcessor::InternalResolveMacros(const String& str, const ResolverList& resolvers,
const CheckResult::Ptr& cr, String *missingMacro,
- const MacroProcessor::EscapeCallback& escapeFn, int recursionLevel)
+ const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros,
+ bool useResolvedMacros, int recursionLevel)
{
CONTEXT("Resolving macros for string '" + str + "'");
String resolved_macro;
bool recursive_macro;
- bool found = ResolveMacro(name, resolvers, cr, &resolved_macro, &recursive_macro);
+ bool found;
+
+ if (useResolvedMacros) {
+ recursive_macro = false;
+ found = resolvedMacros->Contains(name);
+
+ if (found)
+ resolved_macro = resolvedMacros->Get(name);
+ } else
+ found = ResolveMacro(name, resolvers, cr, &resolved_macro, &recursive_macro);
/* $$ is an escape sequence for $. */
if (name.IsEmpty()) {
/* recursively resolve macros in the macro if it was a user macro */
if (recursive_macro)
resolved_macro = InternalResolveMacros(resolved_macro,
- resolvers, cr, missingMacro, EscapeCallback(), recursionLevel + 1);
+ resolvers, cr, missingMacro, EscapeCallback(), Dictionary::Ptr(),
+ false, recursionLevel + 1);
+
+ if (!useResolvedMacros && found && resolvedMacros)
+ resolvedMacros->Set(name, resolved_macro);
if (escapeFn)
resolved_macro = escapeFn(resolved_macro);
static Value ResolveMacros(const Value& str, const ResolverList& resolvers,
const CheckResult::Ptr& cr = CheckResult::Ptr(), String *missingMacro = NULL,
- const EscapeCallback& escapeFn = EscapeCallback());
+ const EscapeCallback& escapeFn = EscapeCallback(),
+ const Dictionary::Ptr& resolvedMacros = Dictionary::Ptr(),
+ bool useResolvedMacros = false);
private:
MacroProcessor(void);
static String InternalResolveMacros(const String& str,
const ResolverList& resolvers, const CheckResult::Ptr& cr,
String *missingMacro, const EscapeCallback& escapeFn,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros,
int recursionLevel = 0);
};
location + ": Type filter is invalid.");
}
}
+
+Endpoint::Ptr Notification::GetCommandEndpoint(void) const
+{
+ return Endpoint::GetByName(GetCommandEndpointRaw());
+}
+
#include "icinga/usergroup.hpp"
#include "icinga/timeperiod.hpp"
#include "icinga/checkresult.hpp"
+#include "remote/endpoint.hpp"
#include "remote/messageorigin.hpp"
#include "base/array.hpp"
bool CheckNotificationUserFilters(NotificationType type, const User::Ptr& user, bool force);
void ResetNotifiedUsers(void);
+ Endpoint::Ptr GetCommandEndpoint(void) const;
static String NotificationTypeToString(NotificationType type);
[state, set_protected] double next_notification (NextNotificationRaw);
[state, set_protected] Value notification_number;
[state] double last_problem_notification;
+
+ [config] String command_endpoint (CommandEndpointRaw);
};
}
REGISTER_TYPE(NotificationCommand);
Dictionary::Ptr NotificationCommand::Execute(const Notification::Ptr& notification,
- const User::Ptr& user, const CheckResult::Ptr& cr, const NotificationType& type,
- const String& author, const String& comment)
+ const User::Ptr& user, const CheckResult::Ptr& cr, const NotificationType& type,
+ const String& author, const String& comment, const Dictionary::Ptr& resolvedMacros,
+ bool useResolvedMacros)
{
std::vector<Value> arguments;
arguments.push_back(notification);
arguments.push_back(type);
arguments.push_back(author);
arguments.push_back(comment);
+ arguments.push_back(resolvedMacros);
+ arguments.push_back(useResolvedMacros);
return InvokeMethod("execute", arguments);
}
virtual Dictionary::Ptr Execute(const intrusive_ptr<Notification>& notification,
const User::Ptr& user, const CheckResult::Ptr& cr, const NotificationType& type,
- const String& author, const String& comment);
+ const String& author, const String& comment,
+ const Dictionary::Ptr& resolvedMacros = Dictionary::Ptr(),
+ bool useResolvedMacros = false);
};
}
void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkable::Ptr& checkable,
const CheckResult::Ptr& cr, const MacroProcessor::ResolverList& macroResolvers,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros,
const boost::function<void(const Value& commandLine, const ProcessResult&)>& callback)
{
Value raw_command = commandObj->GetCommandLine();
Value command;
if (!raw_arguments || raw_command.IsObjectType<Array>())
- command = MacroProcessor::ResolveMacros(raw_command, macroResolvers, cr, NULL, Utility::EscapeShellArg);
+ command = MacroProcessor::ResolveMacros(raw_command, macroResolvers, cr, NULL,
+ Utility::EscapeShellArg, resolvedMacros, useResolvedMacros);
else {
Array::Ptr arr = new Array();
arr->Add(raw_command);
if (!set_if.IsEmpty()) {
String missingMacro;
String set_if_resolved = MacroProcessor::ResolveMacros(set_if, macroResolvers,
- cr, &missingMacro);
+ cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros,
+ useResolvedMacros);
if (!missingMacro.IsEmpty())
continue;
String missingMacro;
arg.Value = MacroProcessor::ResolveMacros(argval, macroResolvers,
- cr, &missingMacro);
+ cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros,
+ useResolvedMacros);
if (!missingMacro.IsEmpty()) {
if (required) {
BOOST_FOREACH(const Dictionary::Pair& kv, env) {
String name = kv.second;
- Value value = MacroProcessor::ResolveMacros(name, macroResolvers, cr);
+ Value value = MacroProcessor::ResolveMacros(name, macroResolvers, cr,
+ NULL, MacroProcessor::EscapeCallback(), resolvedMacros,
+ useResolvedMacros);
envMacros->Set(kv.first, value);
}
}
+ if (resolvedMacros && !useResolvedMacros)
+ return;
+
Process::Ptr process = new Process(Process::PrepareCommand(command), envMacros);
process->SetTimeout(commandObj->GetTimeout());
process->Run(boost::bind(callback, command, _1));
public:
static void ExecuteCommand(const Command::Ptr& commandObj, const Checkable::Ptr& checkable,
const CheckResult::Ptr& cr, const MacroProcessor::ResolverList& macroResolvers,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros,
const boost::function<void(const Value& commandLine, const ProcessResult&)>& callback = boost::function<void(const Value& commandLine, const ProcessResult&)>());
static ServiceState ExitStatusToState(int exitStatus);
{
CLSID clsid;
HRESULT hr = CLSIDFromProgID(L"System.Collections.Hashtable", &clsid);
-
+
mscorlib::IDictionaryPtr pHashtable;
CoCreateInstance(clsid, NULL, CLSCTX_ALL, __uuidof(mscorlib::IDictionary), (void **)&pHashtable);
String value = kv.second;
pHashtable->Add(kv.first.CStr(), value.CStr());
}
-
+
mscorlib::_ObjectPtr pObject;
vtObject.pdispVal->QueryInterface(__uuidof(mscorlib::_Object), (void**)&pObject);
mscorlib::_TypePtr pType = pObject->GetType();
cr->SetPerformanceData(PluginUtility::SplitPerfdata(static_cast<const char *>(sPerformanceData)));
}
-void ClrCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
+void ClrCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
CheckCommand::Ptr commandObj = checkable->GetCheckCommand();
Value raw_command = commandObj->GetCommandLine();
class I2_METHODS_API ClrCheckTask
{
public:
- static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr);
+ static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private:
ClrCheckTask(void);
-
- static void ProcessFinishedHandler(const Checkable::Ptr& service, const CheckResult::Ptr& cr, const ProcessResult& pr);
-
};
}
REGISTER_SCRIPTFUNCTION(ClusterCheck, &ClusterCheckTask::ScriptFunc);
-void ClusterCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
+void ClusterCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
ApiListener::Ptr listener = ApiListener::GetInstance();
class ClusterCheckTask
{
public:
- static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr);
+ static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private:
ClusterCheckTask(void);
REGISTER_SCRIPTFUNCTION(ClusterZoneCheck, &ClusterZoneCheckTask::ScriptFunc);
-void ClusterZoneCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
+void ClusterZoneCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
ApiListener::Ptr listener = ApiListener::GetInstance();
checkable->ProcessCheckResult(cr);
}
-
class ClusterZoneCheckTask
{
public:
- static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr);
+ static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private:
ClusterZoneCheckTask(void);
REGISTER_SCRIPTFUNCTION(IcingaCheck, &IcingaCheckTask::ScriptFunc);
-void IcingaCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr)
+void IcingaCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
double interval = Utility::GetTime() - Application::GetStartTime();
service->ProcessCheckResult(cr);
}
-
class I2_METHODS_API IcingaCheckTask
{
public:
- static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr);
+ static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private:
IcingaCheckTask(void);
REGISTER_SCRIPTFUNCTION(NullCheck, &NullCheckTask::ScriptFunc);
-void NullCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr)
+void NullCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
String output = "Hello from ";
output += Utility::GetFQDN();
service->ProcessCheckResult(cr);
}
-
class I2_METHODS_API NullCheckTask
{
public:
- static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr);
+ static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private:
NullCheckTask(void);
REGISTER_SCRIPTFUNCTION(NullEvent, &NullEventTask::ScriptFunc);
-void NullEventTask::ScriptFunc(const Checkable::Ptr&)
+void NullEventTask::ScriptFunc(const Checkable::Ptr&, const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{ }
class I2_METHODS_API NullEventTask
{
public:
- static void ScriptFunc(const Checkable::Ptr& service);
+ static void ScriptFunc(const Checkable::Ptr& service,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private:
NullEventTask(void);
REGISTER_SCRIPTFUNCTION(PluginCheck, &PluginCheckTask::ScriptFunc);
-void PluginCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
+void PluginCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
CheckCommand::Ptr commandObj = checkable->GetCheckCommand();
resolvers.push_back(std::make_pair("command", commandObj));
resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
- PluginUtility::ExecuteCommand(commandObj, checkable, checkable->GetLastCheckResult(), resolvers, boost::bind(&PluginCheckTask::ProcessFinishedHandler, checkable, cr, _1, _2));
+ PluginUtility::ExecuteCommand(commandObj, checkable, checkable->GetLastCheckResult(),
+ resolvers, resolvedMacros, useResolvedMacros,
+ boost::bind(&PluginCheckTask::ProcessFinishedHandler, checkable, cr, _1, _2));
}
void PluginCheckTask::ProcessFinishedHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, const Value& commandLine, const ProcessResult& pr)
class I2_METHODS_API PluginCheckTask
{
public:
- static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr);
+ static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private:
PluginCheckTask(void);
REGISTER_SCRIPTFUNCTION(PluginEvent, &PluginEventTask::ScriptFunc);
-void PluginEventTask::ScriptFunc(const Checkable::Ptr& checkable)
+void PluginEventTask::ScriptFunc(const Checkable::Ptr& checkable,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
EventCommand::Ptr commandObj = checkable->GetEventCommand();
resolvers.push_back(std::make_pair("command", commandObj));
resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
- PluginUtility::ExecuteCommand(commandObj, checkable, checkable->GetLastCheckResult(), resolvers, boost::bind(&PluginEventTask::ProcessFinishedHandler, checkable, _1, _2));
+ PluginUtility::ExecuteCommand(commandObj, checkable, checkable->GetLastCheckResult(),
+ resolvers, resolvedMacros, useResolvedMacros,
+ boost::bind(&PluginEventTask::ProcessFinishedHandler, checkable, _1, _2));
}
void PluginEventTask::ProcessFinishedHandler(const Checkable::Ptr& checkable, const Value& commandLine, const ProcessResult& pr)
class I2_METHODS_API PluginEventTask
{
public:
- static void ScriptFunc(const Checkable::Ptr& service);
+ static void ScriptFunc(const Checkable::Ptr& service,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private:
PluginEventTask(void);
REGISTER_SCRIPTFUNCTION(PluginNotification, &PluginNotificationTask::ScriptFunc);
-void PluginNotificationTask::ScriptFunc(const Notification::Ptr& notification, const User::Ptr& user, const CheckResult::Ptr& cr, int itype,
- const String& author, const String& comment)
+void PluginNotificationTask::ScriptFunc(const Notification::Ptr& notification,
+ const User::Ptr& user, const CheckResult::Ptr& cr, int itype,
+ const String& author, const String& comment, const Dictionary::Ptr& resolvedMacros,
+ bool useResolvedMacros)
{
NotificationCommand::Ptr commandObj = notification->GetCommand();
resolvers.push_back(std::make_pair("command", commandObj));
resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
- PluginUtility::ExecuteCommand(commandObj, checkable, cr, resolvers, boost::bind(&PluginNotificationTask::ProcessFinishedHandler, checkable, _1, _2));
+ PluginUtility::ExecuteCommand(commandObj, checkable, cr, resolvers,
+ resolvedMacros, useResolvedMacros,
+ boost::bind(&PluginNotificationTask::ProcessFinishedHandler, checkable, _1, _2));
}
void PluginNotificationTask::ProcessFinishedHandler(const Checkable::Ptr& checkable, const Value& commandLine, const ProcessResult& pr)
public:
static void ScriptFunc(const Notification::Ptr& notification,
const User::Ptr& user, const CheckResult::Ptr& cr, int itype,
- const String& author, const String& comment);
+ const String& author, const String& comment,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private:
PluginNotificationTask(void);
REGISTER_SCRIPTFUNCTION(RandomCheck, &RandomCheckTask::ScriptFunc);
-void RandomCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr)
+void RandomCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
String output = "Hello from ";
output += Utility::GetFQDN();
service->ProcessCheckResult(cr);
}
-
class RandomCheckTask
{
public:
- static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr);
+ static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private:
RandomCheckTask(void);
bool verify_ok = tlsStream->IsVerifyOK();
Log(LogInformation, "ApiListener")
- << "New client connection for identity '" << identity << "'" << (verify_ok ? "" : " (unauthenticated");
+ << "New client connection for identity '" << identity << "'" << (verify_ok ? "" : " (unauthenticated)");
Endpoint::Ptr endpoint;
}
}
+void ApiListener::SyncSendMessage(const Endpoint::Ptr& endpoint, const Dictionary::Ptr& message)
+{
+ ObjectLock olock(endpoint);
+
+ if (!endpoint->GetSyncing()) {
+ Log(LogNotice, "ApiListener")
+ << "Sending message to '" << endpoint->GetName() << "'";
+
+ BOOST_FOREACH(const ApiClient::Ptr& client, endpoint->GetClients())
+ client->SendMessage(message);
+ }
+}
+
+
void ApiListener::SyncRelayMessage(const MessageOrigin& origin, const DynamicObject::Ptr& secobj, const Dictionary::Ptr& message, bool log)
{
double ts = Utility::GetTime();
finishedZones.insert(target_zone);
- {
- ObjectLock olock(endpoint);
-
- if (!endpoint->GetSyncing()) {
- Log(LogNotice, "ApiListener")
- << "Sending message to '" << endpoint->GetName() << "'";
-
- BOOST_FOREACH(const ApiClient::Ptr& client, endpoint->GetClients())
- client->SendMessage(message);
- }
- }
+ SyncSendMessage(endpoint, message);
}
BOOST_FOREACH(const Endpoint::Ptr& endpoint, skippedEndpoints)
stats = listener->GetStatus();
+ ObjectLock olock(stats.second);
BOOST_FOREACH(const Dictionary::Pair& kv, stats.second)
perfdata->Add("'api_" + kv.first + "'=" + Convert::ToString(kv.second));
static String GetApiDir(void);
+ void SyncSendMessage(const Endpoint::Ptr& endpoint, const Dictionary::Ptr& message);
void RelayMessage(const MessageOrigin& origin, const DynamicObject::Ptr& secobj, const Dictionary::Ptr& message, bool log);
static Value StatsFunc(Dictionary::Ptr& status, Array::Ptr& perfdata);
};
[config] bool accept_config;
+ [config] bool accept_commands;
[config] String ticket_salt;
%attribute %string "bind_port",
%attribute %number "accept_config",
+ %attribute %number "accept_commands",
%attribute %string "ticket_salt"
}