]> granicus.if.org Git - icinga2/commitdiff
Implement support for executing remote commands
authorGunnar Beutner <gunnar.beutner@netways.de>
Thu, 13 Nov 2014 10:23:57 +0000 (11:23 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 13 Nov 2014 13:54:55 +0000 (14:54 +0100)
fixes #7559

53 files changed:
lib/base/dynamicobject.cpp
lib/base/dynamicobject.hpp
lib/base/scriptfunctionwrapper.hpp
lib/base/threadpool.cpp
lib/cli/nodewizardcommand.cpp
lib/db_ido/dbobject.cpp
lib/hello/CMakeLists.txt
lib/hello/hello.cpp
lib/icinga/apievents.cpp
lib/icinga/apievents.hpp
lib/icinga/checkable-check.cpp
lib/icinga/checkable-event.cpp
lib/icinga/checkable.cpp
lib/icinga/checkable.hpp
lib/icinga/checkable.ti
lib/icinga/checkcommand.cpp
lib/icinga/checkcommand.hpp
lib/icinga/eventcommand.cpp
lib/icinga/eventcommand.hpp
lib/icinga/icinga-type.conf
lib/icinga/macroprocessor.cpp
lib/icinga/macroprocessor.hpp
lib/icinga/notification.cpp
lib/icinga/notification.hpp
lib/icinga/notification.ti
lib/icinga/notificationcommand.cpp
lib/icinga/notificationcommand.hpp
lib/icinga/pluginutility.cpp
lib/icinga/pluginutility.hpp
lib/methods/clrchecktask.cpp
lib/methods/clrchecktask.hpp
lib/methods/clusterchecktask.cpp
lib/methods/clusterchecktask.hpp
lib/methods/clusterzonechecktask.cpp
lib/methods/clusterzonechecktask.hpp
lib/methods/icingachecktask.cpp
lib/methods/icingachecktask.hpp
lib/methods/nullchecktask.cpp
lib/methods/nullchecktask.hpp
lib/methods/nulleventtask.cpp
lib/methods/nulleventtask.hpp
lib/methods/pluginchecktask.cpp
lib/methods/pluginchecktask.hpp
lib/methods/plugineventtask.cpp
lib/methods/plugineventtask.hpp
lib/methods/pluginnotificationtask.cpp
lib/methods/pluginnotificationtask.hpp
lib/methods/randomchecktask.cpp
lib/methods/randomchecktask.hpp
lib/remote/apilistener.cpp
lib/remote/apilistener.hpp
lib/remote/apilistener.ti
lib/remote/remote-type.conf

index 77c4495c7c6492e7f9d56206dcbb8e61a37aa11a..b907ca000c57f821fe0eda6843ca352dd889e43c 100644 (file)
@@ -76,7 +76,7 @@ bool DynamicObject::IsPaused(void) const
        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();
 
@@ -85,15 +85,15 @@ void DynamicObject::SetExtension(const String& key, const Object::Ptr& object)
                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);
 }
index 46e3a24d6371d8396413fa579574feefb6206809..bcae37a20d8f6871f5cd44b88f19b10e6f2262ca 100644 (file)
@@ -60,8 +60,8 @@ public:
        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);
index 4f8002de2ca4421d573430dcf589820e5432c25f..e0b08be4182dab903ec91232a5fcaa4c07c836eb 100644 (file)
@@ -268,6 +268,96 @@ boost::function<Value (const std::vector<Value>& arguments)> WrapScriptFunction(
        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>&))
 {
index 3ffae3a93eee916bb86a54b8c27f03873eeff2b0..b9771c4064208f0c9046c2a8c450101fa469aee2 100644 (file)
@@ -48,7 +48,7 @@ void ThreadPool::Start(void)
        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)
