]> granicus.if.org Git - icinga2/commitdiff
Implement new state and type filters.
authorGunnar Beutner <gunnar.beutner@netways.de>
Mon, 7 Apr 2014 11:59:41 +0000 (13:59 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Mon, 7 Apr 2014 12:00:18 +0000 (14:00 +0200)
Fixes #5906

23 files changed:
doc/3.04-notifications.md
doc/4.3-object-types.md
doc/8-differences-between-icinga-1x-and-2.md
etc/CMakeLists.txt
etc/icinga2/conf.d/generic-host.conf
etc/icinga2/conf.d/generic-service.conf
etc/icinga2/conf.d/notifications.conf
etc/icinga2/scripts/mail-host-notification.sh [new file with mode: 0755]
etc/icinga2/scripts/mail-service-notification.sh [moved from etc/icinga2/scripts/mail-notification.sh with 100% similarity]
lib/icinga/checkresult.cpp
lib/icinga/checkresult.h
lib/icinga/checkresult.ti
lib/icinga/dependency.cpp
lib/icinga/dependency.h
lib/icinga/dependency.ti
lib/icinga/host.h
lib/icinga/icinga-type.conf
lib/icinga/notification.cpp
lib/icinga/notification.h
lib/icinga/notification.ti
lib/icinga/user.cpp
lib/icinga/user.h
lib/icinga/user.ti

index fb5a1e776497a0c51eea9ff15fceb1f3068c5432..ce87ca5b687387cba45915a56f539d753b005b83 100644 (file)
@@ -19,11 +19,8 @@ The user `icingaadmin` in the example below will get notified only on `WARNING`
     object User "icingaadmin" {
       display_name = "Icinga 2 Admin"
       enable_notifications = 1
-      notification_state_filter = (StateFilterOK |
-                                  StateFilterWarning |
-                                  StateFilterCritical)
-      notification_type_filter = (NotificationFilterProblem |
-                                 NotificationFilterRecovery)
+      notification_state_filter = [ OK, Warning, Critical ]
+      notification_type_filter = [ Problem, Recovery ]
       vars.email = "icinga@localhost"
       vars.pager = "+49123456789"
       }
@@ -77,18 +74,9 @@ TODO
     
       notification_command = "mail-service-notification"
   
-      notification_state_filter = (StateFilterWarning |
-                                  StateFilterCritical |
-                                  StateFilterUnknown)
-      notification_type_filter = (NotificationFilterProblem |
-                                 NotificationFilterAcknowledgement |
-                                 NotificationFilterRecovery |
-                                 NotificationFilterCustom |
-                                 NotificationFilterFlappingStart |
-                                 NotificationFilterFlappingEnd |
-                                 NotificationFilterDowntimeStart |
-                                 NotificationFilterDowntimeEnd |
-                                 NotificationFilterDowntimeRemoved)
+      notification_state_filter = [ Warning, Critical, Unknown ]
+      notification_type_filter = [ Problem, Acknowledgement, Recovery, Custom, FlappingStart,
+                                   FlappingEnd, DowntimeStart,DowntimeEnd, DowntimeRemoved ]
   
       notification_period = "24x7"
     }
@@ -234,18 +222,9 @@ Available state and type filters for notifications are:
 
     template Notification "generic-notification" {
   
-      notification_state_filter = (StateFilterWarning |
-                                  StateFilterCritical |
-                                  StateFilterUnknown)
-      notification_type_filter = (NotificationFilterProblem |
-                                 NotificationFilterAcknowledgement |
-                                 NotificationFilterRecovery |
-                                 NotificationFilterCustom |
-                                 NotificationFilterFlappingStart |
-                                 NotificationFilterFlappingEnd |
-                                 NotificationFilterDowntimeStart |
-                                 NotificationFilterDowntimeEnd |
-                                 NotificationFilterDowntimeRemoved)
+      notification_state_filter = [ Warning, Critical, Unknown ]
+      notification_type_filter = [ Problem, Acknowledgement, Recovery, Custom, FlappingStart,
+                                   FlappingEnd, DowntimeStart, DowntimeEnd, DowntimeRemoved ]
     }
 
 If you are familiar with Icinga 1.x `notification_options` please note that they have been split
index 6f44cc25bc1f11f3bfba00487f9c717ebe63b4cd..dff7eecad42eff14d60cd35bff5f1e1174a9b6f4 100644 (file)
@@ -134,6 +134,8 @@ Example:
       notification_command = "mail-notification"
 
       users = [ "user1", "user2" ]
+
+      notification_type_filter = [ Problem, Recovery ]
     }
 
 Attributes:
