mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-26 23:24:09 +02:00
Merge branch 'feature/config-5870' into next
Fixes #5845 Fixes #5848 Fixes #5870 Fixes #5872 Fixes #5875 Fixes #5876 Fixes #5878 Fixes #5880 Fixes #5882 Fixes #5883 Fixes #5884 Fixes #5885
This commit is contained in:
commit
fd0bc8d321
@ -3,7 +3,9 @@
|
||||
* in the conf.d directory (e.g. one per host). By default all *.conf
|
||||
* files in this directory are included.
|
||||
*/
|
||||
object Host "nsca-ng" inherits "generic-host" {
|
||||
object Host "nsca-ng" {
|
||||
import "generic-host",
|
||||
|
||||
display_name = "nsca-ng test",
|
||||
|
||||
services["PassiveService1"] = {
|
||||
@ -15,4 +17,4 @@ object Host "nsca-ng" inherits "generic-host" {
|
||||
templates = [ "generic-service" ],
|
||||
check_command = "passive",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -17,5 +17,5 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type CheckerComponent {
|
||||
%type CheckerComponent {
|
||||
}
|
||||
|
@ -17,22 +17,22 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type ClusterListener {
|
||||
%attribute string "cert_path",
|
||||
%type ClusterListener {
|
||||
%attribute %string "cert_path",
|
||||
%require "cert_path",
|
||||
|
||||
%attribute string "key_path",
|
||||
%attribute %string "key_path",
|
||||
%require "key_path",
|
||||
|
||||
%attribute string "ca_path",
|
||||
%attribute %string "ca_path",
|
||||
%require "ca_path",
|
||||
|
||||
%attribute string "crl_path",
|
||||
%attribute %string "crl_path",
|
||||
|
||||
%attribute string "bind_host",
|
||||
%attribute string "bind_port",
|
||||
%attribute %string "bind_host",
|
||||
%attribute %string "bind_port",
|
||||
|
||||
%attribute array "peers" {
|
||||
%attribute %array "peers" {
|
||||
%attribute name(Endpoint) "*"
|
||||
}
|
||||
}
|
||||
|
@ -17,23 +17,23 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type StatusDataWriter {
|
||||
%attribute string "status_path",
|
||||
%attribute string "objects_path",
|
||||
%attribute number "update_interval"
|
||||
%type StatusDataWriter {
|
||||
%attribute %string "status_path",
|
||||
%attribute %string "objects_path",
|
||||
%attribute %number "update_interval"
|
||||
}
|
||||
|
||||
type ExternalCommandListener {
|
||||
%attribute string "command_path"
|
||||
%type ExternalCommandListener {
|
||||
%attribute %string "command_path"
|
||||
}
|
||||
|
||||
type CompatLogger {
|
||||
%type CompatLogger {
|
||||
%validator "ValidateRotationMethod",
|
||||
|
||||
%attribute string "log_dir",
|
||||
%attribute string "rotation_method"
|
||||
%attribute %string "log_dir",
|
||||
%attribute %string "rotation_method"
|
||||
}
|
||||
|
||||
type CheckResultReader {
|
||||
%attribute string "spool_dir"
|
||||
%type CheckResultReader {
|
||||
%attribute %string "spool_dir"
|
||||
}
|
||||
|
@ -17,15 +17,15 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type IdoMysqlConnection inherits DbConnection {
|
||||
%attribute string "host",
|
||||
%attribute number "port",
|
||||
%type IdoMysqlConnection %inherits DbConnection {
|
||||
%attribute %string "host",
|
||||
%attribute %number "port",
|
||||
|
||||
%attribute string "user",
|
||||
%attribute string "password",
|
||||
%attribute %string "user",
|
||||
%attribute %string "password",
|
||||
|
||||
%attribute string "database",
|
||||
%attribute %string "database",
|
||||
|
||||
%attribute string "instance_name",
|
||||
%attribute string "instance_description"
|
||||
%attribute %string "instance_name",
|
||||
%attribute %string "instance_description"
|
||||
}
|
||||
|
@ -17,15 +17,15 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type IdoPgsqlConnection inherits DbConnection {
|
||||
%attribute string "host",
|
||||
%attribute number "port",
|
||||
%type IdoPgsqlConnection %inherits DbConnection {
|
||||
%attribute %string "host",
|
||||
%attribute %number "port",
|
||||
|
||||
%attribute string "user",
|
||||
%attribute string "password",
|
||||
%attribute %string "user",
|
||||
%attribute %string "password",
|
||||
|
||||
%attribute string "database",
|
||||
%attribute %string "database",
|
||||
|
||||
%attribute string "instance_name",
|
||||
%attribute string "instance_description"
|
||||
%attribute %string "instance_name",
|
||||
%attribute %string "instance_description"
|
||||
}
|
||||
|
@ -17,5 +17,5 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type Demo {
|
||||
%type Demo {
|
||||
}
|
||||
|
@ -17,14 +17,14 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type LivestatusListener {
|
||||
%type LivestatusListener {
|
||||
%validator "ValidateSocketType",
|
||||
|
||||
%attribute string "socket_type",
|
||||
%attribute %string "socket_type",
|
||||
|
||||
%attribute string "socket_path",
|
||||
%attribute string "bind_host",
|
||||
%attribute string "bind_port",
|
||||
%attribute %string "socket_path",
|
||||
%attribute %string "bind_host",
|
||||
%attribute %string "bind_port",
|
||||
|
||||
%attribute string "compat_log_path",
|
||||
%attribute %string "compat_log_path",
|
||||
}
|
||||
|
@ -17,5 +17,5 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type NotificationComponent {
|
||||
%type NotificationComponent {
|
||||
}
|
||||
|
@ -17,13 +17,13 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type PerfdataWriter {
|
||||
%attribute string "perfdata_path",
|
||||
%attribute string "format_template",
|
||||
%attribute number "rotation_interval"
|
||||
%type PerfdataWriter {
|
||||
%attribute %string "perfdata_path",
|
||||
%attribute %string "format_template",
|
||||
%attribute %number "rotation_interval"
|
||||
}
|
||||
|
||||
type GraphiteWriter {
|
||||
%attribute string "host",
|
||||
%attribute string "port",
|
||||
%type GraphiteWriter {
|
||||
%attribute %string "host",
|
||||
%attribute %string "port",
|
||||
}
|
||||
|
@ -48,14 +48,15 @@ for line in out.split("\n"):
|
||||
plugin = "".join([chr(int(ch)) for ch in plugin])
|
||||
plugins.append(plugin)
|
||||
|
||||
print("template Host \"snmp-extend:%s\" {" % (ipaddr))
|
||||
print(" macros[\"community\"] = \"%s\"," % (community))
|
||||
for plugin in plugins:
|
||||
print(" services[\"%s\"] = {" % (plugin))
|
||||
print(" templates = [ \"snmp-extend-service\" ],")
|
||||
print(" check_command = \"snmp-extend\",")
|
||||
print(" macros[\"plugin\"] = \"%s\"" % (plugin))
|
||||
print(" },")
|
||||
print("}")
|
||||
print("apply Service \"%s\" {" % (plugin))
|
||||
print(" import \"snmp-extend-service\",")
|
||||
print()
|
||||
print(" check_command = \"snmp-extend\",")
|
||||
print(" macros[\"community\"] = \"%s\"," % (community))
|
||||
print()
|
||||
print(" assign where host.macros.address == \"%s\"" % (ipaddr))
|
||||
print("}")
|
||||
print()
|
||||
|
||||
sys.exit(0)
|
||||
|
@ -106,22 +106,23 @@ def process_host(host_element):
|
||||
hosts[name] = { "name": name, "address": address, "services": services }
|
||||
|
||||
def print_host(host):
|
||||
print "object Host \"%s\" inherits \"discovered-host\" {" % (host["name"])
|
||||
print "\tmacros[\"address\"] = \"%s\"," % (host["address"])
|
||||
|
||||
for serv, service in host["services"].iteritems():
|
||||
print ""
|
||||
print "\tservices[\"%s\"] = {" % (serv)
|
||||
print "\t\ttemplates = [ \"discovered-service\" ],"
|
||||
print ""
|
||||
print "\t\tcheck_command = \"%s\"," % (service["command"])
|
||||
print ""
|
||||
print "\t\tmacros[\"port\"] = %s" % (service["port"])
|
||||
print "\t},"
|
||||
|
||||
print "object Host \"%s\" {" % (host["name"])
|
||||
print "\timport \"discovered-host\","
|
||||
print ""
|
||||
print "\tmacros.address = \"%s\"," % (host["address"])
|
||||
print "}"
|
||||
print ""
|
||||
|
||||
for serv, service in host["services"].iteritems():
|
||||
print "apply Service \"%s\" {" % (serv)
|
||||
print "\timport \"discovered-service\","
|
||||
print ""
|
||||
print "\tcheck_command = \"%s\"," % (service["command"])
|
||||
print ""
|
||||
print "\tmacros.port = %s" % (service["port"])
|
||||
print "}"
|
||||
print ""
|
||||
|
||||
for arg in sys.argv[1:]:
|
||||
# Expects XML output from 'nmap -oX'
|
||||
dom = parse(arg)
|
||||
|
@ -2,10 +2,11 @@
|
||||
|
||||
## <a id="what-is-icinga2"></a> What is Icinga 2?
|
||||
|
||||
Icinga 2 is an enterprise-grade open source monitoring system which keeps watch over networks
|
||||
and any conceivable network resource, notifies the user of errors and recoveries and generates
|
||||
performance data for reporting. Scalable and extensible, Icinga 2 can monitor complex, large
|
||||
environments across dispersed locations.
|
||||
Icinga 2 is an open source monitoring system which checks the availability of your
|
||||
network resources, notifies users of outages and generates performance data for reporting.
|
||||
|
||||
Scalable and extensible, Icinga 2 can monitor complex, large environments across
|
||||
multiple locations.
|
||||
|
||||
## <a id="licensing"></a> Licensing
|
||||
|
||||
|
@ -4,14 +4,14 @@ First of all you will have to install Icinga 2. The preferred way of doing this
|
||||
is to use the official Debian or RPM package repositories depending on which
|
||||
operating system and distribution you are running.
|
||||
|
||||
Distribution |Repository URL
|
||||
Distribution | Repository URL
|
||||
------------------------|---------------------------
|
||||
Debian |http://packages.icinga.org/debian/
|
||||
Ubuntu |http://packages.icinga.org/ubuntu/
|
||||
RHEL/CentOS 5 |http://packages.icinga.org/epel/5/release/
|
||||
RHEL/CentOS 6 |http://packages.icinga.org/epel/6/release/
|
||||
OpenSUSE 12.3 |http://packages.icinga.org/openSUSE/12.3/release/
|
||||
SLES 11 SP3 |http://packages.icinga.org/SUSE/sles11-sp3/release/
|
||||
Debian | http://packages.icinga.org/debian/
|
||||
Ubuntu | http://packages.icinga.org/ubuntu/
|
||||
RHEL/CentOS 5 | http://packages.icinga.org/epel/5/release/
|
||||
RHEL/CentOS 6 | http://packages.icinga.org/epel/6/release/
|
||||
OpenSUSE 12.3 | http://packages.icinga.org/openSUSE/12.3/release/
|
||||
SLES 11 SP3 | http://packages.icinga.org/SUSE/sles11-sp3/release/
|
||||
|
||||
Packages for distributions other than the ones listed above may also be
|
||||
available. Please check http://packages.icinga.org/ to see if packages
|
||||
@ -29,8 +29,7 @@ to install the `icinga2` package.
|
||||
> **Note**
|
||||
>
|
||||
> On RHEL/CentOS and SLES you will need to use `chkconfig` to enable the
|
||||
`icinga2` service. You can manually start Icinga 2 using `/etc/init.d/icinga2
|
||||
start`.
|
||||
> `icinga2` service. You can manually start Icinga 2 using `/etc/init.d/icinga2 start`.
|
||||
|
||||
Some parts of Icinga 2's functionality are available as separate packages:
|
||||
|
||||
@ -114,7 +113,7 @@ The `conf.d/macros.conf` file can be used to define global macros:
|
||||
/**
|
||||
* Global macros
|
||||
*/
|
||||
set IcingaMacros = {
|
||||
const IcingaMacros = {
|
||||
plugindir = "/usr/local/icinga/libexec"
|
||||
}
|
||||
|
||||
@ -131,70 +130,86 @@ The `conf.d/localhost.conf` file contains our first host definition:
|
||||
* files in this directory are included.
|
||||
*/
|
||||
object Host "localhost" {
|
||||
services["ping4"] = {
|
||||
templates = [ "generic-service" ],
|
||||
import "linux-server",
|
||||
|
||||
check_command = "ping4"
|
||||
},
|
||||
|
||||
services["ping6"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "ping6"
|
||||
},
|
||||
|
||||
services["http"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "http_ip"
|
||||
},
|
||||
|
||||
services["ssh"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "ssh"
|
||||
},
|
||||
|
||||
services["load"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "load"
|
||||
},
|
||||
|
||||
services["processes"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "processes"
|
||||
},
|
||||
|
||||
services["users"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "users"
|
||||
},
|
||||
|
||||
services["disk"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "disk"
|
||||
},
|
||||
|
||||
macros = {
|
||||
address = "127.0.0.1",
|
||||
address6 = "::1",
|
||||
},
|
||||
|
||||
check = "ping4",
|
||||
macros.address = "127.0.0.1",
|
||||
macros.address6 = "::1"
|
||||
}
|
||||
|
||||
|
||||
This defines a host named "localhost" which has a couple of services. Services
|
||||
may inherit from one or more service templates.
|
||||
|
||||
The command objects `ping4`, `ping6`, `http_ip`, `ssh`, `load`, `processes`, `users`
|
||||
and `disk` are all provided by the Icinga Template Library (short ITL) which
|
||||
we enabled earlier by including the `itl/itl.conf` configuration file.
|
||||
This defines the host `localhost`. The `import` keyword is used to import
|
||||
the `linux-server` template which takes care of setting up the `ping4` and
|
||||
`ping6` services for the host as well as adding the host to the `linux-servers`
|
||||
host group.
|
||||
|
||||
The `macros` attribute can be used to define macros that are available for all
|
||||
services which belong to this host. Most of the templates in the Icinga Template
|
||||
Library require an `address` macro.
|
||||
|
||||
apply Service "icinga" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "icinga",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply Service "http" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "http_ip",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply Service "ssh" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "ssh",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply Service "load" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "load",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply ScheduledDowntime "backup-downtime" {
|
||||
import "backup-downtime",
|
||||
|
||||
assign where service.host == "localhost" && service.short_name == "load"
|
||||
}
|
||||
|
||||
apply Service "processes" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "processes",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply Service "users" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "users",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply Service "disk" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "disk",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
The `apply` keyword can be used to dynamically create services for all hosts based
|
||||
on rules.
|
||||
|
||||
The command objects `http_ip`, `ssh`, `load`, `processes`, `users`
|
||||
and `disk` are all provided by the Icinga Template Library (short ITL) which
|
||||
we enabled earlier by including the `itl/itl.conf` configuration file.
|
||||
|
@ -1,17 +1,18 @@
|
||||
## <a id="setting-up-check-plugins"></a> Setting up Check Plugins
|
||||
|
||||
On its own Icinga 2 does not know how to check external services. The
|
||||
[Monitoring Plugins Project](https://www.monitoring-plugins.org/) (former
|
||||
Nagios Plugins) provides an extensive set of plugins which can be used by
|
||||
Icinga 2 to check whether services are working properly.
|
||||
[Monitoring Plugins Project](https://www.monitoring-plugins.org/) provides
|
||||
an extensive set of plugins which can be used with Icinga 2 to check whether
|
||||
services are working properly.
|
||||
|
||||
The recommended way of installing these standard plugins is to use your
|
||||
distribution's package manager.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> The `Nagios Plugins` project was renamed to `Monitoring Plugins` project
|
||||
> in Jan 2014. Therefore package names may still reflect the old name.
|
||||
> The `Nagios Plugins` project was renamed to `Monitoring Plugins`
|
||||
> in January 2014. At the time of this writing the packages are still
|
||||
> using the old name.
|
||||
|
||||
For your convenience here is a list of package names for some of the more
|
||||
popular operating systems/distributions:
|
||||
@ -27,29 +28,41 @@ Depending on which directory your plugins are installed into you may need to
|
||||
update the `plugindir` macro in your Icinga 2 configuration. This macro is used
|
||||
by the service templates contained in the Icinga Template Library to determine
|
||||
where to find the plugin binaries.
|
||||
Alternatively you can create a symbolic link pointing to the installation path
|
||||
of the plugins.
|
||||
|
||||
### <a id="integrate-additional-plugins"></a> Integrate Additional Plugins
|
||||
|
||||
You may require a custom check plugin not provided by the official Nagios plugins.
|
||||
All existing Nagios or Icinga 1.x plugins found on public community websites
|
||||
will work with Icinga 2 as well.
|
||||
For some services you may need additional check plugins which are not provided
|
||||
by the official Monitoring Plugins project.
|
||||
|
||||
All existing Nagios or Icinga 1.x plugins should work with Icinga 2. Here's a
|
||||
list of popular community sites which host check plugins:
|
||||
|
||||
* [MonitoringExchange](https://www.monitoringexchange.org)
|
||||
* [Icinga Wiki](https://wiki.icinga.org)
|
||||
|
||||
Once you have downloaded the plugin copy it into the directory defined by the global
|
||||
`IcingaMacro` `$plugindir$` and make sure that the user the Icinga daemon is running as
|
||||
can execute the the plugin binary. Plugins should support the `--help` parameter
|
||||
providing details how they have to be called in your command definition later on.
|
||||
The recommended way of setting up these plugins is to copy them to a common directory
|
||||
and creating an extra global macro, e.g. `customplugindir` in your `macros.conf`
|
||||
configuration file:
|
||||
|
||||
# cp check_snmp_int.pl /usr/local/icinga/libexec/
|
||||
# chmod +x /usr/local/icinga/libexec/check_snmp_int.pl
|
||||
|
||||
# /usr/local/icinga/libexec/check_snmp_int.pl --help
|
||||
# cp check_snmp_int.pl /opt/plugins
|
||||
# chmod +x /opt/plugins/check_snmp_int.pl
|
||||
|
||||
# cat /etc/icinga2/conf/macros.conf
|
||||
/**
|
||||
* Global macros
|
||||
*/
|
||||
const IcingaMacros = {
|
||||
plugindir = "/usr/lib/nagios/plugins",
|
||||
customplugindir = "/opt/monitoring"
|
||||
}
|
||||
|
||||
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/plugins/check_snmp_int.pl --help
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> You may require additional libraries for scripts. Please consult the installation
|
||||
> You may require additional libraries for some plugins. Please consult the installation
|
||||
> documentation and/or README for their installation requirements.
|
||||
|
@ -32,7 +32,7 @@ Icinga 2's init script is installed in `/etc/init.d/icinga2` by default:
|
||||
-V [ --version ] show version information
|
||||
-l [ --library ] arg load a library
|
||||
-I [ --include ] arg add include search directory
|
||||
-D [ --define] args define a constant
|
||||
-D [ --define] args define a constant
|
||||
-c [ --config ] arg parse a configuration file
|
||||
-C [ --validate ] exit after validating the configuration
|
||||
-Z [ --no-validate ] skip validating the configuration
|
||||
|
@ -15,17 +15,18 @@ on the same physical device.
|
||||
Here is an example of a host object which defines two child services:
|
||||
|
||||
object Host "my-server1" {
|
||||
services["ping4"] = {
|
||||
check_command = "ping4"
|
||||
},
|
||||
macros.address = "10.0.0.1",
|
||||
check = "ping4"
|
||||
}
|
||||
|
||||
services["http"] = {
|
||||
check_command = "http_ip"
|
||||
},
|
||||
apply Service "ping4" {
|
||||
check_command = "ping4"
|
||||
assign where host.name == "my-server1"
|
||||
}
|
||||
|
||||
check = "ping4",
|
||||
|
||||
macros["address"] = "10.0.0.1"
|
||||
apply Service "http" {
|
||||
check_command = "http_ip"
|
||||
assign where host.name == "my-server1"
|
||||
}
|
||||
|
||||
The example host `my-server1` creates two services which belong to this host:
|
||||
|
@ -59,39 +59,37 @@ then use these macros on the command line.
|
||||
> the service using the check command `disk`. The macros can also
|
||||
> be inherited from a parent template using additive inheritance (`+=`).
|
||||
|
||||
object CheckCommand "disk" inherits "plugin-check-command" {
|
||||
object CheckCommand "disk" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_disk",
|
||||
"-w", "$wfree$%",
|
||||
"-c", "$cfree$%"
|
||||
],
|
||||
|
||||
macros += {
|
||||
wfree = 20,
|
||||
cfree = 10,
|
||||
}
|
||||
macros.wfree = 20,
|
||||
macros.cfree = 10
|
||||
}
|
||||
|
||||
The host `localhost` with the service `disk` checks all disks with modified
|
||||
macros (warning thresholds at `10%`, critical thresholds at `5%` free disk
|
||||
space).
|
||||
|
||||
object Host "localhost" inherits "generic-host" {
|
||||
object Host "localhost" {
|
||||
import "generic-host",
|
||||
|
||||
macros.address = "127.0.0.1",
|
||||
macros.address6 = "::1"
|
||||
}
|
||||
|
||||
services["disk"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "disk",
|
||||
macros += {
|
||||
wfree = 10,
|
||||
cfree = 5
|
||||
}
|
||||
},
|
||||
|
||||
macros = {
|
||||
address = "127.0.0.1",
|
||||
address6 = "::1",
|
||||
},
|
||||
apply Service "disk" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "disk",
|
||||
|
||||
macros.wfree = 10,
|
||||
macros.cfree = 5
|
||||
}
|
||||
|
||||
|
||||
@ -112,7 +110,9 @@ notification itself (`email` macro attribute provided as `$USERMACRO$`).
|
||||
If you require default macro definitions, you can add a macro dictionary as shown for the
|
||||
`CheckCommand` object.
|
||||
|
||||
object NotificationCommand "mail-service-notification" inherits "plugin-notification-command" {
|
||||
object NotificationCommand "mail-service-notification" {
|
||||
import "plugin-notification-command",
|
||||
|
||||
command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
|
||||
|
||||
export_macros = [
|
||||
@ -187,7 +187,9 @@ send a check result using the `process_check_result` script forcibly
|
||||
changing the service state back to `OK` (`-r 0`) providing some debug
|
||||
information in the check output (`-o`).
|
||||
|
||||
object EventCommand "plugin-event-process-check-result" inherits "plugin-event-command" {
|
||||
object EventCommand "plugin-event-process-check-result" {
|
||||
import "plugin-event-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/process_check_result",
|
||||
"-H",
|
||||
@ -202,5 +204,3 @@ information in the check output (`-o`).
|
||||
"Event Handler triggered in state '$SERVICESTATE$' with output '$SERVICEOUTPUT$'."
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,7 +21,9 @@ using the available runtime macros for output formatting.
|
||||
|
||||
Here is an example of a command definition which uses user-defined macros:
|
||||
|
||||
object CheckCommand "my-ping" inherits "plugin-check-command" {
|
||||
object CheckCommand "my-ping" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_ping",
|
||||
"-4",
|
||||
@ -73,14 +75,12 @@ values for some of the latency thresholds and timeouts.
|
||||
When using the `my-ping` command you can override all or some of the macros
|
||||
in the service definition like this:
|
||||
|
||||
object Host "my-server1" {
|
||||
services["ping"] = {
|
||||
check_command = "my-ping",
|
||||
apply Service "ping" {
|
||||
check_command = "my-ping",
|
||||
|
||||
macros["packets"] = 10 // Overrides the default value of 5 given in the command
|
||||
},
|
||||
macros.packets = 10 // Overrides the default value of 5 given in the command
|
||||
|
||||
macros["address"] = "10.0.0.1"
|
||||
assign where host.name == "my-server1"
|
||||
}
|
||||
|
||||
If a macro isn't defined anywhere an empty value is used and a warning is
|
||||
@ -126,8 +126,10 @@ Node 2:
|
||||
|
||||
CheckCommand definition:
|
||||
|
||||
object CheckCommand "whatever" inherits "plugin-check-command" {
|
||||
command = "$plugindir$/check_whatever"
|
||||
object CheckCommand "whatever" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = "$plugindir$/check_whatever"
|
||||
}
|
||||
|
||||
On Node 1, this will be evaluated into `/usr/lib/icinga/plugins/check_whatever`.
|
||||
@ -246,18 +248,20 @@ be exported as environment variables prior to executing the command.
|
||||
This is useful for example for hiding sensitive information on the command line output
|
||||
when passing credentials to database checks:
|
||||
|
||||
object CheckCommand "mysql-health" inherits "plugin-check-command" {
|
||||
command = "$plugindir$/check_mysql -H $address$ -d $db$",
|
||||
/* default macro values */
|
||||
macros = {
|
||||
"MYSQLUSER" = "icinga_check",
|
||||
"MYSQLPASS" = "1c1ng42r0xx"
|
||||
},
|
||||
object CheckCommand "mysql-health" {
|
||||
import "plugin-check-command",
|
||||
|
||||
export_macros = [
|
||||
"MYSQLUSER",
|
||||
"MYSQLPASS"
|
||||
]
|
||||
command = "$plugindir$/check_mysql -H $address$ -d $db$",
|
||||
/* default macro values */
|
||||
macros = {
|
||||
"MYSQLUSER" = "icinga_check",
|
||||
"MYSQLPASS" = "1c1ng42r0xx"
|
||||
},
|
||||
|
||||
export_macros = [
|
||||
"MYSQLUSER",
|
||||
"MYSQLPASS"
|
||||
]
|
||||
}
|
||||
|
||||
### <a id="configuration-macros"></a> Configuration Macros
|
||||
|
@ -58,7 +58,9 @@ your environment.
|
||||
There are various macros available at runtime execution of the `NotificationCommand`.
|
||||
The example below may or may not fit your needs.
|
||||
|
||||
object NotificationCommand "mail-service-notification" inherits "plugin-notification-command" {
|
||||
object NotificationCommand "mail-service-notification" {
|
||||
import "plugin-notification-command",
|
||||
|
||||
command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
|
||||
|
||||
export_macros = [
|
||||
@ -111,21 +113,17 @@ to the defined notifications. That way you'll save duplicated attributes in each
|
||||
>
|
||||
> The `TimePeriod` `24x7` is shipped as example configuration with Icinga 2.
|
||||
|
||||
Use the `generic-notification` template for the `mail` notification defined
|
||||
inline to the host's service `ping4` and assign the `icingaadmin` user.
|
||||
Use the `apply` keyword to create `Notification` objects for your services:
|
||||
|
||||
object Host "localhost" {
|
||||
services["ping4"] = {
|
||||
notifications["mail"] = {
|
||||
templates = [ "generic-notification" ],
|
||||
notification_command = "mail-notification",
|
||||
users = [ "icingaadmin" ],
|
||||
}
|
||||
}
|
||||
apply Notification "mail" {
|
||||
import "generic-notification",
|
||||
|
||||
notification_command = "mail-notification",
|
||||
users = [ "icingaadmin" ],
|
||||
|
||||
assign where service.short_name == "ping4"
|
||||
}
|
||||
|
||||
Notifications can be defined in `Service` templates inherited to the objects.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Instead of assigning users to notifications, you can also add the `user_groups`
|
||||
@ -154,7 +152,7 @@ notifications between start and end time.
|
||||
|
||||
object User "icinga-oncall-2nd-level" {
|
||||
display_name = "Icinga 2nd Level",
|
||||
enable_notifications = 1,
|
||||
enable_notifications = true,
|
||||
|
||||
macros = {
|
||||
"mobile" = "+49123456781"
|
||||
@ -163,10 +161,9 @@ notifications between start and end time.
|
||||
|
||||
object User "icinga-oncall-1st-level" {
|
||||
display_name = "Icinga 1st Level",
|
||||
enable_notifications = 1,
|
||||
enable_notifications = true,
|
||||
|
||||
macros = {
|
||||
"mobile" = "+49123456782"
|
||||
macros.mobile = "+49123456782"
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,35 +195,35 @@ If the problem does not get resolved or acknowledged preventing further notifica
|
||||
the `escalation-sms-1st-level` user will be escalated `1h` after the initial problem was
|
||||
notified, but only for one hour (`2h` as `end` key for the `times` dictionary).
|
||||
|
||||
object Host "localhost" {
|
||||
services["ping4"] = {
|
||||
notifications["mail"] = {
|
||||
templates = [ "generic-notification" ],
|
||||
notification_command = "mail-notification",
|
||||
users = [ "icingaadmin" ],
|
||||
},
|
||||
notifications["escalation-sms-2nd-level"] = {
|
||||
templates = [ "generic-notification" ],
|
||||
notification_command = "sms-notification",
|
||||
users = [ "icinga-oncall-2nd-level" ],
|
||||
apply Notification "mail" {
|
||||
import "generic-notification",
|
||||
notification_command = "mail-notification",
|
||||
users = [ "icingaadmin" ],
|
||||
|
||||
assign where service.short_name == "ping4"
|
||||
}
|
||||
|
||||
apply Notification "escalation-sms-2nd-level" {
|
||||
import "generic-notification",
|
||||
notification_command = "sms-notification",
|
||||
users = [ "icinga-oncall-2nd-level" ],
|
||||
|
||||
times = {
|
||||
begin = 30m,
|
||||
end = 1h
|
||||
}
|
||||
},
|
||||
notifications["escalation-sms-1st-level"] = {
|
||||
templates = [ "generic-notification" ],
|
||||
notification_command = "sms-notification",
|
||||
users = [ "icinga-oncall-1st-level" ],
|
||||
|
||||
times = {
|
||||
begin = 1h,
|
||||
end = 2h
|
||||
}
|
||||
}
|
||||
times = {
|
||||
begin = 30m,
|
||||
end = 1h
|
||||
}
|
||||
}
|
||||
|
||||
apply Notification "escalation-sms-1st-level" {
|
||||
import "generic-notification",
|
||||
notification_command = "sms-notification",
|
||||
users = [ "icinga-oncall-1st-level" ],
|
||||
|
||||
times = {
|
||||
begin = 1h,
|
||||
end = 2h
|
||||
}
|
||||
}
|
||||
|
||||
> **Note**
|
||||
>
|
||||
@ -243,18 +240,12 @@ dictionary and set `begin = 15m` as key and value if you want to suppress notifi
|
||||
in the first 15 minutes. Leave out the `end` key - if not set, Icinga 2 will not check against any
|
||||
end time for this notification.
|
||||
|
||||
object Host "localhost" {
|
||||
services["ping4"] = {
|
||||
notifications["mail"] = {
|
||||
templates = [ "generic-notification" ],
|
||||
notification_command = "mail-notification",
|
||||
users = [ "icingaadmin" ],
|
||||
apply Notification "mail" {
|
||||
import "generic-notification",
|
||||
notification_command = "mail-notification",
|
||||
users = [ "icingaadmin" ],
|
||||
|
||||
times = {
|
||||
begin = 15m // delay first notification
|
||||
}
|
||||
}
|
||||
}
|
||||
times.begin = 15m // delay first notification
|
||||
}
|
||||
|
||||
> **Note**
|
||||
|
@ -7,42 +7,28 @@ For example, rather than manually creating a `ping` service object for each of
|
||||
your hosts you can use templates to avoid having to copy & paste parts of your
|
||||
configuration:
|
||||
|
||||
template Host "linux-server" {
|
||||
services["ping"] = {
|
||||
check_command = "ping4"
|
||||
},
|
||||
|
||||
check = "ping"
|
||||
template Service "generic-service" {
|
||||
max_check_attempts = 3,
|
||||
check_interval = 5m,
|
||||
retry_interval = 1m,
|
||||
enable_perfdata = true
|
||||
}
|
||||
|
||||
object Host "my-server1" inherits "linux-server" {
|
||||
macros["address"] = "10.0.0.1"
|
||||
apply Service "ping4" {
|
||||
import "generic-service",
|
||||
check_command = "ping4",
|
||||
assign where host.macros.address
|
||||
}
|
||||
|
||||
object Host "my-server2" inherits "linux-server" {
|
||||
macros["address"] = "10.0.0.2"
|
||||
apply Service "ping6" {
|
||||
import "generic-service",
|
||||
check_command = "ping6",
|
||||
assign where host.macros.address6
|
||||
}
|
||||
|
||||
In this example both `my-server1` and `my-server2` each get their own `ping`
|
||||
service check. Each host gets its own host `check` defined as the `ping`
|
||||
service too.
|
||||
In this example both `ping4` and `ping6` services inherit properties from the
|
||||
template `generic-service`.
|
||||
|
||||
Objects as well as templates themselves can inherit from an arbitrary number of
|
||||
Objects as well as templates themselves can import an arbitrary number of
|
||||
templates. Attributes inherited from a template can be overridden in the
|
||||
object if necessary.
|
||||
|
||||
Templates can also be used in service and notification definitions using the
|
||||
`templates` attribute:
|
||||
|
||||
template Service "weekend-service" {
|
||||
check_interval = 0.5m,
|
||||
check_period = "weekend"
|
||||
}
|
||||
|
||||
object Host "my-server1" {
|
||||
services["backup"] {
|
||||
check_command = "backup-check",
|
||||
|
||||
templates = [ "weekend-service" ]
|
||||
}
|
||||
}
|
||||
|
@ -37,17 +37,16 @@ Then add your hosts to this hostgroup
|
||||
|
||||
template Host "windows-mssql-template" {
|
||||
groups = [ "windows" ],
|
||||
macros = {
|
||||
"mssql_port" = 1433
|
||||
macros.mssql_port = 1433
|
||||
}
|
||||
}
|
||||
|
||||
object Host "mssql-srv1" {
|
||||
templates = [ "windows-mssql-template" ]
|
||||
import "windows-mssql-template"
|
||||
}
|
||||
|
||||
object Host "mssql-srv2" {
|
||||
templates = [ "windows-mssql-template" ]
|
||||
import "windows-mssql-template"
|
||||
}
|
||||
|
||||
This can be done for service and user groups the same way. Additionally
|
||||
@ -61,24 +60,20 @@ the user groups are associated as attributes in `Notification` objects.
|
||||
groups = [ "windows-mssql-admins" ]
|
||||
}
|
||||
|
||||
object User "win-mssql-noc" inherits "generic-windows-mssql-users" {
|
||||
macros = {
|
||||
"email" = "noc@company.com"
|
||||
}
|
||||
object User "win-mssql-noc" {
|
||||
import "generic-windows-mssql-users",
|
||||
|
||||
macros.email = "noc@example.com"
|
||||
}
|
||||
|
||||
object User "win-mssql-ops" inherits "generic-windows-mssql-users" {
|
||||
macros = {
|
||||
"email" = "ops@company.com"
|
||||
}
|
||||
object User "win-mssql-ops" {
|
||||
import "generic-windows-mssql-users",
|
||||
|
||||
macros.email = "ops@example.com"
|
||||
}
|
||||
|
||||
object Host "localhost" {
|
||||
services["ping4"] = {
|
||||
notifications["mail"] = {
|
||||
templates = [ "generic-notification" ],
|
||||
notification_command = "mail-notification",
|
||||
user_groups = [ "windows-admins" ],
|
||||
}
|
||||
}
|
||||
apply Service "ping4" {
|
||||
import "generic-notification",
|
||||
notification_command = "mail-notification",
|
||||
user_groups = [ "windows-admins" ],
|
||||
}
|
||||
|
@ -31,7 +31,9 @@ If you don't set any `check_period` or `notification_period` attribute
|
||||
on your configuration objects Icinga 2 assumes `24x7` as time period
|
||||
as shown below.
|
||||
|
||||
object TimePeriod "24x7" inherits "legacy-timeperiod" {
|
||||
object TimePeriod "24x7" {
|
||||
import "legacy-timeperiod",
|
||||
|
||||
display_name = "Icinga 2 24x7 TimePeriod",
|
||||
ranges = {
|
||||
"monday" = "00:00-24:00",
|
||||
@ -48,7 +50,9 @@ If your operation staff should only be notified during workhours
|
||||
create a new timeperiod named `workhours` defining a work day with
|
||||
09:00 to 17:00.
|
||||
|
||||
object TimePeriod "workhours" inherits "legacy-timeperiod" {
|
||||
object TimePeriod "workhours" {
|
||||
import "legacy-timeperiod",
|
||||
|
||||
display_name = "Icinga 2 8x5 TimePeriod",
|
||||
ranges = {
|
||||
"monday" = "09:00-17:00",
|
||||
@ -62,13 +66,12 @@ create a new timeperiod named `workhours` defining a work day with
|
||||
Assign the timeperiod as `notification_period` to the `Notification`
|
||||
object then.
|
||||
|
||||
object Host "localhost" {
|
||||
services["ping4"] = {
|
||||
notifications["mail"] = {
|
||||
templates = [ "generic-notification" ],
|
||||
notification_command = "mail-notification",
|
||||
users = [ "icingaadmin" ],
|
||||
notification_period = "workhours"
|
||||
}
|
||||
}
|
||||
apply Notification "mail" {
|
||||
import "generic-notification",
|
||||
|
||||
notification_command = "mail-notification",
|
||||
users = [ "icingaadmin" ],
|
||||
notification_period = "workhours"
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
@ -2,26 +2,19 @@
|
||||
|
||||
Icinga 2 supports three different types of logging:
|
||||
|
||||
* File logging (local Icinga 2 log file)
|
||||
* Syslog facility logging (system's syslog application)
|
||||
* File logging
|
||||
* Syslog (on *NIX-based operating systems)
|
||||
* Console logging (`STDOUT` on tty)
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> You can define multiple logging objects at once.
|
||||
You can enable additional loggers using the `icinga2-enable-feature`
|
||||
and `icinga2-disable-feature` commands to configure loggers:
|
||||
|
||||
The most common scenario will be logging Icinga 2's output to
|
||||
syslog with severity `information`.
|
||||
|
||||
object SyslogLogger "syslog" {
|
||||
severity = "information"
|
||||
}
|
||||
|
||||
For debugging purposes you can install a `FileLogger` object
|
||||
and forward the `debug` severity into an Icinga 2 debug file.
|
||||
|
||||
object FileLogger "debug-file" {
|
||||
severity = "debug",
|
||||
path = "/var/log/icinga2/debug.log"
|
||||
}
|
||||
Feature | Description
|
||||
---------|------------
|
||||
debuglog | Debug log (path: `/var/log/icinga2/debug.log`, severity: `debug` or higher)
|
||||
mainlog | Main log (path: `/var/log/icinga2/icinga2.log`, severity: `information` or higher)
|
||||
syslog | Syslog (severity: `warning` or higher)
|
||||
|
||||
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.
|
||||
|
@ -17,5 +17,3 @@ on-demand in your Icinga 2 objects configuration.
|
||||
spool_dir = "/data/check-results"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -21,22 +21,18 @@ binaries. The [Monitoring Plugins package](#setting-up-check-plugins) ships
|
||||
the `check_snmp` plugin binary, but there are plenty of [existing plugins](#integrate-additional-plugins)
|
||||
for specific use cases already around, for example monitoring Cisco routers.
|
||||
|
||||
The following example uses the [SNMP ITL](#itl-snmp) `CheckCommand` and only defines
|
||||
additional macros (note the `+=` operator) as command parameters for the `oid`
|
||||
(`community` is already set):
|
||||
The following example uses the [SNMP ITL](#itl-snmp) `CheckCommand` and just
|
||||
overrides the `oid` macro. A service is created for all hosts which
|
||||
have the `community` macro set.
|
||||
|
||||
object Host "remote-snmp-host" inherits "generic-host" {
|
||||
...
|
||||
services["uptime"] = {
|
||||
templates = [ "generic-service" ],
|
||||
check_command = "snmp",
|
||||
macros += {
|
||||
"oid" = "1.3.6.1.2.1.1.3.0"
|
||||
}
|
||||
},
|
||||
macros = {
|
||||
"address" = "192.168.1.101"
|
||||
}
|
||||
apply Service "uptime" {
|
||||
import "generic-service",
|
||||
|
||||
templates = [ "generic-service" ],
|
||||
check_command = "snmp",
|
||||
macros.oid = "1.3.6.1.2.1.1.3.0",
|
||||
|
||||
assign where host.macros.community
|
||||
}
|
||||
|
||||
#### SSH
|
||||
@ -44,7 +40,9 @@ additional macros (note the `+=` operator) as command parameters for the `oid`
|
||||
Calling a plugin using the SSH protocol to execute a plugin on the remote server fetching
|
||||
its return code and output. `check_by_ssh` is available in the [Monitoring Plugins package](#setting-up-check-plugins).
|
||||
|
||||
object CheckCommand "check_by_ssh_swap" inherits "plugin-check-command" {
|
||||
object CheckCommand "check_by_ssh_swap" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [ "$plugindir$/check_by_ssh",
|
||||
"-l", "remoteuser",
|
||||
"-H", "$address$",
|
||||
@ -52,22 +50,17 @@ its return code and output. `check_by_ssh` is available in the [Monitoring Plugi
|
||||
]
|
||||
}
|
||||
|
||||
object Host "remote-ssh-host" inherits "generic-host" {
|
||||
...
|
||||
services["swap"] = {
|
||||
templates = [ "generic-service" ],
|
||||
check_command = "check_by_ssh_swap",
|
||||
macros = {
|
||||
apply Service "swap" {
|
||||
import "generic-service",
|
||||
check_command = "check_by_ssh_swap",
|
||||
macros = {
|
||||
"warn" = "50%",
|
||||
"crit" = "75%"
|
||||
}
|
||||
},
|
||||
macros = {
|
||||
"address" = "192.168.1.102"
|
||||
}
|
||||
|
||||
assign where host.name == "remote-ssh-host"
|
||||
}
|
||||
|
||||
|
||||
#### NRPE
|
||||
|
||||
[NRPE](http://docs.icinga.org/latest/en/nrpe.html) runs as daemon on the remote client including
|
||||
@ -77,37 +70,33 @@ remote client.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> The NRPE daemon uses its own proprietary configuration format in nrpe.cfg while `check_nrpe`
|
||||
> The NRPE daemon uses its own configuration format in nrpe.cfg while `check_nrpe`
|
||||
> can be embedded into the Icinga 2 `CheckCommand` configuration syntax.
|
||||
|
||||
Example:
|
||||
|
||||
object CheckCommand "check_nrpe" inherits "plugin-check-command" {
|
||||
object CheckCommand "check_nrpe" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [ "$plugindir$/check_nrpe",
|
||||
"-H", "$address$",
|
||||
"-c", "$remote_nrpe_command$",
|
||||
],
|
||||
}
|
||||
|
||||
object Host "remote-nrpe-host" inherits "generic-host" {
|
||||
...
|
||||
services["users"] = {
|
||||
templates = [ "generic-service" ],
|
||||
check_command = "check_nrpe",
|
||||
macros = {
|
||||
"remote_nrpe_command" = "check_users"
|
||||
}
|
||||
},
|
||||
macros = {
|
||||
"address" = "192.168.1.103"
|
||||
}
|
||||
apply Service "users" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "check_nrpe",
|
||||
macros.remote_nrpe_command = "check_users",
|
||||
|
||||
assign where host.name == "remote-nrpe-host"
|
||||
}
|
||||
|
||||
nrpe.cfg:
|
||||
|
||||
command[check_users]=/usr/local/icinga/libexec/check_users -w 5 -c 10
|
||||
|
||||
|
||||
#### NSClient++
|
||||
|
||||
[NSClient++](http://nsclient.org) works on both Windows and Linux platforms and is well
|
||||
@ -122,7 +111,9 @@ the required output and performance counters.
|
||||
|
||||
Example:
|
||||
|
||||
object CheckCommand "check_nscp" inherits "plugin-check-command" {
|
||||
object CheckCommand "check_nscp" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [ "$plugindir$/check_nt",
|
||||
"-H", "$address$",
|
||||
"-p", "$port$",
|
||||
@ -138,21 +129,18 @@ Example:
|
||||
}
|
||||
}
|
||||
|
||||
object Host "remote-windows-host" inherits "generic-host" {
|
||||
...
|
||||
services["users"] = {
|
||||
templates = [ "generic-service" ],
|
||||
check_command = "check_nscp",
|
||||
macros += {
|
||||
"remote_nscp_command" = "USEDDISKSPACE",
|
||||
"partition" = "c",
|
||||
"warn" = "70",
|
||||
"crit" = "80"
|
||||
}
|
||||
},
|
||||
macros = {
|
||||
"address" = "192.168.1.104"
|
||||
apply Service "users" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "check_nscp",
|
||||
macros += {
|
||||
"remote_nscp_command" = "USEDDISKSPACE",
|
||||
"partition" = "c",
|
||||
"warn" = "70",
|
||||
"crit" = "80"
|
||||
}
|
||||
|
||||
assign where host.name == "remote-windows-host"
|
||||
}
|
||||
|
||||
For details on the `NSClient++` configuration please refer to the [official documentation](http://www.nsclient.org/nscp/wiki/doc/configuration/0.4.x).
|
||||
@ -166,13 +154,12 @@ For details on the `NSClient++` configuration please refer to the [official docu
|
||||
|
||||
A dedicated Icinga 2 agent supporting all platforms and using the native
|
||||
Icinga 2 communication protocol supported with SSL certificates, IPv4/IPv6
|
||||
support, etc is on the [development roadmap](https://dev.icinga.org/projects/i2?jump=issues).
|
||||
support, etc. is on the [development roadmap](https://dev.icinga.org/projects/i2?jump=issues).
|
||||
Meanwhile remote checkers in a [Cluster](#cluster) setup could act as
|
||||
immediate replacement, but without any local configuration - or pushing
|
||||
their standalone configuration back to the master node including their check
|
||||
result messages.
|
||||
|
||||
|
||||
### Passive Check Results and SNMP Traps
|
||||
|
||||
> **Note**
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
### <a id="object-definition"></a> Object Definition
|
||||
|
||||
Icinga 2 features an object-based configuration format. In order to
|
||||
define objects the `object` keyword is used:
|
||||
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",
|
||||
@ -66,15 +66,15 @@ Example:
|
||||
Certain characters need to be escaped. The following escape sequences
|
||||
are supported:
|
||||
|
||||
Character |Escape sequence
|
||||
------------------------------------|------------------------------------
|
||||
" |\\"
|
||||
\\ |\\\\
|
||||
\<TAB\> |\\t
|
||||
\<CARRIAGE-RETURN\> |\\r
|
||||
\<LINE-FEED\> |\\n
|
||||
\<BEL\> |\\b
|
||||
\<FORM-FEED\> |\\f
|
||||
Character | Escape sequence
|
||||
--------------------------|------------------------------------
|
||||
" | \\"
|
||||
\\ | \\\\
|
||||
<TAB> | \\t
|
||||
<CARRIAGE-RETURN> | \\r
|
||||
<LINE-FEED> | \\n
|
||||
<BEL> | \\b
|
||||
<FORM-FEED> | \\f
|
||||
|
||||
In addition to these pre-defined escape sequences you can specify
|
||||
arbitrary ASCII characters using the backslash character (\\) followed
|
||||
@ -154,7 +154,8 @@ The following operators are supported in expressions:
|
||||
|
||||
Operator | Examples (Result) | Description
|
||||
---------|-----------------------------------------------|--------------------------------
|
||||
!, ~ | ~true (false) | Bitwise negation of the operand
|
||||
! | !"Hello" (false), !false (true) | Logical negation of the operand
|
||||
~ | ~true (false) | Bitwise negation of the operand
|
||||
+ | 1 + 3 (4), "hello " + "world" ("hello world") | Adds two numbers; concatenates strings
|
||||
- | 3 - 1 (2) | Subtracts two numbers
|
||||
* | 5m * 10 (3000) | Multiplies two numbers
|
||||
@ -295,6 +296,12 @@ The indexer syntax provides a convenient way to set dictionary elements.
|
||||
|
||||
Example:
|
||||
|
||||
{
|
||||
hello.key = "world"
|
||||
}
|
||||
|
||||
Example (alternative syntax):
|
||||
|
||||
{
|
||||
hello["key"] = "world"
|
||||
}
|
||||
@ -307,60 +314,41 @@ This is equivalent to writing:
|
||||
}
|
||||
}
|
||||
|
||||
### <a id="object-inheritance"></a> Object Inheritance
|
||||
### <a id="template-imports"></a> Template Imports
|
||||
|
||||
Objects can inherit attributes from other objects.
|
||||
Objects can import attributes from other objects.
|
||||
|
||||
Example:
|
||||
|
||||
template Host "default-host" {
|
||||
macros["color"] = "red"
|
||||
macros.color = "red"
|
||||
}
|
||||
|
||||
template Host "test-host" inherits "default-host" {
|
||||
macros["color"] = "blue"
|
||||
template Host "test-host" {
|
||||
import "default-host",
|
||||
|
||||
macros.color = "blue"
|
||||
}
|
||||
|
||||
object Host "localhost" inherits "test-host" {
|
||||
macros["address"] = "127.0.0.1",
|
||||
macros["address6"] = "::1"
|
||||
object Host "localhost" {
|
||||
import "test-host",
|
||||
|
||||
macros.address = "127.0.0.1",
|
||||
macros.address6 = "::1"
|
||||
}
|
||||
|
||||
The `default-host` and `test-host` objects are marked as templates
|
||||
using the `template` keyword. Unlike ordinary objects templates are not
|
||||
instantiated at run-time. Parent objects do not necessarily have to be
|
||||
templates though in general they are.
|
||||
templates, however in general they are.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> The final macros dictionary contains all three macros and the macro
|
||||
> `color` has the value `"blue"`.
|
||||
> The macros dictionary for the `localhost` object contains all three
|
||||
> macros and the macro `color` has the value `"blue"`.
|
||||
|
||||
Parent objects are resolved in the order they're specified using the
|
||||
`inherits` keyword.
|
||||
|
||||
### <a id="disable-override-objects-attributes"></a> Disable/Override Objects and Attributes
|
||||
|
||||
Object attributes can be overridden by defining the additional changed attribute
|
||||
directly on the object. Use the `+=` operator for the inline services dictionary.
|
||||
|
||||
services["overridden-custom-attr"] += {
|
||||
custom = {
|
||||
notes = "disabled all custom attr"
|
||||
}
|
||||
}
|
||||
|
||||
If you don't require an attribute inherited from templates, you can simply
|
||||
override its value by setting it explicitely to `null`.
|
||||
|
||||
services["no-custom-attr"] += {
|
||||
custom = null
|
||||
}
|
||||
|
||||
The same method applies for disabling services defined in the inline `services`
|
||||
dictionary by explicitly overriding their value with `null`.
|
||||
|
||||
services["ping6"] = null
|
||||
`import` keyword.
|
||||
|
||||
### <a id="constants"></a> Constants
|
||||
|
||||
@ -368,34 +356,59 @@ Global constants can be set using the `const` keyword:
|
||||
|
||||
const VarName = "some value"
|
||||
|
||||
The value can be a string, number, array, or a dictionary.
|
||||
|
||||
Constants cannot be changed once they are set.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> The `set` and `var` keywords are an alias for `const` and are available
|
||||
> in order to provide compatibility with older versions. Their use is
|
||||
> deprecated.
|
||||
Once defined a constant can be access from any file. Constants cannot be changed
|
||||
once they are set.
|
||||
|
||||
### <a id="apply"></a> Apply
|
||||
|
||||
The `apply` keyword can be used to associate a template with another group of
|
||||
objects. The exact effect of this association depends on the two object types.
|
||||
The `apply` keyword can be used to create new objects which are associated with
|
||||
another group of objects.
|
||||
|
||||
template Service "ping-service" {
|
||||
short_name = "ping",
|
||||
check_command = "ping4"
|
||||
apply Service "ping" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "ping4",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply template Service "ping-service" to Host where host == "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"
|
||||
is created for each matching host.
|
||||
|
||||
In this example the `where` condition is a constant expression which is
|
||||
evaluated for all objects of type Host and a new service is created for each
|
||||
matching host.
|
||||
Depending on the object type used in the `apply` expression additional local
|
||||
variables may be available for use in the `where` condition:
|
||||
|
||||
Depending on the object types used in the `apply` expression additional local
|
||||
variables may be available for use in the `where` condition.
|
||||
Source Type | Target Type | Variables
|
||||
-----------------|-------------|--------------
|
||||
Service | Host | host
|
||||
Dependency | Service | host, service
|
||||
Notification | Service | host, service
|
||||
ScheduledDowntime| Service | host, service
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Any valid config attribute can be accessed using the `host` and `service`
|
||||
> variables. For example, `host.macros.address` would return the host's
|
||||
> "address" macro - or null if it doesn't have that macro.
|
||||
|
||||
### <a id="boolean-values"></a> Boolean Values
|
||||
|
||||
The `assign where` and `ignore where` statements, the unary `!`, `&&` and `||`
|
||||
operators as well as the `bool()` function convert their arguments to a
|
||||
boolean value based on the following rules:
|
||||
|
||||
Description | Example Value | Boolean Value
|
||||
---------------------|-------------------|--------------
|
||||
Empty value | null | false
|
||||
Zero | 0 | false
|
||||
Non-zero integer | -23945 | true
|
||||
Empty string | "" | false
|
||||
Non-empty string | "Hello" | true
|
||||
Empty array | [] | false
|
||||
Non-empty array | [ "Hello" ] | true
|
||||
Empty dictionary | {} | false
|
||||
Non-empty dictionary | { key = "value" } | true
|
||||
|
||||
### <a id="comments"></a> Comments
|
||||
|
||||
@ -433,7 +446,7 @@ C/C++ compiler:
|
||||
|
||||
Note the use of angle brackets instead of double quotes. This causes the
|
||||
config compiler to search the include search paths for the specified
|
||||
file. By default $PREFIX/icinga2 is included in the list of search
|
||||
file. By default $PREFIX/share/icinga2 is included in the list of search
|
||||
paths. Additional include search paths can be added using
|
||||
[command-line options](#cmdline).
|
||||
|
||||
@ -459,7 +472,7 @@ When no pattern is specified the default pattern "*.conf" is used.
|
||||
|
||||
The `library` directive can be used to manually load additional
|
||||
libraries. Libraries can be used to provide additional object types and
|
||||
methods.
|
||||
functions.
|
||||
|
||||
Example:
|
||||
|
||||
@ -467,8 +480,8 @@ Example:
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> The `icinga` library is automatically loaded at startup. You don't need
|
||||
> to load it manually.
|
||||
> The `icinga` and `methods` libraries is automatically loaded at startup.
|
||||
> You don't need to load them manually.
|
||||
|
||||
<!--
|
||||
|
||||
@ -480,18 +493,18 @@ you can specify which attributes are allowed in an object definition.
|
||||
|
||||
Example:
|
||||
|
||||
type Pizza {
|
||||
%type Pizza {
|
||||
%require "radius",
|
||||
%attribute number "radius",
|
||||
%attribute %number "radius",
|
||||
|
||||
%attribute dictionary "ingredients" {
|
||||
%attribute %dictionary "ingredients" {
|
||||
%validator "ValidateIngredients",
|
||||
|
||||
%attribute string "*",
|
||||
%attribute %string "*",
|
||||
|
||||
%attribute dictionary "*" {
|
||||
%attribute number "quantity",
|
||||
%attribute string "name"
|
||||
%attribute %dictionary "*" {
|
||||
%attribute %number "quantity",
|
||||
%attribute %string "name"
|
||||
}
|
||||
},
|
||||
|
||||
@ -512,7 +525,8 @@ The Pizza definition provides the following validation rules:
|
||||
- If they're a dictionary they may contain attributes `quantity` (of
|
||||
type number) and `name` (of type string).
|
||||
|
||||
- The script function `ValidateIngredients` is run to perform further
|
||||
- The s
|
||||
- cript function `ValidateIngredients` is run to perform further
|
||||
validation of the ingredients dictionary.
|
||||
|
||||
- Pizza objects may contain attribute matching the pattern
|
||||
@ -520,10 +534,11 @@ The Pizza definition provides the following validation rules:
|
||||
|
||||
Valid types for type rules include:
|
||||
|
||||
* any
|
||||
* number
|
||||
* string
|
||||
* scalar (an alias for string)
|
||||
* dictionary
|
||||
* %any
|
||||
* %number
|
||||
* %string
|
||||
* %scalar (an alias for string)
|
||||
* %dictionary
|
||||
* %array
|
||||
|
||||
-->
|
||||
|
@ -4,7 +4,7 @@ Icinga 2 provides a number of special global constants. Some of them can be over
|
||||
|
||||
Variable |Description
|
||||
--------------------------|-------------------
|
||||
IcingaPrefixDir |**Read-only.** Contains the installation prefix that was specified with cmake -DCMAKE_INSTALL_PREFIX. Defaults to /usr/local
|
||||
IcingaPrefixDir |**Read-only.** Contains the installation prefix that was specified with cmake -DCMAKE_INSTALL_PREFIX. Defaults to "/usr/local".
|
||||
IcingaSysconfDir |**Read-only.** Contains the path of the sysconf directory. Defaults to IcingaPrefixDir + "/etc".
|
||||
IcingaLocalStateDir |**Read-only.** Contains the path of the local state directory. Defaults to IcingaPrefixDir + "/var".
|
||||
IcingaPkgDataDir |**Read-only.** Contains the path of the package data directory. Defaults to IcingaPrefixDir + "/share/icinga2".
|
||||
|
@ -17,19 +17,6 @@ Example:
|
||||
|
||||
groups = [ "all-hosts" ],
|
||||
|
||||
services["ping"] = {
|
||||
templates = [ "ping" ]
|
||||
},
|
||||
|
||||
services["http"] = {
|
||||
templates = [ "my-http" ],
|
||||
|
||||
macros = {
|
||||
vhost = "test1.example.org",
|
||||
port = 81
|
||||
}
|
||||
},
|
||||
|
||||
check = "ping"
|
||||
}
|
||||
|
||||
@ -40,8 +27,6 @@ Attributes:
|
||||
display_name |**Optional.** A short description of the host.
|
||||
check |**Optional.** A service that is used to determine whether the host is up or down. This must be a service short name of a service that belongs to the host.
|
||||
groups |**Optional.** A list of host groups this host belongs to.
|
||||
services |**Optional.** Inline definition of services. Each dictionary item specifies a service.<br /><br />The `templates` attribute can be used to specify an array of templates that should be inherited by the service.<br /><br />The new service's name is "hostname!service" - where "service" is the dictionary key in the services dictionary.<br /><br />The dictionary key is used as the service's short name.
|
||||
dependencies |**Optional.** Inline definition of dependencies. Each dictionary item specifies a dependency.<br /><br />The `templates` attribute can be used to specify an array of templates that should be inherited by the dependency object.<br /><br />The new dependency object's name is "hostname:service:dependency" - where "dependency" is the dictionary key in the dependencies dictionary.
|
||||
macros |**Optional.** A dictionary containing macros that are specific to this host.
|
||||
|
||||
### <a id="objecttype-hostgroup"></a> HostGroup
|
||||
@ -68,8 +53,8 @@ by Icinga 2.
|
||||
> **Best Practice**
|
||||
>
|
||||
> Rather than creating a `Service` object for a specific host it is usually easier
|
||||
> to just create a `Service` template and use the `services` attribute in the `Host`
|
||||
> object to associate these templates with a host.
|
||||
> to just create a `Service` template and use the `apply` keyword to assign the
|
||||
> service to a number of hosts.
|
||||
|
||||
Example:
|
||||
|
||||
@ -115,8 +100,6 @@ Attributes:
|
||||
flapping\_threshold|**Optional.** The flapping threshold in percent when a service is considered to be flapping.
|
||||
volatile |**Optional.** The volatile setting enables always `HARD` state types if `NOT-OK` state changes occur.
|
||||
groups |**Optional.** The service groups this service belongs to.
|
||||
notifications |**Optional.** Inline definition of notifications. Each dictionary item specifies a notification.<br /><br />The `templates` attribute can be used to specify an array of templates that should be inherited by the notification object.<br /><br />The new notification object's name is "hostname:service:notification" - where "notification" is the dictionary key in the notifications dictionary.
|
||||
dependencies |**Optional.** Inline definition of dependencies. Each dictionary item specifies a dependency.<br /><br />The `templates` attribute can be used to specify an array of templates that should be inherited by the dependency object.<br /><br />The new dependency object's name is "hostname:service:dependency" - where "dependency" is the dictionary key in the dependencies dictionary.
|
||||
authorities |**Optional.** A list of Endpoints on which this service check will be executed in a cluster scenario.
|
||||
domains |**Optional.** A list of Domains for this service object in a cluster scenario.
|
||||
|
||||
@ -144,8 +127,8 @@ of service state changes and other events.
|
||||
> **Best Practice**
|
||||
>
|
||||
> Rather than creating a `Notification` object for a specific service it is usually easier
|
||||
> to just create a `Notification` template and use the `notifications` attribute in the `Service`
|
||||
> object to associate these templates with a service.
|
||||
> to just create a `Notification` template and use the `apply` keyword to assign the
|
||||
> notification to a number of services.
|
||||
|
||||
Example:
|
||||
|
||||
@ -202,8 +185,8 @@ Dependency objects are used to specify dependencies between hosts and services.
|
||||
> **Best Practice**
|
||||
>
|
||||
> Rather than creating a `Dependency` object for a specific service it is usually easier
|
||||
> to just create a `Dependency` template and using the `dependencies` attribute in the `Service`
|
||||
> object to associate these templates with a service.
|
||||
> to just create a `Dependency` template and use the `apply` keyword to assign the
|
||||
> dependency to a number of services.
|
||||
|
||||
Example:
|
||||
|
||||
@ -327,7 +310,9 @@ when notifications should be sent out.
|
||||
|
||||
Example:
|
||||
|
||||
object TimePeriod "24x7" inherits "legacy-timeperiod" {
|
||||
object TimePeriod "24x7" {
|
||||
import "legacy-timeperiod",
|
||||
|
||||
display_name = "Icinga 2 24x7 TimePeriod",
|
||||
ranges = {
|
||||
"monday" = "00:00-24:00",
|
||||
@ -345,7 +330,7 @@ Attributes:
|
||||
Name |Description
|
||||
----------------|----------------
|
||||
display_name |**Optional.** A short description of the time period.
|
||||
methods |**Required.** The "update" script method takes care of updating the internal representation of the time period. In virtually all cases you should just inherit from the "legacy-timeperiod" template to take care of this setting.
|
||||
methods |**Required.** The "update" script method takes care of updating the internal representation of the time period. In virtually all cases you should import the "legacy-timeperiod" template to take care of this setting.
|
||||
ranges |**Required.** A dictionary containing information which days and durations apply to this timeperiod.
|
||||
|
||||
The `/etc/icinga2/conf.d/timeperiods.conf` file is usually used to define
|
||||
@ -358,8 +343,8 @@ ScheduledDowntime objects can be used to set up recurring downtimes for services
|
||||
> **Best Practice**
|
||||
>
|
||||
> Rather than creating a `ScheduledDowntime` object for a specific service it is usually easier
|
||||
> to just create a `ScheduledDowntime` template and use the `scheduled_downtimes` attribute in the `Service`
|
||||
> object to associate these templates with a service.
|
||||
> to just create a `ScheduledDowntime` template and use the `apply` keyword to assign the
|
||||
> scheduled downtime to a number of services.
|
||||
|
||||
Example:
|
||||
|
||||
@ -431,7 +416,9 @@ defined here.
|
||||
|
||||
Example:
|
||||
|
||||
object CheckCommand "check_snmp" inherits "plugin-check-command" {
|
||||
object CheckCommand "check_snmp" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = "$plugindir$/check_snmp -H $address$ -C $community$ -o $oid$",
|
||||
|
||||
macros = {
|
||||
@ -444,7 +431,7 @@ Attributes:
|
||||
|
||||
Name |Description
|
||||
----------------|----------------
|
||||
methods |**Required.** The "execute" script method takes care of executing the check. In virtually all cases you should just inherit from the "plugin-check-command" template to take care of this setting.
|
||||
methods |**Required.** The "execute" script method takes care of executing the check. In virtually all cases you should import the "plugin-check-command" template to take care of this setting.
|
||||
command |**Required.** The command. This can either be an array of individual command arguments. Alternatively a string can be specified in which case the shell interpreter (usually /bin/sh) takes care of parsing the command.
|
||||
export_macros |**Optional.** A list of macros which should be exported as environment variables prior to executing the command.
|
||||
escape_macros |**Optional.** A list of macros which should be shell-escaped in the command.
|
||||
@ -457,7 +444,9 @@ A notification command definition.
|
||||
|
||||
Example:
|
||||
|
||||
object NotificationCommand "mail-service-notification" inherits "plugin-notification-command" {
|
||||
object NotificationCommand "mail-service-notification" {
|
||||
import "plugin-notification-command",
|
||||
|
||||
command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
|
||||
|
||||
export_macros = [
|
||||
@ -480,7 +469,7 @@ Attributes:
|
||||
|
||||
Name |Description
|
||||
----------------|----------------
|
||||
methods |**Required.** The "execute" script method takes care of executing the notification. In virtually all cases you should just inherit from the "plugin-notification-command" template to take care of this setting.
|
||||
methods |**Required.** The "execute" script method takes care of executing the notification. In virtually all cases you should import the "plugin-notification-command" template to take care of this setting.
|
||||
command |**Required.** The command. This can either be an array of individual command arguments. Alternatively a string can be specified in which case the shell interpreter (usually /bin/sh) takes care of parsing the command.
|
||||
export_macros |**Optional.** A list of macros which should be exported as environment variables prior to executing the command.
|
||||
escape_macros |**Optional.** A list of macros which should be shell-escaped in the command.
|
||||
@ -497,7 +486,9 @@ An event command definition.
|
||||
|
||||
Example:
|
||||
|
||||
object EventCommand "restart-httpd-event" inherits "plugin-event-command" {
|
||||
object EventCommand "restart-httpd-event" {
|
||||
import "plugin-event-command",
|
||||
|
||||
command = "/opt/bin/restart-httpd.sh",
|
||||
}
|
||||
|
||||
@ -506,7 +497,7 @@ Attributes:
|
||||
|
||||
Name |Description
|
||||
----------------|----------------
|
||||
methods |**Required.** The "execute" script method takes care of executing the event handler. In virtually all cases you should just inherit from the "plugin-event-command" template to take care of this setting.
|
||||
methods |**Required.** The "execute" script method takes care of executing the event handler. In virtually all cases you should import the "plugin-event-command" template to take care of this setting.
|
||||
command |**Required.** The command. This can either be an array of individual command arguments. Alternatively a string can be specified in which case the shell interpreter (usually /bin/sh) takes care of parsing the command.
|
||||
export_macros |**Optional.** A list of macros which should be exported as environment variables prior to executing the command.
|
||||
escape_macros |**Optional.** A list of macros which should be shell-escaped in the command.
|
||||
|
@ -3,9 +3,11 @@
|
||||
### <a id="best-practice-config-structure"></a> Configuration File and Directory Structure
|
||||
|
||||
Icinga 2 does not care how you name your files and/or directories as long as
|
||||
you'll include them accordingly in the [icinga2.conf](#icinga2-conf) file.
|
||||
you include them in the [icinga2.conf](#icinga2-conf) file.
|
||||
|
||||
By default, the `conf.d` directory is included recursively looking for files
|
||||
which match the pattern `*.conf`.
|
||||
|
||||
By default, `conf.d` is included recursively looking for `*.conf` file endings.
|
||||
If you're putting/generating your configuration structure in there, you do not
|
||||
need to touch the [icinga2.conf](#icinga2-conf) file. This becomes useful with
|
||||
external addons not having write permissions to this file such as LConf.
|
||||
@ -41,7 +43,6 @@ your configuration directory tree and files:
|
||||
vienna/
|
||||
hosts.conf
|
||||
|
||||
|
||||
If you're planning to create a [cluster](#cluster) setup with Icinga 2 and your
|
||||
configuration master should deploy specific configuration parts to slave nodes,
|
||||
it's reasonable not to confuse it with configuration below `conf.d`. Rather
|
||||
@ -54,8 +55,6 @@ create a dedicated directory and put all nodes into their own directories:
|
||||
node2/
|
||||
node99/
|
||||
|
||||
|
||||
|
||||
If you are preferring to control what several parties drop into the configuration
|
||||
pool (for example different departments with their own standalone configuration),
|
||||
you can still deactivate the `conf.d` inclusion and use your own strategy.
|
||||
@ -81,15 +80,16 @@ does not fit everyone, split it into two.
|
||||
Or rather inherit that template into a new template, and override/disable
|
||||
unwanted values.
|
||||
|
||||
template Service "generic-service-disable-notifications" inherits "generic-service" {
|
||||
template Service "generic-service-disable-notifications" {
|
||||
import "generic-service",
|
||||
|
||||
notifications["mail-icingaadmin"] = null
|
||||
}
|
||||
|
||||
### <a id="best-practice-inline-objects-using-templates"></a> Inline Objects using Templates
|
||||
|
||||
While it is reasonable to create single objects by your preferred configuration
|
||||
tool, using templates and inheriting their attributes in inline objects will
|
||||
save you a lot of typing extra work.
|
||||
tool, using templates and the `apply` keyword will save you a lot of typing extra work.
|
||||
|
||||
For instance, you can still create a host object, then a service object linking
|
||||
to it, after that a notification object referencing the service object, and last
|
||||
@ -145,20 +145,17 @@ By doing that everytime for such a series of linked objects, your configuration
|
||||
will get bloated and unreadable. You've already read that [using templates](#best-practice-use-templates)
|
||||
will help here.
|
||||
|
||||
The `Notification` and `ScheduledDowntime` templates will be referenced in the service template and
|
||||
inline definition (both locations are possible).
|
||||
The `Service` template is referenced within the inline service array for the `Host` template. In the end
|
||||
the `Host` object inherits from the `Host` template named `linux-server`.
|
||||
That way similar hosts may just inherit the host template and get all services, notifications, scheduled
|
||||
downtimes through the template automatism.
|
||||
Using the `apply` keyword you can create services, notifications, scheduled downtimes and dependencies
|
||||
for an arbitrary number of hosts and services respectively:
|
||||
|
||||
template Notification "mail-notification" {
|
||||
apply Notification "mail-notification" {
|
||||
notification_command = "mail-service-notification",
|
||||
|
||||
users = [ "user1", "user2" ]
|
||||
|
||||
assign where "generic-service" in service.templates
|
||||
}
|
||||
|
||||
template ScheduledDowntime "backup-downtime" {
|
||||
apply ScheduledDowntime "backup-downtime" {
|
||||
author = "icingaadmin",
|
||||
comment = "Some comment",
|
||||
|
||||
@ -168,6 +165,8 @@ downtimes through the template automatism.
|
||||
ranges = {
|
||||
"sunday" = "02:00-03:00"
|
||||
}
|
||||
|
||||
assign where "generic-service" in service.templates
|
||||
}
|
||||
|
||||
template Service "generic-service" {
|
||||
@ -175,35 +174,24 @@ downtimes through the template automatism.
|
||||
check_interval = 5m,
|
||||
retry_interval = 1m,
|
||||
enable_perfdata = true,
|
||||
}
|
||||
|
||||
notifications["mail"] = {
|
||||
templates = [ "mail-notification" ]
|
||||
}
|
||||
apply Service "ping4" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "ping4",
|
||||
|
||||
assign where "linux-server" in host.templates
|
||||
}
|
||||
|
||||
template Host "linux-server" {
|
||||
display_name = "The best host there is",
|
||||
|
||||
groups = [ "all-hosts" ],
|
||||
|
||||
host_dependencies = [ "router" ],
|
||||
|
||||
services["ping4"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "ping4",
|
||||
|
||||
scheduled_downtimes["backup"] = {
|
||||
templates = [ "backup-downtime" ]
|
||||
}
|
||||
},
|
||||
|
||||
check = "ping4"
|
||||
}
|
||||
|
||||
object Host "localhost" inherits "linux-server" {
|
||||
object Host "localhost" {
|
||||
import "linux-server",
|
||||
|
||||
display_name = "The best host there is",
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -73,7 +73,7 @@ recurring downtimes for services.
|
||||
|
||||
Example:
|
||||
|
||||
template ScheduledDowntime "backup-downtime" {
|
||||
apply ScheduledDowntime "backup-downtime" {
|
||||
author = "icingaadmin",
|
||||
comment = "Scheduled downtime for backup",
|
||||
|
||||
@ -86,17 +86,7 @@ Example:
|
||||
saturday = "02:00-03:00",
|
||||
sunday = "02:00-03:00"
|
||||
}
|
||||
|
||||
assign where "backup" in service.groups
|
||||
}
|
||||
|
||||
object Host "localhost" inherits "generic-host" {
|
||||
...
|
||||
services["load"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "load",
|
||||
|
||||
scheduled_downtimes["backup"] = {
|
||||
templates = [ "backup-downtime" ]
|
||||
}
|
||||
},
|
||||
}
|
@ -210,11 +210,12 @@ If you require specific services to be only executed by one or more checker node
|
||||
within the cluster, you must define `authorities` as additional service object
|
||||
attribute. Required Endpoints must be defined as array.
|
||||
|
||||
object Host "dmz-host1" inherits "generic-host" {
|
||||
services["dmz-oracledb"] = {
|
||||
templates = [ "generic-service" ],
|
||||
authorities = [ "icinga-node-1" ],
|
||||
}
|
||||
apply Service "dmz-oracledb" {
|
||||
import "generic-service",
|
||||
|
||||
authorities = [ "icinga-node-1" ],
|
||||
|
||||
assign where "oracle" in host.groups
|
||||
}
|
||||
|
||||
> **Tip**
|
||||
@ -232,13 +233,14 @@ one or more configured nodes are not connected.
|
||||
|
||||
Example:
|
||||
|
||||
object Host "icinga2a" inherits "generic-host" {
|
||||
services["cluster"] = {
|
||||
templates = [ "generic-service" ],
|
||||
apply Service "cluster" {
|
||||
import "generic-service",
|
||||
|
||||
check_interval = 1m,
|
||||
check_command = "cluster",
|
||||
authorities = [ "icinga2a" ]
|
||||
},
|
||||
authorities = [ "icinga2a" ],
|
||||
|
||||
assign where host.name = "icinga2a"
|
||||
}
|
||||
|
||||
> **Note**
|
||||
|
@ -15,7 +15,9 @@ by any cluster event message, and could be checked by the local authority too pr
|
||||
a different state history. `icinga-node-dmz-2` still receives all cluster message updates
|
||||
from the `icinga-node-dmz-1` endpoint.
|
||||
|
||||
object Host "dmz-host1" inherits "generic-host" {
|
||||
object Host "dmz-host1" {
|
||||
import "generic-host",
|
||||
|
||||
services["dmz-oracledb"] = {
|
||||
templates = [ "generic-service" ],
|
||||
domains = [ "dmz-db" ],
|
||||
@ -28,4 +30,4 @@ from the `icinga-node-dmz-1` endpoint.
|
||||
icinga-node-dmz-1 = DomainPrivReadOnly,
|
||||
icinga-node-dmz-2 = DomainPrivReadWrite
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,39 +15,30 @@ access by pinging the Google DNS server `google-dns` is a common method, but
|
||||
will fail in case the `dsl-router` host is down. Therefore the example below
|
||||
defines a host dependency which acts implicit as parent relation too.
|
||||
|
||||
Furthermore the host may be reachable but ping samples are dropped by the
|
||||
Furthermore the host may be reachable but ping probes are dropped by the
|
||||
router's firewall. In case the `dsl-router``ping4` service check fails, all
|
||||
further checks for the `google-dns` `ping4` service should be suppressed.
|
||||
This is achieved by setting the `disable_checks` attribute to `true`.
|
||||
further checks for the `ping4` service on host `google-dns` service should
|
||||
be suppressed. This is achieved by setting the `disable_checks` attribute to `true`.
|
||||
|
||||
object Host "dsl-router" {
|
||||
services["ping4"] = {
|
||||
templates = "generic-service",
|
||||
check_command = "ping4"
|
||||
}
|
||||
|
||||
macros = {
|
||||
address = "192.168.1.1",
|
||||
},
|
||||
macros.address = "192.168.1.1"
|
||||
}
|
||||
|
||||
object Host "google-dns" {
|
||||
services["ping4"] = {
|
||||
templates = "generic-service",
|
||||
check_command = "ping4",
|
||||
dependencies["dsl-router-ping4"] = {
|
||||
parent_host = "dsl-router",
|
||||
parent_service = "ping4",
|
||||
disable_checks = true
|
||||
}
|
||||
}
|
||||
macros.address = "8.8.8.8",
|
||||
}
|
||||
|
||||
macros = {
|
||||
address = "8.8.8.8",
|
||||
},
|
||||
apply Service "ping4" {
|
||||
import "generic-service",
|
||||
|
||||
dependencies["dsl-router"] = {
|
||||
parent_host = "dsl-router"
|
||||
},
|
||||
check_command = "ping4"
|
||||
|
||||
}
|
||||
assign where host.macros.address
|
||||
}
|
||||
|
||||
apply Dependency "internet" {
|
||||
parent_host = "dsl-router",
|
||||
disable_checks = true
|
||||
|
||||
assign where host.name != "dsl-router"
|
||||
}
|
||||
|
@ -123,15 +123,17 @@ uses the `template` identifier:
|
||||
template Service "ping4-template" { }
|
||||
|
||||
Icinga 1.x objects inherit from templates using the `use` attribute.
|
||||
Icinga 2 uses the keyword `inherits` after the object name and requires a
|
||||
comma-separated list with template names in double quotes.
|
||||
Icinga 2 uses the keyword `import` with template names in double quotes.
|
||||
|
||||
define service {
|
||||
service_description testservice
|
||||
use tmpl1,tmpl2,tmpl3
|
||||
}
|
||||
|
||||
object Service "testservice" inherits "tmpl1", "tmpl2", "tmpl3" {
|
||||
object Service "testservice" {
|
||||
import "tmpl1",
|
||||
import "tmpl2",
|
||||
import "tmpl3"
|
||||
}
|
||||
|
||||
## <a id="differences-1x-2-object-attributes"></a> Object attributes
|
||||
@ -216,12 +218,8 @@ In Icinga 1.x a service object is associated with a host by defining the
|
||||
to `hostgroup_name` or behavior changing regular expression. It's not possible
|
||||
to define a service definition within a host definition.
|
||||
|
||||
The preferred way of associating hosts with services in Icinga 2 are services
|
||||
defined inline to the host object (or template) definition. Icinga 2 will
|
||||
implicitely create a new service object on configuration activation. These
|
||||
inline service definitions can reference service templates.
|
||||
Linking a service to a host is still possible with the 'host' attribute in
|
||||
a service object in Icinga 2.
|
||||
The preferred way of associating hosts with services in Icinga 2 is by
|
||||
using the `apply` keyword.
|
||||
|
||||
## <a id="differences-1x-2-users"></a> Users
|
||||
|
||||
@ -369,17 +367,22 @@ The preferred way of assigning objects to groups is by using a template:
|
||||
|
||||
template Host "dev-host" {
|
||||
groups += [ "dev-hosts" ],
|
||||
|
||||
services["http"] = {
|
||||
check_command = [ "http-ip" ]
|
||||
}
|
||||
}
|
||||
|
||||
object Host "web-dev" inherits "dev-host" { }
|
||||
object Host "web-dev" {
|
||||
import "dev-host"
|
||||
}
|
||||
|
||||
Host groups in Icinga 2 cannot be used to associate services with all members
|
||||
of that group. The example above shows how to use templates to accomplish
|
||||
the same effect.
|
||||
In order to associate a service with all hosts in a host group the `apply`
|
||||
keyword can be used:
|
||||
|
||||
apply Service "ping" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "ping4",
|
||||
|
||||
assign where "group" in host.groups
|
||||
}
|
||||
|
||||
## <a id="differences-1x-2-notifications"></a> Notifications
|
||||
|
||||
|
@ -1,51 +1,44 @@
|
||||
/**
|
||||
* Provides default settings for hosts. By convention
|
||||
* all hosts should inherit from this template.
|
||||
* all hosts should import this template.
|
||||
*/
|
||||
template Host "generic-host" {
|
||||
|
||||
check = "ping4"
|
||||
}
|
||||
|
||||
template Host "linux-server" inherits "generic-host" {
|
||||
apply Service "ping4" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "ping4",
|
||||
|
||||
assign where "generic-host" in host.templates
|
||||
}
|
||||
|
||||
apply Service "ping6" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "ping6",
|
||||
|
||||
assign where "generic-host" in host.templates,
|
||||
ignore where !host.macros.address6
|
||||
}
|
||||
|
||||
template Host "linux-server" {
|
||||
import "generic-host",
|
||||
|
||||
groups += [ "linux-servers" ],
|
||||
|
||||
services["ping4"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "ping4"
|
||||
},
|
||||
|
||||
check = "ping4"
|
||||
}
|
||||
|
||||
template Host "windows-server" inherits "generic-host" {
|
||||
template Host "windows-server" {
|
||||
import "generic-host",
|
||||
|
||||
groups += [ "windows-servers" ],
|
||||
|
||||
services["ping4"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "ping4"
|
||||
},
|
||||
|
||||
check = "ping4"
|
||||
}
|
||||
|
||||
template Host "generic-printer" inherits "generic-host" {
|
||||
services["ping4"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "ping4"
|
||||
},
|
||||
|
||||
check = "ping4"
|
||||
template Host "generic-printer" {
|
||||
import "generic-host",
|
||||
}
|
||||
|
||||
template Host "generic-switch" inherits "generic-host" {
|
||||
services["ping4"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "ping4"
|
||||
},
|
||||
|
||||
check = "ping4"
|
||||
template Host "generic-switch" {
|
||||
import "generic-host",
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
/**
|
||||
* Provides default settings for services. By convention
|
||||
* all services should inherit from this template.
|
||||
* all services should import this template.
|
||||
*/
|
||||
template Service "generic-service" {
|
||||
max_check_attempts = 3,
|
||||
check_interval = 5m,
|
||||
retry_interval = 1m,
|
||||
enable_perfdata = true,
|
||||
|
||||
notifications["mail-icingaadmin"] = {
|
||||
templates = [ "mail-notification" ],
|
||||
user_groups = [ "icingaadmins" ]
|
||||
}
|
||||
enable_perfdata = true
|
||||
}
|
||||
|
||||
apply Notification "mail-icingaadmin" {
|
||||
import "mail-notification",
|
||||
|
||||
user_groups = [ "icingaadmins"],
|
||||
|
||||
assign where "generic-service" in service.templates
|
||||
}
|
||||
|
@ -4,19 +4,5 @@
|
||||
*/
|
||||
|
||||
template User "generic-user" {
|
||||
enable_notifications = true,
|
||||
notification_period = "24x7",
|
||||
|
||||
notification_state_filter = StateFilterWarning |
|
||||
StateFilterCritical |
|
||||
StateFilterUnknown,
|
||||
notification_type_filter = NotificationFilterProblem |
|
||||
NotificationFilterAcknowledgement |
|
||||
NotificationFilterRecovery |
|
||||
NotificationFilterCustom |
|
||||
NotificationFilterFlappingStart |
|
||||
NotificationFilterFlappingEnd |
|
||||
NotificationFilterDowntimeStart |
|
||||
NotificationFilterDowntimeEnd |
|
||||
NotificationFilterDowntimeRemoved
|
||||
}
|
||||
|
@ -3,71 +3,72 @@
|
||||
* in the conf.d directory (e.g. one per host). By default all *.conf
|
||||
* files in this directory are included.
|
||||
*/
|
||||
object Host "localhost" inherits "linux-server" {
|
||||
display_name = "localhost",
|
||||
object Host "localhost" {
|
||||
import "linux-server",
|
||||
|
||||
services["icinga"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "icinga"
|
||||
},
|
||||
|
||||
services["ping4"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "ping4"
|
||||
},
|
||||
|
||||
services["ping6"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "ping6"
|
||||
},
|
||||
|
||||
services["http"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "http_ip"
|
||||
},
|
||||
|
||||
services["ssh"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "ssh"
|
||||
},
|
||||
|
||||
services["load"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "load",
|
||||
|
||||
scheduled_downtimes["backup"] = {
|
||||
templates = [ "backup-downtime" ]
|
||||
}
|
||||
},
|
||||
|
||||
services["processes"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "processes"
|
||||
},
|
||||
|
||||
services["users"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "users"
|
||||
},
|
||||
|
||||
services["disk"] = {
|
||||
templates = [ "generic-service" ],
|
||||
|
||||
check_command = "disk"
|
||||
},
|
||||
|
||||
macros = {
|
||||
address = "127.0.0.1",
|
||||
address6 = "::1",
|
||||
},
|
||||
|
||||
check = "ping4",
|
||||
macros.address = "127.0.0.1",
|
||||
macros.address6 = "::1"
|
||||
}
|
||||
|
||||
apply Service "icinga" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "icinga",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply Service "http" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "http_ip",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply Service "ssh" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "ssh",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply Service "load" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "load",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply ScheduledDowntime "backup-downtime" {
|
||||
import "backup-downtime",
|
||||
|
||||
assign where service.host == "localhost" && service.short_name == "load"
|
||||
}
|
||||
|
||||
apply Service "processes" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "processes",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply Service "users" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "users",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
apply Service "disk" {
|
||||
import "generic-service",
|
||||
|
||||
check_command = "disk",
|
||||
|
||||
assign where host.name == "localhost"
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,9 @@ template Notification "mail-notification" {
|
||||
notification_period = "24x7"
|
||||
}
|
||||
|
||||
object NotificationCommand "mail-service-notification" inherits "plugin-notification-command" {
|
||||
object NotificationCommand "mail-service-notification" {
|
||||
import "plugin-notification-command",
|
||||
|
||||
command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
|
||||
|
||||
export_macros = [
|
||||
|
@ -3,7 +3,9 @@
|
||||
* 'legacy-timeperiod' template from the ITL.
|
||||
*/
|
||||
|
||||
object TimePeriod "24x7" inherits "legacy-timeperiod" {
|
||||
object TimePeriod "24x7" {
|
||||
import "legacy-timeperiod",
|
||||
|
||||
display_name = "Icinga 2 24x7 TimePeriod",
|
||||
ranges = {
|
||||
"monday" = "00:00-24:00",
|
||||
@ -16,7 +18,9 @@ object TimePeriod "24x7" inherits "legacy-timeperiod" {
|
||||
}
|
||||
}
|
||||
|
||||
object TimePeriod "9to5" inherits "legacy-timeperiod" {
|
||||
object TimePeriod "9to5" {
|
||||
import "legacy-timeperiod",
|
||||
|
||||
display_name = "Icinga 2 9to5 TimePeriod",
|
||||
ranges = {
|
||||
"monday" = "09:00-17:00",
|
||||
@ -27,7 +31,9 @@ object TimePeriod "9to5" inherits "legacy-timeperiod" {
|
||||
}
|
||||
}
|
||||
|
||||
object TimePeriod "never" inherits "legacy-timeperiod" {
|
||||
object TimePeriod "never" {
|
||||
import "legacy-timeperiod",
|
||||
|
||||
display_name = "Icinga 2 never TimePeriod",
|
||||
ranges = {
|
||||
}
|
||||
|
@ -3,7 +3,9 @@
|
||||
* group 'icingaadmins'.
|
||||
*/
|
||||
|
||||
object User "icingaadmin" inherits "generic-user" {
|
||||
object User "icingaadmin" {
|
||||
import "generic-user",
|
||||
|
||||
display_name = "Icinga 2 Admin",
|
||||
groups = [ "icingaadmins" ],
|
||||
|
||||
|
@ -89,7 +89,7 @@ static bool LoadConfigFiles(const String& appType, ValidationType validate)
|
||||
|
||||
BOOST_FOREACH(const ConfigCompilerMessage& message, ConfigCompilerContext::GetInstance()->GetMessages()) {
|
||||
std::ostringstream locbuf;
|
||||
ShowCodeFragment(locbuf, message.Location);
|
||||
ShowCodeFragment(locbuf, message.Location, true);
|
||||
String location = locbuf.str();
|
||||
|
||||
String logmsg;
|
||||
|
@ -17,7 +17,9 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
object CheckCommand "ping4" inherits "plugin-check-command" {
|
||||
object CheckCommand "ping4" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_ping",
|
||||
"-4",
|
||||
@ -40,7 +42,9 @@ object CheckCommand "ping4" inherits "plugin-check-command" {
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "ping6" inherits "plugin-check-command" {
|
||||
object CheckCommand "ping6" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_ping",
|
||||
"-6",
|
||||
@ -63,7 +67,9 @@ object CheckCommand "ping6" inherits "plugin-check-command" {
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "dummy" inherits "plugin-check-command" {
|
||||
object CheckCommand "dummy" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_dummy",
|
||||
"$state$",
|
||||
@ -76,14 +82,18 @@ object CheckCommand "dummy" inherits "plugin-check-command" {
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "passive" inherits "dummy" {
|
||||
object CheckCommand "passive" {
|
||||
import "dummy",
|
||||
|
||||
macros = {
|
||||
state = 3,
|
||||
text = "No Passive Check Result Received."
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "tcp" inherits "plugin-check-command" {
|
||||
object CheckCommand "tcp" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_tcp",
|
||||
"-H", "$address$",
|
||||
@ -91,7 +101,9 @@ object CheckCommand "tcp" inherits "plugin-check-command" {
|
||||
]
|
||||
}
|
||||
|
||||
object CheckCommand "udp" inherits "plugin-check-command" {
|
||||
object CheckCommand "udp" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_udp",
|
||||
"-H", "$address$",
|
||||
@ -99,42 +111,54 @@ object CheckCommand "udp" inherits "plugin-check-command" {
|
||||
]
|
||||
}
|
||||
|
||||
object CheckCommand "http_vhost" inherits "plugin-check-command" {
|
||||
object CheckCommand "http_vhost" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_http",
|
||||
"-H", "$vhost$"
|
||||
]
|
||||
}
|
||||
|
||||
object CheckCommand "http_ip" inherits "plugin-check-command" {
|
||||
object CheckCommand "http_ip" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_http",
|
||||
"-H", "$address$"
|
||||
]
|
||||
}
|
||||
|
||||
object CheckCommand "https_vhost" inherits "plugin-check-command" {
|
||||
object CheckCommand "https_vhost" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_http",
|
||||
"-H", "$vhost$", "-S"
|
||||
]
|
||||
}
|
||||
|
||||
object CheckCommand "https_ip" inherits "plugin-check-command" {
|
||||
object CheckCommand "https_ip" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_http",
|
||||
"-I", "$address$", "-S"
|
||||
]
|
||||
}
|
||||
|
||||
object CheckCommand "smtp" inherits "plugin-check-command" {
|
||||
object CheckCommand "smtp" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_smtp",
|
||||
"-H", "$address$"
|
||||
]
|
||||
}
|
||||
|
||||
object CheckCommand "ssmtp" inherits "plugin-check-command" {
|
||||
object CheckCommand "ssmtp" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_ssmtp",
|
||||
"-H", "$address$",
|
||||
@ -146,21 +170,27 @@ object CheckCommand "ssmtp" inherits "plugin-check-command" {
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "ntp_time" inherits "plugin-check-command" {
|
||||
object CheckCommand "ntp_time" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_ntp_time",
|
||||
"-H", "$address$"
|
||||
]
|
||||
}
|
||||
|
||||
object CheckCommand "ssh" inherits "plugin-check-command" {
|
||||
object CheckCommand "ssh" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_ssh",
|
||||
"$address$"
|
||||
]
|
||||
}
|
||||
|
||||
object CheckCommand "disk" inherits "plugin-check-command" {
|
||||
object CheckCommand "disk" {
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_disk",
|
||||
"-w", "$wfree$%",
|
||||
@ -173,7 +203,9 @@ object CheckCommand "disk" inherits "plugin-check-command" {
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "users" inherits "plugin-check-command" {
|
||||
object CheckCommand "users"{
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_users",
|
||||
"-w", "$wgreater$",
|
||||
@ -186,7 +218,9 @@ object CheckCommand "users" inherits "plugin-check-command" {
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "processes" inherits "plugin-check-command" {
|
||||
object CheckCommand "processes"{
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_procs",
|
||||
"-w", "$wgreater$",
|
||||
@ -199,7 +233,9 @@ object CheckCommand "processes" inherits "plugin-check-command" {
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "load" inherits "plugin-check-command" {
|
||||
object CheckCommand "load"{
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_load",
|
||||
"-w", "$wload1$,$wload5$,$wload15$",
|
||||
@ -217,7 +253,9 @@ object CheckCommand "load" inherits "plugin-check-command" {
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "snmp" inherits "plugin-check-command" {
|
||||
object CheckCommand "snmp"{
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
"$plugindir$/check_snmp",
|
||||
"-H", "$address$",
|
||||
@ -230,19 +268,27 @@ object CheckCommand "snmp" inherits "plugin-check-command" {
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "snmp-uptime" inherits "snmp" {
|
||||
object CheckCommand "snmp-uptime"{
|
||||
import "snmp",
|
||||
|
||||
macros += {
|
||||
oid = "1.3.6.1.2.1.1.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
object CheckCommand "icinga" inherits "icinga-check-command" {
|
||||
object CheckCommand "icinga"{
|
||||
import "icinga-check-command",
|
||||
|
||||
}
|
||||
|
||||
object CheckCommand "cluster" inherits "cluster-check-command" {
|
||||
object CheckCommand "cluster"{
|
||||
import "cluster-check-command",
|
||||
|
||||
}
|
||||
|
||||
object CheckCommand "snmp-extend" inherits "plugin-check-command" {
|
||||
object CheckCommand "snmp-extend"{
|
||||
import "plugin-check-command",
|
||||
|
||||
command = [
|
||||
IcingaSysconfDir + "/icinga2/scripts/snmp-extend.sh",
|
||||
"$HOSTADDRESS$",
|
||||
|
@ -3,8 +3,9 @@ namespace icinga
|
||||
|
||||
abstract class DynamicObject
|
||||
{
|
||||
[config] String __name (Name);
|
||||
[config, get_protected] String __type (TypeName);
|
||||
[config] String name (Name);
|
||||
[config, get_protected] String type (TypeName);
|
||||
[config, get_protected] Array::Ptr templates;
|
||||
[config] Dictionary::Ptr methods;
|
||||
[config] Dictionary::Ptr custom;
|
||||
[config] Array::Ptr domains;
|
||||
|
@ -61,19 +61,22 @@ String DiagnosticInformation(const T& ex, StackTrace *stack = NULL, ContextTrace
|
||||
if (boost::get_error_info<StackTraceErrorInfo>(ex) == NULL) {
|
||||
result << std::endl;
|
||||
|
||||
if (!stack)
|
||||
stack = GetLastExceptionStack();
|
||||
|
||||
if (stack)
|
||||
result << *stack;
|
||||
else
|
||||
result << *GetLastExceptionStack();
|
||||
|
||||
}
|
||||
|
||||
if (boost::get_error_info<ContextTraceErrorInfo>(ex) == NULL) {
|
||||
result << std::endl;
|
||||
|
||||
if (!context)
|
||||
context = GetLastExceptionContext();
|
||||
|
||||
if (context)
|
||||
result << *context;
|
||||
else
|
||||
result << *GetLastExceptionContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes)
|
||||
fields->Set(field.Name, Serialize(input->GetField(i), attributeTypes));
|
||||
}
|
||||
|
||||
fields->Set("__type", type->GetName());
|
||||
fields->Set("type", type->GetName());
|
||||
|
||||
return fields;
|
||||
}
|
||||
@ -151,7 +151,7 @@ static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary
|
||||
if (object)
|
||||
type = object->GetReflectionType();
|
||||
else
|
||||
type = Type::GetByName(input->Get("__type"));
|
||||
type = Type::GetByName(input->Get("type"));
|
||||
|
||||
if (!type)
|
||||
return object;
|
||||
@ -165,6 +165,7 @@ static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary
|
||||
instance = type->Instantiate();
|
||||
}
|
||||
|
||||
ObjectLock olock(input);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, input) {
|
||||
if (kv.first.IsEmpty())
|
||||
continue;
|
||||
@ -230,7 +231,7 @@ Value icinga::Deserialize(const Object::Ptr& object, const Value& value, bool sa
|
||||
|
||||
ASSERT(dict != NULL);
|
||||
|
||||
if (!dict->Contains("__type"))
|
||||
if (!dict->Contains("type"))
|
||||
return DeserializeDictionary(dict, safe_mode, attributeTypes);
|
||||
|
||||
return DeserializeObject(object, dict, safe_mode, attributeTypes);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "base/utility.h"
|
||||
#include "base/convert.h"
|
||||
#include "base/application.h"
|
||||
#include "base/initialize.h"
|
||||
|
||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||
# include <execinfo.h>
|
||||
@ -29,7 +30,7 @@
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
boost::once_flag StackTrace::m_OnceFlag = BOOST_ONCE_INIT;
|
||||
INITIALIZE_ONCE(&StackTrace::StaticInitialize);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma optimize("", off)
|
||||
@ -37,8 +38,6 @@ boost::once_flag StackTrace::m_OnceFlag = BOOST_ONCE_INIT;
|
||||
|
||||
StackTrace::StackTrace(void)
|
||||
{
|
||||
boost::call_once(m_OnceFlag, &StackTrace::Initialize);
|
||||
|
||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||
m_Count = backtrace(m_Frames, sizeof(m_Frames) / sizeof(m_Frames[0]));
|
||||
#else /* HAVE_BACKTRACE_SYMBOLS */
|
||||
@ -57,8 +56,6 @@ StackTrace::StackTrace(void)
|
||||
#ifdef _WIN32
|
||||
StackTrace::StackTrace(PEXCEPTION_POINTERS exi)
|
||||
{
|
||||
boost::call_once(m_OnceFlag, &StackTrace::Initialize);
|
||||
|
||||
STACKFRAME64 frame;
|
||||
int architecture;
|
||||
|
||||
@ -91,7 +88,7 @@ StackTrace::StackTrace(PEXCEPTION_POINTERS exi)
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
void StackTrace::Initialize(void)
|
||||
void StackTrace::StaticInitialize(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
(void) SymSetOptions(SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
|
||||
@ -153,33 +150,11 @@ void StackTrace::Print(std::ostream& fp, int ignoreFrames) const
|
||||
# endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||
#else /* _WIN32 */
|
||||
for (int i = ignoreFrames + 1; i < m_Count; i++) {
|
||||
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
DWORD64 dwAddress = (DWORD64)m_Frames[i];
|
||||
DWORD dwDisplacement;
|
||||
DWORD64 dwDisplacement64;
|
||||
|
||||
IMAGEHLP_LINE64 line;
|
||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
fp << "\t(" << i - ignoreFrames - 1 << ") ";
|
||||
|
||||
if (SymGetLineFromAddr64(GetCurrentProcess(), dwAddress, &dwDisplacement, &line))
|
||||
fp << line.FileName << ":" << line.LineNumber;
|
||||
else
|
||||
fp << "(unknown file/line)";
|
||||
|
||||
fp << ": ";
|
||||
|
||||
if (SymFromAddr(GetCurrentProcess(), dwAddress, &dwDisplacement64, pSymbol))
|
||||
fp << pSymbol->Name << "+" << dwDisplacement64;
|
||||
else
|
||||
fp << "(unknown function)";
|
||||
|
||||
fp << std::endl;
|
||||
fp << "\t(" << i - ignoreFrames - 1 << ") "
|
||||
<< Utility::GetSymbolSource(m_Frames[i])
|
||||
<< ": "
|
||||
<< Utility::GetSymbolName(m_Frames[i])
|
||||
<< std::endl;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
@ -43,13 +43,11 @@ public:
|
||||
|
||||
void Print(std::ostream& fp, int ignoreFrames = 0) const;
|
||||
|
||||
static void StaticInitialize(void);
|
||||
|
||||
private:
|
||||
void *m_Frames[64];
|
||||
int m_Count;
|
||||
|
||||
static boost::once_flag m_OnceFlag;
|
||||
|
||||
static void Initialize(void);
|
||||
};
|
||||
|
||||
I2_BASE_API std::ostream& operator<<(std::ostream& stream, const StackTrace& trace);
|
||||
|
@ -128,7 +128,28 @@ String Utility::GetSymbolName(const void *addr)
|
||||
return dli.dli_sname;
|
||||
#endif /* HAVE_DLADDR */
|
||||
|
||||
return "";
|
||||
#ifdef _WIN32
|
||||
char buffer[sizeof(SYMBOL_INFO)+MAX_SYM_NAME * sizeof(TCHAR)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
DWORD64 dwAddress = (DWORD64)addr;
|
||||
DWORD64 dwDisplacement;
|
||||
|
||||
IMAGEHLP_LINE64 line;
|
||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
if (SymFromAddr(GetCurrentProcess(), dwAddress, &dwDisplacement, pSymbol)) {
|
||||
char output[256];
|
||||
if (UnDecorateSymbolName(pSymbol->Name, output, sizeof(output), UNDNAME_COMPLETE))
|
||||
return String(output) + "+" + Convert::ToString(dwDisplacement);
|
||||
else
|
||||
return String(pSymbol->Name) + "+" + Convert::ToString(dwDisplacement);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
return "(unknown function)";
|
||||
}
|
||||
|
||||
String Utility::GetSymbolSource(const void *addr)
|
||||
@ -142,7 +163,23 @@ String Utility::GetSymbolSource(const void *addr)
|
||||
}
|
||||
#endif /* HAVE_DLADDR */
|
||||
|
||||
return "";
|
||||
#ifdef _WIN32
|
||||
char buffer[sizeof(SYMBOL_INFO)+MAX_SYM_NAME * sizeof(TCHAR)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
DWORD64 dwAddress = (DWORD64)addr;
|
||||
DWORD dwDisplacement;
|
||||
|
||||
IMAGEHLP_LINE64 line;
|
||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
if (SymGetLineFromAddr64(GetCurrentProcess(), dwAddress, &dwDisplacement, &line))
|
||||
return String(line.FileName) + ":" + Convert::ToString(line.LineNumber);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
return "(unknown file/line)";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "config/aexpression.h"
|
||||
#include "config/configerror.h"
|
||||
#include "config/configitem.h"
|
||||
#include "base/array.h"
|
||||
#include "base/serializer.h"
|
||||
#include "base/context.h"
|
||||
@ -26,6 +27,8 @@
|
||||
#include "base/scriptvariable.h"
|
||||
#include "base/utility.h"
|
||||
#include "base/objectlock.h"
|
||||
#include "base/object.h"
|
||||
#include "base/logger_fwd.h"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/exception_ptr.hpp>
|
||||
#include <boost/exception/errinfo_nested_exception.hpp>
|
||||
@ -43,6 +46,14 @@ AExpression::AExpression(OpCallback op, const Value& operand1, const Value& oper
|
||||
Value AExpression::Evaluate(const Dictionary::Ptr& locals) const
|
||||
{
|
||||
try {
|
||||
#ifdef _DEBUG
|
||||
if (m_Operator != &AExpression::OpLiteral) {
|
||||
std::ostringstream msgbuf;
|
||||
ShowCodeFragment(msgbuf, m_DebugInfo, false);
|
||||
Log(LogDebug, "config", "Executing:\n" + msgbuf.str());
|
||||
}
|
||||
#endif /* _DEBUG */
|
||||
|
||||
return m_Operator(this, locals);
|
||||
} catch (const std::exception& ex) {
|
||||
if (boost::get_error_info<boost::errinfo_nested_exception>(ex))
|
||||
@ -52,66 +63,6 @@ Value AExpression::Evaluate(const Dictionary::Ptr& locals) const
|
||||
}
|
||||
}
|
||||
|
||||
void AExpression::ExtractPath(const std::vector<String>& path, const Array::Ptr& result) const
|
||||
{
|
||||
ASSERT(!path.empty());
|
||||
|
||||
if (m_Operator == &AExpression::OpDict) {
|
||||
Array::Ptr exprl = m_Operand1;
|
||||
ObjectLock olock(exprl);
|
||||
BOOST_FOREACH(const AExpression::Ptr& expr, exprl) {
|
||||
expr->ExtractPath(path, result);
|
||||
}
|
||||
} else if ((m_Operator == &AExpression::OpSet || m_Operator == &AExpression::OpSetPlus ||
|
||||
m_Operator == &AExpression::OpSetMinus || m_Operator == &AExpression::OpSetMultiply ||
|
||||
m_Operator == &AExpression::OpSetDivide) && path[0] == m_Operand1) {
|
||||
AExpression::Ptr exprl = m_Operand2;
|
||||
|
||||
if (path.size() == 1) {
|
||||
if (m_Operator == &AExpression::OpSet)
|
||||
result->Clear();
|
||||
|
||||
if (exprl->m_Operator != &AExpression::OpDict)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("The '" + path[0] + "' attribute must be a dictionary.") << errinfo_debuginfo(m_DebugInfo));
|
||||
|
||||
Array::Ptr subexprl = exprl->m_Operand1;
|
||||
ObjectLock olock(subexprl);
|
||||
BOOST_FOREACH(const AExpression::Ptr& expr, subexprl) {
|
||||
result->Add(expr);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<String> sub_path(path.begin() + 1, path.end());
|
||||
exprl->ExtractPath(sub_path, result);
|
||||
}
|
||||
}
|
||||
|
||||
void AExpression::FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const
|
||||
{
|
||||
ASSERT(!path.empty());
|
||||
|
||||
if (m_Operator == &AExpression::OpDict) {
|
||||
Array::Ptr exprl = m_Operand1;
|
||||
ObjectLock olock(exprl);
|
||||
BOOST_FOREACH(const AExpression::Ptr& expr, exprl) {
|
||||
expr->FindDebugInfoPath(path, result);
|
||||
}
|
||||
} else if ((m_Operator == &AExpression::OpSet || m_Operator == &AExpression::OpSetPlus ||
|
||||
m_Operator == &AExpression::OpSetMinus || m_Operator == &AExpression::OpSetMultiply ||
|
||||
m_Operator == &AExpression::OpSetDivide) && path[0] == m_Operand1) {
|
||||
AExpression::Ptr exprl = m_Operand2;
|
||||
|
||||
if (path.size() == 1) {
|
||||
result = m_DebugInfo;
|
||||
} else {
|
||||
std::vector<String> sub_path(path.begin() + 1, path.end());
|
||||
exprl->FindDebugInfoPath(sub_path, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AExpression::MakeInline(void)
|
||||
{
|
||||
if (m_Operator == &AExpression::OpDict)
|
||||
@ -179,6 +130,11 @@ Value AExpression::OpNegate(const AExpression *expr, const Dictionary::Ptr& loca
|
||||
return ~(long)expr->EvaluateOperand1(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpLogicalNegate(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return !expr->EvaluateOperand1(locals).ToBool();
|
||||
}
|
||||
|
||||
Value AExpression::OpAdd(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) + expr->EvaluateOperand2(locals);
|
||||
@ -253,7 +209,9 @@ Value AExpression::OpIn(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value right = expr->EvaluateOperand2(locals);
|
||||
|
||||
if (!right.IsObjectType<Array>())
|
||||
if (right.IsEmpty())
|
||||
return false;
|
||||
else if (!right.IsObjectType<Array>())
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
|
||||
|
||||
Value left = expr->EvaluateOperand1(locals);
|
||||
@ -341,14 +299,16 @@ Value AExpression::OpDict(const AExpression *expr, const Dictionary::Ptr& locals
|
||||
|
||||
Value AExpression::OpSet(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value index = expr->EvaluateOperand1(locals);
|
||||
Value right = expr->EvaluateOperand2(locals);
|
||||
locals->Set(expr->m_Operand1, right);
|
||||
locals->Set(index, right);
|
||||
return right;
|
||||
}
|
||||
|
||||
Value AExpression::OpSetPlus(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value left = locals->Get(expr->m_Operand1);
|
||||
Value index = expr->EvaluateOperand1(locals);
|
||||
Value left = locals->Get(index);
|
||||
AExpression::Ptr exp_right = expr->m_Operand2;
|
||||
Dictionary::Ptr xlocals = locals;
|
||||
|
||||
@ -368,13 +328,14 @@ Value AExpression::OpSetPlus(const AExpression *expr, const Dictionary::Ptr& loc
|
||||
dict->Remove("__parent");
|
||||
}
|
||||
|
||||
locals->Set(expr->m_Operand1, result);
|
||||
locals->Set(index, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Value AExpression::OpSetMinus(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value left = locals->Get(expr->m_Operand1);
|
||||
Value index = expr->EvaluateOperand1(locals);
|
||||
Value left = locals->Get(index);
|
||||
AExpression::Ptr exp_right = expr->m_Operand2;
|
||||
Dictionary::Ptr xlocals = locals;
|
||||
|
||||
@ -394,13 +355,14 @@ Value AExpression::OpSetMinus(const AExpression *expr, const Dictionary::Ptr& lo
|
||||
dict->Remove("__parent");
|
||||
}
|
||||
|
||||
locals->Set(expr->m_Operand1, result);
|
||||
locals->Set(index, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Value AExpression::OpSetMultiply(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value left = locals->Get(expr->m_Operand1);
|
||||
Value index = expr->EvaluateOperand1(locals);
|
||||
Value left = locals->Get(index);
|
||||
AExpression::Ptr exp_right = expr->m_Operand2;
|
||||
Dictionary::Ptr xlocals = locals;
|
||||
|
||||
@ -420,13 +382,14 @@ Value AExpression::OpSetMultiply(const AExpression *expr, const Dictionary::Ptr&
|
||||
dict->Remove("__parent");
|
||||
}
|
||||
|
||||
locals->Set(expr->m_Operand1, result);
|
||||
locals->Set(index, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Value AExpression::OpSetDivide(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value left = locals->Get(expr->m_Operand1);
|
||||
Value index = expr->EvaluateOperand1(locals);
|
||||
Value left = locals->Get(index);
|
||||
AExpression::Ptr exp_right = expr->m_Operand2;
|
||||
Dictionary::Ptr xlocals = locals;
|
||||
|
||||
@ -446,16 +409,49 @@ Value AExpression::OpSetDivide(const AExpression *expr, const Dictionary::Ptr& l
|
||||
dict->Remove("__parent");
|
||||
}
|
||||
|
||||
locals->Set(expr->m_Operand1, result);
|
||||
locals->Set(index, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Value AExpression::OpIndexer(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Dictionary::Ptr dict = OpVariable(expr, locals);
|
||||
|
||||
if (!dict)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Script variable '" + expr->m_Operand1 + "' not set in this scope."));
|
||||
|
||||
return dict->Get(expr->m_Operand2);
|
||||
Value value = expr->EvaluateOperand1(locals);
|
||||
Value index = expr->EvaluateOperand2(locals);
|
||||
|
||||
if (value.IsObjectType<Dictionary>()) {
|
||||
Dictionary::Ptr dict = value;
|
||||
return dict->Get(index);
|
||||
} else if (value.IsObjectType<Object>()) {
|
||||
Object::Ptr object = value;
|
||||
const Type *type = object->GetReflectionType();
|
||||
|
||||
if (!type)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Dot operator applied to object which does not support reflection"));
|
||||
|
||||
int field = type->GetFieldId(index);
|
||||
|
||||
if (field == -1)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Tried to access invalid property '" + index + "'"));
|
||||
|
||||
return object->GetField(field);
|
||||
} else if (value.IsEmpty()) {
|
||||
return Empty;
|
||||
} else {
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Dot operator cannot be applied to type '" + value.GetTypeName() + "'"));
|
||||
}
|
||||
}
|
||||
|
||||
Value AExpression::OpImport(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value type = expr->EvaluateOperand1(locals);
|
||||
Value name = expr->EvaluateOperand2(locals);
|
||||
|
||||
ConfigItem::Ptr item = ConfigItem::GetObject(type, name);
|
||||
|
||||
if (!item)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Import references unknown template: '" + name + "'"));
|
||||
|
||||
item->GetExpressionList()->Evaluate(locals);
|
||||
|
||||
return Empty;
|
||||
}
|
||||
|
@ -42,8 +42,6 @@ public:
|
||||
AExpression(OpCallback op, const Value& operand1, const Value& operand2, const DebugInfo& di);
|
||||
|
||||
Value Evaluate(const Dictionary::Ptr& locals) const;
|
||||
void ExtractPath(const std::vector<String>& path, const Array::Ptr& result) const;
|
||||
void FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const;
|
||||
|
||||
void MakeInline(void);
|
||||
|
||||
@ -52,6 +50,7 @@ public:
|
||||
static Value OpLiteral(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpVariable(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpNegate(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpLogicalNegate(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpAdd(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpSubtract(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpMultiply(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
@ -79,6 +78,7 @@ public:
|
||||
static Value OpSetMultiply(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpSetDivide(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpIndexer(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpImport(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
|
||||
private:
|
||||
OpCallback m_Operator;
|
||||
|
@ -18,19 +18,21 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "config/applyrule.h"
|
||||
#include "base/logger_fwd.h"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
ApplyRule::RuleMap ApplyRule::m_Rules;
|
||||
ApplyRule::CallbackMap ApplyRule::m_Callbacks;
|
||||
|
||||
ApplyRule::ApplyRule(const String& tmpl, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope)
|
||||
: m_Template(tmpl), m_Expression(expression), m_DebugInfo(di), m_Scope(scope)
|
||||
ApplyRule::ApplyRule(const String& name, const AExpression::Ptr& expression,
|
||||
const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope)
|
||||
: m_Name(name), m_Expression(expression), m_Filter(filter), m_DebugInfo(di), m_Scope(scope)
|
||||
{ }
|
||||
|
||||
String ApplyRule::GetTemplate(void) const
|
||||
String ApplyRule::GetName(void) const
|
||||
{
|
||||
return m_Template;
|
||||
return m_Name;
|
||||
}
|
||||
|
||||
AExpression::Ptr ApplyRule::GetExpression(void) const
|
||||
@ -38,6 +40,11 @@ AExpression::Ptr ApplyRule::GetExpression(void) const
|
||||
return m_Expression;
|
||||
}
|
||||
|
||||
AExpression::Ptr ApplyRule::GetFilter(void) const
|
||||
{
|
||||
return m_Filter;
|
||||
}
|
||||
|
||||
DebugInfo ApplyRule::GetDebugInfo(void) const
|
||||
{
|
||||
return m_DebugInfo;
|
||||
@ -48,30 +55,56 @@ Dictionary::Ptr ApplyRule::GetScope(void) const
|
||||
return m_Scope;
|
||||
}
|
||||
|
||||
void ApplyRule::AddRule(const String& sourceType, const String& tmpl, const String& targetType, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope)
|
||||
void ApplyRule::AddRule(const String& sourceType, const String& name,
|
||||
const AExpression::Ptr& expression, const AExpression::Ptr& filter,
|
||||
const DebugInfo& di, const Dictionary::Ptr& scope)
|
||||
{
|
||||
m_Rules[std::make_pair(sourceType, targetType)].push_back(ApplyRule(tmpl, expression, di, scope));
|
||||
m_Rules[sourceType].push_back(ApplyRule(name, expression, filter, di, scope));
|
||||
}
|
||||
|
||||
bool ApplyRule::EvaluateFilter(const Dictionary::Ptr& scope) const
|
||||
{
|
||||
return m_Filter->Evaluate(scope);
|
||||
}
|
||||
|
||||
void ApplyRule::EvaluateRules(void)
|
||||
{
|
||||
std::pair<TypeCombination, Callback> kv;
|
||||
BOOST_FOREACH(kv, m_Callbacks) {
|
||||
RuleMap::const_iterator it = m_Rules.find(kv.first);
|
||||
std::set<String> completedTypes;
|
||||
|
||||
if (it == m_Rules.end())
|
||||
continue;
|
||||
while (completedTypes.size() < m_Callbacks.size()) {
|
||||
std::pair<String, std::pair<Callback, String> > kv;
|
||||
BOOST_FOREACH(kv, m_Callbacks) {
|
||||
const String& sourceType = kv.first;
|
||||
|
||||
kv.second(it->second);
|
||||
if (completedTypes.find(sourceType) != completedTypes.end())
|
||||
continue;
|
||||
|
||||
const Callback& callback = kv.second.first;
|
||||
const String& targetType = kv.second.second;
|
||||
|
||||
if (IsValidType(targetType) && completedTypes.find(targetType) == completedTypes.end())
|
||||
continue;
|
||||
|
||||
completedTypes.insert(sourceType);
|
||||
|
||||
RuleMap::const_iterator it = m_Rules.find(kv.first);
|
||||
|
||||
if (it == m_Rules.end())
|
||||
continue;
|
||||
|
||||
callback(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
m_Rules.clear();
|
||||
}
|
||||
|
||||
void ApplyRule::RegisterCombination(const String& sourceType, const String& targetType, const ApplyRule::Callback& callback)
|
||||
void ApplyRule::RegisterType(const String& sourceType, const String& targetType, const ApplyRule::Callback& callback)
|
||||
{
|
||||
m_Callbacks[std::make_pair(sourceType, targetType)] = callback;
|
||||
m_Callbacks[sourceType] = make_pair(callback, targetType);
|
||||
}
|
||||
|
||||
bool ApplyRule::IsValidCombination(const String& sourceType, const String& targetType)
|
||||
bool ApplyRule::IsValidType(const String& sourceType)
|
||||
{
|
||||
return m_Callbacks.find(std::make_pair(sourceType, targetType)) != m_Callbacks.end();
|
||||
return m_Callbacks.find(sourceType) != m_Callbacks.end();
|
||||
}
|
||||
|
@ -34,32 +34,37 @@ namespace icinga
|
||||
class I2_CONFIG_API ApplyRule
|
||||
{
|
||||
public:
|
||||
typedef std::pair<String, String> TypeCombination;
|
||||
typedef boost::function<void (const std::vector<ApplyRule>& rules)> Callback;
|
||||
typedef std::map<TypeCombination, Callback> CallbackMap;
|
||||
typedef std::map<TypeCombination, std::vector<ApplyRule> > RuleMap;
|
||||
typedef std::map<String, std::pair<Callback, String> > CallbackMap;
|
||||
typedef std::map<String, std::vector<ApplyRule> > RuleMap;
|
||||
|
||||
String GetTemplate(void) const;
|
||||
String GetName(void) const;
|
||||
AExpression::Ptr GetExpression(void) const;
|
||||
AExpression::Ptr GetFilter(void) const;
|
||||
DebugInfo GetDebugInfo(void) const;
|
||||
Dictionary::Ptr GetScope(void) const;
|
||||
|
||||
static void AddRule(const String& sourceType, const String& tmpl, const String& targetType, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope);
|
||||
bool EvaluateFilter(const Dictionary::Ptr& scope) const;
|
||||
|
||||
static void AddRule(const String& sourceType, const String& name, const AExpression::Ptr& expression,
|
||||
const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope);
|
||||
static void EvaluateRules(void);
|
||||
|
||||
static void RegisterCombination(const String& sourceType, const String& targetType, const ApplyRule::Callback& callback);
|
||||
static bool IsValidCombination(const String& sourceType, const String& targetType);
|
||||
static void RegisterType(const String& sourceType, const String& targetType, const ApplyRule::Callback& callback);
|
||||
static bool IsValidType(const String& sourceType);
|
||||
|
||||
private:
|
||||
String m_Template;
|
||||
String m_Name;
|
||||
AExpression::Ptr m_Expression;
|
||||
AExpression::Ptr m_Filter;
|
||||
DebugInfo m_DebugInfo;
|
||||
Dictionary::Ptr m_Scope;
|
||||
|
||||
static CallbackMap m_Callbacks;
|
||||
static RuleMap m_Rules;
|
||||
|
||||
ApplyRule(const String& tmpl, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope);
|
||||
ApplyRule(const String& tmpl, const AExpression::Ptr& expression,
|
||||
const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -17,40 +17,44 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type DynamicObject {
|
||||
%require "__name",
|
||||
%attribute string "__name",
|
||||
%type DynamicObject {
|
||||
%require "name",
|
||||
%attribute %string "name",
|
||||
|
||||
%require "__type",
|
||||
%attribute string "__type",
|
||||
%require "type",
|
||||
%attribute %string "type",
|
||||
|
||||
%attribute dictionary "methods",
|
||||
|
||||
%attribute dictionary "custom" {
|
||||
%attribute string "*"
|
||||
%attribute %array "templates" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
|
||||
%attribute array "domains" {
|
||||
%attribute string "*"
|
||||
%attribute %dictionary "methods",
|
||||
|
||||
%attribute %dictionary "custom" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
|
||||
%attribute %array "domains" {
|
||||
%attribute %string "*"
|
||||
}
|
||||
}
|
||||
|
||||
type Logger {
|
||||
%attribute string "severity"
|
||||
%type Logger {
|
||||
%attribute %string "severity"
|
||||
}
|
||||
|
||||
type FileLogger inherits Logger {
|
||||
%type FileLogger %inherits Logger {
|
||||
%require "path",
|
||||
%attribute string "path"
|
||||
%attribute %string "path"
|
||||
}
|
||||
|
||||
type SyslogLogger inherits Logger {
|
||||
%type SyslogLogger %inherits Logger {
|
||||
}
|
||||
|
||||
type Script {
|
||||
%type Script {
|
||||
%require "language",
|
||||
%attribute string "language",
|
||||
%attribute %string "language",
|
||||
|
||||
%require "code",
|
||||
%attribute string "code"
|
||||
%attribute %string "code"
|
||||
}
|
||||
|
@ -197,33 +197,33 @@ static char *lb_steal(lex_buf *lb)
|
||||
[ \t\r\n] /* ignore whitespace */
|
||||
|
||||
<INITIAL>{
|
||||
type return T_TYPE;
|
||||
dictionary { yylval->type = TypeDictionary; return T_TYPE_DICTIONARY; }
|
||||
array { yylval->type = TypeArray; return T_TYPE_ARRAY; }
|
||||
number { yylval->type = TypeNumber; return T_TYPE_NUMBER; }
|
||||
string { yylval->type = TypeString; return T_TYPE_STRING; }
|
||||
scalar { yylval->type = TypeScalar; return T_TYPE_SCALAR; }
|
||||
any { yylval->type = TypeAny; return T_TYPE_ANY; }
|
||||
name { yylval->type = TypeName; return T_TYPE_NAME; }
|
||||
%type return T_TYPE;
|
||||
%dictionary { yylval->type = TypeDictionary; return T_TYPE_DICTIONARY; }
|
||||
%array { yylval->type = TypeArray; return T_TYPE_ARRAY; }
|
||||
%number { yylval->type = TypeNumber; return T_TYPE_NUMBER; }
|
||||
%string { yylval->type = TypeString; return T_TYPE_STRING; }
|
||||
%scalar { yylval->type = TypeScalar; return T_TYPE_SCALAR; }
|
||||
%any { yylval->type = TypeAny; return T_TYPE_ANY; }
|
||||
%name { yylval->type = TypeName; return T_TYPE_NAME; }
|
||||
%validator { return T_VALIDATOR; }
|
||||
%require { return T_REQUIRE; }
|
||||
%attribute { return T_ATTRIBUTE; }
|
||||
%inherits return T_INHERITS;
|
||||
object return T_OBJECT;
|
||||
template return T_TEMPLATE;
|
||||
include return T_INCLUDE;
|
||||
include_recursive return T_INCLUDE_RECURSIVE;
|
||||
library return T_LIBRARY;
|
||||
inherits return T_INHERITS;
|
||||
null return T_NULL;
|
||||
partial return T_PARTIAL;
|
||||
true { yylval->num = 1; return T_NUMBER; }
|
||||
false { yylval->num = 0; return T_NUMBER; }
|
||||
set return T_VAR;
|
||||
var return T_VAR;
|
||||
const return T_CONST;
|
||||
apply return T_APPLY;
|
||||
to return T_TO;
|
||||
where return T_WHERE;
|
||||
import return T_IMPORT;
|
||||
assign return T_ASSIGN;
|
||||
ignore return T_IGNORE;
|
||||
\<\< { yylval->op = &AExpression::OpShiftLeft; return T_SHIFT_LEFT; }
|
||||
\>\> { yylval->op = &AExpression::OpShiftRight; return T_SHIFT_RIGHT; }
|
||||
\<= { yylval->op = &AExpression::OpLessThanOrEqual; return T_LESS_THAN_OR_EQUAL; }
|
||||
|
@ -69,6 +69,13 @@ do { \
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *left, Value *right, DebugInfo& diLeft, DebugInfo& diRight)
|
||||
{
|
||||
*result = new Value(make_shared<AExpression>(op, static_cast<AExpression::Ptr>(*left), static_cast<AExpression::Ptr>(*right), DebugInfoRange(diLeft, diRight)));
|
||||
delete left;
|
||||
delete right;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%pure-parser
|
||||
@ -121,7 +128,6 @@ using namespace icinga;
|
||||
%token <op> T_LESS_THAN "< (T_LESS_THAN)"
|
||||
%token <op> T_GREATER_THAN "> (T_GREATER_THAN)"
|
||||
|
||||
%token T_VAR "var (T_VAR)"
|
||||
%token T_CONST "const (T_CONST)"
|
||||
%token <type> T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)"
|
||||
%token <type> T_TYPE_ARRAY "array (T_TYPE_ARRAY)"
|
||||
@ -142,8 +148,11 @@ using namespace icinga;
|
||||
%token T_INHERITS "inherits (T_INHERITS)"
|
||||
%token T_PARTIAL "partial (T_PARTIAL)"
|
||||
%token T_APPLY "apply (T_APPLY)"
|
||||
%token T_TO "to (T_TO)"
|
||||
%token T_WHERE "where (T_WHERE)"
|
||||
%token T_IMPORT "import (T_IMPORT)"
|
||||
%token T_ASSIGN "assign (T_ASSIGN)"
|
||||
%token T_IGNORE "ignore (T_IGNORE)"
|
||||
|
||||
%type <text> identifier
|
||||
%type <array> rterm_items
|
||||
%type <array> rterm_items_inner
|
||||
@ -151,27 +160,25 @@ using namespace icinga;
|
||||
%type <array> lterm_items_inner
|
||||
%type <variant> typerulelist
|
||||
%type <op> lbinary_op
|
||||
%type <op> rbinary_op
|
||||
%type <type> type
|
||||
%type <num> partial_specifier
|
||||
%type <slist> object_inherits_list
|
||||
%type <slist> object_inherits_specifier
|
||||
%type <variant> rterm
|
||||
%type <variant> rterm_scope
|
||||
%type <variant> lterm
|
||||
%type <num> variable_decl
|
||||
|
||||
%left T_LOGICAL_OR
|
||||
%left T_LOGICAL_AND
|
||||
%left T_BINARY_OR
|
||||
%left T_BINARY_AND
|
||||
%left T_IN
|
||||
%left T_NOT_IN
|
||||
%nonassoc T_EQUAL
|
||||
%nonassoc T_NOT_EQUAL
|
||||
%left '+' '-'
|
||||
%left '*' '/'
|
||||
%left '&'
|
||||
%left '|'
|
||||
%right '~'
|
||||
%right '!'
|
||||
%left T_EQUAL T_NOT_EQUAL
|
||||
%left T_LESS_THAN T_LESS_THAN_OR_EQUAL T_GREATER_THAN T_GREATER_THAN_OR_EQUAL
|
||||
%left T_SHIFT_LEFT T_SHIFT_RIGHT
|
||||
%left T_PLUS T_MINUS
|
||||
%left T_MULTIPLY T_DIVIDE_OP
|
||||
%right '!' '~'
|
||||
%left '.' '(' '['
|
||||
%{
|
||||
|
||||
int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
|
||||
@ -192,6 +199,10 @@ static ConfigType::Ptr m_Type;
|
||||
|
||||
static Dictionary::Ptr m_ModuleScope;
|
||||
|
||||
static bool m_Apply;
|
||||
static AExpression::Ptr m_Assign;
|
||||
static AExpression::Ptr m_Ignore;
|
||||
|
||||
void ConfigCompiler::Compile(void)
|
||||
{
|
||||
m_ModuleScope = make_shared<Dictionary>();
|
||||
@ -215,7 +226,7 @@ statements: /* empty */
|
||||
| statements statement
|
||||
;
|
||||
|
||||
statement: object | type | include | include_recursive | library | variable | apply
|
||||
statement: object | type | include | include_recursive | library | constant | apply
|
||||
{ }
|
||||
| lterm
|
||||
{
|
||||
@ -265,7 +276,7 @@ library: T_LIBRARY T_STRING
|
||||
}
|
||||
;
|
||||
|
||||
variable: variable_decl identifier T_SET rterm
|
||||
constant: T_CONST identifier T_SET rterm
|
||||
{
|
||||
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$4);
|
||||
delete $4;
|
||||
@ -277,16 +288,6 @@ variable: variable_decl identifier T_SET rterm
|
||||
}
|
||||
;
|
||||
|
||||
variable_decl: T_VAR
|
||||
{
|
||||
$$ = true;
|
||||
}
|
||||
| T_CONST
|
||||
{
|
||||
$$ = false;
|
||||
}
|
||||
;
|
||||
|
||||
identifier: T_IDENTIFIER
|
||||
| T_STRING
|
||||
{
|
||||
@ -411,9 +412,9 @@ object:
|
||||
{
|
||||
m_Abstract = false;
|
||||
}
|
||||
object_declaration identifier rterm object_inherits_specifier rterm_scope
|
||||
object_declaration identifier rterm rterm_scope
|
||||
{
|
||||
DebugInfo di = DebugInfoRange(@2, @6);
|
||||
DebugInfo di = DebugInfoRange(@2, @5);
|
||||
ConfigItemBuilder::Ptr item = make_shared<ConfigItemBuilder>(di);
|
||||
|
||||
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$4);
|
||||
@ -444,16 +445,8 @@ object:
|
||||
|
||||
item->SetName(name);
|
||||
|
||||
if ($5) {
|
||||
BOOST_FOREACH(const String& parent, *$5) {
|
||||
item->AddParent(parent);
|
||||
}
|
||||
|
||||
delete $5;
|
||||
}
|
||||
|
||||
AExpression::Ptr exprl = static_cast<AExpression::Ptr>(*$6);
|
||||
delete $6;
|
||||
AExpression::Ptr exprl = static_cast<AExpression::Ptr>(*$5);
|
||||
delete $5;
|
||||
|
||||
exprl->MakeInline();
|
||||
item->AddExpression(exprl);
|
||||
@ -473,38 +466,6 @@ object_declaration: T_OBJECT
|
||||
m_Abstract = true;
|
||||
}
|
||||
|
||||
object_inherits_list:
|
||||
{
|
||||
$$ = NULL;
|
||||
}
|
||||
| T_STRING
|
||||
{
|
||||
$$ = new std::vector<String>();
|
||||
$$->push_back($1);
|
||||
free($1);
|
||||
}
|
||||
| object_inherits_list ',' T_STRING
|
||||
{
|
||||
if ($1)
|
||||
$$ = $1;
|
||||
else
|
||||
$$ = new std::vector<String>();
|
||||
|
||||
$$->push_back($3);
|
||||
free($3);
|
||||
}
|
||||
;
|
||||
|
||||
object_inherits_specifier:
|
||||
{
|
||||
$$ = NULL;
|
||||
}
|
||||
| T_INHERITS object_inherits_list
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
||||
lbinary_op: T_SET
|
||||
| T_SET_PLUS
|
||||
| T_SET_MINUS
|
||||
@ -551,52 +512,77 @@ lterm_items_inner: /* empty */
|
||||
|
||||
lterm: identifier lbinary_op rterm
|
||||
{
|
||||
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$3);
|
||||
$$ = new Value(make_shared<AExpression>($2, $1, aexpr, DebugInfoRange(@1, @3)));
|
||||
AExpression::Ptr aindex = make_shared<AExpression>(&AExpression::OpLiteral, $1, @1);
|
||||
free($1);
|
||||
|
||||
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$3);
|
||||
$$ = new Value(make_shared<AExpression>($2, aindex, aexpr, DebugInfoRange(@1, @3)));
|
||||
delete $3;
|
||||
}
|
||||
| identifier '[' T_STRING ']' lbinary_op rterm
|
||||
| identifier '[' rterm ']' lbinary_op rterm
|
||||
{
|
||||
AExpression::Ptr subexpr = make_shared<AExpression>($5, $3, static_cast<AExpression::Ptr>(*$6), DebugInfoRange(@1, @6));
|
||||
free($3);
|
||||
AExpression::Ptr subexpr = make_shared<AExpression>($5, static_cast<AExpression::Ptr>(*$3), static_cast<AExpression::Ptr>(*$6), DebugInfoRange(@1, @6));
|
||||
delete $3;
|
||||
delete $6;
|
||||
|
||||
Array::Ptr subexprl = make_shared<Array>();
|
||||
subexprl->Add(subexpr);
|
||||
|
||||
AExpression::Ptr expr = make_shared<AExpression>(&AExpression::OpDict, subexprl, DebugInfoRange(@1, @6));
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpSetPlus, $1, expr, DebugInfoRange(@1, @6)));
|
||||
AExpression::Ptr aindex = make_shared<AExpression>(&AExpression::OpLiteral, $1, @1);
|
||||
free($1);
|
||||
|
||||
AExpression::Ptr expr = make_shared<AExpression>(&AExpression::OpDict, subexprl, DebugInfoRange(@1, @6));
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpSetPlus, aindex, expr, DebugInfoRange(@1, @6)));
|
||||
}
|
||||
| identifier '.' T_IDENTIFIER lbinary_op rterm
|
||||
{
|
||||
AExpression::Ptr aindex = make_shared<AExpression>(&AExpression::OpLiteral, $1, @1);
|
||||
AExpression::Ptr subexpr = make_shared<AExpression>($4, aindex, static_cast<AExpression::Ptr>(*$5), DebugInfoRange(@1, @5));
|
||||
free($3);
|
||||
delete $5;
|
||||
|
||||
Array::Ptr subexprl = make_shared<Array>();
|
||||
subexprl->Add(subexpr);
|
||||
|
||||
AExpression::Ptr aindexl = make_shared<AExpression>(&AExpression::OpLiteral, $1, @1);
|
||||
free($1);
|
||||
|
||||
AExpression::Ptr expr = make_shared<AExpression>(&AExpression::OpDict, subexprl, DebugInfoRange(@1, @5));
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpSetPlus, aindexl, expr, DebugInfoRange(@1, @5)));
|
||||
}
|
||||
| T_IMPORT rterm
|
||||
{
|
||||
AExpression::Ptr avar = make_shared<AExpression>(&AExpression::OpVariable, "type", DebugInfoRange(@1, @2));
|
||||
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$2);
|
||||
delete $2;
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpImport, avar, aexpr, DebugInfoRange(@1, @2)));
|
||||
}
|
||||
| T_ASSIGN T_WHERE rterm
|
||||
{
|
||||
if (!m_Apply)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("'assign' keyword not valid in this context."));
|
||||
|
||||
m_Assign = make_shared<AExpression>(&AExpression::OpLogicalOr, m_Assign, static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3));
|
||||
delete $3;
|
||||
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpLiteral, Empty, DebugInfoRange(@1, @3)));
|
||||
}
|
||||
| T_IGNORE T_WHERE rterm
|
||||
{
|
||||
if (!m_Apply)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("'ignore' keyword not valid in this context."));
|
||||
|
||||
m_Ignore = make_shared<AExpression>(&AExpression::OpLogicalOr, m_Ignore, static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3));
|
||||
|
||||
delete $3;
|
||||
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpLiteral, Empty, DebugInfoRange(@1, @3)));
|
||||
}
|
||||
| rterm
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
rbinary_op: T_PLUS
|
||||
| T_MINUS
|
||||
| T_MULTIPLY
|
||||
| T_DIVIDE_OP
|
||||
| T_BINARY_AND
|
||||
| T_BINARY_OR
|
||||
| T_LESS_THAN
|
||||
| T_GREATER_THAN
|
||||
| T_LESS_THAN_OR_EQUAL
|
||||
| T_GREATER_THAN_OR_EQUAL
|
||||
| T_EQUAL
|
||||
| T_NOT_EQUAL
|
||||
| T_IN
|
||||
| T_NOT_IN
|
||||
| T_LOGICAL_AND
|
||||
| T_LOGICAL_OR
|
||||
| T_SHIFT_LEFT
|
||||
| T_SHIFT_RIGHT
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
rterm_items: rterm_items_inner
|
||||
{
|
||||
@ -630,12 +616,6 @@ rterm_items_inner: /* empty */
|
||||
}
|
||||
;
|
||||
|
||||
rbinary_op: '+'
|
||||
{
|
||||
$$ = &AExpression::OpAdd;
|
||||
}
|
||||
;
|
||||
|
||||
rterm_scope: '{' lterm_items '}'
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpDict, Array::Ptr($2), DebugInfoRange(@1, @3)));
|
||||
@ -655,6 +635,12 @@ rterm: T_STRING
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpLiteral, Empty, @1));
|
||||
}
|
||||
| rterm '.' T_IDENTIFIER
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpIndexer, static_cast<AExpression::Ptr>(*$1), make_shared<AExpression>(&AExpression::OpLiteral, $3, @3), DebugInfoRange(@1, @3)));
|
||||
delete $1;
|
||||
free($3);
|
||||
}
|
||||
| T_IDENTIFIER '(' rterm_items ')'
|
||||
{
|
||||
Array::Ptr arguments = Array::Ptr($3);
|
||||
@ -668,7 +654,7 @@ rterm: T_STRING
|
||||
}
|
||||
| '!' rterm
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpNegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpLogicalNegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
|
||||
delete $2;
|
||||
}
|
||||
| '~' rterm
|
||||
@ -676,10 +662,10 @@ rterm: T_STRING
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpNegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
|
||||
delete $2;
|
||||
}
|
||||
| identifier '[' T_STRING ']'
|
||||
| rterm '[' rterm ']'
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpIndexer, $1, $3, DebugInfoRange(@1, @4)));
|
||||
free($1);
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpIndexer, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @4)));
|
||||
delete $1;
|
||||
free($3);
|
||||
}
|
||||
| '[' rterm_items ']'
|
||||
@ -694,30 +680,56 @@ rterm: T_STRING
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| rterm rbinary_op rterm
|
||||
| rterm T_LOGICAL_OR rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_LOGICAL_AND rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_BINARY_OR rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_BINARY_AND rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_IN rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_NOT_IN rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_EQUAL rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_NOT_EQUAL rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_LESS_THAN rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_LESS_THAN_OR_EQUAL rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_GREATER_THAN rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_GREATER_THAN_OR_EQUAL rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_SHIFT_LEFT rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_SHIFT_RIGHT rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_PLUS rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_MINUS rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_MULTIPLY rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
| rterm T_DIVIDE_OP rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
|
||||
;
|
||||
|
||||
apply:
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>($2, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
|
||||
delete $1;
|
||||
delete $3;
|
||||
m_Apply = true;
|
||||
m_Assign = make_shared<AExpression>(&AExpression::OpLiteral, false, DebugInfo());
|
||||
m_Ignore = make_shared<AExpression>(&AExpression::OpLiteral, false, DebugInfo());
|
||||
}
|
||||
;
|
||||
|
||||
optional_template: /* empty */
|
||||
| T_TEMPLATE
|
||||
;
|
||||
|
||||
apply: T_APPLY optional_template identifier identifier T_TO identifier T_WHERE rterm
|
||||
T_APPLY identifier rterm rterm
|
||||
{
|
||||
if (!ApplyRule::IsValidCombination($3, $6)) {
|
||||
BOOST_THROW_EXCEPTION(ConfigError("'apply' cannot be used with types '" + String($3) + "' and '" + String($6) + "'.") << errinfo_debuginfo(@1));
|
||||
}
|
||||
m_Apply = false;
|
||||
|
||||
Array::Ptr arguments = make_shared<Array>();
|
||||
arguments->Add(*$8);
|
||||
delete $8;
|
||||
AExpression::Ptr aname = static_cast<AExpression::Ptr>(*$4);
|
||||
delete $4;
|
||||
String type = $3;
|
||||
free($3);
|
||||
String name = aname->Evaluate(m_ModuleScope);
|
||||
|
||||
AExpression::Ptr aexpr = make_shared<AExpression>(&AExpression::OpFunctionCall, "bool", make_shared<AExpression>(&AExpression::OpLiteral, arguments, @8), @8);
|
||||
if (!ApplyRule::IsValidType(type))
|
||||
BOOST_THROW_EXCEPTION(ConfigError("'apply' cannot be used with type '" + type + "'") << errinfo_debuginfo(DebugInfoRange(@2, @3)));
|
||||
|
||||
ApplyRule::AddRule($3, $4, $6, aexpr, DebugInfoRange(@1, @8), m_ModuleScope);
|
||||
AExpression::Ptr exprl = static_cast<AExpression::Ptr>(*$5);
|
||||
delete $5;
|
||||
|
||||
exprl->MakeInline();
|
||||
|
||||
// assign && !ignore
|
||||
AExpression::Ptr rex = make_shared<AExpression>(&AExpression::OpLogicalNegate, m_Ignore, DebugInfoRange(@2, @5));
|
||||
AExpression::Ptr filter = make_shared<AExpression>(&AExpression::OpLogicalAnd, m_Assign, rex, DebugInfoRange(@2, @5));
|
||||
ApplyRule::AddRule(type, name, exprl, filter, DebugInfoRange(@2, @5), m_ModuleScope);
|
||||
|
||||
m_Assign.reset();
|
||||
m_Ignore.reset();
|
||||
}
|
||||
%%
|
||||
|
@ -38,6 +38,6 @@ std::string icinga::to_string(const errinfo_debuginfo& e)
|
||||
{
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Config location: " << e.value() << "\n";
|
||||
ShowCodeFragment(msgbuf, e.value());
|
||||
ShowCodeFragment(msgbuf, e.value(), true);
|
||||
return msgbuf.str();
|
||||
}
|
||||
|
@ -44,15 +44,13 @@ ConfigItem::ItemMap ConfigItem::m_Items;
|
||||
* @param unit The unit of the item.
|
||||
* @param abstract Whether the item is a template.
|
||||
* @param exprl Expression list for the item.
|
||||
* @param parents Parent objects for the item.
|
||||
* @param debuginfo Debug information.
|
||||
*/
|
||||
ConfigItem::ConfigItem(const String& type, const String& name,
|
||||
bool abstract, const AExpression::Ptr& exprl,
|
||||
const std::vector<String>& parents, const DebugInfo& debuginfo,
|
||||
const Dictionary::Ptr& scope)
|
||||
const DebugInfo& debuginfo, const Dictionary::Ptr& scope)
|
||||
: m_Type(type), m_Name(name), m_Abstract(abstract), m_Validated(false),
|
||||
m_ExpressionList(exprl), m_ParentNames(parents), m_DebugInfo(debuginfo),
|
||||
m_ExpressionList(exprl), m_DebugInfo(debuginfo),
|
||||
m_Scope(scope)
|
||||
{
|
||||
}
|
||||
@ -112,53 +110,19 @@ AExpression::Ptr ConfigItem::GetExpressionList(void) const
|
||||
return m_ExpressionList;
|
||||
}
|
||||
|
||||
AExpression::Ptr ConfigItem::GetLinkedExpressionList(void)
|
||||
{
|
||||
ASSERT(OwnsLock());
|
||||
|
||||
if (m_LinkedExpressionList)
|
||||
return m_LinkedExpressionList;
|
||||
|
||||
Array::Ptr subexprs = make_shared<Array>();
|
||||
|
||||
BOOST_FOREACH(const String& name, m_ParentNames) {
|
||||
ConfigItem::Ptr parent = ConfigItem::GetObject(m_Type, name);
|
||||
|
||||
if (!parent) {
|
||||
std::ostringstream message;
|
||||
message << "Parent object '" << name << "' does not"
|
||||
" exist (" << m_DebugInfo << ")";
|
||||
ConfigCompilerContext::GetInstance()->AddMessage(true, message.str(), m_DebugInfo);
|
||||
} else {
|
||||
AExpression::Ptr pexprl;
|
||||
|
||||
{
|
||||
ObjectLock olock(parent);
|
||||
pexprl = parent->GetLinkedExpressionList();
|
||||
}
|
||||
|
||||
subexprs->Add(pexprl);
|
||||
}
|
||||
}
|
||||
|
||||
subexprs->Add(m_ExpressionList);
|
||||
|
||||
m_LinkedExpressionList = make_shared<AExpression>(&AExpression::OpDict, subexprs, true, m_DebugInfo);
|
||||
|
||||
return m_LinkedExpressionList;
|
||||
}
|
||||
|
||||
Dictionary::Ptr ConfigItem::GetProperties(void)
|
||||
{
|
||||
ASSERT(OwnsLock());
|
||||
|
||||
if (!m_Properties) {
|
||||
m_Properties = make_shared<Dictionary>();
|
||||
m_Properties->Set("type", m_Type);
|
||||
m_Properties->Set("name", m_Name);
|
||||
m_Properties->Set("__parent", m_Scope);
|
||||
GetLinkedExpressionList()->Evaluate(m_Properties);
|
||||
GetExpressionList()->Evaluate(m_Properties);
|
||||
m_Properties->Remove("__parent");
|
||||
|
||||
VERIFY(m_Properties->Get("__type") == GetType() && m_Properties->Get("__name") == GetName());
|
||||
VERIFY(m_Properties->Get("type") == GetType() && m_Properties->Get("name") == GetName());
|
||||
}
|
||||
|
||||
return m_Properties;
|
||||
|
@ -45,8 +45,8 @@ public:
|
||||
DECLARE_PTR_TYPEDEFS(ConfigItem);
|
||||
|
||||
ConfigItem(const String& type, const String& name, bool abstract,
|
||||
const AExpression::Ptr& exprl, const std::vector<String>& parents,
|
||||
const DebugInfo& debuginfo, const Dictionary::Ptr& scope);
|
||||
const AExpression::Ptr& exprl, const DebugInfo& debuginfo,
|
||||
const Dictionary::Ptr& scope);
|
||||
|
||||
String GetType(void) const;
|
||||
String GetName(void) const;
|
||||
@ -54,7 +54,7 @@ public:
|
||||
|
||||
std::vector<ConfigItem::Ptr> GetParents(void) const;
|
||||
|
||||
AExpression::Ptr GetLinkedExpressionList(void);
|
||||
AExpression::Ptr GetExpressionList(void) const;
|
||||
Dictionary::Ptr GetProperties(void);
|
||||
|
||||
DynamicObject::Ptr Commit(void);
|
||||
@ -74,8 +74,6 @@ public:
|
||||
static void DiscardItems(void);
|
||||
|
||||
private:
|
||||
AExpression::Ptr GetExpressionList(void) const;
|
||||
|
||||
String m_Type; /**< The object type. */
|
||||
String m_Name; /**< The name. */
|
||||
bool m_Abstract; /**< Whether this is a template. */
|
||||
@ -88,8 +86,6 @@ private:
|
||||
DebugInfo m_DebugInfo; /**< Debug information. */
|
||||
Dictionary::Ptr m_Scope; /**< variable scope. */
|
||||
|
||||
AExpression::Ptr m_LinkedExpressionList;
|
||||
|
||||
DynamicObject::Ptr m_Object;
|
||||
|
||||
static boost::mutex m_Mutex;
|
||||
|
@ -60,11 +60,6 @@ void ConfigItemBuilder::SetScope(const Dictionary::Ptr& scope)
|
||||
m_Scope = scope;
|
||||
}
|
||||
|
||||
void ConfigItemBuilder::AddParent(const String& parent)
|
||||
{
|
||||
m_Parents.push_back(parent);
|
||||
}
|
||||
|
||||
void ConfigItemBuilder::AddExpression(const AExpression::Ptr& expr)
|
||||
{
|
||||
m_Expressions->Add(expr);
|
||||
@ -90,18 +85,19 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument(msgbuf.str()));
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const String& parent, m_Parents) {
|
||||
if (parent == m_Name)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Configuration item '" + m_Name + "' of type '" + m_Type + "' must not inherit from itself."));
|
||||
}
|
||||
|
||||
Array::Ptr exprs = make_shared<Array>();
|
||||
exprs->Add(make_shared<AExpression>(&AExpression::OpSet, "__type", make_shared<AExpression>(&AExpression::OpLiteral, m_Type, m_DebugInfo), m_DebugInfo));
|
||||
exprs->Add(make_shared<AExpression>(&AExpression::OpSet, "__name", make_shared<AExpression>(&AExpression::OpLiteral, m_Name, m_DebugInfo), m_DebugInfo));
|
||||
Array::Ptr templateArray = make_shared<Array>();
|
||||
templateArray->Add(m_Name);
|
||||
|
||||
exprs->Add(make_shared<AExpression>(&AExpression::OpSetPlus,
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, "templates", m_DebugInfo),
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, templateArray, m_DebugInfo),
|
||||
m_DebugInfo));
|
||||
|
||||
exprs->Add(make_shared<AExpression>(&AExpression::OpDict, m_Expressions, true, m_DebugInfo));
|
||||
|
||||
AExpression::Ptr exprl = make_shared<AExpression>(&AExpression::OpDict, exprs, true, m_DebugInfo);
|
||||
|
||||
return make_shared<ConfigItem>(m_Type, m_Name, m_Abstract, exprl,
|
||||
m_Parents, m_DebugInfo, m_Scope);
|
||||
m_DebugInfo, m_Scope);
|
||||
}
|
||||
|
@ -47,8 +47,6 @@ public:
|
||||
void SetAbstract(bool abstract);
|
||||
void SetScope(const Dictionary::Ptr& scope);
|
||||
|
||||
void AddParent(const String& parent);
|
||||
|
||||
void AddExpression(const AExpression::Ptr& expr);
|
||||
|
||||
ConfigItem::Ptr Compile(void);
|
||||
@ -57,8 +55,6 @@ private:
|
||||
String m_Type; /**< The object type. */
|
||||
String m_Name; /**< The name. */
|
||||
bool m_Abstract; /**< Whether the item is abstract. */
|
||||
std::vector<String> m_Parents; /**< The names of parent configuration
|
||||
items. */
|
||||
Array::Ptr m_Expressions; /**< Expressions for this item. */
|
||||
DebugInfo m_DebugInfo; /**< Debug information. */
|
||||
Dictionary::Ptr m_Scope; /**< variable scope. */
|
||||
|
@ -180,7 +180,7 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,
|
||||
}
|
||||
|
||||
if (overallResult == ValidationUnknownField)
|
||||
ConfigCompilerContext::GetInstance()->AddMessage(false, "Unknown attribute: " + LocationToString(locations));
|
||||
ConfigCompilerContext::GetInstance()->AddMessage(true, "Unknown attribute: " + LocationToString(locations));
|
||||
else if (overallResult == ValidationInvalidType) {
|
||||
String message = "Invalid value for attribute: " + LocationToString(locations);
|
||||
|
||||
|
@ -53,7 +53,7 @@ DebugInfo icinga::DebugInfoRange(const DebugInfo& start, const DebugInfo& end)
|
||||
|
||||
#define EXTRA_LINES 2
|
||||
|
||||
void icinga::ShowCodeFragment(std::ostream& out, const DebugInfo& di)
|
||||
void icinga::ShowCodeFragment(std::ostream& out, const DebugInfo& di, bool verbose)
|
||||
{
|
||||
if (di.Path.IsEmpty())
|
||||
return;
|
||||
@ -61,41 +61,44 @@ void icinga::ShowCodeFragment(std::ostream& out, const DebugInfo& di)
|
||||
std::ifstream ifs;
|
||||
ifs.open(di.Path.CStr(), std::ifstream::in);
|
||||
|
||||
int lineno = 1;
|
||||
int lineno = 0;
|
||||
char line[1024];
|
||||
|
||||
while (ifs.good() && lineno <= di.LastLine + EXTRA_LINES) {
|
||||
lineno++;
|
||||
|
||||
ifs.getline(line, sizeof(line));
|
||||
|
||||
for (int i = 0; line[i]; i++)
|
||||
if (line[i] == '\t')
|
||||
line[i] = ' ';
|
||||
|
||||
if (lineno >= di.FirstLine - EXTRA_LINES && lineno <= di.LastLine + EXTRA_LINES) {
|
||||
String pathInfo = di.Path + "(" + Convert::ToString(lineno) + "): ";
|
||||
out << pathInfo;
|
||||
out << line << "\n";
|
||||
int extra_lines = verbose ? EXTRA_LINES : 0;
|
||||
|
||||
if (lineno >= di.FirstLine && lineno <= di.LastLine) {
|
||||
int start, end;
|
||||
if (lineno < di.FirstLine - extra_lines || lineno > di.LastLine + extra_lines)
|
||||
continue;
|
||||
|
||||
start = 0;
|
||||
end = strlen(line);
|
||||
String pathInfo = di.Path + "(" + Convert::ToString(lineno) + "): ";
|
||||
out << pathInfo;
|
||||
out << line << "\n";
|
||||
|
||||
if (lineno == di.FirstLine)
|
||||
start = di.FirstColumn - 1;
|
||||
if (lineno >= di.FirstLine && lineno <= di.LastLine) {
|
||||
int start, end;
|
||||
|
||||
if (lineno == di.LastLine)
|
||||
end = di.LastColumn;
|
||||
start = 0;
|
||||
end = strlen(line);
|
||||
|
||||
out << String(pathInfo.GetLength(), ' ');
|
||||
out << String(start, ' ');
|
||||
out << String(end - start, '^');
|
||||
if (lineno == di.FirstLine)
|
||||
start = di.FirstColumn - 1;
|
||||
|
||||
out << "\n";
|
||||
}
|
||||
if (lineno == di.LastLine)
|
||||
end = di.LastColumn;
|
||||
|
||||
out << String(pathInfo.GetLength(), ' ');
|
||||
out << String(start, ' ');
|
||||
out << String(end - start, '^');
|
||||
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
lineno++;
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ I2_CONFIG_API std::ostream& operator<<(std::ostream& out, const DebugInfo& val);
|
||||
|
||||
I2_CONFIG_API DebugInfo DebugInfoRange(const DebugInfo& start, const DebugInfo& end);
|
||||
|
||||
I2_CONFIG_API void ShowCodeFragment(std::ostream& out, const DebugInfo& di);
|
||||
I2_CONFIG_API void ShowCodeFragment(std::ostream& out, const DebugInfo& di, bool verbose);
|
||||
|
||||
}
|
||||
|
||||
|
@ -17,26 +17,26 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type DbConnection {
|
||||
%attribute string "table_prefix",
|
||||
%type DbConnection {
|
||||
%attribute %string "table_prefix",
|
||||
|
||||
%attribute dictionary "cleanup" {
|
||||
%attribute number "acknowledgements_age",
|
||||
%attribute number "commenthistory_age",
|
||||
%attribute number "contactnotifications_age",
|
||||
%attribute number "contactnotificationmethods_age",
|
||||
%attribute number "downtimehistory_age",
|
||||
%attribute number "eventhandlers_age",
|
||||
%attribute number "externalcommands_age",
|
||||
%attribute number "flappinghistory_age",
|
||||
%attribute number "hostchecks_age",
|
||||
%attribute number "logentries_age",
|
||||
%attribute number "notifications_age",
|
||||
%attribute number "processevents_age",
|
||||
%attribute number "statehistory_age",
|
||||
%attribute number "servicechecks_age",
|
||||
%attribute number "systemcommands_age",
|
||||
%attribute %dictionary "cleanup" {
|
||||
%attribute %number "acknowledgements_age",
|
||||
%attribute %number "commenthistory_age",
|
||||
%attribute %number "contactnotifications_age",
|
||||
%attribute %number "contactnotificationmethods_age",
|
||||
%attribute %number "downtimehistory_age",
|
||||
%attribute %number "eventhandlers_age",
|
||||
%attribute %number "externalcommands_age",
|
||||
%attribute %number "flappinghistory_age",
|
||||
%attribute %number "hostchecks_age",
|
||||
%attribute %number "logentries_age",
|
||||
%attribute %number "notifications_age",
|
||||
%attribute %number "processevents_age",
|
||||
%attribute %number "statehistory_age",
|
||||
%attribute %number "servicechecks_age",
|
||||
%attribute %number "systemcommands_age",
|
||||
},
|
||||
|
||||
%attribute number "categories"
|
||||
%attribute %number "categories"
|
||||
}
|
||||
|
@ -17,5 +17,5 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type Hello {
|
||||
%type Hello {
|
||||
}
|
||||
|
@ -42,15 +42,15 @@ mkembedconfig_target(icinga-type.conf icinga-type.cpp)
|
||||
add_library(icinga SHARED
|
||||
api.cpp api.h checkcommand.cpp checkcommand.th checkresult.cpp checkresult.th
|
||||
cib.cpp command.cpp command.th comment.cpp comment.th compatutility.cpp dependency.cpp dependency.th
|
||||
domain.cpp domain.th downtime.cpp downtime.th eventcommand.cpp eventcommand.th
|
||||
externalcommandprocessor.cpp host.cpp host.th host-apply.cpp hostgroup.cpp hostgroup.th
|
||||
dependency-apply.cpp domain.cpp domain.th downtime.cpp downtime.th eventcommand.cpp eventcommand.th
|
||||
externalcommandprocessor.cpp host.cpp host.th hostgroup.cpp hostgroup.th
|
||||
icingaapplication.cpp icingaapplication.th icingastatuswriter.cpp
|
||||
icingastatuswriter.th legacytimeperiod.cpp
|
||||
macroprocessor.cpp macroresolver.cpp notificationcommand.cpp notificationcommand.th
|
||||
notification.cpp notification.th perfdatavalue.cpp perfdatavalue.th
|
||||
pluginutility.cpp scheduleddowntime.cpp scheduleddowntime.th service-check.cpp
|
||||
service-comment.cpp service.cpp service-dependency.cpp service-downtime.cpp service-event.cpp
|
||||
service-flapping.cpp service.th servicegroup.cpp servicegroup.th
|
||||
notification.cpp notification.th notification-apply.cpp perfdatavalue.cpp perfdatavalue.th
|
||||
pluginutility.cpp scheduleddowntime.cpp scheduleddowntime.th scheduleddowntime-apply.cpp
|
||||
service-apply.cpp service-check.cpp service-comment.cpp service.cpp service-dependency.cpp
|
||||
service-downtime.cpp service-event.cpp service-flapping.cpp service.th servicegroup.cpp servicegroup.th
|
||||
service-notification.cpp timeperiod.cpp timeperiod.th user.cpp user.th
|
||||
usergroup.cpp usergroup.th icinga-type.cpp
|
||||
)
|
||||
|
87
lib/icinga/dependency-apply.cpp
Normal file
87
lib/icinga/dependency-apply.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-present Icinga Development Team (http://www.icinga.org) *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software Foundation *
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#include "icinga/dependency.h"
|
||||
#include "config/configitembuilder.h"
|
||||
#include "base/initialize.h"
|
||||
#include "base/dynamictype.h"
|
||||
#include "base/convert.h"
|
||||
#include "base/logger_fwd.h"
|
||||
#include "base/context.h"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
INITIALIZE_ONCE(&Dependency::RegisterApplyRuleHandler);
|
||||
|
||||
void Dependency::RegisterApplyRuleHandler(void)
|
||||
{
|
||||
ApplyRule::RegisterType("Dependency", "Service", &Dependency::EvaluateApplyRules);
|
||||
}
|
||||
|
||||
void Dependency::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
|
||||
{
|
||||
BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects<Service>()) {
|
||||
CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'");
|
||||
|
||||
Dictionary::Ptr locals = make_shared<Dictionary>();
|
||||
locals->Set("host", service->GetHost());
|
||||
locals->Set("service", service);
|
||||
|
||||
BOOST_FOREACH(const ApplyRule& rule, rules) {
|
||||
DebugInfo di = rule.GetDebugInfo();
|
||||
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Evaluating 'apply' rule (" << di << ")";
|
||||
CONTEXT(msgbuf.str());
|
||||
|
||||
if (!rule.EvaluateFilter(locals))
|
||||
continue;
|
||||
|
||||
std::ostringstream msgbuf2;
|
||||
msgbuf2 << "Applying dependency '" << rule.GetName() << "' to service '" << service->GetName() << "' for rule " << di;
|
||||
Log(LogDebug, "icinga", msgbuf2.str());
|
||||
|
||||
std::ostringstream namebuf;
|
||||
namebuf << service->GetName() << "!" << rule.GetName();
|
||||
String name = namebuf.str();
|
||||
|
||||
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
|
||||
builder->SetType("Dependency");
|
||||
builder->SetName(name);
|
||||
builder->SetScope(rule.GetScope());
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, "child_host", di),
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, service->GetHost()->GetName(),
|
||||
di), di));
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, "child_service", di),
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, service->GetShortName(), di), di));
|
||||
|
||||
builder->AddExpression(rule.GetExpression());
|
||||
|
||||
ConfigItem::Ptr serviceItem = builder->Compile();
|
||||
serviceItem->Register();
|
||||
DynamicObject::Ptr dobj = serviceItem->Commit();
|
||||
dobj->OnConfigLoaded();
|
||||
}
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@
|
||||
#include "icinga/i2-icinga.h"
|
||||
#include "icinga/dependency.th"
|
||||
#include "icinga/service.h"
|
||||
#include "config/applyrule.h"
|
||||
#include "base/array.h"
|
||||
#include "base/dictionary.h"
|
||||
|
||||
@ -47,6 +48,9 @@ public:
|
||||
|
||||
bool IsAvailable(DependencyType dt) const;
|
||||
|
||||
static void RegisterApplyRuleHandler(void);
|
||||
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
|
||||
|
||||
protected:
|
||||
virtual void OnStateLoaded(void);
|
||||
virtual void Stop(void);
|
||||
|
@ -57,8 +57,6 @@ void Host::OnConfigLoaded(void)
|
||||
hg->AddMember(GetSelf());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSlaveServices();
|
||||
}
|
||||
|
||||
void Host::Stop(void)
|
||||
@ -92,78 +90,6 @@ bool Host::IsReachable(DependencyType dt, shared_ptr<Dependency> *failedDependen
|
||||
return hc->IsReachable(dt, failedDependency);
|
||||
}
|
||||
|
||||
void Host::UpdateSlaveServices(void)
|
||||
{
|
||||
ASSERT(!OwnsLock());
|
||||
|
||||
Dictionary::Ptr service_descriptions = GetServiceDescriptions();
|
||||
|
||||
if (!service_descriptions ||service_descriptions->GetLength() == 0)
|
||||
return;
|
||||
|
||||
ConfigItem::Ptr item = ConfigItem::GetObject("Host", GetName());
|
||||
|
||||
ObjectLock olock(service_descriptions);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, service_descriptions) {
|
||||
std::ostringstream namebuf;
|
||||
namebuf << GetName() << "!" << kv.first;
|
||||
String name = namebuf.str();
|
||||
|
||||
std::vector<String> path;
|
||||
path.push_back("services");
|
||||
path.push_back(kv.first);
|
||||
|
||||
AExpression::Ptr exprl;
|
||||
|
||||
{
|
||||
ObjectLock ilock(item);
|
||||
|
||||
exprl = item->GetLinkedExpressionList();
|
||||
}
|
||||
|
||||
DebugInfo di;
|
||||
exprl->FindDebugInfoPath(path, di);
|
||||
|
||||
if (di.Path.IsEmpty())
|
||||
di = item->GetDebugInfo();
|
||||
|
||||
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
|
||||
builder->SetType("Service");
|
||||
builder->SetName(name);
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "host", make_shared<AExpression>(&AExpression::OpLiteral, GetName(), di), di));
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "display_name", make_shared<AExpression>(&AExpression::OpLiteral, kv.first, di), di));
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "short_name", make_shared<AExpression>(&AExpression::OpLiteral, kv.first, di), di));
|
||||
|
||||
if (!kv.second.IsObjectType<Dictionary>())
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Service description must be either a string or a dictionary."));
|
||||
|
||||
Dictionary::Ptr service = kv.second;
|
||||
|
||||
Array::Ptr templates = service->Get("templates");
|
||||
|
||||
if (templates) {
|
||||
ObjectLock olock(templates);
|
||||
|
||||
BOOST_FOREACH(const Value& tmpl, templates) {
|
||||
builder->AddParent(tmpl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clone attributes from the service expression list. */
|
||||
Array::Ptr svc_exprl = make_shared<Array>();
|
||||
exprl->ExtractPath(path, svc_exprl);
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpDict, svc_exprl, true, di));
|
||||
|
||||
builder->SetScope(item->GetScope());
|
||||
|
||||
ConfigItem::Ptr serviceItem = builder->Compile();
|
||||
serviceItem->Register();
|
||||
DynamicObject::Ptr dobj = serviceItem->Commit();
|
||||
dobj->OnConfigLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Service::Ptr> Host::GetServices(void) const
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_ServicesMutex);
|
||||
|
@ -102,9 +102,6 @@ public:
|
||||
|
||||
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const;
|
||||
|
||||
static void RegisterApplyRuleHandler(void);
|
||||
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
|
||||
|
||||
protected:
|
||||
virtual void Stop(void);
|
||||
|
||||
@ -114,8 +111,6 @@ private:
|
||||
mutable boost::mutex m_ServicesMutex;
|
||||
std::map<String, shared_ptr<Service> > m_Services;
|
||||
|
||||
void UpdateSlaveServices(void);
|
||||
|
||||
static void RefreshServicesCache(void);
|
||||
};
|
||||
|
||||
|
@ -17,283 +17,228 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type Host {
|
||||
%attribute string "display_name",
|
||||
%attribute string "check",
|
||||
%attribute array "groups" {
|
||||
%attribute name(HostGroup) "*"
|
||||
},
|
||||
%attribute dictionary "services" {
|
||||
%attribute dictionary "*" {
|
||||
%attribute array "templates" {
|
||||
%attribute name(Service) "*"
|
||||
},
|
||||
|
||||
%attribute any "*"
|
||||
}
|
||||
%type Host {
|
||||
%attribute %string "display_name",
|
||||
%attribute %string "check",
|
||||
%attribute %array "groups" {
|
||||
%attribute %name(HostGroup) "*"
|
||||
},
|
||||
|
||||
%attribute dictionary "dependencies" {
|
||||
%attribute dictionary "*" {
|
||||
%attribute array "templates" {
|
||||
%attribute name(Dependency) "*"
|
||||
},
|
||||
|
||||
%attribute any "*"
|
||||
}
|
||||
},
|
||||
|
||||
%attribute dictionary "macros" {
|
||||
%attribute string "*"
|
||||
%attribute %dictionary "macros" {
|
||||
%attribute %string "*"
|
||||
}
|
||||
}
|
||||
|
||||
type HostGroup {
|
||||
%attribute string "display_name"
|
||||
%type HostGroup {
|
||||
%attribute %string "display_name"
|
||||
}
|
||||
|
||||
type IcingaApplication {
|
||||
%type IcingaApplication {
|
||||
}
|
||||
|
||||
type IcingaStatusWriter {
|
||||
%attribute string "status_path",
|
||||
%attribute number "update_interval"
|
||||
%type IcingaStatusWriter {
|
||||
%attribute %string "status_path",
|
||||
%attribute %number "update_interval"
|
||||
}
|
||||
|
||||
type Service {
|
||||
%type Service {
|
||||
%require "host",
|
||||
%attribute name(Host) "host",
|
||||
%attribute %name(Host) "host",
|
||||
|
||||
%attribute string "short_name",
|
||||
%attribute %string "short_name",
|
||||
|
||||
%attribute string "display_name",
|
||||
%attribute %string "display_name",
|
||||
|
||||
%attribute dictionary "macros" {
|
||||
%attribute string "*"
|
||||
%attribute %dictionary "macros" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
|
||||
%require "check_command",
|
||||
%attribute name(CheckCommand) "check_command",
|
||||
%attribute number "max_check_attempts",
|
||||
%attribute name(TimePeriod) "check_period",
|
||||
%attribute number "check_interval",
|
||||
%attribute number "retry_interval",
|
||||
%attribute %name(CheckCommand) "check_command",
|
||||
%attribute %number "max_check_attempts",
|
||||
%attribute %name(TimePeriod) "check_period",
|
||||
%attribute %number "check_interval",
|
||||
%attribute %number "retry_interval",
|
||||
|
||||
%attribute number "enable_notifications",
|
||||
%attribute number "enable_active_checks",
|
||||
%attribute number "enable_passive_checks",
|
||||
%attribute number "enable_event_handler",
|
||||
%attribute %number "enable_notifications",
|
||||
%attribute %number "enable_active_checks",
|
||||
%attribute %number "enable_passive_checks",
|
||||
%attribute %number "enable_event_handler",
|
||||
|
||||
%attribute name(EventCommand) "event_command",
|
||||
%attribute %name(EventCommand) "event_command",
|
||||
|
||||
%attribute number "enable_flapping",
|
||||
%attribute number "flapping_threshold",
|
||||
%attribute %number "enable_flapping",
|
||||
%attribute %number "flapping_threshold",
|
||||
|
||||
%attribute number "enable_perfdata",
|
||||
%attribute %number "enable_perfdata",
|
||||
|
||||
%attribute number "volatile",
|
||||
%attribute %number "volatile",
|
||||
|
||||
%attribute dictionary "dependencies" {
|
||||
%attribute dictionary "*" {
|
||||
%attribute array "templates" {
|
||||
%attribute name(Dependency) "*"
|
||||
},
|
||||
|
||||
%attribute any "*"
|
||||
}
|
||||
%attribute %array "groups" {
|
||||
%attribute %name(ServiceGroup) "*"
|
||||
},
|
||||
|
||||
%attribute array "groups" {
|
||||
%attribute name(ServiceGroup) "*"
|
||||
},
|
||||
|
||||
%attribute dictionary "notifications" {
|
||||
%attribute dictionary "*" {
|
||||
%attribute array "templates" {
|
||||
%attribute name(Notification) "*"
|
||||
},
|
||||
|
||||
%attribute any "*"
|
||||
}
|
||||
},
|
||||
|
||||
%attribute dictionary "scheduled_downtimes" {
|
||||
%attribute dictionary "*" {
|
||||
%attribute array "templates" {
|
||||
%attribute name(ScheduledDowntime) "*"
|
||||
},
|
||||
|
||||
%attribute any "*"
|
||||
}
|
||||
},
|
||||
|
||||
%attribute any "templates",
|
||||
|
||||
%attribute array "authorities" {
|
||||
%attribute name(Endpoint) "*"
|
||||
%attribute %array "authorities" {
|
||||
%attribute %name(Endpoint) "*"
|
||||
},
|
||||
}
|
||||
|
||||
type ServiceGroup {
|
||||
%attribute string "display_name"
|
||||
%type ServiceGroup {
|
||||
%attribute %string "display_name"
|
||||
}
|
||||
|
||||
type Notification {
|
||||
%type Notification {
|
||||
%require "host",
|
||||
%attribute name(Host) "host",
|
||||
%attribute %name(Host) "host",
|
||||
|
||||
%require "service",
|
||||
%attribute string "service",
|
||||
%attribute %string "service",
|
||||
|
||||
%attribute dictionary "macros" {
|
||||
%attribute string "*"
|
||||
%attribute %dictionary "macros" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
|
||||
%attribute array "users" {
|
||||
%attribute name(User) "*"
|
||||
%attribute %array "users" {
|
||||
%attribute %name(User) "*"
|
||||
},
|
||||
%attribute array "user_groups" {
|
||||
%attribute name(UserGroup) "*"
|
||||
%attribute %array "user_groups" {
|
||||
%attribute %name(UserGroup) "*"
|
||||
},
|
||||
|
||||
%attribute dictionary "times" {
|
||||
%attribute number "begin",
|
||||
%attribute number "end",
|
||||
%attribute %dictionary "times" {
|
||||
%attribute %number "begin",
|
||||
%attribute %number "end",
|
||||
},
|
||||
|
||||
%require "notification_command",
|
||||
%attribute name(NotificationCommand) "notification_command",
|
||||
%attribute %name(NotificationCommand) "notification_command",
|
||||
|
||||
%attribute number "notification_interval",
|
||||
%attribute name(TimePeriod) "notification_period",
|
||||
%attribute %number "notification_interval",
|
||||
%attribute %name(TimePeriod) "notification_period",
|
||||
|
||||
%attribute number "notification_type_filter",
|
||||
%attribute number "notification_state_filter",
|
||||
%attribute %number "notification_%type_filter",
|
||||
%attribute %number "notification_state_filter",
|
||||
|
||||
%attribute any "templates",
|
||||
|
||||
%attribute array "authorities" {
|
||||
%attribute name(Endpoint) "*"
|
||||
%attribute %array "authorities" {
|
||||
%attribute %name(Endpoint) "*"
|
||||
},
|
||||
}
|
||||
|
||||
type User {
|
||||
%attribute string "display_name",
|
||||
%type User {
|
||||
%attribute %string "display_name",
|
||||
|
||||
%attribute dictionary "macros" {
|
||||
%attribute string "*"
|
||||
%attribute %dictionary "macros" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
|
||||
%attribute array "groups" {
|
||||
%attribute name(UserGroup) "*"
|
||||
%attribute %array "groups" {
|
||||
%attribute %name(UserGroup) "*"
|
||||
},
|
||||
|
||||
%attribute number "enable_notifications",
|
||||
%attribute number "notification_type_filter",
|
||||
%attribute number "notification_state_filter",
|
||||
%attribute name(TimePeriod) "notification_period"
|
||||
%attribute %number "enable_notifications",
|
||||
%attribute %number "notification_%type_filter",
|
||||
%attribute %number "notification_state_filter",
|
||||
%attribute %name(TimePeriod) "notification_period"
|
||||
}
|
||||
|
||||
type UserGroup {
|
||||
%attribute string "display_name"
|
||||
%type UserGroup {
|
||||
%attribute %string "display_name"
|
||||
}
|
||||
|
||||
type TimePeriod {
|
||||
%attribute string "display_name",
|
||||
%type TimePeriod {
|
||||
%attribute %string "display_name",
|
||||
|
||||
%require "methods",
|
||||
%attribute dictionary "methods" {
|
||||
%attribute %dictionary "methods" {
|
||||
%require "update",
|
||||
%attribute string "update"
|
||||
%attribute %string "update"
|
||||
},
|
||||
|
||||
/* %if (methods.update == "LegacyTimePeriod") { */
|
||||
// %require "ranges",
|
||||
%attribute dictionary "ranges" {
|
||||
%attribute string "*"
|
||||
%attribute %dictionary "ranges" {
|
||||
%attribute %string "*"
|
||||
}
|
||||
/* } */
|
||||
}
|
||||
|
||||
type Command {
|
||||
%type Command {
|
||||
%require "methods",
|
||||
%attribute dictionary "methods" {
|
||||
%attribute %dictionary "methods" {
|
||||
%require "execute",
|
||||
%attribute string "execute"
|
||||
%attribute %string "execute"
|
||||
},
|
||||
|
||||
/* %if (methods.execute == "PluginNotification" || methods.execute == "PluginCheck" || methods.execute == "PluginEvent") { */
|
||||
// %require "command",
|
||||
%attribute string "command",
|
||||
%attribute array "command" {
|
||||
%attribute string "*"
|
||||
%attribute %string "command",
|
||||
%attribute %array "command" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
%attribute array "export_macros" {
|
||||
%attribute string "*"
|
||||
%attribute %array "export_macros" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
%attribute array "escape_macros" {
|
||||
%attribute string "*"
|
||||
%attribute %array "escape_macros" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
%attribute dictionary "macros" {
|
||||
%attribute string "*"
|
||||
%attribute %dictionary "macros" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
%attribute number "timeout"
|
||||
%attribute %number "timeout"
|
||||
/* } */
|
||||
}
|
||||
|
||||
type CheckCommand inherits Command {
|
||||
%type CheckCommand %inherits Command {
|
||||
|
||||
}
|
||||
|
||||
type NotificationCommand inherits Command {
|
||||
%type NotificationCommand %inherits Command {
|
||||
|
||||
}
|
||||
|
||||
type EventCommand inherits Command {
|
||||
%type EventCommand %inherits Command {
|
||||
|
||||
}
|
||||
|
||||
type Domain {
|
||||
%attribute dictionary "acl" {
|
||||
%attribute number "*"
|
||||
%type Domain {
|
||||
%attribute %dictionary "acl" {
|
||||
%attribute %number "*"
|
||||
}
|
||||
}
|
||||
|
||||
type ScheduledDowntime {
|
||||
%type ScheduledDowntime {
|
||||
%require "host",
|
||||
%attribute name(Host) "host",
|
||||
%attribute %name(Host) "host",
|
||||
%require "service",
|
||||
%attribute string "service",
|
||||
%attribute %string "service",
|
||||
|
||||
%require "author",
|
||||
%attribute string "author",
|
||||
%attribute %string "author",
|
||||
|
||||
%require "comment",
|
||||
%attribute string "comment",
|
||||
%attribute %string "comment",
|
||||
|
||||
%attribute number "duration",
|
||||
%attribute number "fixed",
|
||||
%attribute %number "duration",
|
||||
%attribute %number "fixed",
|
||||
|
||||
%require "ranges",
|
||||
%attribute dictionary "ranges" {
|
||||
%attribute string "*"
|
||||
%attribute %dictionary "ranges" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
|
||||
%attribute any "templates"
|
||||
}
|
||||
|
||||
type Dependency {
|
||||
%type Dependency {
|
||||
%require "parent_host",
|
||||
%attribute name(Host) "parent_host",
|
||||
%attribute string "parent_service",
|
||||
%attribute %name(Host) "parent_host",
|
||||
%attribute %string "parent_service",
|
||||
|
||||
%require "child_host",
|
||||
%attribute name(Host) "child_host",
|
||||
%attribute string "child_service",
|
||||
%attribute %name(Host) "child_host",
|
||||
%attribute %string "child_service",
|
||||
|
||||
%attribute name(TimePeriod) "period",
|
||||
%attribute %name(TimePeriod) "period",
|
||||
|
||||
%attribute number "state_filter",
|
||||
%attribute number "disable_checks",
|
||||
%attribute number "disable_notifications"
|
||||
%attribute %number "state_filter",
|
||||
%attribute %number "disable_checks",
|
||||
%attribute %number "disable_notifications"
|
||||
}
|
||||
|
88
lib/icinga/notification-apply.cpp
Normal file
88
lib/icinga/notification-apply.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-present Icinga Development Team (http://www.icinga.org) *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software Foundation *
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#include "icinga/service.h"
|
||||
#include "config/configitembuilder.h"
|
||||
#include "base/initialize.h"
|
||||
#include "base/dynamictype.h"
|
||||
#include "base/convert.h"
|
||||
#include "base/logger_fwd.h"
|
||||
#include "base/context.h"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
INITIALIZE_ONCE(&Notification::RegisterApplyRuleHandler);
|
||||
|
||||
void Notification::RegisterApplyRuleHandler(void)
|
||||
{
|
||||
ApplyRule::RegisterType("Notification", "Service", &Notification::EvaluateApplyRules);
|
||||
}
|
||||
|
||||
void Notification::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
|
||||
{
|
||||
BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects<Service>()) {
|
||||
CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'");
|
||||
|
||||
Dictionary::Ptr locals = make_shared<Dictionary>();
|
||||
locals->Set("host", service->GetHost());
|
||||
locals->Set("service", service);
|
||||
|
||||
BOOST_FOREACH(const ApplyRule& rule, rules) {
|
||||
DebugInfo di = rule.GetDebugInfo();
|
||||
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Evaluating 'apply' rule (" << di << ")";
|
||||
CONTEXT(msgbuf.str());
|
||||
|
||||
if (!rule.EvaluateFilter(locals))
|
||||
continue;
|
||||
|
||||
std::ostringstream msgbuf2;
|
||||
msgbuf2 << "Applying notification '" << rule.GetName() << "' to service '" << service->GetName() << "' for rule " << di;
|
||||
Log(LogDebug, "icinga", msgbuf2.str());
|
||||
|
||||
std::ostringstream namebuf;
|
||||
namebuf << service->GetName() << "!" << rule.GetName();
|
||||
String name = namebuf.str();
|
||||
|
||||
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
|
||||
builder->SetType("Notification");
|
||||
builder->SetName(name);
|
||||
builder->SetScope(rule.GetScope());
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, "host", di),
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, service->GetHost()->GetName(), di),
|
||||
di));
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, "service", di),
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, service->GetShortName(), di),
|
||||
di));
|
||||
|
||||
builder->AddExpression(rule.GetExpression());
|
||||
|
||||
ConfigItem::Ptr serviceItem = builder->Compile();
|
||||
serviceItem->Register();
|
||||
DynamicObject::Ptr dobj = serviceItem->Commit();
|
||||
dobj->OnConfigLoaded();
|
||||
}
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@
|
||||
#include "icinga/user.h"
|
||||
#include "icinga/usergroup.h"
|
||||
#include "icinga/timeperiod.h"
|
||||
#include "config/applyrule.h"
|
||||
#include "base/array.h"
|
||||
|
||||
namespace icinga
|
||||
@ -86,6 +87,9 @@ public:
|
||||
|
||||
static boost::signals2::signal<void (const Notification::Ptr&, double, const String&)> OnNextNotificationChanged;
|
||||
|
||||
static void RegisterApplyRuleHandler(void);
|
||||
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
|
||||
|
||||
protected:
|
||||
virtual void Start(void);
|
||||
virtual void Stop(void);
|
||||
|
88
lib/icinga/scheduleddowntime-apply.cpp
Normal file
88
lib/icinga/scheduleddowntime-apply.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-present Icinga Development Team (http://www.icinga.org) *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software Foundation *
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#include "icinga/scheduleddowntime.h"
|
||||
#include "config/configitembuilder.h"
|
||||
#include "base/initialize.h"
|
||||
#include "base/dynamictype.h"
|
||||
#include "base/convert.h"
|
||||
#include "base/logger_fwd.h"
|
||||
#include "base/context.h"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
INITIALIZE_ONCE(&ScheduledDowntime::RegisterApplyRuleHandler);
|
||||
|
||||
void ScheduledDowntime::RegisterApplyRuleHandler(void)
|
||||
{
|
||||
ApplyRule::RegisterType("ScheduledDowntime", "Service", &ScheduledDowntime::EvaluateApplyRules);
|
||||
}
|
||||
|
||||
void ScheduledDowntime::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
|
||||
{
|
||||
BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjects<Service>()) {
|
||||
CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'");
|
||||
|
||||
Dictionary::Ptr locals = make_shared<Dictionary>();
|
||||
locals->Set("host", service->GetHost());
|
||||
locals->Set("service", service);
|
||||
|
||||
BOOST_FOREACH(const ApplyRule& rule, rules) {
|
||||
DebugInfo di = rule.GetDebugInfo();
|
||||
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Evaluating 'apply' rule (" << di << ")";
|
||||
CONTEXT(msgbuf.str());
|
||||
|
||||
if (!rule.EvaluateFilter(locals))
|
||||
continue;
|
||||
|
||||
std::ostringstream msgbuf2;
|
||||
msgbuf2 << "Applying scheduled downtime '" << rule.GetName() << "' to service '" << service->GetName() << "' for rule " << di;
|
||||
Log(LogDebug, "icinga", msgbuf2.str());
|
||||
|
||||
std::ostringstream namebuf;
|
||||
namebuf << service->GetName() << "!" << rule.GetName();
|
||||
String name = namebuf.str();
|
||||
|
||||
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
|
||||
builder->SetType("ScheduledDowntime");
|
||||
builder->SetName(name);
|
||||
builder->SetScope(rule.GetScope());
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, "host", di),
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, service->GetHost()->GetName(), di),
|
||||
di));
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, "service", di),
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, service->GetShortName(), di),
|
||||
di));
|
||||
|
||||
builder->AddExpression(rule.GetExpression());
|
||||
|
||||
ConfigItem::Ptr serviceItem = builder->Compile();
|
||||
serviceItem->Register();
|
||||
DynamicObject::Ptr dobj = serviceItem->Commit();
|
||||
dobj->OnConfigLoaded();
|
||||
}
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@
|
||||
#include "icinga/i2-icinga.h"
|
||||
#include "icinga/scheduleddowntime.th"
|
||||
#include "icinga/service.h"
|
||||
#include "config/applyrule.h"
|
||||
#include <utility>
|
||||
|
||||
namespace icinga
|
||||
@ -43,6 +44,9 @@ public:
|
||||
|
||||
Service::Ptr GetService(void) const;
|
||||
|
||||
static void RegisterApplyRuleHandler(void);
|
||||
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
|
||||
|
||||
protected:
|
||||
virtual void Start(void);
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#include "icinga/host.h"
|
||||
#include "icinga/service.h"
|
||||
#include "config/configitembuilder.h"
|
||||
#include "base/initialize.h"
|
||||
#include "base/dynamictype.h"
|
||||
@ -28,59 +28,55 @@
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
INITIALIZE_ONCE(&Host::RegisterApplyRuleHandler);
|
||||
INITIALIZE_ONCE(&Service::RegisterApplyRuleHandler);
|
||||
|
||||
void Host::RegisterApplyRuleHandler(void)
|
||||
void Service::RegisterApplyRuleHandler(void)
|
||||
{
|
||||
ApplyRule::RegisterCombination("Service", "Host", &Host::EvaluateApplyRules);
|
||||
ApplyRule::RegisterType("Service", "Host", &Service::EvaluateApplyRules);
|
||||
}
|
||||
|
||||
void Host::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
|
||||
void Service::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
|
||||
{
|
||||
BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjects<Host>()) {
|
||||
CONTEXT("Evaluating 'apply' rules for Host '" + host->GetName() + "'");
|
||||
|
||||
Dictionary::Ptr locals = make_shared<Dictionary>();
|
||||
locals->Set("host", host->GetName());
|
||||
|
||||
Array::Ptr groups = host->GetGroups();
|
||||
if (!groups)
|
||||
groups = make_shared<Array>();
|
||||
locals->Set("hostgroups", groups);
|
||||
locals->Set("host", host);
|
||||
|
||||
BOOST_FOREACH(const ApplyRule& rule, rules) {
|
||||
DebugInfo di = rule.GetDebugInfo();
|
||||
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Evaluating 'apply' rule (" << rule.GetDebugInfo() << ")";
|
||||
msgbuf << "Evaluating 'apply' rule (" << di << ")";
|
||||
CONTEXT(msgbuf.str());
|
||||
|
||||
Value result = rule.GetExpression()->Evaluate(locals);
|
||||
|
||||
try {
|
||||
if (!static_cast<bool>(result))
|
||||
continue;
|
||||
} catch (...) {
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Apply rule (" << rule.GetDebugInfo() << ") returned invalid data type, expected bool: " + JsonSerialize(result);
|
||||
Log(LogCritical, "icinga", msgbuf.str());
|
||||
|
||||
if (!rule.EvaluateFilter(locals))
|
||||
continue;
|
||||
}
|
||||
|
||||
std::ostringstream msgbuf2;
|
||||
msgbuf2 << "Applying service template '" << rule.GetTemplate() << "' to host '" << host->GetName() << "' for rule " << rule.GetDebugInfo();
|
||||
msgbuf2 << "Applying service '" << rule.GetName() << "' to host '" << host->GetName() << "' for rule " << di;
|
||||
Log(LogDebug, "icinga", msgbuf2.str());
|
||||
|
||||
std::ostringstream namebuf;
|
||||
namebuf << host->GetName() << "!apply!" << rule.GetTemplate();
|
||||
namebuf << host->GetName() << "!" << rule.GetName();
|
||||
String name = namebuf.str();
|
||||
|
||||
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(rule.GetDebugInfo());
|
||||
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
|
||||
builder->SetType("Service");
|
||||
builder->SetName(name);
|
||||
builder->SetScope(rule.GetScope());
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "host", make_shared<AExpression>(&AExpression::OpLiteral, host->GetName(), rule.GetDebugInfo()), rule.GetDebugInfo()));
|
||||
|
||||
builder->AddParent(rule.GetTemplate());
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, "host", di),
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, host->GetName(), di),
|
||||
di));
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, "short_name", di),
|
||||
make_shared<AExpression>(&AExpression::OpLiteral, rule.GetName(), di),
|
||||
di));
|
||||
|
||||
builder->AddExpression(rule.GetExpression());
|
||||
|
||||
ConfigItem::Ptr serviceItem = builder->Compile();
|
||||
serviceItem->Register();
|
@ -154,89 +154,3 @@ std::set<Service::Ptr> Service::GetChildServices(void) const
|
||||
return parents;
|
||||
}
|
||||
|
||||
void Service::UpdateSlaveDependencies(void)
|
||||
{
|
||||
/*
|
||||
* pass == 0 -> steal host's dependency definitions
|
||||
* pass == 1 -> service's dependencies
|
||||
*/
|
||||
for (int pass = 0; pass < 2; pass++) {
|
||||
/* Service dependency descs */
|
||||
Dictionary::Ptr descs;
|
||||
|
||||
if (pass == 0 && !IsHostCheck())
|
||||
continue;
|
||||
|
||||
if (pass == 0)
|
||||
descs = GetHost()->GetDependencyDescriptions();
|
||||
else
|
||||
descs = GetDependencyDescriptions();
|
||||
|
||||
if (!descs || descs->GetLength() == 0)
|
||||
continue;
|
||||
|
||||
ConfigItem::Ptr item;
|
||||
|
||||
if (pass == 0)
|
||||
item = ConfigItem::GetObject("Host", GetHost()->GetName());
|
||||
else
|
||||
item = ConfigItem::GetObject("Service", GetName());
|
||||
|
||||
ObjectLock olock(descs);
|
||||
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, descs) {
|
||||
std::ostringstream namebuf;
|
||||
namebuf << GetName() << "!" << kv.first;
|
||||
String name = namebuf.str();
|
||||
|
||||
std::vector<String> path;
|
||||
path.push_back("dependencies");
|
||||
path.push_back(kv.first);
|
||||
|
||||
AExpression::Ptr exprl;
|
||||
|
||||
{
|
||||
ObjectLock ilock(item);
|
||||
|
||||
exprl = item->GetLinkedExpressionList();
|
||||
}
|
||||
|
||||
DebugInfo di;
|
||||
exprl->FindDebugInfoPath(path, di);
|
||||
|
||||
if (di.Path.IsEmpty())
|
||||
di = item->GetDebugInfo();
|
||||
|
||||
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
|
||||
builder->SetType("Dependency");
|
||||
builder->SetName(name);
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "child_host", make_shared<AExpression>(&AExpression::OpLiteral, GetHost()->GetName(), di), di));
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "child_service", make_shared<AExpression>(&AExpression::OpLiteral, GetShortName(), di), di));
|
||||
|
||||
Dictionary::Ptr dependency = kv.second;
|
||||
|
||||
Array::Ptr templates = dependency->Get("templates");
|
||||
|
||||
if (templates) {
|
||||
ObjectLock tlock(templates);
|
||||
|
||||
BOOST_FOREACH(const Value& tmpl, templates) {
|
||||
builder->AddParent(tmpl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clone attributes from the scheduled downtime expression list. */
|
||||
Array::Ptr sd_exprl = make_shared<Array>();
|
||||
exprl->ExtractPath(path, sd_exprl);
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpDict, sd_exprl, true, di));
|
||||
|
||||
builder->SetScope(item->GetScope());
|
||||
|
||||
ConfigItem::Ptr dependencyItem = builder->Compile();
|
||||
dependencyItem->Register();
|
||||
DynamicObject::Ptr dobj = dependencyItem->Commit();
|
||||
dobj->OnConfigLoaded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -321,70 +321,3 @@ int Service::GetDowntimeDepth(void) const
|
||||
return downtime_depth;
|
||||
}
|
||||
|
||||
void Service::UpdateSlaveScheduledDowntimes(void)
|
||||
{
|
||||
/* Service scheduled downtime descs */
|
||||
Dictionary::Ptr descs = GetScheduledDowntimeDescriptions();
|
||||
|
||||
if (!descs || descs->GetLength() == 0)
|
||||
return;
|
||||
|
||||
ConfigItem::Ptr item = ConfigItem::GetObject("Service", GetName());
|
||||
|
||||
ObjectLock olock(descs);
|
||||
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, descs) {
|
||||
std::ostringstream namebuf;
|
||||
namebuf << GetName() << "!" << kv.first;
|
||||
String name = namebuf.str();
|
||||
|
||||
std::vector<String> path;
|
||||
path.push_back("scheduled_downtimes");
|
||||
path.push_back(kv.first);
|
||||
|
||||
AExpression::Ptr exprl;
|
||||
|
||||
{
|
||||
ObjectLock ilock(item);
|
||||
|
||||
exprl = item->GetLinkedExpressionList();
|
||||
}
|
||||
|
||||
DebugInfo di;
|
||||
exprl->FindDebugInfoPath(path, di);
|
||||
|
||||
if (di.Path.IsEmpty())
|
||||
di = item->GetDebugInfo();
|
||||
|
||||
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
|
||||
builder->SetType("ScheduledDowntime");
|
||||
builder->SetName(name);
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "host", make_shared<AExpression>(&AExpression::OpLiteral, GetHost()->GetName(), di), di));
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "service", make_shared<AExpression>(&AExpression::OpLiteral, GetShortName(), di), di));
|
||||
|
||||
Dictionary::Ptr scheduledDowntime = kv.second;
|
||||
|
||||
Array::Ptr templates = scheduledDowntime->Get("templates");
|
||||
|
||||
if (templates) {
|
||||
ObjectLock tlock(templates);
|
||||
|
||||
BOOST_FOREACH(const Value& tmpl, templates) {
|
||||
builder->AddParent(tmpl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clone attributes from the scheduled downtime expression list. */
|
||||
Array::Ptr sd_exprl = make_shared<Array>();
|
||||
exprl->ExtractPath(path, sd_exprl);
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpDict, sd_exprl, true, di));
|
||||
|
||||
builder->SetScope(item->GetScope());
|
||||
|
||||
ConfigItem::Ptr scheduledDowntimeItem = builder->Compile();
|
||||
scheduledDowntimeItem->Register();
|
||||
DynamicObject::Ptr dobj = scheduledDowntimeItem->Commit();
|
||||
dobj->OnConfigLoaded();
|
||||
}
|
||||
}
|
||||
|
@ -100,74 +100,6 @@ void Service::RemoveNotification(const Notification::Ptr& notification)
|
||||
m_Notifications.erase(notification);
|
||||
}
|
||||
|
||||
void Service::UpdateSlaveNotifications(void)
|
||||
{
|
||||
/* Service notification descs */
|
||||
Dictionary::Ptr descs = GetNotificationDescriptions();
|
||||
|
||||
if (!descs || descs->GetLength() == 0)
|
||||
return;
|
||||
|
||||
ConfigItem::Ptr item = ConfigItem::GetObject("Service", GetName());
|
||||
|
||||
ObjectLock olock(descs);
|
||||
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, descs) {
|
||||
std::ostringstream namebuf;
|
||||
namebuf << GetName() << "!" << kv.first;
|
||||
String name = namebuf.str();
|
||||
|
||||
std::vector<String> path;
|
||||
path.push_back("notifications");
|
||||
path.push_back(kv.first);
|
||||
|
||||
AExpression::Ptr exprl;
|
||||
|
||||
{
|
||||
ObjectLock ilock(item);
|
||||
|
||||
exprl = item->GetLinkedExpressionList();
|
||||
}
|
||||
|
||||
DebugInfo di;
|
||||
exprl->FindDebugInfoPath(path, di);
|
||||
|
||||
if (di.Path.IsEmpty())
|
||||
di = item->GetDebugInfo();
|
||||
|
||||
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
|
||||
builder->SetType("Notification");
|
||||
builder->SetName(name);
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "host", make_shared<AExpression>(&AExpression::OpLiteral, GetHost()->GetName(), di), di));
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "service", make_shared<AExpression>(&AExpression::OpLiteral, GetShortName(), di), di));
|
||||
|
||||
Dictionary::Ptr notification = kv.second;
|
||||
|
||||
Array::Ptr templates = notification->Get("templates");
|
||||
|
||||
if (templates) {
|
||||
ObjectLock tlock(templates);
|
||||
|
||||
BOOST_FOREACH(const Value& tmpl, templates) {
|
||||
builder->AddParent(tmpl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clone attributes from the notification expression list. */
|
||||
Array::Ptr nfc_exprl = make_shared<Array>();
|
||||
exprl->ExtractPath(path, nfc_exprl);
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpDict, nfc_exprl, true, di));
|
||||
|
||||
builder->SetScope(item->GetScope());
|
||||
|
||||
ConfigItem::Ptr notificationItem = builder->Compile();
|
||||
notificationItem->Register();
|
||||
DynamicObject::Ptr dobj = notificationItem->Commit();
|
||||
dobj->OnConfigLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
bool Service::GetEnableNotifications(void) const
|
||||
{
|
||||
if (!GetOverrideEnableNotifications().IsEmpty())
|
||||
|
@ -76,10 +76,6 @@ void Service::OnConfigLoaded(void)
|
||||
if (m_Host)
|
||||
m_Host->AddService(GetSelf());
|
||||
|
||||
UpdateSlaveNotifications();
|
||||
UpdateSlaveScheduledDowntimes();
|
||||
UpdateSlaveDependencies();
|
||||
|
||||
SetSchedulingOffset(Utility::Random());
|
||||
}
|
||||
|
||||
|
@ -220,8 +220,6 @@ public:
|
||||
bool IsInDowntime(void) const;
|
||||
bool IsAcknowledged(void);
|
||||
|
||||
void UpdateSlaveScheduledDowntimes(void);
|
||||
|
||||
/* Comments */
|
||||
static int GetNextCommentID(void);
|
||||
|
||||
@ -251,8 +249,6 @@ public:
|
||||
|
||||
void ResetNotificationNumbers(void);
|
||||
|
||||
void UpdateSlaveNotifications(void);
|
||||
|
||||
/* Event Handler */
|
||||
void ExecuteEventHandler(void);
|
||||
|
||||
@ -284,7 +280,8 @@ public:
|
||||
void RemoveReverseDependency(const shared_ptr<Dependency>& dep);
|
||||
std::set<shared_ptr<Dependency> > GetReverseDependencies(void) const;
|
||||
|
||||
void UpdateSlaveDependencies(void);
|
||||
static void RegisterApplyRuleHandler(void);
|
||||
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
|
||||
|
||||
protected:
|
||||
virtual void Start(void);
|
||||
|
@ -17,26 +17,26 @@
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
type Endpoint {
|
||||
%type Endpoint {
|
||||
%require "host",
|
||||
%attribute string "host",
|
||||
%attribute %string "host",
|
||||
|
||||
%require "port",
|
||||
%attribute string "port",
|
||||
%attribute %string "port",
|
||||
|
||||
%attribute array "config_files" {
|
||||
%attribute string "*"
|
||||
%attribute %array "config_files" {
|
||||
%attribute %string "*"
|
||||
},
|
||||
|
||||
%attribute array "config_files_recursive" {
|
||||
%attribute string "*",
|
||||
%attribute dictionary "*" {
|
||||
%attribute string "path",
|
||||
%attribute string "pattern"
|
||||
%attribute %array "config_files_recursive" {
|
||||
%attribute %string "*",
|
||||
%attribute %dictionary "*" {
|
||||
%attribute %string "path",
|
||||
%attribute %string "pattern"
|
||||
}
|
||||
},
|
||||
|
||||
%attribute array "accept_config" {
|
||||
%attribute name(Endpoint) "*"
|
||||
%attribute %array "accept_config" {
|
||||
%attribute %name(Endpoint) "*"
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
object EventCommand "test_event" inherits "plugin-event-command" {
|
||||
object EventCommand "test_event" {
|
||||
import "plugin-event-command",
|
||||
|
||||
command = {{{echo "\
|
||||
$$HOSTNAME$HOSTNAME$\
|
||||
|HOSTNAME=$HOSTNAME$\
|
||||
|
@ -24,7 +24,9 @@ template Notification "mail-notification" {
|
||||
/**
|
||||
* 1:1 copy of the default command
|
||||
*/
|
||||
object NotificationCommand "mail-service-notification" inherits "plugin-notification-command" {
|
||||
object NotificationCommand "mail-service-notification" {
|
||||
import "plugin-notification-command",
|
||||
|
||||
command = [ (IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh") ],
|
||||
|
||||
export_macros = [
|
||||
|
Loading…
x
Reference in New Issue
Block a user