index 2612cf78a5dba346663cb9c0bfe2829d942841fa..ffc9b1c01bdca77bf51b737890a74eb0fcf29171 100644 (file)
@@ -76,8 +76,6 @@ int NodeWizardCommand::Run(const boost::program_options::variables_map& vm, cons
            << "\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?
@@ -315,7 +313,7 @@ wizard_master_host:
 
 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);
@@ -621,8 +619,5 @@ wizard_ticket:
 
        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;
 }
index 28fbf8aee6992633a3aaa9fa0944499189b48745..c24f1559b4a55c958fefd776b1c71e845d020035 100644 (file)
@@ -293,7 +293,7 @@ void DbObject::OnStatusUpdate(void)
 
 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;
index ce92e30f05555fbfa1f09e6d4453fc3ddbc01aa4..2a11666c5997d41e3207d2333b21f85cc388264f 100644 (file)
@@ -29,7 +29,7 @@ endif()
 
 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
@@ -42,5 +42,3 @@ install(
   RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/icinga2
 )
-
-
index bd9d0597fcbc5134db7cbfadc6d5f733383f5727..60138037321356e587f520b86c5cd0a10e71d410 100644 (file)
  ******************************************************************************/
 
 #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;
 
@@ -34,5 +39,35 @@ int Hello::Main(void)
 {
        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;
 }
index dc354199a4a549b52b62aaf4c9367f2cddabf115..fdcd4341838457a38c3b50fc148498b8ee0a5041 100644 (file)
@@ -63,6 +63,7 @@ REGISTER_APIFUNCTION(RemoveDowntime, event, &ApiEvents::DowntimeRemovedAPIHandle
 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;
 
@@ -100,13 +101,8 @@ void ApiEvents::StaticInitialize(void)
        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");
@@ -119,16 +115,35 @@ void ApiEvents::CheckResultHandler(const Checkable::Ptr& checkable, const CheckR
        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)
@@ -175,7 +190,7 @@ Value ApiEvents::CheckResultAPIHandler(const MessageOrigin& origin, const Dictio
        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);
@@ -1493,6 +1508,73 @@ Value ApiEvents::AcknowledgementClearedAPIHandler(const MessageOrigin& origin, c
        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();
index 2eb0078de880a52e571c9c77020d4a1f9d67b25e..e76cea5c1b89edaa24da04289d9a4cfad8de7c64 100644 (file)
@@ -109,9 +109,13 @@ public:
        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);
 };
 
 }
index 77c4cd46524ce17c6612df21b53057c4ac9111d7..f3d90493d11d9cb42581ddfc8e031b0597441924 100644 (file)
@@ -23,7 +23,9 @@
 #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"
@@ -255,6 +257,19 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig
        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);
 
@@ -470,7 +485,7 @@ bool Checkable::IsCheckPending(void) const
        return m_CheckRunning;
 }
 
-void Checkable::ExecuteCheck(void)
+void Checkable::ExecuteCheck(const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
 {
        CONTEXT("Executing check for object '" + GetName() + "'");
 
@@ -503,7 +518,52 @@ void Checkable::ExecuteCheck(void)
        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)
index 86e450ddf4f9d1eacb50c54b469ea2010796d9bc..ee3acf1366eb69f5a8e64373d151971c6561f7d3 100644 (file)
@@ -20,6 +20,8 @@
 #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"
 
@@ -63,7 +65,7 @@ void Checkable::SetEventCommand(const EventCommand::Ptr& command, const MessageO
        OnEventCommandChanged(this, command, origin);
 }
 
-void Checkable::ExecuteEventHandler(void)
+void Checkable::ExecuteEventHandler(const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
 {
        CONTEXT("Executing event handler for object '" + GetName() + "'");
 
@@ -78,7 +80,43 @@ void Checkable::ExecuteEventHandler(void)
        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);
 }
index 76a064911f9eaa422b506b641327444edf6738ff..737b5e1f10da492c9a00aad90c2a1d0eb220c0db 100644 (file)
@@ -258,3 +258,8 @@ void Checkable::SetModifiedAttributes(int flags, const MessageOrigin& origin)
                OnVarsChanged(this, GetVars(), origin);
        }
 }
