Merge pull request #6998 from Icinga/bugfix/doc-code-formatting

Unify documentation code formatting
This commit is contained in:
Michael Friedrich 2019-03-26 09:40:17 +01:00 committed by GitHub
commit b9b171b084
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 4570 additions and 3431 deletions

View File

@ -77,12 +77,14 @@ If you prefer to organize your own local object tree, you can also remove
Create a new configuration directory, e.g. `objects.d` and include it
in your icinga2.conf file.
[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/objects.d
```
[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/objects.d
[root@icinga2-master1.localdomain /]# vim /etc/icinga2/icinga2.conf
[root@icinga2-master1.localdomain /]# vim /etc/icinga2/icinga2.conf
/* Local object configuration on our master instance. */
include_recursive "objects.d"
/* Local object configuration on our master instance. */
include_recursive "objects.d"
```
This approach is used by the [Icinga 2 Puppet module](https://github.com/Icinga/puppet-icinga2).
@ -97,74 +99,82 @@ An example configuration file is installed for you in `/etc/icinga2/icinga2.conf
Here's a brief description of the example configuration:
/**
* Icinga 2 configuration file
* -- this is where you define settings for the Icinga application including
* which hosts/services to check.
*
* For an overview of all available configuration options please refer
* to the documentation that is distributed as part of Icinga 2.
*/
```
/**
* Icinga 2 configuration file
* -- this is where you define settings for the Icinga application including
* which hosts/services to check.
*
* For an overview of all available configuration options please refer
* to the documentation that is distributed as part of Icinga 2.
*/
```
Icinga 2 supports [C/C++-style comments](17-language-reference.md#comments).
/**
* The constants.conf defines global constants.
*/
include "constants.conf"
/**
* The constants.conf defines global constants.
*/
include "constants.conf"
The `include` directive can be used to include other files.
/**
* The zones.conf defines zones for a cluster setup.
* Not required for single instance setups.
*/
include "zones.conf"
```
/**
* The zones.conf defines zones for a cluster setup.
* Not required for single instance setups.
*/
include "zones.conf"
```
The [Icinga Template Library](10-icinga-template-library.md#icinga-template-library) provides a set of common templates
and [CheckCommand](03-monitoring-basics.md#check-commands) definitions.
/**
* The Icinga Template Library (ITL) provides a number of useful templates
* and command definitions.
* Common monitoring plugin command definitions are included separately.
*/
include <itl>
include <plugins>
include <plugins-contrib>
include <manubulon>
```
/**
* The Icinga Template Library (ITL) provides a number of useful templates
* and command definitions.
* Common monitoring plugin command definitions are included separately.
*/
include <itl>
include <plugins>
include <plugins-contrib>
include <manubulon>
/**
* This includes the Icinga 2 Windows plugins. These command definitions
* are required on a master node when a client is used as command endpoint.
*/
include <windows-plugins>
/**
* This includes the Icinga 2 Windows plugins. These command definitions
* are required on a master node when a client is used as command endpoint.
*/
include <windows-plugins>
/**
* This includes the NSClient++ check commands. These command definitions
* are required on a master node when a client is used as command endpoint.
*/
include <nscp>
/**
* This includes the NSClient++ check commands. These command definitions
* are required on a master node when a client is used as command endpoint.
*/
include <nscp>
/**
* The features-available directory contains a number of configuration
* files for features which can be enabled and disabled using the
* icinga2 feature enable / icinga2 feature disable CLI commands.
* These commands work by creating and removing symbolic links in
* the features-enabled directory.
*/
include "features-enabled/*.conf"
/**
* The features-available directory contains a number of configuration
* files for features which can be enabled and disabled using the
* icinga2 feature enable / icinga2 feature disable CLI commands.
* These commands work by creating and removing symbolic links in
* the features-enabled directory.
*/
include "features-enabled/*.conf"
```
This `include` directive takes care of including the configuration files for all
the features which have been enabled with `icinga2 feature enable`. See
[Enabling/Disabling Features](11-cli-commands.md#enable-features) for more details.
/**
* Although in theory you could define all your objects in this file
* the preferred way is to create separate directories and files in the conf.d
* directory. Each of these files must have the file extension ".conf".
*/
include_recursive "conf.d"
```
/**
* Although in theory you could define all your objects in this file
* the preferred way is to create separate directories and files in the conf.d
* directory. Each of these files must have the file extension ".conf".
*/
include_recursive "conf.d"
```
You can put your own configuration files in the [conf.d](04-configuring-icinga-2.md#conf-d) directory. This
directive makes sure that all of your own configuration files are included.
@ -184,24 +194,26 @@ cluster setup.
Example:
/* The directory which contains the plugins from the Monitoring Plugins project. */
const PluginDir = "/usr/lib64/nagios/plugins"
```
/* The directory which contains the plugins from the Monitoring Plugins project. */
const PluginDir = "/usr/lib64/nagios/plugins"
/* The directory which contains the Manubulon plugins.
* Check the documentation, chapter "SNMP Manubulon Plugin Check Commands", for details.
*/
const ManubulonPluginDir = "/usr/lib64/nagios/plugins"
/* The directory which contains the Manubulon plugins.
* Check the documentation, chapter "SNMP Manubulon Plugin Check Commands", for details.
*/
const ManubulonPluginDir = "/usr/lib64/nagios/plugins"
/* Our local instance name. By default this is the server's hostname as returned by `hostname --fqdn`.
* This should be the common name from the API certificate.
*/
//const NodeName = "localhost"
/* Our local instance name. By default this is the server's hostname as returned by `hostname --fqdn`.
* This should be the common name from the API certificate.
*/
//const NodeName = "localhost"
/* Our local zone name. */
const ZoneName = NodeName
/* Our local zone name. */
const ZoneName = NodeName
/* Secret key for remote node tickets */
const TicketSalt = ""
/* Secret key for remote node tickets */
const TicketSalt = ""
```
The `ZoneName` and `TicketSalt` constants are required for remote client
and distributed setups only.
@ -286,24 +298,25 @@ rules in [services.conf](04-configuring-icinga-2.md#services-conf) will automati
generate a new service checking the `/icingaweb2` URI using the `http`
check.
/*
* Host definitions with object attributes
* used for apply rules for Service, Notification,
* Dependency and ScheduledDowntime objects.
*
* Tip: Use `icinga2 object list --type Host` to
* list all host objects after running
* configuration validation (`icinga2 daemon -C`).
*/
```
/*
* Host definitions with object attributes
* used for apply rules for Service, Notification,
* Dependency and ScheduledDowntime objects.
*
* Tip: Use `icinga2 object list --type Host` to
* list all host objects after running
* configuration validation (`icinga2 daemon -C`).
*/
/*
/*
* This is an example host based on your
* local host's FQDN. Specify the NodeName
* constant in `constants.conf` or use your
* own description, e.g. "db-host-1".
*/
object Host NodeName {
object Host NodeName {
/* Import the default host template defined in `templates.conf`. */
import "generic-host"
@ -336,7 +349,8 @@ check.
/* The UserGroup `icingaadmins` is defined in `users.conf`. */
groups = [ "icingaadmins" ]
}
}
}
```
This is only the host object definition. Now we'll need to make sure that this
host and your additional hosts are getting [services](04-configuring-icinga-2.md#services-conf) applied.
@ -376,16 +390,18 @@ which we enabled earlier by including the `itl` and `plugins` configuration file
Example `load` service apply rule:
apply Service "load" {
import "generic-service"
```
apply Service "load" {
import "generic-service"
check_command = "load"
check_command = "load"
/* Used by the ScheduledDowntime apply rule in `downtimes.conf`. */
vars.backup_downtime = "02:00-03:00"
/* Used by the ScheduledDowntime apply rule in `downtimes.conf`. */
vars.backup_downtime = "02:00-03:00"
assign where host.name == NodeName
}
assign where host.name == NodeName
}
```
The `apply` keyword can be used to create new objects which are associated with
another group of objects. You can `import` existing templates, define (custom)
@ -403,13 +419,15 @@ may be used in `assign where` conditions.
Multiple `assign where` condition can be combined with `AND` using the `&&` operator
as shown in the `ssh` example:
apply Service "ssh" {
```
apply Service "ssh" {
import "generic-service"
check_command = "ssh"
assign where host.address && host.vars.os == "Linux"
}
}
```
In this example, the service `ssh` is applied to all hosts having the `address`
attribute defined `AND` having the custom attribute `os` set to the string
@ -429,7 +447,8 @@ The idea is simple: Your host in [hosts.conf](04-configuring-icinga-2.md#hosts-c
Remember the example from [hosts.conf](04-configuring-icinga-2.md#hosts-conf):
...
```
...
/* Define disks and attributes for service apply rules in `services.conf`. */
vars.disks["disk"] = {
/* No parameters. */
@ -437,8 +456,8 @@ Remember the example from [hosts.conf](04-configuring-icinga-2.md#hosts-conf):
vars.disks["disk /"] = {
disk_partition = "/"
}
...
...
```
This dictionary contains multiple service names we want to monitor. `disk`
should just check all available disks, while `disk /` will pass an additional
@ -466,13 +485,15 @@ generated service
Configuration example:
apply Service for (disk => config in host.vars.disks) {
```
apply Service for (disk => config in host.vars.disks) {
import "generic-service"
check_command = "disk"
vars += config
}
}
```
A similar example is used for the `http` services. That way you can make your
host the information provider for all apply rules. Define them once, and only
@ -494,19 +515,20 @@ Defines the `icingaadmin` User and the `icingaadmins` UserGroup. The latter is u
[hosts.conf](04-configuring-icinga-2.md#hosts-conf) for defining a custom host attribute later used in
[notifications.conf](04-configuring-icinga-2.md#notifications-conf) for notification apply rules.
object User "icingaadmin" {
```
object User "icingaadmin" {
import "generic-user"
display_name = "Icinga 2 Admin"
groups = [ "icingaadmins" ]
email = "icinga@localhost"
}
}
object UserGroup "icingaadmins" {
object UserGroup "icingaadmins" {
display_name = "Icinga 2 Admin Group"
}
}
```
#### notifications.conf <a id="notifications-conf"></a>
@ -527,23 +549,25 @@ By setting the `user_groups` to the value provided by the
respective [host.vars.notification.mail](04-configuring-icinga-2.md#hosts-conf) attribute we'll
implicitely use the `icingaadmins` UserGroup defined in [users.conf](04-configuring-icinga-2.md#users-conf).
apply Notification "mail-icingaadmin" to Host {
```
apply Notification "mail-icingaadmin" to Host {
import "mail-host-notification"
user_groups = host.vars.notification.mail.groups
users = host.vars.notification.mail.users
assign where host.vars.notification.mail
}
}
apply Notification "mail-icingaadmin" to Service {
apply Notification "mail-icingaadmin" to Service {
import "mail-service-notification"
user_groups = host.vars.notification.mail.groups
users = host.vars.notification.mail.users
assign where host.vars.notification.mail
}
}
```
More details on defining notifications and their additional attributes such as
filters can be read in [this chapter](03-monitoring-basics.md#alert-notifications).
@ -565,65 +589,70 @@ a member of the host group `linux-servers`.
This is done by using the [group assign](17-language-reference.md#group-assign) expressions similar
to previously seen [apply rules](03-monitoring-basics.md#using-apply).
object HostGroup "linux-servers" {
```
object HostGroup "linux-servers" {
display_name = "Linux Servers"
assign where host.vars.os == "Linux"
}
}
object HostGroup "windows-servers" {
object HostGroup "windows-servers" {
display_name = "Windows Servers"
assign where host.vars.os == "Windows"
}
}
```
Service groups can be grouped together by similar pattern matches.
The [match function](18-library-reference.md#global-functions-match) expects a wildcard match string
and the attribute string to match with.
object ServiceGroup "ping" {
```
object ServiceGroup "ping" {
display_name = "Ping Checks"
assign where match("ping*", service.name)
}
}
object ServiceGroup "http" {
object ServiceGroup "http" {
display_name = "HTTP Checks"
assign where match("http*", service.check_command)
}
}
object ServiceGroup "disk" {
object ServiceGroup "disk" {
display_name = "Disk Checks"
assign where match("disk*", service.check_command)
}
}
```
#### templates.conf <a id="templates-conf"></a>
Most of the example configuration objects use generic global templates by
default:
template Host "generic-host" {
```
template Host "generic-host" {
max_check_attempts = 5
check_interval = 1m
retry_interval = 30s
check_command = "hostalive"
}
}
template Service "generic-service" {
template Service "generic-service" {
max_check_attempts = 3
check_interval = 1m
retry_interval = 30s
}
}
```
The `hostalive` check command is part of the
[Plugin Check Commands](10-icinga-template-library.md#icinga-template-library).
template Notification "mail-host-notification" {
```
template Notification "mail-host-notification" {
command = "mail-host-notification"
states = [ Up, Down ]
@ -632,9 +661,9 @@ The `hostalive` check command is part of the
DowntimeStart, DowntimeEnd, DowntimeRemoved ]
period = "24x7"
}
}
template Notification "mail-service-notification" {
template Notification "mail-service-notification" {
command = "mail-service-notification"
states = [ OK, Warning, Critical, Unknown ]
@ -643,7 +672,8 @@ The `hostalive` check command is part of the
DowntimeStart, DowntimeEnd, DowntimeRemoved ]
period = "24x7"
}
}
```
More details on `Notification` object attributes can be found [here](09-object-types.md#objecttype-notification).
@ -658,7 +688,8 @@ for the time ranges required for recurring downtime slots.
Learn more about downtimes in [this chapter](08-advanced-topics.md#downtimes).
apply ScheduledDowntime "backup-downtime" to Service {
```
apply ScheduledDowntime "backup-downtime" to Service {
author = "icingaadmin"
comment = "Scheduled downtime for backup"
@ -673,8 +704,8 @@ Learn more about downtimes in [this chapter](08-advanced-topics.md#downtimes).
}
assign where service.vars.backup_downtime != ""
}
}
```
#### timeperiods.conf <a id="timeperiods-conf"></a>

View File

@ -15,24 +15,28 @@ The recommended way of setting up these plugins is to copy them to a common dire
and create a new global constant, e.g. `CustomPluginDir` in your [constants.conf](04-configuring-icinga-2.md#constants-conf)
configuration file:
# cp check_snmp_int.pl /opt/monitoring/plugins
# chmod +x /opt/monitoring/plugins/check_snmp_int.pl
```
# cp check_snmp_int.pl /opt/monitoring/plugins
# chmod +x /opt/monitoring/plugins/check_snmp_int.pl
# cat /etc/icinga2/constants.conf
/**
# cat /etc/icinga2/constants.conf
/**
* This file defines global constants which can be used in
* the other configuration files. At a minimum the
* PluginDir constant should be defined.
*/
const PluginDir = "/usr/lib/nagios/plugins"
const CustomPluginDir = "/opt/monitoring/plugins"
const PluginDir = "/usr/lib/nagios/plugins"
const CustomPluginDir = "/opt/monitoring/plugins"
```
Prior to using the check plugin with Icinga 2 you should ensure that it is working properly
by trying to run it on the console using whichever user Icinga 2 is running as:
# su - icinga -s /bin/bash
$ /opt/monitoring/plugins/check_snmp_int.pl --help
```
# su - icinga -s /bin/bash
$ /opt/monitoring/plugins/check_snmp_int.pl --help
```
Additional libraries may be required for some plugins. Please consult the plugin
documentation and/or the included README file for installation instructions.
@ -64,7 +68,8 @@ set them on host/service level and you'll always know which command they control
This is an example for a custom `my-snmp-int` check command:
object CheckCommand "my-snmp-int" {
```
object CheckCommand "my-snmp-int" {
command = [ CustomPluginDir + "/check_snmp_int.pl" ]
arguments = {
@ -86,8 +91,8 @@ This is an example for a custom `my-snmp-int` check command:
vars.snmp_perf = true
vars.snmp_warn = "300,400"
vars.snmp_crit = "0,600"
}
}
```
For further information on your monitoring configuration read the
[Monitoring Basics](03-monitoring-basics.md#monitoring-basics) chapter.
@ -127,28 +132,30 @@ Common best practices when creating a new plugin are for example:
Example skeleton:
# 1. include optional libraries
# 2. global variables
# 3. helper functions and/or classes
# 4. define timeout condition
```
# 1. include optional libraries
# 2. global variables
# 3. helper functions and/or classes
# 4. define timeout condition
if (<timeout_reached>) then
if (<timeout_reached>) then
print "UNKNOWN - Timeout (...) reached | 'time'=30.0
endif
endif
# 5. main method
# 5. main method
<execute and fetch data>
<execute and fetch data>
if (<threshold_critical_condition>) then
if (<threshold_critical_condition>) then
print "CRITICAL - ... | 'time'=0.1 'myperfdatavalue'=5.0
exit(2)
else if (<threshold_warning_condition>) then
else if (<threshold_warning_condition>) then
print "WARNING - ... | 'time'=0.1 'myperfdatavalue'=3.0
exit(1)
else
else
print "OK - ... | 'time'=0.2 'myperfdatavalue'=1.0
endif
endif
```
There are various plugin libraries available which will help
with plugin execution and output formatting too, for example

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,8 @@ The following example uses the [SNMP ITL](10-icinga-template-library.md#plugin-c
overrides the `snmp_oid` custom attribute. A service is created for all hosts which
have the `snmp-community` custom attribute.
apply Service "uptime" {
```
apply Service "uptime" {
import "generic-service"
check_command = "snmp"
@ -23,7 +24,8 @@ have the `snmp-community` custom attribute.
vars.snmp_miblist = "DISMAN-EVENT-MIB"
assign where host.vars.snmp_community != ""
}
}
```
Additional SNMP plugins are available using the [Manubulon SNMP Plugins](10-icinga-template-library.md#snmp-manubulon-plugin-check-commands).
@ -37,15 +39,16 @@ Calling a plugin using the SSH protocol to execute a plugin on the remote server
its return code and output. The `by_ssh` command object is part of the built-in templates and
requires the `check_by_ssh` check plugin which is available in the [Monitoring Plugins package](02-getting-started.md#setting-up-check-plugins).
object CheckCommand "by_ssh_swap" {
```
object CheckCommand "by_ssh_swap" {
import "by_ssh"
vars.by_ssh_command = "/usr/lib/nagios/plugins/check_swap -w $by_ssh_swap_warn$ -c $by_ssh_swap_crit$"
vars.by_ssh_swap_warn = "75%"
vars.by_ssh_swap_crit = "50%"
}
}
object Service "swap" {
object Service "swap" {
import "generic-service"
host_name = "remote-ssh-host"
@ -53,7 +56,8 @@ requires the `check_by_ssh` check plugin which is available in the [Monitoring P
check_command = "by_ssh_swap"
vars.by_ssh_logname = "icinga"
}
}
```
## NSClient++ <a id="agent-based-checks-nsclient"></a>
@ -67,7 +71,8 @@ Icinga 2 provides the [nscp check command](10-icinga-template-library.md#plugin-
Example:
object Service "disk" {
```
object Service "disk" {
import "generic-service"
host_name = "remote-windows-host"
@ -78,7 +83,8 @@ Example:
vars.nscp_params = "c"
vars.nscp_warn = 70
vars.nscp_crit = 80
}
}
```
For details on the `NSClient++` configuration please refer to the [official documentation](https://docs.nsclient.org/).
@ -116,18 +122,22 @@ Icinga 2 provides the [nrpe check command](10-icinga-template-library.md#plugin-
Example:
object Service "users" {
```
object Service "users" {
import "generic-service"
host_name = "remote-nrpe-host"
check_command = "nrpe"
vars.nrpe_command = "check_users"
}
}
```
nrpe.cfg:
command[check_users]=/usr/local/icinga/libexec/check_users -w 5 -c 10
```
command[check_users]=/usr/local/icinga/libexec/check_users -w 5 -c 10
```
If you are planning to pass arguments to NRPE using the `-a`
command line parameter, make sure that your NRPE daemon has them
@ -144,7 +154,8 @@ attribute which expects either a single value or an array of values.
Example:
object Service "nrpe-disk-/" {
```
object Service "nrpe-disk-/" {
import "generic-service"
host_name = "remote-nrpe-host"
@ -152,11 +163,14 @@ Example:
check_command = "nrpe"
vars.nrpe_command = "check_disk"
vars.nrpe_arguments = [ "20%", "10%", "/" ]
}
}
```
Icinga 2 will execute the nrpe plugin like this:
/usr/lib/nagios/plugins/check_nrpe -H <remote-nrpe-host> -c 'check_disk' -a '20%' '10%' '/'
```
/usr/lib/nagios/plugins/check_nrpe -H <remote-nrpe-host> -c 'check_disk' -a '20%' '10%' '/'
```
NRPE expects all additional arguments in an ordered fashion
and interprets the first value as `$ARG1$` macro, the second
@ -164,12 +178,16 @@ value as `$ARG2$`, and so on.
nrpe.cfg:
command[check_disk]=/usr/local/icinga/libexec/check_disk -w $ARG1$ -c $ARG2$ -p $ARG3$
```
command[check_disk]=/usr/local/icinga/libexec/check_disk -w $ARG1$ -c $ARG2$ -p $ARG3$
```
Using the above example with `nrpe_arguments` the command
executed by the NRPE daemon looks similar to that:
/usr/local/icinga/libexec/check_disk -w 20% -c 10% -p /
```
/usr/local/icinga/libexec/check_disk -w 20% -c 10% -p /
```
You can pass arguments in a similar manner to [NSClient++](07-agent-based-monitoring.md#agent-based-checks-nsclient)
when using its NRPE supported check method.
@ -193,14 +211,16 @@ state or from a missed reset event.
Add a directive in `snmptt.conf`
EVENT coldStart .1.3.6.1.6.3.1.1.5.1 "Status Events" Normal
FORMAT Device reinitialized (coldStart)
EXEC echo "[$@] PROCESS_SERVICE_CHECK_RESULT;$A;Coldstart;2;The snmp agent has reinitialized." >> /var/run/icinga2/cmd/icinga2.cmd
SDESC
A coldStart trap signifies that the SNMPv2 entity, acting
in an agent role, is reinitializing itself and that its
configuration may have been altered.
EDESC
```
EVENT coldStart .1.3.6.1.6.3.1.1.5.1 "Status Events" Normal
FORMAT Device reinitialized (coldStart)
EXEC echo "[$@] PROCESS_SERVICE_CHECK_RESULT;$A;Coldstart;2;The snmp agent has reinitialized." >> /var/run/icinga2/cmd/icinga2.cmd
SDESC
A coldStart trap signifies that the SNMPv2 entity, acting
in an agent role, is reinitializing itself and that its
configuration may have been altered.
EDESC
```
1. Define the `EVENT` as per your need.
2. Construct the `EXEC` statement with the service name matching your template
@ -210,7 +230,8 @@ match your Icinga convention.
Add an `EventCommand` configuration object for the passive service auto reset event.
object EventCommand "coldstart-reset-event" {
```
object EventCommand "coldstart-reset-event" {
command = [ ConfigDir + "/conf.d/custom/scripts/coldstart_reset_event.sh" ]
arguments = {
@ -218,21 +239,23 @@ Add an `EventCommand` configuration object for the passive service auto reset ev
"-n" = "$host.name$"
"-s" = "$service.name$"
}
}
}
```
Create the `coldstart_reset_event.sh` shell script to pass the expanded variable
data in. The `$service.state_id$` is important in order to prevent an endless loop
of event firing after the service has been reset.
#!/bin/bash
```
#!/bin/bash
SERVICE_STATE_ID=""
HOST_NAME=""
SERVICE_NAME=""
SERVICE_STATE_ID=""
HOST_NAME=""
SERVICE_NAME=""
show_help()
{
cat <<-EOF
show_help()
{
cat <<-EOF
Usage: ${0##*/} [-h] -n HOST_NAME -s SERVICE_NAME
Writes a coldstart reset event to the Icinga command pipe.
@ -240,10 +263,10 @@ of event firing after the service has been reset.
-i SERVICE_STATE_ID The associated service state id.
-n HOST_NAME The associated host name.
-s SERVICE_NAME The associated service name.
EOF
}
EOF
}
while getopts "hi:n:s:" opt; do
while getopts "hi:n:s:" opt; do
case "$opt" in
h)
show_help
@ -263,33 +286,35 @@ of event firing after the service has been reset.
exit 0
;;
esac
done
done
if [ -z "$SERVICE_STATE_ID" ]; then
if [ -z "$SERVICE_STATE_ID" ]; then
show_help
printf "\n Error: -i required.\n"
exit 1
fi
fi
if [ -z "$HOST_NAME" ]; then
if [ -z "$HOST_NAME" ]; then
show_help
printf "\n Error: -n required.\n"
exit 1
fi
fi
if [ -z "$SERVICE_NAME" ]; then
if [ -z "$SERVICE_NAME" ]; then
show_help
printf "\n Error: -s required.\n"
exit 1
fi
fi
if [ "$SERVICE_STATE_ID" -gt 0 ]; then
if [ "$SERVICE_STATE_ID" -gt 0 ]; then
echo "[`date +%s`] PROCESS_SERVICE_CHECK_RESULT;$HOST_NAME;$SERVICE_NAME;0;Auto-reset (`date +"%m-%d-%Y %T"`)." >> /var/run/icinga2/cmd/icinga2.cmd
fi
fi
```
Finally create the `Service` and assign it:
apply Service "Coldstart" {
```
apply Service "Coldstart" {
import "generic-service-custom"
check_command = "dummy"
@ -308,7 +333,8 @@ Finally create the `Service` and assign it:
vars.sla = "24x7"
assign where (host.vars.os == "Linux" || host.vars.os == "Windows")
}
}
```
### Complex SNMP Traps <a id="complex-traps"></a>
@ -321,13 +347,15 @@ As long as the most recent passive update has occurred, the active check is bypa
Add a directive in `snmptt.conf`
EVENT enterpriseSpecific <YOUR OID> "Status Events" Normal
FORMAT Enterprise specific trap
EXEC echo "[$@] PROCESS_SERVICE_CHECK_RESULT;$A;$1;$2;$3" >> /var/run/icinga2/cmd/icinga2.cmd
SDESC
An enterprise specific trap.
The varbinds in order denote the Icinga service name, state and text.
EDESC
```
EVENT enterpriseSpecific <YOUR OID> "Status Events" Normal
FORMAT Enterprise specific trap
EXEC echo "[$@] PROCESS_SERVICE_CHECK_RESULT;$A;$1;$2;$3" >> /var/run/icinga2/cmd/icinga2.cmd
SDESC
An enterprise specific trap.
The varbinds in order denote the Icinga service name, state and text.
EDESC
```
1. Define the `EVENT` as per your need using your actual oid.
2. The service name, state and text are extracted from the first three varbinds.
@ -337,7 +365,8 @@ Create a `Service` for the specific use case associated to the host. If the host
matches and the first varbind value is `Backup`, SNMPTT will submit the corresponding
passive update with the state and text from the second and third varbind:
object Service "Backup" {
```
object Service "Backup" {
import "generic-service-custom"
host_name = "host.domain.com"
@ -355,4 +384,5 @@ passive update with the state and text from the second and third varbind:
vars.sla = "24x7"
vars.dummy_state = 2
vars.dummy_text = "No passive check result received."
}
}
```

View File

@ -387,12 +387,16 @@ In Icinga 2 active check freshness is enabled by default. It is determined by th
The threshold is calculated based on the last check execution time for actively executed checks:
(last check execution time + check interval) > current time
```
(last check execution time + check interval) > current time
```
If this host/service receives check results from an [external source](08-advanced-topics.md#external-check-results),
the threshold is based on the last time a check result was received:
(last check result time + check interval) > current time
```
(last check result time + check interval) > current time
```
> **Tip**
>
@ -579,7 +583,8 @@ In addition to that you can optionally define the `ssl` attribute which enables
Host definition:
object Host "webserver01" {
```
object Host "webserver01" {
import "generic-host"
address = "192.168.56.200"
vars.os = "Linux"
@ -601,20 +606,22 @@ Host definition:
ssl = true
}
}
}
}
```
Service apply for definitions:
apply Service "webserver_ping" for (instance => config in host.vars.webserver.instance) {
```
apply Service "webserver_ping" for (instance => config in host.vars.webserver.instance) {
display_name = "webserver_" + instance
check_command = "ping4"
vars.ping_address = config.address
assign where host.vars.webserver.instance
}
}
apply Service "webserver_port" for (instance => config in host.vars.webserver.instance) {
apply Service "webserver_port" for (instance => config in host.vars.webserver.instance) {
display_name = "webserver_" + instance + "_" + config.port
check_command = "tcp"
@ -622,9 +629,9 @@ Service apply for definitions:
vars.tcp_port = config.port
assign where host.vars.webserver.instance
}
}
apply Service "webserver_url" for (instance => config in host.vars.webserver.instance) {
apply Service "webserver_url" for (instance => config in host.vars.webserver.instance) {
display_name = "webserver_" + instance + "_" + config.url
check_command = "http"
@ -637,7 +644,8 @@ Service apply for definitions:
}
assign where config.url != ""
}
}
```
The variables defined in the host dictionary are not using the typical custom attribute
prefix recommended for CheckCommand parameters. Instead they are re-used for multiple
@ -756,7 +764,8 @@ slightly unexpected way. The following example shows how to assign values
depending on group membership. All hosts in the `slow-lan` host group use 300
as value for `ping_wrta`, all other hosts use 100.
globals.group_specific_value = function(group, group_value, non_group_value) {
```
globals.group_specific_value = function(group, group_value, non_group_value) {
return function() use (group, group_value, non_group_value) {
if (group in host.groups) {
return group_value
@ -764,9 +773,9 @@ as value for `ping_wrta`, all other hosts use 100.
return non_group_value
}
}
}
}
apply Service "ping4" {
apply Service "ping4" {
import "generic-service"
check_command = "ping4"
@ -774,7 +783,8 @@ as value for `ping_wrta`, all other hosts use 100.
vars.ping_crta = group_specific_value("slow-lan", 500, 200)
assign where true
}
}
```
#### Use Functions in Assign Where Expressions <a id="use-functions-assign-where"></a>
@ -790,19 +800,20 @@ The following example requires the host `myprinter` being added
to the host group `printers-lexmark` but only if the host uses
a template matching the name `lexmark*`.
template Host "lexmark-printer-host" {
```
template Host "lexmark-printer-host" {
vars.printer_type = "Lexmark"
}
}
object Host "myprinter" {
object Host "myprinter" {
import "generic-host"
import "lexmark-printer-host"
address = "192.168.1.1"
}
}
/* register a global function for the assign where call */
globals.check_host_templates = function(host, search) {
/* register a global function for the assign where call */
globals.check_host_templates = function(host, search) {
/* iterate over all host templates and check if the search matches */
for (tmpl in host.templates) {
if (match(search, tmpl)) {
@ -812,14 +823,14 @@ a template matching the name `lexmark*`.
/* nothing matched */
return false
}
}
object HostGroup "printers-lexmark" {
object HostGroup "printers-lexmark" {
display_name = "Lexmark Printers"
/* call the global function and pass the arguments */
assign where check_host_templates(host, "lexmark*")
}
}
```
Take a different more complex example: All hosts with the
custom attribute `vars_app` as nested dictionary should be
@ -828,22 +839,25 @@ added to the host group `ABAP-app-server`. But only if the
It could read as wildcard match for nested dictionaries:
```
where host.vars.vars_app["*"].app_type == "ABAP"
```
The solution for this problem is to register a global
function which checks the `app_type` for all hosts
with the `vars_app` dictionary.
object Host "appserver01" {
```
object Host "appserver01" {
check_command = "dummy"
vars.vars_app["ABC"] = { app_type = "ABAP" }
}
object Host "appserver02" {
}
object Host "appserver02" {
check_command = "dummy"
vars.vars_app["DEF"] = { app_type = "ABAP" }
}
}
globals.check_app_type = function(host, type) {
globals.check_app_type = function(host, type) {
/* ensure that other hosts without the custom attribute do not match */
if (typeof(host.vars.vars_app) != Dictionary) {
return false
@ -859,12 +873,12 @@ with the `vars_app` dictionary.
/* nothing matched */
return false
}
}
object HostGroup "ABAP-app-server" {
object HostGroup "ABAP-app-server" {
assign where check_app_type(host, "ABAP")
}
}
```
#### Use Functions in Command Arguments set_if <a id="use-functions-command-arguments-setif"></a>
@ -879,13 +893,15 @@ multiple conditions and attributes.
The following example was found on the community support channels. The user had defined a host
dictionary named `compellent` with the key `disks`. This was then used inside service apply for rules.
object Host "dict-host" {
```
object Host "dict-host" {
check_command = "check_compellent"
vars.compellent["disks"] = {
file = "/var/lib/check_compellent/san_disks.0.json",
checks = ["disks"]
}
}
}
```
The more significant problem was to only add the command parameter `--disk` to the plugin call
when the dictionary `compellent` contains the key `disks`, and omit it if not found.
@ -894,7 +910,8 @@ By defining `set_if` as [abbreviated lambda function](17-language-reference.md#n
and evaluating the host custom attribute `compellent` containing the `disks` this problem was
solved like this:
object CheckCommand "check_compellent" {
```
object CheckCommand "check_compellent" {
command = [ "/usr/bin/check_compellent" ]
arguments = {
"--disks" = {
@ -907,7 +924,8 @@ solved like this:
}}
}
}
}
}
```
This implementation uses the dictionary type method [contains](18-library-reference.md#dictionary-contains)
and will fail if `host.vars.compellent` is not of the type `Dictionary`.
@ -915,18 +933,21 @@ Therefore you can extend the checks using the [typeof](17-language-reference.md#
You can test the types using the `icinga2 console`:
# icinga2 console
Icinga (version: v2.3.0-193-g3eb55ad)
<1> => srv_vars.compellent["check_a"] = { file="outfile_a.json", checks = [ "disks", "fans" ] }
null
<2> => srv_vars.compellent["check_b"] = { file="outfile_b.json", checks = [ "power", "voltages" ] }
null
<3> => typeof(srv_vars.compellent)
type 'Dictionary'
<4> =>
```
# icinga2 console
Icinga (version: v2.3.0-193-g3eb55ad)
<1> => srv_vars.compellent["check_a"] = { file="outfile_a.json", checks = [ "disks", "fans" ] }
null
<2> => srv_vars.compellent["check_b"] = { file="outfile_b.json", checks = [ "power", "voltages" ] }
null
<3> => typeof(srv_vars.compellent)
type 'Dictionary'
<4> =>
```
The more programmatic approach for `set_if` could look like this:
```
"--disks" = {
set_if = {{
var srv_vars = service.vars
@ -943,7 +964,7 @@ The more programmatic approach for `set_if` could look like this:
}
}}
}
```
#### Use Functions as Command Attribute <a id="use-functions-command-attribute"></a>
@ -955,20 +976,22 @@ The following example was taken from the community support channels. The require
specify a custom attribute inside the notification apply rule and decide which notification
script to call based on that.
object User "short-dummy" {
}
```
object User "short-dummy" {
}
object UserGroup "short-dummy-group" {
object UserGroup "short-dummy-group" {
assign where user.name == "short-dummy"
}
}
apply Notification "mail-admins-short" to Host {
apply Notification "mail-admins-short" to Host {
import "mail-host-notification"
command = "mail-host-notification-test"
user_groups = [ "short-dummy-group" ]
vars.short = true
assign where host.vars.notification.mail
}
}
```
The solution is fairly simple: The `command` attribute is implemented as function returning
an array required by the caller Icinga 2.
@ -980,7 +1003,8 @@ returned.
You can omit the `log()` calls, they only help debugging.
object NotificationCommand "mail-host-notification-test" {
```
object NotificationCommand "mail-host-notification-test" {
command = {{
log("command as function")
var mailscript = "mail-host-notification-long.sh"
@ -997,8 +1021,8 @@ You can omit the `log()` calls, they only help debugging.
env = {
}
}
}
```
### Access Object Attributes at Runtime <a id="access-object-attributes-at-runtime"></a>

View File

@ -396,12 +396,14 @@ Configuration Attributes:
Available state filters:
OK
Warning
Critical
Unknown
Up
Down
```
OK
Warning
Critical
Unknown
Up
Down
```
When using [apply rules](03-monitoring-basics.md#using-apply) for dependencies, you can leave out certain attributes which will be
automatically determined by Icinga 2.
@ -1154,27 +1156,33 @@ Configuration Attributes:
Available notification state filters for Service:
OK
Warning
Critical
Unknown
```
OK
Warning
Critical
Unknown
```
Available notification state filters for Host:
Up
Down
```
Up
Down
```
Available notification type filters:
DowntimeStart
DowntimeEnd
DowntimeRemoved
Custom
Acknowledgement
Problem
Recovery
FlappingStart
FlappingEnd
```
DowntimeStart
DowntimeEnd
DowntimeRemoved
Custom
Acknowledgement
Problem
Recovery
FlappingStart
FlappingEnd
```
Runtime Attributes:
@ -1687,24 +1695,28 @@ object User "icingaadmin" {
Available notification state filters:
OK
Warning
Critical
Unknown
Up
Down
```
OK
Warning
Critical
Unknown
Up
Down
```
Available notification type filters:
DowntimeStart
DowntimeEnd
DowntimeRemoved
Custom
Acknowledgement
Problem
Recovery
FlappingStart
FlappingEnd
```
DowntimeStart
DowntimeEnd
DowntimeRemoved
Custom
Acknowledgement
Problem
Recovery
FlappingStart
FlappingEnd
```
Configuration Attributes:

View File

@ -25,7 +25,9 @@ You are advised to create your own CheckCommand definitions in
By default the generic templates are included in the [icinga2.conf](04-configuring-icinga-2.md#icinga2-conf) configuration file:
include <itl>
```
include <itl>
```
These templates are imported by the provided example configuration.

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,9 @@ You need to install Graphite first, then proceed with configuring it in Icinga 2
Use the [GraphiteWriter](14-features.md#graphite-carbon-cache-writer) feature
for sending real-time metrics from Icinga 2 to Graphite.
# icinga2 feature enable graphite
```
# icinga2 feature enable graphite
```
A popular alternative frontend for Graphite is for example [Grafana](https://grafana.org).
@ -36,7 +38,9 @@ Its written in Go and has no external dependencies.
Use the [InfluxdbWriter](14-features.md#influxdb-writer) feature
for sending real-time metrics from Icinga 2 to InfluxDB.
# icinga2 feature enable influxdb
```
# icinga2 feature enable influxdb
```
A popular frontend for InfluxDB is for example [Grafana](https://grafana.org).
@ -61,11 +65,15 @@ data files which Icinga 2 generates.
Enable performance data writer in icinga 2
# icinga2 feature enable perfdata
```
# icinga2 feature enable perfdata
```
Configure npcd to use the performance data created by Icinga 2:
vim /etc/pnp4nagios/npcd.cfg
```
vim /etc/pnp4nagios/npcd.cfg
```
Set `perfdata_spool_dir = /var/spool/icinga2/perfdata` and restart the `npcd` daemon.
@ -120,9 +128,11 @@ based on your monitoring configuration and status data using [NagVis](https://ww
The configuration in nagvis.ini.php should look like this for Livestatus for example:
[backend_live_1]
backendtype="mklivestatus"
socket="unix:/var/run/icinga2/cmd/livestatus"
```
[backend_live_1]
backendtype="mklivestatus"
socket="unix:/var/run/icinga2/cmd/livestatus"
```
If you are planning an integration into Icinga Web 2, look at [this module](https://github.com/Icinga/icingaweb2-module-nagvis).
@ -190,13 +200,15 @@ These tools are currently in development and require feedback and tests:
They work in a similar fashion for Icinga 2 and are used for 1.x web interfaces (Icinga Web 2 doesn't require
the action url attribute in its own module).
template Host "pnp-hst" {
```
template Host "pnp-hst" {
action_url = "/pnp4nagios/graph?host=$HOSTNAME$"
}
}
template Service "pnp-svc" {
template Service "pnp-svc" {
action_url = "/pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$"
}
}
```
### PNP Custom Templates with Icinga 2 <a id="addons-graphing-pnp-custom-templates"></a>
@ -213,24 +225,26 @@ and use that inside the formatting templates as `SERVICECHECKCOMMAND` for instan
Example for services:
# vim /etc/icinga2/features-enabled/perfdata.conf
```
# vim /etc/icinga2/features-enabled/perfdata.conf
service_format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$icinga.timet$\tHOSTNAME::$host.name$\tSERVICEDESC::$service.name$\tSERVICEPERFDATA::$service.perfdata$\tSERVICECHECKCOMMAND::$service.check_command$$pnp_check_arg1$\tHOSTSTATE::$host.state$\tHOSTSTATETYPE::$host.state_type$\tSERVICESTATE::$service.state$\tSERVICESTATETYPE::$service.state_type$"
service_format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$icinga.timet$\tHOSTNAME::$host.name$\tSERVICEDESC::$service.name$\tSERVICEPERFDATA::$service.perfdata$\tSERVICECHECKCOMMAND::$service.check_command$$pnp_check_arg1$\tHOSTSTATE::$host.state$\tHOSTSTATETYPE::$host.state_type$\tSERVICESTATE::$service.state$\tSERVICESTATETYPE::$service.state_type$"
# vim /etc/icinga2/conf.d/services.conf
# vim /etc/icinga2/conf.d/services.conf
template Service "pnp-svc" {
template Service "pnp-svc" {
action_url = "/pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$"
vars.pnp_check_arg1 = ""
}
}
apply Service "nrpe-check" {
apply Service "nrpe-check" {
import "pnp-svc"
check_command = nrpe
vars.nrpe_command = "check_disk"
vars.pnp_check_arg1 = "!$nrpe_command$"
}
}
```
If there are warnings about unresolved macros, make sure to specify a default value for `vars.pnp_check_arg1` inside the

View File

@ -172,7 +172,9 @@ through the web interface).
In order to enable the `ExternalCommandListener` configuration use the
following command and restart Icinga 2 afterwards:
# icinga2 feature enable command
```
# icinga2 feature enable command
```
Icinga 2 creates the command pipe file as `/var/run/icinga2/cmd/icinga2.cmd`
using the default configuration.
@ -181,12 +183,14 @@ Web interfaces and other Icinga addons are able to send commands to
Icinga 2 through the external command pipe, for example for rescheduling
a forced service check:
# /bin/echo "[`date +%s`] SCHEDULE_FORCED_SVC_CHECK;localhost;ping4;`date +%s`" >> /var/run/icinga2/cmd/icinga2.cmd
```
# /bin/echo "[`date +%s`] SCHEDULE_FORCED_SVC_CHECK;localhost;ping4;`date +%s`" >> /var/run/icinga2/cmd/icinga2.cmd
# tail -f /var/log/messages
# tail -f /var/log/messages
Oct 17 15:01:25 icinga-server icinga2: Executing external command: [1382014885] SCHEDULE_FORCED_SVC_CHECK;localhost;ping4;1382014885
Oct 17 15:01:25 icinga-server icinga2: Rescheduling next check for service 'ping4'
Oct 17 15:01:25 icinga-server icinga2: Executing external command: [1382014885] SCHEDULE_FORCED_SVC_CHECK;localhost;ping4;1382014885
Oct 17 15:01:25 icinga-server icinga2: Rescheduling next check for service 'ping4'
```
A list of currently supported external commands can be found [here](24-appendix.md#external-commands-list-detail).
@ -216,13 +220,17 @@ Therefore the Icinga 2 [PerfdataWriter](09-object-types.md#objecttype-perfdatawr
feature allows you to define the output template format for host and services helped
with Icinga 2 runtime vars.
host_format_template = "DATATYPE::HOSTPERFDATA\tTIMET::$icinga.timet$\tHOSTNAME::$host.name$\tHOSTPERFDATA::$host.perfdata$\tHOSTCHECKCOMMAND::$host.check_command$\tHOSTSTATE::$host.state$\tHOSTSTATETYPE::$host.state_type$"
service_format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$icinga.timet$\tHOSTNAME::$host.name$\tSERVICEDESC::$service.name$\tSERVICEPERFDATA::$service.perfdata$\tSERVICECHECKCOMMAND::$service.check_command$\tHOSTSTATE::$host.state$\tHOSTSTATETYPE::$host.state_type$\tSERVICESTATE::$service.state$\tSERVICESTATETYPE::$service.state_type$"
```
host_format_template = "DATATYPE::HOSTPERFDATA\tTIMET::$icinga.timet$\tHOSTNAME::$host.name$\tHOSTPERFDATA::$host.perfdata$\tHOSTCHECKCOMMAND::$host.check_command$\tHOSTSTATE::$host.state$\tHOSTSTATETYPE::$host.state_type$"
service_format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$icinga.timet$\tHOSTNAME::$host.name$\tSERVICEDESC::$service.name$\tSERVICEPERFDATA::$service.perfdata$\tSERVICECHECKCOMMAND::$service.check_command$\tHOSTSTATE::$host.state$\tHOSTSTATETYPE::$host.state_type$\tSERVICESTATE::$service.state$\tSERVICESTATETYPE::$service.state_type$"
```
The default templates are already provided with the Icinga 2 feature configuration
which can be enabled using
# icinga2 feature enable perfdata
```
# icinga2 feature enable perfdata
```
By default all performance data files are rotated in a 15 seconds interval into
the `/var/spool/icinga2/perfdata/` directory as `host-perfdata.<timestamp>` and
@ -240,7 +248,9 @@ write them to the defined Graphite Carbon daemon tcp socket.
You can enable the feature using
# icinga2 feature enable graphite
```
# icinga2 feature enable graphite
```
By default the [GraphiteWriter](09-object-types.md#objecttype-graphitewriter) feature
expects the Graphite Carbon Cache to listen at `127.0.0.1` on TCP port `2003`.
@ -253,8 +263,10 @@ depends on this schema.
The default prefix for hosts and services is configured using
[runtime macros](03-monitoring-basics.md#runtime-macros)like this:
icinga2.$host.name$.host.$host.check_command$
icinga2.$host.name$.services.$service.name$.$service.check_command$
```
icinga2.$host.name$.host.$host.check_command$
icinga2.$host.name$.services.$service.name$.$service.check_command$
```
You can customize the prefix name by using the `host_name_template` and
`service_name_template` configuration attributes.
@ -274,7 +286,9 @@ The following characters are escaped in prefix labels:
Metric values are stored like this:
<prefix>.perfdata.<perfdata-label>.value
```
<prefix>.perfdata.<perfdata-label>.value
```
The following characters are escaped in perfdata labels:
@ -292,22 +306,26 @@ and is therefore replaced by `.`.
By enabling `enable_send_thresholds` Icinga 2 automatically adds the following threshold metrics:
<prefix>.perfdata.<perfdata-label>.min
<prefix>.perfdata.<perfdata-label>.max
<prefix>.perfdata.<perfdata-label>.warn
<prefix>.perfdata.<perfdata-label>.crit
```
<prefix>.perfdata.<perfdata-label>.min
<prefix>.perfdata.<perfdata-label>.max
<prefix>.perfdata.<perfdata-label>.warn
<prefix>.perfdata.<perfdata-label>.crit
```
By enabling `enable_send_metadata` Icinga 2 automatically adds the following metadata metrics:
<prefix>.metadata.current_attempt
<prefix>.metadata.downtime_depth
<prefix>.metadata.acknowledgement
<prefix>.metadata.execution_time
<prefix>.metadata.latency
<prefix>.metadata.max_check_attempts
<prefix>.metadata.reachable
<prefix>.metadata.state
<prefix>.metadata.state_type
```
<prefix>.metadata.current_attempt
<prefix>.metadata.downtime_depth
<prefix>.metadata.acknowledgement
<prefix>.metadata.execution_time
<prefix>.metadata.latency
<prefix>.metadata.max_check_attempts
<prefix>.metadata.reachable
<prefix>.metadata.state
<prefix>.metadata.state_type
```
Metadata metric overview:
@ -326,10 +344,12 @@ Metadata metric overview:
The following example illustrates how to configure the storage schemas for Graphite Carbon
Cache.
[icinga2_default]
# intervals like PNP4Nagios uses them per default
pattern = ^icinga2\.
retentions = 1m:2d,5m:10d,30m:90d,360m:4y
```
[icinga2_default]
# intervals like PNP4Nagios uses them per default
pattern = ^icinga2\.
retentions = 1m:2d,5m:10d,30m:90d,360m:4y
```
### InfluxDB Writer <a id="influxdb-writer"></a>
@ -339,7 +359,9 @@ defined InfluxDB HTTP API.
You can enable the feature using
# icinga2 feature enable influxdb
```
# icinga2 feature enable influxdb
```
By default the [InfluxdbWriter](09-object-types.md#objecttype-influxdbwriter) feature
expects the InfluxDB daemon to listen at `127.0.0.1` on port `8086`.
@ -456,7 +478,9 @@ attribute.
Metric values are stored like this:
check_result.perfdata.<perfdata-label>.value
```
check_result.perfdata.<perfdata-label>.value
```
The following characters are escaped in perfdata labels:
@ -475,10 +499,12 @@ and is therefore replaced by `.`.
Icinga 2 automatically adds the following threshold metrics
if existing:
check_result.perfdata.<perfdata-label>.min
check_result.perfdata.<perfdata-label>.max
check_result.perfdata.<perfdata-label>.warn
check_result.perfdata.<perfdata-label>.crit
```
check_result.perfdata.<perfdata-label>.min
check_result.perfdata.<perfdata-label>.max
check_result.perfdata.<perfdata-label>.warn
check_result.perfdata.<perfdata-label>.crit
```
### Graylog Integration <a id="graylog-integration"></a>
@ -494,7 +520,9 @@ While it has been specified by the [Graylog](https://www.graylog.org) project as
You can enable the feature using
# icinga2 feature enable gelf
```
# icinga2 feature enable gelf
```
By default the `GelfWriter` object expects the GELF receiver to listen at `127.0.0.1` on TCP port `12201`.
The default `source` attribute is set to `icinga2`. You can customize that for your needs if required.
@ -514,27 +542,35 @@ write them to the defined TSDB TCP socket.
You can enable the feature using
# icinga2 feature enable opentsdb
```
# icinga2 feature enable opentsdb
```
By default the `OpenTsdbWriter` object expects the TSD to listen at
`127.0.0.1` on port `4242`.
The current naming schema is
icinga.host.<metricname>
icinga.service.<servicename>.<metricname>
```
icinga.host.<metricname>
icinga.service.<servicename>.<metricname>
```
for host and service checks. The tag host is always applied.
To make sure Icinga 2 writes a valid metric into OpenTSDB some characters are replaced
with `_` in the target name:
\ (and space)
```
\ (and space)
```
The resulting name in OpenTSDB might look like:
www-01 / http-cert / response time
icinga.http_cert.response_time
```
www-01 / http-cert / response time
icinga.http_cert.response_time
```
In addition to the performance data retrieved from the check plugin, Icinga 2 sends
internal check statistic data to OpenTSDB:
@ -554,7 +590,9 @@ internal check statistic data to OpenTSDB:
While reachable, state and state_type are metrics for the host or service the
other metrics follow the current naming schema
icinga.check.<metricname>
```
icinga.check.<metricname>
```
with the following tags
@ -592,18 +630,24 @@ in the [Livestatus Schema](24-appendix.md#schema-livestatus) section.
You can enable Livestatus using icinga2 feature enable:
# icinga2 feature enable livestatus
```
# icinga2 feature enable livestatus
```
After that you will have to restart Icinga 2:
# systemctl restart icinga2
```
# systemctl restart icinga2
```
By default the Livestatus socket is available in `/var/run/icinga2/cmd/livestatus`.
In order for queries and commands to work you will need to add your query user
(e.g. your web server) to the `icingacmd` group:
# usermod -a -G icingacmd www-data
```
# usermod -a -G icingacmd www-data
```
The Debian packages use `nagios` as the user and group name. Make sure to change `icingacmd` to
`nagios` if you're using Debian.
@ -615,8 +659,9 @@ In order to use the historical tables provided by the livestatus feature (for ex
are expected to be in `/var/log/icinga2/compat`. A different path can be set using the
`compat_log_path` configuration attribute.
# icinga2 feature enable compatlog
```
# icinga2 feature enable compatlog
```
### Livestatus Sockets <a id="livestatus-sockets"></a>
@ -642,26 +687,28 @@ programmatically: [Monitoring::Livestatus](http://search.cpan.org/~nierlein/Moni
Example using the unix socket:
# echo -e "GET services\n" | /usr/bin/nc -U /var/run/icinga2/cmd/livestatus
```
# echo -e "GET services\n" | /usr/bin/nc -U /var/run/icinga2/cmd/livestatus
Example using the tcp socket listening on port `6558`:
# echo -e 'GET services\n' | netcat 127.0.0.1 6558
# echo -e 'GET services\n' | netcat 127.0.0.1 6558
# cat servicegroups <<EOF
GET servicegroups
# cat servicegroups <<EOF
GET servicegroups
EOF
(cat servicegroups; sleep 1) | netcat 127.0.0.1 6558
EOF
(cat servicegroups; sleep 1) | netcat 127.0.0.1 6558
```
### Livestatus COMMAND Queries <a id="livestatus-command-queries"></a>
A list of available external commands and their parameters can be found [here](24-appendix.md#external-commands-list-detail)
$ echo -e 'COMMAND <externalcommandstring>' | netcat 127.0.0.1 6558
```
$ echo -e 'COMMAND <externalcommandstring>' | netcat 127.0.0.1 6558
```
### Livestatus Filters <a id="livestatus-filters"></a>
@ -696,20 +743,22 @@ Schema: "Stats: aggregatefunction aggregateattribute"
Example:
GET hosts
Filter: has_been_checked = 1
Filter: check_type = 0
Stats: sum execution_time
Stats: sum latency
Stats: sum percent_state_change
Stats: min execution_time
Stats: min latency
Stats: min percent_state_change
Stats: max execution_time
Stats: max latency
Stats: max percent_state_change
OutputFormat: json
ResponseHeader: fixed16
```
GET hosts
Filter: has_been_checked = 1
Filter: check_type = 0
Stats: sum execution_time
Stats: sum latency
Stats: sum percent_state_change
Stats: min execution_time
Stats: min latency
Stats: min percent_state_change
Stats: max execution_time
Stats: max latency
Stats: max percent_state_change
OutputFormat: json
ResponseHeader: fixed16
```
### Livestatus Output <a id="livestatus-output"></a>
@ -721,7 +770,9 @@ is a pipe (2nd level).
Separators can be set using ASCII codes like:
Separators: 10 59 44 124
```
Separators: 10 59 44 124
```
* JSON
@ -773,7 +824,9 @@ interval to its `objects.cache` and `status.dat` files. Icinga 2 provides
the `StatusDataWriter` object which dumps all configuration objects and
status updates in a regular interval.
# icinga2 feature enable statusdata
```
# icinga2 feature enable statusdata
```
If you are not using any web interface or addon which uses these files,
you can safely disable this feature.
@ -795,7 +848,9 @@ for answering queries to historical tables.
The `CompatLogger` object can be enabled with
# icinga2 feature enable compatlog
```
# icinga2 feature enable compatlog
```
By default, the Icinga 1.x log file called `icinga.log` is located
in `/var/log/icinga2/compat`. Rotated log files are moved into
@ -820,7 +875,8 @@ environments, Icinga 2 supports the `CheckResultReader` object.
There is no feature configuration available, but it must be defined
on-demand in your Icinga 2 objects configuration.
object CheckResultReader "reader" {
```
object CheckResultReader "reader" {
spool_dir = "/data/check-results"
}
}
```

View File

@ -547,15 +547,19 @@ settings of the Icinga 2 systemd service by creating
`/etc/systemd/system/icinga2.service.d/override.conf` with the following
content:
[Service]
Restart=always
RestartSec=1
StartLimitInterval=10
StartLimitBurst=3
```
[Service]
Restart=always
RestartSec=1
StartLimitInterval=10
StartLimitBurst=3
```
Using the watchdog can also help with monitoring Icinga 2, to activate and use it add the following to the override:
WatchdogSec=30s
```
WatchdogSec=30s
```
This way systemd will kill Icinga 2 if does not notify for over 30 seconds, a timout of less than 10 seconds is not
recommended. When the watchdog is activated, `Restart=` can be set to `watchdog` to restart Icinga 2 in the case of a

View File

@ -5,12 +5,14 @@
Icinga 2 features an object-based configuration format. You can define new
objects using the `object` keyword:
object Host "host1.example.org" {
```
object Host "host1.example.org" {
display_name = "host1"
address = "192.168.0.1"
address6 = "2001:db8:1234::42"
}
}
```
In general you need to write each statement on a new line. Expressions started
with `{`, `(` and `[` extend until the matching closing character and can be broken
@ -19,11 +21,13 @@ up into multiple lines.
Alternatively you can write multiple statements on a single line by separating
them with a semicolon:
object Host "host1.example.org" {
```
object Host "host1.example.org" {
display_name = "host1"
address = "192.168.0.1"; address6 = "2001:db8:1234::42"
}
}
```
Each object is uniquely identified by its type (`Host`) and name
(`host1.example.org`). Some types have composite names, e.g. the
@ -53,7 +57,9 @@ A floating-point number.
Example:
27.3
```
27.3
```
### Duration Literals <a id="duration-literals"></a>
@ -62,7 +68,9 @@ suffixes to help with specifying time durations.
Example:
2.5m
```
2.5m
```
Supported suffixes include ms (milliseconds), s (seconds), m (minutes),
h (hours) and d (days).
@ -76,7 +84,9 @@ A string.
Example:
"Hello World!"
```
"Hello World!"
```
#### String Literals Escape Sequences <a id="string-literals-escape-sequences"></a>
@ -104,10 +114,12 @@ Strings spanning multiple lines can be specified by enclosing them in
Example:
{{{This
is
a multi-line
string.}}}
```
{{{This
is
a multi-line
string.}}}
```
Unlike in ordinary strings special characters do not have to be escaped
in multi-line string literals.
@ -130,10 +142,12 @@ The comma after the last key-value pair is optional.
Example:
{
```
{
address = "192.168.0.1"
port = 443
}
}
```
Identifiers may not contain certain characters (e.g. space) or start
with certain characters (e.g. digits). If you want to use a dictionary
@ -149,7 +163,9 @@ The comma after the last element is optional.
Example:
[ "hello", 42 ]
```
[ "hello", 42 ]
```
An array may simultaneously contain values of different types, such as
strings and numbers.
@ -198,36 +214,46 @@ Operator | Precedence | Examples (Result) | Descript
A reference to a value can be obtained using the `&` operator. The `*` operator can be used
to dereference a reference:
var value = "Hello!"
var p = &value /* p refers to value */
*p = "Hi!"
log(value) // Prints "Hi!" because the variable was changed
```
var value = "Hello!"
var p = &value /* p refers to value */
*p = "Hi!"
log(value) // Prints "Hi!" because the variable was changed
```
### Namespaces <a id="namespaces"></a>
Namespaces can be used to organize variables and functions. They are used to avoid name conflicts. The `namespace`
keyword is used to create a new namespace:
namespace Utils {
```
namespace Utils {
function calculate() {
return 2 + 2
}
}
}
```
The namespace is made available as a global variable which has the namespace's name (e.g. `Utils`):
Utils.calculate()
```
Utils.calculate()
```
The `using` keyword can be used to make all attributes in a namespace available to a script without having to
explicitly specify the namespace's name for each access:
using Utils
calculate()
```
using Utils
calculate()
```
The `using` keyword only has an effect for the current file and only for code that follows the keyword:
calculate() // This will not work.
using Utils
```
calculate() // This will not work.
using Utils
```
The following namespaces are automatically imported as if by using the `using` keyword:
@ -240,11 +266,13 @@ The following namespaces are automatically imported as if by using the `using` k
Functions can be called using the `()` operator:
const MyGroups = [ "test1", "test" ]
```
const MyGroups = [ "test1", "test" ]
{
{
check_interval = len(MyGroups) * 1m
}
}
```
A list of available functions is available in the [Library Reference](18-library-reference.md#library-reference) chapter.
@ -260,10 +288,12 @@ Sets an attribute to the specified value.
Example:
{
```
{
a = 5
a = 7
}
}
```
In this example `a` has the value `7` after both instructions are executed.
@ -271,65 +301,81 @@ In this example `a` has the value `7` after both instructions are executed.
The += operator is a shortcut. The following expression:
{
```
{
a = [ "hello" ]
a += [ "world" ]
}
}
```
is equivalent to:
{
```
{
a = [ "hello" ]
a = a + [ "world" ]
}
}
```
### Operator -= <a id="operator-substractive-assignment"></a>
The -= operator is a shortcut. The following expression:
{
```
{
a = 10
a -= 5
}
}
```
is equivalent to:
{
```
{
a = 10
a = a - 5
}
}
```
### Operator \*= <a id="operator-multiply-assignment"></a>
The *= operator is a shortcut. The following expression:
{
```
{
a = 60
a *= 5
}
}
```
is equivalent to:
{
```
{
a = 60
a = a * 5
}
}
```
### Operator /= <a id="operator-dividing-assignment"></a>
The /= operator is a shortcut. The following expression:
{
```
{
a = 300
a /= 5
}
}
```
is equivalent to:
{
```
{
a = 300
a = a / 5
}
}
```
## Indexer <a id="indexer"></a>
@ -337,23 +383,29 @@ The indexer syntax provides a convenient way to set dictionary elements.
Example:
{
```
{
hello.key = "world"
}
}
```
Example (alternative syntax):
{
```
{
hello["key"] = "world"
}
}
```
This is equivalent to writing:
{
```
{
hello += {
key = "world"
}
}
}
```
If the `hello` attribute does not already have a value, it is automatically initialized to an empty dictionary.
@ -363,22 +415,24 @@ Objects can import attributes from other objects.
Example:
template Host "default-host" {
```
template Host "default-host" {
vars.colour = "red"
}
}
template Host "test-host" {
template Host "test-host" {
import "default-host"
vars.colour = "blue"
}
}
object Host "localhost" {
object Host "localhost" {
import "test-host"
address = "127.0.0.1"
address6 = "::1"
}
}
```
The `default-host` and `test-host` objects are marked as templates
using the `template` keyword. Unlike ordinary objects templates are not
@ -394,9 +448,11 @@ Parent objects are resolved in the order they're specified using the
Default templates which are automatically imported into all object definitions
can be specified using the `default` keyword:
template CheckCommand "plugin-check-command" default {
```
template CheckCommand "plugin-check-command" default {
// ...
}
}
```
Default templates are imported before any other user-specified statement in an
object definition is evaluated.
@ -408,7 +464,9 @@ is unspecified.
Global constants can be set using the `const` keyword:
const VarName = "some value"
```
const VarName = "some value"
```
Once defined a constant can be accessed from any file. Constants cannot be changed
once they are set.
@ -503,13 +561,15 @@ ICINGA2\_RLIMIT\_STACK |**Read-write.** Defines the resource limit for RLIMI
The `apply` keyword can be used to create new objects which are associated with
another group of objects.
apply Service "ping" to Host {
```
apply Service "ping" to Host {
import "generic-service"
check_command = "ping4"
assign where host.name == "localhost"
}
}
```
In this example the `assign where` condition is a boolean expression which is
evaluated for all objects of type `Host` and a new service with name "ping"
@ -544,13 +604,14 @@ chapter.
[Apply](17-language-reference.md#apply) rules can be extended with the
[for loop](17-language-reference.md#for-loops) keyword.
apply Service "prefix-" for (key => value in host.vars.dictionary) to Host {
```
apply Service "prefix-" for (key => value in host.vars.dictionary) to Host {
import "generic-service"
check_command = "ping4"
vars.host_value = value
}
}
```
Any valid config attribute can be accessed using the `host` and `service`
variables. The attribute must be of the Array or Dictionary type. In this example
@ -577,11 +638,13 @@ chapter.
Group objects can be assigned to specific member objects using the `assign where`
and `ignore where` conditions.
object HostGroup "linux-servers" {
```
object HostGroup "linux-servers" {
display_name = "Linux Servers"
assign where host.vars.os == "Linux"
}
}
```
In this example the `assign where` condition is a boolean expression which is evaluated
for all objects of the type `Host`. Each matching host is added as member to the host group
@ -623,13 +686,15 @@ The Icinga 2 configuration format supports C/C++-style and shell-style comments.
Example:
/*
```
/*
This is a comment.
*/
object Host "localhost" {
object Host "localhost" {
check_interval = 30 // this is also a comment.
retry_interval = 15 # yet another comment
}
}
```
## Includes <a id="includes"></a>
@ -639,15 +704,19 @@ Paths must be relative to the configuration file that contains the
Example:
include "some/other/file.conf"
include "conf.d/*.conf"
```
include "some/other/file.conf"
include "conf.d/*.conf"
```
Wildcard includes are not recursive.
Icinga also supports include search paths similar to how they work in a
C/C++ compiler:
include <itl>
```
include <itl>
```
Note the use of angle brackets instead of double quotes. This causes the
config compiler to search the include search paths for the specified
@ -664,8 +733,10 @@ files in a directory which match a certain pattern.
Example:
include_recursive "conf.d", "*.conf"
include_recursive "templates"
```
include_recursive "conf.d", "*.conf"
include_recursive "templates"
```
The first parameter specifies the directory from which files should be
recursively included.
@ -683,8 +754,10 @@ in these subdirectories to the name of the subdirectory.
Example:
include_zones "etc", "zones.d", "*.conf"
include_zones "puppet", "puppet-zones"
```
include_zones "etc", "zones.d", "*.conf"
include_zones "puppet", "puppet-zones"
```
The first parameter specifies a tag name for this directive. Each `include_zones`
invocation should use a unique tag name. When copying the zones' configuration
@ -708,14 +781,18 @@ Functions can be defined using the `function` keyword.
Example:
function multiply(a, b) {
```
function multiply(a, b) {
return a * b
}
}
```
When encountering the `return` keyword further execution of the function is terminated and
the specified value is supplied to the caller of the function:
log(multiply(3, 5))
```
log(multiply(3, 5))
```
In this example the `multiply` function we declared earlier is invoked with two arguments (3 and 5).
The function computes the product of those arguments and makes the result available to the
@ -727,16 +804,20 @@ Functions which do not have a `return` statement have their return value set to
last expression which was performed by the function. For example, we could have also written our
`multiply` function like this:
function multiply(a, b) {
```
function multiply(a, b) {
a * b
}
}
```
Anonymous functions can be created by omitting the name in the function definition. The
resulting function object can be used like any other value:
var fn = function() { 3 }
```
var fn = function() { 3 }
fn() /* Returns 3 */
fn() /* Returns 3 */
```
## Lambda Expressions <a id="lambdas"></a>
@ -744,20 +825,26 @@ Functions can also be declared using the alternative lambda syntax.
Example:
f = (x) => x * x
```
f = (x) => x * x
```
Multiple statements can be used by putting the function body into braces:
f = (x) => {
```
f = (x) => {
log("Lambda called")
x * x
}
}
```
Just like with ordinary functions the return value is the value of the last statement.
For lambdas which take exactly one argument the braces around the arguments can be omitted:
f = x => x * x
```
f = x => x * x
```
## Abbreviated Lambda Syntax <a id="nullary-lambdas"></a>
@ -765,7 +852,9 @@ Lambdas which take no arguments can also be written using the abbreviated lambda
Example:
f = {{ 3 }}
```
f = {{ 3 }}
```
This creates a new function which returns the value 3.
@ -781,10 +870,12 @@ already exists there:
The local scope contains variables which only exist during the invocation of the current function,
object or apply statement. Local variables can be declared using the `var` keyword:
function multiply(a, b) {
```
function multiply(a, b) {
var temp = a * b
return temp
}
}
```
Each time the `multiply` function is invoked a new `temp` variable is used which is in no way
related to previous invocations of the function.
@ -795,16 +886,19 @@ the `this` scope is used.
The `this` scope refers to the current object which the function or object/apply statement
operates on.
object Host "localhost" {
```
object Host "localhost" {
check_interval = 5m
}
}
```
In this example the `this` scope refers to the "localhost" object. The `check_interval` attribute
is set for this particular host.
You can explicitly access the `this` scope using the `this` keyword:
object Host "localhost" {
```
object Host "localhost" {
var check_interval = 5m
/* This explicitly specifies that the attribute should be set
@ -812,13 +906,14 @@ You can explicitly access the `this` scope using the `this` keyword:
* local variable `check_interval` would have been modified instead.
*/
this.check_interval = 1m
}
}
```
Similarly the keywords `locals` and `globals` are available to access the local and global scope.
Functions also have a `this` scope. However unlike for object/apply statements the `this` scope for
a function is set to whichever object was used to invoke the function. Here's an example:
```
hm = {
h_word = null
@ -829,6 +924,7 @@ a function is set to whichever object was used to invoke the function. Here's an
/* Let's invoke the init() function */
hm.init("hello")
```
We're using `hm.init` to invoke the function which causes the value of `hm` to become the `this`
scope for this function call.
@ -840,22 +936,26 @@ outside of their scope (except for global variables).
In order to access variables which are defined in the outer scope the `use` keyword can be used:
function MakeHelloFunction(name) {
```
function MakeHelloFunction(name) {
return function() use(name) {
log("Hello, " + name)
}
}
}
```
In this case a new variable `name` is created inside the inner function's scope which has the
value of the `name` function argument.
Alternatively a different value for the inner variable can be specified:
function MakeHelloFunction(name) {
```
function MakeHelloFunction(name) {
return function() use (greeting = "Hello, " + name) {
log(greeting)
}
}
}
```
## Conditional Statements <a id="conditional-statements"></a>
@ -864,26 +964,30 @@ construct can be used to accomplish this.
Example:
a = 3
```
a = 3
if (a < 5) {
if (a < 5) {
a *= 7
} else if (a > 10) {
} else if (a > 10) {
a *= 5
} else {
} else {
a *= 2
}
}
```
An if/else construct can also be used in place of any other value. The value of an if/else statement
is the value of the last statement which was evaluated for the branch which was taken:
a = if (true) {
```
a = if (true) {
log("Taking the 'true' branch")
7 * 3
} else {
} else {
log("Taking the 'false' branch")
9
}
}
```
This example prints the log message "Taking the 'true' branch" and the `a` variable is set to 21 (7 * 3).
@ -896,12 +1000,14 @@ This is repeated until the condition is no longer true.
Example:
var num = 5
```
var num = 5
while (num > 5) {
while (num > 5) {
log("Test")
num -= 1
}
}
```
The `continue` and `break` keywords can be used to control how the loop is executed: The `continue` keyword
skips over the remaining expressions for the loop body and begins the next loop evaluation. The `break` keyword
@ -913,22 +1019,26 @@ The `for` statement can be used to iterate over arrays and dictionaries.
Example:
var list = [ "a", "b", "c" ]
```
var list = [ "a", "b", "c" ]
for (var item in list) {
for (var item in list) {
log("Item: " + item)
}
}
```
The loop body is evaluated once for each item in the array. The variable `item` is declared as a local
variable just as if the `var` keyword had been used.
Iterating over dictionaries can be accomplished in a similar manner:
var dict = { a = 3, b = 7 }
```
var dict = { a = 3, b = 7 }
for (var key => var value in dict) {
for (var key => var value in dict) {
log("Key: " + key + ", Value: " + value)
}
}
```
The `continue` and `break` keywords can be used to control how the loop is executed: The `continue` keyword
skips over the remaining expressions for the loop body and begins the next loop evaluation. The `break` keyword
@ -943,15 +1053,19 @@ In order to create a new value of a specific type constructor calls may be used.
Example:
var pd = PerfdataValue()
pd.label = "test"
pd.value = 10
```
var pd = PerfdataValue()
pd.label = "test"
pd.value = 10
```
You can also try to convert an existing value to another type by specifying it as an argument for the constructor call.
Example:
var s = String(3) /* Sets s to "3". */
```
var s = String(3) /* Sets s to "3". */
```
## Throwing Exceptions <a id="throw"></a>
@ -960,7 +1074,9 @@ using the `throw` keyword.
Example:
throw "An error occurred."
```
throw "An error occurred."
```
## Handling Exceptions <a id="try-except"></a>
@ -969,13 +1085,15 @@ Exceptions can be handled using the `try` and `except` keywords. When an excepti
Example:
try {
```
try {
throw "Test"
log("This statement won't get executed.")
} except {
} except {
log("An error occurred in the try clause.")
}
}
```
## Breakpoints <a id="breakpoints"></a>
@ -987,7 +1105,9 @@ By default breakpoints have no effect unless Icinga is started with the `--scrip
All values have a static type. The `typeof` function can be used to determine the type of a value:
typeof(3) /* Returns an object which represents the type for numbers */
```
typeof(3) /* Returns an object which represents the type for numbers */
```
The following built-in types are available:
@ -1006,14 +1126,18 @@ e.g. Host, Service, CheckCommand, etc.
Each type has an associated type object which describes the type's semantics. These
type objects are made available using global variables which match the type's name:
/* This logs 'true' */
log(typeof(3) == Number)
```
/* This logs 'true' */
log(typeof(3) == Number)
```
The type object's `prototype` property can be used to find out which methods a certain type
supports:
/* This returns: ["contains","find","len","lower","replace","reverse","split","substr","to_string","trim","upper"] */
keys(String.prototype)
```
/* This returns: ["contains","find","len","lower","replace","reverse","split","substr","to_string","trim","upper"] */
keys(String.prototype)
```
Additional documentation on type methods is available in the
[library reference](18-library-reference.md#library-reference).
@ -1025,70 +1149,76 @@ The location of the currently executing script can be obtained using the
Example:
log("Hello from '" + current_filename + "' in line " + current_line)
```
log("Hello from '" + current_filename + "' in line " + current_line)
```
## Reserved Keywords <a id="reserved-keywords"></a>
These keywords are reserved and must not be used as constants or custom attributes.
object
template
include
include_recursive
include_zones
library
null
true
false
const
var
this
globals
locals
use
default
ignore_on_error
current_filename
current_line
apply
to
where
import
assign
ignore
function
return
break
continue
for
if
else
while
throw
try
except
in
using
namespace
```
object
template
include
include_recursive
include_zones
library
null
true
false
const
var
this
globals
locals
use
default
ignore_on_error
current_filename
current_line
apply
to
where
import
assign
ignore
function
return
break
continue
for
if
else
while
throw
try
except
in
using
namespace
```
You can escape reserved keywords using the `@` character. The following example
tries to set `vars.include` which references a reserved keyword and generates
an error:
[2014-09-15 17:24:00 +0200] critical/config: Location:
/etc/icinga2/conf.d/hosts/localhost.conf(13): vars.sla = "24x7"
/etc/icinga2/conf.d/hosts/localhost.conf(14):
/etc/icinga2/conf.d/hosts/localhost.conf(15): vars.include = "some cmdb export field"
```
[2014-09-15 17:24:00 +0200] critical/config: Location:
/etc/icinga2/conf.d/hosts/localhost.conf(13): vars.sla = "24x7"
/etc/icinga2/conf.d/hosts/localhost.conf(14):
/etc/icinga2/conf.d/hosts/localhost.conf(15): vars.include = "some cmdb export field"
^^^^^^^
/etc/icinga2/conf.d/hosts/localhost.conf(16): }
/etc/icinga2/conf.d/hosts/localhost.conf(17):
/etc/icinga2/conf.d/hosts/localhost.conf(16): }
/etc/icinga2/conf.d/hosts/localhost.conf(17):
Config error: in /etc/icinga2/conf.d/hosts/localhost.conf: 15:8-15:14: syntax error, unexpected include (T_INCLUDE), expecting T_IDENTIFIER
[2014-09-15 17:24:00 +0200] critical/config: 1 errors, 0 warnings.
Config error: in /etc/icinga2/conf.d/hosts/localhost.conf: 15:8-15:14: syntax error, unexpected include (T_INCLUDE), expecting T_IDENTIFIER
[2014-09-15 17:24:00 +0200] critical/config: 1 errors, 0 warnings.
```
You can escape the `include` keyword by prefixing it with an additional `@` character:
object Host "localhost" {
```
object Host "localhost" {
import "generic-host"
address = "127.0.0.1"
@ -1098,4 +1228,5 @@ You can escape the `include` keyword by prefixing it with an additional `@` char
vars.sla = "24x7"
vars.@include = "some cmdb export field"
}
}
```

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,9 @@
You can run the Icinga 2 daemon with the `-X` (`--script-debugger`)
parameter to enable the script debugger:
# icinga2 daemon -X
```
# icinga2 daemon -X
```
When an exception occurs or the [debugger](17-language-reference.md#breakpoints)
keyword is encountered in a user script, Icinga 2 launches a console that
@ -11,7 +13,9 @@ allows the user to debug the script.
You can also attach the script debugger to the [configuration validation](11-cli-commands.md#config-validation):
# icinga2 daemon -C -X
```
# icinga2 daemon -C -X
```
Here is a list of common errors which can be diagnosed with the script debugger:
@ -24,48 +28,54 @@ The following example illustrates the problem of a service [apply rule](03-monit
which expects a dictionary value for `config`, but the host custom attribute only
provides a string value:
object Host "script-debugger-host" {
```
object Host "script-debugger-host" {
check_command = "icinga"
vars.http_vhosts["example.org"] = "192.168.1.100" // a string value
}
}
apply Service for (http_vhost => config in host.vars.http_vhosts) {
apply Service for (http_vhost => config in host.vars.http_vhosts) {
import "generic-service"
vars += config // expects a dictionary
check_command = "http"
}
}
```
The error message on config validation will warn about the wrong value type,
but does not provide any context which objects are affected.
Enable the script debugger and run the config validation:
# icinga2 daemon -C -X
```
# icinga2 daemon -C -X
Breakpoint encountered in /etc/icinga2/conf.d/services.conf: 59:67-65:1
Exception: Error: Error while evaluating expression: Cannot convert value of type 'String' to an object.
Location:
/etc/icinga2/conf.d/services.conf(62): check_command = "http"
/etc/icinga2/conf.d/services.conf(63):
/etc/icinga2/conf.d/services.conf(64): vars += config
Breakpoint encountered in /etc/icinga2/conf.d/services.conf: 59:67-65:1
Exception: Error: Error while evaluating expression: Cannot convert value of type 'String' to an object.
Location:
/etc/icinga2/conf.d/services.conf(62): check_command = "http"
/etc/icinga2/conf.d/services.conf(63):
/etc/icinga2/conf.d/services.conf(64): vars += config
^^^^^^^^^^^^^^
/etc/icinga2/conf.d/services.conf(65): }
/etc/icinga2/conf.d/services.conf(66):
You can inspect expressions (such as variables) by entering them at the prompt.
To leave the debugger and continue the program use "$continue".
<1> =>
/etc/icinga2/conf.d/services.conf(65): }
/etc/icinga2/conf.d/services.conf(66):
You can inspect expressions (such as variables) by entering them at the prompt.
To leave the debugger and continue the program use "$continue".
<1> =>
```
You can print the variables `vars` and `config` to get an idea about
their values:
<1> => vars
null
<2> => config
"192.168.1.100"
<3> =>
```
<1> => vars
null
<2> => config
"192.168.1.100"
<3> =>
```
The `vars` attribute has to be a dictionary. Trying to set this attribute to a string caused
the error in our configuration example.
@ -73,10 +83,12 @@ the error in our configuration example.
In order to determine the name of the host where the value of the `config` variable came from
you can inspect attributes of the service object:
<3> => host_name
"script-debugger-host-01"
<4> => name
"http"
```
<3> => host_name
"script-debugger-host-01"
<4> => name
"http"
```
Additionally you can view the service object attributes by printing the value of `this`.
@ -84,7 +96,8 @@ Additionally you can view the service object attributes by printing the value of
In order to halt execution in a script you can use the `debugger` keyword:
object Host "script-debugger-host-02" {
```
object Host "script-debugger-host-02" {
check_command = "dummy"
check_interval = 5s
@ -93,19 +106,21 @@ In order to halt execution in a script you can use the `debugger` keyword:
debugger
return text
}}
}
}
```
Icinga 2 will spawn a debugger console every time the function is executed:
# icinga2 daemon -X
...
Breakpoint encountered in /etc/icinga2/tests/script-debugger.conf: 7:5-7:12
You can inspect expressions (such as variables) by entering them at the prompt.
To leave the debugger and continue the program use "$continue".
<1> => text
"Hello from script-debugger-host-02"
<2> => $continue
```
# icinga2 daemon -X
...
Breakpoint encountered in /etc/icinga2/tests/script-debugger.conf: 7:5-7:12
You can inspect expressions (such as variables) by entering them at the prompt.
To leave the debugger and continue the program use "$continue".
<1> => text
"Hello from script-debugger-host-02"
<2> => $continue
```
## Debugging API Filters <a id="script-debugger-api-filters"></a>

View File

@ -213,32 +213,34 @@ If you want to delete all breakpoints, use `d` and select `yes`.
Breakpoint Example:
(gdb) b __cxa_throw
(gdb) r
(gdb) up
....
(gdb) up
#11 0x00007ffff7cbf9ff in icinga::Utility::GlobRecursive(icinga::String const&, icinga::String const&, boost::function<void (icinga::String const&)> const&, int) (path=..., pattern=..., callback=..., type=1)
```
(gdb) b __cxa_throw
(gdb) r
(gdb) up
....
(gdb) up
#11 0x00007ffff7cbf9ff in icinga::Utility::GlobRecursive(icinga::String const&, icinga::String const&, boost::function<void (icinga::String const&)> const&, int) (path=..., pattern=..., callback=..., type=1)
at /home/michi/coding/icinga/icinga2/lib/base/utility.cpp:609
609 callback(cpath);
(gdb) l
604
605 #endif /* _WIN32 */
606
607 std::sort(files.begin(), files.end());
608 BOOST_FOREACH(const String& cpath, files) {
609 callback(cpath);
610 }
611
612 std::sort(dirs.begin(), dirs.end());
613 BOOST_FOREACH(const String& cpath, dirs) {
(gdb) p files
$3 = std::vector of length 11, capacity 16 = {{static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/agent.conf"}, {static NPos = 18446744073709551615,
609 callback(cpath);
(gdb) l
604
605 #endif /* _WIN32 */
606
607 std::sort(files.begin(), files.end());
608 BOOST_FOREACH(const String& cpath, files) {
609 callback(cpath);
610 }
611
612 std::sort(dirs.begin(), dirs.end());
613 BOOST_FOREACH(const String& cpath, dirs) {
(gdb) p files
$3 = std::vector of length 11, capacity 16 = {{static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/agent.conf"}, {static NPos = 18446744073709551615,
m_Data = "/etc/icinga2/conf.d/commands.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/downtimes.conf"}, {static NPos = 18446744073709551615,
m_Data = "/etc/icinga2/conf.d/groups.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/notifications.conf"}, {static NPos = 18446744073709551615,
m_Data = "/etc/icinga2/conf.d/satellite.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/services.conf"}, {static NPos = 18446744073709551615,
m_Data = "/etc/icinga2/conf.d/templates.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/test.conf"}, {static NPos = 18446744073709551615,
m_Data = "/etc/icinga2/conf.d/timeperiods.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/users.conf"}}
```
### Core Dump <a id="development-debug-core-dump"></a>
@ -1580,66 +1582,76 @@ Please check `appveyor.yml` for instructions.
Install the `boost`, `python` and `icinga2` pretty printers. Absolute paths are required,
so please make sure to update the installation paths accordingly (`pwd`).
$ mkdir -p ~/.gdb_printers && cd ~/.gdb_printers
```
$ mkdir -p ~/.gdb_printers && cd ~/.gdb_printers
```
Boost Pretty Printers compatible with Python 3:
$ git clone https://github.com/mateidavid/Boost-Pretty-Printer.git && cd Boost-Pretty-Printer
$ git checkout python-3
$ pwd
/home/michi/.gdb_printers/Boost-Pretty-Printer
```
$ git clone https://github.com/mateidavid/Boost-Pretty-Printer.git && cd Boost-Pretty-Printer
$ git checkout python-3
$ pwd
/home/michi/.gdb_printers/Boost-Pretty-Printer
```
Python Pretty Printers:
$ cd ~/.gdb_printers
$ svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python
```
$ cd ~/.gdb_printers
$ svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python
```
Icinga 2 Pretty Printers:
$ mkdir -p ~/.gdb_printers/icinga2 && cd ~/.gdb_printers/icinga2
$ wget https://raw.githubusercontent.com/Icinga/icinga2/master/tools/debug/gdb/icingadbg.py
```
$ mkdir -p ~/.gdb_printers/icinga2 && cd ~/.gdb_printers/icinga2
$ wget https://raw.githubusercontent.com/Icinga/icinga2/master/tools/debug/gdb/icingadbg.py
```
Now you'll need to modify/setup your `~/.gdbinit` configuration file.
You can download the one from Icinga 2 and modify all paths.
Example on Fedora 22:
$ wget https://raw.githubusercontent.com/Icinga/icinga2/master/tools/debug/gdb/gdbinit -O ~/.gdbinit
$ vim ~/.gdbinit
```
$ wget https://raw.githubusercontent.com/Icinga/icinga2/master/tools/debug/gdb/gdbinit -O ~/.gdbinit
$ vim ~/.gdbinit
set print pretty on
set print pretty on
python
import sys
sys.path.insert(0, '/home/michi/.gdb_printers/icinga2')
from icingadbg import register_icinga_printers
register_icinga_printers()
end
python
import sys
sys.path.insert(0, '/home/michi/.gdb_printers/icinga2')
from icingadbg import register_icinga_printers
register_icinga_printers()
end
python
import sys
sys.path.insert(0, '/home/michi/.gdb_printers/python')
from libstdcxx.v6.printers import register_libstdcxx_printers
try:
python
import sys
sys.path.insert(0, '/home/michi/.gdb_printers/python')
from libstdcxx.v6.printers import register_libstdcxx_printers
try:
register_libstdcxx_printers(None)
except:
except:
pass
end
python
import sys
sys.path.insert(0, '/home/michi/.gdb_printers/Boost-Pretty-Printer')
import boost_print
boost_print.register_printers()
end
end
python
import sys
sys.path.insert(0, '/home/michi/.gdb_printers/Boost-Pretty-Printer')
import boost_print
boost_print.register_printers()
end
```
If you are getting the following error when running gdb, the `libstdcxx`
printers are already preloaded in your environment and you can remove
the duplicate import in your `~/.gdbinit` file.
RuntimeError: pretty-printer already registered: libstdc++-v6
```
RuntimeError: pretty-printer already registered: libstdc++-v6
```
## Development Tests <a id="development-tests"></a>

View File

@ -18,16 +18,18 @@ There are two ways of installing the SELinux Policy for Icinga 2 on Enterprise L
If the system runs in enforcing mode and you encounter problems you can set Icinga 2's domain to permissive mode.
# sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
```
# sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
```
You can change the configured mode by editing `/etc/selinux/config` and the current mode by executing `setenforce 0`.
@ -35,13 +37,17 @@ You can change the configured mode by editing `/etc/selinux/config` and the curr
Simply add the `icinga2-selinux` package to your installation.
# yum install icinga2-selinux
```
# yum install icinga2-selinux
```
Ensure that the `icinga2` process is running in its own `icinga2_t` domain after installing the policy package:
# systemctl restart icinga2.service
# ps -eZ | grep icinga2
system_u:system_r:icinga2_t:s0 2825 ? 00:00:00 icinga2
```
# systemctl restart icinga2.service
# ps -eZ | grep icinga2
system_u:system_r:icinga2_t:s0 2825 ? 00:00:00 icinga2
```
#### Manual installation <a id="selinux-policy-installation-manual"></a>
@ -49,24 +55,32 @@ This section describes the installation to support development and testing. It a
As a prerequisite install the `git`, `selinux-policy-devel` and `audit` packages. Enable and start the audit daemon afterwards:
# yum install git selinux-policy-devel audit
# systemctl enable auditd.service
# systemctl start auditd.service
```
# yum install git selinux-policy-devel audit
# systemctl enable auditd.service
# systemctl start auditd.service
```
After that clone the icinga2 git repository:
# git clone https://github.com/icinga/icinga2
```
# git clone https://github.com/icinga/icinga2
```
To create and install the policy package run the installation script which also labels the resources. (The script assumes Icinga 2 was started once after system startup, the labeling of the port will only happen once and fail later on.)
# cd tools/selinux/
# ./icinga.sh
```
# cd tools/selinux/
# ./icinga.sh
```
After that restart Icinga 2 and verify it running in its own domain `icinga2_t`.
# systemctl restart icinga2.service
# ps -eZ | grep icinga2
system_u:system_r:icinga2_t:s0 2825 ? 00:00:00 icinga2
```
# systemctl restart icinga2.service
# ps -eZ | grep icinga2
system_u:system_r:icinga2_t:s0 2825 ? 00:00:00 icinga2
```
### General <a id="selinux-policy-general"></a>
@ -130,23 +144,29 @@ Make sure to report the bugs in the policy afterwards.
Download and install a plugin, for example check_mysql_health.
# wget https://labs.consol.de/download/shinken-nagios-plugins/check_mysql_health-2.1.9.2.tar.gz
# tar xvzf check_mysql_health-2.1.9.2.tar.gz
# cd check_mysql_health-2.1.9.2/
# ./configure --libexecdir /usr/lib64/nagios/plugins
# make
# make install
```
# wget https://labs.consol.de/download/shinken-nagios-plugins/check_mysql_health-2.1.9.2.tar.gz
# tar xvzf check_mysql_health-2.1.9.2.tar.gz
# cd check_mysql_health-2.1.9.2/
# ./configure --libexecdir /usr/lib64/nagios/plugins
# make
# make install
```
It is labeled `nagios_unconfined_plugins_exec_t` by default, so it runs without restrictions.
# ls -lZ /usr/lib64/nagios/plugins/check_mysql_health
-rwxr-xr-x. root root system_u:object_r:nagios_unconfined_plugin_exec_t:s0 /usr/lib64/nagios/plugins/check_mysql_health
```
# ls -lZ /usr/lib64/nagios/plugins/check_mysql_health
-rwxr-xr-x. root root system_u:object_r:nagios_unconfined_plugin_exec_t:s0 /usr/lib64/nagios/plugins/check_mysql_health
```
In this case the plugin is monitoring a service, so it should be labeled `nagios_services_plugin_exec_t` to restrict its permissions.
# chcon -t nagios_services_plugin_exec_t /usr/lib64/nagios/plugins/check_mysql_health
# ls -lZ /usr/lib64/nagios/plugins/check_mysql_health
-rwxr-xr-x. root root system_u:object_r:nagios_services_plugin_exec_t:s0 /usr/lib64/nagios/plugins/check_mysql_health
```
# chcon -t nagios_services_plugin_exec_t /usr/lib64/nagios/plugins/check_mysql_health
# ls -lZ /usr/lib64/nagios/plugins/check_mysql_health
-rwxr-xr-x. root root system_u:object_r:nagios_services_plugin_exec_t:s0 /usr/lib64/nagios/plugins/check_mysql_health
```
The plugin still runs fine but if someone changes the script to do weird stuff it will fail to do so.
@ -156,25 +176,29 @@ You are running graphite on a different port than `2003` and want `icinga2` to c
Change the port value for the graphite feature according to your graphite installation before enabling it.
# cat /etc/icinga2/features-enabled/graphite.conf
/**
```
# cat /etc/icinga2/features-enabled/graphite.conf
/**
* The GraphiteWriter type writes check result metrics and
* performance data to a graphite tcp socket.
*/
library "perfdata"
library "perfdata"
object GraphiteWriter "graphite" {
object GraphiteWriter "graphite" {
//host = "127.0.0.1"
//port = 2003
port = 2004
}
# icinga2 feature enable graphite
}
# icinga2 feature enable graphite
```
Before you restart the icinga2 service allow it to connect to all ports by enabling the boolean `icinga2_can_connect_all` (now and permanent).
# setsebool icinga2_can_connect_all true
# setsebool -P icinga2_can_connect_all true
```
# setsebool icinga2_can_connect_all true
# setsebool -P icinga2_can_connect_all true
```
If you restart the daemon now it will successfully connect to graphite.
@ -209,49 +233,63 @@ this user. This is completly optional!
Start by adding the Icinga 2 administrator role `icinga2adm_r` to the administrative SELinux user `staff_u`.
# semanage user -m -R "staff_r sysadm_r system_r unconfined_r icinga2adm_r" staff_u
```
# semanage user -m -R "staff_r sysadm_r system_r unconfined_r icinga2adm_r" staff_u
```
Confine your user login and create a sudo rule.
# semanage login -a dirk -s staff_u
# echo "dirk ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/dirk
```
# semanage login -a dirk -s staff_u
# echo "dirk ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/dirk
```
Login to the system using ssh and verify your id.
$ id -Z
staff_u:staff_r:staff_t:s0-s0:c0.c1023
```
$ id -Z
staff_u:staff_r:staff_t:s0-s0:c0.c1023
```
Try to execute some commands as root using sudo.
$ sudo id -Z
staff_u:staff_r:staff_t:s0-s0:c0.c1023
$ sudo vi /etc/icinga2/icinga2.conf
"/etc/icinga2/icinga2.conf" [Permission Denied]
$ sudo cat /var/log/icinga2/icinga2.log
cat: /var/log/icinga2/icinga2.log: Keine Berechtigung
$ sudo systemctl reload icinga2.service
Failed to get D-Bus connection: No connection to service manager.
```
$ sudo id -Z
staff_u:staff_r:staff_t:s0-s0:c0.c1023
$ sudo vi /etc/icinga2/icinga2.conf
"/etc/icinga2/icinga2.conf" [Permission Denied]
$ sudo cat /var/log/icinga2/icinga2.log
cat: /var/log/icinga2/icinga2.log: Keine Berechtigung
$ sudo systemctl reload icinga2.service
Failed to get D-Bus connection: No connection to service manager.
```
Those commands fail because you only switch to root but do not change your SELinux role. Try again but tell sudo also to switch the SELinux role and type.
$ sudo -r icinga2adm_r -t icinga2adm_t id -Z
staff_u:icinga2adm_r:icinga2adm_t:s0-s0:c0.c1023
$ sudo -r icinga2adm_r -t icinga2adm_t vi /etc/icinga2/icinga2.conf
"/etc/icinga2/icinga2.conf"
$ sudo -r icinga2adm_r -t icinga2adm_t cat /var/log/icinga2/icinga2.log
[2015-03-26 20:48:14 +0000] information/DynamicObject: Dumping program state to file '/var/lib/icinga2/icinga2.state'
$ sudo -r icinga2adm_r -t icinga2adm_t systemctl reload icinga2.service
```
$ sudo -r icinga2adm_r -t icinga2adm_t id -Z
staff_u:icinga2adm_r:icinga2adm_t:s0-s0:c0.c1023
$ sudo -r icinga2adm_r -t icinga2adm_t vi /etc/icinga2/icinga2.conf
"/etc/icinga2/icinga2.conf"
$ sudo -r icinga2adm_r -t icinga2adm_t cat /var/log/icinga2/icinga2.log
[2015-03-26 20:48:14 +0000] information/DynamicObject: Dumping program state to file '/var/lib/icinga2/icinga2.state'
$ sudo -r icinga2adm_r -t icinga2adm_t systemctl reload icinga2.service
```
Now the commands will work, but you have always to remember to add the arguments, so change the sudo rule to set it by default.
# echo "dirk ALL=(ALL) ROLE=icinga2adm_r TYPE=icinga2adm_t NOPASSWD: ALL" > /etc/sudoers.d/dirk
```
# echo "dirk ALL=(ALL) ROLE=icinga2adm_r TYPE=icinga2adm_t NOPASSWD: ALL" > /etc/sudoers.d/dirk
```
Now try the commands again without providing the role and type and they will work, but if you try to read apache logs or restart apache for example it will still fail.
$ sudo cat /var/log/httpd/error_log
/bin/cat: /var/log/httpd/error_log: Keine Berechtigung
$ sudo systemctl reload httpd.service
Failed to issue method call: Access denied
```
$ sudo cat /var/log/httpd/error_log
/bin/cat: /var/log/httpd/error_log: Keine Berechtigung
$ sudo systemctl reload httpd.service
Failed to issue method call: Access denied
```
## Bugreports <a id="selinux-bugreports"></a>

File diff suppressed because it is too large Load Diff