]> granicus.if.org Git - icinga2/blob - doc/3-monitoring-basics.md
Add notifications (e.g. pagerduty) to 'addons & plugins' docs
[icinga2] / doc / 3-monitoring-basics.md
1 # <a id="monitoring-basics"></a> Monitoring Basics
2
3 This part of the Icinga 2 documentation provides an overview of all the basic
4 monitoring concepts you need to know to run Icinga 2.
5 Keep in mind these examples are made with a linux server in mind, if you are
6 using Windows you will need to change the services accordingly. See the [ITL reference](7-icinga-template-library.md#windows-plugins)
7  for further information.
8
9 ## <a id="hosts-services"></a> Hosts and Services
10
11 Icinga 2 can be used to monitor the availability of hosts and services. Hosts
12 and services can be virtually anything which can be checked in some way:
13
14 * Network services (HTTP, SMTP, SNMP, SSH, etc.)
15 * Printers
16 * Switches / routers
17 * Temperature sensors
18 * Other local or network-accessible services
19
20 Host objects provide a mechanism to group services that are running
21 on the same physical device.
22
23 Here is an example of a host object which defines two child services:
24
25     object Host "my-server1" {
26       address = "10.0.0.1"
27       check_command = "hostalive"
28     }
29
30     object Service "ping4" {
31       host_name = "my-server1"
32       check_command = "ping4"
33     }
34
35     object Service "http" {
36       host_name = "my-server1"
37       check_command = "http"
38     }
39
40 The example creates two services `ping4` and `http` which belong to the
41 host `my-server1`.
42
43 It also specifies that the host should perform its own check using the `hostalive`
44 check command.
45
46 The `address` attribute is used by check commands to determine which network
47 address is associated with the host object.
48
49 Details on troubleshooting check problems can be found [here](16-troubleshooting.md#troubleshooting).
50
51 ### <a id="host-states"></a> Host States
52
53 Hosts can be in any of the following states:
54
55   Name        | Description
56   ------------|--------------
57   UP          | The host is available.
58   DOWN        | The host is unavailable.
59
60 ### <a id="service-states"></a> Service States
61
62 Services can be in any of the following states:
63
64   Name        | Description
65   ------------|--------------
66   OK          | The service is working properly.
67   WARNING     | The service is experiencing some problems but is still considered to be in working condition.
68   CRITICAL    | The service is in a critical state.
69   UNKNOWN     | The check could not determine the service's state.
70
71 ### <a id="hard-soft-states"></a> Hard and Soft States
72
73 When detecting a problem with a host/service Icinga re-checks the object a number of
74 times (based on the `max_check_attempts` and `retry_interval` settings) before sending
75 notifications. This ensures that no unnecessary notifications are sent for
76 transient failures. During this time the object is in a `SOFT` state.
77
78 After all re-checks have been executed and the object is still in a non-OK
79 state the host/service switches to a `HARD` state and notifications are sent.
80
81   Name        | Description
82   ------------|--------------
83   HARD        | The host/service's state hasn't recently changed.
84   SOFT        | The host/service has recently changed state and is being re-checked.
85
86 ### <a id="host-service-checks"></a> Host and Service Checks
87
88 Hosts and services determine their state by running checks in a regular interval.
89
90     object Host "router" {
91       check_command = "hostalive"
92       address = "10.0.0.1"
93     }
94
95 The `hostalive` command is one of several built-in check commands. It sends ICMP
96 echo requests to the IP address specified in the `address` attribute to determine
97 whether a host is online.
98
99 A number of other [built-in check commands](7-icinga-template-library.md#plugin-check-commands) are also
100 available. In addition to these commands the next few chapters will explain in
101 detail how to set up your own check commands.
102
103
104 ## <a id="object-inheritance-using-templates"></a> Templates
105
106 Templates may be used to apply a set of identical attributes to more than one
107 object:
108
109     template Service "generic-service" {
110       max_check_attempts = 3
111       check_interval = 5m
112       retry_interval = 1m
113       enable_perfdata = true
114     }
115
116     apply Service "ping4" {
117       import "generic-service"
118
119       check_command = "ping4"
120
121       assign where host.address
122     }
123
124     apply Service "ping6" {
125       import "generic-service"
126
127       check_command = "ping6"
128
129       assign where host.address6
130     }
131
132
133 In this example the `ping4` and `ping6` services inherit properties from the
134 template `generic-service`.
135
136 Objects as well as templates themselves can import an arbitrary number of
137 other templates. Attributes inherited from a template can be overridden in the
138 object if necessary.
139
140 You can also import existing non-template objects. Note that templates
141 and objects share the same namespace, i.e. you can't define a template
142 that has the same name like an object.
143
144
145 ## <a id="custom-attributes"></a> Custom Attributes
146
147 In addition to built-in attributes you can define your own attributes:
148
149     object Host "localhost" {
150       vars.ssh_port = 2222
151     }
152
153 Valid values for custom attributes include:
154
155 * [Strings](19-language-reference.md#string-literals), [numbers](19-language-reference.md#numeric-literals) and [booleans](19-language-reference.md#boolean-literals)
156 * [Arrays](19-language-reference.md#array) and [dictionaries](19-language-reference.md#dictionary)
157 * [Functions](3-monitoring-basics.md#custom-attributes-functions)
158
159 ### <a id="custom-attributes-functions"></a> Functions as Custom Attributes
160
161 Icinga 2 lets you specify [functions](19-language-reference.md#functions) for custom attributes.
162 The special case here is that whenever Icinga 2 needs the value for such a custom attribute it runs
163 the function and uses whatever value the function returns:
164
165     object CheckCommand "random-value" {
166       import "plugin-check-command"
167
168       command = [ PluginDir + "/check_dummy", "0", "$text$" ]
169
170       vars.text = {{ Math.random() * 100 }}
171     }
172
173 This example uses the [abbreviated lambda syntax](19-language-reference.md#nullary-lambdas).
174
175 These functions have access to a number of variables:
176
177   Variable     | Description
178   -------------|---------------
179   user         | The User object (for notifications).
180   service      | The Service object (for service checks/notifications/event handlers).
181   host         | The Host object.
182   command      | The command object (e.g. a CheckCommand object for checks).
183
184 Here's an example:
185
186     vars.text = {{ host.check_interval }}
187
188 In addition to these variables the `macro` function can be used to retrieve the
189 value of arbitrary macro expressions:
190
191     vars.text = {{
192       if (macro("$address$") == "127.0.0.1") {
193         log("Running a check for localhost!")
194       }
195
196       return "Some text"
197     }}
198
199 Acessing object attributes at runtime inside these functions is described in the
200 [advanced topics](5-advanced-topics.md#access-object-attributes-at-runtime) chapter.
201
202 ## <a id="runtime-macros"></a> Runtime Macros
203
204 Macros can be used to access other objects' attributes at runtime. For example they
205 are used in command definitions to figure out which IP address a check should be
206 run against:
207
208     object CheckCommand "my-ping" {
209       import "plugin-check-command"
210
211       command = [ PluginDir + "/check_ping", "-H", "$ping_address$" ]
212
213       arguments = {
214         "-w" = "$ping_wrta$,$ping_wpl$%"
215         "-c" = "$ping_crta$,$ping_cpl$%"
216         "-p" = "$ping_packets$"
217       }
218
219       vars.ping_address = "$address$"
220
221       vars.ping_wrta = 100
222       vars.ping_wpl = 5
223
224       vars.ping_crta = 250
225       vars.ping_cpl = 10
226
227       vars.ping_packets = 5
228     }
229
230     object Host "router" {
231       check_command = "my-ping"
232       address = "10.0.0.1"
233     }
234
235 In this example we are using the `$address$` macro to refer to the host's `address`
236 attribute.
237
238 We can also directly refer to custom attributes, e.g. by using `$ping_wrta$`. Icinga
239 automatically tries to find the closest match for the attribute you specified. The
240 exact rules for this are explained in the next section.
241
242
243 ### <a id="macro-evaluation-order"></a> Evaluation Order
244
245 When executing commands Icinga 2 checks the following objects in this order to look
246 up macros and their respective values:
247
248 1. User object (only for notifications)
249 2. Service object
250 3. Host object
251 4. Command object
252 5. Global custom attributes in the `Vars` constant
253
254 This execution order allows you to define default values for custom attributes
255 in your command objects.
256
257 Here's how you can override the custom attribute `ping_packets` from the previous
258 example:
259
260     object Service "ping" {
261       host_name = "localhost"
262       check_command = "my-ping"
263
264       vars.ping_packets = 10 // Overrides the default value of 5 given in the command
265     }
266
267 If a custom attribute isn't defined anywhere an empty value is used and a warning is
268 written to the Icinga 2 log.
269
270 You can also directly refer to a specific attribute - thereby ignoring these evaluation
271 rules - by specifying the full attribute name:
272
273     $service.vars.ping_wrta$
274
275 This retrieves the value of the `ping_wrta` custom attribute for the service. This
276 returns an empty value if the service does not have such a custom attribute no matter
277 whether another object such as the host has this attribute.
278
279
280 ### <a id="host-runtime-macros"></a> Host Runtime Macros
281
282 The following host custom attributes are available in all commands that are executed for
283 hosts or services:
284
285   Name                         | Description
286   -----------------------------|--------------
287   host.name                    | The name of the host object.
288   host.display_name            | The value of the `display_name` attribute.
289   host.state                   | The host's current state. Can be one of `UNREACHABLE`, `UP` and `DOWN`.
290   host.state_id                | The host's current state. Can be one of `0` (up), `1` (down) and `2` (unreachable).
291   host.state_type              | The host's current state type. Can be one of `SOFT` and `HARD`.
292   host.check_attempt           | The current check attempt number.
293   host.max_check_attempts      | The maximum number of checks which are executed before changing to a hard state.
294   host.last_state              | The host's previous state. Can be one of `UNREACHABLE`, `UP` and `DOWN`.
295   host.last_state_id           | The host's previous state. Can be one of `0` (up), `1` (down) and `2` (unreachable).
296   host.last_state_type         | The host's previous state type. Can be one of `SOFT` and `HARD`.
297   host.last_state_change       | The last state change's timestamp.
298   host.downtime_depth          | The number of active downtimes.
299   host.duration_sec            | The time since the last state change.
300   host.latency                 | The host's check latency.
301   host.execution_time          | The host's check execution time.
302   host.output                  | The last check's output.
303   host.perfdata                | The last check's performance data.
304   host.last_check              | The timestamp when the last check was executed.
305   host.check_source            | The monitoring instance that performed the last check.
306   host.num_services            | Number of services associated with the host.
307   host.num_services_ok         | Number of services associated with the host which are in an `OK` state.
308   host.num_services_warning    | Number of services associated with the host which are in a `WARNING` state.
309   host.num_services_unknown    | Number of services associated with the host which are in an `UNKNOWN` state.
310   host.num_services_critical   | Number of services associated with the host which are in a `CRITICAL` state.
311
312 ### <a id="service-runtime-macros"></a> Service Runtime Macros
313
314 The following service macros are available in all commands that are executed for
315 services:
316
317   Name                       | Description
318   ---------------------------|--------------
319   service.name               | The short name of the service object.
320   service.display_name       | The value of the `display_name` attribute.
321   service.check_command      | The short name of the command along with any arguments to be used for the check.
322   service.state              | The service's current state. Can be one of `OK`, `WARNING`, `CRITICAL` and `UNKNOWN`.
323   service.state_id           | The service's current state. Can be one of `0` (ok), `1` (warning), `2` (critical) and `3` (unknown).
324   service.state_type         | The service's current state type. Can be one of `SOFT` and `HARD`.
325   service.check_attempt      | The current check attempt number.
326   service.max_check_attempts | The maximum number of checks which are executed before changing to a hard state.
327   service.last_state         | The service's previous state. Can be one of `OK`, `WARNING`, `CRITICAL` and `UNKNOWN`.
328   service.last_state_id      | The service's previous state. Can be one of `0` (ok), `1` (warning), `2` (critical) and `3` (unknown).
329   service.last_state_type    | The service's previous state type. Can be one of `SOFT` and `HARD`.
330   service.last_state_change  | The last state change's timestamp.
331   service.downtime_depth     | The number of active downtimes.
332   service.duration_sec       | The time since the last state change.
333   service.latency            | The service's check latency.
334   service.execution_time     | The service's check execution time.
335   service.output             | The last check's output.
336   service.perfdata           | The last check's performance data.
337   service.last_check         | The timestamp when the last check was executed.
338   service.check_source       | The monitoring instance that performed the last check.
339
340 ### <a id="command-runtime-macros"></a> Command Runtime Macros
341
342 The following custom attributes are available in all commands:
343
344   Name                   | Description
345   -----------------------|--------------
346   command.name           | The name of the command object.
347
348 ### <a id="user-runtime-macros"></a> User Runtime Macros
349
350 The following custom attributes are available in all commands that are executed for
351 users:
352
353   Name                   | Description
354   -----------------------|--------------
355   user.name              | The name of the user object.
356   user.display_name      | The value of the display_name attribute.
357
358 ### <a id="notification-runtime-macros"></a> Notification Runtime Macros
359
360   Name                   | Description
361   -----------------------|--------------
362   notification.type      | The type of the notification.
363   notification.author    | The author of the notification comment, if existing.
364   notification.comment   | The comment of the notification, if existing.
365
366 ### <a id="global-runtime-macros"></a> Global Runtime Macros
367
368 The following macros are available in all executed commands:
369
370   Name                   | Description
371   -----------------------|--------------
372   icinga.timet           | Current UNIX timestamp.
373   icinga.long_date_time  | Current date and time including timezone information. Example: `2014-01-03 11:23:08 +0000`
374   icinga.short_date_time | Current date and time. Example: `2014-01-03 11:23:08`
375   icinga.date            | Current date. Example: `2014-01-03`
376   icinga.time            | Current time including timezone information. Example: `11:23:08 +0000`
377   icinga.uptime          | Current uptime of the Icinga 2 process.
378
379 The following macros provide global statistics:
380
381   Name                              | Description
382   ----------------------------------|--------------
383   icinga.num_services_ok            | Current number of services in state 'OK'.
384   icinga.num_services_warning       | Current number of services in state 'Warning'.
385   icinga.num_services_critical      | Current number of services in state 'Critical'.
386   icinga.num_services_unknown       | Current number of services in state 'Unknown'.
387   icinga.num_services_pending       | Current number of pending services.
388   icinga.num_services_unreachable   | Current number of unreachable services.
389   icinga.num_services_flapping      | Current number of flapping services.
390   icinga.num_services_in_downtime   | Current number of services in downtime.
391   icinga.num_services_acknowledged  | Current number of acknowledged service problems.
392   icinga.num_hosts_up               | Current number of hosts in state 'Up'.
393   icinga.num_hosts_down             | Current number of hosts in state 'Down'.
394   icinga.num_hosts_unreachable      | Current number of unreachable hosts.
395   icinga.num_hosts_flapping         | Current number of flapping hosts.
396   icinga.num_hosts_in_downtime      | Current number of hosts in downtime.
397   icinga.num_hosts_acknowledged     | Current number of acknowledged host problems.
398
399
400 ## <a id="using-apply"></a> Apply Rules
401
402 Instead of assigning each object ([Service](6-object-types.md#objecttype-service),
403 [Notification](6-object-types.md#objecttype-notification), [Dependency](6-object-types.md#objecttype-dependency),
404 [ScheduledDowntime](6-object-types.md#objecttype-scheduleddowntime))
405 based on attribute identifiers for example `host_name` objects can be [applied](19-language-reference.md#apply).
406
407 Before you start using the apply rules keep the following in mind:
408
409 * Define the best match.
410     * A set of unique [custom attributes](3-monitoring-basics.md#custom-attributes) for these hosts/services?
411     * Or [group](3-monitoring-basics.md#groups) memberships, e.g. a host being a member of a hostgroup, applying services to it?
412     * A generic pattern [match](19-language-reference.md#function-calls) on the host/service name?
413     * [Multiple expressions combined](3-monitoring-basics.md#using-apply-expressions) with `&&` or `||` [operators](19-language-reference.md#expression-operators)
414 * All expressions must return a boolean value (an empty string is equal to `false` e.g.)
415
416 > **Note**
417 >
418 > You can set/override object attributes in apply rules using the respectively available
419 > objects in that scope (host and/or service objects).
420
421 [Custom attributes](3-monitoring-basics.md#custom-attributes) can also store nested dictionaries and arrays. That way you can use them
422 for not only matching for their existance or values in apply expressions, but also assign
423 ("inherit") their values into the generated objected from apply rules.
424
425 * [Apply services to hosts](3-monitoring-basics.md#using-apply-services)
426 * [Apply notifications to hosts and services](3-monitoring-basics.md#using-apply-notifications)
427 * [Apply dependencies to hosts and services](3-monitoring-basics.md#using-apply-dependencies)
428 * [Apply scheduled downtimes to hosts and services](3-monitoring-basics.md#using-apply-scheduledowntimes)
429
430 A more advanced example is using [apply with for loops on arrays or
431 dictionaries](3-monitoring-basics.md#using-apply-for) for example provided by
432 [custom atttributes](3-monitoring-basics.md#custom-attributes) or groups.
433
434 > **Tip**
435 >
436 > Building configuration in that dynamic way requires detailed information
437 > of the generated objects. Use the `object list` [CLI command](8-cli-commands.md#cli-command-object)
438 > after successful [configuration validation](8-cli-commands.md#config-validation).
439
440
441 ### <a id="using-apply-expressions"></a> Apply Rules Expressions
442
443 You can use simple or advanced combinations of apply rule expressions. Each
444 expression must evaluate into the boolean `true` value. An empty string
445 will be for instance interpreted as `false`. In a similar fashion undefined
446 attributes will return `false`.
447
448 Returns `false`:
449
450     assign where host.vars.attribute_does_not_exist
451
452 Multiple `assign where` condition rows are evaluated as `OR` condition.
453
454 You can combine multiple expressions for matching only a subset of objects. In some cases,
455 you want to be able to add more than one assign/ignore where expression which matches
456 a specific condition. To achieve this you can use the logical `and` and `or` operators.
457
458
459 Match all `*mysql*` patterns in the host name and (`&&`) custom attribute `prod_mysql_db`
460 matches the `db-*` pattern. All hosts with the custom attribute `test_server` set to `true`
461 should be ignored, or any host name ending with `*internal` pattern.
462
463     object HostGroup "mysql-server" {
464       display_name = "MySQL Server"
465
466       assign where match("*mysql*", host.name) && match("db-*", host.vars.prod_mysql_db)
467       ignore where host.vars.test_server == true
468       ignore where match("*internal", host.name)
469     }
470
471 Similar example for advanced notification apply rule filters: If the service
472 attribute `notes` contains the `has gold support 24x7` string `AND` one of the
473 two condition passes: Either the `customer` host custom attribute is set to `customer-xy`
474 `OR` the host custom attribute `always_notify` is set to `true`.
475
476 The notification is ignored for services whose host name ends with `*internal`
477 `OR` the `priority` custom attribute is [less than](19-language-reference.md#expression-operators) `2`.
478
479     template Notification "cust-xy-notification" {
480       users = [ "noc-xy", "mgmt-xy" ]
481       command = "mail-service-notification"
482     }
483
484     apply Notification "notify-cust-xy-mysql" to Service {
485       import "cust-xy-notification"
486
487       assign where match("*has gold support 24x7*", service.notes) && (host.vars.customer == "customer-xy" || host.vars.always_notify == true)
488       ignore where match("*internal", host.name) || (service.vars.priority < 2 && host.vars.is_clustered == true)
489     }
490
491
492
493 ### <a id="using-apply-services"></a> Apply Services to Hosts
494
495 The sample configuration already includes a detailed example in [hosts.conf](4-configuring-icinga-2.md#hosts-conf)
496 and [services.conf](4-configuring-icinga-2.md#services-conf) for this use case.
497
498 The example for `ssh` applies a service object to all hosts with the `address`
499 attribute being defined and the custom attribute `os` set to the string `Linux` in `vars`.
500
501     apply Service "ssh" {
502       import "generic-service"
503
504       check_command = "ssh"
505
506       assign where host.address && host.vars.os == "Linux"
507     }
508
509
510 Other detailed scenario examples are used in their respective chapters, for example
511 [apply services with custom command arguments](3-monitoring-basics.md#command-passing-parameters).
512
513 ### <a id="using-apply-notifications"></a> Apply Notifications to Hosts and Services
514
515 Notifications are applied to specific targets (`Host` or `Service`) and work in a similar
516 manner:
517
518
519     apply Notification "mail-noc" to Service {
520       import "mail-service-notification"
521
522       user_groups = [ "noc" ]
523
524       assign where host.vars.notification.mail
525     }
526
527
528 In this example the `mail-noc` notification will be created as object for all services having the
529 `notification.mail` custom attribute defined. The notification command is set to `mail-service-notification`
530 and all members of the user group `noc` will get notified.
531
532 ### <a id="using-apply-dependencies"></a> Apply Dependencies to Hosts and Services
533
534 Detailed examples can be found in the [dependencies](3-monitoring-basics.md#dependencies) chapter.
535
536 ### <a id="using-apply-scheduledowntimes"></a> Apply Recurring Downtimes to Hosts and Services
537
538 The sample configuration includes an example in [downtimes.conf](4-configuring-icinga-2.md#downtimes-conf).
539
540 Detailed examples can be found in the [recurring downtimes](5-advanced-topics.md#recurring-downtimes) chapter.
541
542
543 ### <a id="using-apply-for"></a> Using Apply For Rules
544
545 Next to the standard way of using [apply rules](3-monitoring-basics.md#using-apply)
546 there is the requirement of generating apply rules objects based on set (array or
547 dictionary).
548
549 The sample configuration already includes a detailed example in [hosts.conf](4-configuring-icinga-2.md#hosts-conf)
550 and [services.conf](4-configuring-icinga-2.md#services-conf) for this use case.
551
552 Take the following example: A host provides the snmp oids for different service check
553 types. This could look like the following example:
554
555     object Host "router-v6" {
556       check_command = "hostalive"
557       address6 = "::1"
558
559       vars.oids["if01"] = "1.1.1.1.1"
560       vars.oids["temp"] = "1.1.1.1.2"
561       vars.oids["bgp"] = "1.1.1.1.5"
562     }
563
564 Now we want to create service checks for `if01` and `temp` but not `bgp`.
565 Furthermore we want to pass the snmp oid stored as dictionary value to the
566 custom attribute called `vars.snmp_oid` - this is the command argument required
567 by the [snmp](7-icinga-template-library.md#plugin-check-command-snmp) check command.
568 The service's `display_name` should be set to the identifier inside the dictionary.
569
570     apply Service for (identifier => oid in host.vars.oids) {
571       check_command = "snmp"
572       display_name = identifier
573       vars.snmp_oid = oid
574
575       ignore where identifier == "bgp" //don't generate service for bgp checks
576     }
577
578 Icinga 2 evaluates the `apply for` rule for all objects with the custom attribute
579 `oids` set. It then iterates over all list items inside the `for` loop and evaluates the
580 `assign/ignore where` expressions. You can access the loop variable
581 in these expressions, e.g. for ignoring certain values.
582 In this example we'd ignore the `bgp` identifier and avoid generating an unwanted service.
583 We could extend the configuration by also matching the `oid` value on certain regex/wildcard
584 patterns for example.
585
586 > **Note**
587 >
588 > You don't need an `assign where` expression only checking for existance
589 > of the custom attribute.
590
591 That way you'll save duplicated apply rules by combining them into one
592 generic `apply for` rule generating the object name with or without a prefix.
593
594
595 #### <a id="using-apply-for-custom-attribute-override"></a> Apply For and Custom Attribute Override
596
597 Imagine a different more advanced example: You are monitoring your network device (host)
598 with many interfaces (services). The following requirements/problems apply:
599
600 * Each interface service check should be named with a prefix and a name defined in your host object (which could be generated from your CMDB, etc)
601 * Each interface has its own vlan tag
602 * Some interfaces have QoS enabled
603 * Additional attributes such as `display_name` or `notes, `notes_url` and `action_url` must be
604 dynamically generated
605
606
607 Tip: Define the snmp community as global constant in your [constants.conf](4-configuring-icinga-2.md#constants-conf) file.
608
609     const IftrafficSnmpCommunity = "public"
610
611 By defining the `interfaces` dictionary with three example interfaces on the `cisco-catalyst-6509-34`
612 host object, you'll make sure to pass the [custom attribute](3-monitoring-basics.md#custom-attributes)
613 storage required by the for loop in the service apply rule.
614
615     object Host "cisco-catalyst-6509-34" {
616       import "generic-host"
617       display_name = "Catalyst 6509 #34 VIE21"
618       address = "127.0.1.4"
619
620       /* "GigabitEthernet0/2" is the interface name,
621        * and key name in service apply for later on
622        */
623       vars.interfaces["GigabitEthernet0/2"] = {
624          /* define all custom attributes with the
625           * same name required for command parameters/arguments
626           * in service apply (look into your CheckCommand definition)
627           */
628          iftraffic_units = "g"
629          iftraffic_community = IftrafficSnmpCommunity
630          iftraffic_bandwidth = 1
631          vlan = "internal"
632          qos = "disabled"
633       }
634       vars.interfaces["GigabitEthernet0/4"] = {
635          iftraffic_units = "g"
636          //iftraffic_community = IftrafficSnmpCommunity
637          iftraffic_bandwidth = 1
638          vlan = "renote"
639          qos = "enabled"
640       }
641       vars.interfaces["MgmtInterface1"] = {
642          iftraffic_community = IftrafficSnmpCommunity
643          vlan = "mgmt"
644          interface_address = "127.99.0.100" #special management ip
645       }
646     }
647
648 You can also omit the `"if-"` string, then all generated service names are directly
649 taken from the `if_name` variable value.
650
651 The config dictionary contains all key-value pairs for the specific interface in one
652 loop cycle, like `iftraffic_units`, `vlan`, and `qos` for the specified interface.
653
654 You can either map the custom attributes from the `interface_config` dictionary to
655 local custom attributes stashed into `vars`. If the names match the required command
656 argument parameters already (for example `iftraffic_units`), you could also add the
657 `interface_config` dictionary to the `vars` dictionary using the `+=` operator.
658
659 After `vars` is fully populated, all object attributes can be set calculated from
660 provided host attributes. For strings, you can use string concatention with the `+` operator.
661
662 You can also specifiy the display_name, check command, interval, notes, notes_url, action_url, etc.
663 attributes that way. Attribute strings can be [concatenated](19-language-reference.md#expression-operators),
664 for example for adding a more detailed service `display_name`.
665
666 This example also uses [if conditions](19-language-reference.md#conditional-statements)
667 if specific values are not set, adding a local default value.
668 The other way around you can override specific custom attributes inherited from a service template,
669 if set.
670
671     /* loop over the host.vars.interfaces dictionary
672      * for (key => value in dict) means `interface_name` as key
673      * and `interface_config` as value. Access config attributes
674      * with the indexer (`.`) character.
675      */
676     apply Service "if-" for (interface_name => interface_config in host.vars.interfaces) {
677       import "generic-service"
678       check_command = "iftraffic"
679       display_name = "IF-" + interface_name
680
681       /* use the key as command argument (no duplication of values in host.vars.interfaces) */
682       vars.iftraffic_interface = interface_name
683
684       /* map the custom attributes as command arguments */
685       vars.iftraffic_units = interface_config.iftraffic_units
686       vars.iftraffic_community = interface_config.iftraffic_community
687
688       /* the above can be achieved in a shorter fashion if the names inside host.vars.interfaces
689        * are the _exact_ same as required as command parameter by the check command
690        * definition.
691        */
692       vars += interface_config
693
694       /* set a default value for units and bandwidth */
695       if (interface_config.iftraffic_units == "") {
696         vars.iftraffic_units = "m"
697       }
698       if (interface_config.iftraffic_bandwidth == "") {
699         vars.iftraffic_bandwidth = 1
700       }
701       if (interface_config.vlan == "") {
702         vars.vlan = "not set"
703       }
704       if (interface_config.qos == "") {
705         vars.qos = "not set"
706       }
707
708       /* set the global constant if not explicitely
709        * not provided by the `interfaces` dictionary on the host
710        */
711       if (len(interface_config.iftraffic_community) == 0 || len(vars.iftraffic_community) == 0) {
712         vars.iftraffic_community = IftrafficSnmpCommunity
713       }
714
715       /* Calculate some additional object attributes after populating the `vars` dictionary */
716       notes = "Interface check for " + interface_name + " (units: '" + interface_config.iftraffic_units + "') in VLAN '" + vars.vlan + "' with ' QoS '" + vars.qos + "'"
717       notes_url = "http://foreman.company.com/hosts/" + host.name
718       action_url = "http://snmp.checker.company.com/" + host.name + "/if-" + interface_name
719     }
720
721
722
723 This example makes use of the [check_iftraffic](https://exchange.icinga.org/exchange/iftraffic) plugin.
724 The `CheckCommand` definition can be found in the
725 [contributed plugin check commands](7-icinga-template-library.md#plugins-contrib-command-iftraffic)
726 - make sure to include them in your [icinga2 configuration file](4-configuring-icinga-2.md#icinga2-conf).
727
728
729 > **Tip**
730 >
731 > Building configuration in that dynamic way requires detailed information
732 > of the generated objects. Use the `object list` [CLI command](8-cli-commands.md#cli-command-object)
733 > after successful [configuration validation](8-cli-commands.md#config-validation).
734
735 Verify that the apply-for-rule successfully created the service objects with the
736 inherited custom attributes:
737
738     # icinga2 daemon -C
739     # icinga2 object list --type Service --name *catalyst*
740
741 Object 'cisco-catalyst-6509-34!if-GigabitEthernet0/2' of type 'Service':
742     ......
743       * vars
744         % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 59:3-59:26
745         * iftraffic_bandwidth = 1
746         * iftraffic_community = "public"
747           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 53:3-53:65
748         * iftraffic_interface = "GigabitEthernet0/2"
749           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 49:3-49:43
750         * iftraffic_units = "g"
751           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 52:3-52:57
752         * qos = "disabled"
753         * vlan = "internal"
754
755
756     Object 'cisco-catalyst-6509-34!if-GigabitEthernet0/4' of type 'Service':
757     ...
758       * vars
759         % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 59:3-59:26
760         * iftraffic_bandwidth = 1
761         * iftraffic_community = "public"
762           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 53:3-53:65
763           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 79:5-79:53
764         * iftraffic_interface = "GigabitEthernet0/4"
765           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 49:3-49:43
766         * iftraffic_units = "g"
767           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 52:3-52:57
768         * qos = "enabled"
769         * vlan = "renote"
770
771     Object 'cisco-catalyst-6509-34!if-MgmtInterface1' of type 'Service':
772     ...
773       * vars
774         % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 59:3-59:26
775         * iftraffic_bandwidth = 1
776           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 66:5-66:32
777         * iftraffic_community = "public"
778           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 53:3-53:65
779         * iftraffic_interface = "MgmtInterface1"
780           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 49:3-49:43
781         * iftraffic_units = "m"
782           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 52:3-52:57
783           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 63:5-63:30
784         * interface_address = "127.99.0.100"
785         * qos = "not set"
786           % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 72:5-72:24
787         * vlan = "mgmt"
788
789
790 ### <a id="using-apply-object-attributes"></a> Use Object Attributes in Apply Rules
791
792 Since apply rules are evaluated after the generic objects, you
793 can reference existing host and/or service object attributes as
794 values for any object attribute specified in that apply rule.
795
796     object Host "opennebula-host" {
797       import "generic-host"
798       address = "10.1.1.2"
799
800       vars.hosting["xyz"] = {
801         http_uri = "/shop"
802         customer_name = "Customer xyz"
803         customer_id = "7568"
804         support_contract = "gold"
805       }
806       vars.hosting["abc"] = {
807         http_uri = "/shop"
808         customer_name = "Customer xyz"
809         customer_id = "7568"
810         support_contract = "silver"
811       }
812     }
813
814     apply Service for (customer => config in host.vars.hosting) {
815       import "generic-service"
816       check_command = "ping4"
817
818       vars.qos = "disabled"
819
820       vars += config
821
822       vars.http_uri = "/" + vars.customer + "/" + config.http_uri
823
824       display_name = "Shop Check for " + vars.customer_name + "-" + vars.customer_id
825
826       notes = "Support contract: " + vars.support_contract + " for Customer " + vars.customer_name + " (" + vars.customer_id + ")."
827
828       notes_url = "http://foreman.company.com/hosts/" + host.name
829       action_url = "http://snmp.checker.company.com/" + host.name + "/" + vars.customer_id
830     }
831
832 ## <a id="groups"></a> Groups
833
834 A group is a collection of similar objects. Groups are primarily used as a
835 visualization aid in web interfaces.
836
837 Group membership is defined at the respective object itself. If
838 you have a hostgroup name `windows` for example, and want to assign
839 specific hosts to this group for later viewing the group on your
840 alert dashboard, first create a HostGroup object:
841
842     object HostGroup "windows" {
843       display_name = "Windows Servers"
844     }
845
846 Then add your hosts to this group:
847
848     template Host "windows-server" {
849       groups += [ "windows" ]
850     }
851
852     object Host "mssql-srv1" {
853       import "windows-server"
854
855       vars.mssql_port = 1433
856     }
857
858     object Host "mssql-srv2" {
859       import "windows-server"
860
861       vars.mssql_port = 1433
862     }
863
864 This can be done for service and user groups the same way:
865
866     object UserGroup "windows-mssql-admins" {
867       display_name = "Windows MSSQL Admins"
868     }
869
870     template User "generic-windows-mssql-users" {
871       groups += [ "windows-mssql-admins" ]
872     }
873
874     object User "win-mssql-noc" {
875       import "generic-windows-mssql-users"
876
877       email = "noc@example.com"
878     }
879
880     object User "win-mssql-ops" {
881       import "generic-windows-mssql-users"
882
883       email = "ops@example.com"
884     }
885
886 ### <a id="group-assign-intro"></a> Group Membership Assign
887
888 Instead of manually assigning each object to a group you can also assign objects
889 to a group based on their attributes:
890
891     object HostGroup "prod-mssql" {
892       display_name = "Production MSSQL Servers"
893
894       assign where host.vars.mssql_port && host.vars.prod_mysql_db
895       ignore where host.vars.test_server == true
896       ignore where match("*internal", host.name)
897     }
898
899 In this example all hosts with the `vars` attribute `mssql_port`
900 will be added as members to the host group `mssql`. However, all `*internal`
901 hosts or with the `test_server` attribute set to `true` are not added to this
902 group.
903
904 Details on the `assign where` syntax can be found in the
905 [Language Reference](19-language-reference.md#apply)
906
907 ## <a id="notifications"></a> Notifications
908
909 Notifications for service and host problems are an integral part of your
910 monitoring setup.
911
912 When a host or service is in a downtime, a problem has been acknowledged or
913 the dependency logic determined that the host/service is unreachable, no
914 notifications are sent. You can configure additional type and state filters
915 refining the notifications being actually sent.
916
917 There are many ways of sending notifications, e.g. by e-mail, XMPP,
918 IRC, Twitter, etc. On its own Icinga 2 does not know how to send notifications.
919 Instead it relies on external mechanisms such as shell scripts to notify users.
920 More notification methods are listed in the [addons and plugins](13-addons-plugins.md#notification-scripts-interfaces)
921 chapter.
922
923 A notification specification requires one or more users (and/or user groups)
924 who will be notified in case of problems. These users must have all custom
925 attributes defined which will be used in the `NotificationCommand` on execution.
926
927 The user `icingaadmin` in the example below will get notified only on `WARNING` and
928 `CRITICAL` states and `problem` and `recovery` notification types.
929
930     object User "icingaadmin" {
931       display_name = "Icinga 2 Admin"
932       enable_notifications = true
933       states = [ OK, Warning, Critical ]
934       types = [ Problem, Recovery ]
935       email = "icinga@localhost"
936     }
937
938 If you don't set the `states` and `types` configuration attributes for the `User`
939 object, notifications for all states and types will be sent.
940
941 Details on troubleshooting notification problems can be found [here](16-troubleshooting.md#troubleshooting).
942
943 > **Note**
944 >
945 > Make sure that the [notification](8-cli-commands.md#features) feature is enabled
946 > in order to execute notification commands.
947
948 You should choose which information you (and your notified users) are interested in
949 case of emergency, and also which information does not provide any value to you and
950 your environment.
951
952 An example notification command is explained [here](3-monitoring-basics.md#notification-commands).
953
954 You can add all shared attributes to a `Notification` template which is inherited
955 to the defined notifications. That way you'll save duplicated attributes in each
956 `Notification` object. Attributes can be overridden locally.
957
958     template Notification "generic-notification" {
959       interval = 15m
960
961       command = "mail-service-notification"
962
963       states = [ Warning, Critical, Unknown ]
964       types = [ Problem, Acknowledgement, Recovery, Custom, FlappingStart,
965                 FlappingEnd, DowntimeStart, DowntimeEnd, DowntimeRemoved ]
966
967       period = "24x7"
968     }
969
970 The time period `24x7` is included as example configuration with Icinga 2.
971
972 Use the `apply` keyword to create `Notification` objects for your services:
973
974     apply Notification "notify-cust-xy-mysql" to Service {
975       import "generic-notification"
976
977       users = [ "noc-xy", "mgmt-xy" ]
978
979       assign where match("*has gold support 24x7*", service.notes) && (host.vars.customer == "customer-xy" || host.vars.always_notify == true
980       ignore where match("*internal", host.name) || (service.vars.priority < 2 && host.vars.is_clustered == true)
981     }
982
983
984 Instead of assigning users to notifications, you can also add the `user_groups`
985 attribute with a list of user groups to the `Notification` object. Icinga 2 will
986 send notifications to all group members.
987
988 > **Note**
989 >
990 > Only users who have been notified of a problem before  (`Warning`, `Critical`, `Unknown`
991 > states for services, `Down` for hosts) will receive `Recovery` notifications.
992
993 ### <a id="notification-escalations"></a> Notification Escalations
994
995 When a problem notification is sent and a problem still exists at the time of re-notification
996 you may want to escalate the problem to the next support level. A different approach
997 is to configure the default notification by email, and escalate the problem via SMS
998 if not already solved.
999
1000 You can define notification start and end times as additional configuration
1001 attributes making the `Notification` object a so-called `notification escalation`.
1002 Using templates you can share the basic notification attributes such as users or the
1003 `interval` (and override them for the escalation then).
1004
1005 Using the example from above, you can define additional users being escalated for SMS
1006 notifications between start and end time.
1007
1008     object User "icinga-oncall-2nd-level" {
1009       display_name = "Icinga 2nd Level"
1010
1011       vars.mobile = "+1 555 424642"
1012     }
1013
1014     object User "icinga-oncall-1st-level" {
1015       display_name = "Icinga 1st Level"
1016
1017       vars.mobile = "+1 555 424642"
1018     }
1019
1020 Define an additional [NotificationCommand](3-monitoring-basics.md#notification-commands) for SMS notifications.
1021
1022 > **Note**
1023 >
1024 > The example is not complete as there are many different SMS providers.
1025 > Please note that sending SMS notifications will require an SMS provider
1026 > or local hardware with a SIM card active.
1027
1028     object NotificationCommand "sms-notification" {
1029        command = [
1030          PluginDir + "/send_sms_notification",
1031          "$mobile$",
1032          "..."
1033     }
1034
1035 The two new notification escalations are added onto the local host
1036 and its service `ping4` using the `generic-notification` template.
1037 The user `icinga-oncall-2nd-level` will get notified by SMS (`sms-notification`
1038 command) after `30m` until `1h`.
1039
1040 > **Note**
1041 >
1042 > The `interval` was set to 15m in the `generic-notification`
1043 > template example. Lower that value in your escalations by using a secondary
1044 > template or by overriding the attribute directly in the `notifications` array
1045 > position for `escalation-sms-2nd-level`.
1046
1047 If the problem does not get resolved nor acknowledged preventing further notifications
1048 the `escalation-sms-1st-level` user will be escalated `1h` after the initial problem was
1049 notified, but only for one hour (`2h` as `end` key for the `times` dictionary).
1050
1051     apply Notification "mail" to Service {
1052       import "generic-notification"
1053
1054       command = "mail-notification"
1055       users = [ "icingaadmin" ]
1056
1057       assign where service.name == "ping4"
1058     }
1059
1060     apply Notification "escalation-sms-2nd-level" to Service {
1061       import "generic-notification"
1062
1063       command = "sms-notification"
1064       users = [ "icinga-oncall-2nd-level" ]
1065
1066       times = {
1067         begin = 30m
1068         end = 1h
1069       }
1070
1071       assign where service.name == "ping4"
1072     }
1073
1074     apply Notification "escalation-sms-1st-level" to Service {
1075       import "generic-notification"
1076
1077       command = "sms-notification"
1078       users = [ "icinga-oncall-1st-level" ]
1079
1080       times = {
1081         begin = 1h
1082         end = 2h
1083       }
1084
1085       assign where service.name == "ping4"
1086     }
1087
1088 ### <a id="notification-delay"></a> Notification Delay
1089
1090 Sometimes the problem in question should not be notified when the notification is due
1091 (the object reaching the `HARD` state) but a defined time duration afterwards. In Icinga 2
1092 you can use the `times` dictionary and set `begin = 15m` as key and value if you want to
1093 postpone the notification window for 15 minutes. Leave out the `end` key - if not set,
1094 Icinga 2 will not check against any end time for this notification. Make sure to
1095 specify a relatively low notification `interval` to get notified soon enough again.
1096
1097     apply Notification "mail" to Service {
1098       import "generic-notification"
1099
1100       command = "mail-notification"
1101       users = [ "icingaadmin" ]
1102
1103       interval = 5m
1104
1105       times.begin = 15m // delay notification window
1106
1107       assign where service.name == "ping4"
1108     }
1109
1110 ### <a id="disable-renotification"></a> Disable Re-notifications
1111
1112 If you prefer to be notified only once, you can disable re-notifications by setting the
1113 `interval` attribute to `0`.
1114
1115     apply Notification "notify-once" to Service {
1116       import "generic-notification"
1117
1118       command = "mail-notification"
1119       users = [ "icingaadmin" ]
1120
1121       interval = 0 // disable re-notification
1122
1123       assign where service.name == "ping4"
1124     }
1125
1126 ### <a id="notification-filters-state-type"></a> Notification Filters by State and Type
1127
1128 If there are no notification state and type filter attributes defined at the `Notification`
1129 or `User` object Icinga 2 assumes that all states and types are being notified.
1130
1131 Available state and type filters for notifications are:
1132
1133     template Notification "generic-notification" {
1134
1135       states = [ Warning, Critical, Unknown ]
1136       types = [ Problem, Acknowledgement, Recovery, Custom, FlappingStart,
1137                 FlappingEnd, DowntimeStart, DowntimeEnd, DowntimeRemoved ]
1138     }
1139
1140 If you are familiar with Icinga 1.x `notification_options` please note that they have been split
1141 into type and state to allow more fine granular filtering for example on downtimes and flapping.
1142 You can filter for acknowledgements and custom notifications too.
1143
1144
1145 ## <a id="commands"></a> Commands
1146
1147 Icinga 2 uses three different command object types to specify how
1148 checks should be performed, notifications should be sent, and
1149 events should be handled.
1150
1151 ### <a id="check-commands"></a> Check Commands
1152
1153 [CheckCommand](6-object-types.md#objecttype-checkcommand) objects define the command line how
1154 a check is called.
1155
1156 [CheckCommand](6-object-types.md#objecttype-checkcommand) objects are referenced by
1157 [Host](6-object-types.md#objecttype-host) and [Service](6-object-types.md#objecttype-service) objects
1158 using the `check_command` attribute.
1159
1160 > **Note**
1161 >
1162 > Make sure that the [checker](8-cli-commands.md#features) feature is enabled in order to
1163 > execute checks.
1164
1165 #### <a id="command-plugin-integration"></a> Integrate the Plugin with a CheckCommand Definition
1166
1167 [CheckCommand](6-object-types.md#objecttype-checkcommand) objects require the [ITL template](7-icinga-template-library.md#itl-plugin-check-command)
1168 `plugin-check-command` to support native plugin based check methods.
1169
1170 Unless you have done so already, download your check plugin and put it
1171 into the [PluginDir](4-configuring-icinga-2.md#constants-conf) directory. The following example uses the
1172 `check_mysql` plugin contained in the Monitoring Plugins package.
1173
1174 The plugin path and all command arguments are made a list of
1175 double-quoted string arguments for proper shell escaping.
1176
1177 Call the `check_disk` plugin with the `--help` parameter to see
1178 all available options. Our example defines warning (`-w`) and
1179 critical (`-c`) thresholds for the disk usage. Without any
1180 partition defined (`-p`) it will check all local partitions.
1181
1182    icinga@icinga2 $ /usr/lib64/nagios/plugins/check_mysql --help
1183    ...
1184
1185     This program tests connections to a MySQL server
1186
1187    Usage:
1188      check_mysql [-d database] [-H host] [-P port] [-s socket]
1189            [-u user] [-p password] [-S] [-l] [-a cert] [-k key]
1190            [-C ca-cert] [-D ca-dir] [-L ciphers] [-f optfile] [-g group]
1191
1192 Next step is to understand how [command parameters](3-monitoring-basics.md#command-passing-parameters)
1193 are being passed from a host or service object, and add a [CheckCommand](6-object-types.md#objecttype-checkcommand)
1194 definition based on these required parameters and/or default values.
1195
1196 Please continue reading in the [plugins section](13-addons-plugins.md#plugins) for additional integration examples.
1197
1198 #### <a id="command-passing-parameters"></a> Passing Check Command Parameters from Host or Service
1199
1200 Check command parameters are defined as custom attributes which can be accessed as runtime macros
1201 by the executed check command.
1202
1203 The check command parameters for ITL provided plugin check command definitions are documented
1204 [here](7-icinga-template-library.md#plugin-check-commands), for example
1205 [disk](7-icinga-template-library.md#plugin-check-command-disk).
1206
1207 In order to practice passing command parameters you should [integrate your own plugin](3-monitoring-basics.md#command-plugin-integration).
1208
1209 The following example will use `check_mysql` provided by the [Monitoring Plugins installation](2-getting-started.md#setting-up-check-plugins).
1210
1211 Define the default check command custom attributes, for example `mysql_user` and `mysql_password`
1212 (freely definable naming schema) and optional their default threshold values. You can
1213 then use these custom attributes as runtime macros for [command arguments](3-monitoring-basics.md#command-arguments)
1214 on the command line.
1215
1216 > **Tip**
1217 >
1218 > Use a common command type as prefix for your command arguments to increase
1219 > readability. `mysql_user` helps understanding the context better than just
1220 > `user` as argument.
1221
1222 The default custom attributes can be overridden by the custom attributes
1223 defined in the host or service using the check command `my-mysql`. The custom attributes
1224 can also be inherited from a parent template using additive inheritance (`+=`).
1225
1226     # vim /etc/icinga2/conf.d/commands.conf
1227
1228     object CheckCommand "my-mysql" {
1229       import "plugin-check-command"
1230
1231       command = [ PluginDir + "/check_mysql" ] //constants.conf -> const PluginDir
1232
1233       arguments = {
1234         "-H" = "$mysql_host$"
1235         "-u" = {
1236           required = true
1237           value = "$mysql_user$"
1238         }
1239         "-p" = "$mysql_password$"
1240         "-P" = "$mysql_port$"
1241         "-s" = "$mysql_socket$"
1242         "-a" = "$mysql_cert$"
1243         "-d" = "$mysql_database$"
1244         "-k" = "$mysql_key$"
1245         "-C" = "$mysql_ca_cert$"
1246         "-D" = "$mysql_ca_dir$"
1247         "-L" = "$mysql_ciphers$"
1248         "-f" = "$mysql_optfile$"
1249         "-g" = "$mysql_group$"
1250         "-S" = {
1251           set_if = "$mysql_check_slave$"
1252           description = "Check if the slave thread is running properly."
1253         }
1254         "-l" = {
1255           set_if = "$mysql_ssl$"
1256           description = "Use ssl encryption"
1257         }
1258       }
1259
1260       vars.mysql_check_slave = false
1261       vars.mysql_ssl = false
1262       vars.mysql_host = "$address$"
1263     }
1264
1265 The check command definition also sets `mysql_host` to the `$address$` default value. You can override
1266 this command parameter if for example your MySQL host is not running on the same server's ip address.
1267
1268 Make sure pass all required command parameters, such as `mysql_user`, `mysql_password` and `mysql_database`.
1269 `MysqlUsername` and `MysqlPassword` are specified as [global constants](4-configuring-icinga-2.md#constants-conf)
1270 in this example.
1271
1272     # vim /etc/icinga2/conf.d/services.conf
1273
1274     apply Service "mysql-icinga-db-health" {
1275       import "generic-service"
1276
1277       check_command = "my-mysql"
1278
1279       vars.mysql_user = MysqlUsername
1280       vars.mysql_password = MysqlPassword
1281
1282       vars.mysql_database = "icinga"
1283       vars.mysql_host = "192.168.33.11"
1284
1285       assign where match("icinga2*", host.name)
1286       ignore where host.vars.no_health_check == true
1287     }
1288
1289
1290 Take a different example: The example host configuration in [hosts.conf](4-configuring-icinga-2.md#hosts-conf)
1291 also applies an `ssh` service check. Your host's ssh port is not the default `22`, but set to `2022`.
1292 You can pass the command parameter as custom attribute `ssh_port` directly inside the service apply rule
1293 inside [services.conf](4-configuring-icinga-2.md#services-conf):
1294
1295     apply Service "ssh" {
1296       import "generic-service"
1297
1298       check_command = "ssh"
1299       vars.ssh_port = 2022 //custom command parameter
1300
1301       assign where (host.address || host.address6) && host.vars.os == "Linux"
1302     }
1303
1304 If you prefer this being configured at the host instead of the service, modify the host configuration
1305 object instead. The runtime macro resolving order is described [here](3-monitoring-basics.md#macro-evaluation-order).
1306
1307    object Host NodeName {
1308    ...
1309      vars.ssh_port = 2022
1310    }
1311
1312 #### <a id="command-passing-parameters-apply-for"></a> Passing Check Command Parameters Using Apply For
1313
1314 The host `localhost` with the generated services from the `basic-partitions` dictionary (see
1315 [apply for](3-monitoring-basics.md#using-apply-for) for details) checks a basic set of disk partitions
1316 with modified custom attributes (warning thresholds at `10%`, critical thresholds at `5%`
1317 free disk space).
1318
1319 The custom attribute `disk_partition` can either hold a single string or an array of
1320 string values for passing multiple partitions to the `check_disk` check plugin.
1321
1322     object Host "my-server" {
1323       import "generic-host"
1324       address = "127.0.0.1"
1325       address6 = "::1"
1326
1327       vars.local_disks["basic-partitions"] = {
1328         disk_partitions = [ "/", "/tmp", "/var", "/home" ]
1329       }
1330     }
1331
1332     apply Service for (disk => config in host.vars.local_disks) {
1333       import "generic-service"
1334       check_command = "my-disk"
1335
1336       vars += config
1337
1338       vars.disk_wfree = "10%"
1339       vars.disk_cfree = "5%"
1340     }
1341
1342
1343 More details on using arrays in custom attributes can be found in
1344 [this chapter](3-monitoring-basics.md#custom-attributes).
1345
1346
1347 #### <a id="command-arguments"></a> Command Arguments
1348
1349 By defining a check command line using the `command` attribute Icinga 2
1350 will resolve all macros in the static string or array. Sometimes it is
1351 required to extend the arguments list based on a met condition evaluated
1352 at command execution. Or making arguments optional - only set if the
1353 macro value can be resolved by Icinga 2.
1354
1355     object CheckCommand "check_http" {
1356       import "plugin-check-command"
1357
1358       command = [ PluginDir + "/check_http" ]
1359
1360       arguments = {
1361         "-H" = "$http_vhost$"
1362         "-I" = "$http_address$"
1363         "-u" = "$http_uri$"
1364         "-p" = "$http_port$"
1365         "-S" = {
1366           set_if = "$http_ssl$"
1367         }
1368         "--sni" = {
1369           set_if = "$http_sni$"
1370         }
1371         "-a" = {
1372           value = "$http_auth_pair$"
1373           description = "Username:password on sites with basic authentication"
1374         }
1375         "--no-body" = {
1376           set_if = "$http_ignore_body$"
1377         }
1378         "-r" = "$http_expect_body_regex$"
1379         "-w" = "$http_warn_time$"
1380         "-c" = "$http_critical_time$"
1381         "-e" = "$http_expect$"
1382       }
1383
1384       vars.http_address = "$address$"
1385       vars.http_ssl = false
1386       vars.http_sni = false
1387     }
1388
1389 The example shows the `check_http` check command defining the most common
1390 arguments. Each of them is optional by default and will be omitted if
1391 the value is not set. For example if the service calling the check command
1392 does not have `vars.http_port` set, it won't get added to the command
1393 line.
1394
1395 If the `vars.http_ssl` custom attribute is set in the service, host or command
1396 object definition, Icinga 2 will add the `-S` argument based on the `set_if`
1397 numeric value to the command line. String values are not supported.
1398
1399 If the macro value cannot be resolved, Icinga 2 will not add the defined argument
1400 to the final command argument array. Empty strings for macro values won't omit
1401 the argument.
1402
1403 That way you can use the `check_http` command definition for both, with and
1404 without SSL enabled checks saving you duplicated command definitions.
1405
1406 Details on all available options can be found in the
1407 [CheckCommand object definition](6-object-types.md#objecttype-checkcommand).
1408
1409
1410 #### <a id="command-environment-variables"></a> Environment Variables
1411
1412 The `env` command object attribute specifies a list of environment variables with values calculated
1413 from either runtime macros or custom attributes which should be exported as environment variables
1414 prior to executing the command.
1415
1416 This is useful for example for hiding sensitive information on the command line output
1417 when passing credentials to database checks:
1418
1419     object CheckCommand "mysql-health" {
1420       import "plugin-check-command"
1421
1422       command = [
1423         PluginDir + "/check_mysql"
1424       ]
1425
1426       arguments = {
1427         "-H" = "$mysql_address$"
1428         "-d" = "$mysql_database$"
1429       }
1430
1431       vars.mysql_address = "$address$"
1432       vars.mysql_database = "icinga"
1433       vars.mysql_user = "icinga_check"
1434       vars.mysql_pass = "password"
1435
1436       env.MYSQLUSER = "$mysql_user$"
1437       env.MYSQLPASS = "$mysql_pass$"
1438     }
1439
1440
1441
1442 ### <a id="notification-commands"></a> Notification Commands
1443
1444 [NotificationCommand](6-object-types.md#objecttype-notificationcommand) objects define how notifications are delivered to external
1445 interfaces (E-Mail, XMPP, IRC, Twitter, etc).
1446
1447 [NotificationCommand](6-object-types.md#objecttype-notificationcommand) objects are referenced by
1448 [Notification](6-object-types.md#objecttype-notification) objects using the `command` attribute.
1449
1450 `NotificationCommand` objects require the [ITL template](7-icinga-template-library.md#itl-plugin-notification-command)
1451 `plugin-notification-command` to support native plugin-based notifications.
1452
1453 > **Note**
1454 >
1455 > Make sure that the [notification](8-cli-commands.md#features) feature is enabled
1456 > in order to execute notification commands.
1457
1458 Below is an example using runtime macros from Icinga 2 (such as `$service.output$` for
1459 the current check output) sending an email to the user(s) associated with the
1460 notification itself (`$user.email$`).
1461
1462 If you want to specify default values for some of the custom attribute definitions,
1463 you can add a `vars` dictionary as shown for the `CheckCommand` object.
1464
1465     object NotificationCommand "mail-service-notification" {
1466       import "plugin-notification-command"
1467
1468       command = [ SysconfDir + "/icinga2/scripts/mail-notification.sh" ]
1469
1470       env = {
1471         NOTIFICATIONTYPE = "$notification.type$"
1472         SERVICEDESC = "$service.name$"
1473         HOSTALIAS = "$host.display_name$"
1474         HOSTADDRESS = "$address$"
1475         SERVICESTATE = "$service.state$"
1476         LONGDATETIME = "$icinga.long_date_time$"
1477         SERVICEOUTPUT = "$service.output$"
1478         NOTIFICATIONAUTHORNAME = "$notification.author$"
1479         NOTIFICATIONCOMMENT = "$notification.comment$"
1480         HOSTDISPLAYNAME = "$host.display_name$"
1481         SERVICEDISPLAYNAME = "$service.display_name$"
1482         USEREMAIL = "$user.email$"
1483       }
1484     }
1485
1486 The command attribute in the `mail-service-notification` command refers to the following
1487 shell script. The macros specified in the `env` array are exported
1488 as environment variables and can be used in the notification script:
1489
1490     #!/usr/bin/env bash
1491     template=$(cat <<TEMPLATE
1492     ***** Icinga  *****
1493
1494     Notification Type: $NOTIFICATIONTYPE
1495
1496     Service: $SERVICEDESC
1497     Host: $HOSTALIAS
1498     Address: $HOSTADDRESS
1499     State: $SERVICESTATE
1500
1501     Date/Time: $LONGDATETIME
1502
1503     Additional Info: $SERVICEOUTPUT
1504
1505     Comment: [$NOTIFICATIONAUTHORNAME] $NOTIFICATIONCOMMENT
1506     TEMPLATE
1507     )
1508
1509     /usr/bin/printf "%b" $template | mail -s "$NOTIFICATIONTYPE - $HOSTDISPLAYNAME - $SERVICEDISPLAYNAME is $SERVICESTATE" $USEREMAIL
1510
1511 > **Note**
1512 >
1513 > This example is for `exim` only. Requires changes for `sendmail` and
1514 > other MTAs.
1515
1516 While it's possible to specify the entire notification command right
1517 in the NotificationCommand object it is generally advisable to create a
1518 shell script in the `/etc/icinga2/scripts` directory and have the
1519 NotificationCommand object refer to that.
1520
1521 ### <a id="event-commands"></a> Event Commands
1522
1523 Unlike notifications, event commands for hosts/services are called on every
1524 check execution if one of these conditions match:
1525
1526 * The host/service is in a [soft state](3-monitoring-basics.md#hard-soft-states)
1527 * The host/service state changes into a [hard state](3-monitoring-basics.md#hard-soft-states)
1528 * The host/service state recovers from a [soft or hard state](3-monitoring-basics.md#hard-soft-states) to [OK](3-monitoring-basics.md#service-states)/[Up](3-monitoring-basics.md#host-states)
1529
1530 [EventCommand](6-object-types.md#objecttype-eventcommand) objects are referenced by
1531 [Host](6-object-types.md#objecttype-host) and [Service](6-object-types.md#objecttype-service) objects
1532 using the `event_command` attribute.
1533
1534 Therefore the `EventCommand` object should define a command line
1535 evaluating the current service state and other service runtime attributes
1536 available through runtime vars. Runtime macros such as `$service.state_type$`
1537 and `$service.state$` will be processed by Icinga 2 helping on fine-granular
1538 events being triggered.
1539
1540 Common use case scenarios are a failing HTTP check requiring an immediate
1541 restart via event command, or if an application is locked and requires
1542 a restart upon detection.
1543
1544 `EventCommand` objects require the ITL template `plugin-event-command`
1545 to support native plugin based checks.
1546
1547 #### <a id="event-command-restart-service-daemon"></a> Use Event Commands to Restart Service Daemon
1548
1549 The following example will triggert a restart of the `httpd` daemon
1550 via ssh when the `http` service check fails. If the service state is
1551 `OK`, it will not trigger any event action.
1552
1553 Requirements:
1554
1555 * ssh connection
1556 * icinga user with public key authentication
1557 * icinga user with sudo permissions for restarting the httpd daemon.
1558
1559 Example on Debian:
1560
1561     # ls /home/icinga/.ssh/
1562     authorized_keys
1563
1564     # visudo
1565     icinga  ALL=(ALL) NOPASSWD: /etc/init.d/apache2 restart
1566
1567
1568 Define a generic [EventCommand](6-object-types.md#objecttype-eventcommand) object `event_by_ssh`
1569 which can be used for all event commands triggered using ssh:
1570
1571     /* pass event commands through ssh */
1572     object EventCommand "event_by_ssh" {
1573       import "plugin-event-command"
1574
1575       command = [ PluginDir + "/check_by_ssh" ]
1576
1577       arguments = {
1578         "-H" = "$event_by_ssh_address$"
1579         "-p" = "$event_by_ssh_port$"
1580         "-C" = "$event_by_ssh_command$"
1581         "-l" = "$event_by_ssh_logname$"
1582         "-i" = "$event_by_ssh_identity$"
1583         "-q" = {
1584           set_if = "$event_by_ssh_quiet$"
1585         }
1586         "-w" = "$event_by_ssh_warn$"
1587         "-c" = "$event_by_ssh_crit$"
1588         "-t" = "$event_by_ssh_timeout$"
1589       }
1590
1591       vars.event_by_ssh_address = "$address$"
1592       vars.event_by_ssh_quiet = false
1593     }
1594
1595 The actual event command only passes the `event_by_ssh_command` attribute.
1596 The `event_by_ssh_service` custom attribute takes care of passing the correct
1597 daemon name, while `test $service.state_id$ -gt 0` makes sure that the daemon
1598 is only restarted when the service is not in an `OK` state.
1599
1600
1601     object EventCommand "event_by_ssh_restart_service" {
1602       import "event_by_ssh"
1603
1604       //only restart the daemon if state > 0 (not-ok)
1605       //requires sudo permissions for the icinga user
1606       vars.event_by_ssh_command = "test $service.state_id$ -gt 0 && sudo /etc/init.d/$event_by_ssh_service$ restart"
1607     }
1608
1609
1610 Now set the `event_command` attribute to `event_by_ssh_restart_service` and tell it
1611 which service should be restarted using the `event_by_ssh_service` attribute.
1612
1613     object Service "http" {
1614       import "generic-service"
1615       host_name = "remote-http-host"
1616       check_command = "http"
1617
1618       event_command = "event_by_ssh_restart_service"
1619       vars.event_by_ssh_service = "$host.vars.httpd_name$"
1620
1621       //vars.event_by_ssh_logname = "icinga"
1622       //vars.event_by_ssh_identity = "/home/icinga/.ssh/id_rsa.pub"
1623     }
1624
1625
1626 Each host with this service then must define the `httpd_name` custom attribute
1627 (for example generated from your cmdb):
1628
1629     object Host "remote-http-host" {
1630       import "generic-host"
1631       address = "192.168.1.100"
1632
1633       vars.httpd_name = "apache2"
1634     }
1635
1636 You can testdrive this example by manually stopping the `httpd` daemon
1637 on your `remote-http-host`. Enable the `debuglog` feature and tail the
1638 `/var/log/icinga2/debug.log` file.
1639
1640 Remote Host Terminal:
1641
1642     # date; service apache2 status
1643     Mon Sep 15 18:57:39 CEST 2014
1644     Apache2 is running (pid 23651).
1645     # date; service apache2 stop
1646     Mon Sep 15 18:57:47 CEST 2014
1647     [ ok ] Stopping web server: apache2 ... waiting .
1648
1649 Icinga 2 Host Terminal:
1650
1651     [2014-09-15 18:58:32 +0200] notice/Process: Running command '/usr/lib64/nagios/plugins/check_http' '-I' '192.168.1.100': PID 32622
1652     [2014-09-15 18:58:32 +0200] notice/Process: PID 32622 ('/usr/lib64/nagios/plugins/check_http' '-I' '192.168.1.100') terminated with exit code 2
1653     [2014-09-15 18:58:32 +0200] notice/Checkable: State Change: Checkable remote-http-host!http soft state change from OK to CRITICAL detected.
1654     [2014-09-15 18:58:32 +0200] notice/Checkable: Executing event handler 'event_by_ssh_restart_service' for service 'remote-http-host!http'
1655     [2014-09-15 18:58:32 +0200] notice/Process: Running command '/usr/lib64/nagios/plugins/check_by_ssh' '-C' 'test 2 -gt 0 && sudo /etc/init.d/apache2 restart' '-H' '192.168.1.100': PID 32623
1656     [2014-09-15 18:58:33 +0200] notice/Process: PID 32623 ('/usr/lib64/nagios/plugins/check_by_ssh' '-C' 'test 2 -gt 0 && sudo /etc/init.d/apache2 restart' '-H' '192.168.1.100') terminated with exit code 0
1657
1658 Remote Host Terminal:
1659
1660     # date; service apache2 status
1661     Mon Sep 15 18:58:44 CEST 2014
1662     Apache2 is running (pid 24908).
1663
1664
1665 ## <a id="dependencies"></a> Dependencies
1666
1667 Icinga 2 uses host and service [Dependency](6-object-types.md#objecttype-dependency) objects
1668 for determing their network reachability.
1669
1670 A service can depend on a host, and vice versa. A service has an implicit
1671 dependency (parent) to its host. A host to host dependency acts implicitly
1672 as host parent relation.
1673 When dependencies are calculated, not only the immediate parent is taken into
1674 account but all parents are inherited.
1675
1676 The `parent_host_name` and `parent_service_name` attributes are mandatory for
1677 service dependencies, `parent_host_name` is required for host dependencies.
1678 [Apply rules](3-monitoring-basics.md#using-apply) will allow you to
1679 [determine these attributes](3-monitoring-basics.md#dependencies-apply-custom-attributes) in a more
1680 dynamic fashion if required.
1681
1682     parent_host_name = "core-router"
1683     parent_service_name = "uplink-port"
1684
1685 Notifications are suppressed by default if a host or service becomes unreachable.
1686 You can control that option by defining the `disable_notifications` attribute.
1687
1688     disable_notifications = false
1689
1690 If the dependency should be triggered in the parent object's soft state, you
1691 need to set `ignore_soft_states` to `false`.
1692
1693 The dependency state filter must be defined based on the parent object being
1694 either a host (`Up`, `Down`) or a service (`OK`, `Warning`, `Critical`, `Unknown`).
1695
1696 The following example will make the dependency fail and trigger it if the parent
1697 object is **not** in one of these states:
1698
1699     states = [ OK, Critical, Unknown ]
1700
1701 Rephrased: If the parent service object changes into the `Warning` state, this
1702 dependency will fail and render all child objects (hosts or services) unreachable.
1703
1704 You can determine the child's reachability by querying the `is_reachable` attribute
1705 in for example [DB IDO](22-appendix.md#schema-db-ido-extensions).
1706
1707 ### <a id="dependencies-implicit-host-service"></a> Implicit Dependencies for Services on Host
1708
1709 Icinga 2 automatically adds an implicit dependency for services on their host. That way
1710 service notifications are suppressed when a host is `DOWN` or `UNREACHABLE`. This dependency
1711 does not overwrite other dependencies and implicitely sets `disable_notifications = true` and
1712 `states = [ Up ]` for all service objects.
1713
1714 Service checks are still executed. If you want to prevent them from happening, you can
1715 apply the following dependency to all services setting their host as `parent_host_name`
1716 and disabling the checks. `assign where true` matches on all `Service` objects.
1717
1718     apply Dependency "disable-host-service-checks" to Service {
1719       disable_checks = true
1720       assign where true
1721     }
1722
1723 ### <a id="dependencies-network-reachability"></a> Dependencies for Network Reachability
1724
1725 A common scenario is the Icinga 2 server behind a router. Checking internet
1726 access by pinging the Google DNS server `google-dns` is a common method, but
1727 will fail in case the `dsl-router` host is down. Therefore the example below
1728 defines a host dependency which acts implicitly as parent relation too.
1729
1730 Furthermore the host may be reachable but ping probes are dropped by the
1731 router's firewall. In case the `dsl-router`'s `ping4` service check fails, all
1732 further checks for the `ping4` service on host `google-dns` service should
1733 be suppressed. This is achieved by setting the `disable_checks` attribute to `true`.
1734
1735     object Host "dsl-router" {
1736       import "generic-host"
1737       address = "192.168.1.1"
1738     }
1739
1740     object Host "google-dns" {
1741       import "generic-host"
1742       address = "8.8.8.8"
1743     }
1744
1745     apply Service "ping4" {
1746       import "generic-service"
1747
1748       check_command = "ping4"
1749
1750       assign where host.address
1751     }
1752
1753     apply Dependency "internet" to Host {
1754       parent_host_name = "dsl-router"
1755       disable_checks = true
1756       disable_notifications = true
1757
1758       assign where host.name != "dsl-router"
1759     }
1760
1761     apply Dependency "internet" to Service {
1762       parent_host_name = "dsl-router"
1763       parent_service_name = "ping4"
1764       disable_checks = true
1765
1766       assign where host.name != "dsl-router"
1767     }
1768
1769 ### <a id="dependencies-apply-custom-attributes"></a> Apply Dependencies based on Custom Attributes
1770
1771 You can use [apply rules](3-monitoring-basics.md#using-apply) to set parent or
1772 child attributes e.g. `parent_host_name` to other object's
1773 attributes.
1774
1775 A common example are virtual machines hosted on a master. The object
1776 name of that master is auto-generated from your CMDB or VMWare inventory
1777 into the host's custom attributes (or a generic template for your
1778 cloud).
1779
1780 Define your master host object:
1781
1782     /* your master */
1783     object Host "master.example.com" {
1784       import "generic-host"
1785     }
1786
1787 Add a generic template defining all common host attributes:
1788
1789     /* generic template for your virtual machines */
1790     template Host "generic-vm" {
1791       import "generic-host"
1792     }
1793
1794 Add a template for all hosts on your example.com cloud setting
1795 custom attribute `vm_parent` to `master.example.com`:
1796
1797     template Host "generic-vm-example.com" {
1798       import "generic-vm"
1799       vars.vm_parent = "master.example.com"
1800     }
1801
1802 Define your guest hosts:
1803
1804     object Host "www.example1.com" {
1805       import "generic-vm-master.example.com"
1806     }
1807
1808     object Host "www.example2.com" {
1809       import "generic-vm-master.example.com"
1810     }
1811
1812 Apply the host dependency to all child hosts importing the
1813 `generic-vm` template and set the `parent_host_name`
1814 to the previously defined custom attribute `host.vars.vm_parent`.
1815
1816     apply Dependency "vm-host-to-parent-master" to Host {
1817       parent_host_name = host.vars.vm_parent
1818       assign where "generic-vm" in host.templates
1819     }
1820
1821 You can extend this example, and make your services depend on the
1822 `master.example.com` host too. Their local scope allows you to use
1823 `host.vars.vm_parent` similar to the example above.
1824
1825     apply Dependency "vm-service-to-parent-master" to Service {
1826       parent_host_name = host.vars.vm_parent
1827       assign where "generic-vm" in host.templates
1828     }
1829
1830 That way you don't need to wait for your guest hosts becoming
1831 unreachable when the master host goes down. Instead the services
1832 will detect their reachability immediately when executing checks.
1833
1834 > **Note**
1835 >
1836 > This method with setting locally scoped variables only works in
1837 > apply rules, but not in object definitions.
1838
1839
1840 ### <a id="dependencies-agent-checks"></a> Dependencies for Agent Checks
1841
1842 Another classic example are agent based checks. You would define a health check
1843 for the agent daemon responding to your requests, and make all other services
1844 querying that daemon depend on that health check.
1845
1846 The following configuration defines two nrpe based service checks `nrpe-load`
1847 and `nrpe-disk` applied to the `nrpe-server`. The health check is defined as
1848 `nrpe-health` service.
1849
1850     apply Service "nrpe-health" {
1851       import "generic-service"
1852       check_command = "nrpe"
1853       assign where match("nrpe-*", host.name)
1854     }
1855
1856     apply Service "nrpe-load" {
1857       import "generic-service"
1858       check_command = "nrpe"
1859       vars.nrpe_command = "check_load"
1860       assign where match("nrpe-*", host.name)
1861     }
1862
1863     apply Service "nrpe-disk" {
1864       import "generic-service"
1865       check_command = "nrpe"
1866       vars.nrpe_command = "check_disk"
1867       assign where match("nrpe-*", host.name)
1868     }
1869
1870     object Host "nrpe-server" {
1871       import "generic-host"
1872       address = "192.168.1.5"
1873     }
1874
1875     apply Dependency "disable-nrpe-checks" to Service {
1876       parent_service_name = "nrpe-health"
1877
1878       states = [ OK ]
1879       disable_checks = true
1880       disable_notifications = true
1881       assign where service.check_command == "nrpe"
1882       ignore where service.name == "nrpe-health"
1883     }
1884
1885 The `disable-nrpe-checks` dependency is applied to all services
1886 on the `nrpe-service` host using the `nrpe` check_command attribute
1887 but not the `nrpe-health` service itself.