/****************************************************************************** * 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. * ******************************************************************************/ #include "icinga/checkable.hpp" #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" using namespace icinga; REGISTER_TYPE_WITH_PROTOTYPE(Checkable, Checkable::GetPrototype()); INITIALIZE_ONCE(&Checkable::StaticInitialize); boost::signals2::signal Checkable::OnAcknowledgementSet; boost::signals2::signal Checkable::OnAcknowledgementCleared; void Checkable::StaticInitialize() { /* 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)); } Checkable::Checkable() { SetSchedulingOffset(Utility::Random()); } void Checkable::OnAllConfigLoaded() { ObjectImpl::OnAllConfigLoaded(); Endpoint::Ptr endpoint = GetCommandEndpoint(); if (endpoint) { Zone::Ptr checkableZone = static_pointer_cast(GetZone()); if (!checkableZone) checkableZone = Zone::GetLocalZone(); Zone::Ptr cmdZone = endpoint->GetZone(); if (checkableZone && 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.")); } } } void Checkable::Start(bool runtimeCreated) { double now = Utility::GetTime(); if (GetNextCheck() < now + 300) UpdateNextCheck(); ObjectImpl::Start(runtimeCreated); } void Checkable::AddGroup(const String& name) { boost::mutex::scoped_lock lock(m_CheckableMutex); Array::Ptr groups; auto *host = dynamic_cast(this); if (host) groups = host->GetGroups(); else groups = static_cast(this)->GetGroups(); if (groups && groups->Contains(name)) return; if (!groups) groups = new Array(); groups->Add(name); } AcknowledgementType Checkable::GetAcknowledgement() { auto avalue = static_cast(GetAcknowledgementRaw()); if (avalue != AcknowledgementNone) { double expiry = GetAcknowledgementExpiry(); if (expiry != 0 && expiry < Utility::GetTime()) { avalue = AcknowledgementNone; ClearAcknowledgement(); } } return avalue; } bool Checkable::IsAcknowledged() const { return const_cast(this)->GetAcknowledgement() != AcknowledgementNone; } 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 && !IsPaused()) OnNotificationsRequested(this, NotificationAcknowledgement, GetLastCheckResult(), author, comment, nullptr); OnAcknowledgementSet(this, author, comment, type, notify, persistent, expiry, origin); } void Checkable::ClearAcknowledgement(const MessageOrigin::Ptr& origin) { SetAcknowledgementRaw(AcknowledgementNone); SetAcknowledgementExpiry(0); OnAcknowledgementCleared(this, origin); } Endpoint::Ptr Checkable::GetCommandEndpoint() const { return Endpoint::GetByName(GetCommandEndpointRaw()); } 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& lvalue, const ValidationUtils& utils) { ObjectImpl::ValidateCheckInterval(lvalue, utils); if (lvalue() <= 0) BOOST_THROW_EXCEPTION(ValidationError(this, { "check_interval" }, "Interval must be greater than 0.")); } void Checkable::ValidateMaxCheckAttempts(const Lazy& lvalue, const ValidationUtils& utils) { ObjectImpl::ValidateMaxCheckAttempts(lvalue, utils); if (lvalue() <= 0) BOOST_THROW_EXCEPTION(ValidationError(this, { "max_check_attempts" }, "Value must be greater than 0.")); }