+
+Endpoint::Ptr Checkable::GetCommandEndpoint(void) const
+{
+       return Endpoint::GetByName(GetCommandEndpointRaw());
+}
index 99d6c90d6baf2b2ca1f5ce40cf043fb23bb27366..5f414539cef0e8f1d3e27d56459f31efa36b387d 100644 (file)
@@ -26,6 +26,7 @@
 #include "icinga/notification.hpp"
 #include "icinga/comment.hpp"
 #include "icinga/downtime.hpp"
+#include "remote/endpoint.hpp"
 #include "remote/messageorigin.hpp"
 
 namespace icinga
@@ -134,12 +135,15 @@ public:
 
        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);
@@ -241,7 +245,8 @@ public:
        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());
index 65d420094201917edec5968dbba0e748fd7d7aed..fbac2687d605b89f83a3b1a706d2c7213f160b0c 100644 (file)
@@ -146,6 +146,8 @@ abstract class Checkable : CustomVarObject
        [state] Value override_check_command;
        [state] Value override_max_check_attempts;
        [state] Value override_check_period;
+
+       [config] String command_endpoint (CommandEndpointRaw);
 };
 
 }
index ff7728f060d643259862529c8793eb3ece21ceef..2ad18c14c5cba8b3ffc332dfbfc174faa7d1e290 100644 (file)
@@ -24,10 +24,13 @@ using namespace icinga;
 
 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);
 }
index dde46ec580d8cda067539f0b0d81c4c0bb983047..f6349a3cc93e07d843cb6a80a60113eb233c3020 100644 (file)
@@ -37,7 +37,9 @@ public:
        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);
 };
 
 }
index 2a0b92e7b417d68c9a2b6fa7eb8c1789f25db9a5..3ad50a992f56f7bfe1984416a342a68f1a2ea560 100644 (file)
@@ -23,9 +23,12 @@ using namespace icinga;
 
 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);
 }
index 6054775266df6de68529987d5889afb8806d068b..d9b4c569c96963c723cc4103c6b764b1ad1111c7 100644 (file)
@@ -37,7 +37,9 @@ public:
        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);
 };
 
 }
index de9861f6c038b5f03433e080f998394d77fc7924..4c8d0677211658fb5f99e7284dfd2cce955df967 100644 (file)
@@ -54,6 +54,8 @@
        %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 {
index 05ce4a4294cd8f3d032d55c300ef2ea1484a3a5d..d47cec010e2085cc57347a0f4916661d4bf4fb52 100644 (file)
@@ -34,7 +34,8 @@ using namespace icinga;
 
 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;
 
@@ -42,7 +43,8 @@ Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolv
                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;
@@ -51,7 +53,8 @@ Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolv
 
                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;
@@ -160,7 +163,8 @@ bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resol
 
 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 + "'");
 
