Skip to content
Commits on Source (4)
......@@ -36,3 +36,4 @@ Michael Insel <mcktr55@gmail.com> <michael@insel.email>
Marianne Spiller <github@spiller.me>
Robin O'Brien <robin@labs.epiuse.com> <robinjohnobrien@gmail.com>
<noah.hilverling@icinga.com> <noah@hilverling.com>
<pe-git@hindenburgring.com> <pe-icinga2@hindenburgring.com>
......@@ -50,6 +50,7 @@ Dolf Schimmel <dolf@transip.nl>
Edgar Fuß <ef@math.uni-bonn.de>
Eduard Güldner <eduard.gueldner@gmail.com>
Edvin Seferovic <edvin@seferovic.net>
Elias Ohm <eohm@novomind.com>
Eric Lippmann <eric.lippmann@icinga.com>
Evgeni Golov <evgeni@golov.de>
Ewoud Kohl van Wijngaarden <ewoud@kohlvanwijngaarden.nl>
......@@ -106,6 +107,7 @@ Leon Stringer <leon@priorsvle.com>
Louis Sautier <sautier.louis@gmail.com>
Luca Lesinigo <luca@lm-net.it>
Lucas Fairchild-Madar <lucas.madar@gmail.com>
Luiz Amaral <luiz.amaral@innogames.com>
Magnus Bäck <magnus@noun.se>
Malte Rabenseifner <mail@malte-rabenseifner.de>
Manuel Reiter <reiter@csc.uni-frankfurt.de>
......@@ -147,7 +149,6 @@ Paul Richards <paul@minimoo.org>
Pawel Szafer <pszafer@gmail.com>
Per von Zweigbergk <pvz@itassistans.se>
Peter Eckel <pe-git@hindenburgring.com>
Peter Eckel <pe-icinga2@hindenburgring.com>
Petr Ruzicka <petr.ruzicka@gmail.com>
Phil Hutchinson <phil@volumedia.co.uk>
Philipp Dallig <philipp.dallig@gmail.com>
......@@ -212,6 +213,7 @@ gitmopp <mopp@gmx.net>
jre3brg <jorge.rebelo@pt.bosch.com>
krishna <gskrishna44@gmail.com>
lihan <tclh123@gmail.com>
marxin <mliska@suse.cz>
mocruz <mocruz@theworkshop.com>
noobahoi <20069422+noobahoi@users.noreply.github.com>
pv2b <pvz@pvz.pp.se>
......
# Icinga 2.x CHANGELOG
## 2.10.5 (2019-05-23)
[Issues and PRs](https://github.com/Icinga/icinga2/milestone/81?closed=1)
### Bugfixes
* Core
* Fix crashes with logrotate signals #6737 (thanks Elias Ohm)
* API
* Fix crashes and problems with permission filters from recent Namespace introduction #6785 (thanks Elias Ohm) #6874 (backported from 2.11)
* Reduce log spam with locked connections (real fix is the network stack rewrite in 2.11) #6877
* Cluster
* Fix problems with replay log rotation and storage #6932 (thanks Peter Eckel)
* IDO DB
* Fix that reload shutdown deactivates hosts and hostgroups (introduced in 2.9) #7157
* Documentation
* Improve the [REST API](https://icinga.com/docs/icinga2/latest/doc/12-icinga2-api/) chapter: Unix timestamp handling, filters, unify POST requests with filters in the body
* Better layout for the [features](https://icinga.com/docs/icinga2/latest/doc/14-features/) chapter, specifically metrics and events
* Split [object types](https://icinga.com/docs/icinga2/latest/doc/09-object-types/) into monitoring, runtime, features
* Add technical concepts for [cluster messages](https://icinga.com/docs/icinga2/latest/doc/19-technical-concepts/#json-rpc-message-api)
## 2.10.4 (2019-03-19)
### Notes
......
Version: 2.10.4
Version: 2.10.5
Revision: 1
icinga2 (2.10.5-1~exp1) experimental; urgency=medium
* Team upload.
* New upstream release.
-- Bas Couwenberg <sebastic@debian.org> Fri, 24 May 2019 05:53:45 +0200
icinga2 (2.10.4-1~exp1) experimental; urgency=medium
* Team upload.
......
......@@ -37,6 +37,11 @@ Community repositories:
Packages for distributions other than the ones listed above may also be
available. Please contact your distribution packagers.
> **Note**
>
> Windows is only supported for agent installations. Please refer
> to the [distributed monitoring chapter](06-distributed-monitoring.md#distributed-monitoring-setup-client-windows).
### Package Repositories <a id="package-repositories"></a>
You need to add the Icinga repository to your package management configuration.
......@@ -47,7 +52,8 @@ The following commands must be executed with `root` permissions unless noted oth
Debian:
```
apt-get -y install apt-transport-https
apt-get update
apt-get -y install apt-transport-https wget gnupg
wget -O - https://packages.icinga.com/icinga.key | apt-key add -
......@@ -63,7 +69,8 @@ apt-get update
Ubuntu:
```
apt-get -y install apt-transport-https
apt-get update
apt-get -y install apt-transport-https wget gnupg
wget -O - https://packages.icinga.com/icinga.key | apt-key add -
......@@ -79,7 +86,8 @@ apt-get update
Raspbian:
```
apt-get -y install apt-transport-https
apt-get update
apt-get -y install apt-transport-https wget gnupg
wget -O - https://packages.icinga.com/icinga.key | apt-key add -
......@@ -92,6 +100,18 @@ DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \
apt-get update
```
##### Debian Backports Repository <a id="package-repositories-debian-backports"></a>
Debian Stretch:
```
DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \
echo "deb https://deb.debian.org/debian ${DIST}-backports main" > \
/etc/apt/sources.list.d/${DIST}-backports.list
apt-get update
```
#### RHEL/CentOS/Fedora Repositories <a id="package-repositories-rhel-centos-fedora"></a>
RHEL/CentOS 7:
......@@ -100,7 +120,7 @@ RHEL/CentOS 7:
yum install https://packages.icinga.com/epel/icinga-rpm-release-7-latest.noarch.rpm
```
RHEL/CentOS 6:
RHEL/CentOS 6 x64:
```
yum install https://packages.icinga.com/epel/icinga-rpm-release-6-latest.noarch.rpm
......@@ -112,7 +132,7 @@ Fedora 29:
dnf install https://packages.icinga.com/fedora/icinga-rpm-release-29-latest.noarch.rpm
```
#### RHEL/CentOS EPEL Repository <a id="package-repositories-rhel-epel"></a>
##### RHEL/CentOS EPEL Repository <a id="package-repositories-rhel-epel"></a>
The packages for RHEL/CentOS depend on other packages which are distributed
as part of the [EPEL repository](https://fedoraproject.org/wiki/EPEL).
......@@ -143,15 +163,6 @@ zypper ar https://packages.icinga.com/SUSE/ICINGA-release.repo
zypper ref
```
SLES 11:
```
rpm --import https://packages.icinga.com/icinga.key
zypper ar https://packages.icinga.com/SUSE/ICINGA-release-11.repo
zypper ref
```
openSUSE:
```
......@@ -161,16 +172,6 @@ zypper ar https://packages.icinga.com/openSUSE/ICINGA-release.repo
zypper ref
```
#### SLES Security Repository <a id="package-repositories-sles-security"></a>
The packages for SLES 11 depend on the `openssl1` package which is distributed
as part of the [SLES 11 Security Module](https://www.suse.com/communities/conversations/introducing-the-suse-linux-enterprise-11-security-module/).
#### SLES 12 SDK <a id="package-sles-sdk"></a>
Icinga 2 requires the `libboost_chrono1_54_0` package from the `SLES 12 SDK` repository. Refer to the SUSE Enterprise
Linux documentation for further information.
#### Alpine Linux Repositories <a id="package-repositories-alpine"></a>
Alpine Linux:
......@@ -329,7 +330,7 @@ yum install nagios-plugins-all
```
The packages for RHEL/CentOS depend on other packages which are distributed
as part of the [EPEL repository](#package-repositories-rhel-epel).
as part of the [EPEL repository](02-getting-started.md#package-repositories-rhel-epel).
Fedora:
......@@ -928,7 +929,7 @@ SUSE:
```
zypper install apache2
chkconfig on
chkconfig apache2 on
service apache2 start
```
......
......@@ -2424,14 +2424,19 @@ states = [ OK, Critical, Unknown ]
> If the parent service object changes into the `Warning` state, this
> dependency will fail and render all child objects (hosts or services) unreachable.
You can determine the child's reachability by querying the `is_reachable` attribute
in for example [DB IDO](24-appendix.md#schema-db-ido-extensions).
You can determine the child's reachability by querying the `last_reachable` attribute
via the [REST API](12-icinga2-api.md#icinga2-api).
> **Note**
>
> Reachability calculation depends on fresh and processed check results. If dependencies
> disable checks for child objects, this won't work reliably.
### Implicit Dependencies for Services on Host <a id="dependencies-implicit-host-service"></a>
Icinga 2 automatically adds an implicit dependency for services on their host. That way
service notifications are suppressed when a host is `DOWN` or `UNREACHABLE`. This dependency
does not overwrite other dependencies and implicitely sets `disable_notifications = true` and
does not overwrite other dependencies and implicitly sets `disable_notifications = true` and
`states = [ Up ]` for all service objects.
Service checks are still executed. If you want to prevent them from happening, you can
......
This diff is collapsed.
......@@ -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
/**
* This file defines global constants which can be used in
* the other configuration files. At a minimum the
* PluginDir constant should be defined.
*/
# 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,30 +68,31 @@ 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" {
command = [ CustomPluginDir + "/check_snmp_int.pl" ]
arguments = {
"-H" = "$snmp_address$"
"-C" = "$snmp_community$"
"-p" = "$snmp_port$"
"-2" = {
set_if = "$snmp_v2$"
}
"-n" = "$snmp_interface$"
"-f" = {
set_if = "$snmp_perf$"
}
"-w" = "$snmp_warn$"
"-c" = "$snmp_crit$"
}
vars.snmp_v2 = true
vars.snmp_perf = true
vars.snmp_warn = "300,400"
vars.snmp_crit = "0,600"
```
object CheckCommand "my-snmp-int" {
command = [ CustomPluginDir + "/check_snmp_int.pl" ]
arguments = {
"-H" = "$snmp_address$"
"-C" = "$snmp_community$"
"-p" = "$snmp_port$"
"-2" = {
set_if = "$snmp_v2$"
}
"-n" = "$snmp_interface$"
"-f" = {
set_if = "$snmp_perf$"
}
"-w" = "$snmp_warn$"
"-c" = "$snmp_crit$"
}
vars.snmp_v2 = true
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
if (<timeout_reached>) then
print "UNKNOWN - Timeout (...) reached | 'time'=30.0
endif
# 5. main method
<execute and fetch data>
if (<threshold_critical_condition>) then
print "CRITICAL - ... | 'time'=0.1 'myperfdatavalue'=5.0
exit(2)
else if (<threshold_warning_condition>) then
print "WARNING - ... | 'time'=0.1 'myperfdatavalue'=3.0
exit(1)
else
print "OK - ... | 'time'=0.2 'myperfdatavalue'=1.0
endif
```
# 1. include optional libraries
# 2. global variables
# 3. helper functions and/or classes
# 4. define timeout condition
if (<timeout_reached>) then
print "UNKNOWN - Timeout (...) reached | 'time'=30.0
endif
# 5. main method
<execute and fetch data>
if (<threshold_critical_condition>) then
print "CRITICAL - ... | 'time'=0.1 'myperfdatavalue'=5.0
exit(2)
else if (<threshold_warning_condition>) then
print "WARNING - ... | 'time'=0.1 'myperfdatavalue'=3.0
exit(1)
else
print "OK - ... | 'time'=0.2 'myperfdatavalue'=1.0
endif
```
There are various plugin libraries available which will help
with plugin execution and output formatting too, for example
......
This diff is collapsed.
......@@ -15,15 +15,17 @@ 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" {
import "generic-service"
```
apply Service "uptime" {
import "generic-service"
check_command = "snmp"
vars.snmp_oid = "1.3.6.1.2.1.1.3.0"
vars.snmp_miblist = "DISMAN-EVENT-MIB"
check_command = "snmp"
vars.snmp_oid = "1.3.6.1.2.1.1.3.0"
vars.snmp_miblist = "DISMAN-EVENT-MIB"
assign where host.vars.snmp_community != ""
}
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,23 +39,25 @@ 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" {
import "by_ssh"
```
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%"
}
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" {
import "generic-service"
object Service "swap" {
import "generic-service"
host_name = "remote-ssh-host"
host_name = "remote-ssh-host"
check_command = "by_ssh_swap"
check_command = "by_ssh_swap"
vars.by_ssh_logname = "icinga"
}
vars.by_ssh_logname = "icinga"
}
```
## NSClient++ <a id="agent-based-checks-nsclient"></a>
......@@ -67,18 +71,20 @@ Icinga 2 provides the [nscp check command](10-icinga-template-library.md#plugin-
Example:
object Service "disk" {
import "generic-service"
```
object Service "disk" {
import "generic-service"
host_name = "remote-windows-host"
host_name = "remote-windows-host"
check_command = "nscp"
check_command = "nscp"
vars.nscp_variable = "USEDDISKSPACE"
vars.nscp_params = "c"
vars.nscp_warn = 70
vars.nscp_crit = 80
}
vars.nscp_variable = "USEDDISKSPACE"
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" {
import "generic-service"
```
object Service "users" {
import "generic-service"
host_name = "remote-nrpe-host"
host_name = "remote-nrpe-host"
check_command = "nrpe"
vars.nrpe_command = "check_users"
}
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,19 +154,23 @@ attribute which expects either a single value or an array of values.
Example:
object Service "nrpe-disk-/" {
import "generic-service"
```
object Service "nrpe-disk-/" {
import "generic-service"
host_name = "remote-nrpe-host"
host_name = "remote-nrpe-host"
check_command = "nrpe"
vars.nrpe_command = "check_disk"
vars.nrpe_arguments = [ "20%", "10%", "/" ]
}
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,105 +230,111 @@ match your Icinga convention.
Add an `EventCommand` configuration object for the passive service auto reset event.
object EventCommand "coldstart-reset-event" {
command = [ ConfigDir + "/conf.d/custom/scripts/coldstart_reset_event.sh" ]
```
object EventCommand "coldstart-reset-event" {
command = [ ConfigDir + "/conf.d/custom/scripts/coldstart_reset_event.sh" ]
arguments = {
"-i" = "$service.state_id$"
"-n" = "$host.name$"
"-s" = "$service.name$"
}
}
arguments = {
"-i" = "$service.state_id$"
"-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
SERVICE_STATE_ID=""
HOST_NAME=""
SERVICE_NAME=""
show_help()
{
cat <<-EOF
Usage: ${0##*/} [-h] -n HOST_NAME -s SERVICE_NAME
Writes a coldstart reset event to the Icinga command pipe.
-h Display this help and exit.
-i SERVICE_STATE_ID The associated service state id.
-n HOST_NAME The associated host name.
-s SERVICE_NAME The associated service name.
EOF
}
while getopts "hi:n:s:" opt; do
case "$opt" in
h)
show_help
exit 0
;;
i)
SERVICE_STATE_ID=$OPTARG
;;
n)
HOST_NAME=$OPTARG
;;
s)
SERVICE_NAME=$OPTARG
;;
'?')
show_help
exit 0
;;
esac
done
if [ -z "$SERVICE_STATE_ID" ]; then
show_help
printf "\n Error: -i required.\n"
exit 1
fi
if [ -z "$HOST_NAME" ]; then
show_help
printf "\n Error: -n required.\n"
exit 1
fi
if [ -z "$SERVICE_NAME" ]; then
show_help
printf "\n Error: -s required.\n"
exit 1
fi
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
```
#!/bin/bash
SERVICE_STATE_ID=""
HOST_NAME=""
SERVICE_NAME=""
show_help()
{
cat <<-EOF
Usage: ${0##*/} [-h] -n HOST_NAME -s SERVICE_NAME
Writes a coldstart reset event to the Icinga command pipe.
-h Display this help and exit.
-i SERVICE_STATE_ID The associated service state id.
-n HOST_NAME The associated host name.
-s SERVICE_NAME The associated service name.
EOF
}
while getopts "hi:n:s:" opt; do
case "$opt" in
h)
show_help
exit 0
;;
i)
SERVICE_STATE_ID=$OPTARG
;;
n)
HOST_NAME=$OPTARG
;;
s)
SERVICE_NAME=$OPTARG
;;
'?')
show_help
exit 0
;;
esac
done
if [ -z "$SERVICE_STATE_ID" ]; then
show_help
printf "\n Error: -i required.\n"
exit 1
fi
if [ -z "$HOST_NAME" ]; then
show_help
printf "\n Error: -n required.\n"
exit 1
fi
if [ -z "$SERVICE_NAME" ]; then
show_help
printf "\n Error: -s required.\n"
exit 1
fi
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
```
Finally create the `Service` and assign it:
apply Service "Coldstart" {
import "generic-service-custom"
```
apply Service "Coldstart" {
import "generic-service-custom"
check_command = "dummy"
event_command = "coldstart-reset-event"
check_command = "dummy"
event_command = "coldstart-reset-event"
enable_notifications = 1
enable_active_checks = 0
enable_passive_checks = 1
enable_flapping = 0
volatile = 1
enable_perfdata = 0
enable_notifications = 1
enable_active_checks = 0
enable_passive_checks = 1
enable_flapping = 0
volatile = 1
enable_perfdata = 0
vars.dummy_state = 0
vars.dummy_text = "Manual reset."
vars.dummy_state = 0
vars.dummy_text = "Manual reset."
vars.sla = "24x7"
vars.sla = "24x7"
assign where (host.vars.os == "Linux" || host.vars.os == "Windows")
}
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,22 +365,24 @@ 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" {
import "generic-service-custom"
host_name = "host.domain.com"
check_command = "dummy"
enable_notifications = 1
enable_active_checks = 1
enable_passive_checks = 1
enable_flapping = 0
volatile = 1
max_check_attempts = 1
check_interval = 87000
enable_perfdata = 0
vars.sla = "24x7"
vars.dummy_state = 2
vars.dummy_text = "No passive check result received."
}
```
object Service "Backup" {
import "generic-service-custom"
host_name = "host.domain.com"
check_command = "dummy"
enable_notifications = 1
enable_active_checks = 1
enable_passive_checks = 1
enable_flapping = 0
volatile = 1
max_check_attempts = 1
check_interval = 87000
enable_perfdata = 0
vars.sla = "24x7"
vars.dummy_state = 2
vars.dummy_text = "No passive check result received."
}
```
\ No newline at end of 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,65 +583,69 @@ In addition to that you can optionally define the `ssl` attribute which enables
Host definition:
object Host "webserver01" {
import "generic-host"
address = "192.168.56.200"
vars.os = "Linux"
vars.webserver = {
instance["status"] = {
address = "192.168.56.201"
port = "80"
url = "/status"
}
instance["tomcat"] = {
address = "192.168.56.202"
port = "8080"
}
instance["icingaweb2"] = {
address = "192.168.56.210"
port = "443"
url = "/icingaweb2"
ssl = true
}
}
```
object Host "webserver01" {
import "generic-host"
address = "192.168.56.200"
vars.os = "Linux"
vars.webserver = {
instance["status"] = {
address = "192.168.56.201"
port = "80"
url = "/status"
}
instance["tomcat"] = {
address = "192.168.56.202"
port = "8080"
}
instance["icingaweb2"] = {
address = "192.168.56.210"
port = "443"
url = "/icingaweb2"
ssl = true
}
}
}
```
Service apply for definitions:
apply Service "webserver_ping" for (instance => config in host.vars.webserver.instance) {
display_name = "webserver_" + instance
check_command = "ping4"
```
apply Service "webserver_ping" for (instance => config in host.vars.webserver.instance) {
display_name = "webserver_" + instance
check_command = "ping4"
vars.ping_address = config.address
vars.ping_address = config.address
assign where host.vars.webserver.instance
}
assign where 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"
apply Service "webserver_port" for (instance => config in host.vars.webserver.instance) {
display_name = "webserver_" + instance + "_" + config.port
check_command = "tcp"
vars.tcp_address = config.address
vars.tcp_port = config.port
vars.tcp_address = config.address
vars.tcp_port = config.port
assign where host.vars.webserver.instance
}
assign where 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"
apply Service "webserver_url" for (instance => config in host.vars.webserver.instance) {
display_name = "webserver_" + instance + "_" + config.url
check_command = "http"
vars.http_address = config.address
vars.http_port = config.port
vars.http_uri = config.url
vars.http_address = config.address
vars.http_port = config.port
vars.http_uri = config.url
if (config.ssl) {
vars.http_ssl = config.ssl
}
if (config.ssl) {
vars.http_ssl = config.ssl
}
assign where config.url != ""
}
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,25 +764,27 @@ 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) {
return function() use (group, group_value, non_group_value) {
if (group in host.groups) {
return group_value
} else {
return 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
} else {
return non_group_value
}
}
}
apply Service "ping4" {
import "generic-service"
check_command = "ping4"
apply Service "ping4" {
import "generic-service"
check_command = "ping4"
vars.ping_wrta = group_specific_value("slow-lan", 300, 100)
vars.ping_crta = group_specific_value("slow-lan", 500, 200)
vars.ping_wrta = group_specific_value("slow-lan", 300, 100)
vars.ping_crta = group_specific_value("slow-lan", 500, 200)
assign where true
}
assign where true
}
```
#### Use Functions in Assign Where Expressions <a id="use-functions-assign-where"></a>
......@@ -790,36 +800,37 @@ 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" {
vars.printer_type = "Lexmark"
}
object Host "myprinter" {
import "generic-host"
import "lexmark-printer-host"
```
template Host "lexmark-printer-host" {
vars.printer_type = "Lexmark"
}
address = "192.168.1.1"
}
object Host "myprinter" {
import "generic-host"
import "lexmark-printer-host"
/* 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)) {
return true
}
}
address = "192.168.1.1"
}
/* nothing matched */
return false
/* 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)) {
return true
}
}
object HostGroup "printers-lexmark" {
display_name = "Lexmark Printers"
/* call the global function and pass the arguments */
assign where check_host_templates(host, "lexmark*")
}
/* nothing matched */
return false
}
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,43 +839,46 @@ 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" {
check_command = "dummy"
vars.vars_app["ABC"] = { app_type = "ABAP" }
}
object Host "appserver02" {
check_command = "dummy"
vars.vars_app["DEF"] = { app_type = "ABAP" }
}
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
}
```
object Host "appserver01" {
check_command = "dummy"
vars.vars_app["ABC"] = { app_type = "ABAP" }
}
object Host "appserver02" {
check_command = "dummy"
vars.vars_app["DEF"] = { app_type = "ABAP" }
}
/* iterate over the vars_app dictionary */
for (key => val in host.vars.vars_app) {
/* if the value is a dictionary and if contains the app_type being the requested type */
if (typeof(val) == Dictionary && val.app_type == type) {
return true
}
}
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
}
/* nothing matched */
return false
/* iterate over the vars_app dictionary */
for (key => val in host.vars.vars_app) {
/* if the value is a dictionary and if contains the app_type being the requested type */
if (typeof(val) == Dictionary && val.app_type == type) {
return true
}
}
object HostGroup "ABAP-app-server" {
assign where check_app_type(host, "ABAP")
}
/* nothing matched */
return false
}
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" {
check_command = "check_compellent"
vars.compellent["disks"] = {
file = "/var/lib/check_compellent/san_disks.0.json",
checks = ["disks"]
}
}
```
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,20 +910,22 @@ 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" {
command = [ "/usr/bin/check_compellent" ]
arguments = {
"--disks" = {
set_if = {{
var host_vars = host.vars
log(host_vars)
var compel = host_vars.compellent
log(compel)
compel.contains("disks")
}}
}
}
```
object CheckCommand "check_compellent" {
command = [ "/usr/bin/check_compellent" ]
arguments = {
"--disks" = {
set_if = {{
var host_vars = host.vars
log(host_vars)
var compel = host_vars.compellent
log(compel)
compel.contains("disks")
}}
}
}
}
```
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,35 +933,38 @@ 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
if(len(srv_vars) > 0) {
if (typeof(srv_vars.compellent) == Dictionary) {
return srv_vars.compellent.contains("disks")
} else {
log(LogInformationen, "checkcommand set_if", "custom attribute compellent_checks is not a dictionary, ignoring it.")
return false
}
} else {
log(LogWarning, "checkcommand set_if", "empty custom attributes")
return false
}
}}
```
"--disks" = {
set_if = {{
var srv_vars = service.vars
if(len(srv_vars) > 0) {
if (typeof(srv_vars.compellent) == Dictionary) {
return srv_vars.compellent.contains("disks")
} else {
log(LogInformationen, "checkcommand set_if", "custom attribute compellent_checks is not a dictionary, ignoring it.")
return false
}
} else {
log(LogWarning, "checkcommand set_if", "empty custom attributes")
return false
}
}}
}
```
#### 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" {
assign where user.name == "short-dummy"
}
object UserGroup "short-dummy-group" {
assign where user.name == "short-dummy"
}
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
}
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,25 +1003,26 @@ returned.
You can omit the `log()` calls, they only help debugging.
object NotificationCommand "mail-host-notification-test" {
command = {{
log("command as function")
var mailscript = "mail-host-notification-long.sh"
if (notification.vars.short) {
mailscript = "mail-host-notification-short.sh"
}
log("Running command")
log(mailscript)
var cmd = [ ConfigDir + "/scripts/" + mailscript ]
log(LogCritical, "me", cmd)
return cmd
}}
env = {
}
```
object NotificationCommand "mail-host-notification-test" {
command = {{
log("command as function")
var mailscript = "mail-host-notification-long.sh"
if (notification.vars.short) {
mailscript = "mail-host-notification-short.sh"
}
log("Running command")
log(mailscript)
var cmd = [ ConfigDir + "/scripts/" + mailscript ]
log(LogCritical, "me", cmd)
return cmd
}}
env = {
}
}
```
### Access Object Attributes at Runtime <a id="access-object-attributes-at-runtime"></a>
......
This diff is collapsed.
......@@ -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.
......
......@@ -22,7 +22,7 @@ Supported commands:
* api setup (setup for API)
* ca list (lists all certificate signing requests)
* ca sign (signs an outstanding certificate request)
* console (Icinga console)
* console (Icinga debug console)
* daemon (starts Icinga 2)
* feature disable (disables specified feature)
* feature enable (enables specified feature)
......@@ -272,7 +272,7 @@ are required for executing config expressions and auto-completion.
> **Note**
>
> The debug console does not currently support SSL certificate verification.
> The debug console does not currently support TLS certificate verification.
>
> Runtime modifications are not validated and might cause the Icinga 2
> daemon to crash or behave in an unexpected way. Use these runtime changes
......
This diff is collapsed.
......@@ -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 @@ It’s 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).
......@@ -56,16 +60,20 @@ Use your distribution's package manager to install the `pnp4nagios` package.
If you're planning to use it, configure it to use the
[bulk mode with npcd and npcdmod](https://docs.pnp4nagios.org/pnp-0.6/modes#bulk_mode_with_npcd_and_npcdmod)
in combination with Icinga 2's [PerfdataWriter](14-features.md#performance-data). NPCD collects the performance
in combination with Icinga 2's [PerfdataWriter](14-features.md#writing-performance-data-files). NPCD collects the performance
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" {
action_url = "/pnp4nagios/graph?host=$HOSTNAME$"
}
```
template Host "pnp-hst" {
action_url = "/pnp4nagios/graph?host=$HOSTNAME$"
}
template Service "pnp-svc" {
action_url = "/pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$"
}
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" {
action_url = "/pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$"
vars.pnp_check_arg1 = ""
}
template Service "pnp-svc" {
action_url = "/pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$"
vars.pnp_check_arg1 = ""
}
apply Service "nrpe-check" {
import "pnp-svc"
check_command = nrpe
vars.nrpe_command = "check_disk"
apply Service "nrpe-check" {
import "pnp-svc"
check_command = nrpe
vars.nrpe_command = "check_disk"
vars.pnp_check_arg1 = "!$nrpe_command$"
}
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
......
This diff is collapsed.
......@@ -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
......@@ -857,8 +861,6 @@ Fetch the `ca.crt` file from the client node and compare it to your master's `ca
# diff -ur /var/lib/icinga2/certs/ca.crt test-client-ca.crt
```
On SLES11 you'll need to use the `openssl1` command instead of `openssl`.
<!--
### Certificate Signing <a id="troubleshooting-certificate-signing"></a>
-->
......
......@@ -9,6 +9,13 @@ follow the instructions for v2.7 too.
## Upgrading to v2.10 <a id="upgrading-to-2-10"></a>
### 2.10.5 Packages <a id="upgrading-to-2-10-5-packages"></a>
EOL distributions where no packages are available with 2.10.5:
* SLES 11
* Ubuntu 14 LTS
### Path Constant Changes <a id="upgrading-to-2-10-path-constant-changes"></a>
During package upgrades you may see a notice that the configuration
......