@@ -149,25 +151,29 @@ Attributes:
   notification_command      | **Required.** The name of the notification command which should be executed when the notification is triggered.
   notification_interval     | **Optional.** The notification interval (in seconds). This interval is used for active notifications. Defaults to 5 minutes. 
   notification_period       | **Optional.** The name of a time period which determines when this notification should be triggered. Not set by default.
-  notification_type_filter  | **Optional.** A set of state filters when this notification should be triggered. By default everything is matched.
-  notification_state_filter | **Optional.** A set of type filters when this notification should be triggered. By default everything is matched.
+  notification_type_filter  | **Optional.** A list of state filters when this notification should be triggered. By default everything is matched.
+  notification_state_filter | **Optional.** A list of type filters when this notification should be triggered. By default everything is matched.
+
+Available notification state filters:
 
-Available notification type and state filters:
+    OK
+    Warning
+    Critical
+    Unknown
+    Up
+    Down
 
-    StateFilterOK
-    StateFilterWarning
-    StateFilterCritical
-    StateFilterUnknown
+Available notification type filters:
     
-    NotificationFilterDowntimeStart
-    NotificationFilterDowntimeEnd
-    NotificationFilterDowntimeRemoved
-    NotificationFilterCustom
-    NotificationFilterAcknowledgement
-    NotificationFilterProblem
-    NotificationFilterRecovery
-    NotificationFilterFlappingStart
-    NotificationFilterFlappingEnd
+    DowntimeStart
+    DowntimeEnd
+    DowntimeRemoved
+    Custom
+    Acknowledgement
+    Problem
+    Recovery
+    FlappingStart
+    FlappingEnd
 
 ### <a id="objecttype-dependency"></a> Dependency
 
@@ -188,7 +194,7 @@ Example:
       parent_host_name = "internet"
       parent_service_name = "ping4"
 
-      state_filter = StateFilterOK
+      state_filter = [ OK, Warning ]
 
       disable_checks = true
     }
@@ -204,14 +210,16 @@ Attributes:
   disable_checks  |**Optional.** Whether to disable checks when this dependency fails. Defaults to false.
   disable_notifications|**Optional.** Whether to disable notifications when this dependency fails. Defaults to true.
   period          |**Optional.** Time period during which this dependency is enabled.
-  state_filter    |**Optional.** A set of type filters when this dependency should be OK. Defaults to StateFilterOK &#124; StateFilterWarning.
+  state_filter    |**Optional.** A list of type filters when this dependency should be OK. Defaults to [ OK, Warning ] for services and [ Up ] for hosts.
 
 Available state filters:
 
-    StateFilterOK
-    StateFilterWarning
-    StateFilterCritical
-    StateFilterUnknown
+    OK
+    Warning
+    Critical
+    Unknown
+    Up
+    Down
 
 Dependency objects have composite names, i.e. their names are based on the `child_host_name` and `child_service_name` attributes and the
 name you specified. This means you can define more than one object with the same (short) name as long as one of the `child_host_name` and
@@ -230,12 +238,8 @@ Example:
       enable_notifications = 1
       notification_period = "24x7"
 
-      notification_state_filter = (StateFilterOK |
-                                  StateFilterWarning |
-                                  StateFilterCritical |
-                                  StateFilterUnknown)
-      notification_type_filter = (NotificationFilterProblem |
-                                 NotificationFilterRecovery)
+      notification_state_filter = [ OK, Warning, Critical, Unknown ]
+      notification_type_filter = [ Problem, Recovery ]
 
       vars = {
         name = "Icinga 2 Admin"
@@ -248,22 +252,26 @@ Example:
       }
     }
 
-Available notification type and state filters:
-
-    StateFilterOK
-    StateFilterWarning
-    StateFilterCritical
-    StateFilterUnknown
-
-    NotificationFilterDowntimeStart
-    NotificationFilterDowntimeEnd
-    NotificationFilterDowntimeRemoved
-    NotificationFilterCustom
-    NotificationFilterAcknowledgement
-    NotificationFilterProblem
-    NotificationFilterRecovery
-    NotificationFilterFlappingStart
-    NotificationFilterFlappingEnd
+Available notification state filters:
+
+    OK
+    Warning
+    Critical
+    Unknown
+    Up
+    Down
+
+Available notification type filters:
+
+    DowntimeStart
+    DowntimeEnd
+    DowntimeRemoved
+    Custom
+    Acknowledgement
+    Problem
+    Recovery
+    FlappingStart
+    FlappingEnd
 
 Attributes:
 
index b16ff3d3cd4e15aaefe60295cc6543ec411eedc2..d3f58445fd1881a6b157e10b264cd05081833408 100644 (file)
@@ -497,8 +497,8 @@ All state and type filter use long names or'd with a pipe together
 
     notification_options w,u,c,r,f,s
 
