]> granicus.if.org Git - icinga2/commitdiff
Move the notification_interval option to the Notification class.
authorGunnar Beutner <gunnar.beutner@netways.de>
Wed, 20 Mar 2013 09:08:27 +0000 (10:08 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Wed, 20 Mar 2013 09:08:27 +0000 (10:08 +0100)
Fixes #3821

components/compat/compatcomponent.cpp
components/notification/notificationcomponent.cpp
lib/icinga/externalcommandprocessor.cpp
lib/icinga/icinga-type.conf
lib/icinga/notification.cpp
lib/icinga/notification.h
lib/icinga/service-notification.cpp
lib/icinga/service.cpp
lib/icinga/service.h

index 87fcdeeee6c2d3a731f376804bde60df1bf9d4cb..7aa3ee7c6ce630055abf9068b8a5c932d349fe6c 100644 (file)
@@ -316,7 +316,7 @@ void CompatComponent::DumpHostObject(std::ostream& fp, const Host::Ptr& host)
                   << "\t" << "passive_checks_enabled" << "\t" << (hc->GetEnablePassiveChecks() ? 1 : 0) << "\n"
                   << "\t" << "notifications_enabled" << "\t" << (hc->GetEnableNotifications() ? 1 : 0) << "\n"
                   << "\t" << "notification_options" << "\t" << "d,u,r" << "\n"
-                  << "\t" << "notification_interval" << "\t" << hc->GetNotificationInterval() << "\n";
+                  << "\t" << "notification_interval" << "\t" << 1 << "\n";
        } else {
                fp << "\t" << "check_interval" << "\t" << 60 << "\n"
                   << "\t" << "retry_interval" << "\t" << 60 << "\n"
@@ -367,6 +367,12 @@ void CompatComponent::DumpServiceStatusAttrs(std::ostream& fp, const Service::Pt
                        state = 2; /* UNREACHABLE */
        }
 
+       double last_notification = 0;
+       BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
+               if (notification->GetLastNotification() > last_notification)
+                       last_notification = notification->GetLastNotification();
+       }
+
        fp << "\t" << "check_interval=" << service->GetCheckInterval() / 60.0 << "\n"
           << "\t" << "retry_interval=" << service->GetRetryInterval() / 60.0 << "\n"
           << "\t" << "has_been_checked=" << (service->GetLastCheckResult() ? 1 : 0) << "\n"
@@ -391,7 +397,7 @@ void CompatComponent::DumpServiceStatusAttrs(std::ostream& fp, const Service::Pt
           << "\t" << "acknowledgement_type=" << static_cast<int>(service->GetAcknowledgement()) << "\n"
           << "\t" << "acknowledgement_end_time=" << service->GetAcknowledgementExpiry() << "\n"
           << "\t" << "scheduled_downtime_depth=" << (service->IsInDowntime() ? 1 : 0) << "\n"
-          << "\t" << "last_notification=" << service->GetLastNotification() << "\n";
+          << "\t" << "last_notification=" << last_notification << "\n";
 }
 
 void CompatComponent::DumpServiceStatus(std::ostream& fp, const Service::Ptr& service)
