if (!host)
return Empty;
- std::vector<MacroResolver::Ptr> resolvers;
-
- resolvers.push_back(host);
- resolvers.push_back(IcingaApplication::GetInstance());
+ MacroProcessor::ResolverList resolvers;
+ resolvers.push_back(std::make_pair("host", host));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value value = CompatUtility::GetCustomAttributeConfig(host, "notes");
if (!host)
return Empty;
- std::vector<MacroResolver::Ptr> resolvers;
-
- resolvers.push_back(host);
- resolvers.push_back(IcingaApplication::GetInstance());
+ MacroProcessor::ResolverList resolvers;
+ resolvers.push_back(std::make_pair("host", host));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value value = CompatUtility::GetCustomAttributeConfig(host, "notes_url");
if (!host)
return Empty;
- std::vector<MacroResolver::Ptr> resolvers;
-
- resolvers.push_back(host);
- resolvers.push_back(IcingaApplication::GetInstance());
+ MacroProcessor::ResolverList resolvers;
+ resolvers.push_back(std::make_pair("host", host));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value value = CompatUtility::GetCustomAttributeConfig(host, "action_url");
if (!host)
return Empty;
- std::vector<MacroResolver::Ptr> resolvers;
-
- resolvers.push_back(host);
- resolvers.push_back(IcingaApplication::GetInstance());
+ MacroProcessor::ResolverList resolvers;
+ resolvers.push_back(std::make_pair("host", host));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value value = CompatUtility::GetCustomAttributeConfig(host, "icon_image");
if (!service)
return Empty;
- std::vector<MacroResolver::Ptr> resolvers;
- resolvers.push_back(service);
- resolvers.push_back(service->GetHost());
- resolvers.push_back(IcingaApplication::GetInstance());
+ MacroProcessor::ResolverList resolvers;
+ resolvers.push_back(std::make_pair("service", service));
+ resolvers.push_back(std::make_pair("host", service->GetHost()));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value value = CompatUtility::GetCustomAttributeConfig(service, "notes");
if (!service)
return Empty;
- std::vector<MacroResolver::Ptr> resolvers;
- resolvers.push_back(service);
- resolvers.push_back(service->GetHost());
- resolvers.push_back(IcingaApplication::GetInstance());
+ MacroProcessor::ResolverList resolvers;
+ resolvers.push_back(std::make_pair("service", service));
+ resolvers.push_back(std::make_pair("host", service->GetHost()));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value value = CompatUtility::GetCustomAttributeConfig(service, "notes_url");
if (!service)
return Empty;
- std::vector<MacroResolver::Ptr> resolvers;
- resolvers.push_back(service);
- resolvers.push_back(service->GetHost());
- resolvers.push_back(IcingaApplication::GetInstance());
+ MacroProcessor::ResolverList resolvers;
+ resolvers.push_back(std::make_pair("service", service));
+ resolvers.push_back(std::make_pair("host", service->GetHost()));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value value = CompatUtility::GetCustomAttributeConfig(service, "action_url");
if (!service)
return Empty;
- std::vector<MacroResolver::Ptr> resolvers;
- resolvers.push_back(service);
- resolvers.push_back(service->GetHost());
- resolvers.push_back(IcingaApplication::GetInstance());
+ MacroProcessor::ResolverList resolvers;
+ resolvers.push_back(std::make_pair("service", service));
+ resolvers.push_back(std::make_pair("host", service->GetHost()));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value value = CompatUtility::GetCustomAttributeConfig(service, "icon_image");
else
host = static_pointer_cast<Host>(checkable);
- std::vector<MacroResolver::Ptr> resolvers;
+ MacroProcessor::ResolverList resolvers;
if (service)
- resolvers.push_back(service);
- resolvers.push_back(host);
- resolvers.push_back(IcingaApplication::GetInstance());
+ resolvers.push_back(std::make_pair("service", service));
+ resolvers.push_back(std::make_pair("host", host));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
if (service) {
String line = MacroProcessor::ResolveMacros(GetServiceFormatTemplate(), resolvers, cr);
"TIMET::$icinga.timet$\t"
"HOSTNAME::$host.name$\t"
"HOSTPERFDATA::$host.perfdata$\t"
- "HOSTCHECKCOMMAND::$host.checkcommand$\t"
+ "HOSTCHECKCOMMAND::$host.check_command$\t"
"HOSTSTATE::$host.state$\t"
- "HOSTSTATETYPE::$host.statetype$";
+ "HOSTSTATETYPE::$host.state_type$";
}}}
};
[config] String service_format_template {
return "DATATYPE::SERVICEPERFDATA\t"
"TIMET::$icinga.timet$\t"
"HOSTNAME::$host.name$\t"
- "SERVICEDESC::$service.description$\t"
+ "SERVICEDESC::$service.name$\t"
"SERVICEPERFDATA::$service.perfdata$\t"
- "SERVICECHECKCOMMAND::$service.checkcommand$\t"
+ "SERVICECHECKCOMMAND::$service.check_command$\t"
"HOSTSTATE::$host.state$\t"
- "HOSTSTATETYPE::$host.statetype$\t"
+ "HOSTSTATETYPE::$host.state_type$\t"
"SERVICESTATE::$service.state$\t"
- "SERVICESTATETYPE::$service.statetype$";
+ "SERVICESTATETYPE::$service.state_type$";
}}}
};
The following host custom attributes are available in all commands that are executed for
hosts or services:
- Name | Description
- ---------------------------|--------------
- host.name | The name of the host object.
- host.displayname | The value of the `display_name` attribute.
- host.state | The host's current state. Can be one of `UNREACHABLE`, `UP` and `DOWN`.
- host.stateid | The host's current state. Can be one of `0` (up), `1` (down) and `2` (unreachable).
- host.statetype | The host's current state type. Can be one of `SOFT` and `HARD`.
- host.attempt | The current check attempt number.
- host.maxattempt | The maximum number of checks which are executed before changing to a hard state.
- host.laststate | The host's previous state. Can be one of `UNREACHABLE`, `UP` and `DOWN`.
- host.laststateid | The host's previous state. Can be one of `0` (up), `1` (down) and `2` (unreachable).
- host.laststatetype | The host's previous state type. Can be one of `SOFT` and `HARD`.
- host.laststatechange | The last state change's timestamp.
- host.durationsec | The time since the last state change.
- host.latency | The host's check latency.
- host.executiontime | The host's check execution time.
- host.output | The last check's output.
- host.perfdata | The last check's performance data.
- host.lastcheck | The timestamp when the last check was executed.
- host.totalservices | Number of services associated with the host.
- host.totalservicesok | Number of services associated with the host which are in an `OK` state.
- host.totalserviceswarning | Number of services associated with the host which are in a `WARNING` state.
- host.totalservicesunknown | Number of services associated with the host which are in an `UNKNOWN` state.
- host.totalservicescritical | Number of services associated with the host which are in a `CRITICAL` state.
+ Name | Description
+ -----------------------------|--------------
+ host.name | The name of the host object.
+ host.display_name | The value of the `display_name` attribute.
+ host.state | The host's current state. Can be one of `UNREACHABLE`, `UP` and `DOWN`.
+ host.stateid | The host's current state. Can be one of `0` (up), `1` (down) and `2` (unreachable).
+ host.statetype | The host's current state type. Can be one of `SOFT` and `HARD`.
+ host.check_attempt | The current check attempt number.
+ host.max_check_attempts | The maximum number of checks which are executed before changing to a hard state.
+ host.last_state | The host's previous state. Can be one of `UNREACHABLE`, `UP` and `DOWN`.
+ host.last_state_id | The host's previous state. Can be one of `0` (up), `1` (down) and `2` (unreachable).
+ host.last_state_type | The host's previous state type. Can be one of `SOFT` and `HARD`.
+ host.last_state_change | The last state change's timestamp.
+ host.duration_sec | The time since the last state change.
+ host.latency | The host's check latency.
+ host.execution_time | The host's check execution time.
+ host.output | The last check's output.
+ host.perfdata | The last check's performance data.
+ host.last_check | The timestamp when the last check was executed.
+ host.total_services | Number of services associated with the host.
+ host.total_services_ok | Number of services associated with the host which are in an `OK` state.
+ host.total_services_warning | Number of services associated with the host which are in a `WARNING` state.
+ host.total_services_unknown | Number of services associated with the host which are in an `UNKNOWN` state.
+ host.total_services_critical | Number of services associated with the host which are in a `CRITICAL` state.
### <a id="service-runtime-macros"></a> Service Runtime Macros
The following service macros are available in all commands that are executed for
services:
- Name | Description
- ------------------------|--------------
- service.description | The short name of the service object.
- service.displayname | The value of the `display_name` attribute.
- service.checkcommand | This is an alias for the `SERVICEDISPLAYNAME` macro.
- service.state | The service's current state. Can be one of `OK`, `WARNING`, `CRITICAL` and `UNKNOWN`.
- service.stateid | The service's current state. Can be one of `0` (ok), `1` (warning), `2` (critical) and `3` (unknown).
- service.statetype | The service's current state type. Can be one of `SOFT` and `HARD`.
- service.attempt | The current check attempt number.
- service.maxattempt | The maximum number of checks which are executed before changing to a hard state.
- service.laststate | The service's previous state. Can be one of `OK`, `WARNING`, `CRITICAL` and `UNKNOWN`.
- service.laststateid | The service's previous state. Can be one of `0` (ok), `1` (warning), `2` (critical) and `3` (unknown).
- service.laststatetype | The service's previous state type. Can be one of `SOFT` and `HARD`.
- service.laststatechange | The last state change's timestamp.
- service.durationsec | The time since the last state change.
- service.latency | The service's check latency.
- service.executiontime | The service's check execution time.
- service.output | The last check's output.
- service.perfdata | The last check's performance data.
- service.lastcheck | The timestamp when the last check was executed.
+ Name | Description
+ ---------------------------|--------------
+ service.name | The short name of the service object.
+ service.display_name | The value of the `display_name` attribute.
+ service.check_command | This is an alias for the `SERVICEDISPLAYNAME` macro.
+ service.state | The service's current state. Can be one of `OK`, `WARNING`, `CRITICAL` and `UNKNOWN`.
+ service.state_id | The service's current state. Can be one of `0` (ok), `1` (warning), `2` (critical) and `3` (unknown).
+ service.state_type | The service's current state type. Can be one of `SOFT` and `HARD`.
+ service.check_attempt | The current check attempt number.
+ service.max_check_attempts | The maximum number of checks which are executed before changing to a hard state.
+ service.last_state | The service's previous state. Can be one of `OK`, `WARNING`, `CRITICAL` and `UNKNOWN`.
+ service.last_state_id | The service's previous state. Can be one of `0` (ok), `1` (warning), `2` (critical) and `3` (unknown).
+ service.last_state_type | The service's previous state type. Can be one of `SOFT` and `HARD`.
+ service.last_state_change | The last state change's timestamp.
+ service.duration_sec | The time since the last state change.
+ service.latency | The service's check latency.
+ service.execution_time | The service's check execution time.
+ service.output | The last check's output.
+ service.perfdata | The last check's performance data.
+ service.last_check | The timestamp when the last check was executed.
+
+### <a id="command-runtime-macros"></a> Command Runtime Macros
+
+The following custom attributes are available in all commands:
+
+ Name | Description
+ -----------------------|--------------
+ command.name | The name of the command object.
### <a id="user-runtime-macros"></a> User Runtime Macros
Name | Description
-----------------------|--------------
user.name | The name of the user object.
- user.displayname | The value of the display_name attribute.
-
+ user.display_name | The value of the display_name attribute.
### <a id="notification-runtime-macros"></a> Notification Runtime Macros
Name | Description
-----------------------|--------------
icinga.timet | Current UNIX timestamp.
- icinga.longdatetime | Current date and time including timezone information. Example: `2014-01-03 11:23:08 +0000`
- icinga.shortdatetime | Current date and time. Example: `2014-01-03 11:23:08`
+ icinga.long_date_time | Current date and time including timezone information. Example: `2014-01-03 11:23:08 +0000`
+ icinga.short_date_time | Current date and time. Example: `2014-01-03 11:23:08`
icinga.date | Current date. Example: `2014-01-03`
icinga.time | Current time including timezone information. Example: `11:23:08 +0000`
object Host "localhost" {
import "linux-server"
- vars.address = "127.0.0.1"
- vars.address6 = "::1"
+ address = "127.0.0.1"
+ address6 = "::1"
}
object Service "icinga" {
default {{{ return true; }}}
};
+ [config] String notes;
+ [config] String notes_url;
+ [config] String action_url;
+ [config] String icon_image;
+ [config] String icon_image_alt;
+
[state] double next_check (NextCheckRaw);
[state] int check_attempt {
default {{{ return 1; }}}
bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
{
- String key;
- Dictionary::Ptr vars;
-
- /* special treatment for address macros providing name fallback */
- if (macro == "address" || macro == "address6") {
- vars = GetVars();
-
- String value;
- if (vars && vars->Contains(macro))
- value = vars->Get(macro);
-
- if (value.IsEmpty()) {
- *result = GetName();
- return true;
- } else {
- *result = value;
- return true;
- }
- }
- else if (macro == "host.vars.address" || macro == "host.vars.address6") {
- key = macro.SubStr(10);
- vars = GetVars();
-
- String value;
- if (vars && vars->Contains(key))
- value = vars->Get(key);
+ if (macro == "state") {
+ *result = StateToString(GetState());
+ return true;
+ } else if (macro == "state_id") {
+ *result = Convert::ToString(GetState());
+ return true;
+ } else if (macro == "state_type") {
+ *result = StateTypeToString(GetStateType());
+ return true;
+ } else if (macro == "last_state") {
+ *result = StateToString(GetLastState());
+ return true;
+ } else if (macro == "last_state_id") {
+ *result = Convert::ToString(GetLastState());
+ return true;
+ } else if (macro == "last_state_type") {
+ *result = StateTypeToString(GetLastStateType());
+ return true;
+ } else if (macro == "last_state_change") {
+ *result = Convert::ToString((long)GetLastStateChange());
+ return true;
+ } else if (macro == "duration_sec") {
+ *result = Convert::ToString((long)(Utility::GetTime() - GetLastStateChange()));
+ return true;
+ } else if (macro == "total_services" || macro == "total_services_ok" || macro == "total_services_warning"
+ || macro == "total_services_unknown" || macro == "total_services_critical") {
+ int filter = -1;
+ int count = 0;
+
+ if (macro == "total_services_ok")
+ filter = ServiceOK;
+ else if (macro == "total_services_warning")
+ filter = ServiceWarning;
+ else if (macro == "total_services_unknown")
+ filter = ServiceUnknown;
+ else if (macro == "total_services_critical")
+ filter = ServiceCritical;
+
+ BOOST_FOREACH(const Service::Ptr& service, GetServices()) {
+ if (filter != -1 && service->GetState() != filter)
+ continue;
+
+ count++;
+ }
- if (value.IsEmpty()) {
- *result = GetName();
+ *result = Convert::ToString(count);
return true;
- } else {
- *result = value;
- return true;
- }
}
- /* require prefix for object macros */
- if (macro.SubStr(0, 5) == "host.") {
- key = macro.SubStr(5);
-
- if (key.SubStr(0, 5) == "vars.") {
- vars = GetVars();
- String vars_key = key.SubStr(5);
-
- if (vars && vars->Contains(vars_key)) {
- *result = vars->Get(vars_key);
- return true;
- }
- }
- else if (key == "name") {
- *result = GetName();
- return true;
- }
- else if (key == "displaymane") {
- *result = GetDisplayName();
- return true;
- }
-
- CheckResult::Ptr cr = GetLastCheckResult();
+ CheckResult::Ptr cr = GetLastCheckResult();
- if (key == "state") {
- *result = StateToString(GetState());
- return true;
- } else if (key == "stateid") {
- *result = Convert::ToString(GetState());
- return true;
- } else if (key == "statetype") {
- *result = StateTypeToString(GetStateType());
- return true;
- } else if (key == "attempt") {
- *result = Convert::ToString(GetCheckAttempt());
- return true;
- } else if (key == "maxattempt") {
- *result = Convert::ToString(GetMaxCheckAttempts());
- return true;
- } else if (key == "laststate") {
- *result = StateToString(GetLastState());
- return true;
- } else if (key == "laststateid") {
- *result = Convert::ToString(GetLastState());
- return true;
- } else if (key == "laststatetype") {
- *result = StateTypeToString(GetLastStateType());
+ if (cr) {
+ if (macro == "latency") {
+ *result = Convert::ToString(Service::CalculateLatency(cr));
return true;
- } else if (key == "laststatechange") {
- *result = Convert::ToString((long)GetLastStateChange());
+ } else if (macro == "execution_time") {
+ *result = Convert::ToString(Service::CalculateExecutionTime(cr));
return true;
- } else if (key == "durationsec") {
- *result = Convert::ToString((long)(Utility::GetTime() - GetLastStateChange()));
+ } else if (macro == "output") {
+ *result = cr->GetOutput();
return true;
- } else if (key == "checkcommand") {
- CheckCommand::Ptr commandObj = GetCheckCommand();
-
- if (commandObj)
- *result = commandObj->GetName();
- else
- *result = "";
-
+ } else if (macro == "perfdata") {
+ *result = PluginUtility::FormatPerfdata(cr->GetPerformanceData());
return true;
- } else if (key == "totalservices" || key == "totalservicesok" || key == "totalserviceswarning"
- || key == "totalservicesunknown" || key == "totalservicescritical") {
- int filter = -1;
- int count = 0;
-
- if (key == "totalservicesok")
- filter = ServiceOK;
- else if (key == "totalserviceswarning")
- filter = ServiceWarning;
- else if (key == "totalservicesunknown")
- filter = ServiceUnknown;
- else if (key == "totalservicescritical")
- filter = ServiceCritical;
-
- BOOST_FOREACH(const Service::Ptr& service, GetServices()) {
- if (filter != -1 && service->GetState() != filter)
- continue;
-
- count++;
- }
-
- *result = Convert::ToString(count);
- return true;
- }
-
-
- if (cr) {
- if (key == "latency") {
- *result = Convert::ToString(Service::CalculateLatency(cr));
- return true;
- } else if (key == "executiontime") {
- *result = Convert::ToString(Service::CalculateExecutionTime(cr));
- return true;
- } else if (key == "output") {
- *result = cr->GetOutput();
- return true;
- } else if (key == "perfdata") {
- *result = PluginUtility::FormatPerfdata(cr->GetPerformanceData());
- return true;
- } else if (key == "lastcheck") {
- *result = Convert::ToString((long)cr->GetScheduleStart());
- return true;
- }
- }
- } else {
- vars = GetVars();
-
- if (vars && vars->Contains(macro)) {
- *result = vars->Get(macro);
+ } else if (macro == "last_check") {
+ *result = Convert::ToString((long)cr->GetScheduleStart());
return true;
}
}
}}}
};
[config] Array::Ptr groups;
+
+ [config] String address;
+ [config] String address6;
};
}
%attribute %array "authorities" {
%attribute %name(Endpoint) "*"
},
+
+ %attribute %string "notes",
+ %attribute %string "notes_url",
+ %attribute %string "action_url",
+ %attribute %string "icon_image",
+ %attribute %string "icon_image_alt",
}
%type Host %inherits Checkable {
%attribute %array "groups" {
%attribute %name(HostGroup) "*"
},
+
+ %attribute %string "address",
+ %attribute %string "address6",
}
%type HostGroup {
%attribute %array "notification_state_filter" {
%attribute %number "*"
},
- %attribute %name(TimePeriod) "notification_period"
+ %attribute %name(TimePeriod) "notification_period",
+
+ %attribute %string "email",
+ %attribute %string "pager",
}
%type UserGroup {
bool IcingaApplication::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
{
- /* require icinga prefix for application macros */
- if (macro.SubStr(0, 7) == "icinga.") {
- String key = macro.SubStr(7);
-
- double now = Utility::GetTime();
-
- if (key == "timet") {
- *result = Convert::ToString((long)now);
- return true;
- } else if (key == "longdatetime") {
- *result = Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", now);
- return true;
- } else if (key == "shortdatetime") {
- *result = Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", now);
- return true;
- } else if (key == "date") {
- *result = Utility::FormatDateTime("%Y-%m-%d", now);
- return true;
- } else if (key == "time") {
- *result = Utility::FormatDateTime("%H:%M:%S %z", now);
- return true;
- }
+ double now = Utility::GetTime();
+ if (macro == "timet") {
+ *result = Convert::ToString((long)now);
+ return true;
+ } else if (macro == "long_date_time") {
+ *result = Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", now);
+ return true;
+ } else if (macro == "short_date_time") {
+ *result = Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", now);
+ return true;
+ } else if (macro == "date") {
+ *result = Utility::FormatDateTime("%Y-%m-%d", now);
+ return true;
+ } else if (macro == "time") {
+ *result = Utility::FormatDateTime("%H:%M:%S %z", now);
+ return true;
}
Dictionary::Ptr vars = GetVars();
#include "base/objectlock.h"
#include "base/logger_fwd.h"
#include "base/context.h"
+#include "base/dynamicobject.h"
#include <boost/foreach.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/join.hpp>
+#include <boost/algorithm/string/classification.hpp>
using namespace icinga;
-Value MacroProcessor::ResolveMacros(const Value& str, const std::vector<MacroResolver::Ptr>& resolvers,
+Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolvers,
const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn)
{
Value result;
return result;
}
-bool MacroProcessor::ResolveMacro(const String& macro, const std::vector<MacroResolver::Ptr>& resolvers,
+bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resolvers,
const CheckResult::Ptr& cr, String *result)
{
CONTEXT("Resolving macro '" + macro + "'");
- BOOST_FOREACH(const MacroResolver::Ptr& resolver, resolvers) {
- if (resolver->ResolveMacro(macro, cr, result))
+ std::vector<String> tokens;
+ boost::algorithm::split(tokens, macro, boost::is_any_of("."));
+
+ String objName;
+ if (tokens.size() > 1) {
+ objName = tokens[0];
+ tokens.erase(tokens.begin());
+ }
+
+ BOOST_FOREACH(const ResolverSpec& resolver, resolvers) {
+ if (!objName.IsEmpty() && objName != resolver.first)
+ continue;
+
+ if (objName.IsEmpty()) {
+ DynamicObject::Ptr dobj = dynamic_pointer_cast<DynamicObject>(resolver.second);
+
+ if (dobj) {
+ Dictionary::Ptr vars = dobj->GetVars();
+
+ if (vars && vars->Contains(macro)) {
+ *result = vars->Get(macro);
+ return true;
+ }
+ }
+ }
+
+ MacroResolver::Ptr mresolver = dynamic_pointer_cast<MacroResolver>(resolver.second);
+
+ if (mresolver && mresolver->ResolveMacro(boost::algorithm::join(tokens, "."), cr, result))
return true;
+
+ Value ref = resolver.second;
+ bool valid = true;
+
+ BOOST_FOREACH(const String& token, tokens) {
+ if (ref.IsObjectType<Dictionary>()) {
+ Dictionary::Ptr dict = ref;
+ if (dict->Contains(token)) {
+ ref = dict->Get(token);
+ continue;
+ } else {
+ valid = false;
+ break;
+ }
+ } else if (ref.IsObject()) {
+ Object::Ptr object = ref;
+
+ const Type *type = object->GetReflectionType();
+
+ if (!type) {
+ valid = false;
+ break;
+ }
+
+ int field = type->GetFieldId(token);
+
+ if (field == -1) {
+ valid = false;
+ break;
+ }
+
+ ref = object->GetField(field);
+ }
+ }
+
+ if (valid) {
+ *result = ref;
+ return true;
+ }
}
return false;
}
-
-String MacroProcessor::InternalResolveMacros(const String& str, const std::vector<MacroResolver::Ptr>& resolvers,
- const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn)
+String MacroProcessor::InternalResolveMacros(const String& str, const ResolverList& resolvers,
+ const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn, int recursionLevel)
{
CONTEXT("Resolving macros for string '" + str + "'");
+ if (recursionLevel > 15)
+ BOOST_THROW_EXCEPTION(std::runtime_error("Infinite recursion detected while resolving macros"));
+
size_t offset, pos_first, pos_second;
offset = 0;
if (!found)
Log(LogWarning, "icinga", "Macro '" + name + "' is not defined.");
+ /* recursively resolve macros in the macro */
+ resolved_macro = InternalResolveMacros(resolved_macro, resolvers, cr, EscapeCallback(), recursionLevel + 1);
+
if (escapeFn)
resolved_macro = escapeFn(resolved_macro);
#include "base/dictionary.h"
#include "base/array.h"
#include <boost/function.hpp>
-#include <vector>
+#include <map>
namespace icinga
{
{
public:
typedef boost::function<String (const String&)> EscapeCallback;
+ typedef std::pair<String, Object::Ptr> ResolverSpec;
+ typedef std::vector<ResolverSpec> ResolverList;
- static Value ResolveMacros(const Value& str, const std::vector<MacroResolver::Ptr>& resolvers,
+ static Value ResolveMacros(const Value& str, const ResolverList& resolvers,
const CheckResult::Ptr& cr, const EscapeCallback& escapeFn = EscapeCallback());
- static bool ResolveMacro(const String& macro, const std::vector<MacroResolver::Ptr>& resolvers,
+ static bool ResolveMacro(const String& macro, const ResolverList& resolvers,
const CheckResult::Ptr& cr, String *result);
private:
MacroProcessor(void);
static String InternalResolveMacros(const String& str,
- const std::vector<MacroResolver::Ptr>& resolvers, const CheckResult::Ptr& cr,
- const EscapeCallback& escapeFn);
+ const ResolverList& resolvers, const CheckResult::Ptr& cr,
+ const EscapeCallback& escapeFn, int recursionLevel = 0);
};
}
#include "icinga/macroresolver.h"
using namespace icinga;
-
-StaticMacroResolver::StaticMacroResolver(void)
- : m_Macros(make_shared<Dictionary>())
-{ }
-
-void StaticMacroResolver::Add(const String& macro, const String& value)
-{
- m_Macros->Set(macro, value);
-}
-
-bool StaticMacroResolver::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
-{
- if (m_Macros->Contains(macro)) {
- *result = m_Macros->Get(macro);
- return true;
- }
-
- return false;
-}
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const = 0;
};
-class I2_ICINGA_API StaticMacroResolver : public Object, public MacroResolver
-{
-public:
- DECLARE_PTR_TYPEDEFS(StaticMacroResolver);
-
- StaticMacroResolver(void);
-
- void Add(const String& macro, const String& value);
-
- virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const;
-
-private:
- Dictionary::Ptr m_Macros;
-};
-
}
#endif /* MACRORESOLVER_H */
bool Service::ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const
{
- String key;
- Dictionary::Ptr vars;
-
- /* require prefix for object macros */
- if (macro.SubStr(0, 8) == "service.") {
- key = macro.SubStr(8);
-
- if (key.SubStr(0, 5) == "vars.") {
- vars = GetVars();
- String vars_key = key.SubStr(5);
-
- if (vars && vars->Contains(vars_key)) {
- *result = vars->Get(vars_key);
- return true;
- }
- } else if (key == "description") {
- *result = GetShortName();
- return true;
- } else if (key == "displayname") {
- *result = GetDisplayName();
- return true;
- } else if (key == "checkcommand") {
- CheckCommand::Ptr commandObj = GetCheckCommand();
-
- if (commandObj)
- *result = commandObj->GetName();
- else
- *result = "";
-
- return true;
- }
+ if (macro == "state") {
+ *result = StateToString(GetState());
+ return true;
+ } else if (macro == "state_id") {
+ *result = Convert::ToString(GetState());
+ return true;
+ } else if (macro == "state_type") {
+ *result = StateTypeToString(GetStateType());
+ return true;
+ } else if (macro == "last_state") {
+ *result = StateToString(GetLastState());
+ return true;
+ } else if (macro == "last_state_id") {
+ *result = Convert::ToString(GetLastState());
+ return true;
+ } else if (macro == "last_state_type") {
+ *result = StateTypeToString(GetLastStateType());
+ return true;
+ } else if (macro == "last_state_change") {
+ *result = Convert::ToString((long)GetLastStateChange());
+ return true;
+ } else if (macro == "duration_sec") {
+ *result = Convert::ToString((long)(Utility::GetTime() - GetLastStateChange()));
+ return true;
+ }
- if (key == "state") {
- *result = StateToString(GetState());
- return true;
- } else if (key == "stateid") {
- *result = Convert::ToString(GetState());
- return true;
- } else if (key == "statetype") {
- *result = StateTypeToString(GetStateType());
+ if (cr) {
+ if (macro == "latency") {
+ *result = Convert::ToString(Service::CalculateLatency(cr));
return true;
- } else if (key == "attempt") {
- *result = Convert::ToString(GetCheckAttempt());
+ } else if (macro == "execution_time") {
+ *result = Convert::ToString(Service::CalculateExecutionTime(cr));
return true;
- } else if (key == "maxattempt") {
- *result = Convert::ToString(GetMaxCheckAttempts());
+ } else if (macro == "output") {
+ *result = cr->GetOutput();
return true;
- } else if (key == "laststate") {
- *result = StateToString(GetLastState());
+ } else if (macro == "perfdata") {
+ *result = PluginUtility::FormatPerfdata(cr->GetPerformanceData());
return true;
- } else if (key == "laststateid") {
- *result = Convert::ToString(GetLastState());
- return true;
- } else if (key == "laststatetype") {
- *result = StateTypeToString(GetLastStateType());
- return true;
- } else if (key == "laststatechange") {
- *result = Convert::ToString((long)GetLastStateChange());
- return true;
- } else if (key == "durationsec") {
- *result = Convert::ToString((long)(Utility::GetTime() - GetLastStateChange()));
- return true;
- }
-
- if (cr) {
- if (key == "latency") {
- *result = Convert::ToString(Service::CalculateLatency(cr));
- return true;
- } else if (key == "executiontime") {
- *result = Convert::ToString(Service::CalculateExecutionTime(cr));
- return true;
- } else if (key == "output") {
- *result = cr->GetOutput();
- return true;
- } else if (key == "perfdata") {
- *result = PluginUtility::FormatPerfdata(cr->GetPerformanceData());
- return true;
- } else if (key == "lastcheck") {
- *result = Convert::ToString((long)cr->GetExecutionEnd());
- return true;
- }
- }
- } else {
- vars = GetVars();
-
- if (vars && vars->Contains(macro)) {
- *result = vars->Get(macro);
+ } else if (macro == "last_check") {
+ *result = Convert::ToString((long)cr->GetExecutionEnd());
return true;
}
}
location + ": Type filter is invalid.");
}
}
-
-bool User::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
-{
- String key;
- Dictionary::Ptr vars;
-
- /* require prefix for object macros */
- if (macro.SubStr(0, 5) == "user.") {
- key = macro.SubStr(5);
-
- if (key.SubStr(0, 5) == "vars.") {
- vars = GetVars();
- String vars_key = key.SubStr(5);
-
- if (vars && vars->Contains(vars_key)) {
- *result = vars->Get(vars_key);
- return true;
- }
- } else if (key == "name") {
- *result = GetName();
- return true;
- } else if (key == "displayname") {
- *result = GetDisplayName();
- return true;
- }
- } else {
- vars = GetVars();
-
- if (vars && vars->Contains(macro)) {
- *result = vars->Get(macro);
- return true;
- }
- }
-
- return false;
-}
*
* @ingroup icinga
*/
-class I2_ICINGA_API User : public ObjectImpl<User>, public MacroResolver
+class I2_ICINGA_API User : public ObjectImpl<User>
{
public:
DECLARE_PTR_TYPEDEFS(User);
/* Notifications */
TimePeriod::Ptr GetNotificationPeriod(void) const;
- virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const;
-
static void ValidateFilters(const String& location, const Dictionary::Ptr& attrs);
protected:
[config] Array::Ptr notification_type_filter (NotificationTypeFilterRaw);
int notification_type_filter_real (NotificationTypeFilter);
[config] Array::Ptr notification_state_filter (NotificationStateFilterRaw);
+
+ [config] String email;
+ [config] String pager;
+
int notification_state_filter_real (NotificationStateFilter);
[state] bool enable_notifications;
[state] double last_notification;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
- std::vector<MacroResolver::Ptr> resolvers;
+ MacroProcessor::ResolverList resolvers;
if (service)
- resolvers.push_back(service);
- resolvers.push_back(host);
- resolvers.push_back(commandObj);
- resolvers.push_back(IcingaApplication::GetInstance());
+ resolvers.push_back(std::make_pair("service", service));
+ resolvers.push_back(std::make_pair("host", host));
+ resolvers.push_back(std::make_pair("command", commandObj));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value command = MacroProcessor::ResolveMacros(raw_command, resolvers, checkable->GetLastCheckResult(), Utility::EscapeShellCmd);
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
- std::vector<MacroResolver::Ptr> resolvers;
+ MacroProcessor::ResolverList resolvers;
if (service)
- resolvers.push_back(service);
- resolvers.push_back(host);
- resolvers.push_back(commandObj);
- resolvers.push_back(IcingaApplication::GetInstance());
+ resolvers.push_back(std::make_pair("service", service));
+ resolvers.push_back(std::make_pair("host", host));
+ resolvers.push_back(std::make_pair("command", commandObj));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value command = MacroProcessor::ResolveMacros(raw_command, resolvers, checkable->GetLastCheckResult(), Utility::EscapeShellCmd);
Value raw_command = commandObj->GetCommandLine();
- StaticMacroResolver::Ptr notificationMacroResolver = make_shared<StaticMacroResolver>();
- notificationMacroResolver->Add("notification.type", Notification::NotificationTypeToString(type));
- notificationMacroResolver->Add("notification.author", author);
- notificationMacroResolver->Add("notification.comment", comment);
+ Dictionary::Ptr notificationExtra = make_shared<Dictionary>();
+ notificationExtra->Set("type", Notification::NotificationTypeToString(type));
+ notificationExtra->Set("author", author);
+ notificationExtra->Set("comment", comment);
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
- std::vector<MacroResolver::Ptr> resolvers;
- resolvers.push_back(user);
- resolvers.push_back(notificationMacroResolver);
- resolvers.push_back(notification);
+ MacroProcessor::ResolverList resolvers;
+ resolvers.push_back(std::make_pair("user", user));
+ resolvers.push_back(std::make_pair("notification", notificationExtra));
+ resolvers.push_back(std::make_pair("notification", notification));
if (service)
- resolvers.push_back(service);
- resolvers.push_back(host);;
- resolvers.push_back(commandObj);
- resolvers.push_back(IcingaApplication::GetInstance());
+ resolvers.push_back(std::make_pair("service", service));
+ resolvers.push_back(std::make_pair("host", host));
+ resolvers.push_back(std::make_pair("command", commandObj));
+ resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
Value command = MacroProcessor::ResolveMacros(raw_command, resolvers, cr, Utility::EscapeShellCmd);