From 1d807d91bc903b3df4578075e6948b39009b9f5c Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 13 Feb 2013 20:08:09 +0100 Subject: [PATCH] Implemented dictionary support for commands. --- itl/service-common.conf | 65 ++++++++++++++++++++++----- itl/types.conf | 2 + lib/base/process.cpp | 15 ++++++- lib/base/process.h | 2 +- lib/icinga/macroprocessor.cpp | 45 ++++++++++++------- lib/icinga/macroprocessor.h | 7 ++- lib/icinga/notification.cpp | 2 +- lib/icinga/notification.h | 2 +- lib/icinga/pluginchecktask.cpp | 8 ++-- lib/icinga/pluginnotificationtask.cpp | 8 ++-- lib/icinga/service-check.cpp | 2 +- lib/icinga/service.h | 2 +- 12 files changed, 116 insertions(+), 44 deletions(-) diff --git a/itl/service-common.conf b/itl/service-common.conf index 9f82f8b03..fb70f916a 100644 --- a/itl/service-common.conf +++ b/itl/service-common.conf @@ -18,7 +18,15 @@ ******************************************************************************/ abstract object Service "ping4" inherits "plugin-service" { - check_command = "$plugindir$/check_ping -4 -H $address$ -w $wrta$,$wpl$% -c $crta$,$cpl$%a -p $packets$ -t $timeout$", + check_command = { + "$plugindir$/check_ping", + "-4", + "-H", "$address$", + "-w", "$wrta$,$wpl$%", + "-c", "$crta$,$cpl$%", + "-p", "$packets$", + "-t", "$timeout$" + }, macros = { wrta = 100, @@ -33,7 +41,15 @@ abstract object Service "ping4" inherits "plugin-service" { } abstract object Service "ping6" inherits "plugin-service" { - check_command = "$plugindir$/check_ping -6 -H $address6$ -w $wrta$,$wpl$% -c $crta$,$cpl$%a -p $packets$ -t $timeout$", + check_command = { + "$plugindir$/check_ping", + "-6", + "-H", "$address6$", + "-w", "$wrta$,$wpl$%", + "-c", "$crta$,$cpl$%", + "-p", "$packets$", + "-t", "$timeout$" + }, macros = { wrta = 100, @@ -48,7 +64,11 @@ abstract object Service "ping6" inherits "plugin-service" { } abstract object Service "dummy" inherits "plugin-service" { - check_command = "$plugindir$/check_dummy $state$ '$text$'", + check_command = { + "$plugindir$/check_dummy", + "$state$", + "$text$" + }, macros = { state = 0, @@ -57,19 +77,32 @@ abstract object Service "dummy" inherits "plugin-service" { } abstract object Service "http_vhost" inherits "plugin-service" { - check_command = "$plugindir$/check_http -H $vhost$" + check_command = { + "$plugindir$/check_http", + "-H", "$vhost$" + }, } abstract object Service "http_ip" inherits "plugin-service" { - check_command = "$plugindir$/check_http -I $address$" + check_command = { + "$plugindir$/check_http", + "-I", "$address$" + } } abstract object Service "ssh" inherits "plugin-service" { - check_command = "$plugindir$/check_ssh $address$" + check_command = { + "$plugindir$/check_ssh", + "$address$" + } } abstract object Service "disk" inherits "plugin-service" { - check_command = "$plugindir$/check_disk -w '$wfree$' -c '$cfree$'", + check_command = { + "$plugindir$/check_disk", + "-w", "$wfree$", + "-c", "$cfree$" + }, macros += { wfree = "20%", @@ -78,7 +111,11 @@ abstract object Service "disk" inherits "plugin-service" { } abstract object Service "users" inherits "plugin-service" { - check_command = "$plugindir$/check_users -w '$wgreater$' -c '$cgreater$'", + check_command = { + "$plugindir$/check_users", + "-w", "$wgreater$", + "-c", "$cgreater$" + }, macros += { wgreater = 20, @@ -87,7 +124,11 @@ abstract object Service "users" inherits "plugin-service" { } abstract object Service "processes" inherits "plugin-service" { - check_command = "$plugindir$/check_procs -w '$wgreater$' -c '$cgreater$'", + check_command = { + "$plugindir$/check_procs", + "-w", "$wgreater$", + "-c", "$cgreater$" + }, macros += { wgreater = 250, @@ -97,7 +138,11 @@ abstract object Service "processes" inherits "plugin-service" { abstract object Service "load" inherits "plugin-service" { - check_command = "$plugindir$/check_load -w $wload1$,$wload5$,$wload15$ -c $cload1$,$cload5$,$cload15$", + check_command = { + "$plugindir$/check_load", + "-w", "$wload1$,$wload5$,$wload15$", + "-c", "$cload1$,$cload5$,$cload15$" + }, macros = { wload1 = 5.0, diff --git a/itl/types.conf b/itl/types.conf index e77f4c462..8f71747e3 100644 --- a/itl/types.conf +++ b/itl/types.conf @@ -74,6 +74,8 @@ type Host { %attribute dictionary "*" { %attribute string "service", + %attribute string "short_name", + %attribute dictionary "macros" { %attribute string "*" }, diff --git a/lib/base/process.cpp b/lib/base/process.cpp index f49a05cfb..229a4d7d5 100644 --- a/lib/base/process.cpp +++ b/lib/base/process.cpp @@ -41,10 +41,21 @@ Process::Process(const vector& arguments, const Dictionary::Ptr& extraEn #endif /* _WIN32 */ } -vector Process::ParseCommand(const String& command) +vector Process::SplitCommand(const Value& command) { - // TODO: implement vector args; + + if (command.IsObjectType()) { + Dictionary::Ptr dict = command; + Value arg; + BOOST_FOREACH(tie(tuples::ignore, arg), dict) { + args.push_back(arg); + } + + return args; + } + + // TODO: implement #ifdef _WIN32 args.push_back(command); #else /* _WIN32 */ diff --git a/lib/base/process.h b/lib/base/process.h index f2805bce0..2a14c16fc 100644 --- a/lib/base/process.h +++ b/lib/base/process.h @@ -52,7 +52,7 @@ public: Process(const vector& arguments, const Dictionary::Ptr& extraEnvironment = Dictionary::Ptr()); - static vector ParseCommand(const String& command); + static vector SplitCommand(const Value& command); private: static bool m_WorkersCreated; diff --git a/lib/icinga/macroprocessor.cpp b/lib/icinga/macroprocessor.cpp index 391ff2485..8e45be9a0 100644 --- a/lib/icinga/macroprocessor.cpp +++ b/lib/icinga/macroprocessor.cpp @@ -21,7 +21,28 @@ using namespace icinga; -String MacroProcessor::ResolveMacros(const String& str, const vector& macroDicts) +Value MacroProcessor::ResolveMacros(const Value& cmd, const Dictionary::Ptr& macros) +{ + Value result; + + if (cmd.IsScalar()) { + result = InternalResolveMacros(cmd, macros); + } else { + Dictionary::Ptr resultDict = boost::make_shared(); + Dictionary::Ptr dict = cmd; + + Value arg; + BOOST_FOREACH(tie(tuples::ignore, arg), dict) { + resultDict->Add(InternalResolveMacros(arg, macros)); + } + + result = resultDict; + } + + return result; +} + +String MacroProcessor::InternalResolveMacros(const String& str, const Dictionary::Ptr& macros) { size_t offset, pos_first, pos_second; @@ -35,29 +56,19 @@ String MacroProcessor::ResolveMacros(const String& str, const vectorContains(name)) - continue; - String value = macroDict->Get(name); - result.Replace(pos_first, pos_second - pos_first + 1, value); - offset = pos_first + value.GetLength(); - - resolved = true; - break; - } - - if (!resolved) + if (!macros || !macros->Contains(name)) BOOST_THROW_EXCEPTION(runtime_error("Macro '" + name + "' is not defined.")); + + String value = macros->Get(name); + result.Replace(pos_first, pos_second - pos_first + 1, value); + offset = pos_first + value.GetLength(); } return result; } -Dictionary::Ptr MacroProcessor::MakeEnvironment(const vector& dicts) +Dictionary::Ptr MacroProcessor::MergeMacroDicts(const vector& dicts) { Dictionary::Ptr result = boost::make_shared(); diff --git a/lib/icinga/macroprocessor.h b/lib/icinga/macroprocessor.h index 41fccad14..7b11f4244 100644 --- a/lib/icinga/macroprocessor.h +++ b/lib/icinga/macroprocessor.h @@ -31,8 +31,11 @@ namespace icinga class I2_ICINGA_API MacroProcessor { public: - static String ResolveMacros(const String& str, const vector& macroDicts); - static Dictionary::Ptr MakeEnvironment(const vector& macroDicts); + static Value ResolveMacros(const Value& str, const Dictionary::Ptr& macros); + static Dictionary::Ptr MergeMacroDicts(const vector& macroDicts); + +private: + static String InternalResolveMacros(const String& str, const Dictionary::Ptr& macros); }; } diff --git a/lib/icinga/notification.cpp b/lib/icinga/notification.cpp index 046d8c066..685b0b3ce 100644 --- a/lib/icinga/notification.cpp +++ b/lib/icinga/notification.cpp @@ -60,7 +60,7 @@ Service::Ptr Notification::GetService(void) const return host->GetServiceByShortName(service); } -String Notification::GetNotificationCommand(void) const +Value Notification::GetNotificationCommand(void) const { return Get("notification_command"); } diff --git a/lib/icinga/notification.h b/lib/icinga/notification.h index ae6071836..ef5e82dbf 100644 --- a/lib/icinga/notification.h +++ b/lib/icinga/notification.h @@ -57,7 +57,7 @@ public: static Notification::Ptr GetByName(const String& name); shared_ptr GetService(void) const; - String GetNotificationCommand(void) const; + Value GetNotificationCommand(void) const; Dictionary::Ptr GetMacros(void) const; void SendNotification(NotificationType type); diff --git a/lib/icinga/pluginchecktask.cpp b/lib/icinga/pluginchecktask.cpp index a5a977c0e..62ed38d15 100644 --- a/lib/icinga/pluginchecktask.cpp +++ b/lib/icinga/pluginchecktask.cpp @@ -38,17 +38,17 @@ void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vectorGetCheckCommand(); - vector macroDicts; macroDicts.push_back(service->GetMacros()); macroDicts.push_back(service->CalculateDynamicMacros()); macroDicts.push_back(service->GetHost()->GetMacros()); macroDicts.push_back(service->GetHost()->CalculateDynamicMacros()); macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros()); - String command = MacroProcessor::ResolveMacros(checkCommand, macroDicts); + Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts); + + Value command = MacroProcessor::ResolveMacros(service->GetCheckCommand(), macros); - Process::Ptr process = boost::make_shared(Process::ParseCommand(command), MacroProcessor::MakeEnvironment(macroDicts)); + Process::Ptr process = boost::make_shared(Process::SplitCommand(command), macros); PluginCheckTask ct(task, process); diff --git a/lib/icinga/pluginnotificationtask.cpp b/lib/icinga/pluginnotificationtask.cpp index 90f0b3641..a66a98289 100644 --- a/lib/icinga/pluginnotificationtask.cpp +++ b/lib/icinga/pluginnotificationtask.cpp @@ -42,8 +42,6 @@ void PluginNotificationTask::ScriptFunc(const ScriptTask::Ptr& task, const vecto Notification::Ptr notification = arguments[0]; NotificationType type = static_cast(static_cast(arguments[1])); - String notificationCommand = notification->GetNotificationCommand(); - vector macroDicts; macroDicts.push_back(notification->GetMacros()); macroDicts.push_back(notification->GetService()->GetMacros()); @@ -51,9 +49,11 @@ void PluginNotificationTask::ScriptFunc(const ScriptTask::Ptr& task, const vecto macroDicts.push_back(notification->GetService()->GetHost()->GetMacros()); macroDicts.push_back(notification->GetService()->GetHost()->CalculateDynamicMacros()); macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros()); - String command = MacroProcessor::ResolveMacros(notificationCommand, macroDicts); + Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts); + + Value command = MacroProcessor::ResolveMacros(notification->GetNotificationCommand(), macros); - Process::Ptr process = boost::make_shared(Process::ParseCommand(command), MacroProcessor::MakeEnvironment(macroDicts)); + Process::Ptr process = boost::make_shared(Process::SplitCommand(command), macros); PluginNotificationTask ct(task, process, notification->GetService()->GetName(), command); diff --git a/lib/icinga/service-check.cpp b/lib/icinga/service-check.cpp index b702040fe..b9cc4cd47 100644 --- a/lib/icinga/service-check.cpp +++ b/lib/icinga/service-check.cpp @@ -28,7 +28,7 @@ const int Service::CheckIntervalDivisor = 5; boost::signal Service::OnCheckerChanged; boost::signal Service::OnNextCheckChanged; -String Service::GetCheckCommand(void) const +Value Service::GetCheckCommand(void) const { return Get("check_command"); } diff --git a/lib/icinga/service.h b/lib/icinga/service.h index 88796d3ce..9d1c18f91 100644 --- a/lib/icinga/service.h +++ b/lib/icinga/service.h @@ -118,7 +118,7 @@ public: /* Checks */ Dictionary::Ptr GetCheckers(void) const; - String GetCheckCommand(void) const; + Value GetCheckCommand(void) const; long GetMaxCheckAttempts(void) const; double GetCheckInterval(void) const; double GetRetryInterval(void) const; -- 2.49.0