@@ -424,6 +430,12 @@ void CompatComponent::DumpServiceObject(std::ostream& fp, const Service::Ptr& se
        if (!host)
                return;
 
+       double notification_interval = -1;
+       BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
+               if (notification_interval == -1 || notification->GetNotificationInterval() < notification_interval)
+                       notification_interval = notification->GetNotificationInterval();
+       }
+
        {
                ObjectLock olock(service);
 
@@ -439,7 +451,7 @@ void CompatComponent::DumpServiceObject(std::ostream& fp, const Service::Ptr& se
                   << "\t" << "passive_checks_enabled" << "\t" << (service->GetEnablePassiveChecks() ? 1 : 0) << "\n"
                   << "\t" << "notifications_enabled" << "\t" << (service->GetEnableNotifications() ? 1 : 0) << "\n"
                   << "\t" << "notification_options" << "\t" << "u,w,c,r" << "\n"
-                  << "\t" << "notification_interval" << "\t" << service->GetNotificationInterval() << "\n"
+                  << "\t" << "notification_interval" << "\t" << notification_interval << "\n"
                   << "\t" << "}" << "\n"
                   << "\n";
        }
index ac0c797724ff4336e30bb6f20d26bf62d64b8b4d..0ea55fe3c2055ebd3385c3c8c18313c5ae062478 100644 (file)
@@ -21,6 +21,7 @@
 #include "icinga/service.h"
 #include "base/dynamictype.h"
 #include "base/objectlock.h"
+#include "base/logger_fwd.h"
 #include <boost/smart_ptr/make_shared.hpp>
 #include <boost/foreach.hpp>
 
@@ -57,7 +58,7 @@ void NotificationComponent::Stop(void)
 }
 
 /**
- * Periodically sends a notification::HelloWorld message.
+ * Periodically sends notifications.
  *
  * @param - Event arguments for the timer.
  */
@@ -65,8 +66,16 @@ void NotificationComponent::NotificationTimerHandler(void)
 {
        double now = Utility::GetTime();
 
-       BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
-               Service::Ptr service = dynamic_pointer_cast<Service>(object);
+       BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Notification")) {
+               Notification::Ptr notification = dynamic_pointer_cast<Notification>(object);
+
+               if (notification->GetNotificationInterval() <= 0)
+                       continue;
+
+               if (notification->GetNextNotification() > now)
+                       continue;
+
+               Service::Ptr service = notification->GetService();
                bool reachable = service->IsReachable();
 
                bool send_notification;
@@ -80,17 +89,25 @@ void NotificationComponent::NotificationTimerHandler(void)
                        if (service->GetState() == StateOK)
                                continue;
 
-                       if (service->GetNotificationInterval() <= 0)
-                               continue;
+                       send_notification = reachable && !service->IsInDowntime() && !service->IsAcknowledged();
+               }
 
-                       if (service->GetLastNotification() > now - service->GetNotificationInterval())
-                               continue;
+               if (!send_notification)
+                       continue;
 
-                       send_notification = reachable && !service->IsInDowntime() && !service->IsAcknowledged();
+               try {
+                       Log(LogInformation, "notification", "Sending reminder notification for service '" + service->GetName() + "'");
+                       notification->BeginExecuteNotification(NotificationProblem, service->GetLastCheckResult());
+               } catch (const std::exception& ex) {
+                       std::ostringstream msgbuf;
+                       msgbuf << "Exception occured during notification for service '"
+                              << GetName() << "': " << boost::diagnostic_information(ex);
+                       String message = msgbuf.str();
+
+                       Log(LogWarning, "icinga", message);
                }
 
-               if (send_notification)
-                       service->RequestNotifications(NotificationProblem, service->GetLastCheckResult());
+               notification->SetNextNotification(Utility::GetTime() + notification->GetNotificationInterval());
        }
 }
 
