]> granicus.if.org Git - icinga2/blobdiff - lib/icinga/checkable.cpp
Re-send suppressed notifications
[icinga2] / lib / icinga / checkable.cpp
index 8494e2c89b9e7dbac3c32d83bdd09f64db7c39ee..c4265d05f266ecb766577e6da45bc24488d7f9c1 100644 (file)
@@ -1,29 +1,14 @@
-/******************************************************************************
- * Icinga 2                                                                   *
- * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/)  *
- *                                                                            *
- * 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.             *
- ******************************************************************************/
+/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
 
 #include "icinga/checkable.hpp"
-#include "icinga/checkable.tcpp"
+#include "icinga/checkable-ti.cpp"
 #include "icinga/host.hpp"
 #include "icinga/service.hpp"
 #include "base/objectlock.hpp"
 #include "base/utility.hpp"
 #include "base/exception.hpp"
+#include "base/timer.hpp"
+#include <boost/thread/once.hpp>
 
 using namespace icinga;
 
@@ -33,6 +18,8 @@ INITIALIZE_ONCE(&Checkable::StaticInitialize);
 boost::signals2::signal<void (const Checkable::Ptr&, const String&, const String&, AcknowledgementType, bool, bool, double, const MessageOrigin::Ptr&)> Checkable::OnAcknowledgementSet;
 boost::signals2::signal<void (const Checkable::Ptr&, const MessageOrigin::Ptr&)> Checkable::OnAcknowledgementCleared;
 
+static Timer::Ptr l_CheckablesFireSuppressedNotifications;
+
 void Checkable::StaticInitialize()
 {
        /* fixed downtime start */
@@ -44,7 +31,6 @@ void Checkable::StaticInitialize()
 }
 
 Checkable::Checkable()
-       : m_CheckRunning(false)
 {
        SetSchedulingOffset(Utility::Random());
 }
@@ -58,14 +44,16 @@ void Checkable::OnAllConfigLoaded()
        if (endpoint) {
                Zone::Ptr checkableZone = static_pointer_cast<Zone>(GetZone());
 
-               if (!checkableZone)
-                       checkableZone = Zone::GetLocalZone();
-
-               Zone::Ptr cmdZone = endpoint->GetZone();
+               if (checkableZone) {
+                       Zone::Ptr cmdZone = endpoint->GetZone();
 
-               if (checkableZone && cmdZone != checkableZone && cmdZone->GetParent() != checkableZone) {
+                       if (cmdZone != checkableZone && cmdZone->GetParent() != checkableZone) {
+                               BOOST_THROW_EXCEPTION(ValidationError(this, { "command_endpoint" },
+                                       "Command endpoint must be in zone '" + checkableZone->GetName() + "' or in a direct child zone thereof."));
+                       }
+               } else {
                        BOOST_THROW_EXCEPTION(ValidationError(this, { "command_endpoint" },
-                               "Command endpoint must be in zone '" + checkableZone->GetName() + "' or in a direct child zone thereof."));
+                               "Command endpoint must not be set."));
                }
        }
 }
@@ -74,10 +62,22 @@ void Checkable::Start(bool runtimeCreated)
 {
        double now = Utility::GetTime();
 
-       if (GetNextCheck() < now + 300)
-               UpdateNextCheck();
+       if (GetNextCheck() < now + 60) {
+               double delta = std::min(GetCheckInterval(), 60.0);
+               delta *= (double)std::rand() / RAND_MAX;
+               SetNextCheck(now + delta);
+       }
 
        ObjectImpl<Checkable>::Start(runtimeCreated);
+
+       static boost::once_flag once = BOOST_ONCE_INIT;
+
+       boost::call_once(once, []() {
+               l_CheckablesFireSuppressedNotifications = new Timer();
+               l_CheckablesFireSuppressedNotifications->SetInterval(5);
+               l_CheckablesFireSuppressedNotifications->OnTimerExpired.connect(&Checkable::FireSuppressedNotifications);
+               l_CheckablesFireSuppressedNotifications->Start();
+       });
 }
 
 void Checkable::AddGroup(const String& name)
@@ -85,7 +85,7 @@ void Checkable::AddGroup(const String& name)
        boost::mutex::scoped_lock lock(m_CheckableMutex);
 
        Array::Ptr groups;
-       Host *host = dynamic_cast<Host *>(this);
+       auto *host = dynamic_cast<Host *>(this);
 
        if (host)
                groups = host->GetGroups();
@@ -103,7 +103,7 @@ void Checkable::AddGroup(const String& name)
 
 AcknowledgementType Checkable::GetAcknowledgement()
 {
-       AcknowledgementType avalue = static_cast<AcknowledgementType>(GetAcknowledgementRaw());
+       auto avalue = static_cast<AcknowledgementType>(GetAcknowledgementRaw());
 
        if (avalue != AcknowledgementNone) {
                double expiry = GetAcknowledgementExpiry();
@@ -152,6 +152,16 @@ int Checkable::GetSeverity() const
        return 0;
 }
 
+bool Checkable::GetProblem() const
+{
+       return !IsStateOK(GetStateRaw());
+}
+
+bool Checkable::GetHandled() const
+{
+       return GetProblem() && (IsInDowntime() || IsAcknowledged());
+}
+
 void Checkable::NotifyFixedDowntimeStart(const Downtime::Ptr& downtime)
 {
        if (!downtime->GetFixed())
@@ -188,18 +198,26 @@ void Checkable::NotifyDowntimeEnd(const Downtime::Ptr& downtime)
                OnNotificationsRequested(checkable, NotificationDowntimeEnd, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
 }
 
-void Checkable::ValidateCheckInterval(double value, const ValidationUtils& utils)
+void Checkable::ValidateCheckInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Checkable>::ValidateCheckInterval(value, utils);
+       ObjectImpl<Checkable>::ValidateCheckInterval(lvalue, utils);
 
-       if (value <= 0)
+       if (lvalue() <= 0)
                BOOST_THROW_EXCEPTION(ValidationError(this, { "check_interval" }, "Interval must be greater than 0."));
 }
 
-void Checkable::ValidateMaxCheckAttempts(int value, const ValidationUtils& utils)
+void Checkable::ValidateRetryInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
+{
+       ObjectImpl<Checkable>::ValidateRetryInterval(lvalue, utils);
+
+       if (lvalue() <= 0)
+               BOOST_THROW_EXCEPTION(ValidationError(this, { "retry_interval" }, "Interval must be greater than 0."));
+}
+
+void Checkable::ValidateMaxCheckAttempts(const Lazy<int>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Checkable>::ValidateMaxCheckAttempts(value, utils);
+       ObjectImpl<Checkable>::ValidateMaxCheckAttempts(lvalue, utils);
 
-       if (value <= 0)
+       if (lvalue() <= 0)
                BOOST_THROW_EXCEPTION(ValidationError(this, { "max_check_attempts" }, "Value must be greater than 0."));
 }