]> granicus.if.org Git - icinga2/blobdiff - lib/icinga/checkable.cpp
Merge pull request #6577 from Icinga/fix/setup-api-including-users-file
[icinga2] / lib / icinga / checkable.cpp
index fd985e995b171e6474c69b70aa387c1c0f12618d..c577848d59ed34ba93e08ec7be6e5d5f40a7f24b 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  * Icinga 2                                                                   *
- * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
+ * Copyright (C) 2012-2018 Icinga Development Team (https://icinga.com/)      *
  *                                                                            *
  * This program is free software; you can redistribute it and/or              *
  * modify it under the terms of the GNU General Public License                *
  ******************************************************************************/
 
 #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 <boost/foreach.hpp>
-#include <boost/bind/apply.hpp>
 
 using namespace icinga;
 
-REGISTER_TYPE(Checkable);
+REGISTER_TYPE_WITH_PROTOTYPE(Checkable, Checkable::GetPrototype());
+INITIALIZE_ONCE(&Checkable::StaticInitialize);
 
-boost::signals2::signal<void (const Checkable::Ptr&, const String&, const String&, AcknowledgementType, bool, double, const MessageOrigin::Ptr&)> Checkable::OnAcknowledgementSet;
+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;
 
-Checkable::Checkable(void)
-       : m_CheckRunning(false)
+void Checkable::StaticInitialize()
 {
-       SetSchedulingOffset(Utility::Random());
+       /* fixed downtime start */
+       Downtime::OnDowntimeStarted.connect(std::bind(&Checkable::NotifyFixedDowntimeStart, _1));
+       /* flexible downtime start */
+       Downtime::OnDowntimeTriggered.connect(std::bind(&Checkable::NotifyFlexibleDowntimeStart, _1));
+       /* fixed/flexible downtime end */
+       Downtime::OnDowntimeRemoved.connect(std::bind(&Checkable::NotifyDowntimeEnd, _1));
 }
 
-void Checkable::Start(void)
+Checkable::Checkable()
 {
-       double now = Utility::GetTime();
-
-       if (GetNextCheck() < now + 300)
-               UpdateNextCheck();
-
-       ObjectImpl<Checkable>::Start();
+       SetSchedulingOffset(Utility::Random());
 }
 
-void Checkable::OnStateLoaded(void)
+void Checkable::OnAllConfigLoaded()
 {
-       AddDowntimesToCache();
-       AddCommentsToCache();
+       ObjectImpl<Checkable>::OnAllConfigLoaded();
 
-       std::vector<String> ids;
-       Dictionary::Ptr downtimes = GetDowntimes();
+       Endpoint::Ptr endpoint = GetCommandEndpoint();
 
-       {
-               ObjectLock dlock(downtimes);
-               BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
-                       Downtime::Ptr downtime = kv.second;
+       if (endpoint) {
+               Zone::Ptr checkableZone = static_pointer_cast<Zone>(GetZone());
 
-                       if (downtime->GetScheduledBy().IsEmpty())
-                               continue;
+               if (checkableZone) {
+                       Zone::Ptr cmdZone = endpoint->GetZone();
 
-                       ids.push_back(kv.first);
+                       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 not be set."));
                }
        }
+}
 
-       BOOST_FOREACH(const String& id, ids) {
-               /* override config owner to clear downtimes once */
-               Downtime::Ptr downtime = GetDowntimeByID(id);
-               downtime->SetConfigOwner(Empty);
-               RemoveDowntime(id, true);
+void Checkable::Start(bool runtimeCreated)
+{
+       double now = Utility::GetTime();
+
+       if (GetNextCheck() < now + 60) {
+               double delta = std::min(GetCheckInterval(), 60.0);
+               delta *= (double)std::rand() / RAND_MAX;
+               SetNextCheck(now + delta);
        }
+
+       ObjectImpl<Checkable>::Start(runtimeCreated);
 }
 
 void Checkable::AddGroup(const String& name)
@@ -83,7 +89,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();
@@ -99,9 +105,9 @@ void Checkable::AddGroup(const String& name)
        groups->Add(name);
 }
 
-AcknowledgementType Checkable::GetAcknowledgement(void)
+AcknowledgementType Checkable::GetAcknowledgement()
 {
-       AcknowledgementType avalue = static_cast<AcknowledgementType>(GetAcknowledgementRaw());
+       auto avalue = static_cast<AcknowledgementType>(GetAcknowledgementRaw());
 
        if (avalue != AcknowledgementNone) {
                double expiry = GetAcknowledgementExpiry();
@@ -115,20 +121,20 @@ AcknowledgementType Checkable::GetAcknowledgement(void)
        return avalue;
 }
 
-bool Checkable::IsAcknowledged(void)
+bool Checkable::IsAcknowledged() const
 {
-       return GetAcknowledgement() != AcknowledgementNone;
+       return const_cast<Checkable *>(this)->GetAcknowledgement() != AcknowledgementNone;
 }
 
-void Checkable::AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify, double expiry, const MessageOrigin::Ptr& origin)
+void Checkable::AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify, bool persistent, double expiry, const MessageOrigin::Ptr& origin)
 {
        SetAcknowledgementRaw(type);
        SetAcknowledgementExpiry(expiry);
 
-       if (notify)
-               OnNotificationsRequested(this, NotificationAcknowledgement, GetLastCheckResult(), author, comment);
+       if (notify && !IsPaused())
+               OnNotificationsRequested(this, NotificationAcknowledgement, GetLastCheckResult(), author, comment, nullptr);
 
-       OnAcknowledgementSet(this, author, comment, type, notify, expiry, origin);
+       OnAcknowledgementSet(this, author, comment, type, notify, persistent, expiry, origin);
 }
 
 void Checkable::ClearAcknowledgement(const MessageOrigin::Ptr& origin)
@@ -139,15 +145,73 @@ void Checkable::ClearAcknowledgement(const MessageOrigin::Ptr& origin)
        OnAcknowledgementCleared(this, origin);
 }
 
