Implemented dictionary support for commands.

This commit is contained in:
Gunnar Beutner 2013-02-13 20:08:09 +01:00
parent 2118e4b490
commit 1d807d91bc
12 changed files with 116 additions and 44 deletions

View File

@ -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,

View File

@ -74,6 +74,8 @@ type Host {
%attribute dictionary "*" {
%attribute string "service",
%attribute string "short_name",
%attribute dictionary "macros" {
%attribute string "*"
},

View File

@ -41,10 +41,21 @@ Process::Process(const vector<String>& arguments, const Dictionary::Ptr& extraEn
#endif /* _WIN32 */
}
vector<String> Process::ParseCommand(const String& command)
vector<String> Process::SplitCommand(const Value& command)
{
// TODO: implement
vector<String> args;
if (command.IsObjectType<Dictionary>()) {
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 */

View File

@ -52,7 +52,7 @@ public:
Process(const vector<String>& arguments, const Dictionary::Ptr& extraEnvironment = Dictionary::Ptr());
static vector<String> ParseCommand(const String& command);
static vector<String> SplitCommand(const Value& command);
private:
static bool m_WorkersCreated;

View File

@ -21,7 +21,28 @@
using namespace icinga;
String MacroProcessor::ResolveMacros(const String& str, const vector<Dictionary::Ptr>& 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>();
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 vector<Dictionary:
BOOST_THROW_EXCEPTION(runtime_error("Closing $ not found in macro format String."));
String name = result.SubStr(pos_first + 1, pos_second - pos_first - 1);
String value;
bool resolved = false;
BOOST_FOREACH(const Dictionary::Ptr& macroDict, macroDicts) {
if (!macroDict || !macroDict->Contains(name))
continue;
if (!macros || !macros->Contains(name))
BOOST_THROW_EXCEPTION(runtime_error("Macro '" + name + "' is not defined."));
String value = macroDict->Get(name);
String value = macros->Get(name);
result.Replace(pos_first, pos_second - pos_first + 1, value);
offset = pos_first + value.GetLength();
resolved = true;
break;
}
if (!resolved)
BOOST_THROW_EXCEPTION(runtime_error("Macro '" + name + "' is not defined."));
}
return result;
}
Dictionary::Ptr MacroProcessor::MakeEnvironment(const vector<Dictionary::Ptr>& dicts)
Dictionary::Ptr MacroProcessor::MergeMacroDicts(const vector<Dictionary::Ptr>& dicts)
{
Dictionary::Ptr result = boost::make_shared<Dictionary>();

View File

@ -31,8 +31,11 @@ namespace icinga
class I2_ICINGA_API MacroProcessor
{
public:
static String ResolveMacros(const String& str, const vector<Dictionary::Ptr>& macroDicts);
static Dictionary::Ptr MakeEnvironment(const vector<Dictionary::Ptr>& macroDicts);
static Value ResolveMacros(const Value& str, const Dictionary::Ptr& macros);
static Dictionary::Ptr MergeMacroDicts(const vector<Dictionary::Ptr>& macroDicts);
private:
static String InternalResolveMacros(const String& str, const Dictionary::Ptr& macros);
};
}

View File

@ -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");
}

View File

@ -57,7 +57,7 @@ public:
static Notification::Ptr GetByName(const String& name);
shared_ptr<Service> GetService(void) const;
String GetNotificationCommand(void) const;
Value GetNotificationCommand(void) const;
Dictionary::Ptr GetMacros(void) const;
void SendNotification(NotificationType type);

View File

@ -38,17 +38,17 @@ void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value
Service::Ptr service = vservice;
String checkCommand = service->GetCheckCommand();
vector<Dictionary::Ptr> 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);
Process::Ptr process = boost::make_shared<Process>(Process::ParseCommand(command), MacroProcessor::MakeEnvironment(macroDicts));
Value command = MacroProcessor::ResolveMacros(service->GetCheckCommand(), macros);
Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), macros);
PluginCheckTask ct(task, process);

View File

@ -42,8 +42,6 @@ void PluginNotificationTask::ScriptFunc(const ScriptTask::Ptr& task, const vecto
Notification::Ptr notification = arguments[0];
NotificationType type = static_cast<NotificationType>(static_cast<int>(arguments[1]));
String notificationCommand = notification->GetNotificationCommand();
vector<Dictionary::Ptr> 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);
Process::Ptr process = boost::make_shared<Process>(Process::ParseCommand(command), MacroProcessor::MakeEnvironment(macroDicts));
Value command = MacroProcessor::ResolveMacros(notification->GetNotificationCommand(), macros);
Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), macros);
PluginNotificationTask ct(task, process, notification->GetService()->GetName(), command);

View File

@ -28,7 +28,7 @@ const int Service::CheckIntervalDivisor = 5;
boost::signal<void (const Service::Ptr&, const String&)> Service::OnCheckerChanged;
boost::signal<void (const Service::Ptr&, const Value&)> Service::OnNextCheckChanged;
String Service::GetCheckCommand(void) const
Value Service::GetCheckCommand(void) const
{
return Get("check_command");
}

View File

@ -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;