Process for Macro Substitutions

Server and Client

GDMA macro substitution is done in two places:

  1. On the server, when externals are built
  2. On the client, when checks are executed

Variables

Here are all the variables that are substituted into the host-config file content, both when externals are built on the server, and when the contents of that file are interpreted on the client.

  1. When externals are built on the server:
    1. Service external macros are substituted first. For each host, all the service externals for that host are processed first and all of their service-related macro substitutions are done at that time. Listed here are macro references that may be used in service externals:
      • $SERVICEDESC$ expands to the full name of the service, as you would expect, including the appropriate instance name suffix in an instance-level external. This should be consistent with the use of this macro name throughout the rest of the system.
      • $BASESERVICEDESC$ expands to the name of the service. For a service without instances, this will be the same value as $SERVICEDESC$. For a service with instances, this will be the name of the base service, without any instance name suffix appended.
      • $INSTANCE$ expands to a simple integer which counts the number of copies of a given external as possibly multiple copies are created for service instances. This macro will generally be used within the square brackets of service-externals lines. For a base service without any service instances defined, this number will be a constant 1.
      • $INSTANCESUFFIX$ expands to the instance name suffix as defined in Monarch, but with a leading underscore (if any) elided. This makes it easier to customize the service externals definitions with a string reflecting just the critical part of the service instance name suffix, while keeping an underscore in the instance name suffix for overall readability of the full service name.
      • $ARG#$ macros ($ARG1$$ARG2$, etc.) expand to values defined in the Monarch UI at either the generic-service, host-service, or service-instance level, depending on the complexity of your setup and what inheritance options you have chosen.
      • Attempting to use these macros to best effect and to generalize service externals definitions as much as possible, the following general form is recommended: (This example is not trying to establish any convention for the ordering or use of the $ARG#$ macros. Instead, it is illustrating the intended uses of the $BASESERVICEDESC$$INSTANCE$$SERVICEDESC$, and $INSTANCESUFFIX$ macros.)

        Check_$BASESERVICEDESC$[$INSTANCE$]_Enable="ON"
        Check_$BASESERVICEDESC$[$INSTANCE$]_Service="$SERVICEDESC$"
        Check_$BASESERVICEDESC$[$INSTANCE$]_Command="check_foo -w $ARG1$ -c $ARG2$ -i $INSTANCESUFFIX$"
        Check_$BASESERVICEDESC$[$INSTANCE$]_Check_Interval="$ARG3$"

        Important Update

        What we have above, as the recommended boilerplate construction for service externals, will work cleanly for all setup cases for GDMA 2.7.0 and later. It will also work adequately when generating externals for earlier GDMA releases, for services with a _Check_Interval of "1". However, if you have earlier GDMA releases deployed, it is necessary to switch to an alternate construction if you have set the _Check_Interval in the service external to a value greater than 1 (in this example boilerplate, we assume that $ARG3$ might expand to a value other than 1) and you have multiple instances for the service:

        The alternate boilerplate form would look like:
        Check_$SERVICEDESC$[1]_Enable="ON"
        Check_$SERVICEDESC$[1]_Service="$SERVICEDESC$"
        Check_$SERVICEDESC$[1]_Command="check_foo -w $ARG1$ -c $ARG2$ -i $INSTANCESUFFIX$"
        Check_$SERVICEDESC$[1]_Check_Interval="2"

        The expanded forms could be these, assuming instance names of _first and _second for the instances of the foo service on this host in Monarch:
        Check_foo_first[1]_Enable="ON"
        Check_foo_first[1]_Service="foo_first"
        Check_foo_first[1]_Command="check_foo -w 10 -c 20 -i first"
        Check_foo_first[1]_Check_Interval="2"
        Check_foo_second[1]_Enable="ON"
        Check_foo_second[1]_Service="foo_second"
        Check_foo_second[1]_Command="check_foo -w 15 -c 25 -i second"
        Check_foo_second[1]_Check_Interval="2"

        Specifically, $BASESERVICEDESC$ gets manually changed to $SERVICEDESC$, and [$INSTANCES$] gets manually changed to [1].  GDMA itself is in this case unaware that these are multiple service instances; it just treats them as completely separate services, each with only one instance.

    2. Then, Nagios resource macros are substituted. These are $USERn$ references, as defined under Configuration > Nagios Monitoring > Control > Nagios resource macros.
    3. Next, Monarch group macros are substituted, as defined under Configuration > Nagios Monitoring > Groups > Macros (to first establish the existence of a given macro name) and then under Configuration > Nagios Monitoring > Groups > Groups > <group name> > Detail > Macros.
      • A given host can be a member of one or more Monarch groups. This membership can be either via assignment of the host to a specific Monarch group, or indirect via assignment of the host to a hostgroup, and assignment of the hostgroup to a Monarch group.
      • Typically, when a host is a member of more than one Monarch group, these Monarch groups are arranged in some kind of parent-group/sub-group tree (which can be quite complex). If the host is a member of multiple Monarch groups like that, then when the externals file for the top-parent Monarch group is created, group-macro substitutions are made in order from sub-groups to parent groups, up the chain of ancestry. This allows the sub-group macro definitions to override parent-group macro definitions, which is an important use case for having sub-groups.
      • When externals are built for a given host, they are really only built for each top-level Monarch group associated with that host; you don't get an extra externals file for each sub-group to which the host belongs.
    4. Finally, a few fixed-name macros are substituted, in order: $HOSTNAME$$HOSTADDRESS$, and $HOSTALIAS$. These values are drawn from the Monarch configuration for this host.
  2. When externals are interpreted on the client:
    1. $Plugin_Directory$ (drawn from the client's configured Poller_Plugin_Directory) and $Monitor_Host$ (the name of the host for which the check is being run) are substituted first into each plugin execution string.
    2. Option parameters are substituted into the plugin execution string, in essentially arbitrary order (you can't depend on a specific ordering of these substitutions).

Option Parameters

In addition to the documented parameters:

Check_{service}_Enable
Check_{service}_Service
Check_{service}_Command
Check_{service}_Timeout
Check_{service}_Check_Interval

which are used in service externals like these lines:

Check_gdma_linux_swap[1]_Enable="ON"
Check_gdma_linux_swap[1]_Service="linux_swap"
Check_gdma_linux_swap[1]_Command="check_swap -w 10% -c 5%"
Check_gdma_linux_swap[1]_Check_Interval="1"

you can also define any number of "Parm" parameters for a given service, in any of several forms:

Check_Disk[1]_Parm_--warning = "10%"

The value of a double-quoted parameter value is set to the string that is enclosed in quotes.

Check_Response_Servlet[1]_Parm_-n = Monitor_Server[1]
Check_This_Servlet[1]_Parm_-n = Check_Other_Servlet[1]_Parm_-n

If there are no quotes after the "=" character, the value of this parameter can be set to the value of another parameter that has already been defined. (Cross-references like this can have considerable complexity, which we are not describing in detail here.)

Check_Response_Servlet[1]_Parm_-n = Monitor_Server[1],Monitor_Server[2]

In the case just described, comma-separated multiples like this are supported.

Check_Response_Servlet[1]_Parm_-n = gw.company.com

If there are no quotes around the value, and that value does not represent some other parameter which is already defined, the value will be taken as-is.

Check_Response_Servlet[1]_Parm_-n = gw1.company.com,gw2.company.com

In the case just described, comma-separated multiples like this are supported.

Check_Disk[1]_Parm_--errors-only

If there is no "=" character in the parameter line, the parameter value is set to an empty string.

These parameters will be substituted into the plugin execution string as follows:

  1. A parameter with a name like "Parm_--ABC" will be appended to the command line as " --ABC=$value", where $value is the value of that parameter as listed above. Note that in the present GDMA code, $value will not itself be surrounded by additional quotes when it is used in the command line this way, which can be problematic (any spaces or shell metacharacters in the $value will not be protected from interpretation by the shell). If you need such protection, the $value itself should contain single-quote characters to provide such protection:

    Check_Load[1]_Parm_--message = "'A protected string.'"
  2. A parameter with a name like "Parm_-DEF" will be appended to the command line as "-DEF $value", where $value is the value of that parameter as listed above. The same issue with quoting applies here.

    It looks like there is some inconsistency in the way the present code works. You would probably want this specification:

    Check_Disk[1]_Parm_--errors-only

    to be substituted into the plugin execution string by having the string --errors-only be appended to the command line. But it looks like the present code will instead append --errors-only=; this can be considered a bug. There are probably some other boundary cases that are also not handled as well as they should be. We will need to clean up these things in a future GDMA release.

Related Resources