-Endpoint::Ptr Checkable::GetCommandEndpoint(void) const
+Endpoint::Ptr Checkable::GetCommandEndpoint() const
 {
        return Endpoint::GetByName(GetCommandEndpointRaw());
 }
 
-void Checkable::ValidateCheckInterval(double value, const ValidationUtils& utils)
+int Checkable::GetSeverity() const
+{
+       /* overridden in Host/Service class. */
+       return 0;
+}
+
+void Checkable::NotifyFixedDowntimeStart(const Downtime::Ptr& downtime)
+{
+       if (!downtime->GetFixed())
+               return;
+
+       NotifyDowntimeInternal(downtime);
+}
+
+void Checkable::NotifyFlexibleDowntimeStart(const Downtime::Ptr& downtime)
+{
+       if (downtime->GetFixed())
+               return;
+
+       NotifyDowntimeInternal(downtime);
+}
+
+void Checkable::NotifyDowntimeInternal(const Downtime::Ptr& downtime)
+{
+       Checkable::Ptr checkable = downtime->GetCheckable();
+
+       if (!checkable->IsPaused())
+               OnNotificationsRequested(checkable, NotificationDowntimeStart, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
+}
+
+void Checkable::NotifyDowntimeEnd(const Downtime::Ptr& downtime)
+{
+       /* don't send notifications for flexible downtimes which never triggered */
+       if (!downtime->GetFixed() && !downtime->IsTriggered())
+               return;
+
+       Checkable::Ptr checkable = downtime->GetCheckable();
+
+       if (!checkable->IsPaused())
+               OnNotificationsRequested(checkable, NotificationDowntimeEnd, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
+}
+
+void Checkable::ValidateCheckInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
+{
+       ObjectImpl<Checkable>::ValidateCheckInterval(lvalue, utils);
+
+       if (lvalue() <= 0)
+               BOOST_THROW_EXCEPTION(ValidationError(this, { "check_interval" }, "Interval must be greater than 0."));
+}
+
+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>::ValidateCheckInterval(value, utils);
+       ObjectImpl<Checkable>::ValidateMaxCheckAttempts(lvalue, utils);
 
-       if (value <= 0)
-               BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("check_interval"), "Interval must be greater than 0."));
+       if (lvalue() <= 0)
+               BOOST_THROW_EXCEPTION(ValidationError(this, { "max_check_attempts" }, "Value must be greater than 0."));
 }