mirror of
				https://github.com/Icinga/icinga2.git
				synced 2025-11-04 05:34:12 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			225 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/******************************************************************************
 | 
						|
 * 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/dependency.hpp"
 | 
						|
#include "icinga/dependency.tcpp"
 | 
						|
#include "icinga/service.hpp"
 | 
						|
#include "base/logger.hpp"
 | 
						|
#include "base/exception.hpp"
 | 
						|
#include <boost/algorithm/string/split.hpp>
 | 
						|
#include <boost/algorithm/string/classification.hpp>
 | 
						|
 | 
						|
using namespace icinga;
 | 
						|
 | 
						|
REGISTER_TYPE(Dependency);
 | 
						|
 | 
						|
String DependencyNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
 | 
						|
{
 | 
						|
	Dependency::Ptr dependency = dynamic_pointer_cast<Dependency>(context);
 | 
						|
 | 
						|
	if (!dependency)
 | 
						|
		return "";
 | 
						|
 | 
						|
	String name = dependency->GetChildHostName();
 | 
						|
 | 
						|
	if (!dependency->GetChildServiceName().IsEmpty())
 | 
						|
		name += "!" + dependency->GetChildServiceName();
 | 
						|
 | 
						|
	name += "!" + shortName;
 | 
						|
 | 
						|
	return name;
 | 
						|
}
 | 
						|
 | 
						|
Dictionary::Ptr DependencyNameComposer::ParseName(const String& name) const
 | 
						|
{
 | 
						|
	std::vector<String> tokens;
 | 
						|
	boost::algorithm::split(tokens, name, boost::is_any_of("!"));
 | 
						|
 | 
						|
	if (tokens.size() < 2)
 | 
						|
		BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid Dependency name."));
 | 
						|
 | 
						|
	Dictionary::Ptr result = new Dictionary();
 | 
						|
	result->Set("child_host_name", tokens[0]);
 | 
						|
 | 
						|
	if (tokens.size() > 2) {
 | 
						|
		result->Set("child_service_name", tokens[1]);
 | 
						|
		result->Set("name", tokens[2]);
 | 
						|
	} else {
 | 
						|
		result->Set("name", tokens[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
void Dependency::OnConfigLoaded()
 | 
						|
{
 | 
						|
	Value defaultFilter;
 | 
						|
 | 
						|
	if (GetParentServiceName().IsEmpty())
 | 
						|
		defaultFilter = StateFilterUp;
 | 
						|
	else
 | 
						|
		defaultFilter = StateFilterOK | StateFilterWarning;
 | 
						|
 | 
						|
	SetStateFilter(FilterArrayToInt(GetStates(), Notification::GetStateFilterMap(), defaultFilter));
 | 
						|
}
 | 
						|
 | 
						|
void Dependency::OnAllConfigLoaded()
 | 
						|
{
 | 
						|
	ObjectImpl<Dependency>::OnAllConfigLoaded();
 | 
						|
 | 
						|
	Host::Ptr childHost = Host::GetByName(GetChildHostName());
 | 
						|
 | 
						|
	if (childHost) {
 | 
						|
		if (GetChildServiceName().IsEmpty())
 | 
						|
			m_Child = childHost;
 | 
						|
		else
 | 
						|
			m_Child = childHost->GetServiceByShortName(GetChildServiceName());
 | 
						|
	}
 | 
						|
 | 
						|
	if (!m_Child)
 | 
						|
		BOOST_THROW_EXCEPTION(ScriptError("Dependency '" + GetName() + "' references a child host/service which doesn't exist.", GetDebugInfo()));
 | 
						|
 | 
						|
	m_Child->AddDependency(this);
 | 
						|
 | 
						|
	Host::Ptr parentHost = Host::GetByName(GetParentHostName());
 | 
						|
 | 
						|
	if (parentHost) {
 | 
						|
		if (GetParentServiceName().IsEmpty())
 | 
						|
			m_Parent = parentHost;
 | 
						|
		else
 | 
						|
			m_Parent = parentHost->GetServiceByShortName(GetParentServiceName());
 | 
						|
	}
 | 
						|
 | 
						|
	if (!m_Parent)
 | 
						|
		BOOST_THROW_EXCEPTION(ScriptError("Dependency '" + GetName() + "' references a parent host/service which doesn't exist.", GetDebugInfo()));
 | 
						|
 | 
						|
	m_Parent->AddReverseDependency(this);
 | 
						|
}
 | 
						|
 | 
						|
void Dependency::Stop(bool runtimeRemoved)
 | 
						|
{
 | 
						|
	ObjectImpl<Dependency>::Stop(runtimeRemoved);
 | 
						|
 | 
						|
	GetChild()->RemoveDependency(this);
 | 
						|
	GetParent()->RemoveReverseDependency(this);
 | 
						|
}
 | 
						|
 | 
						|
bool Dependency::IsAvailable(DependencyType dt) const
 | 
						|
{
 | 
						|
	Checkable::Ptr parent = GetParent();
 | 
						|
 | 
						|
	Host::Ptr parentHost;
 | 
						|
	Service::Ptr parentService;
 | 
						|
	tie(parentHost, parentService) = GetHostService(parent);
 | 
						|
 | 
						|
	/* ignore if it's the same checkable object */
 | 
						|
	if (parent == GetChild()) {
 | 
						|
		Log(LogNotice, "Dependency")
 | 
						|
			<< "Dependency '" << GetName() << "' passed: Parent and child " << (parentService ? "service" : "host") << " are identical.";
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	/* ignore pending  */
 | 
						|
	if (!parent->GetLastCheckResult()) {
 | 
						|
		Log(LogNotice, "Dependency")
 | 
						|
			<< "Dependency '" << GetName() << "' passed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' hasn't been checked yet.";
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	if (GetIgnoreSoftStates()) {
 | 
						|
		/* ignore soft states */
 | 
						|
		if (parent->GetStateType() == StateTypeSoft) {
 | 
						|
			Log(LogNotice, "Dependency")
 | 
						|
				<< "Dependency '" << GetName() << "' passed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' is in a soft state.";
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		Log(LogNotice, "Dependency")
 | 
						|
			<< "Dependency '" << GetName() << "' failed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' is in a soft state.";
 | 
						|
	}
 | 
						|
 | 
						|
	int state;
 | 
						|
 | 
						|
	if (parentService)
 | 
						|
		state = ServiceStateToFilter(parentService->GetState());
 | 
						|
	else
 | 
						|
		state = HostStateToFilter(parentHost->GetState());
 | 
						|
 | 
						|
	/* check state */
 | 
						|
	if (state & GetStateFilter()) {
 | 
						|
		Log(LogNotice, "Dependency")
 | 
						|
			<< "Dependency '" << GetName() << "' passed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' matches state filter.";
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	/* ignore if not in time period */
 | 
						|
	TimePeriod::Ptr tp = GetPeriod();
 | 
						|
	if (tp && !tp->IsInside(Utility::GetTime())) {
 | 
						|
		Log(LogNotice, "Dependency")
 | 
						|
			<< "Dependency '" << GetName() << "' passed: Outside time period.";
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	if (dt == DependencyCheckExecution && !GetDisableChecks()) {
 | 
						|
		Log(LogNotice, "Dependency")
 | 
						|
			<< "Dependency '" << GetName() << "' passed: Checks are not disabled.";
 | 
						|
		return true;
 | 
						|
	} else if (dt == DependencyNotification && !GetDisableNotifications()) {
 | 
						|
		Log(LogNotice, "Dependency")
 | 
						|
			<< "Dependency '" << GetName() << "' passed: Notifications are not disabled";
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	Log(LogNotice, "Dependency")
 | 
						|
		<< "Dependency '" << GetName() << "' failed. Parent "
 | 
						|
		<< (parentService ? "service" : "host") << " '" << parent->GetName() << "' is "
 | 
						|
		<< (parentService ? Service::StateToString(parentService->GetState()) : Host::StateToString(parentHost->GetState()));
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
Checkable::Ptr Dependency::GetChild() const
 | 
						|
{
 | 
						|
	return m_Child;
 | 
						|
}
 | 
						|
 | 
						|
Checkable::Ptr Dependency::GetParent() const
 | 
						|
{
 | 
						|
	return m_Parent;
 | 
						|
}
 | 
						|
 | 
						|
TimePeriod::Ptr Dependency::GetPeriod() const
 | 
						|
{
 | 
						|
	return TimePeriod::GetByName(GetPeriodRaw());
 | 
						|
}
 | 
						|
 | 
						|
void Dependency::ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
 | 
						|
{
 | 
						|
	ObjectImpl<Dependency>::ValidateStates(lvalue, utils);
 | 
						|
 | 
						|
	int sfilter = FilterArrayToInt(lvalue(), Notification::GetStateFilterMap(), 0);
 | 
						|
 | 
						|
	if (GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0)
 | 
						|
		BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid for host dependency."));
 | 
						|
 | 
						|
	if (!GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0)
 | 
						|
		BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid for service dependency."));
 | 
						|
}
 | 
						|
 |