index d6234d7de5e368589c41792b8ad92b533a571d61..7a2b4834bb5a9245bc20a1d032c12c409cb2f0d1 100644 (file)
@@ -1134,10 +1134,10 @@ void ExternalCommandProcessor::DelayHostNotification(double, const std::vector<S
        if (!hc)
                return;
 
-       {
-               ObjectLock olock(hc);
+       BOOST_FOREACH(const Notification::Ptr& notification, hc->GetNotifications()) {
+               ObjectLock olock(notification);
 
-               hc->SetLastNotification(Convert::ToDouble(arguments[1]));
+               notification->SetNextNotification(Convert::ToDouble(arguments[1]));
        }
 }
 
@@ -1150,10 +1150,10 @@ void ExternalCommandProcessor::DelaySvcNotification(double, const std::vector<St
 
        Log(LogInformation, "icinga", "Delaying notifications for service " + service->GetName());
 
-       {
-               ObjectLock olock(service);
+       BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
+               ObjectLock olock(notification);
 
-               service->SetLastNotification(Convert::ToDouble(arguments[2]));
+               notification->SetNextNotification(Convert::ToDouble(arguments[2]));
        }
 }
 
index 5ce5ad3f7f5ef68fd3bf5129cdd907ed9b039e81..eae1fbffb305e5e1fa5387fd486270bb87f348f4 100644 (file)
@@ -223,7 +223,9 @@ type Notification {
        %attribute array "notification_command" {
                %attribute string "*"
        },
-       %attribute string "notification_command"
+       %attribute string "notification_command",
+
+       %attribute number "notification_interval"
 }
 
 type User {
index 7cc1b1f0c17cd5d4e9f86732636967f55e5d0467..1a56b8c3b2bd0d45df3ebabaad4f6f664b4ac5d1 100644 (file)
@@ -35,6 +35,9 @@ Notification::Notification(const Dictionary::Ptr& serializedUpdate)
        : DynamicObject(serializedUpdate)
 {
        RegisterAttribute("notification_command", Attribute_Config, &m_NotificationCommand);
+       RegisterAttribute("notification_interval", Attribute_Config, &m_NotificationInterval);
+       RegisterAttribute("last_notification", Attribute_Replicated, &m_LastNotification);
+       RegisterAttribute("next_notification", Attribute_Replicated, &m_NextNotification);
        RegisterAttribute("macros", Attribute_Config, &m_Macros);
        RegisterAttribute("users", Attribute_Config, &m_Users);
        RegisterAttribute("groups", Attribute_Config, &m_Groups);
@@ -139,6 +142,58 @@ std::set<UserGroup::Ptr> Notification::GetGroups(void) const
        return result;
 }
 
+/**
+ * @threadsafety Always.
+ */
+double Notification::GetNotificationInterval(void) const
+{
+       if (m_NotificationInterval.IsEmpty())
+               return 300;
+       else
+               return m_NotificationInterval;
+}
+
+/**
+ * @threadsafety Always.
+ */
+double Notification::GetLastNotification(void) const
+{
+       if (m_LastNotification.IsEmpty())
+               return 0;
+       else
+               return m_LastNotification;
+}
+
+/**
+ * Sets the timestamp when the last notification was sent.
+ */
+void Notification::SetLastNotification(double time)
+{
+       m_LastNotification = time;
+       Touch("last_notification");
+}
+
+/**
+ * @threadsafety Always.
+ */
+double Notification::GetNextNotification(void) const
+{
+       if (m_NextNotification.IsEmpty())
+               return 0;
+       else
+               return m_NextNotification;
+}
+
+/**
+ * Sets the timestamp when the next periodical notification should be sent.
+ * This does not affect notifications that are sent for state changes.
+ */
+void Notification::SetNextNotification(double time)
+{
+       m_NextNotification = time;
+       Touch("next_notification");
+}
+
 /**
  * @threadsafety Always.
  */
@@ -171,6 +226,12 @@ void Notification::BeginExecuteNotification(NotificationType type, const Diction
 {
        ASSERT(!OwnsLock());
 
+       {
+               ObjectLock olock(this);
+
+               SetLastNotification(Utility::GetTime());
+       }
+
        Dictionary::Ptr macros = cr->Get("macros");
 
        std::set<User::Ptr> allUsers;
index 151092f5d6b9e0b186de72c6ca097317739aa3cf..256c260e24867f0203443944815cda4a01d544e1 100644 (file)
@@ -64,10 +64,17 @@ public:
 
        shared_ptr<Service> GetService(void) const;
        Value GetNotificationCommand(void) const;
+       double GetNotificationInterval(void) const;
        Dictionary::Ptr GetMacros(void) const;
        std::set<User::Ptr> GetUsers(void) const;
        std::set<UserGroup::Ptr> GetGroups(void) const;
 
+       double GetLastNotification(void) const;
+       void SetLastNotification(double time);
+
+       double GetNextNotification(void) const;
+       void SetNextNotification(double time);
+
        void BeginExecuteNotification(NotificationType type, const Dictionary::Ptr& cr);
 
        static String NotificationTypeToString(NotificationType type);
@@ -77,6 +84,9 @@ protected:
 
 private:
        Attribute<Value> m_NotificationCommand;
+       Attribute<double> m_NotificationInterval;
+       Attribute<double> m_LastNotification;
+       Attribute<double> m_NextNotification;
        Attribute<Dictionary::Ptr> m_Macros;
        Attribute<Array::Ptr> m_Users;
        Attribute<Array::Ptr> m_Groups;
index c7f0d49a76e0227d05d66d869e9936cd25384084..8c169def25b2157b8b3bc315c9b081a102278a39 100644 (file)
@@ -41,11 +41,6 @@ static Timer::Ptr l_NotificationsCacheTimer;
  */
 void Service::RequestNotifications(NotificationType type, const Dictionary::Ptr& cr)
 {
-       {
-               ObjectLock olock(this);
-               SetLastNotification(Utility::GetTime());
-       }
-
        RequestMessage msg;
        msg.SetMethod("icinga::SendNotifications");
 
@@ -250,7 +245,7 @@ void Service::UpdateSlaveNotifications(void)
                                }
                        }
 
-                       /* Clone attributes from the service object. */
+                       /* Clone attributes from the host/service object. */
                        std::set<String, string_iless> keys;
                        keys.insert("users");
                        keys.insert("groups");
@@ -295,26 +290,6 @@ void Service::UpdateSlaveNotifications(void)
        }
 }
 
-/**
- * @threadsafety Always.
- */
-double Service::GetLastNotification(void) const
-{
-       if (m_LastNotification.IsEmpty())
-               return 0;
-       else
-               return m_LastNotification;
-}
-
-/**
- * @threadsafety Always.
- */
-void Service::SetLastNotification(double time)
-{
-       m_LastNotification = time;
-       Touch("last_notification");
-}
-
 /**
  * @threadsafety Always.
  */
@@ -334,14 +309,3 @@ void Service::SetEnableNotifications(bool enabled)
        m_EnableNotifications = enabled;
        Touch("enable_notifications");
 }