@@ -181,7 +185,16 @@ String MacroProcessor::InternalResolveMacros(const String& str, const ResolverLi
 
                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()) {
@@ -200,7 +213,11 @@ String MacroProcessor::InternalResolveMacros(const String& str, const ResolverLi
                /* 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);
index 4fb27a9db7e8032ce9859087453b2673bfc0b712..a7e0b0f9c835e5228502ef482dfc2a2baf066180 100644 (file)
@@ -43,7 +43,9 @@ public:
 
        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);
@@ -53,6 +55,7 @@ private:
        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);
 };
 
index a5c561aeb15adda35030c9152bc4aaefb91ca49a..930cdde02f4b611b346b03d87ec259473ad3579b 100644 (file)
@@ -519,3 +519,9 @@ void Notification::ValidateFilters(const String& location, const Dictionary::Ptr
                    location + ": Type filter is invalid.");
        }
 }
+
+Endpoint::Ptr Notification::GetCommandEndpoint(void) const
+{
+       return Endpoint::GetByName(GetCommandEndpointRaw());
+}
+
index 64cd8f7ab9608455d63e20136550aef04a38a8b0..a10f181d952d89c47c4496bf00421b31a0495eaa 100644 (file)
@@ -26,6 +26,7 @@
 #include "icinga/usergroup.hpp"
 #include "icinga/timeperiod.hpp"
 #include "icinga/checkresult.hpp"
+#include "remote/endpoint.hpp"
 #include "remote/messageorigin.hpp"
 #include "base/array.hpp"
 
@@ -98,6 +99,7 @@ public:
        bool CheckNotificationUserFilters(NotificationType type, const User::Ptr& user, bool force);
 
        void ResetNotifiedUsers(void);
+       Endpoint::Ptr GetCommandEndpoint(void) const;
 
        static String NotificationTypeToString(NotificationType type);
 
index dfe6be4bed1cc583004286903d01e1e15089c94a..c0e3591b25f9be0b97be35a0d617b50bea5587c1 100644 (file)
@@ -51,6 +51,8 @@ class Notification : CustomVarObject < NotificationNameComposer
        [state, set_protected] double next_notification (NextNotificationRaw);
        [state, set_protected] Value notification_number;
        [state] double last_problem_notification;
+
+       [config] String command_endpoint (CommandEndpointRaw);
 };
 
 }
index ab00c30a6d06a918ba6301d65553981c3dc568b7..c84aa2986f740f3069357d041489b6cea3df23cd 100644 (file)
@@ -24,8 +24,9 @@ using namespace icinga;
 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);
@@ -34,5 +35,7 @@ Dictionary::Ptr NotificationCommand::Execute(const Notification::Ptr& notificati
        arguments.push_back(type);
        arguments.push_back(author);
        arguments.push_back(comment);
+       arguments.push_back(resolvedMacros);
+       arguments.push_back(useResolvedMacros);
        return InvokeMethod("execute", arguments);
 }
index be8d069ff2965063afc95fba2d508d7f3478275f..98a106e88a43ce8efe9bdb938fa2af8a2aa5cd0c 100644 (file)
@@ -41,7 +41,9 @@ public:
 
        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);
 };
 
 }
index 87f95cb48ce10bff8a4e23f23db2d23da07a5d5d..736d7f465589e128b614c612d57d4f4011268d5f 100644 (file)
@@ -52,6 +52,7 @@ struct CommandArgument
 
 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();
@@ -59,7 +60,8 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab
 
        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);
@@ -92,7 +94,8 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab
                                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;
@@ -116,7 +119,8 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab
 
                        String missingMacro;
                        arg.Value = MacroProcessor::ResolveMacros(argval, macroResolvers,
-                           cr, &missingMacro);
+                           cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros,
+                           useResolvedMacros);
 
                        if (!missingMacro.IsEmpty()) {
                                if (required) {
@@ -165,12 +169,17 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab
                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));
index 309aaa26f466ffca56b8fa18a751ed7a5eac08c2..2039f1237efb934ad90520e4a8cfd32b32067256 100644 (file)
@@ -41,6 +41,7 @@ class I2_ICINGA_API PluginUtility
 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);
index 1c9eeaa5ef692896616aeccd6aed94ea482b81ae..af0fd3c982bc7e2ea5089a7fd2846dbda94e0f3f 100644 (file)
@@ -86,7 +86,7 @@ static variant_t InvokeClrMethod(const variant_t& vtObject, const String& method
 {
        CLSID clsid;
        HRESULT hr = CLSIDFromProgID(L"System.Collections.Hashtable", &clsid);
-       
+
        mscorlib::IDictionaryPtr pHashtable;
        CoCreateInstance(clsid, NULL, CLSCTX_ALL, __uuidof(mscorlib::IDictionary), (void **)&pHashtable);
 
@@ -95,7 +95,7 @@ static variant_t InvokeClrMethod(const variant_t& vtObject, const String& method
                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();
@@ -145,7 +145,8 @@ static void FillCheckResult(const CheckResult::Ptr& cr, variant_t vtResult)
        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();
index 5448030c6147fd6bb9c34f6c3fbe5f04c5089743..f43f2f0050a932e9776831fcd27882cb6f015ccc 100644 (file)
@@ -35,13 +35,11 @@ namespace icinga
 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);
-
 };
 
 }
index efbe4ad0882bd25c89262f42b9612c602ccef4e7..f7e665fb9eac74608c5990b1bfbca0566136c017 100644 (file)
@@ -36,7 +36,8 @@ using namespace icinga;
 
 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();
 
index e6902bfbfa017cf71e8a58b72fca19e963b442f6..d8f0a6203ddaa30465f1e83503af1e4751970e87 100644 (file)
@@ -33,7 +33,8 @@ namespace icinga
 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);
index b7442ac672ed2bb382bb82528cafb4104634f6e5..96ee98727116b71619ffb16b1b50eb51aa7e4b3f 100644 (file)
@@ -30,7 +30,8 @@ using namespace icinga;
 
 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();
 
@@ -92,4 +93,3 @@ void ClusterZoneCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const Che
 
        checkable->ProcessCheckResult(cr);
 }
-
index dd96717b083a32636ec1fdba332dee58790d923e..513bfdf18d161fa831f207cd49d1ad6817a5659b 100644 (file)
@@ -33,7 +33,8 @@ namespace icinga
 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);
index 3cf69fb0d697cce8d08b31e7dc6d1ea2a5bd28b4..400d05f1e7070f2baf3e0c7bd50c059a18641f7a 100644 (file)
@@ -32,7 +32,8 @@ using namespace icinga;
 
 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();
 
@@ -99,4 +100,3 @@ void IcingaCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResul
 
        service->ProcessCheckResult(cr);
 }
-
index b3c1d2bcfcfbe4cce2705ea9b01b6c9a9d7f70b1..53e76d501b7a0507efe55f3fdbccd91d4d8261c4 100644 (file)
@@ -34,7 +34,8 @@ namespace icinga
 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);
index 2c52a945748d31e60052435927903f16cd55c672..efb4795d39e7066818c47b48b244493f1a8f164c 100644 (file)
@@ -31,7 +31,8 @@ using namespace icinga;
 
 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();
@@ -45,4 +46,3 @@ void NullCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResult:
 
        service->ProcessCheckResult(cr);
 }
-
index 6587e71e24daf158d1b40a33ae8e77375f76213a..4ce7b7635cbca19ea22582ca2d5ec1612bd8a024 100644 (file)
@@ -35,7 +35,8 @@ namespace icinga
 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);
index 88c0670dbf816d06159bb3c7b9d86f05aa13b783..4332a67d10e692b97c0e8b1ec1913b70cc86d0ec 100644 (file)
@@ -25,5 +25,5 @@ using namespace icinga;
 
 REGISTER_SCRIPTFUNCTION(NullEvent, &NullEventTask::ScriptFunc);
 
-void NullEventTask::ScriptFunc(const Checkable::Ptr&)
+void NullEventTask::ScriptFunc(const Checkable::Ptr&, const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
 { }
index cc9320104bc831dade196515f07507f4093f47ad..3025661fe6242389c9ac7c073b57c859debb4971 100644 (file)
@@ -35,7 +35,8 @@ namespace icinga
 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);
index dd7d6f526604dfa28509e4baf45b2d0c3056d1ca..b45dcf72cc453bb6a098ceebff916425c84bb25c 100644 (file)
@@ -36,7 +36,8 @@ using namespace icinga;
 
 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();
 
@@ -51,7 +52,9 @@ void PluginCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckRes
        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)
index 526c49251739297adfcabbdd81a917e3e22dfe49..619467bdd617c0c813c112fb69c89e803d7b7062 100644 (file)
@@ -35,7 +35,8 @@ namespace icinga
 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);
index 5686edd93a05569c93f85681809e1c4f5befa7ab..e976b00180e88ad9874e31353f727f662598b862 100644 (file)
@@ -34,7 +34,8 @@ using namespace icinga;
 
 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();
 
@@ -49,7 +50,9 @@ void PluginEventTask::ScriptFunc(const Checkable::Ptr& checkable)
        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)
index 755fc9d1c5d8cced73b3ef82e6cc36b24939d12e..9d536937aa6ed9a91eac23ac59449481a91b8d27 100644 (file)
@@ -35,7 +35,8 @@ namespace icinga
 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);
index ec192436aac7f169a4698962ad88e92471c1d741..39fb67879b1359961c16bb28ca4d557280a9b3c4 100644 (file)
@@ -35,8 +35,10 @@ using namespace icinga;
 
 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();
 
@@ -63,7 +65,9 @@ void PluginNotificationTask::ScriptFunc(const Notification::Ptr& notification, c
        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)
index f96dff84d2425ca3a316a1f65b22e392acd03cbe..5547a796050cb54e85bcf3cef18bb3ac30bc9033 100644 (file)
@@ -38,7 +38,8 @@ class I2_METHODS_API PluginNotificationTask
 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);
index 47a930a1a027eeb320a2d6b80c85c1b039bfc7cb..1b8eaca3732073c48ed0f49059d2ff4df8e260a8 100644 (file)
@@ -31,7 +31,8 @@ using namespace icinga;
 
 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();
@@ -45,4 +46,3 @@ void RandomCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResul
 
        service->ProcessCheckResult(cr);
 }
-
index d026bf7fe8b220958dcadb93122664f4d5560042..8e14ed8ddde28fe873b49ffbd70e917b6e26b17b 100644 (file)
@@ -34,7 +34,8 @@ namespace icinga
 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);
index 5fb31b647e856270f8ee79caabe33e1124a048b0..e8578b0d76b60175ced1933cb9567d8d1e9e19d8 100644 (file)
@@ -304,7 +304,7 @@ void ApiListener::NewClientHandler(const Socket::Ptr& client, ConnectionRole rol
        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;
 
@@ -483,6 +483,20 @@ void ApiListener::PersistMessage(const Dictionary::Ptr& message, const DynamicOb
        }
 }
 
+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();
@@ -548,17 +562,7 @@ void ApiListener::SyncRelayMessage(const MessageOrigin& origin, const DynamicObj
 
                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)
@@ -750,6 +754,7 @@ Value ApiListener::StatsFunc(Dictionary::Ptr& status, Array::Ptr& perfdata)
 
        stats = listener->GetStatus();
 
+       ObjectLock olock(stats.second);
        BOOST_FOREACH(const Dictionary::Pair& kv, stats.second)
                perfdata->Add("'api_" + kv.first + "'=" + Convert::ToString(kv.second));
 
index de1d8a7ab5e62540a0675d4f4d354b13b066835e..5299ed4a0e0d50998fa39c4adc9299ba4aef1851 100644 (file)
@@ -56,6 +56,7 @@ public:
 
        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);
index 886ee1366399302d0e42de94ef5b1bbbbb6cbb3a..3e3e29b0d11d879d8b9265e13894881f4e47a521 100644 (file)
@@ -36,6 +36,7 @@ class ApiListener : DynamicObject
        };
 
        [config] bool accept_config;
+       [config] bool accept_commands;
 
        [config] String ticket_salt;
 
index ae1b97fa1dd19597d2d5a27e68dfdc2850d3d58c..df2331f7dfa7716a2ff4629db961f79cee18c1ed 100644 (file)
@@ -33,6 +33,7 @@
        %attribute %string "bind_port",
 
        %attribute %number "accept_config",
+       %attribute %number "accept_commands",
 
        %attribute %string "ticket_salt"
 }