/******************************************************************************
* 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)
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();
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();
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)
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."));
}