1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
3 #include "icinga/dependency.hpp"
4 #include "icinga/dependency-ti.cpp"
5 #include "icinga/service.hpp"
6 #include "base/logger.hpp"
7 #include "base/exception.hpp"
9 using namespace icinga;
11 REGISTER_TYPE(Dependency);
13 String DependencyNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
15 Dependency::Ptr dependency = dynamic_pointer_cast<Dependency>(context);
20 String name = dependency->GetChildHostName();
22 if (!dependency->GetChildServiceName().IsEmpty())
23 name += "!" + dependency->GetChildServiceName();
25 name += "!" + shortName;
30 Dictionary::Ptr DependencyNameComposer::ParseName(const String& name) const
32 std::vector<String> tokens = name.Split("!");
34 if (tokens.size() < 2)
35 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid Dependency name."));
37 Dictionary::Ptr result = new Dictionary();
38 result->Set("child_host_name", tokens[0]);
40 if (tokens.size() > 2) {
41 result->Set("child_service_name", tokens[1]);
42 result->Set("name", tokens[2]);
44 result->Set("name", tokens[1]);
50 void Dependency::OnConfigLoaded()
54 if (GetParentServiceName().IsEmpty())
55 defaultFilter = StateFilterUp;
57 defaultFilter = StateFilterOK | StateFilterWarning;
59 SetStateFilter(FilterArrayToInt(GetStates(), Notification::GetStateFilterMap(), defaultFilter));
62 void Dependency::OnAllConfigLoaded()
64 ObjectImpl<Dependency>::OnAllConfigLoaded();
66 Host::Ptr childHost = Host::GetByName(GetChildHostName());
69 if (GetChildServiceName().IsEmpty())
72 m_Child = childHost->GetServiceByShortName(GetChildServiceName());
76 BOOST_THROW_EXCEPTION(ScriptError("Dependency '" + GetName() + "' references a child host/service which doesn't exist.", GetDebugInfo()));
78 m_Child->AddDependency(this);
80 Host::Ptr parentHost = Host::GetByName(GetParentHostName());
83 if (GetParentServiceName().IsEmpty())
84 m_Parent = parentHost;
86 m_Parent = parentHost->GetServiceByShortName(GetParentServiceName());
90 BOOST_THROW_EXCEPTION(ScriptError("Dependency '" + GetName() + "' references a parent host/service which doesn't exist.", GetDebugInfo()));
92 m_Parent->AddReverseDependency(this);
95 void Dependency::Stop(bool runtimeRemoved)
97 ObjectImpl<Dependency>::Stop(runtimeRemoved);
99 GetChild()->RemoveDependency(this);
100 GetParent()->RemoveReverseDependency(this);
103 bool Dependency::IsAvailable(DependencyType dt) const
105 Checkable::Ptr parent = GetParent();
107 Host::Ptr parentHost;
108 Service::Ptr parentService;
109 tie(parentHost, parentService) = GetHostService(parent);
111 /* ignore if it's the same checkable object */
112 if (parent == GetChild()) {
113 Log(LogNotice, "Dependency")
114 << "Dependency '" << GetName() << "' passed: Parent and child " << (parentService ? "service" : "host") << " are identical.";
119 if (!parent->GetLastCheckResult()) {
120 Log(LogNotice, "Dependency")
121 << "Dependency '" << GetName() << "' passed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' hasn't been checked yet.";
125 if (GetIgnoreSoftStates()) {
126 /* ignore soft states */
127 if (parent->GetStateType() == StateTypeSoft) {
128 Log(LogNotice, "Dependency")
129 << "Dependency '" << GetName() << "' passed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' is in a soft state.";
133 Log(LogNotice, "Dependency")
134 << "Dependency '" << GetName() << "' failed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' is in a soft state.";
140 state = ServiceStateToFilter(parentService->GetState());
142 state = HostStateToFilter(parentHost->GetState());
145 if (state & GetStateFilter()) {
146 Log(LogNotice, "Dependency")
147 << "Dependency '" << GetName() << "' passed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' matches state filter.";
151 /* ignore if not in time period */
152 TimePeriod::Ptr tp = GetPeriod();
153 if (tp && !tp->IsInside(Utility::GetTime())) {
154 Log(LogNotice, "Dependency")
155 << "Dependency '" << GetName() << "' passed: Outside time period.";
159 if (dt == DependencyCheckExecution && !GetDisableChecks()) {
160 Log(LogNotice, "Dependency")
161 << "Dependency '" << GetName() << "' passed: Checks are not disabled.";
163 } else if (dt == DependencyNotification && !GetDisableNotifications()) {
164 Log(LogNotice, "Dependency")
165 << "Dependency '" << GetName() << "' passed: Notifications are not disabled";
169 Log(LogNotice, "Dependency")
170 << "Dependency '" << GetName() << "' failed. Parent "
171 << (parentService ? "service" : "host") << " '" << parent->GetName() << "' is "
172 << (parentService ? Service::StateToString(parentService->GetState()) : Host::StateToString(parentHost->GetState()));
177 Checkable::Ptr Dependency::GetChild() const
182 Checkable::Ptr Dependency::GetParent() const
187 TimePeriod::Ptr Dependency::GetPeriod() const
189 return TimePeriod::GetByName(GetPeriodRaw());
192 void Dependency::ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
194 ObjectImpl<Dependency>::ValidateStates(lvalue, utils);
196 int sfilter = FilterArrayToInt(lvalue(), Notification::GetStateFilterMap(), 0);
198 if (GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0)
199 BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid for host dependency."));
201 if (!GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0)
202 BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid for service dependency."));