-    notification_state_filter = StateFilterWarning | StateFilterUnknown | StateFilterCritical,
-    notification_type_filter = NotificationProblem | NotificationRecovery | NotificationFlappingStart | NotificationFlappingEnd | NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved
+    notification_state_filter = [ Warning, Unknown, Critical ]
+    notification_type_filter = [ Problem, Recovery, FlappingStart, FlappingEnd, DowntimeStart, DowntimeEnd, DowntimeRemoved ]
 
 Icinga 2 adds more fine-grained type filters for acknowledgements, downtime
 and flapping type (start, end, ...).
index 5eb19701f9ad8ae9059b63bb98923b5d92a86faa..a1f0a8fd185064c8582178cb013030f0696db286 100644 (file)
@@ -43,7 +43,8 @@ install_if_not_exists(icinga2/features-available/notification.conf ${CMAKE_INSTA
 install_if_not_exists(icinga2/features-available/perfdata.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available)
 install_if_not_exists(icinga2/features-available/statusdata.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available)
 install_if_not_exists(icinga2/features-available/syslog.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available)
-install_if_not_exists(icinga2/scripts/mail-notification.sh ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts)
+install_if_not_exists(icinga2/scripts/mail-host-notification.sh ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts)
+install_if_not_exists(icinga2/scripts/mail-service-notification.sh ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts)
 install_if_not_exists(icinga2/scripts/snmp-extend.sh ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts)
 install_if_not_exists(logrotate.d/icinga2 ${CMAKE_INSTALL_SYSCONFDIR}/logrotate.d)
 
index 060e23572421ce8b74bf62241499574fd61f6cdb..499afa4f03fb8a714a298774bb42a76e5102ef53 100644 (file)
@@ -7,7 +7,7 @@ template Host "generic-host" {
 }
 
 apply Notification "mail-icingaadmin" to Host {
-  import "mail-notification"
+  import "mail-host-notification"
 
   user_groups = [ "icingaadmins"]
 
index 811750a82ae1d703c4b8d1ce9e1264cc4cb2e78b..eed24046f7b5a2099a6d0302222d2d5bbd3eeb88 100644 (file)
@@ -10,7 +10,7 @@ template Service "generic-service" {
 }
 
 apply Notification "mail-icingaadmin" to Service {
-  import "mail-notification"
+  import "mail-service-notification"
 
   user_groups = [ "icingaadmins"]
 
index 636d05125170cf406664e9e8328f75a432ef1932..31ea3062d664ff15f49702529e80c251fae5c964 100644 (file)
@@ -2,22 +2,44 @@
  * The example notification templates.
  */
 
-template Notification "mail-notification" {
+template Notification "mail-host-notification" {
+  notification_command = "mail-host-notification"
+
+  notification_state_filter = [ Up, Down ]
+  notification_type_filter = [ Problem, Acknowledgement, Recovery, Custom,
+                               FlappingStart, FlappingEnd,
+                               DowntimeStart, DowntimeEnd, DowntimeRemoved ]
+
+  notification_period = "24x7"
+}
+
+object NotificationCommand "mail-host-notification" {
+  import "plugin-notification-command"
+
+  command = [ IcingaSysconfDir + "/icinga2/scripts/mail-host-notification.sh" ]
+
+  env = {
+    "NOTIFICATIONTYPE" = "$notification.type$"
+    "HOSTALIAS" = "$host.displayname$",
+    "HOSTADDRESS" = "$host.vars.address$",
+    "HOSTSTATE" = "$host.state$",
+    "LONGDATETIME" = "$icinga.longdatetime$",
+    "HOSTOUTPUT" = "$host.output$",
+    "NOTIFICATIONAUTHORNAME" = "$notification.author$",
+    "NOTIFICATIONCOMMENT" = "$notification.comment$",
+    "HOSTDISPLAYNAME" = "$host.displayname$",
+    "HOSTDISPLAYNAME" = "$host.displayname$",
+    "USEREMAIL" = "$user.vars.email$"
+  }
+}
+
+template Notification "mail-service-notification" {
   notification_command = "mail-service-notification"
 
-  notification_state_filter = (StateFilterOK |
-                               StateFilterWarning |
-                               StateFilterCritical |
-                               StateFilterUnknown)
-  notification_type_filter = (NotificationFilterProblem |
-                              NotificationFilterAcknowledgement |
-                              NotificationFilterRecovery |
-                              NotificationFilterCustom | 
-                              NotificationFilterFlappingStart |
-                              NotificationFilterFlappingEnd | 
-                              NotificationFilterDowntimeStart |
-                              NotificationFilterDowntimeEnd | 
-                              NotificationFilterDowntimeRemoved)
+  notification_state_filter = [ OK, Warning, Critical, Unknown ]
+  notification_type_filter = [ Problem, Acknowledgement, Recovery, Custom,
+                               FlappingStart, FlappingEnd,
+                               DowntimeStart, DowntimeEnd, DowntimeRemoved ]
 
   notification_period = "24x7"
 }
@@ -25,7 +47,7 @@ template Notification "mail-notification" {
 object NotificationCommand "mail-service-notification" {
   import "plugin-notification-command"
 
-  command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ]
+  command = [ IcingaSysconfDir + "/icinga2/scripts/mail-service-notification.sh" ]
 
   env = {
     "NOTIFICATIONTYPE" = "$notification.type$"
diff --git a/etc/icinga2/scripts/mail-host-notification.sh b/etc/icinga2/scripts/mail-host-notification.sh
new file mode 100755 (executable)
index 0000000..0ecec0e
--- /dev/null
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+template=$(cat <<TEMPLATE
+***** Icinga  *****
+
+Notification Type: $NOTIFICATIONTYPE
+
+Host: $HOSTALIAS
+Address: $HOSTADDRESS
+State: $HOSTSTATE
+
+Date/Time: $LONGDATETIME
+
+Additional Info: $HOSTOUTPUT
+
+Comment: [$NOTIFICATIONAUTHORNAME] $NOTIFICATIONCOMMENT
+TEMPLATE
+)
+
+/usr/bin/printf "%b" "$template" | mail -s "$NOTIFICATIONTYPE - $HOSTDISPLAYNAME is $HOSTSTATE" $USEREMAIL
+
index b97010129e0cccb9b7583c78aba67bea711e38e1..1d07b2cdcfcbc4d3b082081f9f3ac2338d013242 100644 (file)
 using namespace icinga;
 
 REGISTER_TYPE(CheckResult);
-INITIALIZE_ONCE(&CheckResult::StaticInitialize);
-
-void CheckResult::StaticInitialize(void)
-{
-       ScriptVariable::Set("StateOK", StateOK, true, true);
-       ScriptVariable::Set("StateWarning", StateWarning, true, true);
-       ScriptVariable::Set("StateCritical", StateCritical, true, true);
-       ScriptVariable::Set("StateUnknown", StateUnknown, true, true);
-
-       ScriptVariable::Set("StateFilterOK", 1 << StateOK, true, true);
-       ScriptVariable::Set("StateFilterWarning", 1 << StateWarning, true, true);
-       ScriptVariable::Set("StateFilterCritical", 1 << StateCritical, true, true);
-       ScriptVariable::Set("StateFilterUnknown", 1 << StateUnknown, true, true);
-}
-
index ee584e976bbd32abbdb2dd55b34619e4dda6359b..b0f595ac04d43cbd3535efff990c3ae741993063 100644 (file)
@@ -35,8 +35,6 @@ class I2_ICINGA_API CheckResult : public ObjectImpl<CheckResult>
 {
 public:
        DECLARE_PTR_TYPEDEFS(CheckResult);
-
-       static void StaticInitialize(void);
 };
 
 }
index a209dbd456a0716486bd7e547e0cb5e1ced9d985..6c5a586b7a864d1a75ef2bce59c09bd958c974ce 100644 (file)
@@ -2,6 +2,18 @@ namespace icinga
 {
 
 code {{{
+/**
+ * The state of a host.
+ *
+ * @ingroup icinga
+ */
+enum HostState
+{
+       HostUp = 0,
+       HostDown = 1,
+       HostUnreachable = 2
+};
+
 /**
  * The state of a service.
  *
index 18213f57ad21879471cdcee94863753d1618ac58..efc238eb326f370b6e5d8129c245579baf0f2e57 100644 (file)
 
 #include "icinga/dependency.h"
 #include "icinga/service.h"
+#include "config/configcompilercontext.h"
 #include "base/dynamictype.h"
 #include "base/objectlock.h"
 #include "base/logger_fwd.h"
+#include "base/scriptfunction.h"
 #include <boost/foreach.hpp>
 
 using namespace icinga;
 
 REGISTER_TYPE(Dependency);
+REGISTER_SCRIPTFUNCTION(ValidateDependencyFilters, &Dependency::ValidateFilters);
 
 String DependencyNameComposer::MakeName(const String& shortName, const Dictionary::Ptr props) const
 {
@@ -43,6 +46,18 @@ String DependencyNameComposer::MakeName(const String& shortName, const Dictionar
        return name;
 }
 
+void Dependency::OnConfigLoaded(void)
+{
+       Value defaultFilter;
+
+       if (GetParentServiceName().IsEmpty())
+               defaultFilter = StateFilterUp;
+       else
+               defaultFilter = StateFilterOK | StateFilterWarning;
+
+       SetStateFilter(FilterArrayToInt(GetStateFilterRaw(), defaultFilter));
+}
+
 void Dependency::OnStateLoaded(void)
 {
        DynamicObject::Start();
@@ -100,12 +115,12 @@ bool Dependency::IsAvailable(DependencyType dt) const
        int state;
 
        if (is_service)
-               state = static_cast<int>(static_pointer_cast<Service>(parent)->GetState());
+               state = ServiceStateToFilter(static_pointer_cast<Service>(parent)->GetState());
        else
-               state = static_cast<int>(static_pointer_cast<Host>(parent)->GetState());
+               state = HostStateToFilter(static_pointer_cast<Host>(parent)->GetState());
 
        /* check state */
-       if ((1 << state) & GetStateFilter()) {
+       if (state & GetStateFilter()) {
                Log(LogDebug, "icinga", "Dependency '" + GetName() + "' passed: Object matches state filter.");
                return true;
        }
@@ -159,3 +174,18 @@ TimePeriod::Ptr Dependency::GetPeriod(void) const
 {
        return TimePeriod::GetByName(GetPeriodRaw());
 }
+
+void Dependency::ValidateFilters(const String& location, const Dictionary::Ptr& attrs)
+{
+       int sfilter = FilterArrayToInt(attrs->Get("state_filter"), 0);
+
+       if (!attrs->Contains("parent_service_name") && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) {
+               ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
+                   location + ": State filter is invalid.");
+       }
+
+       if (attrs->Contains("parent_service_name") && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
+               ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
+                   location + ": State filter is invalid.");
+       }
+}
index 57b7000b468fec96c0e51a3466f4feb08604738c..395707e3c0c1fafdbf50d95a313c61fe603367fa 100644 (file)
@@ -49,7 +49,10 @@ public:
 
        static void RegisterApplyRuleHandler(void);
 
+       static void ValidateFilters(const String& location, const Dictionary::Ptr& attrs);
+
 protected:
+       virtual void OnConfigLoaded(void);
        virtual void OnStateLoaded(void);
        virtual void Stop(void);
 
index b350305adc89ea89b6f43a1a0bcb9d6d831741bf..b77437972c7bfaa001e3f85aaddfb91ea30a5009 100644 (file)
@@ -22,9 +22,8 @@ class Dependency : DynamicObject < DependencyNameComposer
 
        [config] String period (PeriodRaw);
 
-       [config] int state_filter {
-               default {{{ return (1 << StateOK) | (1 << StateWarning); }}}
-       };
+       [config] Array::Ptr state_filter (StateFilterRaw);
+       int state_filter_real (StateFilter);
 
        [config] bool disable_checks;
        [config] bool disable_notifications;
index 90a06e5e1687026eb361070a373c2feb6ca99093..868b183c758d4c284d9afb89946d0b555a41fb8c 100644 (file)
@@ -34,18 +34,6 @@ namespace icinga
 class Service;
 class Dependency;
 
-/**
- * The state of a host.
- *
- * @ingroup icinga
- */
-enum HostState
-{
-       HostUp = 0,
-       HostDown = 1,
-       HostUnreachable = 2
-};
-
 /**
  * An Icinga host.
  *
index e2ed754ccad9c142c444ba3d5b50c17d80c6afd1..5acc3b87b9202b9986e3a1b02af07f62ef3ec144 100644 (file)
@@ -81,6 +81,8 @@
 }
 
 %type Notification {
+       %validator "ValidateNotificationFilters"
+
        %require "host_name",
        %attribute %name(Host) "host_name",
        %attribute %string "service_name",
        %attribute %number "notification_interval",
        %attribute %name(TimePeriod) "notification_period",
 
-       %attribute %number "notification_type_filter",
-       %attribute %number "notification_state_filter",
+       %attribute %array "notification_type_filter" {
+               %attribute %number "*"
+       },
+       %attribute %array "notification_state_filter" {
+               %attribute %number "*"
+       },
 
        %attribute %array "authorities" {
                %attribute %name(Endpoint) "*"
        },
 
        %attribute %number "enable_notifications",
-       %attribute %number "notification_type_filter",
-       %attribute %number "notification_state_filter",
+       %attribute %array "notification_type_filter" {
+               %attribute %number "*"
+       },
+       %attribute %array "notification_state_filter" {
+               %attribute %number "*"
+       },
        %attribute %name(TimePeriod) "notification_period"
 }
 
 }
 
 %type Dependency {
+       %validator "ValidateDependencyFilters"
+
        %require "parent_host_name",
        %attribute %name(Host) "parent_host_name",
        %attribute %string "parent_service_name",
index d6833ac83e11aacfb13b39f16e6b0cfe42795cb2..d516f730b6aba239a04d2266c99c215d52c2100d 100644 (file)
@@ -21,6 +21,7 @@
 #include "icinga/notificationcommand.h"
 #include "icinga/macroprocessor.h"
 #include "icinga/service.h"
+#include "config/configcompilercontext.h"
 #include "base/dynamictype.h"
 #include "base/objectlock.h"
 #include "base/logger_fwd.h"
 #include "base/exception.h"
 #include "base/initialize.h"
 #include "base/scriptvariable.h"
+#include "base/scriptfunction.h"
 #include <boost/foreach.hpp>
 
 using namespace icinga;
 
 REGISTER_TYPE(Notification);
+REGISTER_SCRIPTFUNCTION(ValidateNotificationFilters, &Notification::ValidateFilters);
 INITIALIZE_ONCE(&Notification::StaticInitialize);
 
 boost::signals2::signal<void (const Notification::Ptr&, double, const String&)> Notification::OnNextNotificationChanged;
@@ -55,25 +58,30 @@ String NotificationNameComposer::MakeName(const String& shortName, const Diction
 
 void Notification::StaticInitialize(void)
 {
-       ScriptVariable::Set("NotificationDowntimeStart", NotificationDowntimeStart, true, true);
-       ScriptVariable::Set("NotificationDowntimeEnd", NotificationDowntimeEnd, true, true);
-       ScriptVariable::Set("NotificationDowntimeRemoved", NotificationDowntimeRemoved, true, true);
-       ScriptVariable::Set("NotificationCustom", NotificationCustom, true, true);
-       ScriptVariable::Set("NotificationAcknowledgement", NotificationAcknowledgement, true, true);
-       ScriptVariable::Set("NotificationProblem", NotificationProblem, true, true);
-       ScriptVariable::Set("NotificationRecovery", NotificationRecovery, true, true);
-       ScriptVariable::Set("NotificationFlappingStart", NotificationFlappingStart, true, true);
-       ScriptVariable::Set("NotificationFlappingEnd", NotificationFlappingEnd, true, true);
-
-       ScriptVariable::Set("NotificationFilterDowntimeStart", 1 << NotificationDowntimeStart, true, true);
-       ScriptVariable::Set("NotificationFilterDowntimeEnd", 1 << NotificationDowntimeEnd, true, true);
-       ScriptVariable::Set("NotificationFilterDowntimeRemoved", 1 << NotificationDowntimeRemoved, true, true);
-       ScriptVariable::Set("NotificationFilterCustom", 1 << NotificationCustom, true, true);
-       ScriptVariable::Set("NotificationFilterAcknowledgement", 1 << NotificationAcknowledgement, true, true);
-       ScriptVariable::Set("NotificationFilterProblem", 1 << NotificationProblem, true, true);
-       ScriptVariable::Set("NotificationFilterRecovery", 1 << NotificationRecovery, true, true);
-       ScriptVariable::Set("NotificationFilterFlappingStart", 1 << NotificationFlappingStart, true, true);
-       ScriptVariable::Set("NotificationFilterFlappingEnd", 1 << NotificationFlappingEnd, true, true);
+       ScriptVariable::Set("OK", StateFilterOK, true, true);
+       ScriptVariable::Set("Warning", StateFilterWarning, true, true);
+       ScriptVariable::Set("Critical", StateCritical, true, true);
+       ScriptVariable::Set("Unknown", StateUnknown, true, true);
+       ScriptVariable::Set("Up", StateFilterUp, true, true);
+       ScriptVariable::Set("Down", StateFilterDown, true, true);
+
+       ScriptVariable::Set("DowntimeStart", 1 << NotificationDowntimeStart, true, true);
+       ScriptVariable::Set("DowntimeEnd", 1 << NotificationDowntimeEnd, true, true);
+       ScriptVariable::Set("DowntimeRemoved", 1 << NotificationDowntimeRemoved, true, true);
+       ScriptVariable::Set("Custom", 1 << NotificationCustom, true, true);
+       ScriptVariable::Set("Acknowledgement", 1 << NotificationAcknowledgement, true, true);
+       ScriptVariable::Set("Problem", 1 << NotificationProblem, true, true);
+       ScriptVariable::Set("Recovery", 1 << NotificationRecovery, true, true);
+       ScriptVariable::Set("FlappingStart", 1 << NotificationFlappingStart, true, true);
+       ScriptVariable::Set("FlappingEnd", 1 << NotificationFlappingEnd, true, true);
+}
+
+void Notification::OnConfigLoaded(void)
+{
+       SetNotificationTypeFilter(FilterArrayToInt(GetNotificationTypeFilterRaw(), 0));
+       SetNotificationStateFilter(FilterArrayToInt(GetNotificationStateFilterRaw(), 0));
+
+       GetCheckable()->AddNotification(GetSelf());
 }
 
 void Notification::Start(void)
@@ -255,9 +263,9 @@ void Notification::BeginExecuteNotification(NotificationType type, const CheckRe
                unsigned long fstate;
 
                if (service)
-                       fstate = 1 << service->GetState();
+                       fstate = ServiceStateToFilter(service->GetState());
                else
-                       fstate = 1 << host->GetState();
+                       fstate = HostStateToFilter(host->GetState());
 
                if (!(fstate & GetNotificationStateFilter())) {
                        Log(LogInformation, "icinga", "Not sending notifications for notification object '" + GetName() + "': state filter does not match");
@@ -336,9 +344,9 @@ bool Notification::CheckNotificationUserFilters(NotificationType type, const Use
                unsigned long fstate;
 
                if (service)
-                               fstate = 1 << service->GetState();
+                               fstate = ServiceStateToFilter(service->GetState());
                else
-                               fstate = 1 << host->GetState();
+                               fstate = HostStateToFilter(host->GetState());
 
                if (!(fstate & user->GetNotificationStateFilter())) {
                        Log(LogInformation, "icinga", "Not sending notifications for notification object '" +
@@ -382,6 +390,76 @@ void Notification::ExecuteNotificationHelper(NotificationType type, const User::
        }
 }
 
+int icinga::ServiceStateToFilter(ServiceState state)
+{
+       switch (state) {
+               case StateOK:
+                       return StateFilterOK;
+               case StateWarning:
+                       return StateFilterWarning;
+               case StateCritical:
+                       return StateFilterCritical;
+               case StateUnknown:
+                       return StateFilterUnknown;
+               default:
+                       VERIFY(!"Invalid state type.");
+       }
+}
+
+int icinga::HostStateToFilter(HostState state)
+{
+       switch (state) {
+               case HostUp:
+                       return StateFilterUp;
+               case HostDown: /* fall through */
+               case HostUnreachable:
+                       return StateFilterDown;
+               default:
+                       VERIFY(!"Invalid state type.");
+       }
+}
+
+int icinga::FilterArrayToInt(const Array::Ptr& typeFilters, int defaultValue)
+{
+       Value resultTypeFilter;
+
+       if (!typeFilters || typeFilters->GetLength() == 0)
+               return defaultValue;
+
+       resultTypeFilter = 0;
+
+       ObjectLock olock(typeFilters);
+       BOOST_FOREACH(const Value& typeFilter, typeFilters) {
+               resultTypeFilter = resultTypeFilter | typeFilter;
+       }
+
+       return resultTypeFilter;
+}
+
+void Notification::ValidateFilters(const String& location, const Dictionary::Ptr& attrs)
+{
+       int sfilter = FilterArrayToInt(attrs->Get("notification_state_filter"), 0);
+
+       if (!attrs->Contains("service_name") && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) {
+               ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
+                   location + ": State filter is invalid.");
+       }
+
+       if (attrs->Contains("service_name") && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
+               ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
+                   location + ": State filter is invalid.");
+       }
+
+       int tfilter = FilterArrayToInt(attrs->Get("notification_type_filter"), 0);
+
+       if ((tfilter & ~(1 << NotificationDowntimeStart | 1 << NotificationDowntimeEnd | 1 << NotificationDowntimeRemoved |
+           1 << NotificationCustom | 1 << NotificationAcknowledgement | 1 << NotificationProblem | 1 << NotificationRecovery |
+           1 << NotificationFlappingStart | 1 << NotificationFlappingEnd)) != 0) {
+               ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
+                   location + ": Type filter is invalid.");
+       }
+}
+
 bool Notification::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
 {
        Dictionary::Ptr vars = GetVars();
index d786f89272f35e16b667cc400db628644f6b3b8e..641ddb1377702d96aa3305cbbac7c3426edd9aba 100644 (file)
 namespace icinga
 {
 
+/**
+ * @ingroup icinga
+ */
+enum NotificationFilter
+{
+       StateFilterOK = 1,
+       StateFilterWarning = 2,
+       StateFilterCritical = 4,
+       StateFilterUnknown = 8,
+
+       StateFilterUp = 16,
+       StateFilterDown = 32
+};
+
 /**
  * The notification type.
  *
@@ -89,7 +103,10 @@ public:
 
        static void RegisterApplyRuleHandler(void);
 
+       static void ValidateFilters(const String& location, const Dictionary::Ptr& attrs);
+
 protected:
+       virtual void OnConfigLoaded(void);
        virtual void Start(void);
        virtual void Stop(void);
 
@@ -100,6 +117,10 @@ private:
        static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
 };
 
+I2_ICINGA_API int ServiceStateToFilter(ServiceState state);
+I2_ICINGA_API int HostStateToFilter(HostState state);
+I2_ICINGA_API int FilterArrayToInt(const Array::Ptr& typeFilters, int defaultValue);
+
 }
 
 #endif /* NOTIFICATION_H */
index df954f00b0838498af9f06779ab9d1dd2389e84a..f6e145ebfc7e689a13625b75f565a29126c3aade 100644 (file)
@@ -22,12 +22,10 @@ class Notification : DynamicObject < NotificationNameComposer
        [config, protected] Array::Ptr users (UsersRaw);
        [config, protected] Array::Ptr user_groups (UserGroupsRaw);
        [config] Dictionary::Ptr times;
-       [config] int notification_type_filter {
-               default {{{ return ~(int)0; }}}
-       };
-       [config] int notification_state_filter {
-               default {{{ return ~(int)0; }}}
-       };
+       [config] Array::Ptr notification_type_filter (NotificationTypeFilterRaw);
+       int notification_type_filter_real (NotificationTypeFilter);
+       [config] Array::Ptr notification_state_filter (NotificationStateFilterRaw);
+       int notification_state_filter_real (NotificationStateFilter);
        [config, protected] String host_name;
        [config, protected] String service_name;
 
index 4568ce84fa1e67e675c41cae9447f093e8277037..16fffb2680771c43fb2f354343e973e475aac55c 100644 (file)
  ******************************************************************************/
 
 #include "icinga/user.h"
+#include "icinga/notification.h"
 #include "icinga/usergroup.h"
+#include "config/configcompilercontext.h"
 #include "base/dynamictype.h"
+#include "base/scriptfunction.h"
 #include "base/utility.h"
 #include "base/objectlock.h"
 
 using namespace icinga;
 
 REGISTER_TYPE(User);
+REGISTER_SCRIPTFUNCTION(ValidateUserFilters, &User::ValidateFilters);
 
 void User::OnConfigLoaded(void)
 {
+       SetNotificationTypeFilter(FilterArrayToInt(GetNotificationTypeFilterRaw(), 0));
+       SetNotificationStateFilter(FilterArrayToInt(GetNotificationStateFilterRaw(), 0));
+
        Array::Ptr groups = GetGroups();
 
        if (groups) {
@@ -66,6 +73,25 @@ TimePeriod::Ptr User::GetNotificationPeriod(void) const
        return TimePeriod::GetByName(GetNotificationPeriodRaw());
 }
 
+void User::ValidateFilters(const String& location, const Dictionary::Ptr& attrs)
+{
+       int sfilter = FilterArrayToInt(attrs->Get("notification_state_filter"), 0);
+
+       if ((sfilter & ~(StateFilterUp | StateFilterDown | StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
+               ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
+                   location + ": State filter is invalid.");
+       }
+
+       int tfilter = FilterArrayToInt(attrs->Get("notification_type_filter"), 0);
+
+       if ((tfilter & ~(1 << NotificationDowntimeStart | 1 << NotificationDowntimeEnd | 1 << NotificationDowntimeRemoved |
+           1 << NotificationCustom | 1 << NotificationAcknowledgement | 1 << NotificationProblem | 1 << NotificationRecovery |
+           1 << NotificationFlappingStart | 1 << NotificationFlappingEnd)) != 0) {
+               ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
+                   location + ": Type filter is invalid.");
+       }
+}
+
 bool User::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
 {
        String key;
index 8efb4c1ae5e8eb8294a9993c5ca2518c2a41042d..22509f07531c88a12acdbfb9feb004d963853f78 100644 (file)
@@ -45,6 +45,8 @@ public:
 
        virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const;
 
+       static void ValidateFilters(const String& location, const Dictionary::Ptr& attrs);
+
 protected:
        virtual void Stop(void);
 
index 596d45c693dfad596a6ede025910c54cc160aa54..896abf2cfdc587f872a537582857f6b049f10434 100644 (file)
@@ -16,12 +16,10 @@ class User : DynamicObject
        [config] Dictionary::Ptr macros;
        [config] Array::Ptr groups;
        [config] String notification_period (NotificationPeriodRaw);
-       [config] int notification_type_filter {
-               default {{{ return ~(int)0; }}}
-       };
-       [config] int notification_state_filter {
-               default {{{ return ~(int)0; }}}
-       };
+       [config] Array::Ptr notification_type_filter (NotificationTypeFilterRaw);
+       int notification_type_filter_real (NotificationTypeFilter);
+       [config] Array::Ptr notification_state_filter (NotificationStateFilterRaw);
+       int notification_state_filter_real (NotificationStateFilter);
        [state] bool enable_notifications;
        [state] double last_notification;
 };