-
-/**
- * @threadsafety Always.
- */
-double Service::GetNotificationInterval(void) const
-{
-       if (m_NotificationInterval.IsEmpty())
-               return 300;
-       else
-               return m_NotificationInterval;
-}
index fe1590a71fb35fecde7e92aefbcf2bc87b80e7f3..c1cf433d51c7fdcf3e60dc179a5d12f3b0bf564f 100644 (file)
@@ -75,8 +75,6 @@ Service::Service(const Dictionary::Ptr& serializedObject)
        RegisterAttribute("downtimes", Attribute_Replicated, &m_Downtimes);
 
        RegisterAttribute("enable_notifications", Attribute_Replicated, &m_EnableNotifications);
-       RegisterAttribute("last_notification", Attribute_Replicated, &m_LastNotification);
-       RegisterAttribute("notification_interval", Attribute_Config, &m_NotificationInterval);
 
        SetSchedulingOffset(rand());
 }
index b801081733a17f31763e8b1ea54a409aca824c96..028d58cb524642a7ca1cc2c517cf5511b08f9cf7 100644 (file)
@@ -228,8 +228,6 @@ public:
        bool GetEnableNotifications(void) const;
        void SetEnableNotifications(bool enabled);
 
-       double GetNotificationInterval(void) const;
-
        void RequestNotifications(NotificationType type, const Dictionary::Ptr& cr);
        void SendNotifications(NotificationType type, const Dictionary::Ptr& cr);
 
@@ -239,9 +237,6 @@ public:
 
        void UpdateSlaveNotifications(void);
 
-       double GetLastNotification(void) const;
-       void SetLastNotification(double time);
-
 protected:
        virtual void OnRegistrationCompleted(void);
        virtual void OnAttributeChanged(const String& name);
@@ -310,8 +305,6 @@ private:
 
        /* Notifications */
        Attribute<bool> m_EnableNotifications;
-       Attribute<double> m_LastNotification;
-       Attribute<double> m_NotificationInterval;
 
        static void RefreshNotificationsCache(void);
 };