summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2019-05-24 05:38:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2019-05-24 05:41:44 +0000
commitc9b9fa0235545b3583187ab6c60e5bc285d0cf09 (patch)
tree0f492cb3765b0a25db31fe3561430021ad577516
parentReleasing progress-linux version 2.10.4-1~exp1~progress5+u1. (diff)
downloadicinga2-c9b9fa0235545b3583187ab6c60e5bc285d0cf09.tar.xz
icinga2-c9b9fa0235545b3583187ab6c60e5bc285d0cf09.zip
Merging upstream version 2.10.5.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--.mailmap1
-rw-r--r--AUTHORS4
-rw-r--r--CHANGELOG.md22
-rw-r--r--VERSION2
-rw-r--r--doc/02-getting-started.md53
-rw-r--r--doc/03-monitoring-basics.md11
-rw-r--r--doc/04-configuring-icinga-2.md505
-rw-r--r--doc/05-service-monitoring.md119
-rw-r--r--doc/06-distributed-monitoring.md1496
-rw-r--r--doc/07-agent-based-monitoring.md358
-rw-r--r--doc/08-advanced-topics.md396
-rw-r--r--doc/09-object-types.md1719
-rw-r--r--doc/10-icinga-template-library.md4
-rw-r--r--doc/11-cli-commands.md4
-rw-r--r--doc/12-icinga2-api.md2276
-rw-r--r--doc/13-addons.md68
-rw-r--r--doc/14-features.md413
-rw-r--r--doc/15-troubleshooting.md18
-rw-r--r--doc/16-upgrading-icinga-2.md7
-rw-r--r--doc/17-language-reference.md697
-rw-r--r--doc/18-library-reference.md1053
-rw-r--r--doc/19-technical-concepts.md893
-rw-r--r--doc/20-script-debugger.md121
-rw-r--r--doc/21-development.md142
-rw-r--r--doc/22-selinux.md184
-rw-r--r--doc/23-migrating-from-icinga-1x.md998
-rw-r--r--lib/base/application.cpp8
-rw-r--r--lib/base/application.hpp1
-rw-r--r--lib/base/namespace.cpp18
-rw-r--r--lib/base/serializer.cpp4
-rw-r--r--lib/base/streamlogger.cpp10
-rw-r--r--lib/base/timer.cpp6
-rw-r--r--lib/base/timer.hpp2
-rw-r--r--lib/cli/nodesetupcommand.cpp17
-rw-r--r--lib/cli/nodewizardcommand.cpp14
-rw-r--r--lib/db_ido/dbconnection.cpp26
-rw-r--r--lib/icinga/timeperiod.cpp3
-rw-r--r--lib/remote/apilistener.cpp57
-rw-r--r--lib/remote/eventqueue.cpp3
-rw-r--r--lib/remote/filterutility.cpp13
-rw-r--r--lib/remote/httpserverconnection.cpp2
-rw-r--r--test/base-timer.cpp2
42 files changed, 7178 insertions, 4572 deletions
diff --git a/.mailmap b/.mailmap
index bdb19d3..2db3df0 100644
--- a/.mailmap
+++ b/.mailmap
@@ -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>
diff --git a/AUTHORS b/AUTHORS
index 9110940..a54157b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3f5757c..acb7118 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,27 @@
# 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
diff --git a/VERSION b/VERSION
index 60a57e2..d13d363 100644
--- a/VERSION
+++ b/VERSION
@@ -1,2 +1,2 @@
-Version: 2.10.4
+Version: 2.10.5
Revision: 1
diff --git a/doc/02-getting-started.md b/doc/02-getting-started.md
index df2634c..e594995 100644
--- a/doc/02-getting-started.md
+++ b/doc/02-getting-started.md
@@ -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
```
diff --git a/doc/03-monitoring-basics.md b/doc/03-monitoring-basics.md
index 3c44b67..3c80535 100644
--- a/doc/03-monitoring-basics.md
+++ b/doc/03-monitoring-basics.md
@@ -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
diff --git a/doc/04-configuring-icinga-2.md b/doc/04-configuring-icinga-2.md
index 4d8770c..434b8c9 100644
--- a/doc/04-configuring-icinga-2.md
+++ b/doc/04-configuring-icinga-2.md
@@ -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>
-
- /**
- * 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>
-
- /**
- * 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 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 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"
+```
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,57 +298,59 @@ 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`).
- */
-
- /*
- * 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 {
- /* Import the default host template defined in `templates.conf`. */
- import "generic-host"
-
- /* Specify the address attributes for checks e.g. `ssh` or `http`. */
- address = "127.0.0.1"
- address6 = "::1"
-
- /* Set custom attribute `os` for hostgroup assignment in `groups.conf`. */
- vars.os = "Linux"
-
- /* Define http vhost attributes for service apply rules in `services.conf`. */
- vars.http_vhosts["http"] = {
- http_uri = "/"
- }
- /* Uncomment if you've sucessfully installed Icinga Web 2. */
- //vars.http_vhosts["Icinga Web 2"] = {
- // http_uri = "/icingaweb2"
- //}
-
- /* Define disks and attributes for service apply rules in `services.conf`. */
- vars.disks["disk"] = {
- /* No parameters. */
- }
- vars.disks["disk /"] = {
- disk_partitions = "/"
- }
-
- /* Define notification mail attributes for notification apply rules in `notifications.conf`. */
- vars.notification["mail"] = {
- /* The UserGroup `icingaadmins` is defined in `users.conf`. */
- groups = [ "icingaadmins" ]
- }
- }
+```
+/*
+* 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 {
+ /* Import the default host template defined in `templates.conf`. */
+ import "generic-host"
+
+ /* Specify the address attributes for checks e.g. `ssh` or `http`. */
+ address = "127.0.0.1"
+ address6 = "::1"
+
+ /* Set custom attribute `os` for hostgroup assignment in `groups.conf`. */
+ vars.os = "Linux"
+
+ /* Define http vhost attributes for service apply rules in `services.conf`. */
+ vars.http_vhosts["http"] = {
+ http_uri = "/"
+ }
+ /* Uncomment if you've sucessfully installed Icinga Web 2. */
+ //vars.http_vhosts["Icinga Web 2"] = {
+ // http_uri = "/icingaweb2"
+ //}
+
+ /* Define disks and attributes for service apply rules in `services.conf`. */
+ vars.disks["disk"] = {
+ /* No parameters. */
+ }
+ vars.disks["disk /"] = {
+ disk_partitions = "/"
+ }
+
+ /* Define notification mail attributes for notification apply rules in `notifications.conf`. */
+ vars.notification["mail"] = {
+ /* 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" {
- import "generic-service"
+```
+apply Service "ssh" {
+ import "generic-service"
- check_command = "ssh"
+ check_command = "ssh"
- assign where host.address && host.vars.os == "Linux"
- }
+ 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,16 +447,17 @@ 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. */
- }
- vars.disks["disk /"] = {
- disk_partition = "/"
- }
- ...
-
+```
+...
+ /* Define disks and attributes for service apply rules in `services.conf`. */
+ vars.disks["disk"] = {
+ /* No parameters. */
+ }
+ 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) {
- import "generic-service"
+```
+apply Service for (disk => config in host.vars.disks) {
+ import "generic-service"
- check_command = "disk"
+ check_command = "disk"
- vars += config
- }
+ 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" {
- import "generic-user"
-
- display_name = "Icinga 2 Admin"
- groups = [ "icingaadmins" ]
+```
+object User "icingaadmin" {
+ import "generic-user"
- email = "icinga@localhost"
- }
+ display_name = "Icinga 2 Admin"
+ groups = [ "icingaadmins" ]
- object UserGroup "icingaadmins" {
- display_name = "Icinga 2 Admin Group"
- }
+ email = "icinga@localhost"
+}
+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 {
- import "mail-host-notification"
+```
+apply Notification "mail-icingaadmin" to Host {
+ import "mail-host-notification"
- user_groups = host.vars.notification.mail.groups
- users = host.vars.notification.mail.users
+ user_groups = host.vars.notification.mail.groups
+ users = host.vars.notification.mail.users
- assign where host.vars.notification.mail
- }
+ assign where host.vars.notification.mail
+}
- apply Notification "mail-icingaadmin" to Service {
- import "mail-service-notification"
+apply Notification "mail-icingaadmin" to Service {
+ import "mail-service-notification"
- user_groups = host.vars.notification.mail.groups
- users = host.vars.notification.mail.users
+ user_groups = host.vars.notification.mail.groups
+ users = host.vars.notification.mail.users
- assign where host.vars.notification.mail
- }
+ 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,85 +589,91 @@ 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" {
- display_name = "Linux Servers"
+```
+object HostGroup "linux-servers" {
+ display_name = "Linux Servers"
- assign where host.vars.os == "Linux"
- }
+ assign where host.vars.os == "Linux"
+}
- object HostGroup "windows-servers" {
- display_name = "Windows Servers"
+object HostGroup "windows-servers" {
+ display_name = "Windows Servers"
- assign where host.vars.os == "Windows"
- }
+ 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" {
- display_name = "Ping Checks"
+```
+object ServiceGroup "ping" {
+ display_name = "Ping Checks"
- assign where match("ping*", service.name)
- }
+ assign where match("ping*", service.name)
+}
- object ServiceGroup "http" {
- display_name = "HTTP Checks"
+object ServiceGroup "http" {
+ display_name = "HTTP Checks"
- assign where match("http*", service.check_command)
- }
+ assign where match("http*", service.check_command)
+}
- object ServiceGroup "disk" {
- display_name = "Disk Checks"
-
- assign where match("disk*", service.check_command)
- }
+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" {
- max_check_attempts = 5
- check_interval = 1m
- retry_interval = 30s
+```
+template Host "generic-host" {
+ max_check_attempts = 5
+ check_interval = 1m
+ retry_interval = 30s
- check_command = "hostalive"
- }
+ check_command = "hostalive"
+}
- template Service "generic-service" {
- max_check_attempts = 3
- check_interval = 1m
- retry_interval = 30s
- }
+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" {
+ command = "mail-host-notification"
- template Notification "mail-host-notification" {
- command = "mail-host-notification"
-
- states = [ Up, Down ]
- types = [ Problem, Acknowledgement, Recovery, Custom,
- FlappingStart, FlappingEnd,
- DowntimeStart, DowntimeEnd, DowntimeRemoved ]
+ states = [ Up, Down ]
+ types = [ Problem, Acknowledgement, Recovery, Custom,
+ FlappingStart, FlappingEnd,
+ DowntimeStart, DowntimeEnd, DowntimeRemoved ]
- period = "24x7"
- }
+ period = "24x7"
+}
- template Notification "mail-service-notification" {
- command = "mail-service-notification"
+template Notification "mail-service-notification" {
+ command = "mail-service-notification"
- states = [ OK, Warning, Critical, Unknown ]
- types = [ Problem, Acknowledgement, Recovery, Custom,
- FlappingStart, FlappingEnd,
- DowntimeStart, DowntimeEnd, DowntimeRemoved ]
+ states = [ OK, Warning, Critical, Unknown ]
+ types = [ Problem, Acknowledgement, Recovery, Custom,
+ FlappingStart, FlappingEnd,
+ DowntimeStart, DowntimeEnd, DowntimeRemoved ]
- period = "24x7"
- }
+ period = "24x7"
+}
+```
More details on `Notification` object attributes can be found [here](09-object-types.md#objecttype-notification).
@@ -658,23 +688,24 @@ 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 {
- author = "icingaadmin"
- comment = "Scheduled downtime for backup"
-
- ranges = {
- monday = service.vars.backup_downtime
- tuesday = service.vars.backup_downtime
- wednesday = service.vars.backup_downtime
- thursday = service.vars.backup_downtime
- friday = service.vars.backup_downtime
- saturday = service.vars.backup_downtime
- sunday = service.vars.backup_downtime
- }
-
- assign where service.vars.backup_downtime != ""
- }
-
+```
+apply ScheduledDowntime "backup-downtime" to Service {
+ author = "icingaadmin"
+ comment = "Scheduled downtime for backup"
+
+ ranges = {
+ monday = service.vars.backup_downtime
+ tuesday = service.vars.backup_downtime
+ wednesday = service.vars.backup_downtime
+ thursday = service.vars.backup_downtime
+ friday = service.vars.backup_downtime
+ saturday = service.vars.backup_downtime
+ sunday = service.vars.backup_downtime
+ }
+
+ assign where service.vars.backup_downtime != ""
+}
+```
#### timeperiods.conf <a id="timeperiods-conf"></a>
diff --git a/doc/05-service-monitoring.md b/doc/05-service-monitoring.md
index b8e7375..aeeeb48 100644
--- a/doc/05-service-monitoring.md
+++ b/doc/05-service-monitoring.md
@@ -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
diff --git a/doc/06-distributed-monitoring.md b/doc/06-distributed-monitoring.md
index 48cfd1b..2a4f07d 100644
--- a/doc/06-distributed-monitoring.md
+++ b/doc/06-distributed-monitoring.md
@@ -52,19 +52,21 @@ Zones depend on a parent-child relationship in order to trust each other.
Have a look at this example for the `satellite` zones which have the `master` zone as a parent zone:
- object Zone "master" {
- //...
- }
+```
+object Zone "master" {
+ //...
+}
- object Zone "satellite region 1" {
- parent = "master"
- //...
- }
+object Zone "satellite region 1" {
+ parent = "master"
+ //...
+}
- object Zone "satellite region 2" {
- parent = "master"
- //...
- }
+object Zone "satellite region 2" {
+ parent = "master"
+ //...
+}
+```
There are certain limitations for child zones, e.g. their members are not allowed
to send configuration commands to the parent zone members. Vice versa, the
@@ -83,22 +85,24 @@ Nodes which are a member of a zone are so-called [Endpoint](09-object-types.md#o
Here is an example configuration for two endpoints in different zones:
- object Endpoint "icinga2-master1.localdomain" {
- host = "192.168.56.101"
- }
+```
+object Endpoint "icinga2-master1.localdomain" {
+ host = "192.168.56.101"
+}
- object Endpoint "icinga2-satellite1.localdomain" {
- host = "192.168.56.105"
- }
+object Endpoint "icinga2-satellite1.localdomain" {
+ host = "192.168.56.105"
+}
- object Zone "master" {
- endpoints = [ "icinga2-master1.localdomain" ]
- }
+object Zone "master" {
+ endpoints = [ "icinga2-master1.localdomain" ]
+}
- object Zone "satellite" {
- endpoints = [ "icinga2-satellite1.localdomain" ]
- parent = "master"
- }
+object Zone "satellite" {
+ endpoints = [ "icinga2-satellite1.localdomain" ]
+ parent = "master"
+}
+```
All endpoints in the same zone work as high-availability setup. For
example, if you have two nodes in the `master` zone, they will load-balance the check execution.
@@ -135,7 +139,9 @@ and `accept_config` can be configured here.
In order to use the `api` feature you need to enable it and restart Icinga 2.
- icinga2 feature enable api
+```
+icinga2 feature enable api
+```
## Conventions <a id="distributed-monitoring-conventions"></a>
@@ -359,24 +365,28 @@ Required information:
The following example shows how to generate a ticket on the master node `icinga2-master1.localdomain` for the client `icinga2-client1.localdomain`:
- [root@icinga2-master1.localdomain /]# icinga2 pki ticket --cn icinga2-client1.localdomain
+```
+[root@icinga2-master1.localdomain /]# icinga2 pki ticket --cn icinga2-client1.localdomain
+```
Querying the [Icinga 2 API](12-icinga2-api.md#icinga2-api) on the master requires an [ApiUser](12-icinga2-api.md#icinga2-api-authentication)
object with at least the `actions/generate-ticket` permission.
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/conf.d/api-users.conf
+```
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/conf.d/api-users.conf
- object ApiUser "client-pki-ticket" {
- password = "bea11beb7b810ea9ce6ea" //change this
- permissions = [ "actions/generate-ticket" ]
- }
+object ApiUser "client-pki-ticket" {
+ password = "bea11beb7b810ea9ce6ea" //change this
+ permissions = [ "actions/generate-ticket" ]
+}
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
Retrieve the ticket on the master node `icinga2-master1.localdomain` with `curl`, for example:
- [root@icinga2-master1.localdomain /]# curl -k -s -u client-pki-ticket:bea11beb7b810ea9ce6ea -H 'Accept: application/json' \
- -X POST 'https://localhost:5665/v1/actions/generate-ticket' -d '{ "cn": "icinga2-client1.localdomain" }'
+ [root@icinga2-master1.localdomain /]# curl -k -s -u client-pki-ticket:bea11beb7b810ea9ce6ea -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/generate-ticket' -d '{ "cn": "icinga2-client1.localdomain" }'
+```
Store that ticket number for the satellite/client setup below.
@@ -428,6 +438,11 @@ and pass its fingerprint as argument.
information/cli: Signed certificate for 'CN = icinga2-client2.localdomain'.
```
+> **Note**
+>
+> `ca list` cannot be used as historical inventory. Certificate
+> signing requests older than 1 week are automatically deleted.
+
## Client/Satellite Setup <a id="distributed-monitoring-setup-satellite-client"></a>
This section describes the setup of a satellite and/or client connected to an
@@ -448,8 +463,10 @@ The next step is to run the `node wizard` CLI command.
In this example we're generating a ticket on the master node `icinga2-master1.localdomain` for the client `icinga2-client1.localdomain`:
- [root@icinga2-master1.localdomain /]# icinga2 pki ticket --cn icinga2-client1.localdomain
- 4f75d2ecd253575fe9180938ebff7cbca262f96e
+```
+[root@icinga2-master1.localdomain /]# icinga2 pki ticket --cn icinga2-client1.localdomain
+4f75d2ecd253575fe9180938ebff7cbca262f96e
+```
Note: You don't need this step if you have chosen to use [On-Demand CSR Signing](06-distributed-monitoring.md#distributed-monitoring-setup-on-demand-csr-signing).
@@ -923,15 +940,17 @@ Include the endpoint and zone configuration on **both** nodes in the file `/etc/
The endpoint configuration could look like this, for example:
- [root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
- object Endpoint "icinga2-master1.localdomain" {
- host = "192.168.56.101"
- }
+object Endpoint "icinga2-master1.localdomain" {
+ host = "192.168.56.101"
+}
- object Endpoint "icinga2-client1.localdomain" {
- host = "192.168.56.111"
- }
+object Endpoint "icinga2-client1.localdomain" {
+ host = "192.168.56.111"
+}
+```
Next, you need to define two zones. There is no naming convention, best practice is to either use `master`, `satellite`/`client-fqdn` or to choose region names for example `Europe`, `USA` and `Asia`, though.
@@ -940,17 +959,19 @@ is to use the client's FQDN for all object names.
The `master` zone is a parent of the `icinga2-client1.localdomain` zone:
- [root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
- object Zone "master" {
- endpoints = [ "icinga2-master1.localdomain" ] //array with endpoint names
- }
+object Zone "master" {
+ endpoints = [ "icinga2-master1.localdomain" ] //array with endpoint names
+}
- object Zone "icinga2-client1.localdomain" {
- endpoints = [ "icinga2-client1.localdomain" ]
+object Zone "icinga2-client1.localdomain" {
+ endpoints = [ "icinga2-client1.localdomain" ]
- parent = "master" //establish zone hierarchy
- }
+ parent = "master" //establish zone hierarchy
+}
+```
You don't need any local configuration on the client except for
CheckCommand definitions which can be synced using the global zone
@@ -974,11 +995,13 @@ on both nodes.
Example on CentOS 7:
- [root@icinga2-client1.localdomain /]# icinga2 daemon -C
- [root@icinga2-client1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-client1.localdomain /]# icinga2 daemon -C
+[root@icinga2-client1.localdomain /]# systemctl restart icinga2
- [root@icinga2-master1.localdomain /]# icinga2 daemon -C
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+[root@icinga2-master1.localdomain /]# icinga2 daemon -C
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
Once the clients have successfully connected, you are ready for the next step: **execute
a remote check on the client using the command endpoint**.
@@ -986,7 +1009,9 @@ a remote check on the client using the command endpoint**.
Include the host and service object configuration in the `master` zone
-- this will help adding a secondary master for high-availability later.
- [root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/master
+```
+[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/master
+```
Add the host and service objects you want to monitor. There is
no limitation for files and directories -- best practice is to
@@ -995,46 +1020,55 @@ sort things by type.
By convention a master/satellite/client host object should use the same name as the endpoint object.
You can also add multiple hosts which execute checks against remote services/clients.
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
+```
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
- object Host "icinga2-client1.localdomain" {
- check_command = "hostalive" //check is executed on the master
- address = "192.168.56.111"
+object Host "icinga2-client1.localdomain" {
+ check_command = "hostalive" //check is executed on the master
+ address = "192.168.56.111"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- }
+ vars.client_endpoint = name //follows the convention that host name == endpoint name
+}
+```
Given that you are monitoring a Linux client, we'll add a remote [disk](10-icinga-template-library.md#plugin-check-command-disk)
check.
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
- apply Service "disk" {
- check_command = "disk"
+apply Service "disk" {
+ check_command = "disk"
- //specify where the check is executed
- command_endpoint = host.vars.client_endpoint
+ //specify where the check is executed
+ command_endpoint = host.vars.client_endpoint
- assign where host.vars.client_endpoint
- }
+ assign where host.vars.client_endpoint
+}
+```
If you have your own custom `CheckCommand` definition, add it to the global zone:
- [root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/global-templates
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/global-templates/commands.conf
+```
+[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/global-templates
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/global-templates/commands.conf
- object CheckCommand "my-cmd" {
- //...
- }
+object CheckCommand "my-cmd" {
+ //...
+}
+```
Save the changes and validate the configuration on the master node:
- [root@icinga2-master1.localdomain /]# icinga2 daemon -C
-
+```
+[root@icinga2-master1.localdomain /]# icinga2 daemon -C
+```
Restart the Icinga 2 daemon (example for CentOS 7):
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
The following steps will happen:
@@ -1084,15 +1118,17 @@ Include the endpoint and zone configuration on **both** nodes in the file `/etc/
The endpoint configuration could look like this:
- [root@icinga2-client2.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client2.localdomain /]# vim /etc/icinga2/zones.conf
- object Endpoint "icinga2-master1.localdomain" {
- host = "192.168.56.101"
- }
+object Endpoint "icinga2-master1.localdomain" {
+ host = "192.168.56.101"
+}
- object Endpoint "icinga2-client2.localdomain" {
- host = "192.168.56.112"
- }
+object Endpoint "icinga2-client2.localdomain" {
+ host = "192.168.56.112"
+}
+```
Next, you need to define two zones. There is no naming convention, best practice is to either use `master`, `satellite`/`client-fqdn` or to choose region names for example `Europe`, `USA` and `Asia`, though.
@@ -1101,40 +1137,45 @@ is to use the client's FQDN for all object names.
The `master` zone is a parent of the `icinga2-client2.localdomain` zone:
- [root@icinga2-client2.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client2.localdomain /]# vim /etc/icinga2/zones.conf
- object Zone "master" {
- endpoints = [ "icinga2-master1.localdomain" ] //array with endpoint names
- }
+object Zone "master" {
+ endpoints = [ "icinga2-master1.localdomain" ] //array with endpoint names
+}
- object Zone "icinga2-client2.localdomain" {
- endpoints = [ "icinga2-client2.localdomain" ]
+object Zone "icinga2-client2.localdomain" {
+ endpoints = [ "icinga2-client2.localdomain" ]
- parent = "master" //establish zone hierarchy
- }
+ parent = "master" //establish zone hierarchy
+}
+```
Edit the `api` feature on the client `icinga2-client2.localdomain` in
the `/etc/icinga2/features-enabled/api.conf` file and set
`accept_config` to `true`.
- [root@icinga2-client2.localdomain /]# vim /etc/icinga2/features-enabled/api.conf
+```
+[root@icinga2-client2.localdomain /]# vim /etc/icinga2/features-enabled/api.conf
- object ApiListener "api" {
- //...
- accept_config = true
- }
+object ApiListener "api" {
+ //...
+ accept_config = true
+}
+```
Now it is time to validate the configuration and to restart the Icinga 2 daemon
on both nodes.
Example on CentOS 7:
- [root@icinga2-client2.localdomain /]# icinga2 daemon -C
- [root@icinga2-client2.localdomain /]# systemctl restart icinga2
-
- [root@icinga2-master1.localdomain /]# icinga2 daemon -C
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-client2.localdomain /]# icinga2 daemon -C
+[root@icinga2-client2.localdomain /]# systemctl restart icinga2
+[root@icinga2-master1.localdomain /]# icinga2 daemon -C
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
**Tip**: Best practice is to use a [global zone](06-distributed-monitoring.md#distributed-monitoring-global-zone-config-sync)
for common configuration items (check commands, templates, groups, etc.).
@@ -1146,7 +1187,9 @@ Navigate to `/etc/icinga2/zones.d` on your master node
`icinga2-master1.localdomain` and create a new directory with the same
name as your satellite/client zone name:
- [root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/icinga2-client2.localdomain
+```
+[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/icinga2-client2.localdomain
+```
Add the host and service objects you want to monitor. There is
no limitation for files and directories -- best practice is to
@@ -1155,33 +1198,41 @@ sort things by type.
By convention a master/satellite/client host object should use the same name as the endpoint object.
You can also add multiple hosts which execute checks against remote services/clients.
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/icinga2-client2.localdomain
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/icinga2-client2.localdomain]# vim hosts.conf
+```
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/icinga2-client2.localdomain
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/icinga2-client2.localdomain]# vim hosts.conf
- object Host "icinga2-client2.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.112"
- zone = "master" //optional trick: sync the required host object to the client, but enforce the "master" zone to execute the check
- }
+object Host "icinga2-client2.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.112"
+ zone = "master" //optional trick: sync the required host object to the client, but enforce the "master" zone to execute the check
+}
+```
Given that you are monitoring a Linux client we'll just add a local [disk](10-icinga-template-library.md#plugin-check-command-disk)
check.
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/icinga2-client2.localdomain]# vim services.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/icinga2-client2.localdomain]# vim services.conf
- object Service "disk" {
- host_name = "icinga2-client2.localdomain"
+object Service "disk" {
+ host_name = "icinga2-client2.localdomain"
- check_command = "disk"
- }
+ check_command = "disk"
+}
+```
Save the changes and validate the configuration on the master node:
- [root@icinga2-master1.localdomain /]# icinga2 daemon -C
+```
+[root@icinga2-master1.localdomain /]# icinga2 daemon -C
+```
Restart the Icinga 2 daemon (example for CentOS 7):
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
The following steps will happen:
@@ -1215,15 +1266,26 @@ If you are eager to start fresh instead you might take a look into the
The following examples should give you an idea on how to build your own
distributed monitoring environment. We've seen them all in production
-environments and received feedback from our [community](https://icinga.com/community/)
+environments and received feedback from our [community](https://community.icinga.com/)
and [partner support](https://icinga.com/support/) channels:
-* Single master with clients.
-* HA master with clients as command endpoint.
-* Three level cluster with config HA masters, satellites receiving config sync, and clients checked using command endpoint.
+* [Single master with client](06-distributed-monitoring.md#distributed-monitoring-master-clients).
+* [HA master with clients as command endpoint](06-distributed-monitoring.md#distributed-monitoring-scenarios-ha-master-clients)
+* [Three level cluster](06-distributed-monitoring.md#distributed-monitoring-scenarios-master-satellite-client) with config HA masters, satellites receiving config sync, and clients checked using command endpoint.
+
+You can also extend the cluster tree depth to four levels e.g. with 2 satellite levels.
+Just keep in mind that multiple levels become harder to debug in case of errors.
+
+You can also start with a single master setup, and later add a secondary
+master endpoint. This requires an extra step with the [initial sync](06-distributed-monitoring.md#distributed-monitoring-advanced-hints-initial-sync)
+for cloning the runtime state. This is described in detail [here](06-distributed-monitoring.md#distributed-monitoring-scenarios-ha-master-clients).
### Master with Clients <a id="distributed-monitoring-master-clients"></a>
+In this scenario, a single master node runs the check scheduler, notifications
+and IDO database backend and uses the [command endpoint mode](06-distributed-monitoring.md#distributed-monitoring-top-down-command-endpoint)
+to execute checks on the remote clients.
+
![Icinga 2 Distributed Master with Clients](images/distributed-monitoring/icinga2_distributed_scenarios_master_clients.png)
* `icinga2-master1.localdomain` is the primary master node.
@@ -1236,39 +1298,41 @@ Setup requirements:
Edit the `zones.conf` configuration file on the master:
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.conf
- object Endpoint "icinga2-master1.localdomain" {
- }
+object Endpoint "icinga2-master1.localdomain" {
+}
- object Endpoint "icinga2-client1.localdomain" {
- host = "192.168.56.111" //the master actively tries to connect to the client
- }
+object Endpoint "icinga2-client1.localdomain" {
+ host = "192.168.56.111" //the master actively tries to connect to the client
+}
- object Endpoint "icinga2-client2.localdomain" {
- host = "192.168.56.112" //the master actively tries to connect to the client
- }
+object Endpoint "icinga2-client2.localdomain" {
+ host = "192.168.56.112" //the master actively tries to connect to the client
+}
- object Zone "master" {
- endpoints = [ "icinga2-master1.localdomain" ]
- }
+object Zone "master" {
+ endpoints = [ "icinga2-master1.localdomain" ]
+}
- object Zone "icinga2-client1.localdomain" {
- endpoints = [ "icinga2-client1.localdomain" ]
+object Zone "icinga2-client1.localdomain" {
+ endpoints = [ "icinga2-client1.localdomain" ]
- parent = "master"
- }
+ parent = "master"
+}
- object Zone "icinga2-client2.localdomain" {
- endpoints = [ "icinga2-client2.localdomain" ]
+object Zone "icinga2-client2.localdomain" {
+ endpoints = [ "icinga2-client2.localdomain" ]
- parent = "master"
- }
+ parent = "master"
+}
- /* sync global commands */
- object Zone "global-templates" {
- global = true
- }
+/* sync global commands */
+object Zone "global-templates" {
+ global = true
+}
+```
The two client nodes do not necessarily need to know about each other. The only important thing
is that they know about the parent zone and their endpoint members (and optionally the global zone).
@@ -1278,53 +1342,55 @@ the client will actively try to connect to the master node. Since we've specifie
endpoint's attribute on the master node already, we don't want the clients to connect to the
master. **Choose one [connection direction](06-distributed-monitoring.md#distributed-monitoring-advanced-hints-connection-direction).**
- [root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
- object Endpoint "icinga2-master1.localdomain" {
- //do not actively connect to the master by leaving out the 'host' attribute
- }
+object Endpoint "icinga2-master1.localdomain" {
+ //do not actively connect to the master by leaving out the 'host' attribute
+}
- object Endpoint "icinga2-client1.localdomain" {
- }
+object Endpoint "icinga2-client1.localdomain" {
+}
- object Zone "master" {
- endpoints = [ "icinga2-master1.localdomain" ]
- }
+object Zone "master" {
+ endpoints = [ "icinga2-master1.localdomain" ]
+}
- object Zone "icinga2-client1.localdomain" {
- endpoints = [ "icinga2-client1.localdomain" ]
+object Zone "icinga2-client1.localdomain" {
+ endpoints = [ "icinga2-client1.localdomain" ]
- parent = "master"
- }
+ parent = "master"
+}
- /* sync global commands */
- object Zone "global-templates" {
- global = true
- }
+/* sync global commands */
+object Zone "global-templates" {
+ global = true
+}
- [root@icinga2-client2.localdomain /]# vim /etc/icinga2/zones.conf
+[root@icinga2-client2.localdomain /]# vim /etc/icinga2/zones.conf
- object Endpoint "icinga2-master1.localdomain" {
- //do not actively connect to the master by leaving out the 'host' attribute
- }
+object Endpoint "icinga2-master1.localdomain" {
+ //do not actively connect to the master by leaving out the 'host' attribute
+}
- object Endpoint "icinga2-client2.localdomain" {
- }
+object Endpoint "icinga2-client2.localdomain" {
+}
- object Zone "master" {
- endpoints = [ "icinga2-master1.localdomain" ]
- }
+object Zone "master" {
+ endpoints = [ "icinga2-master1.localdomain" ]
+}
- object Zone "icinga2-client2.localdomain" {
- endpoints = [ "icinga2-client2.localdomain" ]
+object Zone "icinga2-client2.localdomain" {
+ endpoints = [ "icinga2-client2.localdomain" ]
- parent = "master"
- }
+ parent = "master"
+}
- /* sync global commands */
- object Zone "global-templates" {
- global = true
- }
+/* sync global commands */
+object Zone "global-templates" {
+ global = true
+}
+```
Now it is time to define the two client hosts and apply service checks using
the command endpoint execution method on them. Note: You can also use the
@@ -1332,62 +1398,77 @@ config sync mode here.
Create a new configuration directory on the master node:
- [root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/master
+```
+[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/master
+```
Add the two client nodes as host objects:
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
+```
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
- object Host "icinga2-client1.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.111"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- }
+object Host "icinga2-client1.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.111"
+ vars.client_endpoint = name //follows the convention that host name == endpoint name
+}
- object Host "icinga2-client2.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.112"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- }
+object Host "icinga2-client2.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.112"
+ vars.client_endpoint = name //follows the convention that host name == endpoint name
+}
+```
Add services using command endpoint checks:
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
- apply Service "ping4" {
- check_command = "ping4"
- //check is executed on the master node
- assign where host.address
- }
+apply Service "ping4" {
+ check_command = "ping4"
+ //check is executed on the master node
+ assign where host.address
+}
- apply Service "disk" {
- check_command = "disk"
+apply Service "disk" {
+ check_command = "disk"
- //specify where the check is executed
- command_endpoint = host.vars.client_endpoint
+ //specify where the check is executed
+ command_endpoint = host.vars.client_endpoint
- assign where host.vars.client_endpoint
- }
+ assign where host.vars.client_endpoint
+}
+```
Validate the configuration and restart Icinga 2 on the master node `icinga2-master1.localdomain`.
- [root@icinga2-master1.localdomain /]# icinga2 daemon -C
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-master1.localdomain /]# icinga2 daemon -C
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
Open Icinga Web 2 and check the two newly created client hosts with two new services
-- one executed locally (`ping4`) and one using command endpoint (`disk`).
-### High-Availability Master with Clients <a id="distributed-monitoring-scenarios-ha-master-clients"></a>
-![Icinga 2 Distributed High Availability Master with Clients](images/distributed-monitoring/icinga2_distributed_scenarios_ha_master_clients.png)
+### High-Availability Master with Clients <a id="distributed-monitoring-scenarios-ha-master-clients"></a>
This scenario is similar to the one in the [previous section](06-distributed-monitoring.md#distributed-monitoring-master-clients). The only difference is that we will now set up two master nodes in a high-availability setup.
These nodes must be configured as zone and endpoints objects.
+![Icinga 2 Distributed High Availability Master with Clients](images/distributed-monitoring/icinga2_distributed_scenarios_ha_master_clients.png)
+
The setup uses the capabilities of the Icinga 2 cluster. All zone members
replicate cluster events amongst each other. In addition to that, several Icinga 2
-features can enable HA functionality.
+features can enable [HA functionality](06-distributed-monitoring.md#distributed-monitoring-high-availability-features).
+
+Best practice is to run the database backend on a dedicated server/cluster and
+only expose a virtual IP address to Icinga and the IDO feature. By default, only one
+endpoint will actively write to the backend then. Typical setups for MySQL clusters
+involve Master-Master-Replication (Master-Slave-Replication in both directions) or Galera,
+more tips can be found on our [community forums](https://community.icinga.com/).
**Note**: All nodes in the same zone require that you enable the same features for high-availability (HA).
@@ -1418,47 +1499,55 @@ you can disable the HA feature and write to a local database on each node.
Both methods require that you configure Icinga Web 2 accordingly (monitoring
backend, IDO database, used transports, etc.).
+> **Note**
+>
+> You can also start with a single master shown [here](06-distributed-monitoring.md#distributed-monitoring-master-clients) and later add
+> the second master. This requires an extra step with the [initial sync](06-distributed-monitoring.md#distributed-monitoring-advanced-hints-initial-sync)
+> for cloning the runtime state after done. Once done, proceed here.
+
The zone hierarchy could look like this. It involves putting the two master nodes
`icinga2-master1.localdomain` and `icinga2-master2.localdomain` into the `master` zone.
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.conf
- object Endpoint "icinga2-master1.localdomain" {
- host = "192.168.56.101"
- }
+object Endpoint "icinga2-master1.localdomain" {
+ host = "192.168.56.101"
+}
- object Endpoint "icinga2-master2.localdomain" {
- host = "192.168.56.102"
- }
+object Endpoint "icinga2-master2.localdomain" {
+ host = "192.168.56.102"
+}
- object Endpoint "icinga2-client1.localdomain" {
- host = "192.168.56.111" //the master actively tries to connect to the client
- }
+object Endpoint "icinga2-client1.localdomain" {
+ host = "192.168.56.111" //the master actively tries to connect to the client
+}
- object Endpoint "icinga2-client2.localdomain" {
- host = "192.168.56.112" //the master actively tries to connect to the client
- }
+object Endpoint "icinga2-client2.localdomain" {
+ host = "192.168.56.112" //the master actively tries to connect to the client
+}
- object Zone "master" {
- endpoints = [ "icinga2-master1.localdomain", "icinga2-master2.localdomain" ]
- }
+object Zone "master" {
+ endpoints = [ "icinga2-master1.localdomain", "icinga2-master2.localdomain" ]
+}
- object Zone "icinga2-client1.localdomain" {
- endpoints = [ "icinga2-client1.localdomain" ]
+object Zone "icinga2-client1.localdomain" {
+ endpoints = [ "icinga2-client1.localdomain" ]
- parent = "master"
- }
+ parent = "master"
+}
- object Zone "icinga2-client2.localdomain" {
- endpoints = [ "icinga2-client2.localdomain" ]
+object Zone "icinga2-client2.localdomain" {
+ endpoints = [ "icinga2-client2.localdomain" ]
- parent = "master"
- }
+ parent = "master"
+}
- /* sync global commands */
- object Zone "global-templates" {
- global = true
- }
+/* sync global commands */
+object Zone "global-templates" {
+ global = true
+}
+```
The two client nodes do not necessarily need to know about each other. The only important thing
is that they know about the parent zone and their endpoint members (and optionally about the global zone).
@@ -1468,61 +1557,63 @@ endpoint objects, the client will actively try to connect to the master node. Si
endpoint's attribute on the master node already, we don't want the clients to connect to the
master nodes. **Choose one [connection direction](06-distributed-monitoring.md#distributed-monitoring-advanced-hints-connection-direction).**
- [root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
- object Endpoint "icinga2-master1.localdomain" {
- //do not actively connect to the master by leaving out the 'host' attribute
- }
+object Endpoint "icinga2-master1.localdomain" {
+ //do not actively connect to the master by leaving out the 'host' attribute
+}
- object Endpoint "icinga2-master2.localdomain" {
- //do not actively connect to the master by leaving out the 'host' attribute
- }
+object Endpoint "icinga2-master2.localdomain" {
+ //do not actively connect to the master by leaving out the 'host' attribute
+}
- object Endpoint "icinga2-client1.localdomain" {
- }
+object Endpoint "icinga2-client1.localdomain" {
+}
- object Zone "master" {
- endpoints = [ "icinga2-master1.localdomain", "icinga2-master2.localdomain" ]
- }
+object Zone "master" {
+ endpoints = [ "icinga2-master1.localdomain", "icinga2-master2.localdomain" ]
+}
- object Zone "icinga2-client1.localdomain" {
- endpoints = [ "icinga2-client1.localdomain" ]
+object Zone "icinga2-client1.localdomain" {
+ endpoints = [ "icinga2-client1.localdomain" ]
- parent = "master"
- }
+ parent = "master"
+}
- /* sync global commands */
- object Zone "global-templates" {
- global = true
- }
+/* sync global commands */
+object Zone "global-templates" {
+ global = true
+}
- [root@icinga2-client2.localdomain /]# vim /etc/icinga2/zones.conf
+[root@icinga2-client2.localdomain /]# vim /etc/icinga2/zones.conf
- object Endpoint "icinga2-master1.localdomain" {
- //do not actively connect to the master by leaving out the 'host' attribute
- }
+object Endpoint "icinga2-master1.localdomain" {
+ //do not actively connect to the master by leaving out the 'host' attribute
+}
- object Endpoint "icinga2-master2.localdomain" {
- //do not actively connect to the master by leaving out the 'host' attribute
- }
+object Endpoint "icinga2-master2.localdomain" {
+ //do not actively connect to the master by leaving out the 'host' attribute
+}
- object Endpoint "icinga2-client2.localdomain" {
- }
+object Endpoint "icinga2-client2.localdomain" {
+}
- object Zone "master" {
- endpoints = [ "icinga2-master1.localdomain", "icinga2-master2.localdomain" ]
- }
+object Zone "master" {
+ endpoints = [ "icinga2-master1.localdomain", "icinga2-master2.localdomain" ]
+}
- object Zone "icinga2-client2.localdomain" {
- endpoints = [ "icinga2-client2.localdomain" ]
+object Zone "icinga2-client2.localdomain" {
+ endpoints = [ "icinga2-client2.localdomain" ]
- parent = "master"
- }
+ parent = "master"
+}
- /* sync global commands */
- object Zone "global-templates" {
- global = true
- }
+/* sync global commands */
+object Zone "global-templates" {
+ global = true
+}
+```
Now it is time to define the two client hosts and apply service checks using
the command endpoint execution method. Note: You can also use the
@@ -1532,48 +1623,56 @@ Create a new configuration directory on the master node `icinga2-master1.localdo
**Note**: The secondary master node `icinga2-master2.localdomain` receives the
configuration using the [config sync mode](06-distributed-monitoring.md#distributed-monitoring-top-down-config-sync).
- [root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/master
+```
+[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/master
+```
Add the two client nodes as host objects:
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
+```
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
- object Host "icinga2-client1.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.111"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- }
+object Host "icinga2-client1.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.111"
+ vars.client_endpoint = name //follows the convention that host name == endpoint name
+}
- object Host "icinga2-client2.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.112"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- }
+object Host "icinga2-client2.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.112"
+ vars.client_endpoint = name //follows the convention that host name == endpoint name
+}
+```
Add services using command endpoint checks:
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
- apply Service "ping4" {
- check_command = "ping4"
- //check is executed on the master node
- assign where host.address
- }
+apply Service "ping4" {
+ check_command = "ping4"
+ //check is executed on the master node
+ assign where host.address
+}
- apply Service "disk" {
- check_command = "disk"
+apply Service "disk" {
+ check_command = "disk"
- //specify where the check is executed
- command_endpoint = host.vars.client_endpoint
+ //specify where the check is executed
+ command_endpoint = host.vars.client_endpoint
- assign where host.vars.client_endpoint
- }
+ assign where host.vars.client_endpoint
+}
+```
Validate the configuration and restart Icinga 2 on the master node `icinga2-master1.localdomain`.
- [root@icinga2-master1.localdomain /]# icinga2 daemon -C
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-master1.localdomain /]# icinga2 daemon -C
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
Open Icinga Web 2 and check the two newly created client hosts with two new services
-- one executed locally (`ping4`) and one using command endpoint (`disk`).
@@ -1584,17 +1683,23 @@ to make sure that your cluster notifies you in case of failure.
### Three Levels with Master, Satellites, and Clients <a id="distributed-monitoring-scenarios-master-satellite-client"></a>
-![Icinga 2 Distributed Master and Satellites with Clients](images/distributed-monitoring/icinga2_distributed_scenarios_master_satellite_client.png)
-
This scenario combines everything you've learned so far: High-availability masters,
satellites receiving their configuration from the master zone, and clients checked via command
endpoint from the satellite zones.
+![Icinga 2 Distributed Master and Satellites with Clients](images/distributed-monitoring/icinga2_distributed_scenarios_master_satellite_client.png)
+
> **Tip**:
>
> It can get complicated, so grab a pen and paper and bring your thoughts to life.
> Play around with a test setup before using it in a production environment!
+Best practice is to run the database backend on a dedicated server/cluster and
+only expose a virtual IP address to Icinga and the IDO feature. By default, only one
+endpoint will actively write to the backend then. Typical setups for MySQL clusters
+involve Master-Master-Replication (Master-Slave-Replication in both directions) or Galera,
+more tips can be found on our [community forums](https://community.icinga.com/).
+
Overview:
* `icinga2-master1.localdomain` is the configuration master master node.
@@ -1814,32 +1919,34 @@ we must configure the client endpoint and zone objects.
In order to minimize the effort, we'll sync the client zone and endpoint configuration to the
satellites where the connection information is needed as well.
- [root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/{master,satellite,global-templates}
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/satellite
+```
+[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/{master,satellite,global-templates}
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/satellite
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim icinga2-client1.localdomain.conf
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim icinga2-client1.localdomain.conf
- object Endpoint "icinga2-client1.localdomain" {
- host = "192.168.56.111" //the satellite actively tries to connect to the client
- }
+object Endpoint "icinga2-client1.localdomain" {
+ host = "192.168.56.111" //the satellite actively tries to connect to the client
+}
- object Zone "icinga2-client1.localdomain" {
- endpoints = [ "icinga2-client1.localdomain" ]
+object Zone "icinga2-client1.localdomain" {
+ endpoints = [ "icinga2-client1.localdomain" ]
- parent = "satellite"
- }
+ parent = "satellite"
+}
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim icinga2-client2.localdomain.conf
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim icinga2-client2.localdomain.conf
- object Endpoint "icinga2-client2.localdomain" {
- host = "192.168.56.112" //the satellite actively tries to connect to the client
- }
+object Endpoint "icinga2-client2.localdomain" {
+ host = "192.168.56.112" //the satellite actively tries to connect to the client
+}
- object Zone "icinga2-client2.localdomain" {
- endpoints = [ "icinga2-client2.localdomain" ]
+object Zone "icinga2-client2.localdomain" {
+ endpoints = [ "icinga2-client2.localdomain" ]
- parent = "satellite"
- }
+ parent = "satellite"
+}
+```
The two client nodes do not necessarily need to know about each other, either. The only important thing
is that they know about the parent zone (the satellite) and their endpoint members (and optionally the global zone).
@@ -1851,73 +1958,77 @@ satellite nodes. **Choose one [connection direction](06-distributed-monitoring.m
Example for `icinga2-client1.localdomain`:
- [root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
- object Endpoint "icinga2-satellite1.localdomain" {
- //do not actively connect to the satellite by leaving out the 'host' attribute
- }
+object Endpoint "icinga2-satellite1.localdomain" {
+ //do not actively connect to the satellite by leaving out the 'host' attribute
+}
- object Endpoint "icinga2-satellite2.localdomain" {
- //do not actively connect to the satellite by leaving out the 'host' attribute
- }
+object Endpoint "icinga2-satellite2.localdomain" {
+ //do not actively connect to the satellite by leaving out the 'host' attribute
+}
- object Endpoint "icinga2-client1.localdomain" {
- //that's us
- }
+object Endpoint "icinga2-client1.localdomain" {
+ //that's us
+}
- object Zone "satellite" {
- endpoints = [ "icinga2-satellite1.localdomain", "icinga2-satellite2.localdomain" ]
- }
+object Zone "satellite" {
+ endpoints = [ "icinga2-satellite1.localdomain", "icinga2-satellite2.localdomain" ]
+}
- object Zone "icinga2-client1.localdomain" {
- endpoints = [ "icinga2-client1.localdomain" ]
+object Zone "icinga2-client1.localdomain" {
+ endpoints = [ "icinga2-client1.localdomain" ]
- parent = "satellite"
- }
+ parent = "satellite"
+}
- /* sync global commands */
- object Zone "global-templates" {
- global = true
- }
+/* sync global commands */
+object Zone "global-templates" {
+ global = true
+}
- object Zone "director-global" {
- global = true
- }
+object Zone "director-global" {
+ global = true
+}
+```
Example for `icinga2-client2.localdomain`:
- [root@icinga2-client2.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client2.localdomain /]# vim /etc/icinga2/zones.conf
- object Endpoint "icinga2-satellite1.localdomain" {
- //do not actively connect to the satellite by leaving out the 'host' attribute
- }
+object Endpoint "icinga2-satellite1.localdomain" {
+ //do not actively connect to the satellite by leaving out the 'host' attribute
+}
- object Endpoint "icinga2-satellite2.localdomain" {
- //do not actively connect to the satellite by leaving out the 'host' attribute
- }
+object Endpoint "icinga2-satellite2.localdomain" {
+ //do not actively connect to the satellite by leaving out the 'host' attribute
+}
- object Endpoint "icinga2-client2.localdomain" {
- //that's us
- }
+object Endpoint "icinga2-client2.localdomain" {
+ //that's us
+}
- object Zone "satellite" {
- endpoints = [ "icinga2-satellite1.localdomain", "icinga2-satellite2.localdomain" ]
- }
+object Zone "satellite" {
+ endpoints = [ "icinga2-satellite1.localdomain", "icinga2-satellite2.localdomain" ]
+}
- object Zone "icinga2-client2.localdomain" {
- endpoints = [ "icinga2-client2.localdomain" ]
+object Zone "icinga2-client2.localdomain" {
+ endpoints = [ "icinga2-client2.localdomain" ]
- parent = "satellite"
- }
+ parent = "satellite"
+}
- /* sync global commands */
- object Zone "global-templates" {
- global = true
- }
+/* sync global commands */
+object Zone "global-templates" {
+ global = true
+}
- object Zone "director-global" {
- global = true
- }
+object Zone "director-global" {
+ global = true
+}
+```
Now it is time to define the two client hosts on the master, sync them to the satellites
and apply service checks using the command endpoint execution method to them.
@@ -1926,57 +2037,69 @@ Add the two client nodes as host objects to the `satellite` zone.
We've already created the directories in `/etc/icinga2/zones.d` including the files for the
zone and endpoint configuration for the clients.
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/satellite
+```
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/satellite
+```
Add the host object configuration for the `icinga2-client1.localdomain` client. You should
have created the configuration file in the previous steps and it should contain the endpoint
and zone object configuration already.
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim icinga2-client1.localdomain.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim icinga2-client1.localdomain.conf
- object Host "icinga2-client1.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.111"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- }
+object Host "icinga2-client1.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.111"
+ vars.client_endpoint = name //follows the convention that host name == endpoint name
+}
+```
Add the host object configuration for the `icinga2-client2.localdomain` client configuration file:
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim icinga2-client2.localdomain.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim icinga2-client2.localdomain.conf
- object Host "icinga2-client2.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.112"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- }
+object Host "icinga2-client2.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.112"
+ vars.client_endpoint = name //follows the convention that host name == endpoint name
+}
+```
Add a service object which is executed on the satellite nodes (e.g. `ping4`). Pin the apply rule to the `satellite` zone only.
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim services.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim services.conf
- apply Service "ping4" {
- check_command = "ping4"
- //check is executed on the satellite node
- assign where host.zone == "satellite" && host.address
- }
+apply Service "ping4" {
+ check_command = "ping4"
+ //check is executed on the satellite node
+ assign where host.zone == "satellite" && host.address
+}
+```
Add services using command endpoint checks. Pin the apply rules to the `satellite` zone only.
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim services.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/satellite]# vim services.conf
- apply Service "disk" {
- check_command = "disk"
+apply Service "disk" {
+ check_command = "disk"
- //specify where the check is executed
- command_endpoint = host.vars.client_endpoint
+ //specify where the check is executed
+ command_endpoint = host.vars.client_endpoint
- assign where host.zone == "satellite" && host.vars.client_endpoint
- }
+ assign where host.zone == "satellite" && host.vars.client_endpoint
+}
+```
Validate the configuration and restart Icinga 2 on the master node `icinga2-master1.localdomain`.
- [root@icinga2-master1.localdomain /]# icinga2 daemon -C
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-master1.localdomain /]# icinga2 daemon -C
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
Open Icinga Web 2 and check the two newly created client hosts with two new services
-- one executed locally (`ping4`) and one using command endpoint (`disk`).
@@ -2014,26 +2137,32 @@ zone. The configuration validation will terminate with an error.
The zone object configuration must be deployed on all nodes which should receive
the global configuration files:
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.conf
- object Zone "global-commands" {
- global = true
- }
+object Zone "global-commands" {
+ global = true
+}
+```
The default global zones generated by the setup wizards are called `global-templates` and `director-global`.
Similar to the zone configuration sync you'll need to create a new directory in
`/etc/icinga2/zones.d`:
- [root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/global-commands
+```
+[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/global-commands
+```
Next, add a new check command, for example:
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/global-commands/web.conf
+```
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/global-commands/web.conf
- object CheckCommand "webinject" {
- //...
- }
+object CheckCommand "webinject" {
+ //...
+}
+```
Restart the client(s) which should receive the global zone before
before restarting the parent master/satellite nodes.
@@ -2045,8 +2174,10 @@ into the default global zone `global-templates`.
Example:
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/conf.d
- [root@icinga2-master1.localdomain /etc/icinga2/conf.d]# cp {commands,groups,notifications,services,templates,timeperiods,users}.conf /etc/icinga2/zones.d/global-templates
+```
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/conf.d
+[root@icinga2-master1.localdomain /etc/icinga2/conf.d]# cp {commands,groups,notifications,services,templates,timeperiods,users}.conf /etc/icinga2/zones.d/global-templates
+```
### Health Checks <a id="distributed-monitoring-health-checks"></a>
@@ -2060,69 +2191,76 @@ additional health checks.
The `cluster` check, for example, will check if all endpoints in the current zone and the directly
connected zones are working properly:
- [root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/master
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/icinga2-master1.localdomain.conf
+```
+[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/master
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/icinga2-master1.localdomain.conf
- object Host "icinga2-master1.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.101"
- }
+object Host "icinga2-master1.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.101"
+}
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/cluster.conf
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/cluster.conf
- object Service "cluster" {
- check_command = "cluster"
- check_interval = 5s
- retry_interval = 1s
+object Service "cluster" {
+ check_command = "cluster"
+ check_interval = 5s
+ retry_interval = 1s
- host_name = "icinga2-master1.localdomain"
- }
+ host_name = "icinga2-master1.localdomain"
+}
+```
The `cluster-zone` check will test whether the configured target zone is currently
connected or not. This example adds a health check for the [ha master with clients scenario](06-distributed-monitoring.md#distributed-monitoring-scenarios-ha-master-clients).
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/services.conf
+```
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/services.conf
- apply Service "cluster-health" {
- check_command = "cluster-zone"
+apply Service "cluster-health" {
+ check_command = "cluster-zone"
- display_name = "cluster-health-" + host.name
+ display_name = "cluster-health-" + host.name
- /* This follows the convention that the client zone name is the FQDN which is the same as the host object name. */
- vars.cluster_zone = host.name
+ /* This follows the convention that the client zone name is the FQDN which is the same as the host object name. */
+ vars.cluster_zone = host.name
- assign where host.vars.client_endpoint
- }
+ assign where host.vars.client_endpoint
+}
+```
In case you cannot assign the `cluster_zone` attribute, add specific
checks to your cluster:
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/cluster.conf
-
- object Service "cluster-zone-satellite" {
- check_command = "cluster-zone"
- check_interval = 5s
- retry_interval = 1s
- vars.cluster_zone = "satellite"
+```
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/cluster.conf
- host_name = "icinga2-master1.localdomain"
- }
+object Service "cluster-zone-satellite" {
+ check_command = "cluster-zone"
+ check_interval = 5s
+ retry_interval = 1s
+ vars.cluster_zone = "satellite"
+ host_name = "icinga2-master1.localdomain"
+}
+```
If you are using top down checks with command endpoint configuration, you can
add a dependency which prevents notifications for all other failing services:
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/dependencies.conf
+```
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/dependencies.conf
- apply Dependency "health-check" to Service {
- parent_service_name = "child-health"
+apply Dependency "health-check" to Service {
+ parent_service_name = "child-health"
- states = [ OK ]
- disable_notifications = true
+ states = [ OK ]
+ disable_notifications = true
- assign where host.vars.client_endpoint
- ignore where service.name == "child-health"
- }
+ assign where host.vars.client_endpoint
+ ignore where service.name == "child-health"
+}
+```
### Pin Checks in a Zone <a id="distributed-monitoring-pin-checks-zone"></a>
@@ -2130,23 +2268,25 @@ In case you want to pin specific checks to their endpoints in a given zone you'l
the `command_endpoint` attribute. This is reasonable if you want to
execute a local disk check in the `master` Zone on a specific endpoint then.
- [root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/master
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/icinga2-master1.localdomain.conf
+```
+[root@icinga2-master1.localdomain /]# mkdir -p /etc/icinga2/zones.d/master
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/icinga2-master1.localdomain.conf
- object Host "icinga2-master1.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.101"
- }
+object Host "icinga2-master1.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.101"
+}
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/services.conf
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.d/master/services.conf
- apply Service "disk" {
- check_command = "disk"
+apply Service "disk" {
+ check_command = "disk"
- command_endpoint = host.name //requires a host object matching the endpoint object name e.g. icinga2-master1.localdomain
+ command_endpoint = host.name //requires a host object matching the endpoint object name e.g. icinga2-master1.localdomain
- assign where host.zone == "master" && match("icinga2-master*", host.name)
- }
+ assign where host.zone == "master" && match("icinga2-master*", host.name)
+}
+```
The `host.zone` attribute check inside the expression ensures that
the service object is only created for host objects inside the `master`
@@ -2160,21 +2300,27 @@ function ensures to only create services for the master nodes.
By default ICMP requests are disabled in the Windows firewall. You can
change that by [adding a new rule](https://support.microsoft.com/en-us/kb/947709).
- C:\WINDOWS\system32>netsh advfirewall firewall add rule name="ICMP Allow incoming V4 echo request" protocol=icmpv4:8,any dir=in action=allow
+```
+C:\WINDOWS\system32>netsh advfirewall firewall add rule name="ICMP Allow incoming V4 echo request" protocol=icmpv4:8,any dir=in action=allow
+```
#### Icinga 2 <a id="distributed-monitoring-windows-firewall-icinga2"></a>
If your master/satellite nodes should actively connect to the Windows client
you'll also need to ensure that port `5665` is enabled.
- C:\WINDOWS\system32>netsh advfirewall firewall add rule name="Open port 5665 (Icinga 2)" dir=in action=allow protocol=TCP localport=5665
+```
+C:\WINDOWS\system32>netsh advfirewall firewall add rule name="Open port 5665 (Icinga 2)" dir=in action=allow protocol=TCP localport=5665
+```
#### NSClient++ API <a id="distributed-monitoring-windows-firewall-nsclient-api"></a>
If the [check_nscp_api](06-distributed-monitoring.md#distributed-monitoring-windows-nscp-check-api)
plugin is used to query NSClient++, you need to ensure that its port is enabled.
- C:\WINDOWS\system32>netsh advfirewall firewall add rule name="Open port 8443 (NSClient++ API)" dir=in action=allow protocol=TCP localport=8443
+```
+C:\WINDOWS\system32>netsh advfirewall firewall add rule name="Open port 8443 (NSClient++ API)" dir=in action=allow protocol=TCP localport=8443
+```
For security reasons, it is advised to enable the NSClient++ HTTP API for local
connection from the Icinga 2 client only. Remote connections to the HTTP API
@@ -2187,45 +2333,53 @@ Detailed [documentation](10-icinga-template-library.md#windows-plugins) is avail
Add the following `include` statement on all your nodes (master, satellite, client):
- vim /etc/icinga2/icinga2.conf
+```
+vim /etc/icinga2/icinga2.conf
- include <windows-plugins>
+include <windows-plugins>
+```
Based on the [master with clients](06-distributed-monitoring.md#distributed-monitoring-master-clients)
scenario we'll now add a local disk check.
First, add the client node as host object:
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
+```
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
- object Host "icinga2-client2.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.112"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- vars.os_type = "windows"
- }
+object Host "icinga2-client2.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.112"
+ vars.client_endpoint = name //follows the convention that host name == endpoint name
+ vars.os_type = "windows"
+}
+```
Next, add the disk check using command endpoint checks (details in the
[disk-windows](10-icinga-template-library.md#windows-plugins-disk-windows) documentation):
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
- apply Service "disk C:" {
- check_command = "disk-windows"
+apply Service "disk C:" {
+ check_command = "disk-windows"
- vars.disk_win_path = "C:"
+ vars.disk_win_path = "C:"
- //specify where the check is executed
- command_endpoint = host.vars.client_endpoint
+ //specify where the check is executed
+ command_endpoint = host.vars.client_endpoint
- assign where host.vars.os_type == "windows" && host.vars.client_endpoint
- }
+ assign where host.vars.os_type == "windows" && host.vars.client_endpoint
+}
+```
Validate the configuration and restart Icinga 2.
- [root@icinga2-master1.localdomain /]# icinga2 daemon -C
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-master1.localdomain /]# icinga2 daemon -C
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
Open Icinga Web 2 and check your newly added Windows disk check :)
@@ -2260,43 +2414,49 @@ scenario we'll now add a local nscp check which queries the NSClient++ API to ch
Define a host object called `icinga2-client2.localdomain` on the master. Add the `nscp_api_password`
custom attribute and specify the drives to check.
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
+```
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
- object Host "icinga2-client1.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.111"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- vars.os_type = "Windows"
- vars.nscp_api_password = "icinga"
- vars.drives = [ "C:", "D:" ]
- }
+object Host "icinga2-client1.localdomain" {
+check_command = "hostalive"
+address = "192.168.56.111"
+vars.client_endpoint = name //follows the convention that host name == endpoint name
+vars.os_type = "Windows"
+vars.nscp_api_password = "icinga"
+vars.drives = [ "C:", "D:" ]
+}
+```
The service checks are generated using an [apply for](03-monitoring-basics.md#using-apply-for)
rule based on `host.vars.drives`:
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
- apply Service "nscp-api-" for (drive in host.vars.drives) {
- import "generic-service"
+apply Service "nscp-api-" for (drive in host.vars.drives) {
+ import "generic-service"
- check_command = "nscp_api"
- command_endpoint = host.vars.client_endpoint
+ check_command = "nscp_api"
+ command_endpoint = host.vars.client_endpoint
- //display_name = "nscp-drive-" + drive
+ //display_name = "nscp-drive-" + drive
- vars.nscp_api_host = "localhost"
- vars.nscp_api_query = "check_drivesize"
- vars.nscp_api_password = host.vars.nscp_api_password
- vars.nscp_api_arguments = [ "drive=" + drive ]
+ vars.nscp_api_host = "localhost"
+ vars.nscp_api_query = "check_drivesize"
+ vars.nscp_api_password = host.vars.nscp_api_password
+ vars.nscp_api_arguments = [ "drive=" + drive ]
- ignore where host.vars.os_type != "Windows"
- }
+ ignore where host.vars.os_type != "Windows"
+}
+```
Validate the configuration and restart Icinga 2.
- [root@icinga2-master1.localdomain /]# icinga2 daemon -C
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-master1.localdomain /]# icinga2 daemon -C
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
Two new services ("nscp-drive-D:" and "nscp-drive-C:") will be visible in Icinga Web 2.
@@ -2306,44 +2466,48 @@ Note: You can also omit the `command_endpoint` configuration to execute
the command on the master. This also requires a different value for `nscp_api_host`
which defaults to `host.address`.
- //command_endpoint = host.vars.client_endpoint
+```
+ //command_endpoint = host.vars.client_endpoint
- //vars.nscp_api_host = "localhost"
+ //vars.nscp_api_host = "localhost"
+```
You can verify the check execution by looking at the `Check Source` attribute
in Icinga Web 2 or the REST API.
If you want to monitor specific Windows services, you could use the following example:
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
+```
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
- object Host "icinga2-client1.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.111"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- vars.os_type = "Windows"
- vars.nscp_api_password = "icinga"
- vars.services = [ "Windows Update", "wscsvc" ]
- }
+object Host "icinga2-client1.localdomain" {
+check_command = "hostalive"
+address = "192.168.56.111"
+vars.client_endpoint = name //follows the convention that host name == endpoint name
+vars.os_type = "Windows"
+vars.nscp_api_password = "icinga"
+vars.services = [ "Windows Update", "wscsvc" ]
+}
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
- apply Service "nscp-api-" for (svc in host.vars.services) {
- import "generic-service"
+apply Service "nscp-api-" for (svc in host.vars.services) {
+ import "generic-service"
- check_command = "nscp_api"
- command_endpoint = host.vars.client_endpoint
+ check_command = "nscp_api"
+ command_endpoint = host.vars.client_endpoint
- //display_name = "nscp-service-" + svc
+ //display_name = "nscp-service-" + svc
- vars.nscp_api_host = "localhost"
- vars.nscp_api_query = "check_service"
- vars.nscp_api_password = host.vars.nscp_api_password
- vars.nscp_api_arguments = [ "service=" + svc ]
+ vars.nscp_api_host = "localhost"
+ vars.nscp_api_query = "check_service"
+ vars.nscp_api_password = host.vars.nscp_api_password
+ vars.nscp_api_arguments = [ "service=" + svc ]
- ignore where host.vars.os_type != "Windows"
- }
+ ignore where host.vars.os_type != "Windows"
+}
+```
#### NSCLient++ with nscp-local <a id="distributed-monitoring-windows-nscp-check-local"></a>
@@ -2356,9 +2520,11 @@ provided by the Icinga Template Library (ITL).
Add the following `include` statement on all your nodes (master, satellite, client):
- vim /etc/icinga2/icinga2.conf
+```
+vim /etc/icinga2/icinga2.conf
- include <nscp>
+include <nscp>
+```
The CheckCommand definitions will automatically determine the installed path
to the `nscp.exe` binary.
@@ -2368,39 +2534,45 @@ scenario we'll now add a local nscp check querying a given performance counter.
First, add the client node as host object:
- [root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
+```
+[root@icinga2-master1.localdomain /]# cd /etc/icinga2/zones.d/master
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim hosts.conf
- object Host "icinga2-client1.localdomain" {
- check_command = "hostalive"
- address = "192.168.56.111"
- vars.client_endpoint = name //follows the convention that host name == endpoint name
- vars.os_type = "windows"
- }
+object Host "icinga2-client1.localdomain" {
+ check_command = "hostalive"
+ address = "192.168.56.111"
+ vars.client_endpoint = name //follows the convention that host name == endpoint name
+ vars.os_type = "windows"
+}
+```
Next, add a performance counter check using command endpoint checks (details in the
[nscp-local-counter](10-icinga-template-library.md#nscp-check-local-counter) documentation):
- [root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
+```
+[root@icinga2-master1.localdomain /etc/icinga2/zones.d/master]# vim services.conf
- apply Service "nscp-local-counter-cpu" {
- check_command = "nscp-local-counter"
- command_endpoint = host.vars.client_endpoint
+apply Service "nscp-local-counter-cpu" {
+ check_command = "nscp-local-counter"
+ command_endpoint = host.vars.client_endpoint
- vars.nscp_counter_name = "\\Processor(_total)\\% Processor Time"
- vars.nscp_counter_perfsyntax = "Total Processor Time"
- vars.nscp_counter_warning = 1
- vars.nscp_counter_critical = 5
+ vars.nscp_counter_name = "\\Processor(_total)\\% Processor Time"
+ vars.nscp_counter_perfsyntax = "Total Processor Time"
+ vars.nscp_counter_warning = 1
+ vars.nscp_counter_critical = 5
- vars.nscp_counter_showall = true
+ vars.nscp_counter_showall = true
- assign where host.vars.os_type == "windows" && host.vars.client_endpoint
- }
+ assign where host.vars.os_type == "windows" && host.vars.client_endpoint
+}
+```
Validate the configuration and restart Icinga 2.
- [root@icinga2-master1.localdomain /]# icinga2 daemon -C
- [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-master1.localdomain /]# icinga2 daemon -C
+[root@icinga2-master1.localdomain /]# systemctl restart icinga2
+```
Open Icinga Web 2 and check your newly added Windows NSClient++ check :)
@@ -2442,7 +2614,9 @@ have the `checker` feature enabled.
Example:
- # icinga2 feature enable checker
+```
+# icinga2 feature enable checker
+```
All nodes in the same zone load-balance the check execution. If one instance shuts down,
the other nodes will automatically take over the remaining checks.
@@ -2454,7 +2628,9 @@ have the `notification` feature enabled.
Example:
- # icinga2 feature enable notification
+```
+# icinga2 feature enable notification
+```
Notifications are load-balanced amongst all nodes in a zone. By default this functionality
is enabled.
@@ -2469,7 +2645,9 @@ have the DB IDO feature enabled.
Example DB IDO MySQL:
- # icinga2 feature enable ido-mysql
+```
+# icinga2 feature enable ido-mysql
+```
By default the DB IDO feature only runs on one node. All other nodes in the same zone disable
the active IDO database connection at runtime. The node with the active DB IDO connection is
@@ -2490,11 +2668,13 @@ The DB IDO feature will try to determine which cluster endpoint is currently wri
to the database and bail out if another endpoint is active. You can manually verify that
by running the following query command:
- icinga=> SELECT status_update_time, endpoint_name FROM icinga_programstatus;
- status_update_time | endpoint_name
- ------------------------+---------------
- 2016-08-15 15:52:26+02 | icinga2-master1.localdomain
- (1 Zeile)
+```
+icinga=> SELECT status_update_time, endpoint_name FROM icinga_programstatus;
+ status_update_time | endpoint_name
+------------------------+---------------
+ 2016-08-15 15:52:26+02 | icinga2-master1.localdomain
+(1 Zeile)
+```
This is useful when the cluster connection between endpoints breaks, and prevents
data duplication in split-brain-scenarios. The failover timeout can be set for the
@@ -2508,26 +2688,30 @@ configuration specifies a valid `host` attribute (FQDN or IP address).
Example for the master node `icinga2-master1.localdomain` actively connecting
to the client node `icinga2-client1.localdomain`:
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.conf
- //...
+//...
- object Endpoint "icinga2-client1.localdomain" {
- host = "192.168.56.111" //the master actively tries to connect to the client
- log_duration = 0
- }
+object Endpoint "icinga2-client1.localdomain" {
+ host = "192.168.56.111" //the master actively tries to connect to the client
+ log_duration = 0
+}
+```
Example for the client node `icinga2-client1.localdomain` not actively
connecting to the master node `icinga2-master1.localdomain`:
- [root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
- //...
+//...
- object Endpoint "icinga2-master1.localdomain" {
- //do not actively connect to the master by leaving out the 'host' attribute
- log_duration = 0
- }
+object Endpoint "icinga2-master1.localdomain" {
+ //do not actively connect to the master by leaving out the 'host' attribute
+ log_duration = 0
+}
+```
It is not necessary that both the master and the client node establish
two connections to each other. Icinga 2 will only use one connection
@@ -2553,35 +2737,57 @@ client is not connected.
Configuration on the master node `icinga2-master1.localdomain`:
- [root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-master1.localdomain /]# vim /etc/icinga2/zones.conf
- //...
+//...
- object Endpoint "icinga2-client1.localdomain" {
- host = "192.168.56.111" //the master actively tries to connect to the client
- log_duration = 0
- }
+object Endpoint "icinga2-client1.localdomain" {
+ host = "192.168.56.111" //the master actively tries to connect to the client
+ log_duration = 0
+}
- object Endpoint "icinga2-client2.localdomain" {
- host = "192.168.56.112" //the master actively tries to connect to the client
- log_duration = 0
- }
+object Endpoint "icinga2-client2.localdomain" {
+ host = "192.168.56.112" //the master actively tries to connect to the client
+ log_duration = 0
+}
+```
Configuration on the client `icinga2-client1.localdomain`:
- [root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
+
+//...
+
+object Endpoint "icinga2-master1.localdomain" {
+ //do not actively connect to the master by leaving out the 'host' attribute
+ log_duration = 0
+}
+
+object Endpoint "icinga2-master2.localdomain" {
+ //do not actively connect to the master by leaving out the 'host' attribute
+ log_duration = 0
+}
+```
+
+### Initial Sync for new Endpoints in a Zone <a id="distributed-monitoring-advanced-hints-initial-sync"></a>
- //...
+In order to make sure that all of your zone endpoints have the same state you need
+to pick the authoritative running one and copy the following content:
- object Endpoint "icinga2-master1.localdomain" {
- //do not actively connect to the master by leaving out the 'host' attribute
- log_duration = 0
- }
+* State file from `/var/lib/icinga2/icinga2.state`
+* Internal config package for runtime created objects (downtimes, comments, hosts, etc.) at `/var/lib/icinga2/api/packages/_api`
- object Endpoint "icinga2-master2.localdomain" {
- //do not actively connect to the master by leaving out the 'host' attribute
- log_duration = 0
- }
+If you need already deployed config packages from the Director, or synced cluster zones,
+you can also sync the entire `/var/lib/icinga2` directory. This directory should also be
+included in your [backup strategy](02-getting-started.md#install-backup).
+
+> **Note**
+>
+> Ensure that all endpoints are shut down during this procedure. Once you have
+> synced the cached files, proceed with configuring the remaining endpoints
+> to let them know about the new master/satellite node (zones.conf).
### Manual Certificate Creation <a id="distributed-monitoring-advanced-hints-certificates-manual"></a>
@@ -2592,7 +2798,9 @@ Choose the host which should store the certificate authority (one of the master
The first step is the creation of the certificate authority (CA) by running the following command
as root user:
- [root@icinga2-master1.localdomain /root]# icinga2 pki new-ca
+```
+[root@icinga2-master1.localdomain /root]# icinga2 pki new-ca
+```
#### Create CSR and Certificate <a id="distributed-monitoring-advanced-hints-certificates-manual-create"></a>
@@ -2674,7 +2882,9 @@ This will tremendously help when someone is trying to help in the [community cha
If you want to install the client silently/unattended, use the `/qn` modifier. The
installation should not trigger a restart, but if you want to be completely sure, you can use the `/norestart` modifier.
- C:> msiexec /i C:\Icinga2-v2.5.0-x86.msi /qn /norestart
+```
+C:> msiexec /i C:\Icinga2-v2.5.0-x86.msi /qn /norestart
+```
Once the setup is completed you can use the `node setup` cli command too.
@@ -2708,7 +2918,9 @@ Example:
In case you want to bind the `ApiListener` object to a specific
host/port you can specify it like this:
- --listen 192.68.56.101,5665
+```
+--listen 192.68.56.101,5665
+```
In case you don't need anything in `conf.d`, use the following command line:
@@ -2722,8 +2934,10 @@ In case you don't need anything in `conf.d`, use the following command line:
Make sure that the `/var/lib/icinga2/certs` directory exists and is owned by the `icinga`
user (or the user Icinga 2 is running as).
- [root@icinga2-client1.localdomain /]# mkdir -p /var/lib/icinga2/certs
- [root@icinga2-client1.localdomain /]# chown -R icinga:icinga /var/lib/icinga2/certs
+```
+[root@icinga2-client1.localdomain /]# mkdir -p /var/lib/icinga2/certs
+[root@icinga2-client1.localdomain /]# chown -R icinga:icinga /var/lib/icinga2/certs
+```
First you'll need to generate a new local self-signed certificate.
Pass the following details to the `pki new-cert` CLI command:
@@ -2735,9 +2949,11 @@ Pass the following details to the `pki new-cert` CLI command:
Example:
- [root@icinga2-client1.localdomain /]# icinga2 pki new-cert --cn icinga2-client1.localdomain \
- --key /var/lib/icinga2/certs/icinga2-client1.localdomain.key \
- --cert /var/lib/icinga2/certs/icinga2-client1.localdomain.crt
+```
+[root@icinga2-client1.localdomain /]# icinga2 pki new-cert --cn icinga2-client1.localdomain \
+--key /var/lib/icinga2/certs/icinga2-client1.localdomain.key \
+--cert /var/lib/icinga2/certs/icinga2-client1.localdomain.crt
+```
Request the master certificate from the master host (`icinga2-master1.localdomain`)
and store it as `trusted-master.crt`. Review it and continue.
@@ -2752,10 +2968,12 @@ Pass the following details to the `pki save-cert` CLI command:
Example:
- [root@icinga2-client1.localdomain /]# icinga2 pki save-cert --key /var/lib/icinga2/certs/icinga2-client1.localdomain.key \
- --cert /var/lib/icinga2/certs/icinga2-client1.localdomain.crt \
- --trustedcert /var/lib/icinga2/certs/trusted-parent.crt \
- --host icinga2-master1.localdomain
+```
+[root@icinga2-client1.localdomain /]# icinga2 pki save-cert --key /var/lib/icinga2/certs/icinga2-client1.localdomain.key \
+--cert /var/lib/icinga2/certs/icinga2-client1.localdomain.crt \
+--trustedcert /var/lib/icinga2/certs/trusted-parent.crt \
+--host icinga2-master1.localdomain
+```
Continue with the additional node setup step. Specify a local endpoint and zone name (`icinga2-client1.localdomain`)
and set the master host (`icinga2-master1.localdomain`) as parent zone configuration. Specify the path to
@@ -2798,17 +3016,23 @@ Example for Icinga 2 v2.9:
In case the client should connect to the master node, you'll
need to modify the `--endpoint` parameter using the format `cn,host,port`:
- --endpoint icinga2-master1.localdomain,192.168.56.101,5665
+```
+--endpoint icinga2-master1.localdomain,192.168.56.101,5665
+```
Specify the parent zone using the `--parent_zone` parameter. This is useful
if the client connects to a satellite, not the master instance.
- --parent_zone satellite
+```
+--parent_zone satellite
+```
In case the client should know the additional global zone `linux-templates`, you'll
need to set the `--global-zones` parameter.
- --global_zones linux-templates
+```
+--global_zones linux-templates
+```
The `--parent-host` parameter is optional since v2.9 and allows you to perform a connection-less setup.
You cannot restart Icinga 2 yet, the CLI command asked to to manually copy the parent's public CA
@@ -2825,46 +3049,58 @@ which holds the CA's key pair.
If this client node is configured as [remote command endpoint execution](06-distributed-monitoring.md#distributed-monitoring-top-down-command-endpoint)
you can safely disable the `checker` feature. The `node setup` CLI command already disabled the `notification` feature.
- [root@icinga2-client1.localdomain /]# icinga2 feature disable checker
+```
+[root@icinga2-client1.localdomain /]# icinga2 feature disable checker
+```
Disable "conf.d" inclusion if this is a [top down](06-distributed-monitoring.md#distributed-monitoring-top-down)
configured client.
- [root@icinga2-client1.localdomain /]# sed -i 's/include_recursive "conf.d"/\/\/include_recursive "conf.d"/g' /etc/icinga2/icinga2.conf
+```
+[root@icinga2-client1.localdomain /]# sed -i 's/include_recursive "conf.d"/\/\/include_recursive "conf.d"/g' /etc/icinga2/icinga2.conf
+```
**Note**: This is the default since v2.9.
**Optional**: Add an ApiUser object configuration for remote troubleshooting.
- [root@icinga2-client1.localdomain /]# cat <<EOF >/etc/icinga2/conf.d/api-users.conf
- object ApiUser "root" {
- password = "clientsupersecretpassword"
- permissions = ["*"]
- }
- EOF
+```
+[root@icinga2-client1.localdomain /]# cat <<EOF >/etc/icinga2/conf.d/api-users.conf
+object ApiUser "root" {
+ password = "clientsupersecretpassword"
+ permissions = ["*"]
+}
+EOF
+```
In case you've previously disabled the "conf.d" directory only
add the file file `conf.d/api-users.conf`:
- [root@icinga2-client1.localdomain /]# echo 'include "conf.d/api-users.conf"' >> /etc/icinga2/icinga2.conf
+```
+[root@icinga2-client1.localdomain /]# echo 'include "conf.d/api-users.conf"' >> /etc/icinga2/icinga2.conf
+```
Finally restart Icinga 2.
- [root@icinga2-client1.localdomain /]# systemctl restart icinga2
+```
+[root@icinga2-client1.localdomain /]# systemctl restart icinga2
+```
Your automation tool must then configure master node in the meantime.
- # cat <<EOF >>/etc/icinga2/zones.conf
- object Endpoint "icinga2-client1.localdomain" {
- //client connects itself
- }
+```
+# cat <<EOF >>/etc/icinga2/zones.conf
+object Endpoint "icinga2-client1.localdomain" {
+ //client connects itself
+}
- object Zone "icinga2-client1.localdomain" {
- endpoints = [ "icinga2-client1.localdomain" ]
- parent = "master"
- }
+object Zone "icinga2-client1.localdomain" {
+ endpoints = [ "icinga2-client1.localdomain" ]
+ parent = "master"
+}
- EOF
+EOF
+```
## Using Multiple Environments <a id="distributed-monitoring-environments"></a>
diff --git a/doc/07-agent-based-monitoring.md b/doc/07-agent-based-monitoring.md
index 48c0d1c..99e4615 100644
--- a/doc/07-agent-based-monitoring.md
+++ b/doc/07-agent-based-monitoring.md
@@ -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
diff --git a/doc/08-advanced-topics.md b/doc/08-advanced-topics.md
index 858323f..a7acb95 100644
--- a/doc/08-advanced-topics.md
+++ b/doc/08-advanced-topics.md
@@ -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>
diff --git a/doc/09-object-types.md b/doc/09-object-types.md
index b785d1f..dc21013 100644
--- a/doc/09-object-types.md
+++ b/doc/09-object-types.md
@@ -1,4 +1,4 @@
-# Config Object Types <a id="object-types"></a>
+# Object Types <a id="object-types"></a>
This chapter provides an overview of all available config object types which can be
instantiated using the `object` keyword.
@@ -12,6 +12,14 @@ You should note that the `Timestamp` type is a `Number`.
In addition to that `Object name` is an object reference to
an existing object name as `String` type.
+## Overview <a id="object-types-overview"></a>
+
+* [Monitoring Objects](09-object-types.md#object-types-monitoring) such as host, service, etc.
+* [Runtime Objects](09-object-types.md#object-types-runtime) generated by Icinga itself.
+* [Features](09-object-types.md#object-types-features) available via `icinga2 feature` CLI command.
+
+## Common Runtime Attributes <a id="object-types-runtime-attributes"></a>
+
Configuration objects share these runtime attributes which cannot be
modified by the user. You can access these attributes using
the [Icinga 2 API](12-icinga2-api.md#icinga2-api-config-objects).
@@ -27,77 +35,9 @@ the [Icinga 2 API](12-icinga2-api.md#icinga2-api-config-objects).
package | String | [Configuration package name](12-icinga2-api.md#icinga2-api-config-management) this object belongs to. Local configuration is set to `_etc`, runtime created objects use `_api`.
source\_location | Dictionary | Location information where the configuration files are stored.
+## Monitoring Objects <a id="object-types-monitoring"></a>
-## ApiListener <a id="objecttype-apilistener"></a>
-
-ApiListener objects are used for distributed monitoring setups
-and API usage specifying the certificate files used for ssl
-authorization and additional restrictions.
-This configuration object is available as [api feature](11-cli-commands.md#cli-command-feature).
-
-The `TicketSalt` constant must be defined in [constants.conf](04-configuring-icinga-2.md#constants-conf).
-
-Example:
-
-```
-object ApiListener "api" {
- accept_commands = true
- accept_config = true
-
- ticket_salt = TicketSalt
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------------------|-----------------------|----------------------------------
- cert\_path | String | **Deprecated.** Path to the public key.
- key\_path | String | **Deprecated.** Path to the private key.
- ca\_path | String | **Deprecated.** Path to the CA certificate file.
- ticket\_salt | String | **Optional.** Private key for [CSR auto-signing](06-distributed-monitoring.md#distributed-monitoring-setup-csr-auto-signing). **Required** for a signing master instance.
- crl\_path | String | **Optional.** Path to the CRL file.
- bind\_host | String | **Optional.** The IP address the api listener should be bound to. Defaults to `0.0.0.0`.
- bind\_port | Number | **Optional.** The port the api listener should be bound to. Defaults to `5665`.
- accept\_config | Boolean | **Optional.** Accept zone configuration. Defaults to `false`.
- accept\_commands | Boolean | **Optional.** Accept remote commands. Defaults to `false`.
- max\_anonymous\_clients | Number | **Optional.** Limit the number of anonymous client connections (not configured endpoints and signing requests).
- cipher\_list | String | **Optional.** Cipher list that is allowed. For a list of available ciphers run `openssl ciphers`. Defaults to `ALL:!LOW:!WEAK:!MEDIUM:!EXP:!NULL`.
- tls\_protocolmin | String | **Optional.** Minimum TLS protocol version. Must be one of `TLSv1`, `TLSv1.1` or `TLSv1.2`. Defaults to `TLSv1`.
- tls\_handshake\_timeout | Number | **Optional.** TLS Handshake timeout. Defaults to `10s`.
- access\_control\_allow\_origin | Array | **Optional.** Specifies an array of origin URLs that may access the API. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Origin)
- access\_control\_allow\_credentials | Boolean | **Deprecated.** Indicates whether or not the actual request can be made using credentials. Defaults to `true`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Credentials)
- access\_control\_allow\_headers | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request. Defaults to `Authorization`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Headers)
- access\_control\_allow\_methods | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP methods can be used when making the actual request. Defaults to `GET, POST, PUT, DELETE`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Methods)
- environment | String | **Optional.** Used as suffix in TLS SNI extension name; default from constant `ApiEnvironment`, which is empty.
-
-The attributes `access_control_allow_credentials`, `access_control_allow_headers` and `access_control_allow_methods`
-are controlled by Icinga 2 and are not changeable by config any more.
-
-
-The ApiListener type expects its certificate files to be in the following locations:
-
- Type | Location
- ---------------------|-------------------------------------
- Private key | `DataDir + "/certs/" + NodeName + ".key"`
- Certificate file | `DataDir + "/certs/" + NodeName + ".crt"`
- CA certificate file | `DataDir + "/certs/ca.crt"`
-
-If the deprecated attributes `cert_path`, `key_path` and/or `ca_path` are specified Icinga 2
-copies those files to the new location in `DataDir + "/certs"` unless the
-file(s) there are newer.
-
-Please check the [upgrading chapter](16-upgrading-icinga-2.md#upgrading-to-2-8-certificate-paths) for more details.
-
-While Icinga 2 and the underlying OpenSSL library use sane and secure defaults, the attributes
-`cipher_list` and `tls_protocolmin` can be used to increase communication security. A good source
-for a more secure configuration is provided by the [Mozilla Wiki](https://wiki.mozilla.org/Security/Server_Side_TLS).
-Ensure to use the same configuration for both attributes on **all** endpoints to avoid communication problems which
-requires to use `cipher_list` compatible with the endpoint using the oldest version of the OpenSSL library. If using
-other tools to connect to the API ensure also compatibility with them as this setting affects not only inter-cluster
-communcation but also the REST API.
-
-## ApiUser <a id="objecttype-apiuser"></a>
+### ApiUser <a id="objecttype-apiuser"></a>
ApiUser objects are used for authentication against the [Icinga 2 API](12-icinga2-api.md#icinga2-api-authentication).
@@ -121,7 +61,7 @@ Configuration Attributes:
Available permissions are explained in the [API permissions](12-icinga2-api.md#icinga2-api-permissions)
chapter.
-## CheckCommand <a id="objecttype-checkcommand"></a>
+### CheckCommand <a id="objecttype-checkcommand"></a>
A check command definition. Additional default command custom attributes can be
defined here.
@@ -173,7 +113,7 @@ Configuration Attributes:
arguments | Dictionary | **Optional.** A dictionary of command arguments.
-### CheckCommand Arguments <a id="objecttype-checkcommand-arguments"></a>
+#### CheckCommand Arguments <a id="objecttype-checkcommand-arguments"></a>
Command arguments can be defined as key-value-pairs in the `arguments`
dictionary. If the argument requires additional configuration, for example
@@ -248,93 +188,6 @@ Argument array with `repeat_key = false`:
'key' 'value[0]' 'value[1]' 'value[2]'
```
-## CheckerComponent <a id="objecttype-checkcomponent"></a>
-
-The checker component is responsible for scheduling active checks.
-This configuration object is available as [checker feature](11-cli-commands.md#cli-command-feature).
-
-Example:
-
-```
-object CheckerComponent "checker" { }
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- concurrent\_checks | Number | **Optional and deprecated.** The maximum number of concurrent checks. Was replaced by global constant `MaxConcurrentChecks` which will be set if you still use `concurrent_checks`.
-
-## CheckResultReader <a id="objecttype-checkresultreader"></a>
-
-Reads Icinga 1.x check result files from a directory. This functionality is provided
-to help existing Icinga 1.x users and might be useful for migration scenarios.
-
-Example:
-
-```
-object CheckResultReader "reader" {
- spool_dir = "/data/check-results"
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- spool\_dir | String | **Optional.** The directory which contains the check result files. Defaults to DataDir + "/spool/checkresults/".
-
-## Comment <a id="objecttype-comment"></a>
-
-Comments created at runtime are represented as objects.
-Note: This is for reference only. You can create comments
-with the [add-comment](12-icinga2-api.md#icinga2-api-actions-add-comment) API action.
-
-Example:
-
-```
-object Comment "localhost!my-comment" {
- host_name = "localhost"
- author = "icingaadmin"
- text = "This is a comment."
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- host\_name | Object name | **Required.** The name of the host this comment belongs to.
- service\_name | Object name | **Optional.** The short name of the service this comment belongs to. If omitted, this comment object is treated as host comment.
- author | String | **Required.** The author's name.
- text | String | **Required.** The comment text.
- entry\_time | Timestamp | **Optional.** The UNIX timestamp when this comment was added.
- entry\_type | Number | **Optional.** The comment type (`User` = 1, `Downtime` = 2, `Flapping` = 3, `Acknowledgement` = 4).
- expire\_time | Timestamp | **Optional.** The comment's expire time as UNIX timestamp.
- persistent | Boolean | **Optional.** Only evaluated for `entry_type` Acknowledgement. `true` does not remove the comment when the acknowledgement is removed.
-
-## CompatLogger <a id="objecttype-compatlogger"></a>
-
-Writes log files in a format that's compatible with Icinga 1.x.
-This configuration object is available as [compatlog feature](14-features.md#compat-logging).
-
-Example:
-
-```
-object CompatLogger "compatlog" {
- log_dir = "/var/log/icinga2/compat"
- rotation_method = "DAILY"
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- log\_dir | String | **Optional.** Path to the compat log directory. Defaults to LogDir + "/compat".
- rotation\_method | String | **Optional.** Specifies when to rotate log files. Can be one of "HOURLY", "DAILY", "WEEKLY" or "MONTHLY". Defaults to "HOURLY".
-
-
## Dependency <a id="objecttype-dependency"></a>
Dependency objects are used to specify dependencies between hosts and services. Dependencies
@@ -395,12 +248,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.
@@ -439,95 +294,6 @@ Dependency objects have composite names, i.e. their names are based on the `chil
name you specified. This means you can define more than one object with the same (short) name as long as one of the `child_host_name` and
`child_service_name` attributes has a different value.
-## Downtime <a id="objecttype-downtime"></a>
-
-Downtimes created at runtime are represented as objects.
-You can create downtimes with the [schedule-downtime](12-icinga2-api.md#icinga2-api-actions-schedule-downtime) API action.
-
-Example:
-
-```
-object Downtime "my-downtime" {
- host_name = "localhost"
- author = "icingaadmin"
- comment = "This is a downtime."
- start_time = 1505312869
- end_time = 1505312924
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- host\_name | Object name | **Required.** The name of the host this comment belongs to.
- service\_name | Object name | **Optional.** The short name of the service this comment belongs to. If omitted, this comment object is treated as host comment.
- author | String | **Required.** The author's name.
- comment | String | **Required.** The comment text.
- start\_time | Timestamp | **Required.** The start time as UNIX timestamp.
- end\_time | Timestamp | **Required.** The end time as UNIX timestamp.
- duration | Number | **Optional.** The duration as number.
- entry\_time | Timestamp | **Optional.** The UNIX timestamp when this downtime was added.
- fixed | Boolean | **Optional.** Whether the downtime is fixed (true) or flexible (false). Defaults to flexible. Details in the [advanced topics chapter](08-advanced-topics.md#fixed-flexible-downtimes).
- triggers | Array of object names | **Optional.** List of downtimes which should be triggered by this downtime.
-
-Runtime Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- trigger\_time | Timestamp | The UNIX timestamp when this downtime was triggered.
- triggered\_by | Object name | The name of the downtime this downtime was triggered by.
-
-
-## ElasticsearchWriter <a id="objecttype-elasticsearchwriter"></a>
-
-Writes check result metrics and performance data to an Elasticsearch instance.
-This configuration object is available as [elasticsearch feature](14-features.md#elasticsearch-writer).
-
-Example:
-
-```
-object ElasticsearchWriter "elasticsearch" {
- host = "127.0.0.1"
- port = 9200
- index = "icinga2"
-
- enable_send_perfdata = true
-
- flush_threshold = 1024
- flush_interval = 10
-}
-```
-
-The index is rotated daily, as is recommended by Elastic, meaning the index will be renamed to `$index-$d.$M.$y`.
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- host | String | **Required.** Elasticsearch host address. Defaults to `127.0.0.1`.
- port | Number | **Required.** Elasticsearch port. Defaults to `9200`.
- index | String | **Required.** Elasticsearch index name. Defaults to `icinga2`.
- enable\_send\_perfdata | Boolean | **Optional.** Send parsed performance data metrics for check results. Defaults to `false`.
- flush\_interval | Duration | **Optional.** How long to buffer data points before transferring to Elasticsearch. Defaults to `10s`.
- flush\_threshold | Number | **Optional.** How many data points to buffer before forcing a transfer to Elasticsearch. Defaults to `1024`.
- username | String | **Optional.** Basic auth username if Elasticsearch is hidden behind an HTTP proxy.
- password | String | **Optional.** Basic auth password if Elasticsearch is hidden behind an HTTP proxy.
- enable\_tls | Boolean | **Optional.** Whether to use a TLS stream. Defaults to `false`. Requires an HTTP proxy.
- ca\_path | String | **Optional.** Path to CA certificate to validate the remote host. Requires `enable_tls` set to `true`.
- cert\_path | String | **Optional.** Path to host certificate to present to the remote host for mutual verification. Requires `enable_tls` set to `true`.
- key\_path | String | **Optional.** Path to host key to accompany the cert\_path. Requires `enable_tls` set to `true`.
-
-Note: If `flush_threshold` is set too low, this will force the feature to flush all data to Elasticsearch too often.
-Experiment with the setting, if you are processing more than 1024 metrics per second or similar.
-
-Basic auth is supported with the `username` and `password` attributes. This requires an
-HTTP proxy (Nginx, etc.) in front of the Elasticsearch instance. Check [this blogpost](https://blog.netways.de/2017/09/14/secure-elasticsearch-and-kibana-with-an-nginx-http-proxy/)
-for an example.
-
-TLS for the HTTP proxy can be enabled with `enable_tls`. In addition to that
-you can specify the certificates with the `ca_path`, `cert_path` and `cert_key` attributes.
-
## Endpoint <a id="objecttype-endpoint"></a>
Endpoint objects are used to specify connection information for remote
@@ -590,102 +356,6 @@ Command arguments can be used the same way as for [CheckCommand objects](09-obje
More advanced examples for event command usage can be found [here](03-monitoring-basics.md#event-commands).
-## ExternalCommandListener <a id="objecttype-externalcommandlistener"></a>
-
-Implements the Icinga 1.x command pipe which can be used to send commands to Icinga.
-This configuration object is available as [command feature](14-features.md#external-commands).
-
-Example:
-
-```
-object ExternalCommandListener "command" {
- command_path = "/var/run/icinga2/cmd/icinga2.cmd"
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- command\_path | String | **Optional.** Path to the command pipe. Defaults to RunDir + "/icinga2/cmd/icinga2.cmd".
-
-
-
-## FileLogger <a id="objecttype-filelogger"></a>
-
-Specifies Icinga 2 logging to a file.
-This configuration object is available as `mainlog` and `debuglog` [logging feature](14-features.md#logging).
-
-Example:
-
-```
-object FileLogger "debug-file" {
- severity = "debug"
- path = "/var/log/icinga2/debug.log"
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- path | String | **Required.** The log path.
- severity | String | **Optional.** The minimum severity for this log. Can be "debug", "notice", "information", "warning" or "critical". Defaults to "information".
-
-
-## GelfWriter <a id="objecttype-gelfwriter"></a>
-
-Writes event log entries to a defined GELF receiver host (Graylog, Logstash).
-This configuration object is available as [gelf feature](14-features.md#gelfwriter).
-
-Example:
-
-```
-object GelfWriter "gelf" {
- host = "127.0.0.1"
- port = 12201
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- host | String | **Optional.** GELF receiver host address. Defaults to `127.0.0.1`.
- port | Number | **Optional.** GELF receiver port. Defaults to `12201`.
- source | String | **Optional.** Source name for this instance. Defaults to `icinga2`.
- enable\_send\_perfdata | Boolean | **Optional.** Enable performance data for 'CHECK RESULT' events.
-
-
-## GraphiteWriter <a id="objecttype-graphitewriter"></a>
-
-Writes check result metrics and performance data to a defined
-Graphite Carbon host.
-This configuration object is available as [graphite feature](14-features.md#graphite-carbon-cache-writer).
-
-Example:
-
-```
-object GraphiteWriter "graphite" {
- host = "127.0.0.1"
- port = 2003
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- host | String | **Optional.** Graphite Carbon host address. Defaults to `127.0.0.1`.
- port | Number | **Optional.** Graphite Carbon port. Defaults to `2003`.
- host\_name\_template | String | **Optional.** Metric prefix for host name. Defaults to `icinga2.$host.name$.host.$host.check_command$`.
- service\_name\_template | String | **Optional.** Metric prefix for service name. Defaults to `icinga2.$host.name$.services.$service.name$.$service.check_command$`.
- enable\_send\_thresholds | Boolean | **Optional.** Send additional threshold metrics. Defaults to `false`.
- enable\_send\_metadata | Boolean | **Optional.** Send additional metadata metrics. Defaults to `false`.
-
-Additional usage examples can be found [here](14-features.md#graphite-carbon-cache-writer).
-
-
## Host <a id="objecttype-host"></a>
@@ -799,306 +469,6 @@ Configuration Attributes:
display\_name | String | **Optional.** A short description of the host group.
groups | Array of object names | **Optional.** An array of nested group names.
-## IcingaApplication <a id="objecttype-icingaapplication"></a>
-
-The IcingaApplication object is required to start Icinga 2.
-The object name must be `app`. If the object configuration
-is missing, Icinga 2 will automatically create an IcingaApplication
-object.
-
-Example:
-
-```
-object IcingaApplication "app" {
- enable_perfdata = false
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- enable\_notifications | Boolean | **Optional.** Whether notifications are globally enabled. Defaults to true.
- enable\_event\_handlers | Boolean | **Optional.** Whether event handlers are globally enabled. Defaults to true.
- enable\_flapping | Boolean | **Optional.** Whether flap detection is globally enabled. Defaults to true.
- enable\_host\_checks | Boolean | **Optional.** Whether active host checks are globally enabled. Defaults to true.
- enable\_service\_checks | Boolean | **Optional.** Whether active service checks are globally enabled. Defaults to true.
- enable\_perfdata | Boolean | **Optional.** Whether performance data processing is globally enabled. Defaults to true.
- vars | Dictionary | **Optional.** A dictionary containing custom attributes that are available globally.
- environment | String | **Optional.** Specify the Icinga environment. This overrides the `Environment` constant specified in the configuration or on the CLI with `--define`. Defaults to empty.
-
-## IdoMySqlConnection <a id="objecttype-idomysqlconnection"></a>
-
-IDO database adapter for MySQL.
-This configuration object is available as [ido-mysql feature](14-features.md#db-ido).
-
-Example:
-
-```
-object IdoMysqlConnection "mysql-ido" {
- host = "127.0.0.1"
- port = 3306
- user = "icinga"
- password = "icinga"
- database = "icinga"
-
- cleanup = {
- downtimehistory_age = 48h
- contactnotifications_age = 31d
- }
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- host | String | **Optional.** MySQL database host address. Defaults to `localhost`.
- port | Number | **Optional.** MySQL database port. Defaults to `3306`.
- socket\_path | String | **Optional.** MySQL socket path.
- user | String | **Optional.** MySQL database user with read/write permission to the icinga database. Defaults to `icinga`.
- password | String | **Optional.** MySQL database user's password. Defaults to `icinga`.
- database | String | **Optional.** MySQL database name. Defaults to `icinga`.
- enable\_ssl | Boolean | **Optional.** Use SSL. Defaults to false. Change to `true` in case you want to use any of the SSL options.
- ssl\_key | String | **Optional.** MySQL SSL client key file path.
- ssl\_cert | String | **Optional.** MySQL SSL certificate file path.
- ssl\_ca | String | **Optional.** MySQL SSL certificate authority certificate file path.
- ssl\_capath | String | **Optional.** MySQL SSL trusted SSL CA certificates in PEM format directory path.
- ssl\_cipher | String | **Optional.** MySQL SSL list of allowed ciphers.
- table\_prefix | String | **Optional.** MySQL database table prefix. Defaults to `icinga_`.
- instance\_name | String | **Optional.** Unique identifier for the local Icinga 2 instance. Defaults to `default`.
- instance\_description | String | **Optional.** Description for the Icinga 2 instance.
- enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-db-ido). Defaults to "true".
- failover\_timeout | Duration | **Optional.** Set the failover timeout in a [HA cluster](06-distributed-monitoring.md#distributed-monitoring-high-availability-db-ido). Must not be lower than 60s. Defaults to `60s`.
- cleanup | Dictionary | **Optional.** Dictionary with items for historical table cleanup.
- categories | Array | **Optional.** Array of information types that should be written to the database.
-
-Cleanup Items:
-
- Name | Type | Description
- --------------------------------|-----------------------|----------------------------------
- acknowledgements\_age | Duration | **Optional.** Max age for acknowledgements table rows (entry\_time). Defaults to 0 (never).
- commenthistory\_age | Duration | **Optional.** Max age for commenthistory table rows (entry\_time). Defaults to 0 (never).
- contactnotifications\_age | Duration | **Optional.** Max age for contactnotifications table rows (start\_time). Defaults to 0 (never).
- contactnotificationmethods\_age | Duration | **Optional.** Max age for contactnotificationmethods table rows (start\_time). Defaults to 0 (never).
- downtimehistory\_age | Duration | **Optional.** Max age for downtimehistory table rows (entry\_time). Defaults to 0 (never).
- eventhandlers\_age | Duration | **Optional.** Max age for eventhandlers table rows (start\_time). Defaults to 0 (never).
- externalcommands\_age | Duration | **Optional.** Max age for externalcommands table rows (entry\_time). Defaults to 0 (never).
- flappinghistory\_age | Duration | **Optional.** Max age for flappinghistory table rows (event\_time). Defaults to 0 (never).
- hostchecks\_age | Duration | **Optional.** Max age for hostalives table rows (start\_time). Defaults to 0 (never).
- logentries\_age | Duration | **Optional.** Max age for logentries table rows (logentry\_time). Defaults to 0 (never).
- notifications\_age | Duration | **Optional.** Max age for notifications table rows (start\_time). Defaults to 0 (never).
- processevents\_age | Duration | **Optional.** Max age for processevents table rows (event\_time). Defaults to 0 (never).
- statehistory\_age | Duration | **Optional.** Max age for statehistory table rows (state\_time). Defaults to 0 (never).
- servicechecks\_age | Duration | **Optional.** Max age for servicechecks table rows (start\_time). Defaults to 0 (never).
- systemcommands\_age | Duration | **Optional.** Max age for systemcommands table rows (start\_time). Defaults to 0 (never).
-
-Data Categories:
-
- Name | Description | Required by
- ---------------------|------------------------|--------------------
- DbCatConfig | Configuration data | Icinga Web 2
- DbCatState | Current state data | Icinga Web 2
- DbCatAcknowledgement | Acknowledgements | Icinga Web 2
- DbCatComment | Comments | Icinga Web 2
- DbCatDowntime | Downtimes | Icinga Web 2
- DbCatEventHandler | Event handler data | Icinga Web 2
- DbCatExternalCommand | External commands | --
- DbCatFlapping | Flap detection data | Icinga Web 2
- DbCatCheck | Check results | --
- DbCatLog | Log messages | --
- DbCatNotification | Notifications | Icinga Web 2
- DbCatProgramStatus | Program status data | Icinga Web 2
- DbCatRetention | Retention data | Icinga Web 2
- DbCatStateHistory | Historical state data | Icinga Web 2
-
-The default value for `categories` includes everything required
-by Icinga Web 2 in the table above.
-
-In addition to the category flags listed above the `DbCatEverything`
-flag may be used as a shortcut for listing all flags.
-
-## IdoPgsqlConnection <a id="objecttype-idopgsqlconnection"></a>
-
-IDO database adapter for PostgreSQL.
-This configuration object is available as [ido-pgsql feature](14-features.md#db-ido).
-
-Example:
-
-```
-object IdoPgsqlConnection "pgsql-ido" {
- host = "127.0.0.1"
- port = 5432
- user = "icinga"
- password = "icinga"
- database = "icinga"
-
- cleanup = {
- downtimehistory_age = 48h
- contactnotifications_age = 31d
- }
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- host | String | **Optional.** PostgreSQL database host address. Defaults to `localhost`.
- port | Number | **Optional.** PostgreSQL database port. Defaults to `5432`.
- user | String | **Optional.** PostgreSQL database user with read/write permission to the icinga database. Defaults to `icinga`.
- password | String | **Optional.** PostgreSQL database user's password. Defaults to `icinga`.
- database | String | **Optional.** PostgreSQL database name. Defaults to `icinga`.
- ssl\_mode | String | **Optional.** Enable SSL connection mode. Value must be set according to the [sslmode setting](https://www.postgresql.org/docs/9.3/static/libpq-connect.html#LIBPQ-CONNSTRING): `prefer`, `require`, `verify-ca`, `verify-full`, `allow`, `disable`.
- ssl\_key | String | **Optional.** PostgreSQL SSL client key file path.
- ssl\_cert | String | **Optional.** PostgreSQL SSL certificate file path.
- ssl\_ca | String | **Optional.** PostgreSQL SSL certificate authority certificate file path.
- table\_prefix | String | **Optional.** PostgreSQL database table prefix. Defaults to `icinga_`.
- instance\_name | String | **Optional.** Unique identifier for the local Icinga 2 instance. Defaults to `default`.
- instance\_description | String | **Optional.** Description for the Icinga 2 instance.
- enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-db-ido). Defaults to "true".
- failover\_timeout | Duration | **Optional.** Set the failover timeout in a [HA cluster](06-distributed-monitoring.md#distributed-monitoring-high-availability-db-ido). Must not be lower than 60s. Defaults to `60s`.
- cleanup | Dictionary | **Optional.** Dictionary with items for historical table cleanup.
- categories | Array | **Optional.** Array of information types that should be written to the database.
-
-Cleanup Items:
-
- Name | Type | Description
- --------------------------------|-----------------------|----------------------------------
- acknowledgements\_age | Duration | **Optional.** Max age for acknowledgements table rows (entry\_time). Defaults to 0 (never).
- commenthistory\_age | Duration | **Optional.** Max age for commenthistory table rows (entry\_time). Defaults to 0 (never).
- contactnotifications\_age | Duration | **Optional.** Max age for contactnotifications table rows (start\_time). Defaults to 0 (never).
- contactnotificationmethods\_age | Duration | **Optional.** Max age for contactnotificationmethods table rows (start\_time). Defaults to 0 (never).
- downtimehistory\_age | Duration | **Optional.** Max age for downtimehistory table rows (entry\_time). Defaults to 0 (never).
- eventhandlers\_age | Duration | **Optional.** Max age for eventhandlers table rows (start\_time). Defaults to 0 (never).
- externalcommands\_age | Duration | **Optional.** Max age for externalcommands table rows (entry\_time). Defaults to 0 (never).
- flappinghistory\_age | Duration | **Optional.** Max age for flappinghistory table rows (event\_time). Defaults to 0 (never).
- hostchecks\_age | Duration | **Optional.** Max age for hostalives table rows (start\_time). Defaults to 0 (never).
- logentries\_age | Duration | **Optional.** Max age for logentries table rows (logentry\_time). Defaults to 0 (never).
- notifications\_age | Duration | **Optional.** Max age for notifications table rows (start\_time). Defaults to 0 (never).
- processevents\_age | Duration | **Optional.** Max age for processevents table rows (event\_time). Defaults to 0 (never).
- statehistory\_age | Duration | **Optional.** Max age for statehistory table rows (state\_time). Defaults to 0 (never).
- servicechecks\_age | Duration | **Optional.** Max age for servicechecks table rows (start\_time). Defaults to 0 (never).
- systemcommands\_age | Duration | **Optional.** Max age for systemcommands table rows (start\_time). Defaults to 0 (never).
-
-Data Categories:
-
- Name | Description | Required by
- ---------------------|------------------------|--------------------
- DbCatConfig | Configuration data | Icinga Web 2
- DbCatState | Current state data | Icinga Web 2
- DbCatAcknowledgement | Acknowledgements | Icinga Web 2
- DbCatComment | Comments | Icinga Web 2
- DbCatDowntime | Downtimes | Icinga Web 2
- DbCatEventHandler | Event handler data | Icinga Web 2
- DbCatExternalCommand | External commands | --
- DbCatFlapping | Flap detection data | Icinga Web 2
- DbCatCheck | Check results | --
- DbCatLog | Log messages | --
- DbCatNotification | Notifications | Icinga Web 2
- DbCatProgramStatus | Program status data | Icinga Web 2
- DbCatRetention | Retention data | Icinga Web 2
- DbCatStateHistory | Historical state data | Icinga Web 2
-
-The default value for `categories` includes everything required
-by Icinga Web 2 in the table above.
-
-In addition to the category flags listed above the `DbCatEverything`
-flag may be used as a shortcut for listing all flags.
-
-## InfluxdbWriter <a id="objecttype-influxdbwriter"></a>
-
-Writes check result metrics and performance data to a defined InfluxDB host.
-This configuration object is available as [influxdb feature](14-features.md#influxdb-writer).
-
-Example:
-
-```
-object InfluxdbWriter "influxdb" {
- host = "127.0.0.1"
- port = 8086
- database = "icinga2"
-
- flush_threshold = 1024
- flush_interval = 10s
-
- host_template = {
- measurement = "$host.check_command$"
- tags = {
- hostname = "$host.name$"
- }
- }
- service_template = {
- measurement = "$service.check_command$"
- tags = {
- hostname = "$host.name$"
- service = "$service.name$"
- }
- }
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- host | String | **Required.** InfluxDB host address. Defaults to `127.0.0.1`.
- port | Number | **Required.** InfluxDB HTTP port. Defaults to `8086`.
- database | String | **Required.** InfluxDB database name. Defaults to `icinga2`.
- username | String | **Optional.** InfluxDB user name. Defaults to `none`.
- password | String | **Optional.** InfluxDB user password. Defaults to `none`.
- ssl\_enable | Boolean | **Optional.** Whether to use a TLS stream. Defaults to `false`.
- ssl\_ca\_cert | String | **Optional.** Path to CA certificate to validate the remote host.
- ssl\_cert | String | **Optional.** Path to host certificate to present to the remote host for mutual verification.
- ssl\_key | String | **Optional.** Path to host key to accompany the ssl\_cert.
- host\_template | String | **Required.** Host template to define the InfluxDB line protocol.
- service\_template | String | **Required.** Service template to define the influxDB line protocol.
- enable\_send\_thresholds | Boolean | **Optional.** Whether to send warn, crit, min & max tagged data.
- enable\_send\_metadata | Boolean | **Optional.** Whether to send check metadata e.g. states, execution time, latency etc.
- flush\_interval | Duration | **Optional.** How long to buffer data points before transferring to InfluxDB. Defaults to `10s`.
- flush\_threshold | Number | **Optional.** How many data points to buffer before forcing a transfer to InfluxDB. Defaults to `1024`.
-
-Note: If `flush_threshold` is set too low, this will always force the feature to flush all data
-to InfluxDB. Experiment with the setting, if you are processing more than 1024 metrics per second
-or similar.
-
-
-
-## LiveStatusListener <a id="objecttype-livestatuslistener"></a>
-
-Livestatus API interface available as TCP or UNIX socket. Historical table queries
-require the [CompatLogger](09-object-types.md#objecttype-compatlogger) feature enabled
-pointing to the log files using the `compat_log_path` configuration attribute.
-This configuration object is available as [livestatus feature](14-features.md#setting-up-livestatus).
-
-Examples:
-
-```
-object LivestatusListener "livestatus-tcp" {
- socket_type = "tcp"
- bind_host = "127.0.0.1"
- bind_port = "6558"
-}
-
-object LivestatusListener "livestatus-unix" {
- socket_type = "unix"
- socket_path = "/var/run/icinga2/cmd/livestatus"
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- socket\_type | String | **Optional.** Specifies the socket type. Can be either `tcp` or `unix`. Defaults to `unix`.
- bind\_host | String | **Optional.** Only valid when `socket_type` is set to `tcp`. Host address to listen on for connections. Defaults to `127.0.0.1`.
- bind\_port | Number | **Optional.** Only valid when `socket_type` is set to `tcp`. Port to listen on for connections. Defaults to `6558`.
- socket\_path | String | **Optional.** Only valid when `socket_type` is set to `unix`. Specifies the path to the UNIX socket file. Defaults to RunDir + "/icinga2/cmd/livestatus".
- compat\_log\_path | String | **Optional.** Path to Icinga 1.x log files. Required for historical table queries. Requires `CompatLogger` feature enabled. Defaults to LogDir + "/compat"
-
-> **Note**
->
-> UNIX sockets are not supported on Windows.
## Notification <a id="objecttype-notification"></a>
@@ -1149,27 +519,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:
@@ -1275,82 +651,6 @@ Command arguments can be used the same way as for [CheckCommand objects](09-obje
More details on specific attributes can be found in [this chapter](03-monitoring-basics.md#notification-commands).
-## NotificationComponent <a id="objecttype-notificationcomponent"></a>
-
-The notification component is responsible for sending notifications.
-This configuration object is available as [notification feature](11-cli-commands.md#cli-command-feature).
-
-Example:
-
-```
-object NotificationComponent "notification" { }
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-notifications). Disabling this currently only affects reminder notifications. Defaults to "true".
-
-## OpenTsdbWriter <a id="objecttype-opentsdbwriter"></a>
-
-Writes check result metrics and performance data to [OpenTSDB](http://opentsdb.net).
-This configuration object is available as [opentsdb feature](14-features.md#opentsdb-writer).
-
-Example:
-
-```
-object OpenTsdbWriter "opentsdb" {
- host = "127.0.0.1"
- port = 4242
-
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- host | String | **Optional.** OpenTSDB host address. Defaults to `127.0.0.1`.
- port | Number | **Optional.** OpenTSDB port. Defaults to `4242`.
-
-
-## PerfdataWriter <a id="objecttype-perfdatawriter"></a>
-
-Writes check result performance data to a defined path using macro
-pattern consisting of custom attributes and runtime macros.
-This configuration object is available as [perfdata feature](14-features.md#writing-performance-data-files).
-
-Example:
-
-```
-object PerfdataWriter "perfdata" {
- host_perfdata_path = "/var/spool/icinga2/perfdata/host-perfdata"
-
- service_perfdata_path = "/var/spool/icinga2/perfdata/service-perfdata"
-
- 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$"
-
- rotation_interval = 15s
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- host\_perfdata\_path | String | **Optional.** Path to the host performance data file. Defaults to SpoolDir + "/perfdata/host-perfdata".
- service\_perfdata\_path | String | **Optional.** Path to the service performance data file. Defaults to SpoolDir + "/perfdata/service-perfdata".
- host\_temp\_path | String | **Optional.** Path to the temporary host file. Defaults to SpoolDir + "/tmp/host-perfdata".
- service\_temp\_path | String | **Optional.** Path to the temporary service file. Defaults to SpoolDir + "/tmp/service-perfdata".
- host\_format\_template | String | **Optional.** Host Format template for the performance data file. Defaults to a template that's suitable for use with PNP4Nagios.
- service\_format\_template | String | **Optional.** Service Format template for the performance data file. Defaults to a template that's suitable for use with PNP4Nagios.
- rotation\_interval | Duration | **Optional.** Rotation interval for the files specified in `{host,service}_perfdata_path`. Defaults to `30s`.
-
-When rotating the performance data file the current UNIX timestamp is appended to the path specified
-in `host_perfdata_path` and `service_perfdata_path` to generate a unique filename.
-
-
## ScheduledDowntime <a id="objecttype-scheduleddowntime"></a>
ScheduledDowntime objects can be used to set up recurring downtimes for hosts/services.
@@ -1526,74 +826,6 @@ Configuration Attributes:
groups | Array of object names | **Optional.** An array of nested group names.
-## StatusDataWriter <a id="objecttype-statusdatawriter"></a>
-
-Periodically writes status and configuration data files which are used by third-party tools.
-This configuration object is available as [statusdata feature](14-features.md#status-data).
-
-Example:
-
-```
-object StatusDataWriter "status" {
- status_path = "/var/cache/icinga2/status.dat"
- objects_path = "/var/cache/icinga2/objects.cache"
- update_interval = 30s
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- status\_path | String | **Optional.** Path to the `status.dat` file. Defaults to CacheDir + "/status.dat".
- objects\_path | String | **Optional.** Path to the `objects.cache` file. Defaults to CacheDir + "/objects.cache".
- update\_interval | Duration | **Optional.** The interval in which the status files are updated. Defaults to `15s`.
-
-
-## SyslogLogger <a id="objecttype-sysloglogger"></a>
-
-Specifies Icinga 2 logging to syslog.
-This configuration object is available as `syslog` [logging feature](14-features.md#logging).
-
-Example:
-
-```
-object SyslogLogger "syslog" {
- severity = "warning"
-}
-```
-
-Configuration Attributes:
-
- Name | Type | Description
- --------------------------|-----------------------|----------------------------------
- severity | String | **Optional.** The minimum severity for this log. Can be "debug", "notice", "information", "warning" or "critical". Defaults to "warning".
- facility | String | **Optional.** Defines the facility to use for syslog entries. This can be a facility constant like `FacilityDaemon`. Defaults to `FacilityUser`.
-
-Facility Constants:
-
- Name | Facility | Description
- ---------------------|---------------|----------------
- FacilityAuth | LOG\_AUTH | The authorization system.
- FacilityAuthPriv | LOG\_AUTHPRIV | The same as `FacilityAuth`, but logged to a file readable only by selected individuals.
- FacilityCron | LOG\_CRON | The cron daemon.
- FacilityDaemon | LOG\_DAEMON | System daemons that are not provided for explicitly by other facilities.
- FacilityFtp | LOG\_FTP | The file transfer protocol daemons.
- FacilityKern | LOG\_KERN | Messages generated by the kernel. These cannot be generated by any user processes.
- FacilityLocal0 | LOG\_LOCAL0 | Reserved for local use.
- FacilityLocal1 | LOG\_LOCAL1 | Reserved for local use.
- FacilityLocal2 | LOG\_LOCAL2 | Reserved for local use.
- FacilityLocal3 | LOG\_LOCAL3 | Reserved for local use.
- FacilityLocal4 | LOG\_LOCAL4 | Reserved for local use.
- FacilityLocal5 | LOG\_LOCAL5 | Reserved for local use.
- FacilityLocal6 | LOG\_LOCAL6 | Reserved for local use.
- FacilityLocal7 | LOG\_LOCAL7 | Reserved for local use.
- FacilityLpr | LOG\_LPR | The line printer spooling system.
- FacilityMail | LOG\_MAIL | The mail system.
- FacilityNews | LOG\_NEWS | The network news system.
- FacilitySyslog | LOG\_SYSLOG | Messages generated internally by syslogd.
- FacilityUser | LOG\_USER | Messages generated by user processes. This is the default facility identifier if none is specified.
- FacilityUucp | LOG\_UUCP | The UUCP system.
## TimePeriod <a id="objecttype-timeperiod"></a>
@@ -1680,24 +912,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:
@@ -1770,3 +1006,836 @@ Configuration Attributes:
global | Boolean | **Optional.** Whether configuration files for this zone should be [synced](06-distributed-monitoring.md#distributed-monitoring-global-zone-config-sync) to all endpoints. Defaults to `false`.
Zone objects cannot currently be created with the API.
+
+
+## Runtime Objects <a id="object-types-runtime"></a>
+
+These objects are generated at runtime by the daemon
+from API actions. Downtime objects are also created
+by ScheduledDowntime objects.
+
+### Comment <a id="objecttype-comment"></a>
+
+Comments created at runtime are represented as objects.
+Note: This is for reference only. You can create comments
+with the [add-comment](12-icinga2-api.md#icinga2-api-actions-add-comment) API action.
+
+Example:
+
+```
+object Comment "my-comment" {
+ host_name = "localhost"
+ author = "icingaadmin"
+ text = "This is a comment."
+ entry_time = 1234567890
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ host\_name | Object name | **Required.** The name of the host this comment belongs to.
+ service\_name | Object name | **Optional.** The short name of the service this comment belongs to. If omitted, this comment object is treated as host comment.
+ author | String | **Required.** The author's name.
+ text | String | **Required.** The comment text.
+ entry\_time | Timestamp | **Optional.** The UNIX timestamp when this comment was added. If omitted, the entry time is volatile!
+ entry\_type | Number | **Optional.** The comment type (`User` = 1, `Downtime` = 2, `Flapping` = 3, `Acknowledgement` = 4).
+ expire\_time | Timestamp | **Optional.** The comment's expire time as UNIX timestamp.
+ persistent | Boolean | **Optional.** Only evaluated for `entry_type` Acknowledgement. `true` does not remove the comment when the acknowledgement is removed.
+
+### Downtime <a id="objecttype-downtime"></a>
+
+Downtimes created at runtime are represented as objects.
+You can create downtimes with the [schedule-downtime](12-icinga2-api.md#icinga2-api-actions-schedule-downtime) API action.
+
+Example:
+
+```
+object Downtime "my-downtime" {
+ host_name = "localhost"
+ author = "icingaadmin"
+ comment = "This is a downtime."
+ start_time = 1505312869
+ end_time = 1505312924
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ host\_name | Object name | **Required.** The name of the host this comment belongs to.
+ service\_name | Object name | **Optional.** The short name of the service this comment belongs to. If omitted, this comment object is treated as host comment.
+ author | String | **Required.** The author's name.
+ comment | String | **Required.** The comment text.
+ start\_time | Timestamp | **Required.** The start time as UNIX timestamp.
+ end\_time | Timestamp | **Required.** The end time as UNIX timestamp.
+ duration | Number | **Optional.** The duration as number.
+ entry\_time | Timestamp | **Optional.** The UNIX timestamp when this downtime was added.
+ fixed | Boolean | **Optional.** Whether the downtime is fixed (true) or flexible (false). Defaults to flexible. Details in the [advanced topics chapter](08-advanced-topics.md#fixed-flexible-downtimes).
+ triggers | Array of object names | **Optional.** List of downtimes which should be triggered by this downtime.
+
+Runtime Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ trigger\_time | Timestamp | The UNIX timestamp when this downtime was triggered.
+ triggered\_by | Object name | The name of the downtime this downtime was triggered by.
+
+
+
+## Features <a id="object-types-features"></a>
+
+### ApiListener <a id="objecttype-apilistener"></a>
+
+ApiListener objects are used for distributed monitoring setups
+and API usage specifying the certificate files used for ssl
+authorization and additional restrictions.
+This configuration object is available as [api feature](11-cli-commands.md#cli-command-feature).
+
+The `TicketSalt` constant must be defined in [constants.conf](04-configuring-icinga-2.md#constants-conf).
+
+Example:
+
+```
+object ApiListener "api" {
+ accept_commands = true
+ accept_config = true
+
+ ticket_salt = TicketSalt
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------------------|-----------------------|----------------------------------
+ cert\_path | String | **Deprecated.** Path to the public key.
+ key\_path | String | **Deprecated.** Path to the private key.
+ ca\_path | String | **Deprecated.** Path to the CA certificate file.
+ ticket\_salt | String | **Optional.** Private key for [CSR auto-signing](06-distributed-monitoring.md#distributed-monitoring-setup-csr-auto-signing). **Required** for a signing master instance.
+ crl\_path | String | **Optional.** Path to the CRL file.
+ bind\_host | String | **Optional.** The IP address the api listener should be bound to. If not specified, the ApiListener is bound to `::` and listens for both IPv4 and IPv6 connections.
+ bind\_port | Number | **Optional.** The port the api listener should be bound to. Defaults to `5665`.
+ accept\_config | Boolean | **Optional.** Accept zone configuration. Defaults to `false`.
+ accept\_commands | Boolean | **Optional.** Accept remote commands. Defaults to `false`.
+ max\_anonymous\_clients | Number | **Optional.** Limit the number of anonymous client connections (not configured endpoints and signing requests).
+ cipher\_list | String | **Optional.** Cipher list that is allowed. For a list of available ciphers run `openssl ciphers`. Defaults to `ALL:!LOW:!WEAK:!MEDIUM:!EXP:!NULL`.
+ tls\_protocolmin | String | **Optional.** Minimum TLS protocol version. Must be one of `TLSv1`, `TLSv1.1` or `TLSv1.2`. Defaults to `TLSv1`.
+ tls\_handshake\_timeout | Number | **Optional.** TLS Handshake timeout. Defaults to `10s`.
+ access\_control\_allow\_origin | Array | **Optional.** Specifies an array of origin URLs that may access the API. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Origin)
+ access\_control\_allow\_credentials | Boolean | **Deprecated.** Indicates whether or not the actual request can be made using credentials. Defaults to `true`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Credentials)
+ access\_control\_allow\_headers | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request. Defaults to `Authorization`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Headers)
+ access\_control\_allow\_methods | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP methods can be used when making the actual request. Defaults to `GET, POST, PUT, DELETE`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Methods)
+ environment | String | **Optional.** Used as suffix in TLS SNI extension name; default from constant `ApiEnvironment`, which is empty.
+
+The attributes `access_control_allow_credentials`, `access_control_allow_headers` and `access_control_allow_methods`
+are controlled by Icinga 2 and are not changeable by config any more.
+
+
+The ApiListener type expects its certificate files to be in the following locations:
+
+ Type | Location
+ ---------------------|-------------------------------------
+ Private key | `DataDir + "/certs/" + NodeName + ".key"`
+ Certificate file | `DataDir + "/certs/" + NodeName + ".crt"`
+ CA certificate file | `DataDir + "/certs/ca.crt"`
+
+If the deprecated attributes `cert_path`, `key_path` and/or `ca_path` are specified Icinga 2
+copies those files to the new location in `DataDir + "/certs"` unless the
+file(s) there are newer.
+
+Please check the [upgrading chapter](16-upgrading-icinga-2.md#upgrading-to-2-8-certificate-paths) for more details.
+
+While Icinga 2 and the underlying OpenSSL library use sane and secure defaults, the attributes
+`cipher_list` and `tls_protocolmin` can be used to increase communication security. A good source
+for a more secure configuration is provided by the [Mozilla Wiki](https://wiki.mozilla.org/Security/Server_Side_TLS).
+Ensure to use the same configuration for both attributes on **all** endpoints to avoid communication problems which
+requires to use `cipher_list` compatible with the endpoint using the oldest version of the OpenSSL library. If using
+other tools to connect to the API ensure also compatibility with them as this setting affects not only inter-cluster
+communcation but also the REST API.
+
+### CheckerComponent <a id="objecttype-checkcomponent"></a>
+
+The checker component is responsible for scheduling active checks.
+This configuration object is available as [checker feature](11-cli-commands.md#cli-command-feature).
+
+Example:
+
+```
+object CheckerComponent "checker" { }
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ concurrent\_checks | Number | **Optional and deprecated.** The maximum number of concurrent checks. Was replaced by global constant `MaxConcurrentChecks` which will be set if you still use `concurrent_checks`.
+
+### CheckResultReader <a id="objecttype-checkresultreader"></a>
+
+Reads Icinga 1.x check result files from a directory. This functionality is provided
+to help existing Icinga 1.x users and might be useful for migration scenarios.
+
+> **Note**
+>
+> This feature is DEPRECATED and will be removed in future releases.
+> Check the [roadmap](https://github.com/Icinga/icinga2/milestones).
+
+Example:
+
+```
+object CheckResultReader "reader" {
+ spool_dir = "/data/check-results"
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ spool\_dir | String | **Optional.** The directory which contains the check result files. Defaults to DataDir + "/spool/checkresults/".
+
+### CompatLogger <a id="objecttype-compatlogger"></a>
+
+Writes log files in a format that's compatible with Icinga 1.x.
+This configuration object is available as [compatlog feature](14-features.md#compat-logging).
+
+> **Note**
+>
+> This feature is DEPRECATED and will be removed in future releases.
+> Check the [roadmap](https://github.com/Icinga/icinga2/milestones).
+
+Example:
+
+```
+object CompatLogger "compatlog" {
+ log_dir = "/var/log/icinga2/compat"
+ rotation_method = "DAILY"
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ log\_dir | String | **Optional.** Path to the compat log directory. Defaults to LogDir + "/compat".
+ rotation\_method | String | **Optional.** Specifies when to rotate log files. Can be one of "HOURLY", "DAILY", "WEEKLY" or "MONTHLY". Defaults to "HOURLY".
+
+
+### ElasticsearchWriter <a id="objecttype-elasticsearchwriter"></a>
+
+Writes check result metrics and performance data to an Elasticsearch instance.
+This configuration object is available as [elasticsearch feature](14-features.md#elasticsearch-writer).
+
+Example:
+
+```
+object ElasticsearchWriter "elasticsearch" {
+ host = "127.0.0.1"
+ port = 9200
+ index = "icinga2"
+
+ enable_send_perfdata = true
+
+ flush_threshold = 1024
+ flush_interval = 10
+}
+```
+
+The index is rotated daily, as is recommended by Elastic, meaning the index will be renamed to `$index-$d.$M.$y`.
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ host | String | **Required.** Elasticsearch host address. Defaults to `127.0.0.1`.
+ port | Number | **Required.** Elasticsearch port. Defaults to `9200`.
+ index | String | **Required.** Elasticsearch index name. Defaults to `icinga2`.
+ enable\_send\_perfdata | Boolean | **Optional.** Send parsed performance data metrics for check results. Defaults to `false`.
+ flush\_interval | Duration | **Optional.** How long to buffer data points before transferring to Elasticsearch. Defaults to `10s`.
+ flush\_threshold | Number | **Optional.** How many data points to buffer before forcing a transfer to Elasticsearch. Defaults to `1024`.
+ username | String | **Optional.** Basic auth username if Elasticsearch is hidden behind an HTTP proxy.
+ password | String | **Optional.** Basic auth password if Elasticsearch is hidden behind an HTTP proxy.
+ enable\_tls | Boolean | **Optional.** Whether to use a TLS stream. Defaults to `false`. Requires an HTTP proxy.
+ ca\_path | String | **Optional.** Path to CA certificate to validate the remote host. Requires `enable_tls` set to `true`.
+ cert\_path | String | **Optional.** Path to host certificate to present to the remote host for mutual verification. Requires `enable_tls` set to `true`.
+ key\_path | String | **Optional.** Path to host key to accompany the cert\_path. Requires `enable_tls` set to `true`.
+ enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-features). Defaults to `false`.
+
+Note: If `flush_threshold` is set too low, this will force the feature to flush all data to Elasticsearch too often.
+Experiment with the setting, if you are processing more than 1024 metrics per second or similar.
+
+Basic auth is supported with the `username` and `password` attributes. This requires an
+HTTP proxy (Nginx, etc.) in front of the Elasticsearch instance. Check [this blogpost](https://blog.netways.de/2017/09/14/secure-elasticsearch-and-kibana-with-an-nginx-http-proxy/)
+for an example.
+
+TLS for the HTTP proxy can be enabled with `enable_tls`. In addition to that
+you can specify the certificates with the `ca_path`, `cert_path` and `cert_key` attributes.
+
+### ExternalCommandListener <a id="objecttype-externalcommandlistener"></a>
+
+Implements the Icinga 1.x command pipe which can be used to send commands to Icinga.
+This configuration object is available as [command feature](14-features.md#external-commands).
+
+> **Note**
+>
+> This feature is DEPRECATED and will be removed in future releases.
+> Check the [roadmap](https://github.com/Icinga/icinga2/milestones).
+
+Example:
+
+```
+object ExternalCommandListener "command" {
+ command_path = "/var/run/icinga2/cmd/icinga2.cmd"
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ command\_path | String | **Optional.** Path to the command pipe. Defaults to RunDir + "/icinga2/cmd/icinga2.cmd".
+
+
+
+### FileLogger <a id="objecttype-filelogger"></a>
+
+Specifies Icinga 2 logging to a file.
+This configuration object is available as `mainlog` and `debuglog` [logging feature](14-features.md#logging).
+
+Example:
+
+```
+object FileLogger "debug-file" {
+ severity = "debug"
+ path = "/var/log/icinga2/debug.log"
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ path | String | **Required.** The log path.
+ severity | String | **Optional.** The minimum severity for this log. Can be "debug", "notice", "information", "warning" or "critical". Defaults to "information".
+
+
+### GelfWriter <a id="objecttype-gelfwriter"></a>
+
+Writes event log entries to a defined GELF receiver host (Graylog, Logstash).
+This configuration object is available as [gelf feature](14-features.md#gelfwriter).
+
+Example:
+
+```
+object GelfWriter "gelf" {
+ host = "127.0.0.1"
+ port = 12201
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ host | String | **Optional.** GELF receiver host address. Defaults to `127.0.0.1`.
+ port | Number | **Optional.** GELF receiver port. Defaults to `12201`.
+ source | String | **Optional.** Source name for this instance. Defaults to `icinga2`.
+ enable\_send\_perfdata | Boolean | **Optional.** Enable performance data for 'CHECK RESULT' events.
+ enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-features). Defaults to `false`.
+
+
+### GraphiteWriter <a id="objecttype-graphitewriter"></a>
+
+Writes check result metrics and performance data to a defined
+Graphite Carbon host.
+This configuration object is available as [graphite feature](14-features.md#graphite-carbon-cache-writer).
+
+Example:
+
+```
+object GraphiteWriter "graphite" {
+ host = "127.0.0.1"
+ port = 2003
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ host | String | **Optional.** Graphite Carbon host address. Defaults to `127.0.0.1`.
+ port | Number | **Optional.** Graphite Carbon port. Defaults to `2003`.
+ host\_name\_template | String | **Optional.** Metric prefix for host name. Defaults to `icinga2.$host.name$.host.$host.check_command$`.
+ service\_name\_template | String | **Optional.** Metric prefix for service name. Defaults to `icinga2.$host.name$.services.$service.name$.$service.check_command$`.
+ enable\_send\_thresholds | Boolean | **Optional.** Send additional threshold metrics. Defaults to `false`.
+ enable\_send\_metadata | Boolean | **Optional.** Send additional metadata metrics. Defaults to `false`.
+ enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-features). Defaults to `false`.
+
+Additional usage examples can be found [here](14-features.md#graphite-carbon-cache-writer).
+
+
+### IcingaApplication <a id="objecttype-icingaapplication"></a>
+
+The IcingaApplication object is required to start Icinga 2.
+The object name must be `app`. If the object configuration
+is missing, Icinga 2 will automatically create an IcingaApplication
+object.
+
+Example:
+
+```
+object IcingaApplication "app" {
+ enable_perfdata = false
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ enable\_notifications | Boolean | **Optional.** Whether notifications are globally enabled. Defaults to true.
+ enable\_event\_handlers | Boolean | **Optional.** Whether event handlers are globally enabled. Defaults to true.
+ enable\_flapping | Boolean | **Optional.** Whether flap detection is globally enabled. Defaults to true.
+ enable\_host\_checks | Boolean | **Optional.** Whether active host checks are globally enabled. Defaults to true.
+ enable\_service\_checks | Boolean | **Optional.** Whether active service checks are globally enabled. Defaults to true.
+ enable\_perfdata | Boolean | **Optional.** Whether performance data processing is globally enabled. Defaults to true.
+ vars | Dictionary | **Optional.** A dictionary containing custom attributes that are available globally.
+ environment | String | **Optional.** Specify the Icinga environment. This overrides the `Environment` constant specified in the configuration or on the CLI with `--define`. Defaults to empty.
+
+### IdoMySqlConnection <a id="objecttype-idomysqlconnection"></a>
+
+IDO database adapter for MySQL.
+This configuration object is available as [ido-mysql feature](14-features.md#db-ido).
+
+Example:
+
+```
+object IdoMysqlConnection "mysql-ido" {
+ host = "127.0.0.1"
+ port = 3306
+ user = "icinga"
+ password = "icinga"
+ database = "icinga"
+
+ cleanup = {
+ downtimehistory_age = 48h
+ contactnotifications_age = 31d
+ }
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ host | String | **Optional.** MySQL database host address. Defaults to `localhost`.
+ port | Number | **Optional.** MySQL database port. Defaults to `3306`.
+ socket\_path | String | **Optional.** MySQL socket path.
+ user | String | **Optional.** MySQL database user with read/write permission to the icinga database. Defaults to `icinga`.
+ password | String | **Optional.** MySQL database user's password. Defaults to `icinga`.
+ database | String | **Optional.** MySQL database name. Defaults to `icinga`.
+ enable\_ssl | Boolean | **Optional.** Use SSL. Defaults to false. Change to `true` in case you want to use any of the SSL options.
+ ssl\_key | String | **Optional.** MySQL SSL client key file path.
+ ssl\_cert | String | **Optional.** MySQL SSL certificate file path.
+ ssl\_ca | String | **Optional.** MySQL SSL certificate authority certificate file path.
+ ssl\_capath | String | **Optional.** MySQL SSL trusted SSL CA certificates in PEM format directory path.
+ ssl\_cipher | String | **Optional.** MySQL SSL list of allowed ciphers.
+ table\_prefix | String | **Optional.** MySQL database table prefix. Defaults to `icinga_`.
+ instance\_name | String | **Optional.** Unique identifier for the local Icinga 2 instance. Defaults to `default`.
+ instance\_description | String | **Optional.** Description for the Icinga 2 instance.
+ enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-db-ido). Defaults to `true`.
+ failover\_timeout | Duration | **Optional.** Set the failover timeout in a [HA cluster](06-distributed-monitoring.md#distributed-monitoring-high-availability-db-ido). Must not be lower than 30s. Defaults to `30s`.
+ cleanup | Dictionary | **Optional.** Dictionary with items for historical table cleanup.
+ categories | Array | **Optional.** Array of information types that should be written to the database.
+
+Cleanup Items:
+
+ Name | Type | Description
+ --------------------------------|-----------------------|----------------------------------
+ acknowledgements\_age | Duration | **Optional.** Max age for acknowledgements table rows (entry\_time). Defaults to 0 (never).
+ commenthistory\_age | Duration | **Optional.** Max age for commenthistory table rows (entry\_time). Defaults to 0 (never).
+ contactnotifications\_age | Duration | **Optional.** Max age for contactnotifications table rows (start\_time). Defaults to 0 (never).
+ contactnotificationmethods\_age | Duration | **Optional.** Max age for contactnotificationmethods table rows (start\_time). Defaults to 0 (never).
+ downtimehistory\_age | Duration | **Optional.** Max age for downtimehistory table rows (entry\_time). Defaults to 0 (never).
+ eventhandlers\_age | Duration | **Optional.** Max age for eventhandlers table rows (start\_time). Defaults to 0 (never).
+ externalcommands\_age | Duration | **Optional.** Max age for externalcommands table rows (entry\_time). Defaults to 0 (never).
+ flappinghistory\_age | Duration | **Optional.** Max age for flappinghistory table rows (event\_time). Defaults to 0 (never).
+ hostchecks\_age | Duration | **Optional.** Max age for hostalives table rows (start\_time). Defaults to 0 (never).
+ logentries\_age | Duration | **Optional.** Max age for logentries table rows (logentry\_time). Defaults to 0 (never).
+ notifications\_age | Duration | **Optional.** Max age for notifications table rows (start\_time). Defaults to 0 (never).
+ processevents\_age | Duration | **Optional.** Max age for processevents table rows (event\_time). Defaults to 0 (never).
+ statehistory\_age | Duration | **Optional.** Max age for statehistory table rows (state\_time). Defaults to 0 (never).
+ servicechecks\_age | Duration | **Optional.** Max age for servicechecks table rows (start\_time). Defaults to 0 (never).
+ systemcommands\_age | Duration | **Optional.** Max age for systemcommands table rows (start\_time). Defaults to 0 (never).
+
+Data Categories:
+
+ Name | Description | Required by
+ ---------------------|------------------------|--------------------
+ DbCatConfig | Configuration data | Icinga Web 2
+ DbCatState | Current state data | Icinga Web 2
+ DbCatAcknowledgement | Acknowledgements | Icinga Web 2
+ DbCatComment | Comments | Icinga Web 2
+ DbCatDowntime | Downtimes | Icinga Web 2
+ DbCatEventHandler | Event handler data | Icinga Web 2
+ DbCatExternalCommand | External commands | --
+ DbCatFlapping | Flap detection data | Icinga Web 2
+ DbCatCheck | Check results | --
+ DbCatLog | Log messages | --
+ DbCatNotification | Notifications | Icinga Web 2
+ DbCatProgramStatus | Program status data | Icinga Web 2
+ DbCatRetention | Retention data | Icinga Web 2
+ DbCatStateHistory | Historical state data | Icinga Web 2
+
+The default value for `categories` includes everything required
+by Icinga Web 2 in the table above.
+
+In addition to the category flags listed above the `DbCatEverything`
+flag may be used as a shortcut for listing all flags.
+
+Runtime Attributes:
+
+ Name | Type | Description
+ ----------------------------|-----------------------|-----------------
+ last\_failover | Timestamp | When the last failover happened for this connection (only available with `enable_ha = true`.
+
+### IdoPgsqlConnection <a id="objecttype-idopgsqlconnection"></a>
+
+IDO database adapter for PostgreSQL.
+This configuration object is available as [ido-pgsql feature](14-features.md#db-ido).
+
+Example:
+
+```
+object IdoPgsqlConnection "pgsql-ido" {
+ host = "127.0.0.1"
+ port = 5432
+ user = "icinga"
+ password = "icinga"
+ database = "icinga"
+
+ cleanup = {
+ downtimehistory_age = 48h
+ contactnotifications_age = 31d
+ }
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ host | String | **Optional.** PostgreSQL database host address. Defaults to `localhost`.
+ port | Number | **Optional.** PostgreSQL database port. Defaults to `5432`.
+ user | String | **Optional.** PostgreSQL database user with read/write permission to the icinga database. Defaults to `icinga`.
+ password | String | **Optional.** PostgreSQL database user's password. Defaults to `icinga`.
+ database | String | **Optional.** PostgreSQL database name. Defaults to `icinga`.
+ ssl\_mode | String | **Optional.** Enable SSL connection mode. Value must be set according to the [sslmode setting](https://www.postgresql.org/docs/9.3/static/libpq-connect.html#LIBPQ-CONNSTRING): `prefer`, `require`, `verify-ca`, `verify-full`, `allow`, `disable`.
+ ssl\_key | String | **Optional.** PostgreSQL SSL client key file path.
+ ssl\_cert | String | **Optional.** PostgreSQL SSL certificate file path.
+ ssl\_ca | String | **Optional.** PostgreSQL SSL certificate authority certificate file path.
+ table\_prefix | String | **Optional.** PostgreSQL database table prefix. Defaults to `icinga_`.
+ instance\_name | String | **Optional.** Unique identifier for the local Icinga 2 instance. Defaults to `default`.
+ instance\_description | String | **Optional.** Description for the Icinga 2 instance.
+ enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-db-ido). Defaults to `true`.
+ failover\_timeout | Duration | **Optional.** Set the failover timeout in a [HA cluster](06-distributed-monitoring.md#distributed-monitoring-high-availability-db-ido). Must not be lower than 30s. Defaults to `30s`.
+ cleanup | Dictionary | **Optional.** Dictionary with items for historical table cleanup.
+ categories | Array | **Optional.** Array of information types that should be written to the database.
+
+Cleanup Items:
+
+ Name | Type | Description
+ --------------------------------|-----------------------|----------------------------------
+ acknowledgements\_age | Duration | **Optional.** Max age for acknowledgements table rows (entry\_time). Defaults to 0 (never).
+ commenthistory\_age | Duration | **Optional.** Max age for commenthistory table rows (entry\_time). Defaults to 0 (never).
+ contactnotifications\_age | Duration | **Optional.** Max age for contactnotifications table rows (start\_time). Defaults to 0 (never).
+ contactnotificationmethods\_age | Duration | **Optional.** Max age for contactnotificationmethods table rows (start\_time). Defaults to 0 (never).
+ downtimehistory\_age | Duration | **Optional.** Max age for downtimehistory table rows (entry\_time). Defaults to 0 (never).
+ eventhandlers\_age | Duration | **Optional.** Max age for eventhandlers table rows (start\_time). Defaults to 0 (never).
+ externalcommands\_age | Duration | **Optional.** Max age for externalcommands table rows (entry\_time). Defaults to 0 (never).
+ flappinghistory\_age | Duration | **Optional.** Max age for flappinghistory table rows (event\_time). Defaults to 0 (never).
+ hostchecks\_age | Duration | **Optional.** Max age for hostalives table rows (start\_time). Defaults to 0 (never).
+ logentries\_age | Duration | **Optional.** Max age for logentries table rows (logentry\_time). Defaults to 0 (never).
+ notifications\_age | Duration | **Optional.** Max age for notifications table rows (start\_time). Defaults to 0 (never).
+ processevents\_age | Duration | **Optional.** Max age for processevents table rows (event\_time). Defaults to 0 (never).
+ statehistory\_age | Duration | **Optional.** Max age for statehistory table rows (state\_time). Defaults to 0 (never).
+ servicechecks\_age | Duration | **Optional.** Max age for servicechecks table rows (start\_time). Defaults to 0 (never).
+ systemcommands\_age | Duration | **Optional.** Max age for systemcommands table rows (start\_time). Defaults to 0 (never).
+
+Data Categories:
+
+ Name | Description | Required by
+ ---------------------|------------------------|--------------------
+ DbCatConfig | Configuration data | Icinga Web 2
+ DbCatState | Current state data | Icinga Web 2
+ DbCatAcknowledgement | Acknowledgements | Icinga Web 2
+ DbCatComment | Comments | Icinga Web 2
+ DbCatDowntime | Downtimes | Icinga Web 2
+ DbCatEventHandler | Event handler data | Icinga Web 2
+ DbCatExternalCommand | External commands | --
+ DbCatFlapping | Flap detection data | Icinga Web 2
+ DbCatCheck | Check results | --
+ DbCatLog | Log messages | --
+ DbCatNotification | Notifications | Icinga Web 2
+ DbCatProgramStatus | Program status data | Icinga Web 2
+ DbCatRetention | Retention data | Icinga Web 2
+ DbCatStateHistory | Historical state data | Icinga Web 2
+
+The default value for `categories` includes everything required
+by Icinga Web 2 in the table above.
+
+In addition to the category flags listed above the `DbCatEverything`
+flag may be used as a shortcut for listing all flags.
+
+Runtime Attributes:
+
+ Name | Type | Description
+ ----------------------------|-----------------------|-----------------
+ last\_failover | Timestamp | When the last failover happened for this connection (only available with `enable_ha = true`.
+
+### InfluxdbWriter <a id="objecttype-influxdbwriter"></a>
+
+Writes check result metrics and performance data to a defined InfluxDB host.
+This configuration object is available as [influxdb feature](14-features.md#influxdb-writer).
+
+Example:
+
+```
+object InfluxdbWriter "influxdb" {
+ host = "127.0.0.1"
+ port = 8086
+ database = "icinga2"
+
+ flush_threshold = 1024
+ flush_interval = 10s
+
+ host_template = {
+ measurement = "$host.check_command$"
+ tags = {
+ hostname = "$host.name$"
+ }
+ }
+ service_template = {
+ measurement = "$service.check_command$"
+ tags = {
+ hostname = "$host.name$"
+ service = "$service.name$"
+ }
+ }
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ host | String | **Required.** InfluxDB host address. Defaults to `127.0.0.1`.
+ port | Number | **Required.** InfluxDB HTTP port. Defaults to `8086`.
+ database | String | **Required.** InfluxDB database name. Defaults to `icinga2`.
+ username | String | **Optional.** InfluxDB user name. Defaults to `none`.
+ password | String | **Optional.** InfluxDB user password. Defaults to `none`.
+ ssl\_enable | Boolean | **Optional.** Whether to use a TLS stream. Defaults to `false`.
+ ssl\_ca\_cert | String | **Optional.** Path to CA certificate to validate the remote host.
+ ssl\_cert | String | **Optional.** Path to host certificate to present to the remote host for mutual verification.
+ ssl\_key | String | **Optional.** Path to host key to accompany the ssl\_cert.
+ host\_template | String | **Required.** Host template to define the InfluxDB line protocol.
+ service\_template | String | **Required.** Service template to define the influxDB line protocol.
+ enable\_send\_thresholds | Boolean | **Optional.** Whether to send warn, crit, min & max tagged data.
+ enable\_send\_metadata | Boolean | **Optional.** Whether to send check metadata e.g. states, execution time, latency etc.
+ flush\_interval | Duration | **Optional.** How long to buffer data points before transferring to InfluxDB. Defaults to `10s`.
+ flush\_threshold | Number | **Optional.** How many data points to buffer before forcing a transfer to InfluxDB. Defaults to `1024`.
+ enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-features). Defaults to `false`.
+
+Note: If `flush_threshold` is set too low, this will always force the feature to flush all data
+to InfluxDB. Experiment with the setting, if you are processing more than 1024 metrics per second
+or similar.
+
+
+
+### LiveStatusListener <a id="objecttype-livestatuslistener"></a>
+
+Livestatus API interface available as TCP or UNIX socket. Historical table queries
+require the [CompatLogger](09-object-types.md#objecttype-compatlogger) feature enabled
+pointing to the log files using the `compat_log_path` configuration attribute.
+This configuration object is available as [livestatus feature](14-features.md#setting-up-livestatus).
+
+Examples:
+
+```
+object LivestatusListener "livestatus-tcp" {
+ socket_type = "tcp"
+ bind_host = "127.0.0.1"
+ bind_port = "6558"
+}
+
+object LivestatusListener "livestatus-unix" {
+ socket_type = "unix"
+ socket_path = "/var/run/icinga2/cmd/livestatus"
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ socket\_type | String | **Optional.** Specifies the socket type. Can be either `tcp` or `unix`. Defaults to `unix`.
+ bind\_host | String | **Optional.** Only valid when `socket_type` is set to `tcp`. Host address to listen on for connections. Defaults to `127.0.0.1`.
+ bind\_port | Number | **Optional.** Only valid when `socket_type` is set to `tcp`. Port to listen on for connections. Defaults to `6558`.
+ socket\_path | String | **Optional.** Only valid when `socket_type` is set to `unix`. Specifies the path to the UNIX socket file. Defaults to RunDir + "/icinga2/cmd/livestatus".
+ compat\_log\_path | String | **Optional.** Path to Icinga 1.x log files. Required for historical table queries. Requires `CompatLogger` feature enabled. Defaults to LogDir + "/compat"
+
+> **Note**
+>
+> UNIX sockets are not supported on Windows.
+
+### NotificationComponent <a id="objecttype-notificationcomponent"></a>
+
+The notification component is responsible for sending notifications.
+This configuration object is available as [notification feature](11-cli-commands.md#cli-command-feature).
+
+Example:
+
+```
+object NotificationComponent "notification" { }
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-notifications). Disabling this currently only affects reminder notifications. Defaults to "true".
+
+### OpenTsdbWriter <a id="objecttype-opentsdbwriter"></a>
+
+Writes check result metrics and performance data to [OpenTSDB](http://opentsdb.net).
+This configuration object is available as [opentsdb feature](14-features.md#opentsdb-writer).
+
+Example:
+
+```
+object OpenTsdbWriter "opentsdb" {
+ host = "127.0.0.1"
+ port = 4242
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ host | String | **Optional.** OpenTSDB host address. Defaults to `127.0.0.1`.
+ port | Number | **Optional.** OpenTSDB port. Defaults to `4242`.
+ enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-features). Defaults to `false`.
+
+
+### PerfdataWriter <a id="objecttype-perfdatawriter"></a>
+
+Writes check result performance data to a defined path using macro
+pattern consisting of custom attributes and runtime macros.
+This configuration object is available as [perfdata feature](14-features.md#writing-performance-data-files).
+
+Example:
+
+```
+object PerfdataWriter "perfdata" {
+ host_perfdata_path = "/var/spool/icinga2/perfdata/host-perfdata"
+
+ service_perfdata_path = "/var/spool/icinga2/perfdata/service-perfdata"
+
+ 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$"
+
+ rotation_interval = 15s
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ host\_perfdata\_path | String | **Optional.** Path to the host performance data file. Defaults to SpoolDir + "/perfdata/host-perfdata".
+ service\_perfdata\_path | String | **Optional.** Path to the service performance data file. Defaults to SpoolDir + "/perfdata/service-perfdata".
+ host\_temp\_path | String | **Optional.** Path to the temporary host file. Defaults to SpoolDir + "/tmp/host-perfdata".
+ service\_temp\_path | String | **Optional.** Path to the temporary service file. Defaults to SpoolDir + "/tmp/service-perfdata".
+ host\_format\_template | String | **Optional.** Host Format template for the performance data file. Defaults to a template that's suitable for use with PNP4Nagios.
+ service\_format\_template | String | **Optional.** Service Format template for the performance data file. Defaults to a template that's suitable for use with PNP4Nagios.
+ rotation\_interval | Duration | **Optional.** Rotation interval for the files specified in `{host,service}_perfdata_path`. Defaults to `30s`.
+ enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-features). Defaults to `false`.
+
+When rotating the performance data file the current UNIX timestamp is appended to the path specified
+in `host_perfdata_path` and `service_perfdata_path` to generate a unique filename.
+
+
+### StatusDataWriter <a id="objecttype-statusdatawriter"></a>
+
+Periodically writes status and configuration data files which are used by third-party tools.
+This configuration object is available as [statusdata feature](14-features.md#status-data).
+
+Example:
+
+```
+object StatusDataWriter "status" {
+ status_path = "/var/cache/icinga2/status.dat"
+ objects_path = "/var/cache/icinga2/objects.cache"
+ update_interval = 30s
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ status\_path | String | **Optional.** Path to the `status.dat` file. Defaults to CacheDir + "/status.dat".
+ objects\_path | String | **Optional.** Path to the `objects.cache` file. Defaults to CacheDir + "/objects.cache".
+ update\_interval | Duration | **Optional.** The interval in which the status files are updated. Defaults to `15s`.
+
+### SyslogLogger <a id="objecttype-sysloglogger"></a>
+
+Specifies Icinga 2 logging to syslog.
+This configuration object is available as `syslog` [logging feature](14-features.md#logging).
+
+Example:
+
+```
+object SyslogLogger "syslog" {
+ severity = "warning"
+}
+```
+
+Configuration Attributes:
+
+ Name | Type | Description
+ --------------------------|-----------------------|----------------------------------
+ severity | String | **Optional.** The minimum severity for this log. Can be "debug", "notice", "information", "warning" or "critical". Defaults to "warning".
+ facility | String | **Optional.** Defines the facility to use for syslog entries. This can be a facility constant like `FacilityDaemon`. Defaults to `FacilityUser`.
+
+Facility Constants:
+
+ Name | Facility | Description
+ ---------------------|---------------|----------------
+ FacilityAuth | LOG\_AUTH | The authorization system.
+ FacilityAuthPriv | LOG\_AUTHPRIV | The same as `FacilityAuth`, but logged to a file readable only by selected individuals.
+ FacilityCron | LOG\_CRON | The cron daemon.
+ FacilityDaemon | LOG\_DAEMON | System daemons that are not provided for explicitly by other facilities.
+ FacilityFtp | LOG\_FTP | The file transfer protocol daemons.
+ FacilityKern | LOG\_KERN | Messages generated by the kernel. These cannot be generated by any user processes.
+ FacilityLocal0 | LOG\_LOCAL0 | Reserved for local use.
+ FacilityLocal1 | LOG\_LOCAL1 | Reserved for local use.
+ FacilityLocal2 | LOG\_LOCAL2 | Reserved for local use.
+ FacilityLocal3 | LOG\_LOCAL3 | Reserved for local use.
+ FacilityLocal4 | LOG\_LOCAL4 | Reserved for local use.
+ FacilityLocal5 | LOG\_LOCAL5 | Reserved for local use.
+ FacilityLocal6 | LOG\_LOCAL6 | Reserved for local use.
+ FacilityLocal7 | LOG\_LOCAL7 | Reserved for local use.
+ FacilityLpr | LOG\_LPR | The line printer spooling system.
+ FacilityMail | LOG\_MAIL | The mail system.
+ FacilityNews | LOG\_NEWS | The network news system.
+ FacilitySyslog | LOG\_SYSLOG | Messages generated internally by syslogd.
+ FacilityUser | LOG\_USER | Messages generated by user processes. This is the default facility identifier if none is specified.
+ FacilityUucp | LOG\_UUCP | The UUCP system.
+
+
+
diff --git a/doc/10-icinga-template-library.md b/doc/10-icinga-template-library.md
index 45172ac..fb7283f 100644
--- a/doc/10-icinga-template-library.md
+++ b/doc/10-icinga-template-library.md
@@ -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.
diff --git a/doc/11-cli-commands.md b/doc/11-cli-commands.md
index 886dff5..2428c30 100644
--- a/doc/11-cli-commands.md
+++ b/doc/11-cli-commands.md
@@ -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
diff --git a/doc/12-icinga2-api.md b/doc/12-icinga2-api.md
index 8709438..5bbe226 100644
--- a/doc/12-icinga2-api.md
+++ b/doc/12-icinga2-api.md
@@ -7,15 +7,19 @@ You can run the CLI command `icinga2 api setup` to enable the
certificates as well as a new API user `root` with an auto-generated password in the
`/etc/icinga2/conf.d/api-users.conf` configuration file:
- # icinga2 api setup
+```
+# icinga2 api setup
+```
Make sure to restart Icinga 2 to enable the changes you just made:
- # service icinga2 restart
+```
+# systemctl restart icinga2
+```
If you prefer to set up the API manually, you will have to perform the following steps:
-* Set up X.509 certificates for Icinga 2
+* Set up X.509 TLS certificates for Icinga 2
* Enable the `api` feature (`icinga2 feature enable api`)
* Create an `ApiUser` object for authentication
@@ -58,13 +62,15 @@ Supported request methods:
PUT | Create a new object. The PUT request must include all attributes required to create a new object.
DELETE | Remove an object created by the API. The DELETE method is idempotent and does not require any check if the object actually exists.
-All requests apart from `GET` require that the following `Accept` header is set:
+All requests except `GET` require the following `Accept` header:
- Accept: application/json
+```
+Accept: application/json
+```
Each URL is prefixed with the API version (currently "/v1").
-HTTP header size is limited to 8KB.
+HTTP header size is limited to 8KB per request.
### Responses <a id="icinga2-api-responses"></a>
@@ -74,27 +80,38 @@ list. Depending on the number of affected objects in your request, the
The output will be sent back as a JSON object:
-
- {
- "results": [
- {
- "code": 200.0,
- "status": "Object was created."
- }
- ]
- }
+```
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Object was created."
+ }
+ ]
+}
+```
> **Tip**
>
-> You can use the [pretty](12-icinga2-api.md#icinga2-api-parameters-global) parameter to beautify the JSON response with Icinga v2.9+.
+> You can use the [pretty](12-icinga2-api.md#icinga2-api-parameters-global) parameter to beautify the JSON response.
You can also use [jq](https://stedolan.github.io/jq/) or `python -m json.tool`
in combination with curl on the CLI.
```
+curl ... | jq
curl ... | python -m json.tool
```
+jq also has additional filter capabilities, as shown in [this blogpost](https://www.netways.de/blog/2018/08/24/json-in-bequem/).
+
+```
+curl ... |jq '{name: .results[].name}'
+```
+
+For programmatic examples in various languages, check the chapter
+[below](12-icinga2-api.md#icinga2-api-clients).
+
> **Note**
>
> Future versions of Icinga 2 might set additional fields. Your application
@@ -125,41 +142,51 @@ and Icinga 2 is unable to process your request.
There are two different ways for authenticating against the Icinga 2 API:
-* username and password using HTTP basic auth
-* X.509 certificate
+* Username and password using HTTP basic auth
+* X.509 client certificate
In order to configure a new API user you'll need to add a new [ApiUser](09-object-types.md#objecttype-apiuser)
configuration object. In this example `root` will be the basic auth username
and the `password` attribute contains the basic auth password.
- # vim /etc/icinga2/conf.d/api-users.conf
+```
+# vim /etc/icinga2/conf.d/api-users.conf
- object ApiUser "root" {
- password = "icinga"
- }
+object ApiUser "root" {
+ password = "icinga"
+}
+```
Alternatively you can use X.509 client certificates by specifying the `client_cn`
the API should trust. The X.509 certificate has to be signed by the CA certificate
that is configured in the [ApiListener](09-object-types.md#objecttype-apilistener) object.
- # vim /etc/icinga2/conf.d/api-users.conf
+```
+# vim /etc/icinga2/conf.d/api-users.conf
- object ApiUser "root" {
- client_cn = "CertificateCommonName"
- }
+object ApiUser "root" {
+ client_cn = "CertificateCommonName"
+}
+```
An `ApiUser` object can have both authentication methods configured.
+#### Authentication Test <a id="icinga2-api-authentication-test"></a>
+
You can test authentication by sending a GET request to the API:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1'
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1'
+```
In case you get an error message make sure to check the API user credentials.
When using client certificates for authentication you'll need to pass your client certificate
and private key to the curl call:
- $ curl -k --cert example.localdomain.crt --key example.localdomain.key 'https://example.localdomain:5665/v1/status'
+```
+$ curl -k --cert example.localdomain.crt --key example.localdomain.key 'https://example.localdomain:5665/v1/status'
+```
In case of an error make sure to verify the client certificate and CA.
@@ -167,7 +194,9 @@ The curl parameter `-k` disables certificate verification and should therefore
only be used for testing. In order to securely check each connection you'll need to
specify the trusted CA certificate using the curl parameter`--cacert`:
- $ curl -u root:icinga --cacert ca.crt 'icinga2.node1.localdomain:5665/v1'
+```
+$ curl -u root:icinga --cacert ca.crt 'icinga2.node1.localdomain:5665/v1'
+```
Read the next chapter on [API permissions](12-icinga2-api.md#icinga2-api-permissions)
in order to configure authorization settings for your newly created API user.
@@ -185,12 +214,16 @@ The permission system mainly relies on the url scheme of the API endpoints (See
Example for an API user with all permissions:
- permissions = [ "*" ]
+```
+permissions = [ "*" ]
+```
Note that you can use wildcards to include all possible hierarchically lower items. Here's another example that only allows the user
to perform read-only object queries for hosts and services:
- permissions = [ "objects/query/Host", "objects/query/Service" ]
+```
+permissions = [ "objects/query/Host", "objects/query/Service" ]
+```
You can also further restrict permissions by specifying a filter expression. The
filter expression has to be a [lambda function](17-language-reference.md#nullary-lambdas)
@@ -200,19 +233,27 @@ The following example allows the API user to query all hosts and services which
custom attribute `os` that matches the regular expression `^Linux`.
The [regex function](18-library-reference.md#global-functions-regex) is available as global function.
- permissions = [
- {
- permission = "objects/query/Host"
- filter = {{ regex("^Linux", host.vars.os) }}
- },
- {
- permission = "objects/query/Service"
- filter = {{ regex("^Linux", service.vars.os) }}
- }
- ]
+```
+permissions = [
+ {
+ permission = "objects/query/Host"
+ filter = {{ regex("^Linux", host.vars.os) }}
+ },
+ {
+ permission = "objects/query/Service"
+ filter = {{ regex("^Linux", service.vars.os) }}
+ }
+]
+```
More information about filters can be found in the [filters](12-icinga2-api.md#icinga2-api-filters) chapter.
+Prior to setting complex permissions, ensure to always [test](12-icinga2-api.md#icinga2-api-authentication-test)
+them step by step.
+
+
+#### Overview <a id="icinga2-api-permissions-overview"></a>
+
Permissions are tied to a maximum HTTP request size to prevent abuse, responses sent by Icinga are not limited.
An API user with all permissions ("\*") may send up to 512 MB regardless of the endpoint.
@@ -236,6 +277,7 @@ Available permissions for specific URL endpoints:
The required actions or types can be replaced by using a wildcard match ("\*").
+
### Parameters <a id="icinga2-api-parameters"></a>
Depending on the request method there are two ways of passing parameters to the request:
@@ -248,15 +290,27 @@ as query string, e.g. a space character becomes `%20`.
Example for a URL-encoded query string:
- /v1/objects/hosts?filter=match(%22example.localdomain*%22,host.name)&attrs=name&attrs=state
+```
+/v1/objects/hosts?filter=match(%22example.localdomain*%22,host.name)&attrs=name&attrs=state
+```
Here are the exact same query parameters as a JSON object:
- { "filter": "match(\"example.localdomain*\",host.name)", "attrs": [ "host.name", "host.state" ] }
+```
+{ "filter": "match(\"example.localdomain*\",host.name)", "attrs": [ "host.name", "host.state" ] }
+```
The [match function](18-library-reference.md#global-functions-match) is available as global function
in Icinga 2.
+Whenever filters and other URL parameters don't work due to encoding issues,
+consider passing them in the request body. For GET requests, this method is explained
+[here](12-icinga2-api.md#icinga2-api-requests-method-override).
+
+You can use [jo](https://github.com/jpmens/jo) to format JSON strings on the shell. An example
+for API actions shown [here](12-icinga2-api.md#icinga2-api-actions-unix-timestamps).
+
+
### Global Parameters <a id="icinga2-api-parameters-global"></a>
Name | Description
@@ -276,8 +330,6 @@ Example as JSON object:
{ "pretty": true }
```
-Both parameters have been added in Icinga 2 v2.9.
-
### Request Method Override <a id="icinga2-api-requests-method-override"></a>
`GET` requests do not allow you to send a request body. In case you cannot pass everything as URL
@@ -286,11 +338,29 @@ header. This comes in handy when you are using HTTP proxies disallowing `PUT` or
Query an existing object by sending a `POST` request with `X-HTTP-Method-Override: GET` as request header:
- $ curl -k -s -u 'root:icinga' -H 'Accept: application/json' -X POST -H 'X-HTTP-Method-Override: GET' 'https://localhost:5665/v1/objects/hosts'
+```
+$ curl -k -s -u 'root:icinga' -H 'Accept: application/json' \
+ -H 'X-HTTP-Method-Override: GET' -X POST \
+ 'https://localhost:5665/v1/objects/hosts'
+```
Delete an existing object by sending a `POST` request with `X-HTTP-Method-Override: DELETE` as request header:
- $ curl -k -s -u 'root:icinga' -H 'Accept: application/json' -X POST -H 'X-HTTP-Method-Override: DELETE' 'https://localhost:5665/v1/objects/hosts/example.localdomain'
+```
+$ curl -k -s -u 'root:icinga' -H 'Accept: application/json' \
+ -H 'X-HTTP-Method-Override: DELETE' -X POST \
+ 'https://localhost:5665/v1/objects/hosts/example.localdomain'
+```
+
+Query objects with complex filters. For a detailed introduction into filter, please
+read the [following chapter](12-icinga2-api.md#icinga2-api-filters).
+
+```
+curl -k -s -u 'root:icinga' -H 'Accept: application/json' \
+ -H 'X-HTTP-Method-Override: GET' -X POST \
+ 'https://localhost:5665/v1/objects/services' \
+ -d '{ "filter": "service.state==2 && match(\"ping*\",service.name)" }'
+```
### Filters <a id="icinga2-api-filters"></a>
@@ -299,11 +369,15 @@ Delete an existing object by sending a `POST` request with `X-HTTP-Method-Overri
By default actions and queries operate on all objects unless further restricted by the user. For
example, the following query returns all `Host` objects:
- https://localhost:5665/v1/objects/hosts
+```
+https://localhost:5665/v1/objects/hosts
+```
If you're only interested in a single object, you can limit the output to that object by specifying its name:
- https://localhost:5665/v1/objects/hosts?host=localhost
+```
+https://localhost:5665/v1/objects/hosts?host=localhost
+```
**The name of the URL parameter is the lower-case version of the type the query applies to.** For
example, for `Host` objects the URL parameter therefore is `host`, for `Service` objects it is
@@ -311,14 +385,18 @@ example, for `Host` objects the URL parameter therefore is `host`, for `Service`
You can also specify multiple objects:
- https://localhost:5665/v1/objects/hosts?hosts=first-host&hosts=second-host
+```
+https://localhost:5665/v1/objects/hosts?hosts=first-host&hosts=second-host
+```
Again -- like in the previous example -- the name of the URL parameter is the lower-case version of the type. However, because we're specifying multiple objects here the **plural form** of the type is used.
When specifying names for objects which have composite names like for example services the
full name has to be used:
- https://localhost:5665/v1/objects/services?service=localhost!ping6
+```
+https://localhost:5665/v1/objects/services?service=localhost!ping6
+```
The full name of an object can be obtained by looking at the `__name` attribute.
@@ -327,7 +405,11 @@ The full name of an object can be obtained by looking at the `__name` attribute.
Most of the information provided in this chapter applies to both permission filters (as used when
configuring `ApiUser` objects) and filters specified in queries.
-Advanced filters allow users to filter objects using lambda expressions. The syntax for these filters is the same like for [apply rule expressions](03-monitoring-basics.md#using-apply-expressions).
+Advanced filters allow users to filter objects using lambda expressions.
+The syntax for these filters is the same like for [apply rule expressions](03-monitoring-basics.md#using-apply-expressions).
+
+The `filter` parameter can only be specified once, complex filters must
+be defined once in the provided string value.
> **Note**
>
@@ -336,15 +418,25 @@ Advanced filters allow users to filter objects using lambda expressions. The syn
Example matching all services in NOT-OK state:
- https://localhost:5665/v1/objects/services?filter=service.state!=ServiceOK
+```
+https://localhost:5665/v1/objects/services?filter=service.state!=ServiceOK
+```
Example [matching](18-library-reference.md#global-functions-match) all hosts by a name string pattern:
- https://localhost:5665/v1/objects/hosts?filter=match("example.localdomain*",host.name)
+```
+https://localhost:5665/v1/objects/hosts?filter=match("example.localdomain*",host.name)
+```
Example for all hosts which are in the host group `linux-servers`:
+```
+https://localhost:5665/v1/objects/hosts?filter="linux-servers" in host.groups
+```
- https://localhost:5665/v1/objects/hosts?filter="linux-servers" in host.groups
+> **Tip**
+>
+> Best practice for filters is to use [X-HTTP-Method-Override](12-icinga2-api.md#icinga2-api-requests-method-override)
+> for GET requests and always pass them in the request body.
User-specified filters are run in a sandbox environment which ensures that filters cannot
modify Icinga's state, for example object attributes or global variables.
@@ -366,19 +458,42 @@ Some queries can be performed for more than just one object type. One example is
action which can be used for both hosts and services. When using advanced filters you will also have to specify the
type using the `type` parameter:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/reschedule-check' \
- -d '{ "type": "Service", "filter": "service.name==\"ping6\"", "pretty": true }'
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST \
+ 'https://localhost:5665/v1/actions/reschedule-check' \
+ -d '{ "type": "Service", "filter": "service.name==\"ping6\"", "pretty": true }'
+```
+
+##### Filter Variables <a id="icinga2-api-advanced-filters-variables"></a>
+
+Filter values need to be escaped in the same way as in the Icinga 2 DSL.
-When building filters you have to ensure that values such as
-`"linux-servers"` are escaped properly according to the rules of the Icinga 2 configuration
-language.
+The example below is not valid:
-To make using the API in scripts easier you can use the `filter_vars` attribute to specify
-variables which should be made available to your filter expression. This way you don't have
-to worry about escaping values:
+```
+-d '{ "type": "Host", "filter": ""linux-servers" in host.groups" }'
+```
+
+The double quotes need to be escaped with a preceeding backslash:
+
+```
+-d '{ "type": "Host", "filter": "\"linux-servers\" in host.groups" }'
+```
+
+You can use the `filter_vars` attribute to avoid additional escaping.
+This follows the same principle as with parameter binding known from RDBMS.
+Specify a placeholder variable inside the `filter` string, and actually
+assign its value inside the `filter_vars` dictionary.
- $ curl -k -s -u 'root:icinga' -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://localhost:5665/v1/objects/hosts' \
- -d '{ "filter": "host.vars.os == os", "filter_vars": { "os": "Linux" }, "pretty": true }'
+That way you can also keep the `filter` string the same for different
+requests with only changing the `filter_vars`.
+
+```
+$ curl -k -s -u 'root:icinga' -H 'Accept: application/json' \
+ -H 'X-HTTP-Method-Override: GET' -X POST \
+ 'https://localhost:5665/v1/objects/hosts' \
+ -d '{ "filter": "group in host.groups", "filter_vars": { "group": "linux-servers" }, "pretty": true }'
+```
We're using [X-HTTP-Method-Override](12-icinga2-api.md#icinga2-api-requests-method-override) here because
the HTTP specification does not allow message bodies for GET requests.
@@ -386,6 +501,16 @@ the HTTP specification does not allow message bodies for GET requests.
The `filters_vars` attribute can only be used inside the request body, but not as
a URL parameter because there is no way to specify a dictionary in a URL.
+The example from [X-HTTP-Method-Override](12-icinga2-api.md#icinga2-api-requests-method-override)
+can be enhanced to avoid additional parameter value escaping.
+
+```
+curl -k -s -u 'root:icinga' -H 'Accept: application/json' \
+ -H 'X-HTTP-Method-Override: GET' -X POST \
+ 'https://localhost:5665/v1/objects/services' \
+ -d '{ "filter": "service.state==state && match(pattern,service.name)", "filter_vars": { "state": 2, "pattern": "ping*" } }'
+```
+
## Config Objects <a id="icinga2-api-config-objects"></a>
Provides methods to manage configuration objects:
@@ -421,7 +546,9 @@ a `GET` query to the `/v1/objects/<type>` URL endpoint. `<type` has
to be replaced with the plural name of the object type you are interested
in:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/hosts'
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/hosts'
+```
A list of all available configuration types is available in the
[object types](09-object-types.md#object-types) chapter.
@@ -440,25 +567,29 @@ Instead of using a filter you can optionally specify the object name in the
URL path when querying a single object. For objects with composite names
(e.g. services) the full name (e.g. `example.localdomain!http`) must be specified:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/services/example.localdomain!http'
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/services/example.localdomain!http'
+```
You can limit the output to specific attributes using the `attrs` URL parameter:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/hosts/example.localdomain?attrs=name&attrs=address&pretty=1'
- {
- "results": [
- {
- "attrs": {
- "name": "example.localdomain"
- "address": "192.168.1.1"
- },
- "joins": {},
- "meta": {},
- "name": "example.localdomain",
- "type": "Host"
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/hosts/example.localdomain?attrs=name&attrs=address&pretty=1'
+{
+ "results": [
+ {
+ "attrs": {
+ "name": "example.localdomain"
+ "address": "192.168.1.1"
+ },
+ "joins": {},
+ "meta": {},
+ "name": "example.localdomain",
+ "type": "Host"
+ }
+ ]
+}
+```
#### Object Queries Result <a id="icinga2-api-config-objects-query-result"></a>
@@ -479,17 +610,23 @@ information about the host when querying service objects.
The following query retrieves all host attributes:
- https://localhost:5665/v1/objects/services?joins=host
+```
+https://localhost:5665/v1/objects/services?joins=host
+```
Instead of requesting all host attributes you can also limit the output to specific
attributes:
- https://localhost:5665/v1/objects/services?joins=host.name&joins=host.address
+```
+https://localhost:5665/v1/objects/services?joins=host.name&joins=host.address
+```
You can request that all available joins are returned in the result set by using
the `all_joins` query parameter.
- https://localhost:5665/v1/objects/services?all_joins=1
+```
+https://localhost:5665/v1/objects/services?all_joins=1
+```
> **Note**
>
@@ -512,105 +649,129 @@ custom attribute set to `Linux`. The result set contains the `display_name` and
attributes for the service. The query also returns the host's `name` and `address` attribute
via a join:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/services?attrs=display_name&attrs=check_command&joins=host.name&joins=host.address&filter=host.vars.os==%22Linux%22&pretty=1'
-
- {
- "results": [
- {
- "attrs": {
- "check_command": "ping4",
- "display_name": "ping4"
- },
- "joins": {
- "host": {
- "address": "192.168.1.1",
- "name": "example.localdomain"
- }
- },
- "meta": {},
- "name": "example.localdomain!ping4",
- "type": "Service"
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/services?attrs=display_name&attrs=check_command&joins=host.name&joins=host.address&filter=host.vars.os==%22Linux%22&pretty=1'
+
+{
+ "results": [
+ {
+ "attrs": {
+ "check_command": "ping4",
+ "display_name": "ping4"
},
- {
- "attrs": {
- "check_command": "ssh",
- "display_name": "ssh"
- },
- "joins": {
- "host": {
- "address": "192.168.1.1",
- "name": "example.localdomain"
- }
- },
- "meta": {},
- "name": "example.localdomain!ssh",
- "type": "Service"
- }
- ]
- }
+ "joins": {
+ "host": {
+ "address": "192.168.1.1",
+ "name": "example.localdomain"
+ }
+ },
+ "meta": {},
+ "name": "example.localdomain!ping4",
+ "type": "Service"
+ },
+ {
+ "attrs": {
+ "check_command": "ssh",
+ "display_name": "ssh"
+ },
+ "joins": {
+ "host": {
+ "address": "192.168.1.1",
+ "name": "example.localdomain"
+ }
+ },
+ "meta": {},
+ "name": "example.localdomain!ssh",
+ "type": "Service"
+ }
+ ]
+}
+```
+
+> **Tip**
+>
+> Use [X-HTTP-Method-Override](12-icinga2-api.md#icinga2-api-requests-method-override)
+> and pass everything in the request body like this:
+
+```
+$ curl -k -s -u 'root:icinga' -H 'Accept: application/json' \
+ -H 'X-HTTP-Method-Override: GET' -X POST \
+ 'https://localhost:5665/v1/objects/services' \
+ -d '{ "attrs": [ "display_name", "check_command" ], "joins": [ "host.name", "host.address" ], "filter": "host.vars.os==\"Linux\"", "pretty": true }'
+```
In case you want to fetch all [comments](09-object-types.md#objecttype-comment)
for hosts and services, you can use the following query URL (similar example
for downtimes):
- https://localhost:5665/v1/objects/comments?joins=host&joins=service
+```
+https://localhost:5665/v1/objects/comments?joins=host&joins=service
+```
This is another example for listing all service objects which are unhandled problems (state is not OK
and no downtime or acknowledgement set). We're using [X-HTTP-Method-Override](12-icinga2-api.md#icinga2-api-requests-method-override)
here because we want to pass all query attributes in the request body.
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://127.0.0.1:5665/v1/objects/services' \
- -d '{ "joins": [ "host.name", "host.address" ], "attrs": [ "name", "state", "downtime_depth", "acknowledgement" ], "filter": "service.state != ServiceOK && service.downtime_depth == 0.0 && service.acknowledgement == 0.0", "pretty": true }'
-
- {
- "results": [
- {
- "attrs": {
- "acknowledgement": 0.0,
- "downtime_depth": 0.0,
- "name": "10807-service",
- "state": 3.0
- },
- "joins": {
- "host": {
- "address": "",
- "name": "10807-host"
- }
- },
- "meta": {},
- "name": "10807-host!10807-service",
- "type": "Service"
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -H 'X-HTTP-Method-Override: GET' -X POST \
+ 'https://127.0.0.1:5665/v1/objects/services' \
+-d '{ "joins": [ "host.name", "host.address" ], "attrs": [ "name", "state", "downtime_depth", "acknowledgement" ], "filter": "service.state != ServiceOK && service.downtime_depth == 0.0 && service.acknowledgement == 0.0", "pretty": true }'
+
+{
+ "results": [
+ {
+ "attrs": {
+ "acknowledgement": 0.0,
+ "downtime_depth": 0.0,
+ "name": "10807-service",
+ "state": 3.0
+ },
+ "joins": {
+ "host": {
+ "address": "",
+ "name": "10807-host"
+ }
+ },
+ "meta": {},
+ "name": "10807-host!10807-service",
+ "type": "Service"
+ }
+ ]
+}
+```
In order to list all acknowledgements without expire time, you query the `/v1/objects/comments`
URL endpoint with `joins` and `filter` request parameters using the [X-HTTP-Method-Override](12-icinga2-api.md#icinga2-api-requests-method-override)
method:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://localhost:5665/v1/objects/comments' \
- -d '{ "joins": [ "service.name", "service.acknowledgement", "service.acknowledgement_expiry" ], "attrs": [ "author", "text" ], "filter": "service.acknowledgement!=0 && service.acknowledgement_expiry==0", "pretty": true }'
-
- {
- "results": [
- {
- "attrs": {
- "author": "icingaadmin",
- "text": "maintenance work"
- },
- "joins": {
- "service": {
- "__name": "example.localdomain!disk /",
- "acknowledgement": 1.0,
- "acknowledgement_expiry": 0.0
- }
- },
- "meta": {},
- "name": "example.localdomain!disk /!example.localdomain-1495457222-0",
- "type": "Comment"
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -H 'X-HTTP-Method-Override: GET' -X POST \
+ 'https://localhost:5665/v1/objects/comments' \
+ -d '{ "joins": [ "service.name", "service.acknowledgement", "service.acknowledgement_expiry" ], "attrs": [ "author", "text" ], "filter": "service.acknowledgement!=0 && service.acknowledgement_expiry==0", "pretty": true }'
+
+{
+ "results": [
+ {
+ "attrs": {
+ "author": "icingaadmin",
+ "text": "maintenance work"
+ },
+ "joins": {
+ "service": {
+ "__name": "example.localdomain!disk /",
+ "acknowledgement": 1.0,
+ "acknowledgement_expiry": 0.0
+ }
+ },
+ "meta": {},
+ "name": "example.localdomain!disk /!example.localdomain-1495457222-0",
+ "type": "Comment"
+ }
+ ]
+}
+```
### Creating Config Objects <a id="icinga2-api-config-objects-create"></a>
@@ -628,50 +789,62 @@ the full name (e.g. `example.localdomain!http`) must be specified.
If attributes are of the Dictionary type, you can also use the indexer format. This might be necessary to only override specific custom variables and keep all other existing custom variables (e.g. from templates):
- "attrs": { "vars.os": "Linux" }
+```
+"attrs": { "vars.os": "Linux" }
+```
Example for creating the new host object `example.localdomain`:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/hosts/example.localdomain' \
- -d '{ "templates": [ "generic-host" ], "attrs": { "address": "192.168.1.1", "check_command": "hostalive", "vars.os" : "Linux" }, "pretty": true }'
- {
- "results": [
- {
- "code": 200.0,
- "status": "Object was created."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X PUT 'https://localhost:5665/v1/objects/hosts/example.localdomain' \
+ -d '{ "templates": [ "generic-host" ], "attrs": { "address": "192.168.1.1", "check_command": "hostalive", "vars.os" : "Linux" }, "pretty": true }'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Object was created."
+ }
+ ]
+}
+```
If the configuration validation fails, the new object will not be created and the response body
contains a detailed error message. The following example is missing the `check_command` attribute
which is required for host objects:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/hosts/example.localdomain' \
- -d '{ "attrs": { "address": "192.168.1.1", "vars.os" : "Linux" }, "pretty": true }'
- {
- "results": [
- {
- "code": 500.0,
- "errors": [
- "Error: Validation failed for object 'example.localdomain' of type 'Host'; Attribute 'check_command': Attribute must not be empty."
- ],
- "status": "Object could not be created."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X PUT 'https://localhost:5665/v1/objects/hosts/example.localdomain' \
+ -d '{ "attrs": { "address": "192.168.1.1", "vars.os" : "Linux" }, "pretty": true }'
+{
+ "results": [
+ {
+ "code": 500.0,
+ "errors": [
+ "Error: Validation failed for object 'example.localdomain' of type 'Host'; Attribute 'check_command': Attribute must not be empty."
+ ],
+ "status": "Object could not be created."
+ }
+ ]
+}
+```
Service objects must be created using their full name ("hostname!servicename") referencing an existing host object:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/services/example.localdomain!realtime-load' \
- -d '{ "templates": [ "generic-service" ], "attrs": { "check_command": "load", "check_interval": 1,"retry_interval": 1 } }'
-
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X PUT 'https://localhost:5665/v1/objects/services/example.localdomain!realtime-load' \
+ -d '{ "templates": [ "generic-service" ], "attrs": { "check_command": "load", "check_interval": 1,"retry_interval": 1 } }'
+```
Example for a new CheckCommand object:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/checkcommands/mytest' \
- -d '{ "templates": [ "plugin-check-command" ], "attrs": { "command": [ "/usr/local/sbin/check_http" ], "arguments": { "-I": "$mytest_iparam$" } } }'
-
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X PUT 'https://localhost:5665/v1/objects/checkcommands/mytest' \
+ -d '{ "templates": [ "plugin-check-command" ], "attrs": { "command": [ "/usr/local/sbin/check_http" ], "arguments": { "-I": "$mytest_iparam$" } } }'
+```
### Modifying Objects <a id="icinga2-api-config-objects-modify"></a>
@@ -682,38 +855,44 @@ parameters need to be passed inside the JSON body:
-----------|------------|---------------------------
attrs | Dictionary | **Required.** Set specific object attributes for this [object type](09-object-types.md#object-types).
-In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) should be provided.
+In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters)
+parameter should be provided.
> **Note**:
>
> Modified attributes do not trigger a re-evaluation of existing
> static [apply rules](03-monitoring-basics.md#using-apply) and [group assignments](03-monitoring-basics.md#group-assign-intro).
-> Delete and re-create the objects if you require such changes.
+> Delete and re-create the objects if you require such changes or
+> consider funding [this feature request](https://github.com/Icinga/icinga2/issues/4084).
>
> Furthermore you cannot modify templates which have already been resolved
> during [object creation](12-icinga2-api.md#icinga2-api-config-objects-create).
> There are attributes which can only be set for [PUT requests](12-icinga2-api.md#icinga2-api-config-objects-create) such as `groups`
> or `zone`. A complete list of `no_user_modify` attributes can be fetched from the [types](12-icinga2-api.md#icinga2-api-types) URL endpoint.
-If attributes are of the Dictionary type, you can also use the indexer format:
+If attributes are of the [Dictionary](17-language-reference.md#dictionary) type, you can also use the indexer format:
- "attrs": { "vars.os": "Linux" }
+```
+"attrs": { "vars.os": "Linux" }
+```
The following example updates the `address` attribute and the custom attribute `os` for the `example.localdomain` host:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/hosts/example.localdomain' \
- -d '{ "attrs": { "address": "192.168.1.2", "vars.os" : "Windows" }, "pretty": true }'
- {
- "results": [
- {
- "code": 200.0,
- "name": "example.localdomain",
- "status": "Attributes updated.",
- "type": "Host"
- }
- ]
- }
-
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/objects/hosts/example.localdomain' \
+ -d '{ "attrs": { "address": "192.168.1.2", "vars.os" : "Windows" }, "pretty": true }'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "name": "example.localdomain",
+ "status": "Attributes updated.",
+ "type": "Host"
+ }
+ ]
+}
+```
### Deleting Objects <a id="icinga2-api-config-objects-delete"></a>
@@ -728,17 +907,20 @@ In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters
Example for deleting the host object `example.localdomain`:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE 'https://localhost:5665/v1/objects/hosts/example.localdomain?cascade=1&pretty=1'
- {
- "results": [
- {
- "code": 200.0,
- "name": "example.localdomain",
- "status": "Object was deleted.",
- "type": "Host"
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X DELETE 'https://localhost:5665/v1/objects/hosts/example.localdomain?cascade=1&pretty=1'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "name": "example.localdomain",
+ "status": "Object was deleted.",
+ "type": "Host"
+ }
+ ]
+}
+```
## Config Templates <a id="icinga2-api-config-templates"></a>
@@ -755,7 +937,9 @@ a `GET` query to the `/v1/templates/<type>` URL endpoint. `<type` has
to be replaced with the plural name of the object type you are interested
in:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/templates/hosts'
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/templates/hosts'
+```
A list of all available configuration types is available in the
[object types](09-object-types.md#object-types) chapter.
@@ -767,13 +951,19 @@ check a wildcard string pattern against `tmpl.name`.
The `filter` attribute is passed inside the request body thus requiring to use [X-HTTP-Method-Override](12-icinga2-api.md#icinga2-api-requests-method-override)
here.
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://localhost:5661/v1/templates/hosts' \
- -d '{ "filter": "match(\"g*\", tmpl.name)" }'
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -H 'X-HTTP-Method-Override: GET' -X POST \
+ 'https://localhost:5661/v1/templates/hosts' \
+ -d '{ "filter": "match(\"g*\", tmpl.name)" }'
+```
Instead of using a filter you can optionally specify the template name in the
URL path when querying a single object:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/templates/hosts/generic-host'
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/templates/hosts/generic-host'
+```
The result set contains the type, name as well as the location of the template.
@@ -788,20 +978,28 @@ Provides methods to manage global variables:
You can request information about global variables by sending
a `GET` query to the `/v1/variables/` URL endpoint:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/variables'
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/variables'
+```
A [filter](12-icinga2-api.md#icinga2-api-filters) may be provided for this query type. The
variable information object can be accessed in the filter using the `variable` variable.
The `filter` attribute is passed inside the request body thus requiring to use [X-HTTP-Method-Override](12-icinga2-api.md#icinga2-api-requests-method-override)
here.
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://localhost:5661/v1/variables' \
- -d '{ "filter": "variable.type in [ \"String\", \"Number\" ]" }'
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -H 'X-HTTP-Method-Override: GET' -X POST \
+ 'https://localhost:5661/v1/variables' \
+ -d '{ "filter": "variable.type in [ \"String\", \"Number\" ]" }'
+```
Instead of using a filter you can optionally specify the variable name in the
URL path when querying a single variable:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/variables/PrefixDir'
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/variables/PrefixDir'
+```
The result set contains the type, name and value of the global variable.
@@ -810,10 +1008,12 @@ The result set contains the type, name and value of the global variable.
There are several actions available for Icinga 2 provided by the `/v1/actions`
URL endpoint. You can run actions by sending a `POST` request.
-In case you have been using the [external commands](14-features.md#external-commands)
-in the past, the API actions provide a similar interface with filter
-capabilities for some of the more common targets which do not directly change
-the configuration.
+The following actions are also used by [Icinga Web 2](https://icinga.com/products/icinga-web-2/):
+
+* sending check results to Icinga from scripts, remote agents, etc.
+* scheduling downtimes from external scripts or cronjobs
+* acknowledging problems
+* adding comments
All actions return a 200 `OK` or an appropriate error code for each
action performed on each object matching the supplied filter.
@@ -823,7 +1023,40 @@ notification on a program-wide basis must be applied by updating the
[IcingaApplication object](12-icinga2-api.md#icinga2-api-config-objects)
called `app`.
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/icingaapplications/app' -d '{ "attrs": { "enable_notifications": false } }'
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/objects/icingaapplications/app' \
+ -d '{ "attrs": { "enable_notifications": false } }'
+```
+
+### Unix Timestamp Handling <a id="icinga2-api-actions-unix-timestamps"></a>
+
+If you don't want to write JSON manually, especially for adding the `start_time`
+and `end_time` parameters, you can use [jo](https://github.com/jpmens/jo) to format this.
+
+```
+$ jo -p pretty=true type=Service filter="service.name==\"ping4\"" author=icingaadmin comment="IPv4 network maintenance" fixed=true start_time=$(date +%s -d "+0 hour") end_time=$(date +%s -d "+1 hour")
+{
+ "pretty": true,
+ "type": "Service",
+ "filter": "service.name==\"ping4\"",
+ "author": "icingaadmin",
+ "comment": "IPv4 network maintenance",
+ "fixed": true,
+ "start_time": 1557414097,
+ "end_time": 1557417697
+}
+```
+
+Now wrap this into the actual curl command:
+
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/schedule-downtime' \
+ -d "$(jo -p pretty=true type=Service filter="service.name==\"ping4\"" author=icingaadmin comment="IPv4 network maintanence" fixed=true start_time=$(date +%s -d "+0 hour") end_time=$(date +%s -d "+1 hour"))"
+```
+
+Note: This requires GNU date. On macOS, install `coreutils` from Homebrew and use `gdate`.
### process-check-result <a id="icinga2-api-actions-process-check-result"></a>
@@ -844,26 +1077,33 @@ Send a `POST` request to the URL endpoint `/v1/actions/process-check-result`.
In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
-Example for the service `passive-ping6`:
+Example for the service `passive-ping`:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/process-check-result?service=example.localdomain!passive-ping6' \
- -d '{ "exit_status": 2, "plugin_output": "PING CRITICAL - Packet loss = 100%", "performance_data": [ "rta=5000.000000ms;3000.000000;5000.000000;0.000000", "pl=100%;80;100;0" ], "check_source": "example.localdomain", "pretty": true }'
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/process-check-result' \
+-d '{ "type": "Service", "filter": "host.name==\"icinga2-master1.localdomain\" && service.name==\"passive-ping\"", "exit_status": 2, "plugin_output": "PING CRITICAL - Packet loss = 100%", "performance_data": [ "rta=5000.000000ms;3000.000000;5000.000000;0.000000", "pl=100%;80;100;0" ], "check_source": "example.localdomain", "pretty": true }'
+
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully processed check result for object 'icinga2-master1.localdomain!passive-ping'."
+ }
+ ]
+}
+```
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully processed check result for object 'localdomain!passive-ping6'."
- }
- ]
- }
+You can avoid URL encoding of white spaces in object names by using the `filter` attribute in the request body.
Example for using the `Host` type and filter by the host name:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/process-check-result' \
- -d '{ "filter": "host.name==\"example.localdomain\"", "type": "Host", "exit_status": 1, "plugin_output": "Host is not available." }'
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/process-check-result' \
+ -d '{ "filter": "host.name==\"example.localdomain\"", "type": "Host", "exit_status": 1, "plugin_output": "Host is not available." }'
+```
-You can avoid URL encoding of white spaces in object names by using the `filter` attribute in the request body.
> **Note**
>
@@ -888,18 +1128,20 @@ The example reschedules all services with the name "ping6" to immediately perfor
(`next_check` default), ignoring any time periods or whether active checks are
allowed for the service (`force=true`).
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/reschedule-check' \
- -d '{ "type": "Service", "filter": "service.name==\"ping6\"", "force": true, "pretty": true }'
-
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully rescheduled check for object 'example.localdomain!ping6'."
- }
- ]
- }
-
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/reschedule-check' \
+ -d '{ "type": "Service", "filter": "service.name==\"ping6\"", "force": true, "pretty": true }'
+
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully rescheduled check for object 'icinga2-master1.localdomain!ping6'."
+ }
+ ]
+}
+```
### send-custom-notification <a id="icinga2-api-actions-send-custom-notification"></a>
@@ -919,20 +1161,23 @@ In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters
Example for a custom host notification announcing a global maintenance to
host owners:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/send-custom-notification' \
- -d '{ "type": "Host", "author": "icingaadmin", "comment": "System is going down for maintenance", "force": true, "pretty": true }'
-
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully sent custom notification for object 'host0'."
- },
- {
- "code": 200.0,
- "status": "Successfully sent custom notification for object 'host1'."
- }
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/send-custom-notification' \
+ -d '{ "type": "Host", "author": "icingaadmin", "comment": "System is going down for maintenance", "force": true, "pretty": true }'
+
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully sent custom notification for object 'host0'."
+ },
+ {
+ "code": 200.0,
+ "status": "Successfully sent custom notification for object 'host1'."
+ }
+}
+```
### delay-notification <a id="icinga2-api-actions-delay-notification"></a>
@@ -951,20 +1196,23 @@ In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters
Example:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/delay-notification' \
- -d '{ "type": "Service", "timestamp": 1446389894, "pretty": true }'
-
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully delayed notifications for object 'host0!service0'."
- },
- {
- "code": 200.0,
- "status": "Successfully delayed notifications for object 'host1!service1'."
- }
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/delay-notification' \
+ -d '{ "type": "Service", "timestamp": 1446389894, "pretty": true }'
+
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully delayed notifications for object 'host0!service0'."
+ },
+ {
+ "code": 200.0,
+ "status": "Successfully delayed notifications for object 'host1!service1'."
+ }
+}
+```
### acknowledge-problem <a id="icinga2-api-actions-acknowledge-problem"></a>
@@ -988,26 +1236,28 @@ In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters
The following example acknowledges all services which are in a hard critical state and sends out
a notification for them:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/acknowledge-problem?type=Service&filter=service.state==2&service.state_type=1' \
- -d '{ "author": "icingaadmin", "comment": "Global outage. Working on it.", "notify": true, "pretty": true }'
-
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully acknowledged problem for object 'example2.localdomain!ping4'."
- },
- {
- "code": 200.0,
- "status": "Successfully acknowledged problem for object 'example.localdomain!ping4'."
- }
- }
-
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/acknowledge-problem' \
+ -d '{ "type": "Service", "filter": "service.state==2&service.state_type=1", "author": "icingaadmin", "comment": "Global outage. Working on it.", "notify": true, "pretty": true }'
+
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully acknowledged problem for object 'icinga2-satellite1.localdomain!ping4'."
+ },
+ {
+ "code": 200.0,
+ "status": "Successfully acknowledged problem for object 'icinga2-satellite2.localdomain!ping4'."
+ }
+}
+```
### remove-acknowledgement <a id="icinga2-api-actions-remove-acknowledgement"></a>
Removes the acknowledgements for services or hosts. Once the acknowledgement has
-been removed notifications will be sent out again.
+been removed the next notification will be sent again.
Send a `POST` request to the URL endpoint `/v1/actions/remove-acknowledgement`.
@@ -1015,19 +1265,23 @@ A [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid ty
The example removes all service acknowledgements:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-acknowledgement?type=Service&pretty=1'
-
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully removed acknowledgement for object 'host0!service0'."
- },
- {
- "code": 200.0,
- "status": "Successfully removed acknowledgement for object 'example2.localdomain!aws-health'."
- }
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/remove-acknowledgement' \
+ -d '{ "type": "Service", "pretty": true }'
+
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully removed acknowledgement for object 'host0!service0'."
+ },
+ {
+ "code": 200.0,
+ "status": "Successfully removed acknowledgement for object 'example2.localdomain!aws-health'."
+ }
+}
+```
### add-comment <a id="icinga2-api-actions-add-comment"></a>
@@ -1044,23 +1298,27 @@ In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters
The following example adds a comment for all `ping4` services:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/add-comment?type=Service&filter=service.name==%22ping4%22' -d '{ "author": "icingaadmin", "comment": "Troubleticket #123456789 opened.", "pretty": true }'
- {
- "results": [
- {
- "code": 200.0,
- "legacy_id": 26.0,
- "name": "example.localdomain!ping4!example.localdomain-1446824161-0",
- "status": "Successfully added comment 'example.localdomain!ping4!example.localdomain-1446824161-0' for object 'example.localdomain!ping4'."
- },
- {
- "code": 200.0,
- "legacy_id": 27.0,
- "name": "example2.localdomain!ping4!example.localdomain-1446824161-1",
- "status": "Successfully added comment 'example2.localdomain!ping4!example.localdomain-1446824161-1' for object 'example2.localdomain!ping4'."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/add-comment' \
+ -d '{ "type": "Service", "filter": "service.name==\"ping4\"", "author": "icingaadmin", "comment": "Troubleticket #123456789 opened.", "pretty": true }'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "legacy_id": 26.0,
+ "name": "icinga2-satellite1.localdomain!ping4!7e7861c8-8008-4e8d-9910-2a0bb26921bd",
+ "status": "Successfully added comment 'icinga2-satellite1.localdomain!ping4!7e7861c8-8008-4e8d-9910-2a0bb26921bd' for object 'icinga2-satellite1.localdomain!ping4'."
+ },
+ {
+ "code": 200.0,
+ "legacy_id": 27.0,
+ "name": "icinga2-satellite2.localdomain!ping4!9a4c43f5-9407-a536-18bf-4a6cc4b73a9f",
+ "status": "Successfully added comment 'icinga2-satellite2.localdomain!ping4!9a4c43f5-9407-a536-18bf-4a6cc4b73a9f' for object 'icinga2-satellite2.localdomain!ping4'."
+ }
+ ]
+}
+```
### remove-comment <a id="icinga2-api-actions-remove-comment"></a>
@@ -1075,32 +1333,39 @@ A [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid ty
Example for a simple filter using the `comment` URL parameter:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-comment?comment=example2.localdomain!ping4!mbmif.local-1446986367-0&pretty=1'
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully removed comment 'example2.localdomain!ping4!mbmif.local-1446986367-0'."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/remove-comment' \
+ -d '{ "comment": "icinga2-satellite2.localdomain!ping4!9a4c43f5-9407-a536-18bf-4a6cc4b73a9f", "pretty": true }'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully removed comment 'icinga2-satellite2.localdomain!ping4!9a4c43f5-9407-a536-18bf-4a6cc4b73a9f'."
+ }
+ ]
+}
+```
Example for removing all service comments using a service name filter for `ping4`:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-comment?filter=service.name==%22ping4%22&type=Service&pretty=1'
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully removed all comments for object 'example2.localdomain!ping4'."
- },
- {
- "code": 200.0,
- "status": "Successfully removed all comments for object 'example.localdomain!ping4'."
- }
- ]
- }
-
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/remove-comment'
+ -d '{ "type": "Service", "filter": "service.name==\"ping4\"", "pretty": true }'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully removed all comments for object 'icinga2-satellite1.localdomain!ping4'."
+ },
+ {
+ "code": 200.0,
+ "status": "Successfully removed all comments for object 'icinga2-satellite2.localdomain!ping4'."
+ }
+ ]
+}
+```
### schedule-downtime <a id="icinga2-api-actions-schedule-downtime"></a>
@@ -1121,25 +1386,36 @@ Send a `POST` request to the URL endpoint `/v1/actions/schedule-downtime`.
In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
-Example:
+Example for scheduling a downtime for all `ping4` services:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/schedule-downtime?type=Service&filter=service.name==%22ping4%22' -d '{ "start_time": 1446388806, "end_time": 1446389806, "duration": 1000, "author": "icingaadmin", "comment": "IPv4 network maintenance", "pretty": true }'
- {
- "results": [
- {
- "code": 200.0,
- "legacy_id": 2.0,
- "name": "example2.localdomain!ping4!example.localdomain-1446822004-0",
- "status": "Successfully scheduled downtime 'example2.localdomain!ping4!example.localdomain-1446822004-0' for object 'example2.localdomain!ping4'."
- },
- {
- "code": 200.0,
- "legacy_id": 3.0,
- "name": "example.localdomain!ping4!example.localdomain-1446822004-1",
- "status": "Successfully scheduled downtime 'example.localdomain!ping4!example.localdomain-1446822004-1' for object 'example.localdomain!ping4'."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/schedule-downtime' \
+ -d '{ "type": "Service", "filter": "service.name==\"ping4\"", "start_time": 1446388806, "end_time": 1446389806, "duration": 1000, "author": "icingaadmin", "comment": "IPv4 network maintenance", "pretty": true }'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "legacy_id": 2.0,
+ "name": "icinga2-satellite1.localdomain!ping4!ecc5fa55-a5b8-4189-a013-a5d4bb47af34",
+ "status": "Successfully scheduled downtime 'icinga2-satellite1.localdomain!ping4!ecc5fa55-a5b8-4189-a013-a5d4bb47af34' for object 'icinga2-satellite1.localdomain!ping4'."
+ },
+ {
+ "code": 200.0,
+ "legacy_id": 3.0,
+ "name": "icinga2-satellite2.localdomain!ping4!abc59032-4589-abcd-4567-ecf67856c347",
+ "status": "Successfully scheduled downtime 'icinga2-satellite2.localdomain!ping4!abc59032-4589-abcd-4567-ecf67856c347' for object 'icinga2-satellite2.localdomain!ping4'."
+ }
+ ]
+}
+```
+
+In case you want to target just a single service on a host, modify the filter
+like this:
+
+```
+"filter": "host.name==\"icinga2-satellite1.localdomain\" && service.name==\"ping4\""
+```
### remove-downtime <a id="icinga2-api-actions-remove-downtime"></a>
@@ -1154,54 +1430,65 @@ A [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid ty
Example for a simple filter using the `downtime` URL parameter:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-downtime?downtime=example.localdomain!ping4!mbmif.local-1446979168-6&pretty=1'
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully removed downtime 'example.localdomain!ping4!mbmif.local-1446979168-6'."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/remove-downtime' \
+ -d '{ "downtime": "icinga2-satellite2.localdomain!ping4!abc59032-4589-abcd-4567-ecf67856c347", "pretty": true }'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully removed downtime 'icinga2-satellite2.localdomain!ping4!abc59032-4589-abcd-4567-ecf67856c347'."
+ }
+ ]
+}
+```
-Example for removing all host downtimes using a host name filter for `example.localdomain`:
+Example for removing all host downtimes using a host name filter for `icinga2-satellite2.localdomain`:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-downtime?filter=host.name==%22example.localdomain%22&type=Host&pretty=1'
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully removed all downtimes for object 'example.localdomain'."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/remove-downtime' \
+ -d '{ "type": "Host", "filter": "host.name==\"icinga2-satellite2.localdomain\"", "pretty": true }'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully removed all downtimes for object 'icinga2-satellite2.localdomain'."
+ }
+ ]
+}
+```
Example for removing a downtime from a host but not the services filtered by the author name. This example uses
filter variables explained in the [advanced filters](12-icinga2-api.md#icinga2-api-advanced-filters) chapter.
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-downtime' \
- -d $'{
- "type": "Downtime",
- "filter": "host.name == filterHost && !service && downtime.author == filterAuthor",
- "filter_vars": {
- "filterHost": "example.localdomain",
- "filterAuthor": "icingaadmin"
- },
- "pretty": true
- }'
-
- {
- "results": [
- {
- "code": 200.0,
- "status": "Successfully removed downtime 'example.localdomain!mbmif.local-1463043129-3'."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/remove-downtime' \
+ -d $'{
+ "type": "Downtime",
+ "filter": "host.name == filterHost && !service && downtime.author == filterAuthor",
+ "filter_vars": {
+ "filterHost": "icinga2-satellite1.localdomain",
+ "filterAuthor": "icingaadmin"
+ },
+ "pretty": true
+}'
+
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Successfully removed downtime 'icinga2-satellite1.localdomain!ecc5fa55-a5b8-ef34-abcd-a5d41234af34'."
+ }
+ ]
+}
+```
### shutdown-process <a id="icinga2-api-actions-shutdown-process"></a>
-Shuts down Icinga2. May or may not return.
+Shuts down Icinga. May or may not return.
Send a `POST` request to the URL endpoint `/v1/actions/shutdown-process`.
@@ -1209,20 +1496,23 @@ This action does not support a target type or filter.
Example:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/shutdown-process?pretty=1'
-
- {
- "results": [
- {
- "code": 200.0,
- "status": "Shutting down Icinga 2."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/shutdown-process?pretty=1'
+
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Shutting down Icinga 2."
+ }
+ ]
+}
+```
### restart-process <a id="icinga2-api-actions-restart-process"></a>
-Restarts Icinga2. May or may not return.
+Restarts Icinga. May or may not return.
Send a `POST` request to the URL endpoint `/v1/actions/restart-process`.
@@ -1230,22 +1520,31 @@ This action does not support a target type or filter.
Example:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/restart-process?pretty=1'
-
- {
- "results": [
- {
- "code": 200.0,
- "status": "Restarting Icinga 2."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/restart-process?pretty=1'
+
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Restarting Icinga 2."
+ }
+ ]
+}
+```
### generate-ticket <a id="icinga2-api-actions-generate-ticket"></a>
Generates a PKI ticket for [CSR auto-signing](06-distributed-monitoring.md#distributed-monitoring-setup-csr-auto-signing).
This can be used in combination with satellite/client setups requesting this ticket number.
+> **Note**
+>
+> This must be used on the local host, or e.g. by a Puppet master.
+> Doing so remotely may result in security issues with cluster
+> trust relationships.
+
Send a `POST` request to the URL endpoint `/v1/actions/generate-ticket`.
Parameter | Type | Description
@@ -1254,21 +1553,31 @@ Send a `POST` request to the URL endpoint `/v1/actions/generate-ticket`.
Example:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/generate-ticket' \
- -d '{ "cn": "icinga2-client1.localdomain", "pretty": true }'
- {
- "results": [
- {
- "code": 200.0,
- "status": "Generated PKI ticket '4f75d2ecd253575fe9180938ebff7cbca262f96e' for common name 'icinga2-client1.localdomain'.",
- "ticket": "4f75d2ecd253575fe9180938ebff7cbca262f96e"
- }
- ]
- }
-
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/generate-ticket' \
+ -d '{ "cn": "icinga2-client1.localdomain", "pretty": true }'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Generated PKI ticket '4f75d2ecd253575fe9180938ebff7cbca262f96e' for common name 'icinga2-client1.localdomain'.",
+ "ticket": "4f75d2ecd253575fe9180938ebff7cbca262f96e"
+ }
+ ]
+}
+```
## Event Streams <a id="icinga2-api-event-streams"></a>
+Event streams can be used to receive check results, downtimes, comments,
+acknowledgements, etc. as a "live stream" from Icinga.
+
+You can for example forward these types into your own backend. Process the
+metrics and correlate them with notifications and state changes e.g. in Elasticsearch
+with the help of [Icingabeat](https://icinga.com/docs/icingabeat/latest/). Another use
+case are aligned events and creating/resolving tickets automatically in your ticket system.
+
You can subscribe to event streams by sending a `POST` request to the URL endpoint `/v1/events`.
The following parameters need to be specified (either as URL parameters or in a JSON-encoded message body):
@@ -1301,7 +1610,11 @@ being set.
Example for all downtime events:
- &types=DowntimeAdded&types=DowntimeRemoved&types=DowntimeTriggered
+```
+&types=DowntimeAdded&types=DowntimeRemoved&types=DowntimeTriggered
+
+-d '{ "types": ["DowntimeAdded", "DowntimeRemoved", "DowntimeTriggered"] }'
+```
#### <a id="icinga2-api-event-streams-type-checkresult"></a> Event Stream Type: CheckResult
@@ -1438,13 +1751,20 @@ Event streams can be filtered by attributes using the prefix `event.`.
Example for the `CheckResult` type with the `exit_code` set to `2`:
- &types=CheckResult&filter=event.check_result.exit_status==2
+```
+&types=CheckResult&filter=event.check_result.exit_status==2
+
+-d '{ "types": "CheckResult", "filter": "event.check_result.exit_status==2" }'
+```
Example for the `CheckResult` type with the service [matching](18-library-reference.md#global-functions-match)
the string pattern "random\*":
- &types=CheckResult&filter=match%28%22random*%22,event.service%29
+```
+&types=CheckResult&filter=match%28%22random*%22,event.service%29
+-d { "types": "CheckResult", "filter": "match(\"random*\", event.service)" }
+```
### Event Stream Response <a id="icinga2-api-event-streams-response"></a>
@@ -1453,12 +1773,15 @@ must support long-polling and HTTP/1.1. HTTP/1.0 is not supported.
Example:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/events?queue=michi&types=CheckResult&filter=event.check_result.exit_status==2'
-
- {"check_result":{ ... },"host":"example.localdomain","service":"ping4","timestamp":1445421319.7226390839,"type":"CheckResult"}
- {"check_result":{ ... },"host":"example.localdomain","service":"ping4","timestamp":1445421324.7226390839,"type":"CheckResult"}
- {"check_result":{ ... },"host":"example.localdomain","service":"ping4","timestamp":1445421329.7226390839,"type":"CheckResult"}
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/events' \
+ -d '{ "queue": "myqueue", "types": "CheckResult", "filter": "event.check_result.exit_status==2" }'
+{"check_result":{ ... },"host":"example.localdomain","service":"ping4","timestamp":1445421319.7226390839,"type":"CheckResult"}
+{"check_result":{ ... },"host":"example.localdomain","service":"ping4","timestamp":1445421324.7226390839,"type":"CheckResult"}
+{"check_result":{ ... },"host":"example.localdomain","service":"ping4","timestamp":1445421329.7226390839,"type":"CheckResult"}
+```
## Status and Statistics <a id="icinga2-api-status"></a>
@@ -1466,86 +1789,106 @@ Send a `GET` request to the URL endpoint `/v1/status` to retrieve status informa
Example:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/status?pretty=1'
- {
- "results": [
- {
- "name": "ApiListener",
- "perfdata": [ ... ],
- "status": [ ... ]
- },
- ...
- {
- "name": "IcingaAplication",
- "perfdata": [ ... ],
- "status": [ ... ]
- },
- ...
- ]
- }
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/status?pretty=1'
+{
+ "results": [
+ {
+ "name": "ApiListener",
+ "perfdata": [ ... ],
+ "status": [ ... ]
+ },
+ ...
+ {
+ "name": "IcingaAplication",
+ "perfdata": [ ... ],
+ "status": [ ... ]
+ },
+ ...
+ ]
+}
+```
You can limit the output by specifying a status type in the URL, e.g. `IcingaApplication`:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/status/IcingaApplication?pretty=1'
- {
- "results": [
- {
- "perfdata": [],
- "status": {
- "icingaapplication": {
- "app": {
- "enable_event_handlers": true,
- "enable_flapping": true,
- "enable_host_checks": true,
- "enable_notifications": true,
- "enable_perfdata": true,
- "enable_service_checks": true,
- "node_name": "example.localdomain",
- "pid": 59819.0,
- "program_start": 1443019345.093372,
- "version": "v2.3.0-573-g380a131"
- }
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/status/IcingaApplication?pretty=1'
+{
+ "results": [
+ {
+ "perfdata": [],
+ "status": {
+ "icingaapplication": {
+ "app": {
+ "enable_event_handlers": true,
+ "enable_flapping": true,
+ "enable_host_checks": true,
+ "enable_notifications": true,
+ "enable_perfdata": true,
+ "enable_service_checks": true,
+ "node_name": "example.localdomain",
+ "pid": 59819.0,
+ "program_start": 1443019345.093372,
+ "version": "v2.3.0-573-g380a131"
}
}
}
- ]
- }
-
+ }
+ ]
+}
+```
## Configuration Management <a id="icinga2-api-config-management"></a>
-The main idea behind configuration management is to allow external applications
-creating configuration packages and stages based on configuration files and
+The main idea behind configuration management is that external applications
+can create configuration packages and stages based on configuration files and
directory trees. This replaces any additional SSH connection and whatnot to
dump configuration files to Icinga 2 directly.
+
In case you are pushing a new configuration stage to a package, Icinga 2 will
validate the configuration asynchronously and populate a status log which
-can be fetched in a separated request.
+can be fetched in a separated request. Once the validation succeeds,
+a reload is triggered by default.
+This functionality was primarly developed for the [Icinga Director](https://icinga.com/docs/director/latest/)
+but can be used with your own deployments too. It also solves the problem
+with certain runtime objects (zones, endpoints) and can be used to
+deploy global templates in [global cluster zones](06-distributed-monitoring.md#distributed-monitoring-global-zone-config-sync).
-### Creating a Config Package <a id="icinga2-api-config-management-create-package"></a>
+
+### Create a Config Package <a id="icinga2-api-config-management-create-package"></a>
Send a `POST` request to a new config package called `example-cmdb` in this example. This
-will create a new empty configuration package.
-
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST \
- 'https://localhost:5665/v1/config/packages/example-cmdb?pretty=1'
- {
- "results": [
- {
- "code": 200.0,
- "package": "example-cmdb",
- "status": "Created package."
- }
- ]
- }
+creates a new empty configuration package.
-Package names starting with an underscore are reserved for internal packages and must not be used.
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+-X POST 'https://localhost:5665/v1/config/packages/example-cmdb?pretty=1'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "package": "example-cmdb",
+ "status": "Created package."
+ }
+ ]
+}
+```
+
+Package names with the `_` prefix are reserved for internal packages and must not be used.
+You can recognize `_api`, `_etc` and `_cluster` when querying specific objects and packages.
-### Uploading configuration for a Config Package <a id="icinga2-api-config-management-create-config-stage"></a>
+Each configuration object stores the package source in the `package` attribute.
-Configuration files in packages are managed in stages.
-Stages provide a way to maintain multiple configuration versions for a package.
+### Create a Stage: Upload Configuration <a id="icinga2-api-config-management-create-config-stage"></a>
+
+Configuration files in packages are managed in stages. Stages provide a way
+to maintain multiple configuration versions for a package. Once a new stage
+is deployed, the content is validated and set as active stage on success.
+
+On failure, the older stage remains active, and the caller can fetch the `startup.log`
+from this stage deployment attempt to see what exactly failed. You can see that
+in the Director's deployment log.
Send a `POST` request to the URL endpoint `/v1/config/stages` and add the name of an existing
configuration package to the URL path (e.g. `example-cmdb`).
@@ -1562,30 +1905,36 @@ The file path requires one of these two directories inside its path:
Example for a local configuration in the `conf.d` directory:
- "files": { "conf.d/host1.conf": "object Host \"local-host\" { address = \"127.0.0.1\", check_command = \"hostalive\" }" }
+```
+"files": { "conf.d/host1.conf": "object Host \"local-host\" { address = \"127.0.0.1\", check_command = \"hostalive\" }" }
+```
Example for a host configuration inside the `satellite` zone in the `zones.d` directory:
- "files": { "zones.d/satellite/host2.conf": "object Host \"satellite-host\" { address = \"192.168.1.100\", check_command = \"hostalive\" }" }
+```
+"files": { "zones.d/satellite/host2.conf": "object Host \"satellite-host\" { address = \"192.168.1.100\", check_command = \"hostalive\" }" }
+```
The example below will create a new file called `test.conf` in the `conf.d`
directory. Note: This example contains an error (`chec_command`). This is
intentional.
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST \
- -d '{ "files": { "conf.d/test.conf": "object Host \"cmdb-host\" { chec_command = \"dummy\" }" }, "pretty": true }' \
- 'https://localhost:5665/v1/config/stages/example-cmdb'
- {
- "results": [
- {
- "code": 200.0,
- "package": "example-cmdb",
- "stage": "example.localdomain-1441625839-0",
- "status": "Created stage. Icinga2 will reload."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST \
+-d '{ "files": { "conf.d/test.conf": "object Host \"cmdb-host\" { chec_command = \"dummy\" }" }, "pretty": true }' \
+'https://localhost:5665/v1/config/stages/example-cmdb'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "package": "example-cmdb",
+ "stage": "7e7861c8-8008-4e8d-9910-2a0bb26921bd",
+ "status": "Created stage. Reload triggered."
+ }
+ ]
+}
+```
The Icinga 2 API returns the `package` name this stage was created for, and also
generates a unique name for the `stage` attribute you'll need for later requests.
@@ -1599,7 +1948,7 @@ and its configuration objects will remain active.
>
> Old stages are not purged automatically. You can [remove stages](12-icinga2-api.md#icinga2-api-config-management-delete-config-stage) that are no longer in use.
-Icinga 2 will create the following files in the configuration package
+Icinga 2 creates the following files in the configuration package
stage after configuration validation:
File | Description
@@ -1608,7 +1957,8 @@ stage after configuration validation:
startup.log | Contains the [configuration validation](11-cli-commands.md#config-validation) output.
You can [fetch these files](12-icinga2-api.md#icinga2-api-config-management-fetch-config-package-stage-files)
-in order to verify that the new configuration was deployed successfully.
+in order to verify that the new configuration was deployed successfully. Please follow the chapter below
+to learn more about this.
### List Configuration Packages and their Stages <a id="icinga2-api-config-management-list-config-packages"></a>
@@ -1618,52 +1968,55 @@ A list of packages and their stages can be retrieved by sending a `GET` request
The following example contains one configuration package `example-cmdb`. The package does not currently
have an active stage.
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/packages?pretty=1'
- {
- "results": [
- {
- "active-stage": "",
- "name": "example-cmdb",
- "stages": [
- "example.localdomain-1441625839-0"
- ]
- }
- ]
- }
-
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/packages?pretty=1'
+{
+ "results": [
+ {
+ "active-stage": "",
+ "name": "example-cmdb",
+ "stages": [
+ "7e7861c8-8008-4e8d-9910-2a0bb26921bd"
+ ]
+ }
+ ]
+}
+```
-### List Configuration Packages and their Stages <a id="icinga2-api-config-management-list-config-package-stage-files"></a>
+### List Configuration Package Stage Files <a id="icinga2-api-config-management-list-config-package-stage-files"></a>
In order to retrieve a list of files for a stage you can send a `GET` request to
the URL endpoint `/v1/config/stages`. You need to include
-the package name (`example-cmdb`) and stage name (`example.localdomain-1441625839-0`) in the URL:
-
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/stages/example-cmdb/example.localdomain-1441625839-0?pretty=1'
- {
- "results": [
- ...
- {
- "name": "startup.log",
- "type": "file"
- },
- {
- "name": "status",
- "type": "file"
- },
- {
- "name": "conf.d",
- "type": "directory"
- },
- {
- "name": "zones.d",
- "type": "directory"
- },
- {
- "name": "conf.d/test.conf",
- "type": "file"
- }
- ]
- }
+the package name (`example-cmdb`) and stage name (`7e7861c8-8008-4e8d-9910-2a0bb26921bd`) in the URL:
+
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/stages/example-cmdb/7e7861c8-8008-4e8d-9910-2a0bb26921bd?pretty=1'
+{
+ "results": [
+...
+ {
+ "name": "startup.log",
+ "type": "file"
+ },
+ {
+ "name": "status",
+ "type": "file"
+ },
+ {
+ "name": "conf.d",
+ "type": "directory"
+ },
+ {
+ "name": "zones.d",
+ "type": "directory"
+ },
+ {
+ "name": "conf.d/test.conf",
+ "type": "file"
+ }
+ ]
+}
+```
### Fetch Configuration Package Stage Files <a id="icinga2-api-config-management-fetch-config-package-stage-files"></a>
@@ -1676,9 +2029,11 @@ the package name, the stage name and the relative path to the file to the URL pa
The following example fetches the configuration file `conf.d/test.conf`:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/files/example-cmdb/example.localdomain-1441625839-0/conf.d/test.conf'
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/files/example-cmdb/7e7861c8-8008-4e8d-9910-2a0bb26921bd/conf.d/test.conf'
- object Host "cmdb-host" { chec_command = "dummy" }
+object Host "cmdb-host" { chec_command = "dummy" }
+```
You can fetch a [list of existing files](12-icinga2-api.md#icinga2-api-config-management-list-config-package-stage-files)
in a configuration stage and then specifically request their content.
@@ -1692,17 +2047,19 @@ In order to check for validation errors you can fetch the `startup.log` file
by sending a `GET` request to the URL endpoint `/v1/config/files`. You must include
the package name, stage name and the `startup.log` in the URL path.
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/files/example-cmdb/example.localdomain-1441133065-1/startup.log'
- ...
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/files/example-cmdb/7e7861c8-8008-4e8d-9910-2a0bb26921bd/startup.log'
+...
- critical/config: Error: Attribute 'chec_command' does not exist.
- Location:
- /var/lib/icinga2/api/packages/example-cmdb/example.localdomain-1441133065-1/conf.d/test.conf(1): object Host "cmdb-host" { chec_command = "dummy" }
- ^^^^^^^^^^^^^^^^^^^^^^
+critical/config: Error: Attribute 'chec_command' does not exist.
+Location:
+/var/lib/icinga2/api/packages/example-cmdb/7e7861c8-8008-4e8d-9910-2a0bb26921bd/conf.d/test.conf(1): object Host "cmdb-host" { chec_command = "dummy" }
+ ^^^^^^^^^^^^^^^^^^^^^^
- critical/config: 1 error
+critical/config: 1 error
+```
-The output is similar to the manual [configuration validation](11-cli-commands.md#config-validation).
+The output is the exact as known from [configuration validation](11-cli-commands.md#config-validation).
> **Note**
>
@@ -1715,20 +2072,21 @@ You can send a `DELETE` request to the URL endpoint `/v1/config/stages`
in order to purge a configuration stage. You must include the package and
stage name inside the URL path.
-The following example removes the failed configuration stage `example.localdomain-1441133065-1`
+The following example removes the failed configuration stage `7e7861c8-8008-4e8d-9910-2a0bb26921bd`
in the `example-cmdb` configuration package:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE \
- 'https://localhost:5665/v1/config/stages/example-cmdb/example.localdomain-1441133065-1?pretty=1'
- {
- "results": [
- {
- "code": 200.0,
- "status": "Stage deleted."
- }
- ]
- }
-
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X DELETE 'https://localhost:5665/v1/config/stages/example-cmdb/7e7861c8-8008-4e8d-9910-2a0bb26921bd?pretty=1'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Stage deleted."
+ }
+ ]
+}
+```
### Deleting Configuration Package <a id="icinga2-api-config-management-delete-config-package"></a>
@@ -1738,18 +2096,19 @@ with the package name in the URL path.
This example entirely deletes the configuration package `example-cmdb`:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE \
- 'https://localhost:5665/v1/config/packages/example-cmdb?pretty=1'
- {
- "results": [
- {
- "code": 200.0,
- "package": "example-cmdb",
- "status": "Deleted package."
- }
- ]
- }
-
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE \
+'https://localhost:5665/v1/config/packages/example-cmdb?pretty=1'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "package": "example-cmdb",
+ "status": "Deleted package."
+ }
+ ]
+}
+```
## Types <a id="icinga2-api-types"></a>
@@ -1769,43 +2128,50 @@ Each response entry in the results array contains the following attributes:
In order to view a specific configuration object type specify its name inside the URL path:
- $ curl -k -s -u root:icinga 'https://localhost:5665/v1/types/Object?pretty=1'
- {
- "results": [
- {
- "abstract": false,
- "fields": {
- "type": {
- "array_rank": 0.0,
- "attributes": {
- "config": false,
- "navigation": false,
- "no_user_modify": false,
- "no_user_view": false,
- "required": false,
- "state": false
- },
- "id": 0.0,
- "type": "String"
- }
- },
- "name": "Object",
- "plural_name": "Objects",
- "prototype_keys": [
- "clone",
- "notify_attribute",
- "to_string"
- ]
- }
- ]
- }
-
+```
+$ curl -k -s -u root:icinga 'https://localhost:5665/v1/types/Object?pretty=1'
+{
+ "results": [
+ {
+ "abstract": false,
+ "fields": {
+ "type": {
+ "array_rank": 0.0,
+ "attributes": {
+ "config": false,
+ "navigation": false,
+ "no_user_modify": false,
+ "no_user_view": false,
+ "required": false,
+ "state": false
+ },
+ "id": 0.0,
+ "type": "String"
+ }
+ },
+ "name": "Object",
+ "plural_name": "Objects",
+ "prototype_keys": [
+ "clone",
+ "notify_attribute",
+ "to_string"
+ ]
+ }
+ ]
+}
+```
-## Console <a id="icinga2-api-console"></a>
+## Debug Console <a id="icinga2-api-console"></a>
You can inspect variables and execute other expressions by sending a `POST` request to the URL endpoint `/v1/console/execute-script`.
In order to receive auto-completion suggestions, send a `POST` request to the URL endpoint `/v1/console/auto-complete-script`.
+> **Note**
+>
+> This functionality is used by the [debug console](11-cli-commands.md#cli-command-console). Do not use this in production, unless
+> you are aware of the fact that expressions and commands may crash the daemon, or lead into
+> unwanted behaviour. Use this URL endpoint **read-only** when needed.
+
The following parameters need to be specified (either as URL parameters or in a JSON-encoded message body):
Parameter | Type | Description
@@ -1826,82 +2192,155 @@ If you specify a session identifier, the same script context can be reused for m
Example for fetching the command line from the local host's last check result:
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/console/execute-script?command=get_host(NodeName).last_check_result.command&sandboxed=0&session=bb75fd7c-c686-407d-9688-582c04227756&pretty=1'
- {
- "results": [
- {
- "code": 200.0,
- "result": [
- "/usr/local/sbin/check_ping",
- "-H",
- "127.0.0.1",
- "-c",
- "5000,100%",
- "-w",
- "3000,80%"
- ],
- "status": "Executed successfully."
- }
- ]
- }
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/console/execute-script?command=get_host(NodeName).last_check_result.command&sandboxed=0&session=bb75fd7c-c686-407d-9688-582c04227756&pretty=1'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "result": [
+ "/usr/local/sbin/check_ping",
+ "-H",
+ "127.0.0.1",
+ "-c",
+ "5000,100%",
+ "-w",
+ "3000,80%"
+ ],
+ "status": "Executed successfully."
+ }
+ ]
+}
+```
Example for fetching auto-completion suggestions for the `Host.` type. This works in a
similar fashion when pressing TAB inside the [console CLI command](11-cli-commands.md#cli-command-console):
- $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/console/auto-complete-script?command=Host.&sandboxed=0&session=bb75fd7c-c686-407d-9688-582c04227756&pretty=1'
- {
- "results": [
- {
- "code": 200.0,
- "status": "Auto-completed successfully.",
- "suggestions": [
- "Host.type",
- "Host.name",
- "Host.prototype",
- "Host.base",
- "Host.register_attribute_handler",
- "Host.clone",
- "Host.notify_attribute",
- "Host.to_string"
- ]
- }
- ]
- }
-
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/console/auto-complete-script?command=Host.&sandboxed=0&session=bb75fd7c-c686-407d-9688-582c04227756&pretty=1'
+{
+ "results": [
+ {
+ "code": 200.0,
+ "status": "Auto-completed successfully.",
+ "suggestions": [
+ "Host.type",
+ "Host.name",
+ "Host.prototype",
+ "Host.base",
+ "Host.register_attribute_handler",
+ "Host.clone",
+ "Host.notify_attribute",
+ "Host.to_string"
+ ]
+ }
+ ]
+}
+```
## API Clients <a id="icinga2-api-clients"></a>
-There are a couple of existing clients which can be used with the Icinga 2 API:
-
-* [curl](https://curl.haxx.se/) or any other HTTP client really
-* [Icinga 2 console (CLI command)](12-icinga2-api.md#icinga2-api-clients-cli-console)
-* [Icinga Web 2 Director](https://icinga.com/products/icinga-web-2-modules/)
+After its initial release in 2015, community members
+and developers have been working hard to add more REST API
+clients and integrations into DevOps tools.
-Demo cases:
-
-* [Dashing](https://github.com/Icinga/dashing-icinga2)
-* [API examples](https://github.com/Icinga/icinga2-api-examples)
+* [Libraries](12-icinga2-api.md#icinga2-api-clients-libraries)
+* [Status](12-icinga2-api.md#icinga2-api-clients-status)
+* [Management](12-icinga2-api.md#icinga2-api-clients-management)
+* [Event Streams](12-icinga2-api.md#icinga2-api-clients-event-streams)
+* [Actions](12-icinga2-api.md#icinga2-api-clients-actions)
+* [REST API Apps](12-icinga2-api.md#icinga2-api-clients-apps)
Additional [programmatic examples](12-icinga2-api.md#icinga2-api-clients-programmatic-examples)
will help you getting started using the Icinga 2 API in your environment.
-### Icinga 2 Console <a id="icinga2-api-clients-cli-console"></a>
-
-By default the [console CLI command](11-cli-commands.md#cli-command-console) evaluates
-expressions in a local interpreter, i.e. independently from your Icinga 2 daemon.
-Add the `--connect` parameter to debug and evaluate expressions via the API.
-
-### API Clients Programmatic Examples <a id="icinga2-api-clients-programmatic-examples"></a>
-
-The programmatic examples use HTTP basic authentication and SSL certificate
-verification. The CA file is expected in `pki/icinga2-ca.crt`
-but you may adjust the examples for your likings.
-
-The [request method](icinga2-api-requests) is `POST` using
-[X-HTTP-Method-Override: GET](12-icinga2-api.md#icinga2-api-requests-method-override)
-which allows you to send a JSON request body. The examples request
-specific service attributes joined with host attributes. `attrs`
-and `joins` are therefore specified as array.
+### Libraries <a id="icinga2-api-clients-libraries"></a>
+
+Name | Language | Description
+------------------------------------------------------------------------------------------------|---------------|--------------------------------------------------------
+[ruby-icinga2](https://github.com/bodsch/ruby-icinga2) | Ruby | Ruby library
+[python-icinga2_api](https://github.com/KevinHonka/Icinga2_Python_API) | Python | Python library
+[python-icinga2-api](https://github.com/fmnisme/python-icinga2api) | Python | Python bindings for Icinga 2 interaction
+[go-icinga2](https://github.com/xert/go-icinga2) | Golang | Golang functions and type definitions
+[go-icinga2-api](https://github.com/lrsmith/go-icinga2-api/) | Golang | Golang implementation used inside the Terraform provider
+[go-icinga2-client](https://github.com/Nexinto/go-icinga2-client) | Golang | Golang implementation for the Rancher integration.
+[Monitoring::Icinga2::Client::REST](https://metacpan.org/release/THESEAL/Monitoring-Icinga2-Client-REST-2.0.0) | Perl | Perl bindings.
+[Icinga 2 API in PHP](https://github.com/uniwue-rz/icinga2-api) | PHP | PHP implementation. For other examples, look into Icinga Web 2 and Director.
+
+### Status <a id="icinga2-api-clients-status"></a>
+
+Name | Language | Description
+------------------------------------------------------------------------------------------------|---------------|--------------------------------------------------------
+[Dashing](https://github.com/dnsmichi/dashing-icinga2) | Ruby, HTML | Dashboard for Dashing querying the REST API for current host/service/global status
+[InfluxDB Telegraf Input](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/icinga2/README.md) | Golang | [Telegraf](https://github.com/influxdata/telegraf) is an agent written in Go for collecting, processing, aggregating, and writing metrics.
+[Icinga 2 Slack Bot](https://github.com/mlabouardy/icinga2-slack-bot) | Golang | Query host/service details from a [Slack](https://slack.com/) channel
+[icinga2bot](https://github.com/reikoNeko/icinga2bot) | Python | [Errbot](http://errbot.io/en/latest/user_guide/setup.html) plugin to fetch status and event stream information and forward to XMPP, IRC, etc.
+[IcingaBusyLightAgent](https://github.com/stdevel/IcingaBusylightAgent) | C# | Notification Agent in Systray
+[BitBar for OSX](https://getbitbar.com/plugins/Dev/Icinga2/icinga2.24m.py) | Python | macOS tray app for highlighting the host/service status
+[Icinga 2 Multistatus](https://chrome.google.com/webstore/detail/icinga-multi-status/khabbhcojgkibdeipanmiphceeoiijal/related) | - | Chrome Extension
+
+### Manage Objects <a id="icinga2-api-clients-management"></a>
+
+Name | Language | Description
+------------------------------------------------------------------------------------------------|---------------|--------------------------------------------------------
+[Icinga Director](https://icinga.com/docs/director/latest) | PHP, JS | Icinga 2 configuration interface with a nice frontend, and automated imports for nearly any source.
+[Terraform Provider](https://github.com/terraform-providers/terraform-provider-icinga2) | Golang | Register hosts from Terraform in Icinga 2. [Official docs](https://www.terraform.io/docs/providers/icinga2/index.html).
+[Kube Icinga](https://github.com/gyselroth/kube-icinga) | Typescript | Monitor Kubernetes services / resources using icinga2 (including autodiscovery support)
+[Logstash output for Icinga](https://www.icinga.com/products/integrations/elastic/) | Ruby | Forward check results and create objects from log events
+[Foreman Smart Proxy Monitoring](https://github.com/theforeman/smart_proxy_monitoring) | Ruby | Smart Proxy extension for Foreman creating and deleting hosts and services in Icinga 2
+[Rancher integration](https://github.com/Nexinto/rancher-icinga) | Golang | Registers [Rancher](http://rancher.com/rancher/) resources in Icinga 2 for monitoring.
+[AWS/EC2](https://github.com/Icinga/icinga2-api-examples/tree/master/aws-ec2) | Ruby | Example script for creating and deleting AWS instances in Icinga 2
+[Ansible Host Module](https://docs.ansible.com/ansible/latest/modules/icinga2_host_module.html) | Python | In progress, [Ansible Feature](https://docs.ansible.com/ansible/latest/modules/icinga2_feature_module.html#icinga2-feature-module) is also there.
+
+### Event Streams <a id="icinga2-api-clients-event-streams"></a>
+
+Name | Language | Description
+------------------------------------------------------------------------------------------------|---------------|--------------------------------------------------------
+[Elastic Icingabeat](https://icinga.com/docs/icingabeat/latest/) | Golang | Process events and send to Elasticsearch/Logstash outputs
+[Request Tracker ticket integration](https://github.com/bytemine/icinga2rt) | Golang | Create and update RT tickets
+[Logstash input event stream](https://github.com/bobapple/logstash-input-icinga_eventstream) | Ruby | Forward events as Logstash input
+[Flapjack events](https://github.com/sol1/flapjack-icinga2) | Golang | Dumping events into Redis for Flapjack processing
+[Stackstorm integration](https://github.com/StackStorm-Exchange/stackstorm-icinga2) | Python | Processing events and fetching status information
+
+### Actions <a id="icinga2-api-clients-actions"></a>
+
+Name | Language | Description
+------------------------------------------------------------------------------------------------|---------------|--------------------------------------------------------
+[Icinga Web 2](https://icinga.com/docs/icingaweb2/latest/) | PHP | Trigger actions via command transport
+[Logstash output for Icinga](https://www.icinga.com/products/integrations/elastic/) | Ruby | Forward check results and create objects from log events
+[OTRS SystemMonitoring](https://github.com/OTRS/SystemMonitoring) | Perl | Acknowledge problems in Icinga 2 from OTRS tickets
+[mqttwarn](https://github.com/jpmens/mqttwarn#icinga2) | Python | Forward check results from mqttwarn to Icinga 2
+[Lita handler](https://github.com/tuxmea/lita-icinga2) | Ruby | List, recheck and acknowledge through a #chatops bot called [Lita](https://github.com/litaio/lita)
+[Sakuli forwarder](http://sakuli.readthedocs.io/en/latest/forwarder-icinga2api/) | Java | Forward check results from tests from [Sakuli](https://github.com/ConSol/sakuli) to Icinga 2
+[OpsGenie actions](https://www.opsgenie.com/docs/integrations/icinga2-integration) | Golang, Java | Integrate Icinga 2 into OpsGenie
+
+
+### REST API Apps <a id="icinga2-api-clients-apps"></a>
+
+Name | Language | Description
+------------------------------------------------------------------------------------------------|---------------|--------------------------------------------------------
+Browser plugins | - | [Postman for Chrome](https://www.getpostman.com), [RESTED for Firefox](https://addons.mozilla.org/en-US/firefox/addon/rested/)
+[Postman](https://www.getpostman.com/) | - | App instead of browser plugin
+[Cocoa Rest Client](http://mmattozzi.github.io/cocoa-rest-client/) | - | macOS app
+[Paw for MacOS](https://paw.cloud) | (exported) | Paw is a full-featured HTTP client that lets you test and describe the APIs you build or consume. It has a beautiful native macOS interface to compose requests, inspect server responses, generate client code and export API definitions.
+
+
+### Programmatic Examples <a id="icinga2-api-clients-programmatic-examples"></a>
+
+The following languages are covered:
+
+* [Python](12-icinga2-api.md#icinga2-api-clients-programmatic-examples-python)
+* [Ruby](12-icinga2-api.md#icinga2-api-clients-programmatic-examples-ruby)
+* [PHP](12-icinga2-api.md#icinga2-api-clients-programmatic-examples-php)
+* [Perl](12-icinga2-api.md#icinga2-api-clients-programmatic-examples-perl)
+* [Golang](12-icinga2-api.md#icinga2-api-clients-programmatic-examples-golang)
+
+The [request method](icinga2-api-requests) is `POST` using [X-HTTP-Method-Override: GET](12-icinga2-api.md#icinga2-api-requests-method-override)
+which allows you to send a JSON request body. The examples request specific service
+attributes joined with host attributes. `attrs` and `joins` are therefore specified
+as array.
The `filter` attribute [matches](18-library-reference.md#global-functions-match)
on all services with `ping` in their name.
@@ -1909,92 +2348,95 @@ on all services with `ping` in their name.
The following example uses **Python** and the `requests` and `json` module:
- # pip install requests
- # pip install json
-
- $ vim icinga2-api-example.py
-
- #!/usr/bin/env python
-
- import requests, json
-
- # Replace 'localhost' with your FQDN and certificate CN
- # for SSL verification
- request_url = "https://localhost:5665/v1/objects/services"
- headers = {
- 'Accept': 'application/json',
- 'X-HTTP-Method-Override': 'GET'
- }
- data = {
- "attrs": [ "name", "state", "last_check_result" ],
- "joins": [ "host.name", "host.state", "host.last_check_result" ],
- "filter": "match(\"ping*\", service.name)",
- }
-
- r = requests.post(request_url,
- headers=headers,
- auth=('root', 'icinga'),
- data=json.dumps(data),
- verify="pki/icinga2-ca.crt")
-
- print "Request URL: " + str(r.url)
- print "Status code: " + str(r.status_code)
-
- if (r.status_code == 200):
- print "Result: " + json.dumps(r.json())
- else:
- print r.text
- r.raise_for_status()
-
- $ python icinga2-api-example.py
-
+```
+# pip install requests
+# pip install json
+
+$ vim icinga2-api-example.py
+
+#!/usr/bin/env python
+
+import requests, json
+
+# Replace 'localhost' with your FQDN and certificate CN
+# for SSL verification
+request_url = "https://localhost:5665/v1/objects/services"
+headers = {
+ 'Accept': 'application/json',
+ 'X-HTTP-Method-Override': 'GET'
+ }
+data = {
+ "attrs": [ "name", "state", "last_check_result" ],
+ "joins": [ "host.name", "host.state", "host.last_check_result" ],
+ "filter": "match(\"ping*\", service.name)",
+}
+
+r = requests.post(request_url,
+ headers=headers,
+ auth=('root', 'icinga'),
+ data=json.dumps(data),
+ verify="pki/icinga2-ca.crt")
+
+print "Request URL: " + str(r.url)
+print "Status code: " + str(r.status_code)
+
+if (r.status_code == 200):
+ print "Result: " + json.dumps(r.json())
+else:
+ print r.text
+ r.raise_for_status()
+
+$ python icinga2-api-example.py
+```
#### Example API Client in Ruby <a id="icinga2-api-clients-programmatic-examples-ruby"></a>
The following example uses **Ruby** and the `rest_client` gem:
- # gem install rest_client
-
- $ vim icinga2-api-example.rb
-
- #!/usr/bin/ruby
-
- require 'rest_client'
-
- # Replace 'localhost' with your FQDN and certificate CN
- # for SSL verification
- request_url = "https://localhost:5665/v1/objects/services"
- headers = {
- "Accept" => "application/json",
- "X-HTTP-Method-Override" => "GET"
- }
- data = {
- "attrs" => [ "name", "state", "last_check_result" ],
- "joins" => [ "host.name", "host.state", "host.last_check_result" ],
- "filter" => "match(\"ping*\", service.name)",
- }
-
- r = RestClient::Resource.new(
- URI.encode(request_url),
- :headers => headers,
- :user => "root",
- :password => "icinga",
- :ssl_ca_file => "pki/icinga2-ca.crt")
-
- begin
- response = r.post(data.to_json)
- rescue => e
- response = e.response
- end
-
- puts "Status: " + response.code.to_s
- if response.code == 200
- puts "Result: " + (JSON.pretty_generate JSON.parse(response.body))
- else
- puts "Error: " + response
- end
-
- $ ruby icinga2-api-example.rb
+```
+# gem install rest_client
+
+$ vim icinga2-api-example.rb
+
+#!/usr/bin/ruby
+
+require 'rest_client'
+
+# Replace 'localhost' with your FQDN and certificate CN
+# for SSL verification
+request_url = "https://localhost:5665/v1/objects/services"
+headers = {
+ "Accept" => "application/json",
+ "X-HTTP-Method-Override" => "GET"
+}
+data = {
+ "attrs" => [ "name", "state", "last_check_result" ],
+ "joins" => [ "host.name", "host.state", "host.last_check_result" ],
+ "filter" => "match(\"ping*\", service.name)",
+}
+
+r = RestClient::Resource.new(
+ URI.encode(request_url),
+ :headers => headers,
+ :user => "root",
+ :password => "icinga",
+ :ssl_ca_file => "pki/icinga2-ca.crt")
+
+begin
+ response = r.post(data.to_json)
+rescue => e
+ response = e.response
+end
+
+puts "Status: " + response.code.to_s
+if response.code == 200
+ puts "Result: " + (JSON.pretty_generate JSON.parse(response.body))
+else
+ puts "Error: " + response
+end
+
+$ ruby icinga2-api-example.rb
+```
A more detailed example can be found in the [Dashing demo](https://github.com/Icinga/dashing-icinga2).
@@ -2002,100 +2444,172 @@ A more detailed example can be found in the [Dashing demo](https://github.com/Ic
The following example uses **PHP** and its `curl` library:
- $ vim icinga2-api-example.php
-
- #!/usr/bin/env php
- <?php
- # Replace 'localhost' with your FQDN and certificate CN
- # for SSL verification
- $request_url = "https://localhost:5665/v1/objects/services";
- $username = "root";
- $password = "icinga";
- $headers = array(
- 'Accept: application/json',
- 'X-HTTP-Method-Override: GET'
- );
- $data = array(
- attrs => array('name', 'state', 'last_check_result'),
- joins => array('host.name', 'host.state', 'host.last_check_result'),
- filter => 'match("ping*", service.name)',
- );
-
- $ch = curl_init();
- curl_setopt_array($ch, array(
- CURLOPT_URL => $request_url,
- CURLOPT_HTTPHEADER => $headers,
- CURLOPT_USERPWD => $username . ":" . $password,
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_CAINFO => "pki/icinga2-ca.crt",
- CURLOPT_POST => count($data),
- CURLOPT_POSTFIELDS => json_encode($data)
- ));
-
- $response = curl_exec($ch);
- if ($response === false) {
- print "Error: " . curl_error($ch) . "(" . $response . ")\n";
- }
-
- $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
- print "Status: " . $code . "\n";
-
- if ($code == 200) {
- $response = json_decode($response, true);
- print_r($response);
- }
- ?>
-
- $ php icinga2-api-example.php
+```
+$ vim icinga2-api-example.php
+
+#!/usr/bin/env php
+<?php
+# Replace 'localhost' with your FQDN and certificate CN
+# for SSL verification
+$request_url = "https://localhost:5665/v1/objects/services";
+$username = "root";
+$password = "icinga";
+$headers = array(
+ 'Accept: application/json',
+ 'X-HTTP-Method-Override: GET'
+);
+$data = array(
+ attrs => array('name', 'state', 'last_check_result'),
+ joins => array('host.name', 'host.state', 'host.last_check_result'),
+ filter => 'match("ping*", service.name)',
+);
+
+$ch = curl_init();
+curl_setopt_array($ch, array(
+ CURLOPT_URL => $request_url,
+ CURLOPT_HTTPHEADER => $headers,
+ CURLOPT_USERPWD => $username . ":" . $password,
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_CAINFO => "pki/icinga2-ca.crt",
+ CURLOPT_POST => count($data),
+ CURLOPT_POSTFIELDS => json_encode($data)
+));
+
+$response = curl_exec($ch);
+if ($response === false) {
+ print "Error: " . curl_error($ch) . "(" . $response . ")\n";
+}
+
+$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+curl_close($ch);
+print "Status: " . $code . "\n";
+
+if ($code == 200) {
+ $response = json_decode($response, true);
+ print_r($response);
+}
+?>
+
+$ php icinga2-api-example.php
+```
#### Example API Client in Perl <a id="icinga2-api-clients-programmatic-examples-perl"></a>
The following example uses **Perl** and the `Rest::Client` module:
- # perl -MCPAN -e 'install REST::Client'
- # perl -MCPAN -e 'install JSON'
- # perl -MCPAN -e 'install MIME::Base64'
- # perl -MCPAN -e 'install Data::Dumper'
-
- $ vim icinga2-api-example.pl
-
- #!/usr/bin/env perl
-
- use strict;
- use warnings;
- use REST::Client;
- use MIME::Base64;
- use JSON;
- use Data::Dumper;
-
- # Replace 'localhost' with your FQDN and certificate CN
- # for SSL verification
- my $request_host = "https://localhost:5665";
- my $userpass = "root:icinga";
-
- my $client = REST::Client->new();
- $client->setHost($request_host);
- $client->setCa("pki/icinga2-ca.crt");
- $client->addHeader("Accept", "application/json");
- $client->addHeader("X-HTTP-Method-Override", "GET");
- $client->addHeader("Authorization", "Basic " . encode_base64($userpass));
- my %json_data = (
- attrs => ['name', 'state', 'last_check_result'],
- joins => ['host.name', 'host.state', 'host.last_check_result'],
- filter => 'match("ping*", service.name)',
- );
- my $data = encode_json(\%json_data);
- $client->POST("/v1/objects/services", $data);
-
- my $status = $client->responseCode();
- print "Status: " . $status . "\n";
- my $response = $client->responseContent();
- if ($status == 200) {
- print "Result: " . Dumper(decode_json($response)) . "\n";
- } else {
- print "Error: " . $response . "\n";
- }
-
- $ perl icinga2-api-example.pl
+```
+# perl -MCPAN -e 'install REST::Client'
+# perl -MCPAN -e 'install JSON'
+# perl -MCPAN -e 'install MIME::Base64'
+# perl -MCPAN -e 'install Data::Dumper'
+
+$ vim icinga2-api-example.pl
+
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use REST::Client;
+use MIME::Base64;
+use JSON;
+use Data::Dumper;
+
+# Replace 'localhost' with your FQDN and certificate CN
+# for SSL verification
+my $request_host = "https://localhost:5665";
+my $userpass = "root:icinga";
+
+my $client = REST::Client->new();
+$client->setHost($request_host);
+$client->setCa("pki/icinga2-ca.crt");
+$client->addHeader("Accept", "application/json");
+$client->addHeader("X-HTTP-Method-Override", "GET");
+$client->addHeader("Authorization", "Basic " . encode_base64($userpass));
+my %json_data = (
+ attrs => ['name', 'state', 'last_check_result'],
+ joins => ['host.name', 'host.state', 'host.last_check_result'],
+ filter => 'match("ping*", service.name)',
+);
+my $data = encode_json(\%json_data);
+$client->POST("/v1/objects/services", $data);
+
+my $status = $client->responseCode();
+print "Status: " . $status . "\n";
+my $response = $client->responseContent();
+if ($status == 200) {
+ print "Result: " . Dumper(decode_json($response)) . "\n";
+} else {
+ print "Error: " . $response . "\n";
+}
+
+$ perl icinga2-api-example.pl
+```
+
+
+#### Example API Client in Golang <a id="icinga2-api-clients-programmatic-examples-golang"></a>
+
+Requires the Golang build chain.
+```
+$ vim icinga2-api-example.go
+
+package main
+
+import (
+ "bytes"
+ "crypto/tls"
+ "log"
+ "io/ioutil"
+ "net/http"
+)
+
+func main() {
+ var urlBase= "https://localhost:5665"
+ var apiUser= "root"
+ var apiPass= "icinga"
+
+ urlEndpoint := urlBase + "/v1/objects/services"
+
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ }
+ httpClient := &http.Client{Transport: tr}
+
+ var requestBody = []byte(`{
+ "attrs": [ "name", "state", "last_check_result" ],
+ "joins": [ "host.name", "host.state", "host.last_check_result" ],
+ "filter": "match(\"ping*\", service.name)"
+ }`)
+
+ req, err := http.NewRequest("POST", urlEndpoint, bytes.NewBuffer(requestBody))
+ req.Header.Set("Accept", "application/json")
+ req.Header.Set("X-HTTP-Method-Override", "GET")
+
+ req.SetBasicAuth(apiUser, apiPass)
+
+ resp, err := httpClient.Do(req)
+ if err != nil {
+ log.Fatal("Server error:", err)
+ return
+ }
+ defer resp.Body.Close()
+
+ log.Print("Response status:", resp.Status)
+
+ bodyBytes, _ := ioutil.ReadAll(resp.Body)
+ bodyString := string(bodyBytes)
+
+ if resp.StatusCode == http.StatusOK {
+ log.Print("Result: " + bodyString)
+ } else {
+ log.Fatal(bodyString)
+ }
+}
+```
+
+Build the binary:
+
+```
+go build icinga2-api-example.go
+./icinga2-api-example
+```
diff --git a/doc/13-addons.md b/doc/13-addons.md
index b617498..01bdfee 100644
--- a/doc/13-addons.md
+++ b/doc/13-addons.md
@@ -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
diff --git a/doc/14-features.md b/doc/14-features.md
index 0ecafd6..a5aacf4 100644
--- a/doc/14-features.md
+++ b/doc/14-features.md
@@ -21,11 +21,30 @@ By default file the `mainlog` feature is enabled. When running Icinga 2
on a terminal log messages with severity `information` or higher are
written to the console.
-Packages will install a configuration file for logrotate on supported
-platforms. This configuration ensures that the `icinga2.log`, `error.log` and
-`debug.log` files are rotated on a daily basis.
+### Log Rotation <a id="logging-logrotate"></a>
-## DB IDO <a id="db-ido"></a>
+Packages provide a configuration file for [logrotate](https://linux.die.net/man/8/logrotate)
+on Linux/Unix. Typically this is installed into `/etc/logrotate.d/icinga2`
+and modifications won't be overridden on upgrade.
+
+Instead of sending the reload HUP signal, logrotate
+sends the USR1 signal to notify the Icinga daemon
+that it has rotate the log file. Icinga reopens the log
+files then:
+
+* `/var/log/icinga2/icinga2.log` (requires `mainlog` enabled)
+* `/var/log/icinga2/debug.log` (requires `debuglog` enabled)
+* `/var/log/icinga2/erorr.log`
+
+By default, log files will be rotated daily.
+
+## Core Backends <a id="core-backends"></a>
+
+### REST API <a id="core-backends-api"></a>
+
+The REST API is documented [here](12-icinga2-api.md#icinga2-api) as a core feature.
+
+### IDO Database (DB IDO) <a id="db-ido"></a>
The IDO (Icinga Data Output) feature for Icinga 2 takes care of exporting all
configuration and status information into a database. The IDO database is used
@@ -36,10 +55,8 @@ chapter. Details on the configuration can be found in the
[IdoMysqlConnection](09-object-types.md#objecttype-idomysqlconnection) and
[IdoPgsqlConnection](09-object-types.md#objecttype-idopgsqlconnection)
object configuration documentation.
-The DB IDO feature supports [High Availability](06-distributed-monitoring.md#distributed-monitoring-high-availability-db-ido) in
-the Icinga 2 cluster.
-### DB IDO Health <a id="db-ido-health"></a>
+#### DB IDO Health <a id="db-ido-health"></a>
If the monitoring health indicator is critical in Icinga Web 2,
you can use the following queries to manually check whether Icinga 2
@@ -87,7 +104,21 @@ status_update_time
A detailed list on the available table attributes can be found in the [DB IDO Schema documentation](24-appendix.md#schema-db-ido).
-### DB IDO Cleanup <a id="db-ido-cleanup"></a>
+#### DB IDO in Cluster HA Zones <a id="db-ido-cluster-ha"></a>
+
+The DB IDO feature supports [High Availability](06-distributed-monitoring.md#distributed-monitoring-high-availability-db-ido) in
+the Icinga 2 cluster.
+
+By default, both endpoints in a zone calculate the
+endpoint which activates the feature, the other endpoint
+automatically pauses it. If the cluster connection
+breaks at some point, the paused IDO feature automatically
+does a failover.
+
+You can disable this behaviour by setting `enable_ha = false`
+in both feature configuration files.
+
+#### DB IDO Cleanup <a id="db-ido-cleanup"></a>
Objects get deactivated when they are deleted from the configuration.
This is visible with the `is_active` column in the `icinga_objects` table.
@@ -112,7 +143,7 @@ Example if you prefer to keep notification history for 30 days:
The historical tables are populated depending on the data `categories` specified.
Some tables are empty by default.
-### DB IDO Tuning <a id="db-ido-tuning"></a>
+#### DB IDO Tuning <a id="db-ido-tuning"></a>
As with any application database, there are ways to optimize and tune the database performance.
@@ -158,94 +189,41 @@ VACUUM
> Don't use `VACUUM FULL` as this has a severe impact on performance.
-## External Commands <a id="external-commands"></a>
+## Metrics <a id="metrics"></a>
-> **Note**
->
-> Please use the [REST API](12-icinga2-api.md#icinga2-api) as modern and secure alternative
-> for external actions.
+Whenever a host or service check is executed, or received via the REST API,
+best practice is to provide performance data.
-Icinga 2 provides an external command pipe for processing commands
-triggering specific actions (for example rescheduling a service check
-through the web interface).
+This data is parsed by features sending metrics to time series databases (TSDB):
-In order to enable the `ExternalCommandListener` configuration use the
-following command and restart Icinga 2 afterwards:
+* [Graphite](14-features.md#graphite-carbon-cache-writer)
+* [InfluxDB](14-features.md#influxdb-writer)
+* [OpenTSDB](14-features.md#opentsdb-writer)
- # icinga2 feature enable command
+Metrics, state changes and notifications can be managed with the following integrations:
-Icinga 2 creates the command pipe file as `/var/run/icinga2/cmd/icinga2.cmd`
-using the default configuration.
-
-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:
+* [Elastic Stack](14-features.md#elastic-stack-integration)
+* [Graylog](14-features.md#graylog-integration)
- # /bin/echo "[`date +%s`] SCHEDULE_FORCED_SVC_CHECK;localhost;ping4;`date +%s`" >> /var/run/icinga2/cmd/icinga2.cmd
- # 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'
-
-A list of currently supported external commands can be found [here](24-appendix.md#external-commands-list-detail).
-
-Detailed information on the commands and their required parameters can be found
-on the [Icinga 1.x documentation](https://docs.icinga.com/latest/en/extcommands2.html).
+### Graphite Writer <a id="graphite-carbon-cache-writer"></a>
-## Performance Data <a id="performance-data"></a>
-
-When a host or service check is executed plugins should provide so-called
-`performance data`. Next to that additional check performance data
-can be fetched using Icinga 2 runtime macros such as the check latency
-or the current service state (or additional custom attributes).
-
-The performance data can be passed to external applications which aggregate and
-store them in their backends. These tools usually generate graphs for historical
-reporting and trending.
-
-Well-known addons processing Icinga performance data are [PNP4Nagios](13-addons.md#addons-graphing-pnp),
-[Graphite](13-addons.md#addons-graphing-graphite) or [OpenTSDB](14-features.md#opentsdb-writer).
-
-### Writing Performance Data Files <a id="writing-performance-data-files"></a>
-
-PNP4Nagios and Graphios use performance data collector daemons to fetch
-the current performance files for their backend updates.
-
-Therefore the Icinga 2 [PerfdataWriter](09-object-types.md#objecttype-perfdatawriter)
-feature allows you to define the output template format for host and services helped
-with Icinga 2 runtime vars.
+[Graphite](13-addons.md#addons-graphing-graphite) is a tool stack for storing
+metrics and needs to be running prior to enabling the `graphite` feature.
- 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
-
-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
-`service-perfdata.<timestamp>`.
-External collectors need to parse the rotated performance data files and then
-remove the processed files.
-
-### Graphite Carbon Cache Writer <a id="graphite-carbon-cache-writer"></a>
-
-While there are some [Graphite](13-addons.md#addons-graphing-graphite)
-collector scripts and daemons like Graphios available for Icinga 1.x it's more
-reasonable to directly process the check and plugin performance
-in memory in Icinga 2. Once there are new metrics available, Icinga 2 will directly
-write them to the defined Graphite Carbon daemon tcp socket.
+Icinga 2 writes parsed metrics directly to Graphite's Carbon Cache
+TCP port, defaulting to `2003`.
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`.
-#### Current Graphite Schema <a id="graphite-carbon-cache-writer-schema"></a>
+#### Graphite Schema <a id="graphite-carbon-cache-writer-schema"></a>
The current naming schema is defined as follows. The [Icinga Web 2 Graphite module](https://github.com/icinga/icingaweb2-module-graphite)
depends on this schema.
@@ -253,8 +231,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,9 +254,12 @@ 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:
+The following characters are escaped in performance labels
+parsed from plugin output:
Character | Escaped character
--------------|--------------------------
@@ -285,29 +268,33 @@ The following characters are escaped in perfdata labels:
/ | _
:: | .
-Note that perfdata labels may contain dots (`.`) allowing to
+Note that labels may contain dots (`.`) allowing to
add more subsequent levels inside the Graphite tree.
`::` adds support for [multi performance labels](http://my-plugin.de/wiki/projects/check_multi/configuration/performance)
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,11 +313,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 +327,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 +446,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 +467,13 @@ 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 +489,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 +511,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 +559,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
@@ -570,6 +577,35 @@ with the following tags
> in your opentsdb.conf configuration file.
+### Writing Performance Data Files <a id="writing-performance-data-files"></a>
+
+PNP and Graphios use performance data collector daemons to fetch
+the current performance files for their backend updates.
+
+Therefore the Icinga 2 [PerfdataWriter](09-object-types.md#objecttype-perfdatawriter)
+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$"
+```
+
+The default templates are already provided with the Icinga 2 feature configuration
+which can be enabled using
+
+```
+# 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
+`service-perfdata.<timestamp>`.
+External collectors need to parse the rotated performance data files and then
+remove the processed files.
+
+
+
## Livestatus <a id="setting-up-livestatus"></a>
The [MK Livestatus](https://mathias-kettner.de/checkmk_livestatus.html) project
@@ -592,18 +628,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 +657,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 +685,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
-
- # cat servicegroups <<EOF
- GET servicegroups
+# echo -e 'GET services\n' | netcat 127.0.0.1 6558
- EOF
+# cat servicegroups <<EOF
+GET servicegroups
- (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 +741,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 +768,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
@@ -762,7 +811,9 @@ The `commands` table is populated with `CheckCommand`, `EventCommand` and `Notif
A detailed list on the available table attributes can be found in the [Livestatus Schema documentation](24-appendix.md#schema-livestatus).
-## Status Data Files <a id="status-data"></a>
+## Deprecated Features <a id="deprecated-features"></a>
+
+### Status Data Files <a id="status-data"></a>
> **Note**
>
@@ -773,12 +824,14 @@ 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.
-## Compat Log Files <a id="compat-logging"></a>
+### Compat Log Files <a id="compat-logging"></a>
> **Note**
>
@@ -795,13 +848,60 @@ 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
`var/log/icinga2/compat/archives`.
-## Check Result Files <a id="check-result-files"></a>
+### External Command Pipe <a id="external-commands"></a>
+
+> **Note**
+>
+> Please use the [REST API](12-icinga2-api.md#icinga2-api) as modern and secure alternative
+> for external actions.
+
+> **Note**
+>
+> This feature is DEPRECATED with 2.11 and will be removed in future releases.
+> Check the [roadmap](https://github.com/Icinga/icinga2/milestones).
+
+Icinga 2 provides an external command pipe for processing commands
+triggering specific actions (for example rescheduling a service check
+through the web interface).
+
+In order to enable the `ExternalCommandListener` configuration use the
+following command and restart Icinga 2 afterwards:
+
+```
+# icinga2 feature enable command
+```
+
+Icinga 2 creates the command pipe file as `/var/run/icinga2/cmd/icinga2.cmd`
+using the default configuration.
+
+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
+
+# 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'
+```
+
+A list of currently supported external commands can be found [here](24-appendix.md#external-commands-list-detail).
+
+Detailed information on the commands and their required parameters can be found
+on the [Icinga 1.x documentation](https://docs.icinga.com/latest/en/extcommands2.html).
+
+
+### Check Result Files <a id="check-result-files"></a>
> **Note**
>
@@ -820,7 +920,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" {
- spool_dir = "/data/check-results"
- }
-
+```
+object CheckResultReader "reader" {
+ spool_dir = "/data/check-results"
+}
+```
diff --git a/doc/15-troubleshooting.md b/doc/15-troubleshooting.md
index 42afa28..a11a5c5 100644
--- a/doc/15-troubleshooting.md
+++ b/doc/15-troubleshooting.md
@@ -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>
-->
diff --git a/doc/16-upgrading-icinga-2.md b/doc/16-upgrading-icinga-2.md
index bede671..5323d05 100644
--- a/doc/16-upgrading-icinga-2.md
+++ b/doc/16-upgrading-icinga-2.md
@@ -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
diff --git a/doc/17-language-reference.md b/doc/17-language-reference.md
index eff67a0..2782ef7 100644
--- a/doc/17-language-reference.md
+++ b/doc/17-language-reference.md
@@ -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" {
- display_name = "host1"
+```
+object Host "host1.example.org" {
+ display_name = "host1"
- address = "192.168.0.1"
- address6 = "2001:db8:1234::42"
- }
+ 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" {
- display_name = "host1"
+```
+object Host "host1.example.org" {
+ display_name = "host1"
- address = "192.168.0.1"; address6 = "2001:db8:1234::42"
- }
+ 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
- }
+```
+{
+ 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 {
- function calculate() {
- return 2 + 2
- }
+```
+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
- }
+{
+ 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
- }
+```
+{
+ 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" ]
- }
+```
+{
+ a = [ "hello" ]
+ a += [ "world" ]
+}
+```
is equivalent to:
- {
- a = [ "hello" ]
- a = a + [ "world" ]
- }
+```
+{
+ a = [ "hello" ]
+ a = a + [ "world" ]
+}
+```
### Operator -= <a id="operator-substractive-assignment"></a>
The -= operator is a shortcut. The following expression:
- {
- a = 10
- a -= 5
- }
+```
+{
+ a = 10
+ a -= 5
+}
+```
is equivalent to:
- {
- a = 10
- a = a - 5
- }
+```
+{
+ a = 10
+ a = a - 5
+}
+```
### Operator \*= <a id="operator-multiply-assignment"></a>
The *= operator is a shortcut. The following expression:
- {
- a = 60
- a *= 5
- }
+```
+{
+ a = 60
+ a *= 5
+}
+```
is equivalent to:
- {
- a = 60
- a = a * 5
- }
+```
+{
+ a = 60
+ a = a * 5
+}
+```
### Operator /= <a id="operator-dividing-assignment"></a>
The /= operator is a shortcut. The following expression:
- {
- a = 300
- a /= 5
- }
+```
+{
+ a = 300
+ a /= 5
+}
+```
is equivalent to:
- {
- a = 300
- a = a / 5
- }
+```
+{
+ 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"
- }
+```
+{
+ hello.key = "world"
+}
+```
Example (alternative syntax):
- {
- hello["key"] = "world"
- }
+```
+{
+ hello["key"] = "world"
+}
+```
This is equivalent to writing:
- {
- hello += {
- key = "world"
- }
- }
+```
+{
+ 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" {
- vars.colour = "red"
- }
+```
+template Host "default-host" {
+ vars.colour = "red"
+}
- template Host "test-host" {
- import "default-host"
+template Host "test-host" {
+ import "default-host"
- vars.colour = "blue"
- }
+ vars.colour = "blue"
+}
- object Host "localhost" {
- import "test-host"
+object Host "localhost" {
+ import "test-host"
- address = "127.0.0.1"
- address6 = "::1"
- }
+ 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.
@@ -502,13 +560,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 {
- import "generic-service"
+```
+apply Service "ping" to Host {
+ import "generic-service"
- check_command = "ping4"
+ check_command = "ping4"
- assign where host.name == "localhost"
- }
+ 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"
@@ -543,13 +603,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 {
- import "generic-service"
-
- check_command = "ping4"
- vars.host_value = value
- }
+```
+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
@@ -576,11 +637,13 @@ chapter.
Group objects can be assigned to specific member objects using the `assign where`
and `ignore where` conditions.
- object HostGroup "linux-servers" {
- display_name = "Linux Servers"
+```
+object HostGroup "linux-servers" {
+ display_name = "Linux Servers"
- assign where host.vars.os == "Linux"
- }
+ 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
@@ -622,13 +685,15 @@ The Icinga 2 configuration format supports C/C++-style and shell-style comments.
Example:
- /*
- This is a comment.
- */
- object Host "localhost" {
- check_interval = 30 // this is also a comment.
- retry_interval = 15 # yet another comment
- }
+```
+/*
+ This is a comment.
+ */
+object Host "localhost" {
+ check_interval = 30 // this is also a comment.
+ retry_interval = 15 # yet another comment
+}
+```
## Includes <a id="includes"></a>
@@ -638,15 +703,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
@@ -663,8 +732,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.
@@ -682,8 +753,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
@@ -707,14 +780,18 @@ Functions can be defined using the `function` keyword.
Example:
- function multiply(a, b) {
- return 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
@@ -726,16 +803,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) {
- 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>
@@ -743,20 +824,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) => {
- log("Lambda called")
- x * 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>
@@ -764,7 +851,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.
@@ -780,10 +869,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) {
- var temp = a * b
- return temp
- }
+```
+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.
@@ -794,40 +885,45 @@ 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" {
- check_interval = 5m
- }
+```
+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" {
- var check_interval = 5m
-
- /* This explicitly specifies that the attribute should be set
- * for the host, if we had omitted `this.` the (poorly named)
- * local variable `check_interval` would have been modified instead.
- */
- this.check_interval = 1m
- }
-
+```
+object Host "localhost" {
+ var check_interval = 5m
+
+ /* This explicitly specifies that the attribute should be set
+ * for the host, if we had omitted `this.` the (poorly named)
+ * 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
+```
+ hm = {
+ h_word = null
- function init(word) {
- h_word = word
- }
- }
+ function init(word) {
+ h_word = word
+ }
+ }
- /* Let's invoke the init() function */
- hm.init("hello")
+ /* 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.
@@ -839,22 +935,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) {
- return function() use(name) {
- log("Hello, " + 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) {
- return function() use (greeting = "Hello, " + name) {
- log(greeting)
- }
- }
+```
+function MakeHelloFunction(name) {
+ return function() use (greeting = "Hello, " + name) {
+ log(greeting)
+ }
+}
+```
## Conditional Statements <a id="conditional-statements"></a>
@@ -863,26 +963,30 @@ construct can be used to accomplish this.
Example:
- a = 3
+```
+a = 3
- if (a < 5) {
- a *= 7
- } else if (a > 10) {
- a *= 5
- } else {
- a *= 2
- }
+if (a < 5) {
+ a *= 7
+} else if (a > 10) {
+ a *= 5
+} 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) {
- log("Taking the 'true' branch")
- 7 * 3
- } else {
- log("Taking the 'false' branch")
- 9
- }
+```
+a = if (true) {
+ log("Taking the 'true' branch")
+ 7 * 3
+} 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).
@@ -895,12 +999,14 @@ This is repeated until the condition is no longer true.
Example:
- var num = 5
+```
+var num = 5
- while (num > 5) {
- log("Test")
- num -= 1
- }
+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
@@ -912,22 +1018,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) {
- log("Item: " + item)
- }
+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) {
- log("Key: " + key + ", Value: " + value)
- }
+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
@@ -942,15 +1052,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>
@@ -959,7 +1073,9 @@ using the `throw` keyword.
Example:
- throw "An error occurred."
+```
+throw "An error occurred."
+```
## Handling Exceptions <a id="try-except"></a>
@@ -968,13 +1084,15 @@ Exceptions can be handled using the `try` and `except` keywords. When an excepti
Example:
- try {
- throw "Test"
+```
+try {
+ throw "Test"
- log("This statement won't get executed.")
- } except {
- log("An error occurred in the try clause.")
- }
+ log("This statement won't get executed.")
+} except {
+ log("An error occurred in the try clause.")
+}
+```
## Breakpoints <a id="breakpoints"></a>
@@ -986,7 +1104,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:
@@ -1005,14 +1125,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).
@@ -1024,77 +1148,84 @@ 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"
- ^^^^^^^
- /etc/icinga2/conf.d/hosts/localhost.conf(16): }
- /etc/icinga2/conf.d/hosts/localhost.conf(17):
+```
+[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):
- 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" {
- import "generic-host"
+```
+object Host "localhost" {
+ import "generic-host"
- address = "127.0.0.1"
- address6 = "::1"
+ address = "127.0.0.1"
+ address6 = "::1"
- vars.os = "Linux"
- vars.sla = "24x7"
+ vars.os = "Linux"
+ vars.sla = "24x7"
- vars.@include = "some cmdb export field"
- }
+ vars.@include = "some cmdb export field"
+}
+``` \ No newline at end of file
diff --git a/doc/18-library-reference.md b/doc/18-library-reference.md
index 30277bf..897400c 100644
--- a/doc/18-library-reference.md
+++ b/doc/18-library-reference.md
@@ -14,7 +14,9 @@ them in your scenarios.
Signature:
- function regex(pattern, value, mode)
+```
+function regex(pattern, value, mode)
+```
Returns true if the regular expression `pattern` matches the `value`, false otherwise.
The `value` can be of the type [String](18-library-reference.md#string-type) or [Array](18-library-reference.md#array-type) (which
@@ -28,32 +30,37 @@ The default mode is `MatchAll`.
Example for string values:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => host.vars.os_type = "Linux/Unix"
- null
- <2> => regex("^Linux", host.vars.os_type)
- true
- <3> => regex("^Linux$", host.vars.os_type)
- false
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => host.vars.os_type = "Linux/Unix"
+null
+<2> => regex("^Linux", host.vars.os_type)
+true
+<3> => regex("^Linux$", host.vars.os_type)
+false
+```
Example for an array of string values:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => host.vars.databases = [ "db-prod1", "db-prod2", "db-dev" ]
- null
- <2> => regex("^db-prod\\d+", host.vars.databases, MatchAny)
- true
- <3> => regex("^db-prod\\d+", host.vars.databases, MatchAll)
- false
-
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => host.vars.databases = [ "db-prod1", "db-prod2", "db-dev" ]
+null
+<2> => regex("^db-prod\\d+", host.vars.databases, MatchAny)
+true
+<3> => regex("^db-prod\\d+", host.vars.databases, MatchAll)
+false
+```
### match <a id="global-functions-match"></a>
Signature:
- function match(pattern, text, mode)
+```
+function match(pattern, text, mode)
+```
Returns true if the wildcard (`?*`) `pattern` matches the `value`, false otherwise.
The `value` can be of the type [String](18-library-reference.md#string-type) or [Array](18-library-reference.md#array-type) (which
@@ -65,32 +72,37 @@ The default mode is `MatchAll`.
Example for string values:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => var name = "db-prod-sfo-657"
- null
- <2> => match("*prod-sfo*", name)
- true
- <3> => match("*-dev-*", name)
- false
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => var name = "db-prod-sfo-657"
+null
+<2> => match("*prod-sfo*", name)
+true
+<3> => match("*-dev-*", name)
+false
+```
Example for an array of string values:
- $ icinga2 console
- Icinga 2 (version: v2.7.0-28)
- <1> => host.vars.application_types = [ "web-wp", "web-rt", "db-local" ]
- null
- <2> => match("web-*", host.vars.application_types, MatchAll)
- false
- <3> => match("web-*", host.vars.application_types, MatchAny)
- true
-
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0-28)
+<1> => host.vars.application_types = [ "web-wp", "web-rt", "db-local" ]
+null
+<2> => match("web-*", host.vars.application_types, MatchAll)
+false
+<3> => match("web-*", host.vars.application_types, MatchAny)
+true
+```
### cidr_match <a id="global-functions-cidr_match"></a>
Signature:
- function cidr_match(pattern, ip, mode)
+```
+function cidr_match(pattern, ip, mode)
+```
Returns true if the CIDR pattern matches the IP address, false otherwise.
@@ -102,33 +114,39 @@ either `MatchAll` (in which case all elements for an array have to match) or `Ma
Example for a single IP address:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => host.address = "192.168.56.101"
- null
- <2> => cidr_match("192.168.56.0/24", host.address)
- true
- <3> => cidr_match("192.168.56.0/26", host.address)
- false
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => host.address = "192.168.56.101"
+null
+<2> => cidr_match("192.168.56.0/24", host.address)
+true
+<3> => cidr_match("192.168.56.0/26", host.address)
+false
+```
Example for an array of IP addresses:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => host.vars.vhost_ips = [ "192.168.56.101", "192.168.56.102", "10.0.10.99" ]
- null
- <2> => cidr_match("192.168.56.0/24", host.vars.vhost_ips, MatchAll)
- false
- <3> => cidr_match("192.168.56.0/24", host.vars.vhost_ips, MatchAny)
- true
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => host.vars.vhost_ips = [ "192.168.56.101", "192.168.56.102", "10.0.10.99" ]
+null
+<2> => cidr_match("192.168.56.0/24", host.vars.vhost_ips, MatchAll)
+false
+<3> => cidr_match("192.168.56.0/24", host.vars.vhost_ips, MatchAny)
+true
+```
### range <a id="global-functions-range"></a>
Signature:
- function range(end)
- function range(start, end)
- function range(start, end, increment)
+```
+function range(end)
+function range(start, end)
+function range(start, end, increment)
+```
Returns an array of numbers in the specified range.
If you specify one parameter, the first element starts at `0`.
@@ -142,20 +160,24 @@ as third parameter.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => range(5)
- [ 0.000000, 1.000000, 2.000000, 3.000000, 4.000000 ]
- <2> => range(2,4)
- [ 2.000000, 3.000000 ]
- <3> => range(2,10,2)
- [ 2.000000, 4.000000, 6.000000, 8.000000 ]
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => range(5)
+[ 0.000000, 1.000000, 2.000000, 3.000000, 4.000000 ]
+<2> => range(2,4)
+[ 2.000000, 3.000000 ]
+<3> => range(2,10,2)
+[ 2.000000, 4.000000, 6.000000, 8.000000 ]
+```
### len <a id="global-functions-len"></a>
Signature:
- function len(value)
+```
+function len(value)
+```
Returns the length of the value, i.e. the number of elements for an array
or dictionary, or the length of the string in bytes.
@@ -166,68 +188,78 @@ prototype method: [Array#len](18-library-reference.md#array-len), [Dictionary#le
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => host.groups = [ "linux-servers", "db-servers" ]
- null
- <2> => host.groups.len()
- 2.000000
- <3> => host.vars.disks["/"] = {}
- null
- <4> => host.vars.disks["/var"] = {}
- null
- <5> => host.vars.disks.len()
- 2.000000
- <6> => host.vars.os_type = "Linux/Unix"
- null
- <7> => host.vars.os_type.len()
- 10.000000
-
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => host.groups = [ "linux-servers", "db-servers" ]
+null
+<2> => host.groups.len()
+2.000000
+<3> => host.vars.disks["/"] = {}
+null
+<4> => host.vars.disks["/var"] = {}
+null
+<5> => host.vars.disks.len()
+2.000000
+<6> => host.vars.os_type = "Linux/Unix"
+null
+<7> => host.vars.os_type.len()
+10.000000
+```
### union <a id="global-functions-union"></a>
Signature:
- function union(array, array, ...)
+```
+function union(array, array, ...)
+```
Returns an array containing all unique elements from the specified arrays.
Example:
-
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => var dev_notification_groups = [ "devs", "slack" ]
- null
- <2> => var host_notification_groups = [ "slack", "noc" ]
- null
- <3> => union(dev_notification_groups, host_notification_groups)
- [ "devs", "noc", "slack" ]
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => var dev_notification_groups = [ "devs", "slack" ]
+null
+<2> => var host_notification_groups = [ "slack", "noc" ]
+null
+<3> => union(dev_notification_groups, host_notification_groups)
+[ "devs", "noc", "slack" ]
+```
### intersection <a id="global-functions-intersection"></a>
Signature:
- function intersection(array, array, ...)
+```
+function intersection(array, array, ...)
+```
Returns an array containing all unique elements which are common to all
specified arrays.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => var dev_notification_groups = [ "devs", "slack" ]
- null
- <2> => var host_notification_groups = [ "slack", "noc" ]
- null
- <3> => intersection(dev_notification_groups, host_notification_groups)
- [ "slack" ]
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => var dev_notification_groups = [ "devs", "slack" ]
+null
+<2> => var host_notification_groups = [ "slack", "noc" ]
+null
+<3> => intersection(dev_notification_groups, host_notification_groups)
+[ "slack" ]
+```
### keys <a id="global-functions-keys"></a>
Signature:
- function keys(dict)
+```
+function keys(dict)
+```
Returns an array containing the dictionary's keys.
@@ -236,20 +268,24 @@ prototype method: [Dictionary#keys](18-library-reference.md#dictionary-keys).
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => host.vars.disks["/"] = {}
- null
- <2> => host.vars.disks["/var"] = {}
- null
- <3> => host.vars.disks.keys()
- [ "/", "/var" ]
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => host.vars.disks["/"] = {}
+null
+<2> => host.vars.disks["/var"] = {}
+null
+<3> => host.vars.disks.keys()
+[ "/", "/var" ]
+```
### string <a id="global-functions-string"></a>
Signature:
- function string(value)
+```
+function string(value)
+```
Converts the value to a string.
@@ -264,81 +300,99 @@ prototype method:
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => 5.to_string()
- "5"
- <2> => false.to_string()
- "false"
- <3> => "abc".to_string()
- "abc"
- <4> => [ "dev", "slack" ].to_string()
- "[ \"dev\", \"slack\" ]"
- <5> => { "/" = {}, "/var" = {} }.to_string()
- "{\n\t\"/\" = {\n\t}\n\t\"/var\" = {\n\t}\n}"
- <6> => DateTime(2016, 11, 25).to_string()
- "2016-11-25 00:00:00 +0100"
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => 5.to_string()
+"5"
+<2> => false.to_string()
+"false"
+<3> => "abc".to_string()
+"abc"
+<4> => [ "dev", "slack" ].to_string()
+"[ \"dev\", \"slack\" ]"
+<5> => { "/" = {}, "/var" = {} }.to_string()
+"{\n\t\"/\" = {\n\t}\n\t\"/var\" = {\n\t}\n}"
+<6> => DateTime(2016, 11, 25).to_string()
+"2016-11-25 00:00:00 +0100"
+```
### number <a id="global-functions-number"></a>
Signature:
- function number(value)
+```
+function number(value)
+```
Converts the value to a number.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => number(false)
- 0.000000
- <2> => number("78")
- 78.000000
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => number(false)
+0.000000
+<2> => number("78")
+78.000000
+```
### bool <a id="global-functions-bool"></a>
Signature:
- function bool(value)
+```
+function bool(value)
+```
Converts the value to a bool.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => bool(1)
- true
- <2> => bool(0)
- false
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => bool(1)
+true
+<2> => bool(0)
+false
+```
### random <a id="global-functions-random"></a>
Signature:
- function random()
+```
+function random()
+```
Returns a random value between 0 and RAND\_MAX (as defined in stdlib.h).
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => random()
- 1263171996.000000
- <2> => random()
- 108402530.000000
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => random()
+1263171996.000000
+<2> => random()
+108402530.000000
+```
### log <a id="global-functions-log"></a>
Signature:
- function log(value)
+```
+function log(value)
+```
Writes a message to the log. Non-string values are converted to a JSON string.
Signature:
- function log(severity, facility, value)
+```
+function log(severity, facility, value)
+```
Writes a message to the log. `severity` can be one of `LogDebug`, `LogNotice`,
`LogInformation`, `LogWarning`, and `LogCritical`.
@@ -347,140 +401,168 @@ Non-string values are converted to a JSON string.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => log(LogCritical, "Console", "First line")
- critical/Console: First line
- null
- <2> => var groups = [ "devs", "slack" ]
- null
- <3> => log(LogCritical, "Console", groups)
- critical/Console: ["devs","slack"]
- null
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => log(LogCritical, "Console", "First line")
+critical/Console: First line
+null
+<2> => var groups = [ "devs", "slack" ]
+null
+<3> => log(LogCritical, "Console", groups)
+critical/Console: ["devs","slack"]
+null
+```
### typeof <a id="global-functions-typeof"></a>
Signature:
- function typeof(value)
+```
+function typeof(value)
+```
Returns the [Type](18-library-reference.md#type-type) object for a value.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => typeof(3) == Number
- true
- <2> => typeof("str") == String
- true
- <3> => typeof(true) == Boolean
- true
- <4> => typeof([ 1, 2, 3]) == Array
- true
- <5> => typeof({ a = 2, b = 3 }) == Dictionary
- true
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => typeof(3) == Number
+true
+<2> => typeof("str") == String
+true
+<3> => typeof(true) == Boolean
+true
+<4> => typeof([ 1, 2, 3]) == Array
+true
+<5> => typeof({ a = 2, b = 3 }) == Dictionary
+true
+```
### get_time <a id="global-functions-get_time"></a>
Signature:
- function get_time()
+```
+function get_time()
+```
Returns the current UNIX timestamp as floating point number.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => get_time()
- 1480072135.633008
- <2> => get_time()
- 1480072140.401207
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => get_time()
+1480072135.633008
+<2> => get_time()
+1480072140.401207
+```
### parse_performance_data <a id="global-functions-parse_performance_data"></a>
Signature:
- function parse_performance_data(pd)
+```
+function parse_performance_data(pd)
+```
Parses a performance data string and returns an array describing the values.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => var pd = "'time'=1480074205.197363;;;"
- null
- <2> => parse_performance_data(pd)
- {
- counter = false
- crit = null
- label = "time"
- max = null
- min = null
- type = "PerfdataValue"
- unit = ""
- value = 1480074205.197363
- warn = null
- }
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => var pd = "'time'=1480074205.197363;;;"
+null
+<2> => parse_performance_data(pd)
+{
+ counter = false
+ crit = null
+ label = "time"
+ max = null
+ min = null
+ type = "PerfdataValue"
+ unit = ""
+ value = 1480074205.197363
+ warn = null
+}
+```
### dirname <a id="global-functions-dirname"></a>
Signature:
- function dirname(path)
+```
+function dirname(path)
+```
Returns the directory portion of the specified path.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => var path = "/etc/icinga2/scripts/xmpp-notification.pl"
- null
- <2> => dirname(path)
- "/etc/icinga2/scripts"
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => var path = "/etc/icinga2/scripts/xmpp-notification.pl"
+null
+<2> => dirname(path)
+"/etc/icinga2/scripts"
+```
### basename <a id="global-functions-basename"></a>
Signature:
- function basename(path)
+```
+function basename(path)
+```
Returns the filename portion of the specified path.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => var path = "/etc/icinga2/scripts/xmpp-notification.pl"
- null
- <2> => basename(path)
- "xmpp-notification.pl"
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => var path = "/etc/icinga2/scripts/xmpp-notification.pl"
+null
+<2> => basename(path)
+"xmpp-notification.pl"
+```
### path\_exists <a id="global-functions-path-exists"></a>
Signature:
- function path_exists(path)
+```
+function path_exists(path)
+```
Returns true if the specified path exists, false otherwise.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => var path = "/etc/icinga2/scripts/xmpp-notification.pl"
- null
- <2> => path_exists(path)
- true
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => var path = "/etc/icinga2/scripts/xmpp-notification.pl"
+null
+<2> => path_exists(path)
+true
+```
### glob <a id="global-functions-glob"></a>
Signature:
- function glob(pathSpec, type)
+```
+function glob(pathSpec, type)
+```
Returns an array containing all paths which match the
`pathSpec` argument.
@@ -489,18 +571,22 @@ The `type` argument is optional and specifies which types
of paths are matched. This can be a combination of the `GlobFile`
and `GlobDirectory` constants. The default value is `GlobFile | GlobDirectory`.
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => var pathSpec = "/etc/icinga2/conf.d/*.conf"
- null
- <2> => glob(pathSpec)
- [ "/etc/icinga2/conf.d/app.conf", "/etc/icinga2/conf.d/commands.conf", ... ]
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => var pathSpec = "/etc/icinga2/conf.d/*.conf"
+null
+<2> => glob(pathSpec)
+[ "/etc/icinga2/conf.d/app.conf", "/etc/icinga2/conf.d/commands.conf", ... ]
+```
### glob\_recursive <a id="global-functions-glob-recursive"></a>
Signature:
- function glob_recursive(path, pattern, type)
+```
+function glob_recursive(path, pattern, type)
+```
Recursively descends into the specified directory and returns an array containing
all paths which match the `pattern` argument.
@@ -509,50 +595,62 @@ The `type` argument is optional and specifies which types
of paths are matched. This can be a combination of the `GlobFile`
and `GlobDirectory` constants. The default value is `GlobFile | GlobDirectory`.
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => var path = "/etc/icinga2/zones.d/"
- null
- <2> => var pattern = "*.conf"
- null
- <3> => glob_recursive(path, pattern)
- [ "/etc/icinga2/zones.d/global-templates/templates.conf", "/etc/icinga2/zones.d/master/hosts.conf", ... ]
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => var path = "/etc/icinga2/zones.d/"
+null
+<2> => var pattern = "*.conf"
+null
+<3> => glob_recursive(path, pattern)
+[ "/etc/icinga2/zones.d/global-templates/templates.conf", "/etc/icinga2/zones.d/master/hosts.conf", ... ]
+```
### escape_shell_arg <a id="global-functions-escape_shell_arg"></a>
Signature:
- function escape_shell_arg(text)
+```
+function escape_shell_arg(text)
+```
Escapes a string for use as a single shell argument.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => escape_shell_arg("'$host.name$' '$service.name$'")
- "''\\''$host.name$'\\'' '\\''$service.name$'\\'''"
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => escape_shell_arg("'$host.name$' '$service.name$'")
+"''\\''$host.name$'\\'' '\\''$service.name$'\\'''"
+```
### escape_shell_cmd <a id="global-functions-escape_shell_cmd"></a>
Signature:
- function escape_shell_cmd(text)
+```
+function escape_shell_cmd(text)
+```
Escapes shell meta characters in a string.
Example:
- $ icinga2 console
- Icinga 2 (version: v2.7.0)
- <1> => escape_shell_cmd("/bin/echo 'shell test' $ENV")
- "/bin/echo 'shell test' \\$ENV"
+```
+$ icinga2 console
+Icinga 2 (version: v2.7.0)
+<1> => escape_shell_cmd("/bin/echo 'shell test' $ENV")
+"/bin/echo 'shell test' \\$ENV"
+```
### escape_create_process_arg <a id="global-functions-escape_create_process_arg"></a>
Signature:
- function escape_create_process_arg(text)
+```
+function escape_create_process_arg(text)
+```
Escapes a string for use as an argument for CreateProcess(). Windows only.
@@ -560,7 +658,9 @@ Escapes a string for use as an argument for CreateProcess(). Windows only.
Signature:
- function sleep(interval)
+```
+function sleep(interval)
+```
Sleeps for the specified amount of time (in seconds).
@@ -614,7 +714,9 @@ These functions can be used to retrieve a reference to another object by name.
Signature:
- function get_check_command(name);
+```
+function get_check_command(name);
+```
Returns the CheckCommand object with the specified name, or `null` if no such CheckCommand object exists.
@@ -622,7 +724,9 @@ Returns the CheckCommand object with the specified name, or `null` if no such Ch
Signature:
- function get_event_command(name);
+```
+function get_event_command(name);
+```
Returns the EventCommand object with the specified name, or `null` if no such EventCommand object exists.
@@ -630,7 +734,9 @@ Returns the EventCommand object with the specified name, or `null` if no such Ev
Signature:
- function get_notification_command(name);
+```
+function get_notification_command(name);
+```
Returns the NotificationCommand object with the specified name, or `null` if no such NotificationCommand object exists.
@@ -638,7 +744,9 @@ Returns the NotificationCommand object with the specified name, or `null` if no
Signature:
- function get_host(host_name);
+```
+function get_host(host_name);
+```
Returns the Host object with the specified name, or `null` if no such Host object exists.
@@ -647,8 +755,10 @@ Returns the Host object with the specified name, or `null` if no such Host objec
Signature:
- function get_service(host_name, service_name);
- function get_service(host, service_name);
+```
+function get_service(host_name, service_name);
+function get_service(host, service_name);
+```
Returns the Service object with the specified host name or object and service name pair,
or `null` if no such Service object exists.
@@ -672,8 +782,10 @@ Icinga 2 (version: v2.7.0)
Signature:
- function get_services(host_name);
- function get_services(host);
+```
+function get_services(host_name);
+function get_services(host);
+```
Returns an [array](17-language-reference.md#array) of service objects for the specified host name or object,
or `null` if no such host object exists.
@@ -704,7 +816,9 @@ in using the [map](18-library-reference.md#array-map) functionality:
Signature:
- function get_user(name);
+```
+function get_user(name);
+```
Returns the User object with the specified name, or `null` if no such User object exists.
@@ -712,7 +826,9 @@ Returns the User object with the specified name, or `null` if no such User objec
Signature:
- function get_host_group(name);
+```
+function get_host_group(name);
+```
Returns the HostGroup object with the specified name, or `null` if no such HostGroup object exists.
@@ -721,7 +837,9 @@ Returns the HostGroup object with the specified name, or `null` if no such HostG
Signature:
- function get_service_group(name);
+```
+function get_service_group(name);
+```
Returns the ServiceGroup object with the specified name, or `null` if no such ServiceGroup object exists.
@@ -729,7 +847,9 @@ Returns the ServiceGroup object with the specified name, or `null` if no such Se
Signature:
- function get_user_group(name);
+```
+function get_user_group(name);
+```
Returns the UserGroup object with the specified name, or `null` if no such UserGroup object exists.
@@ -738,7 +858,9 @@ Returns the UserGroup object with the specified name, or `null` if no such UserG
Signature:
- function get_time_period(name);
+```
+function get_time_period(name);
+```
Returns the TimePeriod object with the specified name, or `null` if no such TimePeriod object exists.
@@ -747,7 +869,9 @@ Returns the TimePeriod object with the specified name, or `null` if no such Time
Signature:
- function get_object(type, name);
+```
+function get_object(type, name);
+```
Returns the object with the specified type and name, or `null` if no such object exists. `type` must refer
to a type object.
@@ -757,7 +881,9 @@ to a type object.
Signature:
- function get_objects(type);
+```
+function get_objects(type);
+```
Returns an array of objects whose type matches the specified type. `type` must refer
to a type object.
@@ -800,7 +926,9 @@ Square root of 2.
Signature:
- function abs(x);
+```
+function abs(x);
+```
Returns the absolute value of `x`.
@@ -808,7 +936,9 @@ Returns the absolute value of `x`.
Signature:
- function acos(x);
+```
+function acos(x);
+```
Returns the arccosine of `x`.
@@ -816,7 +946,9 @@ Returns the arccosine of `x`.
Signature:
- function asin(x);
+```
+function asin(x);
+```
Returns the arcsine of `x`.
@@ -824,7 +956,9 @@ Returns the arcsine of `x`.
Signature:
- function atan(x);
+```
+function atan(x);
+```
Returns the arctangent of `x`.
@@ -832,15 +966,18 @@ Returns the arctangent of `x`.
Signature:
- function atan2(y, x);
-
+```
+function atan2(y, x);
+```
Returns the arctangent of the quotient of `y` and `x`.
### Math.ceil <a id="math-ceil"></a>
Signature:
- function ceil(x);
+```
+function ceil(x);
+```
Returns the smallest integer value not less than `x`.
@@ -848,7 +985,9 @@ Returns the smallest integer value not less than `x`.
Signature:
- function cos(x);
+```
+function cos(x);
+```
Returns the cosine of `x`.
@@ -856,7 +995,9 @@ Returns the cosine of `x`.
Signature:
- function exp(x);
+```
+function exp(x);
+```
Returns E raised to the `x`th power.
@@ -864,7 +1005,9 @@ Returns E raised to the `x`th power.
Signature:
- function floor(x);
+```
+function floor(x);
+```
Returns the largest integer value not greater than `x`.
@@ -872,7 +1015,9 @@ Returns the largest integer value not greater than `x`.
Signature:
- function isinf(x);
+```
+function isinf(x);
+```
Returns whether `x` is infinite.
@@ -880,7 +1025,9 @@ Returns whether `x` is infinite.
Signature:
- function isnan(x);
+```
+function isnan(x);
+```
Returns whether `x` is NaN (not-a-number).
@@ -888,7 +1035,9 @@ Returns whether `x` is NaN (not-a-number).
Signature:
- function log(x);
+```
+function log(x);
+```
Returns the natural logarithm of `x`.
@@ -896,7 +1045,9 @@ Returns the natural logarithm of `x`.
Signature:
- function max(...);
+```
+function max(...);
+```
Returns the largest argument. A variable number of arguments can be specified.
If no arguments are given, -Infinity is returned.
@@ -905,7 +1056,9 @@ If no arguments are given, -Infinity is returned.
Signature:
- function min(...);
+```
+function min(...);
+```
Returns the smallest argument. A variable number of arguments can be specified.
If no arguments are given, +Infinity is returned.
@@ -914,7 +1067,9 @@ If no arguments are given, +Infinity is returned.
Signature:
- function pow(x, y);
+```
+function pow(x, y);
+```
Returns `x` raised to the `y`th power.
@@ -922,7 +1077,9 @@ Returns `x` raised to the `y`th power.
Signature:
- function random();
+```
+function random();
+```
Returns a pseudo-random number between 0 and 1.
@@ -930,7 +1087,9 @@ Returns a pseudo-random number between 0 and 1.
Signature:
- function round(x);
+```
+function round(x);
+```
Returns `x` rounded to the nearest integer value.
@@ -938,7 +1097,9 @@ Returns `x` rounded to the nearest integer value.
Signature:
- function sign(x);
+```
+function sign(x);
+```
Returns -1 if `x` is negative, 1 if `x` is positive
and 0 if `x` is 0.
@@ -947,7 +1108,9 @@ and 0 if `x` is 0.
Signature:
- function sin(x);
+```
+function sin(x);
+```
Returns the sine of `x`.
@@ -955,7 +1118,9 @@ Returns the sine of `x`.
Signature:
- function sqrt(x);
+```
+function sqrt(x);
+```
Returns the square root of `x`.
@@ -963,7 +1128,9 @@ Returns the square root of `x`.
Signature:
- function tan(x);
+```
+function tan(x);
+```
Returns the tangent of `x`.
@@ -975,7 +1142,9 @@ The global `Json` object can be used to encode and decode JSON.
Signature:
- function encode(x);
+```
+function encode(x);
+```
Encodes an arbitrary value into JSON.
@@ -983,7 +1152,9 @@ Encodes an arbitrary value into JSON.
Signature:
- function decode(x);
+```
+function decode(x);
+```
Decodes a JSON string.
@@ -993,14 +1164,18 @@ Decodes a JSON string.
Signature:
- function to_string();
+```
+function to_string();
+```
The `to_string` method returns a string representation of the number.
Example:
- var example = 7
+```
+var example = 7
example.to_string() /* Returns "7" */
+```
## Boolean type <a id="boolean-type"></a>
@@ -1008,14 +1183,18 @@ Example:
Signature:
- function to_string();
+```
+function to_string();
+```
The `to_string` method returns a string representation of the boolean value.
Example:
- var example = true
+```
+var example = true
example.to_string() /* Returns "true" */
+```
## String type <a id="string-type"></a>
@@ -1023,7 +1202,9 @@ Example:
Signature:
- function find(str, start);
+```
+function find(str, start);
+```
Returns the zero-based index at which the string `str` was found in the string. If the string
was not found, -1 is returned. `start` specifies the zero-based index at which `find` should
@@ -1031,13 +1212,17 @@ start looking for the string (defaults to 0 when not specified).
Example:
- "Hello World".find("World") /* Returns 6 */
+```
+"Hello World".find("World") /* Returns 6 */
+```
### String#contains <a id="string-contains"></a>
Signature:
- function contains(str);
+```
+function contains(str);
+```
Returns `true` if the string `str` was found in the string. If the string
was not found, `false` is returned. Use [find](18-library-reference.md#string-find)
@@ -1045,50 +1230,66 @@ for getting the index instead.
Example:
- "Hello World".contains("World") /* Returns true */
+```
+"Hello World".contains("World") /* Returns true */
+```
### String#len <a id="string-len"></a>
Signature
- function len();
+```
+function len();
+```
Returns the length of the string in bytes. Note that depending on the encoding type of the string
this is not necessarily the number of characters.
Example:
- "Hello World".len() /* Returns 11 */
+```
+"Hello World".len() /* Returns 11 */
+```
### String#lower <a id="string-lower"></a>
Signature:
- function lower();
+```
+function lower();
+```
Returns a copy of the string with all of its characters converted to lower-case.
Example:
- "Hello World".lower() /* Returns "hello world" */
+```
+"Hello World".lower() /* Returns "hello world" */
+```
### String#upper <a id="string-upper"></a>
Signature:
- function upper();
+```
+function upper();
+```
Returns a copy of the string with all of its characters converted to upper-case.
Example:
- "Hello World".upper() /* Returns "HELLO WORLD" */
+```
+"Hello World".upper() /* Returns "HELLO WORLD" */
+```
### String#replace <a id="string-replace"></a>
Signature:
- function replace(search, replacement);
+```
+function replace(search, replacement);
+```
Returns a copy of the string with all occurences of the string specified in `search` replaced
with the string specified in `replacement`.
@@ -1097,33 +1298,43 @@ with the string specified in `replacement`.
Signature:
- function split(delimiters);
+```
+function split(delimiters);
+```
Splits a string into individual parts and returns them as an array. The `delimiters` argument
specifies the characters which should be used as delimiters between parts.
Example:
- "x-7,y".split("-,") /* Returns [ "x", "7", "y" ] */
+```
+"x-7,y".split("-,") /* Returns [ "x", "7", "y" ] */
+```
### String#substr <a id="string-substr"></a>
Signature:
- function substr(start, len);
+```
+function substr(start, len);
+```
Returns a part of a string. The `start` argument specifies the zero-based index at which the part begins.
The optional `len` argument specifies the length of the part ("until the end of the string" if omitted).
Example:
- "Hello World".substr(6) /* Returns "World" */
+```
+"Hello World".substr(6) /* Returns "World" */
+```
### String#to_string <a id="string-to_string"></a>
Signature:
- function to_string();
+```
+function to_string();
+```
Returns a copy of the string.
@@ -1131,7 +1342,9 @@ Returns a copy of the string.
Signature:
- function reverse();
+```
+function reverse();
+```
Returns a copy of the string in reverse order.
@@ -1139,7 +1352,9 @@ Returns a copy of the string in reverse order.
Signature:
- function trim();
+```
+function trim();
+```
Removes trailing whitespaces and returns the string.
@@ -1151,7 +1366,9 @@ This is the base type for all types in the Icinga application.
Signature:
- function clone();
+```
+ function clone();
+```
Returns a copy of the object. Note that for object elements which are
reference values (e.g. objects such as arrays or dictionaries) the entire
@@ -1161,7 +1378,9 @@ object is recursively copied.
Signature:
- function to_string();
+```
+function to_string();
+```
Returns a string representation for the object. Unless overridden this returns a string
of the format "Object of type '<typename>'" where <typename> is the name of the
@@ -1169,19 +1388,23 @@ object's type.
Example:
- [ 3, true ].to_string() /* Returns "[ 3.000000, true ]" */
+```
+[ 3, true ].to_string() /* Returns "[ 3.000000, true ]" */
+```
### Object#type <a id="object-type-field"></a>
Signature:
- String type;
+String type;
Returns the object's type name. This attribute is read-only.
Example:
- get_host("localhost").type /* Returns "Host" */
+```
+get_host("localhost").type /* Returns "Host" */
+```
## Type type <a id="type-type"></a>
@@ -1195,19 +1418,25 @@ All types are registered as global variables. For example, in order to obtain a
Signature:
- Type base;
+```
+Type base;
+```
Returns a reference to the type's base type. This attribute is read-only.
Example:
- Dictionary.base == Object /* Returns true, because the Dictionary type inherits directly from the Object type. */
+```
+Dictionary.base == Object /* Returns true, because the Dictionary type inherits directly from the Object type. */
+```
### Type#name <a id="type-name"></a>
Signature:
- String name;
+```
+String name;
+```
Returns the name of the type.
@@ -1215,7 +1444,9 @@ Returns the name of the type.
Signature:
- Object prototype;
+```
+Object prototype;
+```
Returns the prototype object for the type. When an attribute is accessed on an object that doesn't exist the prototype object is checked to see if an attribute with the requested name exists. If it does, the attribute's value is returned.
@@ -1223,7 +1454,9 @@ The prototype functionality is used to implement methods.
Example:
- 3.to_string() /* Even though '3' does not have a to_string property the Number type's prototype object does. */
+```
+3.to_string() /* Even though '3' does not have a to_string property the Number type's prototype object does. */
+```
## Array type <a id="array-type"></a>
@@ -1233,7 +1466,9 @@ Inherits methods from the [Object type](18-library-reference.md#object-type).
Signature:
- function add(value);
+```
+function add(value);
+```
Adds a new value after the last element in the array.
@@ -1241,13 +1476,17 @@ Adds a new value after the last element in the array.
Signature:
- function clear();
+```
+function clear();
+```
Removes all elements from the array.
### Array#shallow_clone <a id="array-shallow-clone"></a>
- function shallow_clone();
+```
+function shallow_clone();
+```
Returns a copy of the array. Note that for elements which are reference values (e.g. objects such
as arrays and dictionaries) only the references are copied.
@@ -1256,7 +1495,9 @@ as arrays and dictionaries) only the references are copied.
Signature:
- function contains(value);
+```
+function contains(value);
+```
Returns true if the array contains the specified value, false otherwise.
@@ -1264,7 +1505,9 @@ Returns true if the array contains the specified value, false otherwise.
Signature:
- function freeze()
+```
+function freeze()
+```
Disallows further modifications to this array. Trying to modify the array will result in an exception.
@@ -1272,7 +1515,9 @@ Disallows further modifications to this array. Trying to modify the array will r
Signature:
- function len();
+```
+function len();
+```
Returns the number of elements contained in the array.
@@ -1280,7 +1525,9 @@ Returns the number of elements contained in the array.
Signature:
- function remove(index);
+```
+function remove(index);
+```
Removes the element at the specified zero-based index.
@@ -1288,7 +1535,9 @@ Removes the element at the specified zero-based index.
Signature:
- function set(index, value);
+```
+function set(index, value);
+```
Sets the element at the zero-based index to the specified value. The `index` must refer to an element
which already exists in the array.
@@ -1297,7 +1546,9 @@ which already exists in the array.
Signature:
- function get(index);
+```
+function get(index);
+```
Retrieves the element at the specified zero-based index.
@@ -1305,7 +1556,9 @@ Retrieves the element at the specified zero-based index.
Signature:
- function sort(less_cmp);
+```
+function sort(less_cmp);
+```
Returns a copy of the array where all items are sorted. The items are
compared using the `<` (less-than) operator. A custom comparator function
@@ -1315,7 +1568,9 @@ can be specified with the `less_cmp` argument.
Signature:
- function join(separator);
+```
+function join(separator);
+```
Joins all elements of the array using the specified separator.
@@ -1323,7 +1578,9 @@ Joins all elements of the array using the specified separator.
Signature:
- function reverse();
+```
+function reverse();
+```
Returns a new array with all elements of the current array in reverse order.
@@ -1331,7 +1588,9 @@ Returns a new array with all elements of the current array in reverse order.
Signature:
- function map(func);
+```
+function map(func);
+```
Calls `func(element)` for each of the elements in the array and returns
a new array containing the return values of these function calls.
@@ -1340,7 +1599,9 @@ a new array containing the return values of these function calls.
Signature:
- function reduce(func);
+```
+function reduce(func);
+```
Reduces the elements of the array into a single value by calling the provided
function `func` as `func(a, b)` repeatedly where `a` and `b` are elements of the array
@@ -1350,7 +1611,9 @@ or results from previous function calls.
Signature:
- function filter(func);
+```
+function filter(func);
+```
Returns a copy of the array containing only the elements for which `func(element)`
is true.
@@ -1359,7 +1622,9 @@ is true.
Signature:
- function any(func);
+```
+function any(func);
+```
Returns true if the array contains at least one element for which `func(element)`
is true, false otherwise.
@@ -1368,7 +1633,9 @@ is true, false otherwise.
Signature:
- function all(func);
+```
+function all(func);
+```
Returns true if the array contains only elements for which `func(element)`
is true, false otherwise.
@@ -1377,7 +1644,9 @@ is true, false otherwise.
Signature:
- function unique();
+```
+function unique();
+```
Returns a copy of the array with all duplicate elements removed. The original order
of the array is not preserved.
@@ -1390,7 +1659,9 @@ Inherits methods from the [Object type](18-library-reference.md#object-type).
Signature:
- function shallow_clone();
+```
+function shallow_clone();
+```
Returns a copy of the dictionary. Note that for elements which are reference values (e.g. objects such
as arrays and dictionaries) only the references are copied.
@@ -1399,7 +1670,9 @@ as arrays and dictionaries) only the references are copied.
Signature:
- function contains(key);
+```
+function contains(key);
+```
Returns true if a dictionary item with the specified `key` exists, false otherwise.
@@ -1407,7 +1680,9 @@ Returns true if a dictionary item with the specified `key` exists, false otherwi
Signature:
- function freeze()
+```
+function freeze()
+```
Disallows further modifications to this dictionary. Trying to modify the dictionary will result in an exception.
@@ -1415,7 +1690,9 @@ Disallows further modifications to this dictionary. Trying to modify the diction
Signature:
- function len();
+```
+function len();
+```
Returns the number of items contained in the dictionary.
@@ -1423,7 +1700,9 @@ Returns the number of items contained in the dictionary.
Signature:
- function remove(key);
+```
+function remove(key);
+```
Removes the item with the specified `key`. Trying to remove an item which does not exist
is a no-op.
@@ -1432,7 +1711,9 @@ is a no-op.
Signature:
- function clear();
+```
+function clear();
+```
Removes all items from the dictionary.
@@ -1440,7 +1721,9 @@ Removes all items from the dictionary.
Signature:
- function set(key, value);
+```
+function set(key, value);
+```
Creates or updates an item with the specified `key` and `value`.
@@ -1448,7 +1731,9 @@ Creates or updates an item with the specified `key` and `value`.
Signature:
- function get(key);
+```
+function get(key);
+```
Retrieves the value for the specified `key`. Returns `null` if they `key` does not exist
in the dictionary.
@@ -1457,7 +1742,9 @@ in the dictionary.
Signature:
- function keys();
+```
+function keys();
+```
Returns a list of keys for all items that are currently in the dictionary.
@@ -1465,7 +1752,9 @@ Returns a list of keys for all items that are currently in the dictionary.
Signature:
- function values();
+```
+function values();
+```
Returns a list of values for all items that are currently in the dictionary.
@@ -1477,41 +1766,49 @@ Inherits methods from the [Object type](18-library-reference.md#object-type).
Signature:
- function call(thisArg, ...);
+```
+function call(thisArg, ...);
+```
Invokes the function using an alternative `this` scope. The `thisArg` argument specifies the `this`
scope for the function. All other arguments are passed directly to the function.
Example:
- function set_x(val) {
- this.x = val
- }
+```
+function set_x(val) {
+ this.x = val
+}
- dict = {}
+dict = {}
- set_x.call(dict, 7) /* Invokes set_x using `dict` as `this` */
+set_x.call(dict, 7) /* Invokes set_x using `dict` as `this` */
+```
### Function#callv <a id="scriptfunction-callv"></a>
Signature:
- function callv(thisArg, args);
+```
+function callv(thisArg, args);
+```
Invokes the function using an alternative `this` scope. The `thisArg` argument specifies the `this`
scope for the function. The items in the `args` array are passed to the function as individual arguments.
Example:
- function set_x(val) {
- this.x = val
- }
+```
+function set_x(val) {
+ this.x = val
+}
- var dict = {}
+var dict = {}
- var args = [ 7 ]
+var args = [ 7 ]
- set_x.callv(dict, args) /* Invokes set_x using `dict` as `this` */
+set_x.callv(dict, args) /* Invokes set_x using `dict` as `this` */
+```
## DateTime type <a id="datetime-type"></a>
@@ -1521,18 +1818,22 @@ Inherits methods from the [Object type](18-library-reference.md#object-type).
Signature:
- function DateTime()
- function DateTime(unixTimestamp)
- function DateTime(year, month, day)
- function DateTime(year, month, day, hours, minutes, seconds)
+```
+function DateTime()
+function DateTime(unixTimestamp)
+function DateTime(year, month, day)
+function DateTime(year, month, day, hours, minutes, seconds)
+```
Constructs a new DateTime object. When no arguments are specified for the constructor a new
DateTime object representing the current time is created.
Example:
- var d1 = DateTime() /* current time */
- var d2 = DateTime(2016, 5, 21) /* midnight April 21st, 2016 (local time) */
+```
+var d1 = DateTime() /* current time */
+var d2 = DateTime(2016, 5, 21) /* midnight April 21st, 2016 (local time) */
+```
### DateTime arithmetic <a id="datetime-arithmetic"></a>
@@ -1540,41 +1841,55 @@ Subtracting two DateTime objects yields the interval between them, in seconds.
Example:
- var delta = DateTime() - DateTime(2016, 5, 21) /* seconds since midnight April 21st, 2016 */
+```
+var delta = DateTime() - DateTime(2016, 5, 21) /* seconds since midnight April 21st, 2016 */
+```
Subtracting a number from a DateTime object yields a new DateTime object that is further in the past:
Example:
- var dt = DateTime() - 2 * 60 * 60 /* Current time minus 2 hours */
+```
+var dt = DateTime() - 2 * 60 * 60 /* Current time minus 2 hours */
+```
Adding a number to a DateTime object yields a new DateTime object that is in the future:
Example:
- var dt = DateTime() + 24 * 60 60 /* Current time plus 24 hours */
+```
+var dt = DateTime() + 24 * 60 60 /* Current time plus 24 hours */
+```
### DateTime#format <a id="datetime-format"></a>
Signature:
- function format(fmt)
+```
+function format(fmt)
+```
Returns a string representation for the DateTime object using the specified format string.
The format string may contain format conversion placeholders as specified in strftime(3).
Example:
- var s = DateTime(2016, 4, 21).format("%A") /* Sets s to "Thursday". */
+```
+var s = DateTime(2016, 4, 21).format("%A") /* Sets s to "Thursday". */
+```
### DateTime#to_string <a id="datetime-tostring"></a>
Signature:
- function to_string()
+```
+function to_string()
+```
Returns a string representation for the DateTime object. Uses a suitable default format.
Example:
- var s = DateTime(2016, 4, 21).to_string() /* Sets s to "2016-04-21 00:00:00 +0200". */
+```
+var s = DateTime(2016, 4, 21).to_string() /* Sets s to "2016-04-21 00:00:00 +0200". */
+```
diff --git a/doc/19-technical-concepts.md b/doc/19-technical-concepts.md
index b9021a2..9fc0fb3 100644
--- a/doc/19-technical-concepts.md
+++ b/doc/19-technical-concepts.md
@@ -165,6 +165,15 @@ The following signals are triggered in the stages:
- **Activate**: Calls `Start()` on the object, sets the local HA authority and notifies subscribers that this object is now activated (e.g. for config updates in the DB backend).
+### References <a id="technical-concepts-configuration-references"></a>
+
+* [The Icinga Config Compiler: An Overview](https://www.netways.de/blog/2018/07/12/the-icinga-config-compiler-an-overview/)
+* [A parser/lexer/compiler for the Leonardo language](https://github.com/EmilGedda/Leonardo)
+* [I wrote a programming language. Here’s how you can, too.](https://medium.freecodecamp.org/the-programming-language-pipeline-91d3f449c919)
+* [http://onoffswitch.net/building-a-custom-lexer/](http://onoffswitch.net/building-a-custom-lexer/)
+* [Writing an Interpreter with Lex, Yacc, and Memphis](http://memphis.compilertools.net/interpreter.html)
+* [Flex](https://github.com/westes/flex)
+* [GNU Bison](https://www.gnu.org/software/bison/)
## Features <a id="technical-concepts-features"></a>
@@ -191,10 +200,12 @@ The GraphiteWriter feature calls the registered function and processes
the received data. Features which connect Icinga 2 to external interfaces
normally parse and reformat the received data into an applicable format.
+Since this check result signal is blocking, many of the features include a work queue
+with asynchronous task handling.
+
The GraphiteWriter uses a TCP socket to communicate with the carbon cache
daemon of Graphite. The InfluxDBWriter is instead writing bulk metric messages
-to InfluxDB's HTTP API.
-
+to InfluxDB's HTTP API, similar to Elasticsearch.
## Check Scheduler <a id="technical-concepts-check-scheduler"></a>
@@ -512,10 +523,10 @@ The update procedure works the same way as above.
### High Availability <a id="technical-concepts-cluster-ha"></a>
-High availability is automatically enabled between two nodes in the same
+General high availability is automatically enabled between two endpoints in the same
cluster zone.
-This requires the same configuration and enabled features on both nodes.
+**This requires the same configuration and enabled features on both nodes.**
HA zone members trust each other and share event updates as cluster messages.
This includes for example check results, next check timestamp updates, acknowledgements
@@ -524,18 +535,52 @@ or notifications.
This ensures that both nodes are synchronized. If one node goes away, the
remaining node takes over and continues as normal.
+#### High Availability: Object Authority <a id="technical-concepts-cluster-ha-object-authority"></a>
Cluster nodes automatically determine the authority for configuration
-objects. This results in activated but paused objects. You can verify
-that by querying the `paused` attribute for all objects via REST API
-or debug console.
+objects. By default, all config objects are set to `HARunEverywhere` and
+as such the object authority is true for any config object on any instance.
+
+Specific objects can override and influence this setting, e.g. with `HARunOnce`
+instead prior to config object activation.
+
+This is done when the daemon starts and in a regular interval inside
+the ApiListener class, specifically calling `ApiListener::UpdateObjectAuthority()`.
+
+The algorithm works like this:
+
+* Determine whether this instance is assigned to a local zone and endpoint.
+* Collects all endpoints in this zone if they are connected.
+* If there's two endpoints, but only us seeing ourselves and the application start is less than 60 seconds in the past, do nothing (wait for cluster reconnect to take place, grace period).
+* Sort the collected endpoints by name.
+* Iterate over all config types and their respective objects
+ * Ignore !active objects
+ * Ignore objects which are !HARunOnce. This means, they can run multiple times in a zone and don't need an authority update.
+ * If this instance doesn't have a local zone, set authority to true. This is for non-clustered standalone environments where everything belongs to this instance.
+ * Calculate the object authority based on the connected endpoint names.
+ * Set the authority (true or false)
+
+The object authority calculation works "offline" without any message exchange.
+Each instance alculates the SDBM hash of the config object name, puts that in contrast
+modulo the connected endpoints size.
+This index is used to lookup the corresponding endpoint in the connected endpoints array,
+including the local endpoint. Whether the local endpoint is equal to the selected endpoint,
+or not, this sets the authority to `true` or `false`.
+
+```
+authority = endpoints[Utility::SDBM(object->GetName()) % endpoints.size()] == my_endpoint;
+```
-Nodes inside a HA zone calculate the object authority independent from each other.
+`ConfigObject::SetAuthority(bool authority)` triggers the following events:
-The number of endpoints in a zone is defined through the configuration. This number
-is used inside a local modulo calculation to determine whether the node feels
-responsible for this object or not.
+* Authority is true and object now paused: Resume the object and set `paused` to `false`.
+* Authority is false, object not paused: Pause the object and set `paused` to true.
+**This results in activated but paused objects on one endpoint.** You can verify
+that by querying the `paused` attribute for all objects via REST API
+or debug console on both endpoints.
+
+Endpoints inside a HA zone calculate the object authority independent from each other.
This object authority is important for selected features explained below.
Since features are configuration objects too, you must ensure that all nodes
@@ -544,6 +589,36 @@ one might have a checker feature on the left node, nothing on the right node.
This leads to late check results because one half is not executed by the right
node which holds half of the object authorities.
+By default, features are enabled to "Run-Everywhere". Specific features which
+support HA awareness, provide the `enable_ha` configuration attribute. When `enable_ha`
+is set to `true` (usually the default), "Run-Once" is set and the feature pauses on one side.
+
+```
+vim /etc/icinga2/features-enabled/ido-mysql.conf
+
+object IdoMysqlConnection "ido-mysql" {
+ ...
+ enable_ha = true
+}
+```
+
+Once such a feature is paused, there won't be any more event handling, e.g. the IDO MySQL
+feature won't write status and config updates anymore for this endpoint.
+
+When the cluster connection drops, the feature configuration object is updated with
+the new object authority by the ApiListener timer and resumes its operation. You can see
+that by grepping the log file for `resumed` and `paused`.
+
+```
+[2018-10-24 13:28:28 +0200] information/IdoMysqlConnection: 'ido-mysql' paused.
+```
+
+```
+[2018-10-24 13:28:28 +0200] information/IdoMysqlConnection: 'ido-mysql' resumed.
+```
+
+Specific features with HA capabilities are explained below.
+
### High Availability: Checker <a id="technical-concepts-cluster-ha-checker"></a>
The `checker` feature only executes checks for `Checkable` objects (Host, Service)
@@ -660,14 +735,6 @@ Icinga 2 v2.9+ adds more performance metrics for these values:
* `sum_bytes_sent_per_second` and `sum_bytes_received_per_second`
-<!--
-## REST API <a id="technical-concepts-rest-api"></a>
-
-Icinga 2 provides its own HTTP server which shares the port 5665 with
-the JSON-RPC cluster protocol.
--->
-
-
## TLS Network IO <a id="technical-concepts-tls-network-io"></a>
### TLS Connection Handling <a id="technical-concepts-tls-network-io-connection-handling"></a>
@@ -838,7 +905,7 @@ below have been collected too. [This thread](https://www.reddit.com/r/cpp/commen
also sheds more light in modern programming techniques.
Our main "problem" with Icinga 2 are modern compilers supporting the full C++11 feature set.
-Recent analysis have proven that gcc on CentOS 6 or SLES11 are too old to use modern
+Recent analysis have proven that gcc on CentOS 6 are too old to use modern
programming techniques or anything which implemens C++14 at least.
Given the below projects, we are also not fans of wrapping C interfaces into
@@ -861,3 +928,789 @@ into the Icinga 2 binary.
* cpp-netlib: https://github.com/cpp-netlib/cpp-netlib
* evpp: https://github.com/Qihoo360/evpp
+
+
+<!--
+## REST API <a id="technical-concepts-rest-api"></a>
+
+Icinga 2 provides its own HTTP server which shares the port 5665 with
+the JSON-RPC cluster protocol.
+-->
+
+## JSON-RPC Message API <a id="technical-concepts-json-rpc-messages"></a>
+
+**The JSON-RPC message API is not a public API for end users.** In case you want
+to interact with Icinga, use the [REST API](12-icinga2-api.md#icinga2-api).
+
+This section describes the internal cluster messages exchanged between endpoints.
+
+> **Tip**
+>
+> Debug builds with `icinga2 daemon -DInternal.DebugJsonRpc=1` unveils the JSON-RPC messages.
+
+### Registered Handler Functions
+
+Functions by example:
+
+Event Sender: `Checkable::OnNewCheckResult`
+
+```
+On<xyz>.connect(&xyzHandler)
+```
+
+Event Receiver (Client): `CheckResultAPIHandler` in `REGISTER_APIFUNCTION`
+
+```
+<xyz>APIHandler()
+```
+
+### Messages
+
+#### icinga::Hello <a id="technical-concepts-json-rpc-messages-icinga-hello"></a>
+
+> Location: `apilistener.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | icinga::Hello
+params | Dictionary
+
+##### Params
+
+Currently empty.
+
+##### Functions
+
+Event Sender: When a new client connects in `NewClientHandlerInternal()`.
+Event Receiver: `HelloAPIHandler`
+
+##### Permissions
+
+None, this is a required message.
+
+#### event::Heartbeat <a id="technical-concepts-json-rpc-messages-event-heartbeat"></a>
+
+> Location: `jsonrpcconnection-heartbeat.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::Heartbeat
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+----------|---------------|------------------
+timeout | Number | Heartbeat timeout, sender sets 120s.
+
+
+##### Functions
+
+Event Sender: `JsonRpcConnection::HeartbeatTimerHandler`
+Event Receiver: `HeartbeatAPIHandler`
+
+Both sender and receiver exchange this heartbeat message. If the sender detects
+that a client endpoint hasn't sent anything in the updated timeout span, it disconnects
+the client. This is to avoid stale connections with no message processing.
+
+##### Permissions
+
+None, this is a required message.
+
+#### event::CheckResult <a id="technical-concepts-json-rpc-messages-event-checkresult"></a>
+
+> Location: `clusterevents.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::CheckResult
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+----------|---------------|------------------
+host | String | Host name
+service | String | Service name
+cr | Serialized CR | Check result
+
+##### Functions
+
+Event Sender: `Checkable::OnNewCheckResult`
+Event Receiver: `CheckResultAPIHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Hosts/services do not exist
+* Origin is a remote command endpoint different to the configured, and whose zone is not allowed to access this checkable.
+
+#### event::SetNextCheck <a id="technical-concepts-json-rpc-messages-event-setnextcheck"></a>
+
+> Location: `clusterevents.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::SetNextCheck
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+------------|---------------|------------------
+host | String | Host name
+service | String | Service name
+next\_check | Timestamp | Next scheduled time as UNIX timestamp.
+
+##### Functions
+
+Event Sender: `Checkable::OnNextCheckChanged`
+Event Receiver: `NextCheckChangedAPIHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Checkable does not exist.
+* Origin endpoint's zone is not allowed to access this checkable.
+
+#### event::SetNextNotification <a id="technical-concepts-json-rpc-messages-event-setnextnotification"></a>
+
+> Location: `clusterevents.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::SetNextNotification
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+-------------------|---------------|------------------
+host | String | Host name
+service | String | Service name
+notification | String | Notification name
+next\_notification | Timestamp | Next scheduled notification time as UNIX timestamp.
+
+##### Functions
+
+Event Sender: `Notification::OnNextNotificationChanged`
+Event Receiver: `NextNotificationChangedAPIHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Notification does not exist.
+* Origin endpoint's zone is not allowed to access this checkable.
+
+#### event::SetForceNextCheck <a id="technical-concepts-json-rpc-messages-event-setforcenextcheck"></a>
+
+> Location: `clusterevents.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::SetForceNextCheck
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+----------|---------------|------------------
+host | String | Host name
+service | String | Service name
+forced | Boolean | Forced next check (execute now)
+
+##### Functions
+
+Event Sender: `Checkable::OnForceNextCheckChanged`
+Event Receiver: `ForceNextCheckChangedAPIHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Checkable does not exist.
+* Origin endpoint's zone is not allowed to access this checkable.
+
+#### event::SetForceNextNotification <a id="technical-concepts-json-rpc-messages-event-setforcenextnotification"></a>
+
+> Location: `clusterevents.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::SetForceNextNotification
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+----------|---------------|------------------
+host | String | Host name
+service | String | Service name
+forced | Boolean | Forced next check (execute now)
+
+##### Functions
+
+Event Sender: `Checkable::SetForceNextNotification`
+Event Receiver: `ForceNextNotificationChangedAPIHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Checkable does not exist.
+* Origin endpoint's zone is not allowed to access this checkable.
+
+#### event::SetAcknowledgement <a id="technical-concepts-json-rpc-messages-event-setacknowledgement"></a>
+
+> Location: `clusterevents.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::SetAcknowledgement
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+-----------|---------------|------------------
+host | String | Host name
+service | String | Service name
+author | String | Acknowledgement author name.
+comment | String | Acknowledgement comment content.
+acktype | Number | Acknowledgement type (0=None, 1=Normal, 2=Sticky)
+notify | Boolean | Notification should be sent.
+persistent | Boolean | Whether the comment is persistent.
+expiry | Timestamp | Optional expire time as UNIX timestamp.
+
+##### Functions
+
+Event Sender: `Checkable::OnForceNextCheckChanged`
+Event Receiver: `ForceNextCheckChangedAPIHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Checkable does not exist.
+* Origin endpoint's zone is not allowed to access this checkable.
+
+#### event::ClearAcknowledgement <a id="technical-concepts-json-rpc-messages-event-clearacknowledgement"></a>
+
+> Location: `clusterevents.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::ClearAcknowledgement
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+----------|---------------|------------------
+host | String | Host name
+service | String | Service name
+
+##### Functions
+
+Event Sender: `Checkable::OnAcknowledgementCleared`
+Event Receiver: `AcknowledgementClearedAPIHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Checkable does not exist.
+* Origin endpoint's zone is not allowed to access this checkable.
+
+#### event::SendNotifications <a id="technical-concepts-json-rpc-messages-event-sendnotifications"></a>
+
+> Location: `clusterevents.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::SendNotifications
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+----------|---------------|------------------
+host | String | Host name
+service | String | Service name
+cr | Serialized CR | Check result
+type | Number | enum NotificationType, same as `types` for notification objects.
+author | String | Author name
+text | String | Notification text
+
+##### Functions
+
+Event Sender: `Checkable::OnNotificationsRequested`
+Event Receiver: `SendNotificationsAPIHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Checkable does not exist.
+* Origin endpoint's zone the same as the receiver. This binds notification messages to the HA zone.
+
+#### event::NotificationSentUser <a id="technical-concepts-json-rpc-messages-event-notificationsentuser"></a>
+
+> Location: `clusterevents.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::NotificationSentUser
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+--------------|-----------------|------------------
+host | String | Host name
+service | String | Service name
+notification | String | Notification name.
+user | String | Notified user name.
+type | Number | enum NotificationType, same as `types` in Notification objects.
+cr | Serialized CR | Check result.
+author | String | Notification author (for specific types)
+text | String | Notification text (for specific types)
+command | String | Notification command name.
+
+##### Functions
+
+Event Sender: `Checkable::OnNotificationSentToUser`
+Event Receiver: `NotificationSentUserAPIHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Checkable does not exist.
+* Origin endpoint's zone the same as the receiver. This binds notification messages to the HA zone.
+
+#### event::NotificationSentToAllUsers <a id="technical-concepts-json-rpc-messages-event-notificationsenttoallusers"></a>
+
+> Location: `clusterevents.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::NotificationSentToAllUsers
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+----------------------------|-----------------|------------------
+host | String | Host name
+service | String | Service name
+notification | String | Notification name.
+users | Array of String | Notified user names.
+type | Number | enum NotificationType, same as `types` in Notification objects.
+cr | Serialized CR | Check result.
+author | String | Notification author (for specific types)
+text | String | Notification text (for specific types)
+last\_notification | Timestamp | Last notification time as UNIX timestamp.
+next\_notification | Timestamp | Next scheduled notification time as UNIX timestamp.
+notification\_number | Number | Current notification number in problem state.
+last\_problem\_notification | Timestamp | Last problem notification time as UNIX timestamp.
+no\_more\_notifications | Boolean | Whether to send future notifications when this notification becomes active on this HA node.
+
+##### Functions
+
+Event Sender: `Checkable::OnNotificationSentToAllUsers`
+Event Receiver: `NotificationSentToAllUsersAPIHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Checkable does not exist.
+* Origin endpoint's zone the same as the receiver. This binds notification messages to the HA zone.
+
+#### event::ExecuteCommand <a id="technical-concepts-json-rpc-messages-event-executecommand"></a>
+
+> Location: `clusterevents-check.cpp` and `checkable-check.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | event::ExecuteCommand
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+--------------|---------------|------------------
+host | String | Host name.
+service | String | Service name.
+command\_type | String | `check_command` or `event_command`.
+command | String | CheckCommand or EventCommand name.
+macros | Dictionary | Command arguments as key/value pairs for remote execution.
+
+
+##### Functions
+
+**Event Sender:** This gets constructed directly in `Checkable::ExecuteCheck()` or `Checkable::ExecuteEventHandler()` when a remote command endpoint is configured.
+
+* `Get{CheckCommand,EventCommand}()->Execute()` simulates an execution and extracts all command arguments into the `macro` dictionary (inside lib/methods tasks).
+* When the endpoint is connected, the message is constructed and sent directly.
+* When the endpoint is not connected and not syncing replay logs and 5m after application start, generate an UNKNOWN check result for the user ("not connected").
+
+**Event Receiver:** `ExecuteCommandAPIHandler`
+
+Special handling, calls `ClusterEvents::EnqueueCheck()` for command endpoint checks.
+This function enqueues check tasks into a queue which is controlled in `RemoteCheckThreadProc()`.
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Origin endpoint's zone is not a parent zone of the receiver endpoint.
+* `accept_commands = false` in the `api` feature configuration sends back an UNKNOWN check result to the sender.
+
+The receiver constructs a virtual host object and looks for the local CheckCommand object.
+
+Returns UNKNWON as check result to the sender
+
+* when the CheckCommand object does not exist.
+* when there was an exception triggered from check execution, e.g. the plugin binary could not be executed or similar.
+
+The returned messages are synced directly to the sender's endpoint, no cluster broadcast.
+
+> **Note**: EventCommand errors are just logged on the remote endpoint.
+
+#### config::Update <a id="technical-concepts-json-rpc-messages-config-update"></a>
+
+> Location: `apilistener-filesync.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | config::Update
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+-----------|---------------|------------------
+update | Dictionary | Config file paths and their content.
+update\_v2 | Dictionary | Additional meta config files introduced in 2.4+ for compatibility reasons.
+
+##### Functions
+
+**Event Sender:** `SendConfigUpdate()` called in `ApiListener::SyncClient()` when a new client endpoint connects.
+**Event Receiver:** `ConfigUpdateHandler` reads the config update content and stores them in `/var/lib/icinga2/api`.
+When it detects a configuration change, the function requests and application restart.
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* The origin sender is not in a parent zone of the receiver.
+* `api` feature does not accept config.
+
+Config updates will be ignored when:
+
+* The zone is not configured on the receiver endpoint.
+* The zone is authoritative on this instance (this only happens on a master which has `/etc/icinga2/zones.d` populated, and prevents sync loops)
+
+#### config::UpdateObject <a id="technical-concepts-json-rpc-messages-config-updateobject"></a>
+
+> Location: `apilistener-configsync.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | config::UpdateObject
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+---------------------|-------------|------------------
+name | String | Object name.
+type | String | Object type name.
+version | Number | Object version.
+config | String | Config file content for `_api` packages.
+modified\_attributes | Dictionary | Modified attributes at runtime as key value pairs.
+original\_attributes | Array | Original attributes as array of keys.
+
+
+##### Functions
+
+**Event Sender:** Either on client connect (full sync), or runtime created/updated object
+
+`ApiListener::SendRuntimeConfigObjects()` gets called when a new endpoint is connected
+and runtime created config objects need to be synced. This invokes a call to `UpdateConfigObject()`
+to only sync this JsonRpcConnection client.
+
+`ConfigObject::OnActiveChanged` (created or deleted) or `ConfigObject::OnVersionChanged` (updated)
+also call `UpdateConfigObject()`.
+
+**Event Receiver:** `ConfigUpdateObjectAPIHandler` calls `ConfigObjectUtility::CreateObject()` in order
+to create the object if it is not already existing. Afterwards, all modified attributes are applied
+and in case, original attributes are restored. The object version is set as well, keeping it in sync
+with the sender.
+
+##### Permissions
+
+###### Sender
+
+Client receiver connects:
+
+The sender only syncs config object updates to a client which can access
+the config object, in `ApiListener::SendRuntimeConfigObjects()`.
+
+In addition to that, the client endpoint's zone is checked whether this zone may access
+the config object.
+
+Runtime updated object:
+
+Only if the config object belongs to the `_api` package.
+
+
+###### Receiver
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Origin sender endpoint's zone is in a child zone.
+* `api` feature does not accept config
+* The received config object type does not exist (this is to prevent failures with older nodes and new object types).
+
+Error handling:
+
+* Log an error if `CreateObject` fails (only if the object does not already exist)
+* Local object version is newer than the received version, object will not be updated.
+* Compare modified and original attributes and restore any type of change here.
+
+
+#### config::DeleteObject <a id="technical-concepts-json-rpc-messages-config-deleteobject"></a>
+
+> Location: `apilistener-configsync.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | config::DeleteObject
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+--------------------|-------------|------------------
+name | String | Object name.
+type | String | Object type name.
+version | Number | Object version.
+
+##### Functions
+
+**Event Sender:**
+
+`ConfigObject::OnActiveChanged` (created or deleted) or `ConfigObject::OnVersionChanged` (updated)
+call `DeleteConfigObject()`.
+
+**Event Receiver:** `ConfigDeleteObjectAPIHandler`
+
+##### Permissions
+
+###### Sender
+
+Runtime deleted object:
+
+Only if the config object belongs to the `_api` package.
+
+###### Receiver
+
+The receiver will not process messages from not configured endpoints.
+
+Message updates will be dropped when:
+
+* Origin sender endpoint's zone is in a child zone.
+* `api` feature does not accept config
+* The received config object type does not exist (this is to prevent failures with older nodes and new object types).
+* The object in question was not created at runtime, it does not belong to the `_api` package.
+
+Error handling:
+
+* Log an error if `DeleteObject` fails (only if the object does not already exist)
+
+#### pki::RequestCertificate <a id="technical-concepts-json-rpc-messages-pki-requestcertificate"></a>
+
+> Location: `jsonrpcconnection-pki.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | pki::RequestCertificate
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+--------------|---------------|------------------
+ticket | String | Own ticket, or as satellite in CA proxy from local store.
+cert\_request | String | Certificate request content from local store, optional.
+
+##### Functions
+
+Event Sender: `RequestCertificateHandler`
+Event Receiver: `RequestCertificateHandler`
+
+##### Permissions
+
+This is an anonymous request, and the number of anonymous clients can be configured
+in the `api` feature.
+
+Only valid certificate request messages are processed, and valid signed certificates
+won't be signed again.
+
+#### pki::UpdateCertificate <a id="technical-concepts-json-rpc-messages-pki-updatecertificate"></a>
+
+> Location: `jsonrpcconnection-pki.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | pki::UpdateCertificate
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+---------------------|---------------|------------------
+status\_code | Number | Status code, 0=ok.
+cert | String | Signed certificate content.
+ca | String | Public CA certificate content.
+fingerprint\_request | String | Certificate fingerprint from the CSR.
+
+
+##### Functions
+
+**Event Sender:**
+
+* When a client requests a certificate in `RequestCertificateHandler` and the satellite
+already has a signed certificate, the `pki::UpdateCertificate` message is constructed and sent back.
+* When the endpoint holding the master's CA private key (and TicketSalt private key) is able to sign
+the request, the `pki::UpdateCertificate` message is constructed and sent back.
+
+**Event Receiver:** `UpdateCertificateHandler`
+
+##### Permissions
+
+Message updates are dropped when
+
+* The origin sender is not in a parent zone of the receiver.
+* The certificate fingerprint is in an invalid format.
+
+#### log::SetLogPosition <a id="technical-concepts-json-rpc-messages-log-setlogposition"></a>
+
+> Location: `apilistener.cpp` and `jsonrpcconnection.cpp`
+
+##### Message Body
+
+Key | Value
+----------|---------
+jsonrpc | 2.0
+method | log::SetLogPosition
+params | Dictionary
+
+##### Params
+
+Key | Type | Description
+--------------------|---------------|------------------
+log\_position | Timestamp | The endpoint's log position as UNIX timestamp.
+
+
+##### Functions
+
+**Event Sender:**
+
+During log replay to a client endpoint in `ApiListener::ReplayLog()`, each processed
+file generates a message which updates the log position timestamp.
+
+`ApiListener::ApiTimerHandler()` invokes a check to keep all connected endpoints and
+their log position in sync during replay log.
+
+**Event Receiver:** `SetLogPositionHandler`
+
+##### Permissions
+
+The receiver will not process messages from not configured endpoints.
diff --git a/doc/20-script-debugger.md b/doc/20-script-debugger.md
index 09a11e9..711600c 100644
--- a/doc/20-script-debugger.md
+++ b/doc/20-script-debugger.md
@@ -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" {
- check_command = "icinga"
+```
+object Host "script-debugger-host" {
+ check_command = "icinga"
- vars.http_vhosts["example.org"] = "192.168.1.100" // a string value
- }
+ vars.http_vhosts["example.org"] = "192.168.1.100" // a string value
+}
- apply Service for (http_vhost => config in host.vars.http_vhosts) {
- import "generic-service"
+apply Service for (http_vhost => config in host.vars.http_vhosts) {
+ import "generic-service"
- vars += config // expects a dictionary
+ vars += config // expects a dictionary
- check_command = "http"
- }
+ 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
-
- 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> =>
+```
+# 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
+ ^^^^^^^^^^^^^^
+/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,28 +96,31 @@ 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" {
- check_command = "dummy"
- check_interval = 5s
-
- vars.dummy_text = {{
- var text = "Hello from " + macro("$name$")
- debugger
- return text
- }}
- }
+```
+object Host "script-debugger-host-02" {
+ check_command = "dummy"
+ check_interval = 5s
+
+ vars.dummy_text = {{
+ var text = "Hello from " + macro("$name$")
+ 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>
diff --git a/doc/21-development.md b/doc/21-development.md
index c5ea8e7..feccdd8 100644
--- a/doc/21-development.md
+++ b/doc/21-development.md
@@ -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)
- 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,
- 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"}}
+```
+(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,
+ 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>
@@ -1584,66 +1586,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
-
- 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/python')
- from libstdcxx.v6.printers import register_libstdcxx_printers
- try:
- register_libstdcxx_printers(None)
- 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
+```
+$ wget https://raw.githubusercontent.com/Icinga/icinga2/master/tools/debug/gdb/gdbinit -O ~/.gdbinit
+$ vim ~/.gdbinit
+
+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/python')
+from libstdcxx.v6.printers import register_libstdcxx_printers
+try:
+ register_libstdcxx_printers(None)
+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
+```
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>
diff --git a/doc/22-selinux.md b/doc/22-selinux.md
index 9801553..15f111a 100644
--- a/doc/22-selinux.md
+++ b/doc/22-selinux.md
@@ -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>
@@ -126,23 +140,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.
@@ -152,25 +172,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
- /**
- * The GraphiteWriter type writes check result metrics and
- * performance data to a graphite tcp socket.
- */
+```
+# 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" {
- //host = "127.0.0.1"
- //port = 2003
- port = 2004
- }
- # icinga2 feature enable graphite
+object GraphiteWriter "graphite" {
+ //host = "127.0.0.1"
+ //port = 2003
+ port = 2004
+}
+# 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.
@@ -181,49 +205,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>
diff --git a/doc/23-migrating-from-icinga-1x.md b/doc/23-migrating-from-icinga-1x.md
index 4583b16..8ae0aaa 100644
--- a/doc/23-migrating-from-icinga-1x.md
+++ b/doc/23-migrating-from-icinga-1x.md
@@ -33,24 +33,28 @@ all existing Icinga 1.x `*_interval` attributes require an additional `m` durati
Icinga 1.x:
- define service {
- service_description service1
- host_name localhost1
- check_command test_customvar
- use generic-service
- check_interval 5
- retry_interval 1
- }
+```
+define service {
+ service_description service1
+ host_name localhost1
+ check_command test_customvar
+ use generic-service
+ check_interval 5
+ retry_interval 1
+}
+```
Icinga 2:
- object Service "service1" {
- import "generic-service"
- host_name = "localhost1"
- check_command = "test_customvar"
- check_interval = 5m
- retry_interval = 1m
- }
+```
+object Service "service1" {
+ import "generic-service"
+ host_name = "localhost1"
+ check_command = "test_customvar"
+ check_interval = 5m
+ retry_interval = 1m
+}
+```
#### Manual Config Migration Hints for Services <a id="manual-config-migration-hints-services"></a>
@@ -59,70 +63,81 @@ belongs to, you can migrate this to the [apply rules](03-monitoring-basics.md#us
Icinga 1.x:
- define service {
- service_description service1
- host_name localhost1,localhost2
- check_command test_check
- use generic-service
- }
+```
+define service {
+ service_description service1
+ host_name localhost1,localhost2
+ check_command test_check
+ use generic-service
+}
+```
Icinga 2:
- apply Service "service1" {
- import "generic-service"
- check_command = "test_check"
+```
+apply Service "service1" {
+ import "generic-service"
+ check_command = "test_check"
- assign where host.name in [ "localhost1", "localhost2" ]
- }
+ assign where host.name in [ "localhost1", "localhost2" ]
+}
+```
In Icinga 1.x you would have organized your services with hostgroups using the `hostgroup_name` attribute
like the following example:
- define service {
- service_description servicewithhostgroups
- hostgroup_name hostgroup1,hostgroup3
- check_command test_check
- use generic-service
- }
+```
+define service {
+ service_description servicewithhostgroups
+ hostgroup_name hostgroup1,hostgroup3
+ check_command test_check
+ use generic-service
+}
+```
Using Icinga 2 you can migrate this to the [apply rules](03-monitoring-basics.md#using-apply) syntax:
- apply Service "servicewithhostgroups" {
- import "generic-service"
- check_command = "test_check"
+```
+apply Service "servicewithhostgroups" {
+ import "generic-service"
+ check_command = "test_check"
- assign where "hostgroup1" in host.groups
- assign where "hostgroup3" in host.groups
- }
+ assign where "hostgroup1" in host.groups
+ assign where "hostgroup3" in host.groups
+}
+```
#### Manual Config Migration Hints for Group Members <a id="manual-config-migration-hints-group-members"></a>
The Icinga 1.x hostgroup `hg1` has two members `host1` and `host2`. The hostgroup `hg2` has `host3` as
a member and includes all members of the `hg1` hostgroup.
- define hostgroup {
- hostgroup_name hg1
- members host1,host2
- }
+```
+define hostgroup {
+ hostgroup_name hg1
+ members host1,host2
+}
- define hostgroup {
- hostgroup_name hg2
- members host3
- hostgroup_members hg1
- }
+define hostgroup {
+ hostgroup_name hg2
+ members host3
+ hostgroup_members hg1
+}
+```
This can be migrated to Icinga 2 and [using group assign](17-language-reference.md#group-assign). The additional nested hostgroup
`hg1` is included into `hg2` with the `groups` attribute.
+```
+object HostGroup "hg1" {
+ groups = [ "hg2" ]
+ assign where host.name in [ "host1", "host2" ]
+}
- object HostGroup "hg1" {
- groups = [ "hg2" ]
- assign where host.name in [ "host1", "host2" ]
- }
-
- object HostGroup "hg2" {
- assign where host.name == "host3"
- }
+object HostGroup "hg2" {
+ assign where host.name == "host3"
+}
+```
These assign rules can be applied for all groups: `HostGroup`, `ServiceGroup` and `UserGroup`
(requires renaming from `contactgroup`).
@@ -138,50 +153,54 @@ These assign rules can be applied for all groups: `HostGroup`, `ServiceGroup` an
Host and service check command arguments are separated by a `!` in Icinga 1.x. Their order is important and they
are referenced as `$ARGn$` where `n` is the argument counter.
- define command {
- command_name my-ping
- command_line $USER1$/check_ping -H $HOSTADDRESS$ -w $ARG1$ -c $ARG2$ -p 5
- }
+```
+define command {
+ command_name my-ping
+ command_line $USER1$/check_ping -H $HOSTADDRESS$ -w $ARG1$ -c $ARG2$ -p 5
+}
- define service {
- use generic-service
- host_name my-server
- service_description my-ping
- check_command my-ping-check!100.0,20%!500.0,60%
- }
+define service {
+ use generic-service
+ host_name my-server
+ service_description my-ping
+ check_command my-ping-check!100.0,20%!500.0,60%
+}
+```
While you could manually migrate this like (please note the new generic command arguments and default argument values!):
- object CheckCommand "my-ping-check" {
- command = [
- PluginDir + "/check_ping", "-4"
- ]
-
- arguments = {
- "-H" = "$ping_address$"
- "-w" = "$ping_wrta$,$ping_wpl$%"
- "-c" = "$ping_crta$,$ping_cpl$%"
- "-p" = "$ping_packets$"
- "-t" = "$ping_timeout$"
- }
-
- vars.ping_address = "$address$"
- vars.ping_wrta = 100
- vars.ping_wpl = 5
- vars.ping_crta = 200
- vars.ping_cpl = 15
- }
-
- object Service "my-ping" {
- import "generic-service"
- host_name = "my-server"
- check_command = "my-ping-check"
-
- vars.ping_wrta = 100
- vars.ping_wpl = 20
- vars.ping_crta = 500
- vars.ping_cpl = 60
- }
+```
+object CheckCommand "my-ping-check" {
+ command = [
+ PluginDir + "/check_ping", "-4"
+ ]
+
+ arguments = {
+ "-H" = "$ping_address$"
+ "-w" = "$ping_wrta$,$ping_wpl$%"
+ "-c" = "$ping_crta$,$ping_cpl$%"
+ "-p" = "$ping_packets$"
+ "-t" = "$ping_timeout$"
+ }
+
+ vars.ping_address = "$address$"
+ vars.ping_wrta = 100
+ vars.ping_wpl = 5
+ vars.ping_crta = 200
+ vars.ping_cpl = 15
+}
+
+object Service "my-ping" {
+ import "generic-service"
+ host_name = "my-server"
+ check_command = "my-ping-check"
+
+ vars.ping_wrta = 100
+ vars.ping_wpl = 20
+ vars.ping_crta = 500
+ vars.ping_cpl = 60
+}
+```
#### Manual Config Migration Hints for Runtime Macros <a id="manual-config-migration-hints-runtime-macros"></a>
@@ -189,62 +208,73 @@ Runtime macros have been renamed. A detailed comparison table can be found [here
For example, accessing the service check output looks like the following in Icinga 1.x:
- $SERVICEOUTPUT$
+```
+$SERVICEOUTPUT$
+```
In Icinga 2 you will need to write:
- $service.output$
+```
+$service.output$
+```
Another example referencing the host's address attribute in Icinga 1.x:
- $HOSTADDRESS$
+```
+$HOSTADDRESS$
+```
In Icinga 2 you'd just use the following macro to access all `address` attributes (even overridden from the service objects):
- $address$
-
+```
+$address$
+```
#### Manual Config Migration Hints for Runtime Custom Attributes <a id="manual-config-migration-hints-runtime-custom-attributes"></a>
Custom variables from Icinga 1.x are available as Icinga 2 custom attributes.
- define command {
- command_name test_customvar
- command_line echo "Host CV: $_HOSTCVTEST$ Service CV: $_SERVICECVTEST$\n"
- }
-
- define host {
- host_name localhost1
- check_command test_customvar
- use generic-host
- _CVTEST host cv value
- }
-
- define service {
- service_description service1
- host_name localhost1
- check_command test_customvar
- use generic-service
- _CVTEST service cv value
- }
+```
+define command {
+ command_name test_customvar
+ command_line echo "Host CV: $_HOSTCVTEST$ Service CV: $_SERVICECVTEST$\n"
+}
+
+define host {
+ host_name localhost1
+ check_command test_customvar
+ use generic-host
+ _CVTEST host cv value
+}
+
+define service {
+ service_description service1
+ host_name localhost1
+ check_command test_customvar
+ use generic-service
+ _CVTEST service cv value
+}
+```
Can be written as the following in Icinga 2:
- object CheckCommand "test_customvar" {
- command = "echo "Host CV: $host.vars.CVTEST$ Service CV: $service.vars.CVTEST$\n""
- }
+```
+object CheckCommand "test_customvar" {
+ command = "echo "Host CV: $host.vars.CVTEST$ Service CV: $service.vars.CVTEST$\n""
+}
- object Host "localhost1" {
- import "generic-host"
- check_command = "test_customvar"
- vars.CVTEST = "host cv value"
- }
+object Host "localhost1" {
+ import "generic-host"
+ check_command = "test_customvar"
+ vars.CVTEST = "host cv value"
+}
- object Service "service1" {
- host_name = "localhost1"
- check_command = "test_customvar"
- vars.CVTEST = "service cv value"
- }
+object Service "service1" {
+ host_name = "localhost1"
+ check_command = "test_customvar"
+ vars.CVTEST = "service cv value"
+}
+```
If you are just defining `$CVTEST$` in your command definition, its value depends on the
execution scope -- the host check command will fetch the host attribute value of `vars.CVTEST`
@@ -259,23 +289,27 @@ while the service check command resolves its value to the service attribute attr
Contacts in Icinga 1.x act as users in Icinga 2, but do not have any notification commands specified.
This migration part is explained in the [next chapter](23-migrating-from-icinga-1x.md#manual-config-migration-hints-notifications).
- define contact{
- contact_name testconfig-user
- use generic-user
- alias Icinga Test User
- service_notification_options c,f,s,u
- email icinga@localhost
- }
+```
+define contact{
+ contact_name testconfig-user
+ use generic-user
+ alias Icinga Test User
+ service_notification_options c,f,s,u
+ email icinga@localhost
+}
+```
The `service_notification_options` can be [mapped](23-migrating-from-icinga-1x.md#manual-config-migration-hints-notification-filters)
into generic `state` and `type` filters, if additional notification filtering is required. `alias` gets
renamed to `display_name`.
- object User "testconfig-user" {
- import "generic-user"
- display_name = "Icinga Test User"
- email = "icinga@localhost"
- }
+```
+object User "testconfig-user" {
+ import "generic-user"
+ display_name = "Icinga Test User"
+ email = "icinga@localhost"
+}
+```
This user can be put into usergroups (former contactgroups) or referenced in newly migration notification
objects.
@@ -312,23 +346,28 @@ the host and service notification commands involved.
Generate a new notification object based on these values. Import the generic template based on the type (`host` or `service`).
Assign it to the host or service and set the newly generated notification command name as `command` attribute.
- object Notification "<notificationname>" {
- import "mail-host-notification"
- host_name = "<thishostname>"
- command = "<notificationcommandname>"
-
+```
+object Notification "<notificationname>" {
+ import "mail-host-notification"
+ host_name = "<thishostname>"
+ command = "<notificationcommandname>"
+```
Convert the `notification_options` attribute from Icinga 1.x to Icinga 2 `states` and `types`. Details
[here](23-migrating-from-icinga-1x.md#manual-config-migration-hints-notification-filters). Add the notification period.
- states = [ OK, Warning, Critical ]
- types = [ Recovery, Problem, Custom ]
- period = "24x7"
+```
+ states = [ OK, Warning, Critical ]
+ types = [ Recovery, Problem, Custom ]
+ period = "24x7"
+```
The current contact acts as `users` attribute.
- users = [ "<contactwithnotificationcommand>" ]
- }
+```
+ users = [ "<contactwithnotificationcommand>" ]
+}
+```
Do this in a loop for all notification commands (depending if host or service contact). Once done, dump the
collected notification commands.
@@ -374,53 +413,57 @@ hostgroup. The default `notification_interval` is set to `10` minutes notifying
After 20 minutes (`10*2`, notification_interval * first_notification) the notification is escalated to the
`cg_ops` contactgroup until 60 minutes (`10*6`) have passed.
- define service {
- service_description dep_svc01
- host_name dep_hostsvc01,dep_hostsvc03
- check_command test2
- use generic-service
- notification_interval 10
- contact_groups cg_admin
- }
-
- define hostgroup {
- hostgroup_name hg_svcdep2
- members dep_hostsvc03
- }
-
- # with hostgroup_name and service_description
- define serviceescalation {
- hostgroup_name hg_svcdep2
- service_description dep_svc01
- first_notification 2
- last_notification 6
- contact_groups cg_ops
- }
+```
+define service {
+ service_description dep_svc01
+ host_name dep_hostsvc01,dep_hostsvc03
+ check_command test2
+ use generic-service
+ notification_interval 10
+ contact_groups cg_admin
+}
+
+define hostgroup {
+ hostgroup_name hg_svcdep2
+ members dep_hostsvc03
+}
+
+# with hostgroup_name and service_description
+define serviceescalation {
+ hostgroup_name hg_svcdep2
+ service_description dep_svc01
+ first_notification 2
+ last_notification 6
+ contact_groups cg_ops
+}
+```
In Icinga 2 the service and hostgroup definition will look quite the same. Save the `notification_interval`
and `contact_groups` attribute for an additional notification.
- apply Service "dep_svc01" {
- import "generic-service"
+```
+apply Service "dep_svc01" {
+ import "generic-service"
- check_command = "test2"
+ check_command = "test2"
- assign where host.name == "dep_hostsvc01"
- assign where host.name == "dep_hostsvc03"
- }
+ assign where host.name == "dep_hostsvc01"
+ assign where host.name == "dep_hostsvc03"
+}
- object HostGroup "hg_svcdep2" {
- assign where host.name == "dep_hostsvc03"
- }
+object HostGroup "hg_svcdep2" {
+ assign where host.name == "dep_hostsvc03"
+}
- apply Notification "email" to Service {
- import "service-mail-notification"
+apply Notification "email" to Service {
+ import "service-mail-notification"
- interval = 10m
- user_groups = [ "cg_admin" ]
+ interval = 10m
+ user_groups = [ "cg_admin" ]
- assign where service.name == "dep_svc01" && (host.name == "dep_hostsvc01" || host.name == "dep_hostsvc03")
- }
+ assign where service.name == "dep_svc01" && (host.name == "dep_hostsvc01" || host.name == "dep_hostsvc03")
+}
+```
Calculate the begin and end time for the newly created escalation notification:
@@ -429,19 +472,21 @@ Calculate the begin and end time for the newly created escalation notification:
Assign the notification escalation to the service `dep_svc01` on all hosts in the hostgroup `hg_svcdep2`.
- apply Notification "email-escalation" to Service {
- import "service-mail-notification"
+```
+apply Notification "email-escalation" to Service {
+ import "service-mail-notification"
- interval = 10m
- user_groups = [ "cg_ops" ]
+ interval = 10m
+ user_groups = [ "cg_ops" ]
- times = {
- begin = 20m
- end = 1h
- }
+ times = {
+ begin = 20m
+ end = 1h
+ }
- assign where service.name == "dep_svc01" && "hg_svcdep2" in host.groups
- }
+ assign where service.name == "dep_svc01" && "hg_svcdep2" in host.groups
+}
+```
The assign rule could be made more generic and the notification be applied to more than
just this service belonging to hosts in the matched hostgroup.
@@ -469,41 +514,43 @@ If the state filter matches, you can define whether to disable checks and notifi
The following example describes service dependencies. If you migrate from Icinga 1.x, you will only
want to use the classic `Host-to-Host` and `Service-to-Service` dependency relationships.
- define service {
- service_description dep_svc01
- hostgroup_name hg_svcdep1
- check_command test2
- use generic-service
- }
-
- define service {
- service_description dep_svc02
- hostgroup_name hg_svcdep2
- check_command test2
- use generic-service
- }
-
- define hostgroup {
- hostgroup_name hg_svcdep2
- members host2
- }
-
- define host{
- use linux-server-template
- host_name host1
- address 192.168.1.10
- }
-
- # with hostgroup_name and service_description
- define servicedependency {
- host_name host1
- dependent_hostgroup_name hg_svcdep2
- service_description dep_svc01
- dependent_service_description *
- execution_failure_criteria u,c
- notification_failure_criteria w,u,c
- inherits_parent 1
- }
+```
+define service {
+ service_description dep_svc01
+ hostgroup_name hg_svcdep1
+ check_command test2
+ use generic-service
+}
+
+define service {
+ service_description dep_svc02
+ hostgroup_name hg_svcdep2
+ check_command test2
+ use generic-service
+}
+
+define hostgroup {
+ hostgroup_name hg_svcdep2
+ members host2
+}
+
+define host{
+ use linux-server-template
+ host_name host1
+ address 192.168.1.10
+}
+
+# with hostgroup_name and service_description
+define servicedependency {
+ host_name host1
+ dependent_hostgroup_name hg_svcdep2
+ service_description dep_svc01
+ dependent_service_description *
+ execution_failure_criteria u,c
+ notification_failure_criteria w,u,c
+ inherits_parent 1
+}
+```
Map the dependency attributes accordingly.
@@ -517,44 +564,48 @@ Map the dependency attributes accordingly.
And migrate the host and services.
- object Host "host1" {
- import "linux-server-template"
- address = "192.168.1.10"
- }
+```
+object Host "host1" {
+ import "linux-server-template"
+ address = "192.168.1.10"
+}
- object HostGroup "hg_svcdep2" {
- assign where host.name == "host2"
- }
+object HostGroup "hg_svcdep2" {
+ assign where host.name == "host2"
+}
- apply Service "dep_svc01" {
- import "generic-service"
- check_command = "test2"
+apply Service "dep_svc01" {
+ import "generic-service"
+ check_command = "test2"
- assign where "hp_svcdep1" in host.groups
- }
+ assign where "hp_svcdep1" in host.groups
+}
- apply Service "dep_svc02" {
- import "generic-service"
- check_command = "test2"
+apply Service "dep_svc02" {
+ import "generic-service"
+ check_command = "test2"
- assign where "hp_svcdep2" in host.groups
- }
+ assign where "hp_svcdep2" in host.groups
+}
+```
When it comes to the `execution_failure_criteria` and `notification_failure_criteria` attribute migration,
you will need to map the most common values, in this example `u,c` (`Unknown` and `Critical` will cause the
dependency to fail). Therefore the `Dependency` should be ok on Ok and Warning. `inherits_parents` is always
enabled.
- apply Dependency "all-svc-for-hg-hg_svcdep2-on-host1-dep_svc01" to Service {
- parent_host_name = "host1"
- parent_service_name = "dep_svc01"
+```
+apply Dependency "all-svc-for-hg-hg_svcdep2-on-host1-dep_svc01" to Service {
+ parent_host_name = "host1"
+ parent_service_name = "dep_svc01"
- states = [ Ok, Warning ]
- disable_checks = true
- disable_notifications = true
+ states = [ Ok, Warning ]
+ disable_checks = true
+ disable_notifications = true
- assign where "hg_svcdep2" in host.groups
- }
+ assign where "hg_svcdep2" in host.groups
+}
+```
Host dependencies are explained in the [next chapter](23-migrating-from-icinga-1x.md#manual-config-migration-hints-host-parents).
@@ -570,42 +621,46 @@ virtual machines `vmware-vm1` and `vmware-vm2`.
By default all hosts in the hostgroup `vmware` should get the parent assigned. This isn't really
solvable with Icinga 1.x parents, but only with host dependencies.
- define host{
- use linux-server-template
- host_name vmware-master
- hostgroups vmware
- address 192.168.1.10
- }
-
- define host{
- use linux-server-template
- host_name vmware-vm1
- hostgroups vmware
- address 192.168.27.1
- parents vmware-master
- }
-
- define host{
- use linux-server-template
- host_name vmware-vm2
- hostgroups vmware
- address 192.168.28.1
- parents vmware-master
- }
+```
+define host{
+ use linux-server-template
+ host_name vmware-master
+ hostgroups vmware
+ address 192.168.1.10
+}
+
+define host{
+ use linux-server-template
+ host_name vmware-vm1
+ hostgroups vmware
+ address 192.168.27.1
+ parents vmware-master
+}
+
+define host{
+ use linux-server-template
+ host_name vmware-vm2
+ hostgroups vmware
+ address 192.168.28.1
+ parents vmware-master
+}
+```
By default all hosts in the hostgroup `vmware` should get the parent assigned (but not the `vmware-master`
host itself). This isn't really solvable with Icinga 1.x parents, but only with host dependencies as shown
below:
- define hostdependency {
- dependent_hostgroup_name vmware
- dependent_host_name !vmware-master
- host_name vmware-master
- inherits_parent 1
- notification_failure_criteria d,u
- execution_failure_criteria d,u
- dependency_period testconfig-24x7
- }
+```
+define hostdependency {
+ dependent_hostgroup_name vmware
+ dependent_host_name !vmware-master
+ host_name vmware-master
+ inherits_parent 1
+ notification_failure_criteria d,u
+ execution_failure_criteria d,u
+ dependency_period testconfig-24x7
+}
+```
When migrating to Icinga 2, the parents must be changed to a newly created host dependency.
@@ -620,33 +675,34 @@ Map the following attributes
The Icinga 2 configuration looks like this:
-
- object Host "vmware-master" {
- import "linux-server-template"
- groups += [ "vmware" ]
- address = "192.168.1.10"
- vars.is_vmware_master = true
- }
-
- object Host "vmware-vm1" {
- import "linux-server-template"
- groups += [ "vmware" ]
- address = "192.168.27.1"
- }
-
- object Host "vmware-vm2" {
- import "linux-server-template"
- groups += [ "vmware" ]
- address = "192.168.28.1"
- }
-
- apply Dependency "vmware-master" to Host {
- parent_host_name = "vmware-master"
-
- assign where "vmware" in host.groups
- ignore where host.vars.is_vmware_master
- ignore where host.name == "vmware-master"
- }
+```
+object Host "vmware-master" {
+ import "linux-server-template"
+ groups += [ "vmware" ]
+ address = "192.168.1.10"
+ vars.is_vmware_master = true
+}
+
+object Host "vmware-vm1" {
+ import "linux-server-template"
+ groups += [ "vmware" ]
+ address = "192.168.27.1"
+}
+
+object Host "vmware-vm2" {
+ import "linux-server-template"
+ groups += [ "vmware" ]
+ address = "192.168.28.1"
+}
+
+apply Dependency "vmware-master" to Host {
+ parent_host_name = "vmware-master"
+
+ assign where "vmware" in host.groups
+ ignore where host.vars.is_vmware_master
+ ignore where host.name == "vmware-master"
+}
+```
For easier identification you could add the `vars.is_vmware_master` attribute to the `vmware-master`
host and let the dependency ignore that instead of the hardcoded host name. That's different
@@ -655,29 +711,31 @@ to the Icinga 1.x example and a best practice hint only.
Another way to express the same configuration would be something like:
- object Host "vmware-master" {
- import "linux-server-template"
- groups += [ "vmware" ]
- address = "192.168.1.10"
- }
-
- object Host "vmware-vm1" {
- import "linux-server-template"
- groups += [ "vmware" ]
- address = "192.168.27.1"
- vars.parents = [ "vmware-master" ]
- }
-
- object Host "vmware-vm2" {
- import "linux-server-template"
- groups += [ "vmware" ]
- address = "192.168.28.1"
- vars.parents = [ "vmware-master" ]
- }
-
- apply Dependency "host-to-parent-" for (parent in host.vars.parents) to Host {
- parent_host_name = parent
- }
+```
+object Host "vmware-master" {
+ import "linux-server-template"
+ groups += [ "vmware" ]
+ address = "192.168.1.10"
+}
+
+object Host "vmware-vm1" {
+ import "linux-server-template"
+ groups += [ "vmware" ]
+ address = "192.168.27.1"
+ vars.parents = [ "vmware-master" ]
+}
+
+object Host "vmware-vm2" {
+ import "linux-server-template"
+ groups += [ "vmware" ]
+ address = "192.168.28.1"
+ vars.parents = [ "vmware-master" ]
+}
+
+apply Dependency "host-to-parent-" for (parent in host.vars.parents) to Host {
+ parent_host_name = parent
+}
+```
This example allows finer grained host-to-host dependency, as well as multiple dependency support.
@@ -707,24 +765,30 @@ the Icinga daemon at startup.
icinga.cfg:
- enable_notifications=1
+```
+enable_notifications=1
+```
objects.cfg:
- define service {
- notifications_enabled 0
- }
+```
+define service {
+ notifications_enabled 0
+}
+```
Icinga 2 supports objects and (global) variables, but does not make a difference
between the main configuration file or any other included file.
icinga2.conf:
- const EnableNotifications = true
+```
+const EnableNotifications = true
- object Service "test" {
- enable_notifications = false
- }
+object Service "test" {
+ enable_notifications = false
+}
+```
#### Sample Configuration and ITL <a id="differences-1x-2-sample-configuration-itl"></a>
@@ -765,25 +829,33 @@ suffix in the given directory. Only absolute paths may be used. The `cfg_file`
and `cfg_dir` directives can include the same file twice which leads to
configuration errors in Icinga 1.x.
- cfg_file=/etc/icinga/objects/commands.cfg
- cfg_dir=/etc/icinga/objects
+```
+cfg_file=/etc/icinga/objects/commands.cfg
+cfg_dir=/etc/icinga/objects
+```
Icinga 2 supports wildcard includes and relative paths, e.g. for including
`conf.d/*.conf` in the same directory.
- include "conf.d/*.conf"
+```
+include "conf.d/*.conf"
+```
If you want to include files and directories recursively, you need to define
a separate option and add the directory and an optional pattern.
- include_recursive "conf.d"
+```
+include_recursive "conf.d"
+```
A global search path for includes is available for advanced features like
the Icinga Template Library (ITL) or additional monitoring plugins check
command configuration.
- include <itl>
- include <plugins>
+```
+include <itl>
+include <plugins>
+```
By convention the `.conf` suffix is used for Icinga 2 configuration files.
@@ -796,13 +868,15 @@ set in the `resource.cfg` configuration file in Icinga 1.x. By convention the
Icinga 2 uses global constants instead. In the default config these are
set in the `constants.conf` configuration file:
- /**
- * This file defines global constants which can be used in
- * the other configuration files. At a minimum the
- * PluginDir constant should be defined.
- */
+```
+/**
+ * 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 PluginDir = "/usr/lib/nagios/plugins"
+```
[Global macros](17-language-reference.md#constants) can only be defined once. Trying to modify a
global constant will result in an error.
@@ -825,35 +899,41 @@ Icinga Web 2 for example).
Object names are not specified using attributes (e.g. `service_description` for
services) like in Icinga 1.x but directly after their type definition.
- define service {
- host_name localhost
- service_description ping4
- }
+```
+define service {
+ host_name localhost
+ service_description ping4
+}
- object Service "ping4" {
- host_name = "localhost"
- }
+object Service "ping4" {
+ host_name = "localhost"
+}
+```
### Templates <a id="differences-1x-2-templates"></a>
In Icinga 1.x templates are identified using the `register 0` setting. Icinga 2
uses the `template` identifier:
- template Service "ping4-template" { }
+```
+template Service "ping4-template" { }
+```
Icinga 1.x objects inherit from templates using the `use` attribute.
Icinga 2 uses the keyword `import` with template names in double quotes.
- define service {
- service_description testservice
- use tmpl1,tmpl2,tmpl3
- }
+```
+define service {
+ service_description testservice
+ use tmpl1,tmpl2,tmpl3
+}
- object Service "testservice" {
- import "tmpl1"
- import "tmpl2"
- import "tmpl3"
- }
+object Service "testservice" {
+ import "tmpl1"
+ import "tmpl2"
+ import "tmpl3"
+}
+```
The last template overrides previously set values.
@@ -862,13 +942,15 @@ The last template overrides previously set values.
Icinga 1.x separates attribute and value pairs with whitespaces/tabs. Icinga 2
requires an equal sign (=) between them.
- define service {
- check_interval 5
- }
+```
+define service {
+ check_interval 5
+}
- object Service "test" {
- check_interval = 5m
- }
+object Service "test" {
+ check_interval = 5m
+}
+```
Please note that the default time value is seconds if no duration literal
is given. `check_interval = 5` behaves the same as `check_interval = 5s`.
@@ -899,8 +981,10 @@ attributes for host and service objects are still available in Icinga 2.
Icinga 1.x custom variable attributes must be prefixed using an underscore (`_`).
In Icinga 2 these attributes must be added to the `vars` dictionary as custom attributes.
- vars.dn = "cn=icinga2-dev-host,ou=icinga,ou=main,ou=IcingaConfig,ou=LConf,dc=icinga,dc=org"
- vars.cv = "my custom cmdb description"
+```
+vars.dn = "cn=icinga2-dev-host,ou=icinga,ou=main,ou=IcingaConfig,ou=LConf,dc=icinga,dc=org"
+vars.cv = "my custom cmdb description"
+```
These custom attributes are also used as [command parameters](03-monitoring-basics.md#command-passing-parameters).
@@ -1110,47 +1194,49 @@ Changes to global statistic macros:
The following external commands are not supported:
- CHANGE_*MODATTR
- CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD
- CHANGE_HOST_NOTIFICATION_TIMEPERIOD
- CHANGE_SVC_NOTIFICATION_TIMEPERIOD
- DEL_DOWNTIME_BY_HOSTGROUP_NAME
- DEL_DOWNTIME_BY_START_TIME_COMMENT
- DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST
- DISABLE_CONTACT_HOST_NOTIFICATIONS
- DISABLE_CONTACT_SVC_NOTIFICATIONS
- DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS
- DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS
- DISABLE_FAILURE_PREDICTION
- DISABLE_HOST_AND_CHILD_NOTIFICATIONS
- DISABLE_HOST_FRESHNESS_CHECKS
- DISABLE_NOTIFICATIONS_EXPIRE_TIME
- DISABLE_SERVICE_FRESHNESS_CHECKS
- ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST
- ENABLE_CONTACT_HOST_NOTIFICATIONS
- ENABLE_CONTACT_SVC_NOTIFICATIONS
- ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS
- ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS
- ENABLE_FAILURE_PREDICTION
- ENABLE_HOST_AND_CHILD_NOTIFICATIONS
- ENABLE_HOST_FRESHNESS_CHECKS
- ENABLE_SERVICE_FRESHNESS_CHECKS
- READ_STATE_INFORMATION
- SAVE_STATE_INFORMATION
- SET_HOST_NOTIFICATION_NUMBER
- SET_SVC_NOTIFICATION_NUMBER
- START_ACCEPTING_PASSIVE_HOST_CHECKS
- START_ACCEPTING_PASSIVE_SVC_CHECKS
- START_OBSESSING_OVER_HOST
- START_OBSESSING_OVER_HOST_CHECKS
- START_OBSESSING_OVER_SVC
- START_OBSESSING_OVER_SVC_CHECKS
- STOP_ACCEPTING_PASSIVE_HOST_CHECKS
- STOP_ACCEPTING_PASSIVE_SVC_CHECKS
- STOP_OBSESSING_OVER_HOST
- STOP_OBSESSING_OVER_HOST_CHECKS
- STOP_OBSESSING_OVER_SVC
- STOP_OBSESSING_OVER_SVC_CHECKS
+```
+CHANGE_*MODATTR
+CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD
+CHANGE_HOST_NOTIFICATION_TIMEPERIOD
+CHANGE_SVC_NOTIFICATION_TIMEPERIOD
+DEL_DOWNTIME_BY_HOSTGROUP_NAME
+DEL_DOWNTIME_BY_START_TIME_COMMENT
+DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST
+DISABLE_CONTACT_HOST_NOTIFICATIONS
+DISABLE_CONTACT_SVC_NOTIFICATIONS
+DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS
+DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS
+DISABLE_FAILURE_PREDICTION
+DISABLE_HOST_AND_CHILD_NOTIFICATIONS
+DISABLE_HOST_FRESHNESS_CHECKS
+DISABLE_NOTIFICATIONS_EXPIRE_TIME
+DISABLE_SERVICE_FRESHNESS_CHECKS
+ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST
+ENABLE_CONTACT_HOST_NOTIFICATIONS
+ENABLE_CONTACT_SVC_NOTIFICATIONS
+ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS
+ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS
+ENABLE_FAILURE_PREDICTION
+ENABLE_HOST_AND_CHILD_NOTIFICATIONS
+ENABLE_HOST_FRESHNESS_CHECKS
+ENABLE_SERVICE_FRESHNESS_CHECKS
+READ_STATE_INFORMATION
+SAVE_STATE_INFORMATION
+SET_HOST_NOTIFICATION_NUMBER
+SET_SVC_NOTIFICATION_NUMBER
+START_ACCEPTING_PASSIVE_HOST_CHECKS
+START_ACCEPTING_PASSIVE_SVC_CHECKS
+START_OBSESSING_OVER_HOST
+START_OBSESSING_OVER_HOST_CHECKS
+START_OBSESSING_OVER_SVC
+START_OBSESSING_OVER_SVC_CHECKS
+STOP_ACCEPTING_PASSIVE_HOST_CHECKS
+STOP_ACCEPTING_PASSIVE_SVC_CHECKS
+STOP_OBSESSING_OVER_HOST
+STOP_OBSESSING_OVER_HOST_CHECKS
+STOP_OBSESSING_OVER_SVC
+STOP_OBSESSING_OVER_SVC_CHECKS
+```
### Asynchronous Event Execution <a id="differences-1x-2-async-event-execution"></a>
@@ -1222,27 +1308,31 @@ attribute in the object. The old way of listing all group members in the group's
`members` attribute is available through `assign where` and `ignore where`
expressions by using [group assign](03-monitoring-basics.md#group-assign-intro).
- object Host "web-dev" {
- import "generic-host"
- }
+```
+object Host "web-dev" {
+ import "generic-host"
+}
- object HostGroup "dev-hosts" {
- display_name = "Dev Hosts"
- assign where match("*-dev", host.name)
- }
+object HostGroup "dev-hosts" {
+ display_name = "Dev Hosts"
+ assign where match("*-dev", host.name)
+}
+```
#### Add Service to Hostgroup where Host is Member <a id="differences-1x-2-service-hostgroup-host"></a>
In order to associate a service with all hosts in a host group the [apply](03-monitoring-basics.md#using-apply)
keyword can be used:
- apply Service "ping4" {
- import "generic-service"
+```
+apply Service "ping4" {
+ import "generic-service"
- check_command = "ping4"
+ check_command = "ping4"
- assign where "dev-hosts" in host.groups
- }
+ assign where "dev-hosts" in host.groups
+}
+```
### Notifications <a id="differences-1x-2-notifications"></a>
@@ -1282,12 +1372,16 @@ Icinga 2 attempts to solve that problem in this way
Previously in Icinga 1.x it looked like this:
- service -> (contact, contactgroup) -> notification command
+```
+service -> (contact, contactgroup) -> notification command
+```
In Icinga 2 it will look like this:
- Service -> Notification -> NotificationCommand
- -> User, UserGroup
+```
+Service -> Notification -> NotificationCommand
+ -> User, UserGroup
+```
#### Escalations <a id="differences-1x-2-escalations"></a>
@@ -1295,8 +1389,10 @@ Escalations in Icinga 1.x require a separated object matching on existing
objects. Escalations happen between a defined start and end time which is
calculated from the notification_interval:
- start = notification start + (notification_interval * first_notification)
- end = notification start + (notification_interval * last_notification)
+```
+start = notification start + (notification_interval * first_notification)
+end = notification start + (notification_interval * last_notification)
+```
In theory first_notification and last_notification can be set to readable
numbers. In practice users are manipulating those attributes in combination
@@ -1319,10 +1415,12 @@ Unlike Icinga 1.x with the 'notification_options' attribute with comma-separated
state and type filters, Icinga 2 uses two configuration attributes for that.
All state and type filter use long names OR'd with a pipe together
- notification_options w,u,c,r,f,s
+```
+notification_options w,u,c,r,f,s
- states = [ Warning, Unknown, Critical ]
- types = [ Problem, Recovery, FlappingStart, FlappingEnd, DowntimeStart, DowntimeEnd, DowntimeRemoved ]
+states = [ Warning, Unknown, Critical ]
+types = [ Problem, Recovery, FlappingStart, FlappingEnd, DowntimeStart, DowntimeEnd, DowntimeRemoved ]
+```
Icinga 2 adds more fine-grained type filters for acknowledgements, downtime,
and flapping type (start, end, ...).
@@ -1358,7 +1456,9 @@ The Icinga 1.x flapping detection uses the last 21 states of a service. This
value is hardcoded and cannot be changed. The algorithm on determining a flapping state
is as follows:
- flapping value = (number of actual state changes / number of possible state changes)
+```
+flapping value = (number of actual state changes / number of possible state changes)
+```
The flapping value is then compared to the low and high flapping thresholds.
diff --git a/lib/base/application.cpp b/lib/base/application.cpp
index 2ccf275..be98109 100644
--- a/lib/base/application.cpp
+++ b/lib/base/application.cpp
@@ -374,6 +374,11 @@ bool Application::IsShuttingDown()
return m_ShuttingDown;
}
+bool Application::IsRestarting()
+{
+ return l_Restarting;
+}
+
void Application::OnShutdown()
{
/* Nothing to do here. */
@@ -722,6 +727,9 @@ void Application::SigIntTermHandler(int signum)
*/
void Application::SigUsr1Handler(int)
{
+ Log(LogInformation, "Application")
+ << "Received USR1 signal, reopening application logs.";
+
RequestReopenLogs();
}
diff --git a/lib/base/application.hpp b/lib/base/application.hpp
index d88e65a..1f0d4da 100644
--- a/lib/base/application.hpp
+++ b/lib/base/application.hpp
@@ -75,6 +75,7 @@ public:
static void RequestReopenLogs();
static bool IsShuttingDown();
+ static bool IsRestarting();
static void SetDebuggingSeverity(LogSeverity severity);
static LogSeverity GetDebuggingSeverity();
diff --git a/lib/base/namespace.cpp b/lib/base/namespace.cpp
index 8ca7853..91373fb 100644
--- a/lib/base/namespace.cpp
+++ b/lib/base/namespace.cpp
@@ -37,6 +37,8 @@ Namespace::Namespace(NamespaceBehavior *behavior)
Value Namespace::Get(const String& field) const
{
+ ObjectLock olock(this);
+
Value value;
if (!GetOwnField(field, &value))
BOOST_THROW_EXCEPTION(ScriptError("Namespace does not contain field '" + field + "'"));
@@ -45,6 +47,8 @@ Value Namespace::Get(const String& field) const
bool Namespace::Get(const String& field, Value *value) const
{
+ ObjectLock olock(this);
+
auto nsVal = GetAttribute(field);
if (!nsVal)
@@ -56,16 +60,22 @@ bool Namespace::Get(const String& field, Value *value) const
void Namespace::Set(const String& field, const Value& value, bool overrideFrozen)
{
+ ObjectLock olock(this);
+
return SetFieldByName(field, value, overrideFrozen, DebugInfo());
}
bool Namespace::Contains(const String& field) const
{
+ ObjectLock olock(this);
+
return HasOwnField(field);
}
void Namespace::Remove(const String& field, bool overrideFrozen)
{
+ ObjectLock olock(this);
+
m_Behavior->Remove(this, field, overrideFrozen);
}
@@ -103,6 +113,8 @@ void Namespace::SetAttribute(const String& key, const std::shared_ptr<NamespaceV
Value Namespace::GetFieldByName(const String& field, bool, const DebugInfo& debugInfo) const
{
+ ObjectLock olock(this);
+
auto nsVal = GetAttribute(field);
if (nsVal)
@@ -113,6 +125,8 @@ Value Namespace::GetFieldByName(const String& field, bool, const DebugInfo& debu
void Namespace::SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo)
{
+ ObjectLock olock(this);
+
auto nsVal = GetAttribute(field);
if (!nsVal)
@@ -123,11 +137,15 @@ void Namespace::SetFieldByName(const String& field, const Value& value, bool ove
bool Namespace::HasOwnField(const String& field) const
{
+ ObjectLock olock(this);
+
return GetAttribute(field) != nullptr;
}
bool Namespace::GetOwnField(const String& field, Value *result) const
{
+ ObjectLock olock(this);
+
auto nsVal = GetAttribute(field);
if (!nsVal)
diff --git a/lib/base/serializer.cpp b/lib/base/serializer.cpp
index cb4088e..7b2c844 100644
--- a/lib/base/serializer.cpp
+++ b/lib/base/serializer.cpp
@@ -146,6 +146,8 @@ static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes,
DictionaryData fields;
fields.reserve(type->GetFieldCount() + 1);
+ ObjectLock olock(input);
+
for (int i = 0; i < type->GetFieldCount(); i++) {
Field field = type->GetFieldInfo(i);
@@ -157,7 +159,7 @@ static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes,
Value value = input->GetField(i);
stack.Push(field.Name, value);
- fields.emplace_back(field.Name, SerializeInternal(input->GetField(i), attributeTypes, stack));
+ fields.emplace_back(field.Name, SerializeInternal(value, attributeTypes, stack));
stack.Pop();
}
diff --git a/lib/base/streamlogger.cpp b/lib/base/streamlogger.cpp
index aa1d62c..9ce1a29 100644
--- a/lib/base/streamlogger.cpp
+++ b/lib/base/streamlogger.cpp
@@ -72,10 +72,12 @@ void StreamLogger::BindStream(std::ostream *stream, bool ownsStream)
m_Stream = stream;
m_OwnsStream = ownsStream;
- m_FlushLogTimer = new Timer();
- m_FlushLogTimer->SetInterval(1);
- m_FlushLogTimer->OnTimerExpired.connect(std::bind(&StreamLogger::FlushLogTimerHandler, this));
- m_FlushLogTimer->Start();
+ if (!m_FlushLogTimer) {
+ m_FlushLogTimer = new Timer();
+ m_FlushLogTimer->SetInterval(1);
+ m_FlushLogTimer->OnTimerExpired.connect(std::bind(&StreamLogger::FlushLogTimerHandler, this));
+ m_FlushLogTimer->Start();
+ }
}
/**
diff --git a/lib/base/timer.cpp b/lib/base/timer.cpp
index 2bcff3a..3d3dde7 100644
--- a/lib/base/timer.cpp
+++ b/lib/base/timer.cpp
@@ -127,7 +127,7 @@ void Timer::UninitializeThread()
void Timer::Call()
{
try {
- OnTimerExpired(Timer::Ptr(this));
+ OnTimerExpired(this);
} catch (...) {
InternalReschedule(true);
@@ -318,8 +318,6 @@ void Timer::TimerThreadProc()
continue;
}
- Timer::Ptr ptimer = timer;
-
/* Remove the timer from the list so it doesn't get called again
* until the current call is completed. */
l_Timers.erase(timer);
@@ -329,6 +327,6 @@ void Timer::TimerThreadProc()
lock.unlock();
/* Asynchronously call the timer. */
- Utility::QueueAsyncCallback(std::bind(&Timer::Call, ptimer));
+ Utility::QueueAsyncCallback([timer]() { timer->Call(); });
}
}
diff --git a/lib/base/timer.hpp b/lib/base/timer.hpp
index 96b7753..7950faf 100644
--- a/lib/base/timer.hpp
+++ b/lib/base/timer.hpp
@@ -56,7 +56,7 @@ public:
void Reschedule(double next = -1);
double GetNext() const;
- boost::signals2::signal<void(const Timer::Ptr&)> OnTimerExpired;
+ boost::signals2::signal<void(const Timer * const&)> OnTimerExpired;
private:
double m_Interval{0}; /**< The interval of the timer. */
diff --git a/lib/cli/nodesetupcommand.cpp b/lib/cli/nodesetupcommand.cpp
index 166c842..a90d10c 100644
--- a/lib/cli/nodesetupcommand.cpp
+++ b/lib/cli/nodesetupcommand.cpp
@@ -236,13 +236,13 @@ int NodeSetupCommand::SetupMaster(const boost::program_options::variables_map& v
}
/* update constants.conf with NodeName = CN + TicketSalt = random value */
- if (cn != Utility::GetFQDN()) {
+ if (endpointName != Utility::GetFQDN()) {
Log(LogWarning, "cli")
- << "CN '" << cn << "' does not match the default FQDN '" << Utility::GetFQDN() << "'. Requires update for NodeName constant in constants.conf!";
+ << "CN/Endpoint name '" << endpointName << "' does not match the default FQDN '" << Utility::GetFQDN() << "'. Requires update for NodeName constant in constants.conf!";
}
- NodeUtility::UpdateConstant("NodeName", cn);
- NodeUtility::UpdateConstant("ZoneName", cn);
+ NodeUtility::UpdateConstant("NodeName", endpointName);
+ NodeUtility::UpdateConstant("ZoneName", zoneName);
String salt = RandomString(16);
@@ -536,13 +536,14 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm,
NodeUtility::GenerateNodeIcingaConfig(endpointName, zoneName, parentZoneName, vm["endpoint"].as<std::vector<std::string> >(), globalZones);
/* update constants.conf with NodeName = CN */
- if (cn != Utility::GetFQDN()) {
+ if (endpointName != Utility::GetFQDN()) {
Log(LogWarning, "cli")
- << "CN '" << cn << "' does not match the default FQDN '" << Utility::GetFQDN() << "'. Requires an update for the NodeName constant in constants.conf!";
+ << "CN/Endpoint name '" << endpointName << "' does not match the default FQDN '"
+ << Utility::GetFQDN() << "'. Requires an update for the NodeName constant in constants.conf!";
}
- NodeUtility::UpdateConstant("NodeName", cn);
- NodeUtility::UpdateConstant("ZoneName", vm["zone"].as<std::string>());
+ NodeUtility::UpdateConstant("NodeName", endpointName);
+ NodeUtility::UpdateConstant("ZoneName", zoneName);
if (!ticket.IsEmpty()) {
String ticketPath = ApiListener::GetCertsDir() + "/ticket";
diff --git a/lib/cli/nodewizardcommand.cpp b/lib/cli/nodewizardcommand.cpp
index ea57593..b9865b2 100644
--- a/lib/cli/nodewizardcommand.cpp
+++ b/lib/cli/nodewizardcommand.cpp
@@ -103,7 +103,7 @@ int NodeWizardCommand::Run(const boost::program_options::variables_map& vm,
* 8. copy key information to /var/lib/icinga2/certs
* 9. enable ApiListener feature
* 10. generate zones.conf with endpoints and zone objects
- * 11. set NodeName = cn in constants.conf
+ * 11. set NodeName = cn and ZoneName in constants.conf
* 12. disable conf.d directory?
* 13. reload icinga2, or tell the user to
*/
@@ -570,14 +570,14 @@ wizard_global_zone_loop_start:
/* Generate node configuration. */
NodeUtility::GenerateNodeIcingaConfig(endpointName, zoneName, parentZoneName, endpoints, globalZones);
- if (cn != Utility::GetFQDN()) {
+ if (endpointName != Utility::GetFQDN()) {
Log(LogWarning, "cli")
- << "CN '" << cn << "' does not match the default FQDN '"
+ << "CN/Endpoint name '" << endpointName << "' does not match the default FQDN '"
<< Utility::GetFQDN() << "'. Requires update for NodeName constant in constants.conf!";
}
- NodeUtility::UpdateConstant("NodeName", cn);
- NodeUtility::UpdateConstant("ZoneName", cn);
+ NodeUtility::UpdateConstant("NodeName", endpointName);
+ NodeUtility::UpdateConstant("ZoneName", zoneName);
if (!ticket.IsEmpty()) {
String ticketPath = ApiListener::GetCertsDir() + "/ticket";
@@ -821,8 +821,8 @@ wizard_global_zone_loop_start:
NodeUtility::CreateBackupFile(NodeUtility::GetConstantsConfPath());
- NodeUtility::UpdateConstant("NodeName", cn);
- NodeUtility::UpdateConstant("ZoneName", cn);
+ NodeUtility::UpdateConstant("NodeName", endpointName);
+ NodeUtility::UpdateConstant("ZoneName", zoneName);
String salt = RandomString(16);
diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp
index b8e1a50..44782db 100644
--- a/lib/db_ido/dbconnection.cpp
+++ b/lib/db_ido/dbconnection.cpp
@@ -392,7 +392,26 @@ bool DbConnection::GetStatusUpdate(const DbObject::Ptr& dbobj) const
void DbConnection::UpdateObject(const ConfigObject::Ptr& object)
{
- if (!GetConnected() || Application::IsShuttingDown())
+ bool isShuttingDown = Application::IsShuttingDown();
+ bool isRestarting = Application::IsRestarting();
+
+#ifdef I2_DEBUG
+ if (isShuttingDown || isRestarting) {
+ //Log(LogDebug, "DbConnection")
+ // << "Updating object '" << object->GetName() << "' \t\t active '" << Convert::ToLong(object->IsActive())
+ // << "' shutting down '" << Convert::ToLong(isShuttingDown) << "' restarting '" << Convert::ToLong(isRestarting) << "'.";
+ }
+#endif /* I2_DEBUG */
+
+ /* Wait until a database connection is established on reconnect. */
+ if (!GetConnected())
+ return;
+
+ /* Don't update inactive objects during shutdown/reload/restart.
+ * They would be marked as deleted. This gets triggered with ConfigObject::StopObjects().
+ * During startup/reconnect this is fine, the handler is not active there.
+ */
+ if (isShuttingDown || isRestarting)
return;
DbObject::Ptr dbobj = DbObject::GetOrCreateByObject(object);
@@ -419,7 +438,10 @@ void DbConnection::UpdateObject(const ConfigObject::Ptr& object)
dbobj->SendConfigUpdateLight();
}
} else if (!active) {
- /* Deactivate the deleted object no matter
+ /* This may happen on reload/restart actions too
+ * and is blocked above already.
+ *
+ * Deactivate the deleted object no matter
* which state it had in the database.
*/
DeactivateObject(dbobj);
diff --git a/lib/icinga/timeperiod.cpp b/lib/icinga/timeperiod.cpp
index f71e36c..7ed74c5 100644
--- a/lib/icinga/timeperiod.cpp
+++ b/lib/icinga/timeperiod.cpp
@@ -238,6 +238,7 @@ void TimePeriod::Merge(const TimePeriod::Ptr& timeperiod, bool include)
void TimePeriod::UpdateRegion(double begin, double end, bool clearExisting)
{
if (clearExisting) {
+ ObjectLock olock(this);
SetSegments(new Array());
} else {
if (begin < GetValidEnd())
@@ -363,6 +364,8 @@ void TimePeriod::UpdateTimerHandler()
void TimePeriod::Dump()
{
+ ObjectLock olock(this);
+
Array::Ptr segments = GetSegments();
Log(LogDebug, "TimePeriod")
diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp
index 504ad77..7cf4659 100644
--- a/lib/remote/apilistener.cpp
+++ b/lib/remote/apilistener.cpp
@@ -36,6 +36,12 @@
#include "base/statsfunction.hpp"
#include "base/exception.hpp"
#include <fstream>
+#include <memory>
+#include <openssl/ssl.h>
+#include <openssl/tls1.h>
+#include <openssl/x509.h>
+#include <sstream>
+#include <utility>
using namespace icinga;
@@ -246,7 +252,6 @@ void ApiListener::Start(bool runtimeCreated)
{
boost::mutex::scoped_lock lock(m_LogLock);
- RotateLogFile();
OpenLogFile();
}
@@ -293,6 +298,7 @@ void ApiListener::Stop(bool runtimeDeleted)
{
boost::mutex::scoped_lock lock(m_LogLock);
CloseLogFile();
+ RotateLogFile();
}
RemoveStatusFile();
@@ -694,11 +700,19 @@ void ApiListener::ApiTimerHandler()
for (int ts : files) {
bool need = false;
+ auto localZone (GetLocalEndpoint()->GetZone());
for (const Endpoint::Ptr& endpoint : ConfigType::GetObjectsByType<Endpoint>()) {
if (endpoint == GetLocalEndpoint())
continue;
+ auto zone (endpoint->GetZone());
+
+ /* only care for endpoints in a) the same zone b) our parent zone c) immediate child zones */
+ if (!(zone == localZone || zone == localZone->GetParent() || zone->GetParent() == localZone)) {
+ continue;
+ }
+
if (endpoint->GetLogDuration() >= 0 && ts < now - endpoint->GetLogDuration())
continue;
@@ -1087,13 +1101,11 @@ void ApiListener::RotateLogFile()
String oldpath = GetApiDir() + "log/current";
String newpath = GetApiDir() + "log/" + Convert::ToString(static_cast<int>(ts)+1);
-
-#ifdef _WIN32
- _unlink(newpath.CStr());
-#endif /* _WIN32 */
-
-
- (void) rename(oldpath.CStr(), newpath.CStr());
+ // If the log is being rotated more than once per second,
+ // don't overwrite the previous one, but silently deny rotation.
+ if (!Utility::PathExists(newpath)) {
+ (void) rename(oldpath.CStr(), newpath.CStr());
+ }
}
void ApiListener::LogGlobHandler(std::vector<int>& files, const String& file)
@@ -1146,7 +1158,6 @@ void ApiListener::ReplayLog(const JsonRpcConnection::Ptr& client)
boost::mutex::scoped_lock lock(m_LogLock);
CloseLogFile();
- RotateLogFile();
if (count == -1 || count > 50000) {
OpenLogFile();
@@ -1161,16 +1172,21 @@ void ApiListener::ReplayLog(const JsonRpcConnection::Ptr& client)
Utility::Glob(GetApiDir() + "log/*", std::bind(&ApiListener::LogGlobHandler, std::ref(files), _1), GlobFile);
std::sort(files.begin(), files.end());
+ std::vector<std::pair<int, String>> allFiles;
+
for (int ts : files) {
- String path = GetApiDir() + "log/" + Convert::ToString(ts);
+ if (ts >= peer_ts) {
+ allFiles.emplace_back(ts, GetApiDir() + "log/" + Convert::ToString(ts));
+ }
+ }
- if (ts < peer_ts)
- continue;
+ allFiles.emplace_back(Utility::GetTime() + 1, GetApiDir() + "log/current");
+ for (auto& file : allFiles) {
Log(LogNotice, "ApiListener")
- << "Replaying log: " << path;
+ << "Replaying log: " << file.second;
- auto *fp = new std::fstream(path.CStr(), std::fstream::in | std::fstream::binary);
+ auto *fp = new std::fstream(file.second.CStr(), std::fstream::in | std::fstream::binary);
StdioStream::Ptr logStream = new StdioStream(fp, true);
String message;
@@ -1190,7 +1206,7 @@ void ApiListener::ReplayLog(const JsonRpcConnection::Ptr& client)
pmessage = JsonDecode(message);
} catch (const std::exception&) {
Log(LogWarning, "ApiListener")
- << "Unexpected end-of-file for cluster log: " << path;
+ << "Unexpected end-of-file for cluster log: " << file.second;
/* Log files may be incomplete or corrupted. This is perfectly OK. */
break;
@@ -1227,8 +1243,8 @@ void ApiListener::ReplayLog(const JsonRpcConnection::Ptr& client)
peer_ts = pmessage->Get("timestamp");
- if (ts > logpos_ts + 10) {
- logpos_ts = ts;
+ if (file.first > logpos_ts + 10) {
+ logpos_ts = file.first;
Dictionary::Ptr lmessage = new Dictionary({
{ "jsonrpc", "2.0" },
@@ -1250,9 +1266,10 @@ void ApiListener::ReplayLog(const JsonRpcConnection::Ptr& client)
Log(LogInformation, "ApiListener")
<< "Replayed " << count << " messages.";
}
-
- Log(LogNotice, "ApiListener")
- << "Replayed " << count << " messages.";
+ else {
+ Log(LogNotice, "ApiListener")
+ << "Replayed " << count << " messages.";
+ }
if (last_sync) {
{
diff --git a/lib/remote/eventqueue.cpp b/lib/remote/eventqueue.cpp
index d724517..436bd7d 100644
--- a/lib/remote/eventqueue.cpp
+++ b/lib/remote/eventqueue.cpp
@@ -37,7 +37,8 @@ bool EventQueue::CanProcessEvent(const String& type) const
void EventQueue::ProcessEvent(const Dictionary::Ptr& event)
{
- ScriptFrame frame(true);
+ Namespace::Ptr frameNS = new Namespace();
+ ScriptFrame frame(true, frameNS);
frame.Sandboxed = true;
try {
diff --git a/lib/remote/filterutility.cpp b/lib/remote/filterutility.cpp
index cf6cb9e..7ef6f65 100644
--- a/lib/remote/filterutility.cpp
+++ b/lib/remote/filterutility.cpp
@@ -106,6 +106,8 @@ bool FilterUtility::EvaluateFilter(ScriptFrame& frame, Expression *filter,
ASSERT(frame.Self.IsObjectType<Namespace>());
frameNS = frame.Self;
+
+ ASSERT(frameNS != ScriptGlobal::GetGlobals());
}
frameNS->Set("obj", target);
@@ -171,7 +173,7 @@ void FilterUtility::CheckPermission(const ApiUser::Ptr& user, const String& perm
if (filter && permissionFilter) {
std::vector<std::unique_ptr<Expression> > args;
- args.emplace_back(new GetScopeExpression(ScopeLocal));
+ args.emplace_back(new GetScopeExpression(ScopeThis));
std::unique_ptr<Expression> indexer{new IndexerExpression(std::unique_ptr<Expression>(MakeLiteral(filter)), std::unique_ptr<Expression>(MakeLiteral("call")))};
FunctionCallExpression *fexpr = new FunctionCallExpression(std::move(indexer), std::move(args));
@@ -205,7 +207,8 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
Expression *permissionFilter;
CheckPermission(user, qd.Permission, &permissionFilter);
- ScriptFrame permissionFrame(true);
+ Namespace::Ptr permissionFrameNS = new Namespace();
+ ScriptFrame permissionFrame(false, permissionFrameNS);
for (const String& type : qd.Types) {
String attr = type;
@@ -255,9 +258,9 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
if (qd.Types.find(type) == qd.Types.end())
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type specified for this query."));
- ScriptFrame frame(true);
- frame.Sandboxed = true;
Namespace::Ptr frameNS = new Namespace();
+ ScriptFrame frame(false, frameNS);
+ frame.Sandboxed = true;
if (query->Contains("filter")) {
String filter = HttpUtility::GetLastParameter(query, "filter");
@@ -271,8 +274,6 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
}
}
- frame.Self = frameNS;
-
provider->FindTargets(type, std::bind(&FilteredAddTarget,
std::ref(permissionFrame), permissionFilter,
std::ref(frame), &*ufilter, std::ref(result), variableName, _1));
diff --git a/lib/remote/httpserverconnection.cpp b/lib/remote/httpserverconnection.cpp
index c0550bf..dc4637d 100644
--- a/lib/remote/httpserverconnection.cpp
+++ b/lib/remote/httpserverconnection.cpp
@@ -353,7 +353,7 @@ void HttpServerConnection::DataAvailableHandler()
if (!m_Stream->IsEof()) {
boost::recursive_mutex::scoped_try_lock lock(m_DataHandlerMutex);
if (!lock.owns_lock()) {
- Log(LogInformation, "HttpServerConnection", "Unable to process available data, they're already being processed in another thread");
+ Log(LogNotice, "HttpServerConnection", "Unable to process available data, they're already being processed in another thread");
return;
}
diff --git a/test/base-timer.cpp b/test/base-timer.cpp
index a9500a2..81b303f 100644
--- a/test/base-timer.cpp
+++ b/test/base-timer.cpp
@@ -41,7 +41,7 @@ BOOST_AUTO_TEST_CASE(interval)
int counter = 0;
-static void Callback(const Timer::Ptr&)
+static void Callback(const Timer * const&)
{
counter++;
}