From b75aa74cbdc86f0a41c1f05938f25f414df06a7c Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 17 Nov 2015 22:04:50 +0100 Subject: [PATCH 01/32] Fix crash in Process::IOThreadProc when building Icinga 2 with GCC 4.7.2 fixes #10648 --- lib/base/process.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/base/process.cpp b/lib/base/process.cpp index 089e41dae..37ca62935 100644 --- a/lib/base/process.cpp +++ b/lib/base/process.cpp @@ -199,8 +199,8 @@ void Process::IOThreadProc(int tid) #endif /* _WIN32 */ int i = 1; - std::pair kv; - BOOST_FOREACH(kv, l_Processes[tid]) { + typedef std::pair kv_pair; + BOOST_FOREACH(const kv_pair& kv, l_Processes[tid]) { const Process::Ptr& process = kv.second; #ifdef _WIN32 handles[i] = kv.first; From 51dba718c5b28162726a7341ff4c83c5cbc40d32 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Wed, 18 Nov 2015 12:44:13 +0100 Subject: [PATCH 02/32] Fix webinject URL fixes #10661 --- doc/7-icinga-template-library.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/7-icinga-template-library.md b/doc/7-icinga-template-library.md index a79c2b83b..6c271bdc5 100644 --- a/doc/7-icinga-template-library.md +++ b/doc/7-icinga-template-library.md @@ -1945,7 +1945,7 @@ This category includes all plugins for web-based checks. #### webinject -Check command object for the [check_webinject](http://http://www.webinject.org/manual.html) plugin. +Check command object for the [check_webinject](http://www.webinject.org/manual.html) plugin. Custom attributes passed as [command parameters](3-monitoring-basics.md#command-passing-parameters): From 5c310c4ec85a4339840bb96d26110e82d7f5c348 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 18 Nov 2015 20:18:04 +0100 Subject: [PATCH 03/32] Fix typo in prepare-dirs / safe-reload fixes #10663 --- etc/initsystem/prepare-dirs | 2 +- etc/initsystem/safe-reload | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/initsystem/prepare-dirs b/etc/initsystem/prepare-dirs index 64757c2a6..6c4a08869 100644 --- a/etc/initsystem/prepare-dirs +++ b/etc/initsystem/prepare-dirs @@ -47,7 +47,7 @@ fi mkdir -p $ICINGA2_RUN_DIR/icinga2/cmd chown $ICINGA2_USER:$ICINGA2_COMMAND_GROUP $ICINGA2_RUN_DIR/icinga2/cmd -if type restorecon >/dev/null 2&>1; then +if type restorecon >/dev/null 2>&1; then restorecon -R $ICINGA2_RUN_DIR/icinga2/ fi chmod 2750 $ICINGA2_RUN_DIR/icinga2/cmd diff --git a/etc/initsystem/safe-reload b/etc/initsystem/safe-reload index c22069cce..faac2dbc7 100644 --- a/etc/initsystem/safe-reload +++ b/etc/initsystem/safe-reload @@ -12,7 +12,7 @@ printf "Validating config files: " OUTPUTFILE=`mktemp` -if type chcon >/dev/null 2&>1; then +if type chcon >/dev/null 2>&1; then chcon -t icinga2_tmp_t $OUTPUTFILE fi From b43d2256e5451b569fc9bcf3ecf65850b0b157c1 Mon Sep 17 00:00:00 2001 From: Bruno Lingner Date: Sat, 14 Nov 2015 13:08:21 +0100 Subject: [PATCH 04/32] Add by_ssh_options argument for the check_by_ssh plugin fixes #10622 Signed-off-by: Gunnar Beutner --- doc/7-icinga-template-library.md | 1 + itl/command-plugins.conf | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/doc/7-icinga-template-library.md b/doc/7-icinga-template-library.md index 6c271bdc5..588617ac0 100644 --- a/doc/7-icinga-template-library.md +++ b/doc/7-icinga-template-library.md @@ -128,6 +128,7 @@ by_ssh_quiet | **Optional.** Whether to suppress SSH warnings. Defaults to fa by_ssh_warn | **Optional.** The warning threshold. by_ssh_crit | **Optional.** The critical threshold. by_ssh_timeout | **Optional.** The timeout in seconds. +by_ssh_options | **Optional.** Call ssh with '-o OPTION' (multiple options may be specified as an array). ### clamd diff --git a/itl/command-plugins.conf b/itl/command-plugins.conf index 949fe418e..c201141c2 100644 --- a/itl/command-plugins.conf +++ b/itl/command-plugins.conf @@ -1369,6 +1369,10 @@ object CheckCommand "by_ssh" { "-w" = "$by_ssh_warn$" "-c" = "$by_ssh_crit$" "-t" = "$by_ssh_timeout$" + "-o" = { + value = "$by_ssh_options$" + description = "Provide ssh options (may be repeated)" + } } vars.by_ssh_address = "$check_address$" From 9f348c63f2cef97816788f47f1ea43b4c8b63441 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 18 Nov 2015 20:30:42 +0100 Subject: [PATCH 05/32] Update AUTHORS refs #10622 --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index ed2492071..f12b583a3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,6 +8,7 @@ Benedikt Heine Bernd Erk Blerim Sheqa Brian Dockter +Bruno Lingner Carlos Cesario Christian Harke Christian Jonak From aaa9715a67a67186e6ace3e306a4c4ec1070f742 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Thu, 19 Nov 2015 17:06:41 +0100 Subject: [PATCH 06/32] Fix pki new-ca not checking for existing ca files fixes #10677 --- lib/cli/pkiutility.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/cli/pkiutility.cpp b/lib/cli/pkiutility.cpp index d40cdc2da..6f0faab80 100644 --- a/lib/cli/pkiutility.cpp +++ b/lib/cli/pkiutility.cpp @@ -45,17 +45,20 @@ String PkiUtility::GetLocalCaPath(void) int PkiUtility::NewCa(void) { - String cadir = GetLocalCaPath(); + String caDir = GetLocalCaPath(); + String caCertFile = caDir + "/ca.crt"; + String caKeyFile = caDir + "/ca.key"; + String caSerialFile = caDir + "/serial.txt"; - if (Utility::PathExists(cadir)) { + if (Utility::PathExists(caCertFile) && Utility::PathExists(caKeyFile)) { Log(LogCritical, "cli") - << "CA directory '" << cadir << "' already exists."; + << "CA files '" << caCertFile << "' and '" << caKeyFile << "'already exist."; return 1; } - Utility::MkDirP(cadir, 0700); + Utility::MkDirP(caDir, 0700); - MakeX509CSR("Icinga CA", cadir + "/ca.key", String(), cadir + "/ca.crt", cadir + "/serial.txt", true); + MakeX509CSR("Icinga CA", caKeyFile, String(), caCertFile, caSerialFile, true); return 0; } From 8e7957802e2a773c2b0ca14b878d626128791934 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 20 Nov 2015 10:48:48 +0100 Subject: [PATCH 07/32] Fix indentation in command-plugins.conf fixes #10667 --- itl/command-plugins.conf | 84 ++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/itl/command-plugins.conf b/itl/command-plugins.conf index c201141c2..8cfa91fe3 100644 --- a/itl/command-plugins.conf +++ b/itl/command-plugins.conf @@ -857,48 +857,48 @@ object CheckCommand "disk" { } object CheckCommand "disk_smb" { - import "plugin-check-command" + import "plugin-check-command" - command = [ PluginDir + "/check_disk_smb" ] + command = [ PluginDir + "/check_disk_smb" ] - arguments = { - "-H" = { - value = "$disk_smb_hostname$" - description = "NetBIOS name of the server." - } - "-s" = { - value = "$disk_smb_share$" - description = "Share name to be tested." - } - "-W" = { - value = "$disk_smb_workgroup$" - description = "Workgroup or Domain used (Defaults to 'WORKGROUP' if omitted)." - } - "-a" = { - value = "$disk_smb_address$" - description = "IP-address of HOST (only necessary if HOST is in another network)." - } - "-u" = { - value = "$disk_smb_username$" - description = "Username to log in to server. (Defaults to 'guest' if omitted)." - } - "-p" = { - value = "$disk_smb_password$" - description = "Password to log in to server. (Defaults to an empty password if omitted)." - } - "-w" = { - value = "$disk_smb_wused$" - description = "Percent of used space at which a warning will be generated (Default: 85%)." - } - "-c" = { - value = "$disk_smb_cused$" - description = "Percent of used space at which a critical will be generated (Defaults: 95%)" - } - "-P" = { - value = "$disk_smb_port$" - description = "Port to be used to connect to. Some Windows boxes use 139, others 445 (Defaults to smbclient default if omitted)." - } - } + arguments = { + "-H" = { + value = "$disk_smb_hostname$" + description = "NetBIOS name of the server." + } + "-s" = { + value = "$disk_smb_share$" + description = "Share name to be tested." + } + "-W" = { + value = "$disk_smb_workgroup$" + description = "Workgroup or Domain used (Defaults to 'WORKGROUP' if omitted)." + } + "-a" = { + value = "$disk_smb_address$" + description = "IP-address of HOST (only necessary if HOST is in another network)." + } + "-u" = { + value = "$disk_smb_username$" + description = "Username to log in to server. (Defaults to 'guest' if omitted)." + } + "-p" = { + value = "$disk_smb_password$" + description = "Password to log in to server. (Defaults to an empty password if omitted)." + } + "-w" = { + value = "$disk_smb_wused$" + description = "Percent of used space at which a warning will be generated (Default: 85%)." + } + "-c" = { + value = "$disk_smb_cused$" + description = "Percent of used space at which a critical will be generated (Defaults: 95%)" + } + "-P" = { + value = "$disk_smb_port$" + description = "Port to be used to connect to. Some Windows boxes use 139, others 445 (Defaults to smbclient default if omitted)." + } + } vars.disk_smb_wused = "85%" vars.disk_smb_cused = "95%" @@ -1514,8 +1514,8 @@ object CheckCommand "icmp" { } object CheckCommand "ldap" { - import "plugin-check-command" - import "ipv4-or-ipv6" + import "plugin-check-command" + import "ipv4-or-ipv6" command = [ PluginDir + "/check_ldap" ] From 24b70899647f4c79464a1a35efd7e84a3f943b81 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 20 Nov 2015 15:52:11 +0100 Subject: [PATCH 08/32] Fix: CLI command 'repository add' doesn't work fixes #10690 --- lib/cli/repositoryutility.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/cli/repositoryutility.cpp b/lib/cli/repositoryutility.cpp index 53acd01fd..bcbaf1070 100644 --- a/lib/cli/repositoryutility.cpp +++ b/lib/cli/repositoryutility.cpp @@ -233,6 +233,7 @@ bool RepositoryUtility::AddObject(const std::vector& object_paths, const if (check_config) { try { ConfigObject::Ptr object = static_pointer_cast(utype->Instantiate()); + attrs->Set("type", utype->GetName()); Deserialize(object, attrs, false, FAConfig); object->SetName(name); From 04c803243ad8bb4409267147d56d4a5cd81bde80 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Fri, 20 Nov 2015 15:57:16 +0100 Subject: [PATCH 09/32] Fix typos in the documentation fixes #10692 Signed-off-by: Gunnar Beutner --- doc/17-upgrading-icinga-2.md | 8 ++++---- doc/22-migrating-from-icinga-1x.md | 4 ++-- doc/3-monitoring-basics.md | 6 +++--- doc/4-configuring-icinga-2.md | 1 - doc/5-advanced-topics.md | 14 +++++++------- doc/7-icinga-template-library.md | 12 ++++++------ doc/8-cli-commands.md | 2 +- doc/9-icinga2-api.md | 2 +- 8 files changed, 24 insertions(+), 25 deletions(-) diff --git a/doc/17-upgrading-icinga-2.md b/doc/17-upgrading-icinga-2.md index c96745057..005d01f6c 100644 --- a/doc/17-upgrading-icinga-2.md +++ b/doc/17-upgrading-icinga-2.md @@ -12,7 +12,7 @@ If you're upgrading an existing Icinga 2 instance you should check the > > If there isn't an upgrade file for your current version available there's nothing to do. -Apply all database schema upgrade files incrementially. +Apply all database schema upgrade files incrementally. # mysql -u root -p icinga < /usr/share/icinga2-ido-mysql/schema/upgrade/.sql @@ -27,7 +27,7 @@ the *upgrade* directory: 2.0.2.sql 2.1.0.sql 2.2.0.sql 2.3.0.sql There are two new upgrade files called `2.1.0.sql`, `2.2.0.sql` and `2.3.0.sql` -which must be applied incrementially to your IDO database. +which must be applied incrementally to your IDO database. ## Upgrading the PostgreSQL database @@ -38,7 +38,7 @@ If you're updating an existing Icinga 2 instance you should check the > > If there isn't an upgrade file for your current version available there's nothing to do. -Apply all database schema upgrade files incrementially. +Apply all database schema upgrade files incrementally. # export PGPASSWORD=icinga # psql -U icinga -d icinga < /usr/share/icinga2-ido-pgsql/schema/upgrade/.sql @@ -53,4 +53,4 @@ the *upgrade* directory: 2.0.2.sql 2.1.0.sql 2.2.0.sql 2.3.0.sql There are two new upgrade files called `2.1.0.sql`, `2.2.0.sql` and `2.3.0.sql` -which must be applied incrementially to your IDO database. +which must be applied incrementally to your IDO database. diff --git a/doc/22-migrating-from-icinga-1x.md b/doc/22-migrating-from-icinga-1x.md index c6e742f44..aacfe2471 100644 --- a/doc/22-migrating-from-icinga-1x.md +++ b/doc/22-migrating-from-icinga-1x.md @@ -1184,7 +1184,7 @@ Icinga 2 doesn't support non-persistent comments. Unlike in Icinga 1.x there are three different command types in Icinga 2: `CheckCommand`, `NotificationCommand`, and `EventCommand`. -For example in Icinga 1.x it is possible to accidently use a notification +For example in Icinga 1.x it is possible to accidentally use a notification command as an event handler which might cause problems depending on which runtime macros are used in the notification command. @@ -1356,7 +1356,7 @@ is as follows: The flapping value is then compared to the low and high flapping thresholds. -The algorithm used in Icinga 2 does not store the past states but calculcates the flapping +The algorithm used in Icinga 2 does not store the past states but calculates the flapping threshold from a single value based on counters and half-life values. Icinga 2 compares the value with a single flapping threshold configuration attribute. diff --git a/doc/3-monitoring-basics.md b/doc/3-monitoring-basics.md index 6cad4c0f4..a39a8215f 100644 --- a/doc/3-monitoring-basics.md +++ b/doc/3-monitoring-basics.md @@ -672,7 +672,7 @@ with many interfaces (services). The following requirements/problems apply: * Each interface service check should be named with a prefix and a name defined in your host object (which could be generated from your CMDB, etc) * Each interface has its own vlan tag * Some interfaces have QoS enabled -* Additional attributes such as `display_name` or `notes, `notes_url` and `action_url` must be +* Additional attributes such as `display_name` or `notes`, `notes_url` and `action_url` must be dynamically generated @@ -810,7 +810,7 @@ inherited custom attributes: # icinga2 daemon -C # icinga2 object list --type Service --name *catalyst* -Object 'cisco-catalyst-6509-34!if-GigabitEthernet0/2' of type 'Service': + Object 'cisco-catalyst-6509-34!if-GigabitEthernet0/2' of type 'Service': ...... * vars % = modified in '/etc/icinga2/conf.d/iftraffic.conf', lines 59:3-59:26 @@ -969,7 +969,7 @@ to a group based on their attributes: } In this example all hosts with the `vars` attribute `mssql_port` -will be added as members to the host group `mssql`. However, all `*internal` +will be added as members to the host group `mssql`. However, all `\*internal` hosts or with the `test_server` attribute set to `true` are not added to this group. diff --git a/doc/4-configuring-icinga-2.md b/doc/4-configuring-icinga-2.md index a4635e420..998d73924 100644 --- a/doc/4-configuring-icinga-2.md +++ b/doc/4-configuring-icinga-2.md @@ -382,7 +382,6 @@ The idea is simple: Your host in [hosts.conf](4-configuring-icinga-2.md#hosts-co Remember the example from [hosts.conf](4-configuring-icinga-2.md#hosts-conf): ... - /* Define disks and attributes for service apply rules in `services.conf`. */ vars.disks["disk"] = { /* No parameters. */ diff --git a/doc/5-advanced-topics.md b/doc/5-advanced-topics.md index eefa3fad4..fc08c563d 100644 --- a/doc/5-advanced-topics.md +++ b/doc/5-advanced-topics.md @@ -6,7 +6,7 @@ can safely skip over things you're not interested in. ## Downtimes Downtimes can be scheduled for planned server maintenance or -any other targetted service outage you are aware of in advance. +any other targeted service outage you are aware of in advance. Downtimes will suppress any notifications, and may trigger other downtimes too. If the downtime was set by accident, or the duration @@ -66,7 +66,7 @@ This is optional when scheduling a downtime. If there is already a downtime scheduled for a future maintenance, the current downtime can be triggered by that downtime. This renders useful if you have scheduled a host downtime and are now scheduling a child host's downtime getting triggered by the parent -downtime on NOT-OK state change. +downtime on `NOT-OK` state change. ### Recurring Downtimes @@ -98,7 +98,7 @@ Example: Comments can be added at runtime and are persistent over restarts. You can add useful information for others on repeating incidents (for example "last time syslog at 100% cpu on 17.10.2013 due to stale nfs mount") which -is primarly accessible using web interfaces. +is primarily accessible using web interfaces. Adding and deleting comment actions are possible through the external command pipe provided with the `ExternalCommandListener` configuration. The caller must @@ -140,7 +140,7 @@ configuration attributes for `Notification` and `User` objects. > **Note** > -> If you are familar with Icinga 1.x - these time period definitions +> If you are familiar with Icinga 1.x - these time period definitions > are called `legacy timeperiods` in Icinga 2. > > An Icinga 2 legacy timeperiod requires the `ITL` provided template @@ -234,10 +234,10 @@ inside the `icinga2.log` file depending in your log severity ### Use Functions in Command Arguments set_if The `set_if` attribute inside the command arguments definition in the -[CheckCommand object definition](6-object-types.md#objecttype-checkcommand) is primarly used to +[CheckCommand object definition](6-object-types.md#objecttype-checkcommand) is primarily used to evaluate whether the command parameter should be set or not. -By default you can evaluate runtime macros for their existance, and if the result is not an empty +By default you can evaluate runtime macros for their existence, and if the result is not an empty string the command parameter is passed. This becomes fairly complicated when want to evaluate multiple conditions and attributes. @@ -489,7 +489,7 @@ If the freshness checks are invalid, a new check is executed defined by the ## Check Flapping The flapping algorithm used in Icinga 2 does not store the past states but -calculcates the flapping threshold from a single value based on counters and +calculates the flapping threshold from a single value based on counters and half-life values. Icinga 2 compares the value with a single flapping threshold configuration attribute named `flapping_threshold`. diff --git a/doc/7-icinga-template-library.md b/doc/7-icinga-template-library.md index 588617ac0..b3227a865 100644 --- a/doc/7-icinga-template-library.md +++ b/doc/7-icinga-template-library.md @@ -223,7 +223,7 @@ disk_local | **Optional.** Only check local filesystems. May be true disk_stat_remote_fs | **Optional.** Only check local filesystems against thresholds. Yet call stat on remote filesystems to test if they are accessible (e.g. to detect Stale NFS Handles). Myy be true or false disk_mountpoint | **Optional.** Display the mountpoint instead of the partition. May be true or false. disk_megabytes | **Optional.** Same as --units MB. May be true or false. -disk_all | **Optional.** Explicitly select all paths. This is equivalent to -R '.*'. May be true or false. +disk_all | **Optional.** Explicitly select all paths. This is equivalent to -R '.\*'. May be true or false. disk_eregi_path | **Optional.** Case insensitive regular expression for path/partition (may be repeated). disk_ereg_path | **Optional.** Regular expression for path or partition (may be repeated). disk_ignore_eregi_path | **Optional.** Regular expression to ignore selected path/partition (case insensitive) (may be repeated). @@ -510,7 +510,7 @@ Name | Description ----------------|-------------- ldap_address | **Optional.** Host name, IP Address, or unix socket (must be an absolute path). Defaults to "$address$" if the host's `address` attribute is set, "$address6$" otherwise. ldap_port | **Optional.** Port number. Defaults to 389. -ldap_attr | **Optional.** LDAP attribute to search for (default: "(objectclass=*)" +ldap_attr | **Optional.** LDAP attribute to search for (default: "(objectclass=\*)" ldap_base | **Required.** LDAP base (eg. ou=myunit,o=myorg,c=at). ldap_bind | **Optional.** LDAP bind DN (if required). ldap_pass | **Optional.** LDAP password (if required). @@ -1514,7 +1514,7 @@ snmp_authprotocol | **Optional.** SNMP version 3 authentication protocol. snmp_privpass | **Required.** SNMP version 3 priv password. No value defined as default.. snmp_warn | **Optional.** The warning threshold. snmp_crit | **Optional.** The critical threshold. -snmp_process_name | **Optional.** Name of the process (regexp). No trailing slash!. Defaults to ".*". +snmp_process_name | **Optional.** Name of the process (regexp). No trailing slash!. Defaults to ".\*". snmp_perf | **Optional.** Enable perfdata values. Defaults to true. snmp_timeout | **Optional.** The command timeout in seconds. Defaults to 5 seconds. @@ -1758,7 +1758,7 @@ ipmi_config_file | **Optional.** Path to the FreeIPMI configurat ipmi_username | **Optional.** The IPMI username. ipmi_password | **Optional.** The IPMI password. ipmi_privilege_level | **Optional.** The IPMI privilege level of the IPMI user. -ipmi_backward_compatibility_mode | **Optional.** Enable backward compatibility mode, useful for FreeIPMI 0.5.* (this omits FreeIPMI options "--quiet-cache" and "--sdr-cache-recreate"). +ipmi_backward_compatibility_mode | **Optional.** Enable backward compatibility mode, useful for FreeIPMI 0.5.\* (this omits FreeIPMI options "--quiet-cache" and "--sdr-cache-recreate"). ipmi_sensor_type | **Optional.** Limit sensors to query based on IPMI sensor type. Examples for IPMI sensor types are 'Fan', 'Temperature' and 'Voltage'. ipmi_exclude_sensor_id | **Optional.** Exclude sensor matching ipmi_sensor_id. ipmi_sensor_id | **Optional.** Include sensor matching ipmi_sensor_id. @@ -2058,8 +2058,8 @@ Name | Description mem_used | **Optional.** Tell the plugin to check for used memory in opposite of **mem_free**. Must specify one of these as true. mem_free | **Optional.** Tell the plugin to check for free memory in opposite of **mem_used**. Must specify one of these as true. mem_cache | **Optional.** If set to true plugin will count cache as free memory. Defaults to false. -mem_warning | **Required.** Specifiy the warning threshold as number interpreted as percent. -mem_critical | **Required.** Specifiy the critical threshold as number interpreted as percent. +mem_warning | **Required.** Specify the warning threshold as number interpreted as percent. +mem_critical | **Required.** Specify the critical threshold as number interpreted as percent. #### running_kernel diff --git a/doc/8-cli-commands.md b/doc/8-cli-commands.md index 0ec471bfd..e17b419cf 100644 --- a/doc/8-cli-commands.md +++ b/doc/8-cli-commands.md @@ -628,7 +628,7 @@ Or manually passing the `-C` argument: > > `# icinga2 daemon -C` -If you encouter errors during configuration validation, please make sure +If you encounter errors during configuration validation, please make sure to read the [troubleshooting](16-troubleshooting.md#troubleshooting) chapter. You can also use the [CLI command](8-cli-commands.md#cli-command-object) `icinga2 object list` diff --git a/doc/9-icinga2-api.md b/doc/9-icinga2-api.md index bbbfbf931..d8ce9211f 100644 --- a/doc/9-icinga2-api.md +++ b/doc/9-icinga2-api.md @@ -211,7 +211,7 @@ Available permissions for specific URL endpoints: events/<type> | /v1/events | No console | /v1/console | No -The required actions or types can be replaced by using a wildcard match ("*"). +The required actions or types can be replaced by using a wildcard match ("\*"). ### Parameters From d9c4e5d6b1729b999376c0959eb1145268da70da Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 20 Nov 2015 16:12:56 +0100 Subject: [PATCH 10/32] Update AUTHORS refs #10692 --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index f12b583a3..f86a9fe4a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -61,6 +61,7 @@ Reto Zeder Ricardo Bartels Sam Kottler Sebastian Chrostek +Simon Ruderich Siyalrach Anton Thomas Stephan Platz Steve McMaster From f2be32eda1449debd9fab76893687d51075e2c89 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 21 Nov 2015 04:46:13 +0100 Subject: [PATCH 11/32] Build fix for SLES 11 (with -std=c++11) fixes #10615 --- lib/config/config_parser.yy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy index 1b5e5ed09..dc83a242e 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -342,8 +342,8 @@ object: context->m_ObjectAssign.push(true); context->m_SeenAssign.push(false); context->m_SeenIgnore.push(false); - context->m_Assign.push(NULL); - context->m_Ignore.push(NULL); + context->m_Assign.push(0); + context->m_Ignore.push(0); } object_declaration identifier optional_rterm use_specifier ignore_specifier rterm_scope_require_side_effect { From d96ee6b4174ce7c3383f67daf24dd2f476819091 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 24 Nov 2015 09:20:04 +0100 Subject: [PATCH 12/32] Build fix for systems where strsignal() returns a const char * --- lib/base/process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/base/process.cpp b/lib/base/process.cpp index 37ca62935..0e2881476 100644 --- a/lib/base/process.cpp +++ b/lib/base/process.cpp @@ -748,7 +748,7 @@ bool Process::DoEvents(void) << "PID " << m_PID << " (" << PrettyPrintArguments(m_Arguments) << ") terminated with exit code " << exitcode; } else if (WIFSIGNALED(status)) { int signum = WTERMSIG(status); - char *zsigname = strsignal(signum); + const char *zsigname = strsignal(signum); String signame = Convert::ToString(signum); From c0dc4ec7d6392e199c3acbb0f5dc0f1cd2b5e1ff Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 23 Nov 2015 14:37:49 +0100 Subject: [PATCH 13/32] Fix wrong icinga2 binary in development docs fixes #10710 --- doc/21-development.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/21-development.md b/doc/21-development.md index 043948b28..906c1c135 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -116,10 +116,11 @@ the duplicate import in your `~/.gdbinit` file. ### GDB Run -Call GDB with the binary and all arguments and run it in foreground. +Call GDB with the binary (`/usr/sbin/icinga2` is a wrapper script calling +`/usr/lib64/icinga2/sbin/icinga2` since 2.4) and all arguments and run it in foreground. If VFork causes trouble disable it inside the gdb run. - # gdb --args /usr/sbin/icinga2 daemon -x debug -DUseVfork=0 + # gdb --args /usr/lib64/icinga2/sbin/icinga2 daemon -x debug -DUseVfork=0 > **Note** > From 57c5262e5b30bc3810a5d3cd86373bf29967e041 Mon Sep 17 00:00:00 2001 From: Jean Flach Date: Fri, 20 Nov 2015 13:42:13 +0100 Subject: [PATCH 14/32] Update docs An action was missing two parameters. fixes #10645 --- doc/9-icinga2-api.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/doc/9-icinga2-api.md b/doc/9-icinga2-api.md index d8ce9211f..42d4e6a71 100644 --- a/doc/9-icinga2-api.md +++ b/doc/9-icinga2-api.md @@ -829,7 +829,7 @@ Send a `POST` request to the URL endpoint `/v1/actions/add-comment`. Parameter | Type | Description ----------|--------|-------------- - author | string | **Required.** name of the author, may be empty. + author | string | **Required.** Name of the author, may be empty. comment | string | **Required.** Comment text, may be empty. In addition to these parameters a [filter](9-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`. @@ -900,13 +900,15 @@ Schedule a downtime for hosts and services. Send a `POST` request to the URL endpoint `/v1/actions/schedule-downtime`. - Parameter | Type | Description - ------------|-----------|-------------- - start\_time | timestamp | **Required.** Timestamp marking the beginning of the downtime. - end\_time | timestamp | **Required.** Timestamp marking the end of the downtime. - duration | integer | **Required.** Duration of the downtime in seconds if `fixed` is set to false. - fixed | boolean | **Optional.** Defaults to `false`. If true the downtime is `fixed` otherwise `flexible`. See [downtimes](5-advanced-topics.md#downtimes) for more information. - trigger\_name | string | **Optional.** Sets the trigger for a triggered downtime. See [downtimes](5-advanced-topics.md#downtimes) for more information on triggered downtimes. + Parameter | Type | Description + --------------|-----------|-------------- + author | string | **Required.** Name of the author. + comment | string | **Required.** Comment text. + start\_time | timestamp | **Required.** Timestamp marking the beginning of the downtime. + end\_time | timestamp | **Required.** Timestamp marking the end of the downtime. + duration | integer | **Required.** Duration of the downtime in seconds if `fixed` is set to false. + fixed | boolean | **Optional.** Defaults to `false`. If true the downtime is `fixed` otherwise `flexible`. See [downtimes](5-advanced-topics.md#downtimes) for more information. + trigger\_name | string | **Optional.** Sets the trigger for a triggered downtime. See [downtimes](5-advanced-topics.md#downtimes) for more information on triggered downtimes. In addition to these parameters a [filter](9-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`. From 6a5f3e4cbd6afe3fd762a0a0b257b23f3de90db2 Mon Sep 17 00:00:00 2001 From: Jean Flach Date: Mon, 23 Nov 2015 14:12:25 +0100 Subject: [PATCH 15/32] Fix possible crash in Icinga 2 Setup Wizard fixes #10708 --- agent/windows-setup-agent/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/windows-setup-agent/Program.cs b/agent/windows-setup-agent/Program.cs index dea5a0f28..a36af0ef9 100644 --- a/agent/windows-setup-agent/Program.cs +++ b/agent/windows-setup-agent/Program.cs @@ -23,7 +23,7 @@ namespace Icinga public static void FatalError(Form owner, string message) { - MessageBox.Show(owner, message, owner.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); + MessageBox.Show(owner, message, "Icinga 2 Setup Wizard", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); } From 33fbd6c877ddfc967832726727afb1f74a0dafbf Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 19 Nov 2015 19:38:20 +0100 Subject: [PATCH 16/32] Fix race condition in the ConfigItem class fixes #10643 --- lib/cli/daemoncommand.cpp | 15 ++- lib/cli/daemonutility.cpp | 5 +- lib/cli/daemonutility.hpp | 4 +- lib/config/CMakeLists.txt | 2 +- lib/config/activationcontext.cpp | 78 ++++++++++++++++ lib/config/activationcontext.hpp | 63 +++++++++++++ lib/config/configitem.cpp | 141 ++++++++++++++++------------- lib/config/configitem.hpp | 17 ++-- lib/remote/configobjectutility.cpp | 5 +- test/livestatus.cpp | 7 +- 10 files changed, 260 insertions(+), 77 deletions(-) create mode 100644 lib/config/activationcontext.cpp create mode 100644 lib/config/activationcontext.hpp diff --git a/lib/cli/daemoncommand.cpp b/lib/cli/daemoncommand.cpp index d938e20f6..4618bbd6b 100644 --- a/lib/cli/daemoncommand.cpp +++ b/lib/cli/daemoncommand.cpp @@ -230,7 +230,9 @@ int DaemonCommand::Run(const po::variables_map& vm, const std::vector newItems; + + if (!DaemonUtility::LoadConfigFiles(configs, newItems, Application::GetObjectsPath(), Application::GetVarsPath())) return EXIT_FAILURE; if (vm.count("validate")) { @@ -258,11 +260,20 @@ int DaemonCommand::Run(const po::variables_map& vm, const std::vector& configs, } bool DaemonUtility::LoadConfigFiles(const std::vector& configs, + std::vector& newItems, const String& objectsFile, const String& varsfile) { + ActivationScope ascope; + if (!DaemonUtility::ValidateConfigFiles(configs, objectsFile)) return false; WorkQueue upq(25000, Application::GetConcurrency()); - bool result = ConfigItem::CommitItems(upq); + bool result = ConfigItem::CommitItems(ascope.GetContext(), upq, newItems); if (!result) return false; diff --git a/lib/cli/daemonutility.hpp b/lib/cli/daemonutility.hpp index c3d8c97e9..84a98ea59 100644 --- a/lib/cli/daemonutility.hpp +++ b/lib/cli/daemonutility.hpp @@ -21,6 +21,7 @@ #define DAEMONUTILITY_H #include "cli/i2-cli.hpp" +#include "config/configitem.hpp" #include "base/string.hpp" #include @@ -34,7 +35,8 @@ class I2_CLI_API DaemonUtility { public: static bool ValidateConfigFiles(const std::vector& configs, const String& objectsFile = String()); - static bool LoadConfigFiles(const std::vector& configs, const String& objectsFile = String(), const String& varsfile = String()); + static bool LoadConfigFiles(const std::vector& configs, std::vector& newItems, + const String& objectsFile = String(), const String& varsfile = String()); }; } diff --git a/lib/config/CMakeLists.txt b/lib/config/CMakeLists.txt index 72038ff1a..dad65c19b 100644 --- a/lib/config/CMakeLists.txt +++ b/lib/config/CMakeLists.txt @@ -34,7 +34,7 @@ add_flex_bison_dependency(config_lexer config_parser) include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) set(config_SOURCES - applyrule.cpp + activationcontext.cpp applyrule.cpp configcompilercontext.cpp configcompiler.cpp configitembuilder.cpp configitem.cpp ${FLEX_config_lexer_OUTPUTS} ${BISON_config_parser_OUTPUTS} expression.cpp objectrule.cpp diff --git a/lib/config/activationcontext.cpp b/lib/config/activationcontext.cpp new file mode 100644 index 000000000..be89efdd9 --- /dev/null +++ b/lib/config/activationcontext.cpp @@ -0,0 +1,78 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2015 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 "config/activationcontext.hpp" +#include "base/exception.hpp" + +using namespace icinga; + +boost::thread_specific_ptr > ActivationContext::m_ActivationStack; + +std::stack& ActivationContext::GetActivationStack(void) +{ + std::stack *actx = m_ActivationStack.get(); + + if (!actx) { + actx = new std::stack(); + m_ActivationStack.reset(actx); + } + + return *actx; +} + +void ActivationContext::PushContext(const ActivationContext::Ptr& context) +{ + GetActivationStack().push(context); +} + +void ActivationContext::PopContext(void) +{ + ASSERT(!GetActivationStack().empty()); + GetActivationStack().pop(); +} + +ActivationContext::Ptr ActivationContext::GetCurrentContext(void) +{ + std::stack& astack = GetActivationStack(); + + if (astack.empty()) + BOOST_THROW_EXCEPTION(std::runtime_error("Objects may not be created outside of an activation context.")); + + return astack.top(); +} + +ActivationScope::ActivationScope(const ActivationContext::Ptr& context) + : m_Context(context) +{ + if (!m_Context) + m_Context = new ActivationContext(); + + ActivationContext::PushContext(m_Context); +} + +ActivationScope::~ActivationScope(void) +{ + ActivationContext::PopContext(); +} + +ActivationContext::Ptr ActivationScope::GetContext(void) const +{ + return m_Context; +} + diff --git a/lib/config/activationcontext.hpp b/lib/config/activationcontext.hpp new file mode 100644 index 000000000..b0e1b573b --- /dev/null +++ b/lib/config/activationcontext.hpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2015 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. * + ******************************************************************************/ + +#ifndef ACTIVATIONCONTEXT_H +#define ACTIVATIONCONTEXT_H + +#include "config/i2-config.hpp" +#include "base/object.hpp" +#include +#include + +namespace icinga +{ + +class I2_CONFIG_API ActivationContext : public Object +{ +public: + DECLARE_PTR_TYPEDEFS(ActivationContext); + + static ActivationContext::Ptr GetCurrentContext(void); + +private: + static void PushContext(const ActivationContext::Ptr& context); + static void PopContext(void); + + static std::stack& GetActivationStack(void); + + static boost::thread_specific_ptr > m_ActivationStack; + + friend class ActivationScope; +}; + +class I2_CONFIG_API ActivationScope +{ +public: + ActivationScope(const ActivationContext::Ptr& context = ActivationContext::Ptr()); + ~ActivationScope(void); + + ActivationContext::Ptr GetContext(void) const; + +private: + ActivationContext::Ptr m_Context; +}; + +} + +#endif /* ACTIVATIONCONTEXT_H */ diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 4bc0e6418..d6aad29c3 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -44,9 +44,8 @@ using namespace icinga; boost::mutex ConfigItem::m_Mutex; ConfigItem::TypeMap ConfigItem::m_Items; ConfigItem::ItemList ConfigItem::m_UnnamedItems; -ConfigItem::ItemList ConfigItem::m_CommittedItems; -REGISTER_SCRIPTFUNCTION(commit_objects, &ConfigItem::CommitAndActivate); +REGISTER_SCRIPTFUNCTION(__run_with_activation_context, &ConfigItem::RunWithActivationContext); /** * Constructor for the ConfigItem class. @@ -235,11 +234,6 @@ ConfigObject::Ptr ConfigItem::Commit(bool discard) throw; } - { - boost::mutex::scoped_lock lock(m_Mutex); - m_CommittedItems.push_back(this); - } - Dictionary::Ptr persistentItem = new Dictionary(); persistentItem->Set("type", GetType()); @@ -291,14 +285,15 @@ void ConfigItem::Register(void) { Type::Ptr type = Type::GetByName(m_Type); + m_ActivationContext = ActivationContext::GetCurrentContext(); + + boost::mutex::scoped_lock lock(m_Mutex); + /* If this is a non-abstract object with a composite name * we register it in m_UnnamedItems instead of m_Items. */ - if (!m_Abstract && dynamic_cast(type.get())) { - boost::mutex::scoped_lock lock(m_Mutex); + if (!m_Abstract && dynamic_cast(type.get())) m_UnnamedItems.push_back(this); - } else { - boost::mutex::scoped_lock lock(m_Mutex); - + else { ItemMap::const_iterator it = m_Items[m_Type].find(m_Name); if (it != m_Items[m_Type].end()) { @@ -324,7 +319,6 @@ void ConfigItem::Unregister(void) boost::mutex::scoped_lock lock(m_Mutex); m_UnnamedItems.erase(std::remove(m_UnnamedItems.begin(), m_UnnamedItems.end(), this), m_UnnamedItems.end()); m_Items[m_Type].erase(m_Name); - m_CommittedItems.erase(std::remove(m_CommittedItems.begin(), m_CommittedItems.end(), this), m_CommittedItems.end()); } /** @@ -351,7 +345,7 @@ ConfigItem::Ptr ConfigItem::GetByTypeAndName(const String& type, const String& n return it2->second; } -void ConfigItem::OnAllConfigLoadedWrapper(void) +void ConfigItem::OnAllConfigLoadedHelper(void) { try { m_Object->OnAllConfigLoaded(); @@ -369,7 +363,13 @@ void ConfigItem::OnAllConfigLoadedWrapper(void) } } -bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector& newItems) +void ConfigItem::CreateChildObjectsHelper(const Type::Ptr& type) +{ + ActivationScope ascope(m_ActivationContext); + m_Object->CreateChildObjects(type); +} + +bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue& upq, std::vector& newItems) { typedef std::pair ItemPair; std::vector items; @@ -379,17 +379,31 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector& ne BOOST_FOREACH(const TypeMap::value_type& kv, m_Items) { BOOST_FOREACH(const ItemMap::value_type& kv2, kv.second) { - if (!kv2.second->m_Abstract && !kv2.second->m_Object) - items.push_back(std::make_pair(kv2.second, false)); + if (kv2.second->m_Abstract || kv2.second->m_Object) + continue; + + if (kv2.second->m_ActivationContext != context) + continue; + + items.push_back(std::make_pair(kv2.second, false)); } } + ItemList newUnnamedItems; + BOOST_FOREACH(const ConfigItem::Ptr& item, m_UnnamedItems) { - if (!item->m_Abstract && !item->m_Object) - items.push_back(std::make_pair(item, true)); + if (item->m_ActivationContext != context) { + newUnnamedItems.push_back(item); + continue; + } + + if (item->m_Abstract || item->m_Object) + continue; + + items.push_back(std::make_pair(item, true)); } - m_UnnamedItems.clear(); + m_UnnamedItems.swap(newUnnamedItems); } if (items.empty()) @@ -405,13 +419,6 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector& ne if (upq.HasExceptions()) return false; - std::vector new_items; - - { - boost::mutex::scoped_lock lock(m_Mutex); - new_items.swap(m_CommittedItems); - } - std::set types; std::vector all_types; @@ -451,12 +458,14 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector& ne if (unresolved_dep) continue; - BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) { + BOOST_FOREACH(const ItemPair& ip, items) { + const ConfigItem::Ptr& item = ip.first; + if (!item->m_Object) continue; if (item->m_Type == type) - upq.Enqueue(boost::bind(&ConfigItem::OnAllConfigLoadedWrapper, item)); + upq.Enqueue(boost::bind(&ConfigItem::OnAllConfigLoadedHelper, item)); } completed_types.insert(type); @@ -467,12 +476,14 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector& ne return false; BOOST_FOREACH(const String& loadDep, ptype->GetLoadDependencies()) { - BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) { + BOOST_FOREACH(const ItemPair& ip, items) { + const ConfigItem::Ptr& item = ip.first; + if (!item->m_Object) continue; if (item->m_Type == loadDep) - upq.Enqueue(boost::bind(&ConfigObject::CreateChildObjects, item->m_Object, ptype)); + upq.Enqueue(boost::bind(&ConfigItem::CreateChildObjectsHelper, item, ptype)); } } @@ -481,7 +492,7 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector& ne if (upq.HasExceptions()) return false; - if (!CommitNewItems(upq, newItems)) + if (!CommitNewItems(context, upq, newItems)) return false; } } @@ -489,13 +500,11 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector& ne return true; } -bool ConfigItem::CommitItems(WorkQueue& upq) +bool ConfigItem::CommitItems(const ActivationContext::Ptr& context, WorkQueue& upq, std::vector& newItems) { Log(LogInformation, "ConfigItem", "Committing config items"); - std::vector newItems; - - if (!CommitNewItems(upq, newItems)) { + if (!CommitNewItems(context, upq, newItems)) { upq.ReportExceptions("config"); BOOST_FOREACH(const ConfigItem::Ptr& item, newItems) { @@ -505,6 +514,8 @@ bool ConfigItem::CommitItems(WorkQueue& upq) return false; } + ASSERT(newItems.size() > 0); + ApplyRule::CheckMatches(); /* log stats for external parsers */ @@ -525,34 +536,27 @@ bool ConfigItem::CommitItems(WorkQueue& upq) return true; } -bool ConfigItem::ActivateItems(WorkQueue& upq, bool restoreState, bool runtimeCreated) +bool ConfigItem::ActivateItems(WorkQueue& upq, const std::vector& newItems, bool runtimeCreated) { static boost::mutex mtx; boost::mutex::scoped_lock lock(mtx); - if (restoreState) { - /* restore the previous program state */ - try { - ConfigObject::RestoreObjects(Application::GetStatePath()); - } catch (const std::exception& ex) { - Log(LogCritical, "ConfigItem") - << "Failed to restore state file: " << DiagnosticInformation(ex); - } - } - Log(LogInformation, "ConfigItem", "Triggering Start signal for config items"); - BOOST_FOREACH(const ConfigType::Ptr& type, ConfigType::GetTypes()) { - BOOST_FOREACH(const ConfigObject::Ptr& object, type->GetObjects()) { - if (object->IsActive()) - continue; + BOOST_FOREACH(const ConfigItem::Ptr& item, newItems) { + if (!item->m_Object) + continue; + + ConfigObject::Ptr object = item->m_Object; + + if (object->IsActive()) + continue; #ifdef I2_DEBUG - Log(LogDebug, "ConfigItem") - << "Activating object '" << object->GetName() << "' of type '" << object->GetType()->GetName() << "'"; + Log(LogDebug, "ConfigItem") + << "Activating object '" << object->GetName() << "' of type '" << object->GetType()->GetName() << "'"; #endif /* I2_DEBUG */ - upq.Enqueue(boost::bind(&ConfigObject::Activate, object, runtimeCreated)); - } + upq.Enqueue(boost::bind(&ConfigObject::Activate, object, runtimeCreated)); } upq.Join(); @@ -563,10 +567,13 @@ bool ConfigItem::ActivateItems(WorkQueue& upq, bool restoreState, bool runtimeCr } #ifdef I2_DEBUG - BOOST_FOREACH(const ConfigType::Ptr& type, ConfigType::GetTypes()) { - BOOST_FOREACH(const ConfigObject::Ptr& object, type->GetObjects()) { - ASSERT(object->IsActive()); - } + BOOST_FOREACH(const ConfigItem::Ptr& item, newItems) { + ConfigObject::Ptr object = item->m_Object; + + if (item->m_Abstract) + continue; + + ASSERT(object && object->IsActive()); } #endif /* I2_DEBUG */ @@ -575,14 +582,22 @@ bool ConfigItem::ActivateItems(WorkQueue& upq, bool restoreState, bool runtimeCr return true; } -bool ConfigItem::CommitAndActivate(void) +bool ConfigItem::RunWithActivationContext(const Function::Ptr& function) { - WorkQueue upq(25000, Application::GetConcurrency()); + ActivationScope scope; - if (!CommitItems(upq)) + { + ScriptFrame frame; + function->Invoke(); + } + + WorkQueue upq(25000, Application::GetConcurrency()); + std::vector newItems; + + if (!CommitItems(scope.GetContext(), upq, newItems)) return false; - if (!ActivateItems(upq, false)) + if (!ActivateItems(upq, newItems)) return false; return true; diff --git a/lib/config/configitem.hpp b/lib/config/configitem.hpp index b53327e62..59df917d7 100644 --- a/lib/config/configitem.hpp +++ b/lib/config/configitem.hpp @@ -22,12 +22,14 @@ #include "config/i2-config.hpp" #include "config/expression.hpp" +#include "config/activationcontext.hpp" #include "base/configobject.hpp" #include "base/workqueue.hpp" namespace icinga { + /** * A configuration item. Non-abstract configuration items can be used to * create configuration objects at runtime. @@ -55,7 +57,6 @@ public: boost::shared_ptr GetExpression(void) const; boost::shared_ptr GetFilter(void) const; - ConfigObject::Ptr Commit(bool discard = true); void Register(void); void Unregister(void); @@ -67,10 +68,10 @@ public: static ConfigItem::Ptr GetByTypeAndName(const String& type, const String& name); - static bool CommitItems(WorkQueue& upq); - static bool ActivateItems(WorkQueue& upq, bool restoreState, bool runtimeCreated = false); + static bool CommitItems(const ActivationContext::Ptr& context, WorkQueue& upq, std::vector& newItems); + static bool ActivateItems(WorkQueue& upq, const std::vector& newItems, bool runtimeCreated = false); - static bool CommitAndActivate(void); + static bool RunWithActivationContext(const Function::Ptr& function); static std::vector GetItems(const String& type); @@ -86,6 +87,7 @@ private: Dictionary::Ptr m_Scope; /**< variable scope. */ String m_Zone; /**< The zone. */ String m_Package; + ActivationContext::Ptr m_ActivationContext; ConfigObject::Ptr m_Object; @@ -102,9 +104,12 @@ private: static ConfigItem::Ptr GetObjectUnlocked(const String& type, const String& name); - static bool CommitNewItems(WorkQueue& upq, std::vector& newItems); + ConfigObject::Ptr Commit(bool discard = true); - void OnAllConfigLoadedWrapper(void); + static bool CommitNewItems(const ActivationContext::Ptr& context, WorkQueue& upq, std::vector& newItems); + + void OnAllConfigLoadedHelper(void); + void CreateChildObjectsHelper(const Type::Ptr& type); }; } diff --git a/lib/remote/configobjectutility.cpp b/lib/remote/configobjectutility.cpp index 442c5c80a..ce1763350 100644 --- a/lib/remote/configobjectutility.cpp +++ b/lib/remote/configobjectutility.cpp @@ -121,14 +121,17 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full Expression *expr = ConfigCompiler::CompileFile(path, String(), "_api"); try { + ActivationScope ascope; + ScriptFrame frame; expr->Evaluate(frame); delete expr; expr = NULL; WorkQueue upq; + std::vector newItems; - if (!ConfigItem::CommitItems(upq) || !ConfigItem::ActivateItems(upq, false, true)) { + if (!ConfigItem::CommitItems(ascope.GetContext(), upq, newItems) || !ConfigItem::ActivateItems(upq, newItems, true)) { if (errors) { if (unlink(path.CStr()) < 0) { BOOST_THROW_EXCEPTION(posix_error() diff --git a/test/livestatus.cpp b/test/livestatus.cpp index b59876c5e..237445e41 100644 --- a/test/livestatus.cpp +++ b/test/livestatus.cpp @@ -84,11 +84,14 @@ struct GlobalConfigFixture { std::vector configs; configs.push_back(TestConfig); - DaemonUtility::LoadConfigFiles(configs, "icinga2.debug", "icinga2.vars"); + ActivationScope ascope; + std::vector newItems; + + DaemonUtility::LoadConfigFiles(configs, newItems, "icinga2.debug", "icinga2.vars"); /* ignore config errors */ WorkQueue upq; - ConfigItem::ActivateItems(upq, false); + ConfigItem::ActivateItems(upq, newItems); } ~GlobalConfigFixture() From efe014aa7ef665f76488053b321ba98db847b774 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 19 Nov 2015 20:25:10 +0100 Subject: [PATCH 17/32] Fix unit tests for livestatus refs #10643 --- test/livestatus.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/livestatus.cpp b/test/livestatus.cpp index 237445e41..18043fbc3 100644 --- a/test/livestatus.cpp +++ b/test/livestatus.cpp @@ -78,13 +78,14 @@ struct GlobalConfigFixture { Application::DeclareSysconfDir("etc"); Application::DeclareLocalStateDir("var"); + ActivationScope ascope; + Loader::LoadExtensionLibrary("icinga"); Loader::LoadExtensionLibrary("methods"); //loaded by ITL std::vector configs; configs.push_back(TestConfig); - ActivationScope ascope; std::vector newItems; DaemonUtility::LoadConfigFiles(configs, newItems, "icinga2.debug", "icinga2.vars"); From d3aae8132330e831d882b36982ee43cf8f19a383 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 23 Nov 2015 14:02:33 +0100 Subject: [PATCH 18/32] Fix crash in ConfigItem::ActivateItems refs #10643 --- lib/config/configitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index d6aad29c3..9e172d817 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -570,7 +570,7 @@ bool ConfigItem::ActivateItems(WorkQueue& upq, const std::vectorm_Object; - if (item->m_Abstract) + if (!object) continue; ASSERT(object && object->IsActive()); From 21cb5690f5b2d53aad4698af8f9366c62574eb85 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Mon, 23 Nov 2015 17:25:35 +0100 Subject: [PATCH 19/32] Fix crash in ConfigItem::ActivateItems refs #10643 --- lib/config/configitem.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 9e172d817..51d1301eb 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -313,8 +313,10 @@ void ConfigItem::Register(void) */ void ConfigItem::Unregister(void) { - if (m_Object) + if (m_Object) { m_Object->Unregister(); + m_Object.reset(); + } boost::mutex::scoped_lock lock(m_Mutex); m_UnnamedItems.erase(std::remove(m_UnnamedItems.begin(), m_UnnamedItems.end(), this), m_UnnamedItems.end()); From f79b07326cc61488cb508cf84a61be3bfde8368a Mon Sep 17 00:00:00 2001 From: Markus Waldmueller Date: Wed, 4 Nov 2015 11:50:21 +0100 Subject: [PATCH 20/32] Documentation: Fix error in Access Object Attributes at Runtime example fixes #10528 Signed-off-by: Michael Friedrich --- doc/5-advanced-topics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/5-advanced-topics.md b/doc/5-advanced-topics.md index fc08c563d..c5a09f19e 100644 --- a/doc/5-advanced-topics.md +++ b/doc/5-advanced-topics.md @@ -411,7 +411,7 @@ cluster state and output: if (up_count >= down_count) { return 0 //same up as down -> UP } else { - return 1 //something is broken + return 2 //something is broken } }} From 65018fb75b5bf7bc73dfd81b7f28d449dded0370 Mon Sep 17 00:00:00 2001 From: Jean Flach Date: Tue, 24 Nov 2015 14:32:07 +0100 Subject: [PATCH 21/32] Fix master zone name fixes #10716 --- lib/cli/nodeutility.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/cli/nodeutility.cpp b/lib/cli/nodeutility.cpp index bd77c2679..fd44710b0 100644 --- a/lib/cli/nodeutility.cpp +++ b/lib/cli/nodeutility.cpp @@ -19,6 +19,7 @@ #include "cli/nodeutility.hpp" #include "cli/clicommand.hpp" +#include "cli/variableutility.hpp" #include "base/logger.hpp" #include "base/application.hpp" #include "base/tlsutility.hpp" @@ -314,6 +315,7 @@ int NodeUtility::GenerateNodeIcingaConfig(const std::vector& endpoi my_zone->Set("__name", zonename); my_zone->Set("__type", "Zone"); my_zone->Set("parent", master_zone_name); //set the master zone as parent + my_zone->Set("// This is the local node", nodename); my_zone->Set("endpoints", my_zone_members); @@ -343,9 +345,11 @@ int NodeUtility::GenerateNodeMasterIcingaConfig(const String& nodename) my_master_zone_members->Add(nodename); - my_master_zone->Set("__name", "master"); + String zonename = VariableUtility::GetVariable("ZoneName"); + + my_master_zone->Set("__name", zonename); my_master_zone->Set("__type", "Zone"); - my_master_zone->Set("// This is the local master zone", "master"); + my_master_zone->Set("// This is the local master zone", zonename); my_master_zone->Set("endpoints", my_master_zone_members); /* store the local config */ From 93c5fc5b82b26d1a53eb5847a060135ebbcd9516 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 25 Nov 2015 17:41:03 +0100 Subject: [PATCH 22/32] Use the ZoneName and NodeName constants for 'node setup' and 'node wizard' refs #10716 --- lib/base/configwriter.cpp | 11 +++++ lib/base/configwriter.hpp | 18 ++++++++ lib/cli/nodesetupcommand.cpp | 10 ++-- lib/cli/nodeutility.cpp | 87 +++++++++-------------------------- lib/cli/nodeutility.hpp | 8 ++-- lib/cli/nodewizardcommand.cpp | 5 +- 6 files changed, 63 insertions(+), 76 deletions(-) diff --git a/lib/base/configwriter.cpp b/lib/base/configwriter.cpp index f43e68da3..19cc8c1bf 100644 --- a/lib/base/configwriter.cpp +++ b/lib/base/configwriter.cpp @@ -122,6 +122,8 @@ void ConfigWriter::EmitValue(std::ostream& fp, int indentLevel, const Value& val EmitArray(fp, indentLevel, val); else if (val.IsObjectType()) EmitScope(fp, indentLevel, val); + else if (val.IsObjectType()) + EmitIdentifier(fp, static_cast(val)->GetName(), false); else if (val.IsString()) EmitString(fp, val); else if (val.IsNumber()) @@ -260,3 +262,12 @@ const std::vector& ConfigWriter::GetKeywords(void) return keywords; } + +ConfigIdentifier::ConfigIdentifier(const String& identifier) + : m_Name(identifier) +{ } + +String ConfigIdentifier::GetName(void) const +{ + return m_Name; +} diff --git a/lib/base/configwriter.hpp b/lib/base/configwriter.hpp index f6ab2c9c2..db02735c1 100644 --- a/lib/base/configwriter.hpp +++ b/lib/base/configwriter.hpp @@ -28,6 +28,24 @@ namespace icinga { +/** + * A config identifier. + * + * @ingroup base + */ +class I2_BASE_API ConfigIdentifier : public Object +{ +public: + DECLARE_PTR_TYPEDEFS(ConfigIdentifier); + + ConfigIdentifier(const String& name); + + String GetName(void) const; + +private: + String m_Name; +}; + /** * A configuration writer. * diff --git a/lib/cli/nodesetupcommand.cpp b/lib/cli/nodesetupcommand.cpp index 90f00f1e5..2ec07859f 100644 --- a/lib/cli/nodesetupcommand.cpp +++ b/lib/cli/nodesetupcommand.cpp @@ -154,13 +154,11 @@ int NodeSetupCommand::SetupMaster(const boost::program_options::variables_map& v << "'api' feature already enabled.\n"; } - NodeUtility::GenerateNodeMasterIcingaConfig(cn); - - /* read zones.conf and update with zone + endpoint information */ + /* write zones.conf and update with zone + endpoint information */ Log(LogInformation, "cli", "Generating zone and object configuration."); - NodeUtility::GenerateNodeMasterIcingaConfig(cn); + NodeUtility::GenerateNodeMasterIcingaConfig(); /* update the ApiListener config - SetupMaster() will always enable it */ @@ -220,6 +218,7 @@ int NodeSetupCommand::SetupMaster(const boost::program_options::variables_map& v NodeUtility::CreateBackupFile(Application::GetSysconfDir() + "/icinga2/constants.conf"); NodeUtility::UpdateConstant("NodeName", cn); + NodeUtility::UpdateConstant("ZoneName", cn); String salt = RandomString(16); @@ -433,7 +432,7 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, Log(LogInformation, "cli", "Generating zone and object configuration."); - NodeUtility::GenerateNodeIcingaConfig(vm["endpoint"].as >(), cn, vm["zone"].as()); + NodeUtility::GenerateNodeIcingaConfig(vm["endpoint"].as >()); /* update constants.conf with NodeName = CN */ if (cn != Utility::GetFQDN()) { @@ -446,6 +445,7 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, NodeUtility::CreateBackupFile(Application::GetSysconfDir() + "/icinga2/constants.conf"); NodeUtility::UpdateConstant("NodeName", cn); + NodeUtility::UpdateConstant("ZoneName", vm["zone"].as()); /* tell the user to reload icinga2 */ diff --git a/lib/cli/nodeutility.cpp b/lib/cli/nodeutility.cpp index fd44710b0..2f119bd27 100644 --- a/lib/cli/nodeutility.cpp +++ b/lib/cli/nodeutility.cpp @@ -33,6 +33,7 @@ #include "base/objectlock.hpp" #include "base/console.hpp" #include "base/exception.hpp" +#include "base/configwriter.hpp" #include #include #include @@ -254,7 +255,7 @@ void NodeUtility::CollectNodes(const String& node_file, std::vector& endpoints, const String& nodename, const String& zonename) +int NodeUtility::GenerateNodeIcingaConfig(const std::vector& endpoints) { Array::Ptr my_config = new Array(); @@ -306,17 +307,16 @@ int NodeUtility::GenerateNodeIcingaConfig(const std::vector& endpoi Dictionary::Ptr my_endpoint = new Dictionary(); Dictionary::Ptr my_zone = new Dictionary(); - my_endpoint->Set("__name", nodename); + my_endpoint->Set("__name", new ConfigIdentifier("NodeName")); my_endpoint->Set("__type", "Endpoint"); Array::Ptr my_zone_members = new Array(); - my_zone_members->Add(nodename); + my_zone_members->Add(new ConfigIdentifier("NodeName")); - my_zone->Set("__name", zonename); + my_zone->Set("__name", new ConfigIdentifier("ZoneName")); my_zone->Set("__type", "Zone"); my_zone->Set("parent", master_zone_name); //set the master zone as parent - my_zone->Set("// This is the local node", nodename); my_zone->Set("endpoints", my_zone_members); /* store the local config */ @@ -331,7 +331,7 @@ int NodeUtility::GenerateNodeIcingaConfig(const std::vector& endpoi return 0; } -int NodeUtility::GenerateNodeMasterIcingaConfig(const String& nodename) +int NodeUtility::GenerateNodeMasterIcingaConfig(void) { Array::Ptr my_config = new Array(); @@ -340,16 +340,13 @@ int NodeUtility::GenerateNodeMasterIcingaConfig(const String& nodename) Dictionary::Ptr my_master_zone = new Dictionary(); Array::Ptr my_master_zone_members = new Array(); - my_master_endpoint->Set("__name", nodename); + my_master_endpoint->Set("__name", new ConfigIdentifier("NodeName")); my_master_endpoint->Set("__type", "Endpoint"); - my_master_zone_members->Add(nodename); + my_master_zone_members->Add(new ConfigIdentifier("NodeName")); - String zonename = VariableUtility::GetVariable("ZoneName"); - - my_master_zone->Set("__name", zonename); + my_master_zone->Set("__name", new ConfigIdentifier("ZoneName")); my_master_zone->Set("__type", "Zone"); - my_master_zone->Set("// This is the local master zone", zonename); my_master_zone->Set("endpoints", my_master_zone_members); /* store the local config */ @@ -364,10 +361,6 @@ int NodeUtility::GenerateNodeMasterIcingaConfig(const String& nodename) return 0; } -/* - * This is ugly and requires refactoring into a generic config writer class. - * TODO. - */ bool NodeUtility::WriteNodeConfigObjects(const String& filename, const Array::Ptr& objects) { Log(LogInformation, "cli") @@ -403,10 +396,7 @@ bool NodeUtility::WriteNodeConfigObjects(const String& filename, const Array::Pt ObjectLock olock(objects); BOOST_FOREACH(const Dictionary::Ptr& object, objects) { - String name = object->Get("__name"); - String type = object->Get("__type"); - - SerializeObject(fp, name, type, object); + SerializeObject(fp, object); } fp << std::endl; @@ -622,60 +612,29 @@ bool NodeUtility::CreateBackupFile(const String& target, bool is_private) return true; } -void NodeUtility::SerializeObject(std::ostream& fp, const String& name, const String& type, const Dictionary::Ptr& object) +void NodeUtility::SerializeObject(std::ostream& fp, const Dictionary::Ptr& object) { - fp << "object " << type << " \"" << name << "\" {\n"; + fp << "object "; + ConfigWriter::EmitIdentifier(fp, object->Get("__type"), false); + fp << " "; + ConfigWriter::EmitValue(fp, 0, object->Get("__name")); + fp << " {\n"; + ObjectLock olock(object); BOOST_FOREACH(const Dictionary::Pair& kv, object) { if (kv.first == "__type" || kv.first == "__name") continue; - fp << "\t" << kv.first << " = "; - FormatValue(fp, kv.second); - fp << "\n"; + fp << "\t"; + ConfigWriter::EmitIdentifier(fp, kv.first, true); + fp << " = "; + ConfigWriter::EmitValue(fp, 1, kv.second); + fp << ";\n"; } + fp << "}\n\n"; } -void NodeUtility::FormatValue(std::ostream& fp, const Value& val) -{ - if (val.IsObjectType()) { - FormatArray(fp, val); - return; - } - - if (val.IsString()) { - fp << "\"" << Convert::ToString(val) << "\""; - return; - } - - fp << Convert::ToString(val); -} - -void NodeUtility::FormatArray(std::ostream& fp, const Array::Ptr& arr) -{ - bool first = true; - - fp << "[ "; - - if (arr) { - ObjectLock olock(arr); - BOOST_FOREACH(const Value& value, arr) { - if (first) - first = false; - else - fp << ", "; - - FormatValue(fp, value); - } - } - - if (!first) - fp << " "; - - fp << "]"; -} - void NodeUtility::UpdateConstant(const String& name, const String& value) { String constantsFile = Application::GetSysconfDir() + "/icinga2/constants.conf"; diff --git a/lib/cli/nodeutility.hpp b/lib/cli/nodeutility.hpp index 90eab3410..aab3d820c 100644 --- a/lib/cli/nodeutility.hpp +++ b/lib/cli/nodeutility.hpp @@ -59,8 +59,8 @@ public: static void UpdateConstant(const String& name, const String& value); /* node setup helpers */ - static int GenerateNodeIcingaConfig(const std::vector& endpoints, const String& nodename, const String& zonename); - static int GenerateNodeMasterIcingaConfig(const String& nodename); + static int GenerateNodeIcingaConfig(const std::vector& endpoints); + static int GenerateNodeMasterIcingaConfig(void); /* black/whitelist */ static String GetBlackAndWhiteListPath(const String& type); @@ -79,9 +79,7 @@ private: static Dictionary::Ptr LoadNodeFile(const String& node_file); static void CollectNodes(const String& node_file, std::vector& nodes); - static void SerializeObject(std::ostream& fp, const String& name, const String& type, const Dictionary::Ptr& object); - static void FormatValue(std::ostream& fp, const Value& val); - static void FormatArray(std::ostream& fp, const Array::Ptr& arr); + static void SerializeObject(std::ostream& fp, const Dictionary::Ptr& object); }; } diff --git a/lib/cli/nodewizardcommand.cpp b/lib/cli/nodewizardcommand.cpp index f89b6e347..4e4e3c768 100644 --- a/lib/cli/nodewizardcommand.cpp +++ b/lib/cli/nodewizardcommand.cpp @@ -420,7 +420,7 @@ wizard_ticket: /* apilistener config */ Log(LogInformation, "cli", "Generating local zones.conf."); - NodeUtility::GenerateNodeIcingaConfig(endpoints, cn, local_zone); + NodeUtility::GenerateNodeIcingaConfig(endpoints); if (cn != Utility::GetFQDN()) { Log(LogWarning, "cli") @@ -471,7 +471,7 @@ wizard_ticket: else std::cout << "'api' feature already enabled.\n"; - NodeUtility::GenerateNodeMasterIcingaConfig(cn); + NodeUtility::GenerateNodeMasterIcingaConfig(); /* apilistener config */ std::cout << ConsoleColorTag(Console_Bold) << "Please specify the API bind host/port (optional):\n"; @@ -543,6 +543,7 @@ wizard_ticket: NodeUtility::CreateBackupFile(constants_file); NodeUtility::UpdateConstant("NodeName", cn); + NodeUtility::UpdateConstant("ZoneName", cn); String salt = RandomString(16); From bf97d7cc57478bed20d53c93b8b74e52eccfe240 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 25 Nov 2015 18:58:52 +0100 Subject: [PATCH 23/32] Hide the --master_zone option in --help because it's not currently implemented fixes #10720 --- lib/cli/nodesetupcommand.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/cli/nodesetupcommand.cpp b/lib/cli/nodesetupcommand.cpp index 2ec07859f..20579a7b7 100644 --- a/lib/cli/nodesetupcommand.cpp +++ b/lib/cli/nodesetupcommand.cpp @@ -58,7 +58,6 @@ void NodeSetupCommand::InitParameters(boost::program_options::options_descriptio { visibleDesc.add_options() ("zone", po::value(), "The name of the local zone") - ("master_zone", po::value(), "The name of the master zone") ("master_host", po::value(), "The name of the master host for auto-signing the csr") ("endpoint", po::value >(), "Connect to remote endpoint; syntax: cn[,host,port]") ("listen", po::value(), "Listen on host,port") @@ -68,6 +67,9 @@ void NodeSetupCommand::InitParameters(boost::program_options::options_descriptio ("accept-config", "Accept config from master") ("accept-commands", "Accept commands from master") ("master", "Use setup for a master instance"); + + hiddenDesc.add_options() + ("master_zone", po::value(), "The name of the master zone"); } std::vector NodeSetupCommand::GetArgumentSuggestions(const String& argument, const String& word) const From 05af1cba0dd302a3da55a8da7d68973eb4e9d371 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 26 Nov 2015 08:09:24 +0100 Subject: [PATCH 24/32] Use the NodeName constant in 'api setup' fixes #10641 --- lib/cli/apisetupcommand.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/cli/apisetupcommand.cpp b/lib/cli/apisetupcommand.cpp index 562a44d64..8d6aa35fe 100644 --- a/lib/cli/apisetupcommand.cpp +++ b/lib/cli/apisetupcommand.cpp @@ -19,6 +19,7 @@ #include "cli/apisetupcommand.hpp" #include "cli/apisetuputility.hpp" +#include "cli/variableutility.hpp" #include "base/logger.hpp" #include "base/console.hpp" #include @@ -55,7 +56,12 @@ int ApiSetupCommand::GetMaxArguments(void) const */ int ApiSetupCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const { - if (!ApiSetupUtility::SetupMaster(Utility::GetFQDN(), true)) + String cn = VariableUtility::GetVariable("NodeName"); + + if (cn.IsEmpty()) + cn = Utility::GetFQDN(); + + if (!ApiSetupUtility::SetupMaster(cn, true)) return 1; return 0; From c55f97a0e5ec905c6ade22fb9374c07b90dab297 Mon Sep 17 00:00:00 2001 From: Jean Flach Date: Tue, 24 Nov 2015 17:01:46 +0100 Subject: [PATCH 25/32] Update node wizard The wizard now displays basic information on the to-be-imported master certificate and asks the user for confirmation. fixes #10632 --- lib/cli/nodesetupcommand.cpp | 2 +- lib/cli/nodewizardcommand.cpp | 157 ++++++++++++++++++++++----------- lib/cli/pkirequestcommand.cpp | 3 +- lib/cli/pkisavecertcommand.cpp | 28 +++--- lib/cli/pkiutility.cpp | 89 ++++++++++++------- lib/cli/pkiutility.hpp | 9 +- 6 files changed, 186 insertions(+), 102 deletions(-) diff --git a/lib/cli/nodesetupcommand.cpp b/lib/cli/nodesetupcommand.cpp index 20579a7b7..110b29794 100644 --- a/lib/cli/nodesetupcommand.cpp +++ b/lib/cli/nodesetupcommand.cpp @@ -292,7 +292,7 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, return 1; } - String trustedcert = vm["trustedcert"].as(); + boost::shared_ptr trustedcert = GetX509Certificate(vm["trustedcert"].as()); Log(LogInformation, "cli") << "Verifying trusted certificate from file '" << trustedcert << "'."; diff --git a/lib/cli/nodewizardcommand.cpp b/lib/cli/nodewizardcommand.cpp index 4e4e3c768..a14368276 100644 --- a/lib/cli/nodewizardcommand.cpp +++ b/lib/cli/nodewizardcommand.cpp @@ -67,14 +67,16 @@ int NodeWizardCommand::GetMaxArguments(void) const * * @returns An exit status. */ -int NodeWizardCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const +int NodeWizardCommand::Run(const boost::program_options::variables_map& vm, + const std::vector& ap) const { /* * The wizard will get all information from the user, * and then call all required functions. */ - std::cout << ConsoleColorTag(Console_Bold | Console_ForegroundBlue) << "Welcome to the Icinga 2 Setup Wizard!\n" + std::cout << ConsoleColorTag(Console_Bold | Console_ForegroundBlue) + << "Welcome to the Icinga 2 Setup Wizard!\n" << "\n" << "We'll guide you through all required configuration details.\n" << "\n" @@ -101,8 +103,10 @@ int NodeWizardCommand::Run(const boost::program_options::variables_map& vm, cons bool is_node_setup = true; /* master or node setup */ - std::cout << ConsoleColorTag(Console_Bold) << "Please specify if this is a satellite setup " - << "('n' installs a master setup)" << ConsoleColorTag(Console_Normal) << " [Y/n]: "; + std::cout << ConsoleColorTag(Console_Bold) + << "Please specify if this is a satellite setup " + << "('n' installs a master setup)" << ConsoleColorTag(Console_Normal) + << " [Y/n]: "; std::getline (std::cin, answer); boost::algorithm::to_lower(answer); @@ -117,7 +121,10 @@ int NodeWizardCommand::Run(const boost::program_options::variables_map& vm, cons std::cout << "Starting the Node setup routine...\n"; /* CN */ - std::cout << ConsoleColorTag(Console_Bold) << "Please specifiy the common name (CN)" << ConsoleColorTag(Console_Normal) << " [" << Utility::GetFQDN() << "]: "; + std::cout << ConsoleColorTag(Console_Bold) + << "Please specifiy the common name (CN)" + << ConsoleColorTag(Console_Normal) + << " [" << Utility::GetFQDN() << "]: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -128,7 +135,9 @@ int NodeWizardCommand::Run(const boost::program_options::variables_map& vm, cons String cn = answer; cn = cn.Trim(); - std::cout << ConsoleColorTag(Console_Bold) << "Please specifiy the local zone name" << ConsoleColorTag(Console_Normal) << " [" << cn << "]: "; + std::cout << ConsoleColorTag(Console_Bold) + << "Please specifiy the local zone name" + << ConsoleColorTag(Console_Normal) << " [" << cn << "]: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -143,12 +152,16 @@ int NodeWizardCommand::Run(const boost::program_options::variables_map& vm, cons String endpoint_buffer; - std::cout << ConsoleColorTag(Console_Bold) << "Please specify the master endpoint(s) this node should connect to:" << ConsoleColorTag(Console_Normal) << "\n"; + std::cout << ConsoleColorTag(Console_Bold) + << "Please specify the master endpoint(s) this node should connect to:" + << ConsoleColorTag(Console_Normal) << "\n"; String master_endpoint_name; wizard_endpoint_loop_start: - std::cout << ConsoleColorTag(Console_Bold) << "Master Common Name" << ConsoleColorTag(Console_Normal) << " (CN from your master setup): "; + std::cout << ConsoleColorTag(Console_Bold) + << "Master Common Name" << ConsoleColorTag(Console_Normal) + << " (CN from your master setup): "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -161,7 +174,9 @@ wizard_endpoint_loop_start: endpoint_buffer = answer; endpoint_buffer = endpoint_buffer.Trim(); - std::cout << "Do you want to establish a connection to the master " << ConsoleColorTag(Console_Bold) << "from this node?" << ConsoleColorTag(Console_Normal) << " [Y/n]: "; + std::cout << "Do you want to establish a connection to the master " + << ConsoleColorTag(Console_Bold) << "from this node?" + << ConsoleColorTag(Console_Normal) << " [Y/n]: "; std::getline (std::cin, answer); boost::algorithm::to_lower(answer); @@ -171,8 +186,11 @@ wizard_endpoint_loop_start: Log(LogWarning, "cli", "Node to master connection setup skipped"); std::cout << "Connection setup skipped. Please configure your master to connect to this node.\n"; } else { - std::cout << ConsoleColorTag(Console_Bold) << "Please fill out the master connection information:" << ConsoleColorTag(Console_Normal) << "\n"; - std::cout << ConsoleColorTag(Console_Bold) << "Master endpoint host" << ConsoleColorTag(Console_Normal) << " (Your master's IP address or FQDN): "; + std::cout << ConsoleColorTag(Console_Bold) + << "Please fill out the master connection information:" + << ConsoleColorTag(Console_Normal) << "\n" + << ConsoleColorTag(Console_Bold) << "Master endpoint host" + << ConsoleColorTag(Console_Normal) << " (Your master's IP address or FQDN): "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -188,7 +206,9 @@ wizard_endpoint_loop_start: endpoint_buffer += "," + tmp; master_endpoint_name = tmp; //store the endpoint name for later - std::cout << ConsoleColorTag(Console_Bold) << "Master endpoint port" << ConsoleColorTag(Console_Normal) << " [5665]: "; + std::cout << ConsoleColorTag(Console_Bold) + << "Master endpoint port" << ConsoleColorTag(Console_Normal) + << " [5665]: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -203,7 +223,8 @@ wizard_endpoint_loop_start: endpoints.push_back(endpoint_buffer); - std::cout << ConsoleColorTag(Console_Bold) << "Add more master endpoints?" << ConsoleColorTag(Console_Normal) << " [y/N]: "; + std::cout << ConsoleColorTag(Console_Bold) << "Add more master endpoints?" + << ConsoleColorTag(Console_Normal) << " [y/N]: "; std::getline (std::cin, answer); boost::algorithm::to_lower(answer); @@ -213,10 +234,13 @@ wizard_endpoint_loop_start: if (choice.Contains("y")) goto wizard_endpoint_loop_start; - std::cout << ConsoleColorTag(Console_Bold) << "Please specify the master connection for CSR auto-signing" << ConsoleColorTag(Console_Normal) << " (defaults to master endpoint host):\n"; + std::cout << ConsoleColorTag(Console_Bold) + << "Please specify the master connection for CSR auto-signing" + << ConsoleColorTag(Console_Normal) << " (defaults to master endpoint host):\n"; wizard_master_host: - std::cout << ConsoleColorTag(Console_Bold) << "Host" << ConsoleColorTag(Console_Normal) << " [" << master_endpoint_name << "]: "; + std::cout << ConsoleColorTag(Console_Bold) << "Host" + << ConsoleColorTag(Console_Normal) << " [" << master_endpoint_name << "]: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -230,7 +254,8 @@ wizard_master_host: String master_host = answer; master_host = master_host.Trim(); - std::cout << ConsoleColorTag(Console_Bold) << "Port" << ConsoleColorTag(Console_Normal) << " [5665]: "; + std::cout << ConsoleColorTag(Console_Bold) << "Port" + << ConsoleColorTag(Console_Normal) << " [5665]: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -250,7 +275,9 @@ wizard_master_host: if (!Utility::SetFileOwnership(pki_path, user, group)) { Log(LogWarning, "cli") - << "Cannot set ownership for user '" << user << "' group '" << group << "' on file '" << pki_path << "'. Verify it yourself!"; + << "Cannot set ownership for user '" << user + << "' group '" << group + << "' on file '" << pki_path << "'. Verify it yourself!"; } String node_cert = pki_path + "/" + cn + ".crt"; @@ -263,40 +290,48 @@ wizard_master_host: if (PkiUtility::NewCert(cn, node_key, Empty, node_cert) > 0) { Log(LogCritical, "cli") - << "Failed to create new self-signed certificate for CN '" << cn << "'. Please try again."; + << "Failed to create new self-signed certificate for CN '" + << cn << "'. Please try again."; return 1; } /* fix permissions: root -> icinga daemon user */ if (!Utility::SetFileOwnership(node_key, user, group)) { Log(LogWarning, "cli") - << "Cannot set ownership for user '" << user << "' group '" << group << "' on file '" << node_key << "'. Verify it yourself!"; + << "Cannot set ownership for user '" << user + << "' group '" << group + << "' on file '" << node_key << "'. Verify it yourself!"; } //save-cert and store the master certificate somewhere - - Log(LogInformation, "cli", "Generating self-signed certificate:"); - Log(LogInformation, "cli") << "Fetching public certificate from master (" << master_host << ", " << master_port << "):\n"; - String trusted_cert = PkiUtility::GetPkiPath() + "/trusted-master.crt"; - - if (Utility::PathExists(trusted_cert)) - NodeUtility::CreateBackupFile(trusted_cert); - - if (PkiUtility::SaveCert(master_host, master_port, node_key, node_cert, trusted_cert) > 0) { - Log(LogCritical, "cli") - << "Failed to fetch trusted master certificate. Please try again."; + boost::shared_ptr trustedcert = PkiUtility::FetchCert(master_host, master_port); + if (!trustedcert) { + Log(LogCritical, "cli", "Peer did not present a valid certificate."); return 1; } - Log(LogInformation, "cli") - << "Stored trusted master certificate in '" << trusted_cert << "'.\n"; + std::cout << ConsoleColorTag(Console_Bold) << "Certificate information:\n" + << ConsoleColorTag(Console_Normal) << PkiUtility::GetCertificateInformation(trustedcert) + << ConsoleColorTag(Console_Bold) << "\nIs this information correct?" + << ConsoleColorTag(Console_Normal) << " [y/N]: "; + + std::getline (std::cin, answer); + boost::algorithm::to_lower(answer); + if (answer != "y") { + Log(LogWarning, "cli", "Process aborted."); + return 1; + } + + Log(LogInformation, "cli", "Received trusted master certificate.\n"); wizard_ticket: - std::cout << ConsoleColorTag(Console_Bold) << "Please specify the request ticket generated on your Icinga 2 master." << ConsoleColorTag(Console_Normal) << "\n" + std::cout << ConsoleColorTag(Console_Bold) + << "Please specify the request ticket generated on your Icinga 2 master." + << ConsoleColorTag(Console_Normal) << "\n" << " (Hint: # icinga2 pki ticket --cn '" << cn << "'): "; std::getline(std::cin, answer); @@ -309,7 +344,7 @@ wizard_ticket: ticket = ticket.Trim(); Log(LogInformation, "cli") - << "Processing self-signed certificate request. Ticket '" << ticket << "'.\n"; + << "Requesting certificate with ticket '" << ticket << "'.\n"; String target_ca = pki_path + "/ca.crt"; @@ -318,9 +353,11 @@ wizard_ticket: if (Utility::PathExists(node_cert)) NodeUtility::CreateBackupFile(node_cert); - if (PkiUtility::RequestCertificate(master_host, master_port, node_key, node_cert, target_ca, trusted_cert, ticket) > 0) { + if (PkiUtility::RequestCertificate(master_host, master_port, node_key, + node_cert, target_ca, trustedcert, ticket) > 0) { Log(LogCritical, "cli") - << "Failed to fetch signed certificate from master '" << master_host << ", " + << "Failed to fetch signed certificate from master '" + << master_host << ", " << master_port <<"'. Please try again."; goto wizard_ticket; } @@ -328,12 +365,17 @@ wizard_ticket: /* fix permissions (again) when updating the signed certificate */ if (!Utility::SetFileOwnership(node_cert, user, group)) { Log(LogWarning, "cli") - << "Cannot set ownership for user '" << user << "' group '" << group << "' on file '" << node_cert << "'. Verify it yourself!"; + << "Cannot set ownership for user '" << user + << "' group '" << group << "' on file '" + << node_cert << "'. Verify it yourself!"; } /* apilistener config */ - std::cout << ConsoleColorTag(Console_Bold) << "Please specify the API bind host/port" << ConsoleColorTag(Console_Normal) << " (optional):\n"; - std::cout << ConsoleColorTag(Console_Bold) << "Bind Host" << ConsoleColorTag(Console_Normal) << " []: "; + std::cout << ConsoleColorTag(Console_Bold) + << "Please specify the API bind host/port" + << ConsoleColorTag(Console_Normal) << " (optional):\n" + << ConsoleColorTag(Console_Bold) << "Bind Host" + << ConsoleColorTag(Console_Normal) << " []: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -349,14 +391,18 @@ wizard_ticket: String bind_port = answer; bind_port = bind_port.Trim(); - std::cout << ConsoleColorTag(Console_Bold) << "Accept config from master?" << ConsoleColorTag(Console_Normal) << " [y/N]: "; + std::cout << ConsoleColorTag(Console_Bold) + << "Accept config from master?" << ConsoleColorTag(Console_Normal) + << " [y/N]: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); choice = answer; String accept_config = choice.Contains("y") ? "true" : "false"; - std::cout << ConsoleColorTag(Console_Bold) << "Accept commands from master?" << ConsoleColorTag(Console_Normal) << " [y/N]: "; + std::cout << ConsoleColorTag(Console_Bold) + << "Accept commands from master?" << ConsoleColorTag(Console_Normal) + << " [y/N]: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); choice = answer; @@ -424,7 +470,8 @@ wizard_ticket: if (cn != Utility::GetFQDN()) { Log(LogWarning, "cli") - << "CN '" << cn << "' does not match the default FQDN '" << Utility::GetFQDN() << "'. Requires update for NodeName constant in constants.conf!"; + << "CN '" << cn << "' does not match the default FQDN '" + << Utility::GetFQDN() << "'. Requires update for NodeName constant in constants.conf!"; } Log(LogInformation, "cli", "Updating constants.conf."); @@ -440,7 +487,9 @@ wizard_ticket: std::cout << ConsoleColorTag(Console_Bold) << "Starting the Master setup routine...\n"; /* CN */ - std::cout << ConsoleColorTag(Console_Bold) << "Please specifiy the common name" << ConsoleColorTag(Console_Normal) << " (CN) [" << Utility::GetFQDN() << "]: "; + std::cout << ConsoleColorTag(Console_Bold) + << "Please specifiy the common name" << ConsoleColorTag(Console_Normal) + << " (CN) [" << Utility::GetFQDN() << "]: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -454,16 +503,20 @@ wizard_ticket: /* check whether the user wants to generate a new certificate or not */ String existing_path = PkiUtility::GetPkiPath() + "/" + cn + ".crt"; - std::cout << ConsoleColorTag(Console_Normal) << "Checking for existing certificates for common name '" << cn << "'...\n"; + std::cout << ConsoleColorTag(Console_Normal) + << "Checking for existing certificates for common name '" << cn << "'...\n"; if (Utility::PathExists(existing_path)) { - std::cout << "Certificate '" << existing_path << "' for CN '" << cn << "' already existing. Skipping certificate generation.\n"; + std::cout << "Certificate '" << existing_path << "' for CN '" + << cn << "' already existing. Skipping certificate generation.\n"; } else { std::cout << "Certificates not yet generated. Running 'api setup' now.\n"; ApiSetupUtility::SetupMasterCertificates(cn); } - std::cout << ConsoleColorTag(Console_Bold) << "Generating master configuration for Icinga 2.\n" << ConsoleColorTag(Console_Normal); + std::cout << ConsoleColorTag(Console_Bold) + << "Generating master configuration for Icinga 2.\n" + << ConsoleColorTag(Console_Normal); ApiSetupUtility::SetupMasterApiUser(); if (!FeatureUtility::CheckFeatureEnabled("api")) @@ -474,8 +527,10 @@ wizard_ticket: NodeUtility::GenerateNodeMasterIcingaConfig(); /* apilistener config */ - std::cout << ConsoleColorTag(Console_Bold) << "Please specify the API bind host/port (optional):\n"; - std::cout << ConsoleColorTag(Console_Bold) << "Bind Host" << ConsoleColorTag(Console_Normal) << " []: "; + std::cout << ConsoleColorTag(Console_Bold) + << "Please specify the API bind host/port (optional):\n"; + std::cout << ConsoleColorTag(Console_Bold) + << "Bind Host" << ConsoleColorTag(Console_Normal) << " []: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -483,7 +538,8 @@ wizard_ticket: String bind_host = answer; bind_host = bind_host.Trim(); - std::cout << ConsoleColorTag(Console_Bold) << "Bind Port" << ConsoleColorTag(Console_Normal) << " []: "; + std::cout << ConsoleColorTag(Console_Bold) + << "Bind Port" << ConsoleColorTag(Console_Normal) << " []: "; std::getline(std::cin, answer); boost::algorithm::to_lower(answer); @@ -533,7 +589,8 @@ wizard_ticket: /* update constants.conf with NodeName = CN + TicketSalt = random value */ if (cn != Utility::GetFQDN()) { Log(LogWarning, "cli") - << "CN '" << cn << "' does not match the default FQDN '" << Utility::GetFQDN() << "'. Requires update for NodeName constant in constants.conf!"; + << "CN '" << cn << "' does not match the default FQDN '" + << Utility::GetFQDN() << "'. Requires update for NodeName constant in constants.conf!"; } Log(LogInformation, "cli", "Updating constants.conf."); diff --git a/lib/cli/pkirequestcommand.cpp b/lib/cli/pkirequestcommand.cpp index cbb842e35..8b7c32547 100644 --- a/lib/cli/pkirequestcommand.cpp +++ b/lib/cli/pkirequestcommand.cpp @@ -20,6 +20,7 @@ #include "cli/pkirequestcommand.hpp" #include "cli/pkiutility.hpp" #include "base/logger.hpp" +#include "base/tlsutility.hpp" #include using namespace icinga; @@ -105,6 +106,6 @@ int PKIRequestCommand::Run(const boost::program_options::variables_map& vm, cons port = vm["port"].as(); return PkiUtility::RequestCertificate(vm["host"].as(), port, vm["key"].as(), - vm["cert"].as(), vm["ca"].as(), vm["trustedcert"].as(), + vm["cert"].as(), vm["ca"].as(), GetX509Certificate(vm["trustedcert"].as()), vm["ticket"].as()); } diff --git a/lib/cli/pkisavecertcommand.cpp b/lib/cli/pkisavecertcommand.cpp index e50a7bc92..96a811545 100644 --- a/lib/cli/pkisavecertcommand.cpp +++ b/lib/cli/pkisavecertcommand.cpp @@ -20,6 +20,7 @@ #include "cli/pkisavecertcommand.hpp" #include "cli/pkiutility.hpp" #include "base/logger.hpp" +#include "base/tlsutility.hpp" using namespace icinga; namespace po = boost::program_options; @@ -40,11 +41,11 @@ void PKISaveCertCommand::InitParameters(boost::program_options::options_descript boost::program_options::options_description& hiddenDesc) const { visibleDesc.add_options() - ("key", po::value(), "Key file path (input)") - ("cert", po::value(), "Certificate file path (input)") + ("key", po::value(), "Key file path (input), obsolete") + ("cert", po::value(), "Certificate file path (input), obsolete") ("trustedcert", po::value(), "Trusted certificate file path (output)") ("host", po::value(), "Icinga 2 host") - ("port", po::value(), "Icinga 2 port"); + ("port", po::value()->default_value("5665"), "Icinga 2 port"); } std::vector PKISaveCertCommand::GetArgumentSuggestions(const String& argument, const String& word) const @@ -71,25 +72,18 @@ int PKISaveCertCommand::Run(const boost::program_options::variables_map& vm, con return 1; } - if (!vm.count("key")) { - Log(LogCritical, "cli", "Key input file path (--key) must be specified."); - return 1; - } - - if (!vm.count("cert")) { - Log(LogCritical, "cli", "Certificate input file path (--cert) must be specified."); - return 1; - } - if (!vm.count("trustedcert")) { Log(LogCritical, "cli", "Trusted certificate output file path (--trustedcert) must be specified."); return 1; } - String port = "5665"; + boost::shared_ptr cert = + PkiUtility::FetchCert(vm["host"].as(), vm["port"].as()); - if (vm.count("port")) - port = vm["port"].as(); + if (!cert) { + Log(LogCritical, "cli", "Failed to fetch certificate from host"); + return 1; + } - return PkiUtility::SaveCert(vm["host"].as(), port, vm["key"].as(), vm["cert"].as(), vm["trustedcert"].as()); + return PkiUtility::WriteCert(cert, vm["trustedcert"].as()); } diff --git a/lib/cli/pkiutility.cpp b/lib/cli/pkiutility.cpp index 6f0faab80..b1003665d 100644 --- a/lib/cli/pkiutility.cpp +++ b/lib/cli/pkiutility.cpp @@ -22,6 +22,7 @@ #include "base/logger.hpp" #include "base/application.hpp" #include "base/tlsutility.hpp" +#include "base/console.hpp" #include "base/tlsstream.hpp" #include "base/tcpsocket.hpp" #include "base/json.hpp" @@ -110,30 +111,30 @@ int PkiUtility::SignCsr(const String& csrfile, const String& certfile) return 0; } -int PkiUtility::SaveCert(const String& host, const String& port, const String& keyfile, const String& certfile, const String& trustedfile) +boost::shared_ptr PkiUtility::FetchCert(const String& host, const String& port) { TcpSocket::Ptr client = new TcpSocket(); try { client->Connect(host, port); } catch (const std::exception& ex) { - Log(LogCritical, "cli") + Log(LogCritical, "pki") << "Cannot connect to host '" << host << "' on port '" << port << "'"; - Log(LogDebug, "cli") + Log(LogDebug, "pki") << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex); - return 1; + return NULL; } boost::shared_ptr sslContext; try { - sslContext = MakeSSLContext(certfile, keyfile); + sslContext = MakeSSLContext(); } catch (const std::exception& ex) { - Log(LogCritical, "cli") - << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "'."; - Log(LogDebug, "cli") - << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "':\n" << DiagnosticInformation(ex); - return 1; + Log(LogCritical, "pki") + << "Cannot make SSL context."; + Log(LogDebug, "pki") + << "Cannot make SSL context:\n" << DiagnosticInformation(ex); + return NULL; } TlsStream::Ptr stream = new TlsStream(client, String(), RoleClient, sslContext); @@ -144,25 +145,23 @@ int PkiUtility::SaveCert(const String& host, const String& port, const String& k } - boost::shared_ptr cert = stream->GetPeerCertificate(); - - if (!cert) { - Log(LogCritical, "cli", "Peer did not present a valid certificate."); - return 1; - } + return stream->GetPeerCertificate(); +} +int PkiUtility::WriteCert(const boost::shared_ptr& cert, const String& trustedfile) +{ std::ofstream fpcert; fpcert.open(trustedfile.CStr()); fpcert << CertificateToString(cert); fpcert.close(); if (fpcert.fail()) { - Log(LogCritical, "cli") + Log(LogCritical, "pki") << "Could not write certificate to file '" << trustedfile << "'."; return 1; } - Log(LogInformation, "cli") + Log(LogInformation, "pki") << "Writing trusted certificate to file '" << trustedfile << "'."; return 0; @@ -176,7 +175,7 @@ int PkiUtility::GenTicket(const String& cn, const String& salt, std::ostream& ti } int PkiUtility::RequestCertificate(const String& host, const String& port, const String& keyfile, - const String& certfile, const String& cafile, const String& trustedfile, const String& ticket) + const String& certfile, const String& cafile, const boost::shared_ptr& trustedCert, const String& ticket) { TcpSocket::Ptr client = new TcpSocket(); @@ -213,17 +212,7 @@ int PkiUtility::RequestCertificate(const String& host, const String& port, const boost::shared_ptr peerCert = stream->GetPeerCertificate(); - boost::shared_ptr trustedCert; - - try { - trustedCert = GetX509Certificate(trustedfile); - } catch (const std::exception&) { - Log(LogCritical, "cli") - << "Cannot get trusted from cert path: '" << trustedfile << "'."; - return 1; - } - - if (CertificateToString(peerCert) != CertificateToString(trustedCert)) { + if (X509_cmp(peerCert.get(), trustedCert.get())) { Log(LogCritical, "cli", "Peer certificate does not match trusted certificate."); return 1; } @@ -312,3 +301,43 @@ int PkiUtility::RequestCertificate(const String& host, const String& port, const return 0; } + +String PkiUtility::GetCertificateInformation(const boost::shared_ptr& cert) { + BIO *out = BIO_new(BIO_s_mem()); + String pre; + + pre = "\n Subject: "; + BIO_write(out, pre.CStr(), pre.GetLength()); + X509_NAME_print_ex(out, X509_get_subject_name(cert.get()), 0, XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB); + + pre = "\n Issuer: "; + BIO_write(out, pre.CStr(), pre.GetLength()); + X509_NAME_print_ex(out, X509_get_issuer_name(cert.get()), 0, XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB); + + pre = "\n Valid From: "; + BIO_write(out, pre.CStr(), pre.GetLength()); + ASN1_TIME_print(out, X509_get_notBefore(cert)); + + pre = "\n Valid Until: "; + BIO_write(out, pre.CStr(), pre.GetLength()); + ASN1_TIME_print(out, X509_get_notAfter(cert)); + + pre = "\n Fingerprint: "; + BIO_write(out, pre.CStr(), pre.GetLength()); + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int diglen; + X509_digest(cert.get(), EVP_sha1(), md, &diglen); + + char *data; + long length = BIO_get_mem_data(out, &data); + + std::stringstream info; + info << String(data, data + length); + for (unsigned int i = 0; i < diglen; i++) { + info << std::setfill('0') << std::setw(2) << std::uppercase + << std::hex << static_cast(md[i]) << ' '; + } + info << '\n'; + + return info.str(); +} diff --git a/lib/cli/pkiutility.hpp b/lib/cli/pkiutility.hpp index cfa2230e8..323066bce 100644 --- a/lib/cli/pkiutility.hpp +++ b/lib/cli/pkiutility.hpp @@ -24,6 +24,7 @@ #include "cli/i2-cli.hpp" #include "base/dictionary.hpp" #include "base/string.hpp" +#include namespace icinga { @@ -40,15 +41,17 @@ public: static int NewCa(void); static int NewCert(const String& cn, const String& keyfile, const String& csrfile, const String& certfile); static int SignCsr(const String& csrfile, const String& certfile); - static int SaveCert(const String& host, const String& port, const String& keyfile, const String& certfile, const String& trustedfile); + static boost::shared_ptr FetchCert(const String& host, const String& port); + static int WriteCert(const boost::shared_ptr& cert, const String& trustedfile); static int GenTicket(const String& cn, const String& salt, std::ostream& ticketfp); static int RequestCertificate(const String& host, const String& port, const String& keyfile, - const String& certfile, const String& cafile, const String& trustedfile, const String& ticket); + const String& certfile, const String& cafile, const boost::shared_ptr& trustedcert, + const String& ticket); + static String GetCertificateInformation(const boost::shared_ptr& certificate); private: PkiUtility(void); - }; } From 7c2553146661294b78606e49b8b3920156b9aa48 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Thu, 26 Nov 2015 10:33:13 +0100 Subject: [PATCH 26/32] Add a note for different binary locations to development docs refs #10710 --- doc/21-development.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/21-development.md b/doc/21-development.md index 906c1c135..62f3ba3e6 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -122,6 +122,10 @@ If VFork causes trouble disable it inside the gdb run. # gdb --args /usr/lib64/icinga2/sbin/icinga2 daemon -x debug -DUseVfork=0 +The exact path to the Icinga 2 binary differs on each distribution. On Ubuntu +it is installed into `/usr/lib/x86_64-linux-gnu/icinga2/sbin/icinga2` on 64-bit systems +for example. + > **Note** > > If gdb tells you it's missing debug symbols, quit gdb and install From c983fdea316a8e42d84edbae52abd6dce2641813 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Thu, 26 Nov 2015 10:34:35 +0100 Subject: [PATCH 27/32] Update AUTHORS refs #10528 --- .mailmap | 1 + AUTHORS | 1 + 2 files changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index e9f2417c1..6c6b3f583 100644 --- a/.mailmap +++ b/.mailmap @@ -6,3 +6,4 @@ Gunnar Beutner Jean-Marcel Flach Dolf Schimmel +Markus Waldmüller diff --git a/AUTHORS b/AUTHORS index f86a9fe4a..08e1d887e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -47,6 +47,7 @@ Malte Rabenseifner Marcus van Dam Marius Sturm Markus Frosch +Markus Waldmüller Martin Stiborsky Matthaus Owens Max Zhang From b14a48d519ce1c89c2261b67c033f5a0a19fa329 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sun, 22 Nov 2015 12:36:50 +0100 Subject: [PATCH 28/32] Implement Platform* global variables refs #10693 --- doc/18-language-reference.md | 6 +- icinga-app/icinga.cpp | 6 + lib/base/application.cpp | 125 +---------------- lib/base/utility.cpp | 254 ++++++++++++++++++++++++++++++++++- lib/base/utility.hpp | 6 + 5 files changed, 273 insertions(+), 124 deletions(-) diff --git a/doc/18-language-reference.md b/doc/18-language-reference.md index 43e1f520d..7a2f2cde6 100644 --- a/doc/18-language-reference.md +++ b/doc/18-language-reference.md @@ -371,7 +371,11 @@ NodeName |**Read-write.** Contains the cluster node name. Set to the UseVfork |**Read-write.** Whether to use vfork(). Only available on *NIX. Defaults to true. AttachDebugger |**Read-write.** Whether to attach a debugger when Icinga 2 crashes. Defaults to false. RunAsUser |**Read-write.** Defines the user the Icinga 2 daemon is running as. Used in the `init.conf` configuration file. -RunAsGroup |**Read-write.** Defines the group the Icinga 2 daemon is running as. Used in the `init.conf` configuration file. +RunAsGroup |**Read-write.** Defines the group the Icinga 2 daemon is running as. Used in the `init.conf` configuration file. +PlatformName |**Read-only.** The name of the operating system, e.g. "Ubuntu". +PlatformVersion |**Read-only.** The version of the operating system, e.g. "14.04.3 LTS". +PlatformKernel |**Read-only.** The name of the operating system kernel, e.g. "Linux". +PlatformKernelVersion|**Read-only.** The version of the operating system kernel, e.g. "3.13.0-63-generic". ## Apply diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 2b154d1ce..b6bfb31b8 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -176,6 +176,12 @@ int Main(void) ScriptGlobal::Set("AttachDebugger", false); + ScriptGlobal::Set("PlatformKernel", Utility::GetPlatformKernel()); + ScriptGlobal::Set("PlatformKernelVersion", Utility::GetPlatformKernelVersion()); + ScriptGlobal::Set("PlatformName", Utility::GetPlatformName()); + ScriptGlobal::Set("PlatformVersion", Utility::GetPlatformVersion()); + ScriptGlobal::Set("PlatformArchitecture", Utility::GetPlatformArchitecture()); + LogSeverity logLevel = Logger::GetConsoleLogSeverity(); Logger::SetConsoleLogSeverity(LogWarning); diff --git a/lib/base/application.cpp b/lib/base/application.cpp index 1000c1a67..e5e9caed6 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -44,9 +44,6 @@ #ifdef __linux__ #include #endif /* __linux__ */ -#ifdef _WIN32 -#include -#endif /*_WIN32*/ using namespace icinga; @@ -483,107 +480,6 @@ String Application::GetExePath(const String& argv0) #endif /* _WIN32 */ } -#ifndef _WIN32 -static String UnameHelper(char type) -{ - /* Unfortunately the uname() system call doesn't support some of the - * query types we're interested in - so we're using popen() instead. */ - - char cmd[] = "uname -X 2>&1"; - cmd[7] = type; - - FILE *fp = popen(cmd, "r"); - - char line[1024]; - std::ostringstream msgbuf; - - while (fgets(line, sizeof(line), fp) != NULL) - msgbuf << line; - - pclose(fp); - - String result = msgbuf.str(); - - return result.Trim(); -} - -int ReleaseHelper(std::string &result) -{ - /* You are useing *some* distribution */ - FILE *fp = popen("lsb_release -s -d 2>&1", "r"); - std::ostringstream msgbuf; - - if (fp != NULL) { - char line[1024]; - while (fgets(line, sizeof(line), fp) != NULL) - msgbuf << line; - int status = pclose(fp); - if (WEXITSTATUS(status) == 0) { - result = msgbuf.str(); - boost::trim(result); - return result.length(); - } - } - - /* You have systemd or Ubuntu etc. */ - std::ifstream release("/etc/os-release"); - std::string release_line; - if (release.is_open()) { - while (getline(release, release_line)) { - if (release_line.find("PRETTY_NAME") != std::string::npos) { - result = release_line.substr(13, release_line.length() - 14); - return result.length(); - } - } - } - - /* Centos < 7 */ - release.close(); - release.open("/etc/redhat-release"); - if (release.is_open()) { - getline(release, release_line); - result = release_line; - return result.length(); - } - - /* sles 11 sp3, opensuse w/e */ - release.close(); - release.open("etc/SuSE-release"); - if (release.is_open()) { - getline(release, release_line); - result = release_line; - return result.length(); - } - - /* Just give up */ - return 0; -} - -#else -static String WindowsVersionHelper() -{ - //Minimum required Version, the installer/user is in the responsibility to take care of that - String winver = "Windows Vista"; - if (IsWindowsVistaSP1OrGreater()) - winver = "Windows Vista SP1"; - if (IsWindowsVistaSP2OrGreater()) - winver = "Windows Vista SP2"; - if (IsWindows7OrGreater()) - winver = "Windows 7"; - if (IsWindows7SP1OrGreater()) - winver = "Windows 7 SP1"; - if (IsWindows8OrGreater()) - winver = "Windows 8"; - if (IsWindows8Point1OrGreater()) - winver = "Windows 8.1 or greater"; - if (IsWindowsServer()) - winver += " (Server)"; - - return winver; -} - -#endif /* _WIN32 */ - /** * Display version and path information. */ @@ -605,24 +501,13 @@ void Application::DisplayInfoMessage(std::ostream& os, bool skipVersion) << " Vars path: " << GetVarsPath() << "\n" << " PID path: " << GetPidPath() << "\n"; -#ifndef _WIN32 os << "\n" << "System information:" << "\n" - << " Operating system: " << UnameHelper('s') << "\n" - << " Operating system version: " << UnameHelper('r') << "\n" - << " Architecture: " << UnameHelper('m') << "\n"; -#else - os << "\n" - << "System information:\n" - << " Operating system: Windows\n" - << " Operating system version: " << WindowsVersionHelper() << "\n"; -#endif /* _WIN32 */ - -#ifdef __linux__ - std::string release; - if (ReleaseHelper(release)) - os << " Distribution: " << release << "\n"; -#endif /* __linux__ */ + << " Platform: " << Utility::GetPlatformName() << "\n" + << " Platform version: " << Utility::GetPlatformVersion() << "\n" + << " Kernel: " << Utility::GetPlatformKernel() << "\n" + << " Kernel version: " << Utility::GetPlatformKernelVersion() << "\n" + << " Architecture: " << Utility::GetPlatformArchitecture() << "\n"; } /** diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index 2a88a44be..32ea82022 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -46,11 +46,14 @@ #endif /* HAVE_CXXABI_H */ #ifndef _WIN32 -# include -# include -# include +# include +# include +# include #endif /* _WIN32 */ +#ifdef _WIN32 +# include +#endif /*_WIN32*/ using namespace icinga; @@ -1405,3 +1408,248 @@ String Utility::UnescapeString(const String& s) return result.str(); } + +#ifndef _WIN32 +static String UnameHelper(char type) +{ + /* Unfortunately the uname() system call doesn't support some of the + * query types we're interested in - so we're using popen() instead. */ + + char cmd[] = "uname -X 2>&1"; + cmd[7] = type; + + FILE *fp = popen(cmd, "r"); + + char line[1024]; + std::ostringstream msgbuf; + + while (fgets(line, sizeof(line), fp) != NULL) + msgbuf << line; + + pclose(fp); + + String result = msgbuf.str(); + + return result.Trim(); +} +#endif /* _WIN32 */ +static bool ReleaseHelper(String *platformName, String *platformVersion) +{ +#ifdef _WIN32 + if (platformName) + *platformName = "Windows"; + + if (platformVersion) { + String *platformVersion = "Vista"; + if (IsWindowsVistaSP1OrGreater()) + *platformVersion = "Vista SP1"; + if (IsWindowsVistaSP2OrGreater()) + *platformVersion = "Vista SP2"; + if (IsWindows7OrGreater()) + *platformVersion = "7"; + if (IsWindows7SP1OrGreater()) + *platformVersion = "7 SP1"; + if (IsWindows8OrGreater()) + *platformVersion = "8"; + if (IsWindows8Point1OrGreater()) + *platformVersion = "8.1 or greater"; + if (IsWindowsServer()) + *platformVersion += " (Server)"; + } + + return true; +#else /* _WIN32 */ + if (platformName) + *platformName = "Unknown"; + + if (platformVersion) + *platformVersion = "Unknown"; + + /* You are using a distribution which supports LSB. */ + FILE *fp = popen("lsb_release -s -i 2>&1", "r"); + + if (fp != NULL) { + std::ostringstream msgbuf; + char line[1024]; + while (fgets(line, sizeof(line), fp) != NULL) + msgbuf << line; + int status = pclose(fp); + if (WEXITSTATUS(status) == 0) { + if (platformName) + *platformName = msgbuf.str(); + } + } + + fp = popen("lsb_release -s -r 2>&1", "r"); + + if (fp != NULL) { + std::ostringstream msgbuf; + char line[1024]; + while (fgets(line, sizeof(line), fp) != NULL) + msgbuf << line; + int status = pclose(fp); + if (WEXITSTATUS(status) == 0) { + if (platformVersion) + *platformVersion = msgbuf.str(); + } + } + + /* OS X */ + fp = popen("sw_vers -productName 2>&1", "r"); + + if (fp != NULL) { + std::ostringstream msgbuf; + char line[1024]; + while (fgets(line, sizeof(line), fp) != NULL) + msgbuf << line; + int status = pclose(fp); + if (WEXITSTATUS(status) == 0) { + String info = msgbuf.str(); + info = info.Trim(); + + if (platformName) + *platformName = info; + } + } + + fp = popen("sw_vers -productVersion 2>&1", "r"); + + if (fp != NULL) { + std::ostringstream msgbuf; + char line[1024]; + while (fgets(line, sizeof(line), fp) != NULL) + msgbuf << line; + int status = pclose(fp); + if (WEXITSTATUS(status) == 0) { + String info = msgbuf.str(); + info = info.Trim(); + + if (platformVersion) + *platformVersion = info; + + return true; + } + } + + /* You have systemd or Ubuntu etc. */ + std::ifstream release("/etc/os-release"); + if (release.is_open()) { + std::string release_line; + while (getline(release, release_line)) { + if (platformName) { + if (release_line.find("NAME") != std::string::npos) { + *platformName = release_line.substr(6, release_line.length() - 7); + } + } + + if (platformVersion) { + if (release_line.find("VERSION") != std::string::npos) { + *platformVersion = release_line.substr(8, release_line.length() - 9); + } + } + } + + return true; + } + + /* Centos < 7 */ + release.close(); + release.open("/etc/redhat-release"); + if (release.is_open()) { + std::string release_line; + getline(release, release_line); + + String info = release_line; + + if (platformName) + *platformName = info.SubStr(0, info.FindFirstOf(" ")); + + if (platformVersion) + *platformVersion = info.SubStr(info.FindFirstOf(" ") + 1); + + return true; + } + + /* sles 11 sp3, opensuse w/e */ + release.close(); + release.open("/etc/SuSE-release"); + if (release.is_open()) { + std::string release_line; + getline(release, release_line); + + String info = release_line; + + if (platformName) + *platformName = info.SubStr(0, info.FindFirstOf(" ")); + + if (platformVersion) + *platformVersion = info.SubStr(info.FindFirstOf(" ") + 1); + + return true; + } + + /* Just give up */ + return false; +#endif /* _WIN32 */ +} + +String Utility::GetPlatformKernel(void) +{ +#ifdef _WIN32 + return "Windows"; +#else /* _WIN32 */ + return UnameHelper('s'); +#endif /* _WIN32 */ +} + +String Utility::GetPlatformKernelVersion(void) +{ +#ifdef _WIN32 + OSVERSIONINFO info; + info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&info); + + std::ostringstream msgbuf; + msgbuf << info.dwMajorVersion << "." << info.dwMinorVersion; + + return msgbuf.str(); +#else /* _WIN32 */ + return UnameHelper('r'); +#endif /* _WIN32 */ +} + +String Utility::GetPlatformName(void) +{ + String platformName; + if (!ReleaseHelper(&platformName, NULL)) + return "Unknown"; + return platformName; +} + +String Utility::GetPlatformVersion(void) +{ + String platformVersion; + if (!ReleaseHelper(NULL, &platformVersion)) + return "Unknown"; + return platformVersion; +} + +String Utility::GetPlatformArchitecture(void) +{ +#ifdef _WIN32 + SYSTEM_INFO info; + GetNativeSystemInfo(&info); + switch (info.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_AMD64: + return "x86_64"; + case PROCESSOR_ARCHITECTURE_ARM: + return "arm"; + case PROCESSOR_ARCHITECTURE_INTEL: + return "x86"; + default: + return "unknown"; + } +#else /* _WIN32 */ + return UnameHelper('m'); +#endif /* _WIN32 */ +} diff --git a/lib/base/utility.hpp b/lib/base/utility.hpp index 0dbfc6e60..3a44c176b 100644 --- a/lib/base/utility.hpp +++ b/lib/base/utility.hpp @@ -133,6 +133,12 @@ public: static Value LoadJsonFile(const String& path); static void SaveJsonFile(const String& path, const Value& value); + static String GetPlatformKernel(void); + static String GetPlatformKernelVersion(void); + static String GetPlatformName(void); + static String GetPlatformVersion(void); + static String GetPlatformArchitecture(void); + private: Utility(void); static void CollectPaths(const String& path, std::vector& paths); From 330e8db486101b3759abcc8450284434b0292fe0 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Mon, 23 Nov 2015 13:26:42 +0100 Subject: [PATCH 29/32] Add running_kernel_use_sudo option for the running_kernel check fixes #10693 --- doc/7-icinga-template-library.md | 6 +++++- itl/plugins-contrib.d/operating-system.conf | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/doc/7-icinga-template-library.md b/doc/7-icinga-template-library.md index b3227a865..69cec1e5f 100644 --- a/doc/7-icinga-template-library.md +++ b/doc/7-icinga-template-library.md @@ -2066,7 +2066,11 @@ mem_critical | **Required.** Specify the critical threshold as number interprete Check command object for the `check_running_kernel` plugin provided by the `nagios-plugins-contrib` package on Debian. -The `running_kernel` check command does not support any vars. +Custom attributes: + +Name | Description +---------------------------|------------- +running\_kernel\_use\_sudo | Whether to run the plugin with `sudo`. Defaults to false except on Ubuntu where it defaults to true. #### yum diff --git a/itl/plugins-contrib.d/operating-system.conf b/itl/plugins-contrib.d/operating-system.conf index ca7214578..c065c18c2 100644 --- a/itl/plugins-contrib.d/operating-system.conf +++ b/itl/plugins-contrib.d/operating-system.conf @@ -53,7 +53,25 @@ object CheckCommand "mem" { object CheckCommand "running_kernel" { import "plugin-check-command" - command = [ "sudo", PluginContribDir + "/check_running_kernel" ] + command = {{ + var use_sudo = macro("$running_kernel_use_sudo$") + + if (use_sudo == null && PlatformName == "Ubuntu") { + use_sudo = true + } + + var args + + if (use_sudo) { + args = [ "sudo" ] + } else { + args = [] + } + + args += [ PluginContribDir + "/check_running_kernel" ] + + return args + }} } object CheckCommand "yum" { From 141f255d5ba22556a089bcf6a6194c10f3dfe1ad Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 26 Nov 2015 11:17:17 +0100 Subject: [PATCH 30/32] Build fix for Windows refs #10693 --- lib/base/utility.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index 32ea82022..3e52ab6ed 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -1440,7 +1440,7 @@ static bool ReleaseHelper(String *platformName, String *platformVersion) *platformName = "Windows"; if (platformVersion) { - String *platformVersion = "Vista"; + *platformVersion = "Vista"; if (IsWindowsVistaSP1OrGreater()) *platformVersion = "Vista SP1"; if (IsWindowsVistaSP2OrGreater()) From 4e05a4ca7ff23804b6050354ac68bc23651334df Mon Sep 17 00:00:00 2001 From: Jean Flach Date: Thu, 26 Nov 2015 11:10:55 +0100 Subject: [PATCH 31/32] Fix return value in PkiUtility refs #10632 --- lib/cli/pkiutility.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cli/pkiutility.cpp b/lib/cli/pkiutility.cpp index b1003665d..2080dede7 100644 --- a/lib/cli/pkiutility.cpp +++ b/lib/cli/pkiutility.cpp @@ -122,7 +122,7 @@ boost::shared_ptr PkiUtility::FetchCert(const String& host, const String& << "Cannot connect to host '" << host << "' on port '" << port << "'"; Log(LogDebug, "pki") << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex); - return NULL; + return boost::shared_ptr(); } boost::shared_ptr sslContext; @@ -134,7 +134,7 @@ boost::shared_ptr PkiUtility::FetchCert(const String& host, const String& << "Cannot make SSL context."; Log(LogDebug, "pki") << "Cannot make SSL context:\n" << DiagnosticInformation(ex); - return NULL; + return boost::shared_ptr(); } TlsStream::Ptr stream = new TlsStream(client, String(), RoleClient, sslContext); From 508e2f8998f0e25f0c677b49523893f9595f1721 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 26 Nov 2015 11:00:12 +0100 Subject: [PATCH 32/32] Release version 2.4.1 --- ChangeLog | 36 ++++++++++++++++++++++++++++++++++++ doc/1-about.md | 36 ++++++++++++++++++++++++++++++++++++ icinga2.nuspec | 2 +- icinga2.spec | 2 +- tools/chocolateyInstall.ps1 | 2 +- 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9bcfd7853..161bc9361 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,42 @@ Please check [doc/1-about.md]. ## What's New +### What's New in Version 2.4.1 + +#### Changes + +* ITL + * Add running_kernel_use_sudo option for the running_kernel check +* Configuration + * Add global constants: `PlatformName`. `PlatformVersion`, `PlatformKernel` and `PlatformKernelVersion` +* CLI + * Use NodeName and ZoneName constants for 'node setup' and 'node wizard' + +#### Feature + +* Feature 10622: Add by_ssh_options argument for the check_by_ssh plugin +* Feature 10693: Add running_kernel_use_sudo option for the running_kernel check +* Feature 10716: Use NodeName and ZoneName constants for 'node setup' and 'node wizard' + +#### Bugfixes + +* Bug 10528: Documentation example in "Access Object Attributes at Runtime" doesn't work correctly +* Bug 10615: Build fails on SLES 11 SP3 with GCC 4.8 +* Bug 10632: "node wizard" does not ask user to verify SSL certificate +* Bug 10641: API setup command incorrectly overwrites existing certificates +* Bug 10643: Icinga 2 crashes when ScheduledDowntime objects are used +* Bug 10645: Documentation for schedule-downtime is missing required paremeters +* Bug 10648: lib/base/process.cpp SIGSEGV on Debian squeeze / RHEL 6 +* Bug 10661: Incorrect web inject URL in documentation +* Bug 10663: Incorrect redirect for stderr in /usr/lib/icinga2/prepare-dirs +* Bug 10667: Indentation in command-plugins.conf +* Bug 10677: node wizard checks for /var/lib/icinga2/ca directory but not the files +* Bug 10690: CLI command 'repository add' doesn't work +* Bug 10692: Fix typos in the documentation +* Bug 10708: Windows setup wizard crashes when InstallDir registry key is not set +* Bug 10710: Incorrect path for icinga2 binary in development documentation +* Bug 10720: Remove --master_zone from --help because it is currently not implemented + ### What's New in Version 2.4.0 #### Changes diff --git a/doc/1-about.md b/doc/1-about.md index 0e83e00b3..bcd0c17e3 100644 --- a/doc/1-about.md +++ b/doc/1-about.md @@ -54,6 +54,42 @@ More details in the [Icinga FAQ](https://www.icinga.org/icinga/faq/). ## What's New +### What's New in Version 2.4.1 + +#### Changes + +* ITL + * Add running_kernel_use_sudo option for the running_kernel check +* Configuration + * Add global constants: `PlatformName`. `PlatformVersion`, `PlatformKernel` and `PlatformKernelVersion` +* CLI + * Use NodeName and ZoneName constants for 'node setup' and 'node wizard' + +#### Feature + +* Feature [10622](https://dev.icinga.org/issues/10622 "Feature 10622"): Add by_ssh_options argument for the check_by_ssh plugin +* Feature [10693](https://dev.icinga.org/issues/10693 "Feature 10693"): Add running_kernel_use_sudo option for the running_kernel check +* Feature [10716](https://dev.icinga.org/issues/10716 "Feature 10716"): Use NodeName and ZoneName constants for 'node setup' and 'node wizard' + +#### Bugfixes + +* Bug [10528](https://dev.icinga.org/issues/10528 "Bug 10528"): Documentation example in "Access Object Attributes at Runtime" doesn't work correctly +* Bug [10615](https://dev.icinga.org/issues/10615 "Bug 10615"): Build fails on SLES 11 SP3 with GCC 4.8 +* Bug [10632](https://dev.icinga.org/issues/10632 "Bug 10632"): "node wizard" does not ask user to verify SSL certificate +* Bug [10641](https://dev.icinga.org/issues/10641 "Bug 10641"): API setup command incorrectly overwrites existing certificates +* Bug [10643](https://dev.icinga.org/issues/10643 "Bug 10643"): Icinga 2 crashes when ScheduledDowntime objects are used +* Bug [10645](https://dev.icinga.org/issues/10645 "Bug 10645"): Documentation for schedule-downtime is missing required paremeters +* Bug [10648](https://dev.icinga.org/issues/10648 "Bug 10648"): lib/base/process.cpp SIGSEGV on Debian squeeze / RHEL 6 +* Bug [10661](https://dev.icinga.org/issues/10661 "Bug 10661"): Incorrect web inject URL in documentation +* Bug [10663](https://dev.icinga.org/issues/10663 "Bug 10663"): Incorrect redirect for stderr in /usr/lib/icinga2/prepare-dirs +* Bug [10667](https://dev.icinga.org/issues/10667 "Bug 10667"): Indentation in command-plugins.conf +* Bug [10677](https://dev.icinga.org/issues/10677 "Bug 10677"): node wizard checks for /var/lib/icinga2/ca directory but not the files +* Bug [10690](https://dev.icinga.org/issues/10690 "Bug 10690"): CLI command 'repository add' doesn't work +* Bug [10692](https://dev.icinga.org/issues/10692 "Bug 10692"): Fix typos in the documentation +* Bug [10708](https://dev.icinga.org/issues/10708 "Bug 10708"): Windows setup wizard crashes when InstallDir registry key is not set +* Bug [10710](https://dev.icinga.org/issues/10710 "Bug 10710"): Incorrect path for icinga2 binary in development documentation +* Bug [10720](https://dev.icinga.org/issues/10720 "Bug 10720"): Remove --master_zone from --help because it is currently not implemented + ### What's New in Version 2.4.0 #### Changes diff --git a/icinga2.nuspec b/icinga2.nuspec index d4afc901f..e1af6c054 100755 --- a/icinga2.nuspec +++ b/icinga2.nuspec @@ -6,7 +6,7 @@ icinga2 Icinga2 - 2.4.0 + 2.4.1 2015 - The Icinga Project Icinga Development Team icinga2 - Monitoring Agent for Windows diff --git a/icinga2.spec b/icinga2.spec index 1ecfb1b8c..3a1e3eda3 100644 --- a/icinga2.spec +++ b/icinga2.spec @@ -66,7 +66,7 @@ Summary: Network monitoring application Name: icinga2 -Version: 2.4.0 +Version: 2.4.1 Release: %{revision}%{?dist} License: GPL-2.0+ Group: Applications/System diff --git a/tools/chocolateyInstall.ps1 b/tools/chocolateyInstall.ps1 index 8bc4721d0..5fa5d116f 100755 --- a/tools/chocolateyInstall.ps1 +++ b/tools/chocolateyInstall.ps1 @@ -1,6 +1,6 @@ $packageName = 'icinga2' $installerType = 'exe' -$url = 'http://packages.icinga.org/windows/Icinga2-v2.4.0.exe' +$url = 'http://packages.icinga.org/windows/Icinga2-v2.4.1.exe' $silentArgs = '/S' $validExitCodes = @(0)