Download_Icinga2v0.0.10The more we’ve been playing with Icinga 2 in our test labs, the better insight we’ve gotten into how the configuration works in “real life”. One of the outcomes from our testing was already addressed in 0.0.9, which introduced the new apply rules for objects.

A new configuration format would not be justified in a new major release (2.0.0 is near), if we didn’t tinker a bit more and try to make Icinga 2 even more satisfying to use. For a detailed list on all config-related changes check #5909.

Find the change log at docs.icinga.com – Icinga 2 0.0.10 is available for download.

More ‘Apply’ Goodness


The new apply rules are really sexy – they now generate errors and warnings if used in the wrong scope too (#5911). Furthermore a new apply target type was introduced (#5924, for example when applying a notification object to a host or service object).

apply Notification "mail-icingaadmin" to Service {
  import "mail-service-notification"

  user_groups = [ "icingaadmins" ]

  assign where "generic-service" in service.templates
}

Apply rules generate new objects each time (services linked to hosts for example) – if you want to assign members to a group based on such a rule set (#5910), you cannot use the ‘apply’ keyword. Instead, you’ll just use the ‘assign’ and ‘ignore’ rules within group objects to assign all matching objects a membership to this group (and all nested groups too). Nested groups for better interface grouping or web interface permissions can be defined using the additional group object attribute ‘groups’.

The example below shows a host with the custom attribute ‘os’ being set to ‘Linux’. The host group ‘linux-servers’ matches that pattern, and assigns the membership for localhost into that group. We’ve also provided a similar example using service groups – make all services a member of the group ‘http’ based on the ‘check_command’ attribute matching ‘http_*’.

object Host "localhost" {
  import "generic-host"

  address = "127.0.0.1"
  address6 = "::1"

  vars.os = "Linux"
}

object HostGroup "linux-servers" {
  display_name = "Linux Servers"

  assign where host.vars.os == "Linux"
}

object Service "http" {
  import "generic-service"

  host_name = "localhost"
  check_command = "http"
}

object ServiceGroup "http" {
  display_name = "HTTP Checks"

  assign where match("http_*", service.check_command)
}

Relative Service Object Names

We’ve also found it hard to keep unique service object names everywhere. A service object is still bound to a host object, making that relationship unique. Therefore relative service object names are introduced in #5925 allowing the same service object name to be defined multiple times with a different ‘host_name’ attribute. Icinga 2 will create new objects similar to the objects generated by the apply rules, internally.

# node1/services.conf
object Service "mail" {
  host_name = "node1"
  ...
}

# node2/services.conf
object Service "mail" {
  host_name = "node2"
  ...
}

What’s in a Name?

When it comes to naming conventions, we’ve changed various configuration attributes to a shorter name or sometimes more self-explanatory names, for example ‘notification_type_filter’ is now called ‘types’ only (#5906, #5857, #5960 ). Furthermore the notification and dependency filters don’t have their own prefix anymore (for example ‘Up’ or ‘Critical’, #5906)

template Notification "mail-service-notification" {
  command = "mail-service-notification"

  states = [ OK, Warning, Critical, Unknown ]
  types = [ Problem, Acknowledgement, Recovery, Custom,
            FlappingStart, FlappingEnd,
            DowntimeStart, DowntimeEnd, DowntimeRemoved ]

  period = "24x7"
}

Macros

The ‘macros’ and ‘custom’ dictionaries have been merged into a general ‘vars’ dictionary (details in #5855). This may sound like existing 1.x custom variables and there is certainly a similarity when making them available to existing interfaces. Custom attributes are available in command objects too – DB IDO, Livestatus and status.dat schemas have been updated for that reason.
These custom attributes are available as runtime macros in their local object scope as $varname$, or as object attributes in their inherited scope, like $host.vars.varname$ accessed in a certain service check command. The previous notation ${HOST,SERVICE}attributename$ has been dropped (same for $_{HOST,SERVICE}varname$ when accessing custom attributes).

Special runtime macros such as state information or the application time can be accessed using their scope prefix for example $host.state$ or $icinga.datetime$. This change applies to performance data file templates as well as existing command definitions. If the address macro cannot be resolved, it won’t be replaced by the host name – that is one major difference to the workaround in Icinga 1.x.

Previously named ‘export_macros’, the command attribute is now called ‘env’ and the dictionary enabling  environment variables and their values ‘escape_macros’ to be defined  is gone. All macros are escaped if a string is provided.

object Host "macro-test-host1" {
  import "generic-host"
  vars.macro1 = "foo1"
  vars.macro2 = "bar1"
}

object Host "macro-test-host2" {
  import "generic-host"
  vars.macro1 = "foo2"
  vars.macro2 = "bar2"
}

apply Service "macro-test-service" {
  check_command = "macro-test-check"
  vars.address = "$host.vars.macro1$"
  assign where match("macro-test-host*", host.name)
}

object CheckCommand "macro-test-check" {
  command = "echo "address macro: '$address$' env var: $$MACROTEST""
  env.MACROTEST = "$host.name$ $address$"
}

Custom attributes can be modified and reset at runtime using external commands. All external interfaces will reflect these changes properly.

[2014-04-15 17:26:08 +0200]  information/compat: Executing external command: [1397575568] CHANGE_CUSTOM_HOST_VAR;macro-test;urlpath;override_custom_var_value
[2014-04-15 17:26:08 +0200]  information/icinga: Changing custom var 'urlpath' for host 'macro-test' to value 'override_custom_var_value'

More Macros & Attributes

When it comes to runtime macros, we found it reasonable to access object attributes in apply rules . Therefore the runtime macros are evaluated as such too – $host.address$ accesses the host’s ‘address’ attribute for example. Under certain circumstances custom attributes may be overridden by macro-evaluated values (#5959).

object Host "keks" {
  import "generic-host"

  vars.ip_address = "$vars.my_customer_ip$"
  vars.my_costumer_ip = "1.2.3.4"
  vars.my_service_http_ip = "3.4.5.6"
}

apply Service "schaschlik" {
  import "generic-service"
  vars.ip_address = "$host.vars.my_service_http_ip$"

  assign where host.vars.my_service_http_ip
}

Furthermore the most common host, service and group attributes (#5856) have been added again – ‘address’, ‘address6’, ‘notes’, ‘notes_url’, ‘action_url’, ‘icon_image’, ‘icon_image_alt’. You may use them for all available backends (and web interfaces can use them again). If you require additional custom attributes, the ‘vars’ dictionary is still available. Last but not least, global constants do not have the ‘Icinga’ prefix anymore.

Mapping Host Status

Aside from configuration changes, we’ve thought about the decision to make a service the virtual host check, and require everyone to follow in that spirit. Interfaces like DB IDO, Livestatus, Status files, Performance data writer were just mapping the host check’s service for that reason and duplicating the data somehow.
Furthermore the handling of a critical service is influenced by different rules and thresholds to a host being down – be it for notifications, SLA reporting or dependencies.

Thanks to our 5th (felt like the 1000th) discussion on that topic, the host ‘check_command’ is now back on duty. This means that the default configuration does not map ‘ping4’ as a virtual host check but ships the ‘hostalive’ check command with different thresholds as defined host check. The idea of cloning a service’s state into a host is not gone – we found it very useful, and will properly implement a general ‘clone state’ functionality for all checkable objects (hosts and services). The ‘hostalive’ check command is shipped using  ITL.

template Host "generic-host" {
  max_check_attempts = 5
  check_interval = 5m
  retry_interval = 1m

  check_command = "hostalive"
}

This is also visible when providing host performance data in PerfdataWriter/GraphiteWriter features. Meanwhile DB IDO, Livestatus and the status files fetch their data from the defined host state (no direct visible change).

Finally…

The updated example configuration in /etc/icinga2/conf.d reflects all those changes (and is incompatible with previous configurations). The example ‘localhost’ configuration has been moved into a separate directory named ‘hosts’. An experimental not yet documented feature is optional command arguments for commands – for details, see #5933. We plan to finish this one in the next version.

If you have made it this far, you are most certainly ready to test. So please, download away and share your thoughts with us on the usual channels.