1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2 
3 #include "remote/zone.hpp"
4 #include "remote/zone-ti.cpp"
5 #include "remote/jsonrpcconnection.hpp"
6 #include "base/array.hpp"
7 #include "base/objectlock.hpp"
8 #include "base/logger.hpp"
9 
10 using namespace icinga;
11 
12 REGISTER_TYPE(Zone);
13 
OnAllConfigLoaded()14 void Zone::OnAllConfigLoaded()
15 {
16 	ObjectImpl<Zone>::OnAllConfigLoaded();
17 
18 	m_Parent = Zone::GetByName(GetParentRaw());
19 
20 	if (m_Parent && m_Parent->IsGlobal())
21 		BOOST_THROW_EXCEPTION(ScriptError("Zone '" + GetName() + "' can not have a global zone as parent.", GetDebugInfo()));
22 
23 	Zone::Ptr zone = m_Parent;
24 	int levels = 0;
25 
26 	Array::Ptr endpoints = GetEndpointsRaw();
27 
28 	if (endpoints) {
29 		ObjectLock olock(endpoints);
30 		for (const String& endpoint : endpoints) {
31 			Endpoint::Ptr ep = Endpoint::GetByName(endpoint);
32 
33 			if (ep)
34 				ep->SetCachedZone(this);
35 		}
36 	}
37 
38 	while (zone) {
39 		m_AllParents.push_back(zone);
40 
41 		zone = Zone::GetByName(zone->GetParentRaw());
42 		levels++;
43 
44 		if (levels > 32)
45 			BOOST_THROW_EXCEPTION(ScriptError("Infinite recursion detected while resolving zone graph. Check your zone hierarchy.", GetDebugInfo()));
46 	}
47 }
48 
GetParent() const49 Zone::Ptr Zone::GetParent() const
50 {
51 	return m_Parent;
52 }
53 
GetEndpoints() const54 std::set<Endpoint::Ptr> Zone::GetEndpoints() const
55 {
56 	std::set<Endpoint::Ptr> result;
57 
58 	Array::Ptr endpoints = GetEndpointsRaw();
59 
60 	if (endpoints) {
61 		ObjectLock olock(endpoints);
62 
63 		for (const String& name : endpoints) {
64 			Endpoint::Ptr endpoint = Endpoint::GetByName(name);
65 
66 			if (!endpoint)
67 				continue;
68 
69 			result.insert(endpoint);
70 		}
71 	}
72 
73 	return result;
74 }
75 
GetAllParentsRaw() const76 std::vector<Zone::Ptr> Zone::GetAllParentsRaw() const
77 {
78 	return m_AllParents;
79 }
80 
GetAllParents() const81 Array::Ptr Zone::GetAllParents() const
82 {
83 	auto result (new Array);
84 
85 	for (auto& parent : m_AllParents)
86 		result->Add(parent->GetName());
87 
88 	return result;
89 }
90 
CanAccessObject(const ConfigObject::Ptr & object)91 bool Zone::CanAccessObject(const ConfigObject::Ptr& object)
92 {
93 	Zone::Ptr object_zone;
94 
95 	if (object->GetReflectionType() == Zone::TypeInstance)
96 		object_zone = static_pointer_cast<Zone>(object);
97 	else
98 		object_zone = static_pointer_cast<Zone>(object->GetZone());
99 
100 	if (!object_zone)
101 		object_zone = Zone::GetLocalZone();
102 
103 	if (object_zone->GetGlobal())
104 		return true;
105 
106 	return object_zone->IsChildOf(this);
107 }
108 
IsChildOf(const Zone::Ptr & zone)109 bool Zone::IsChildOf(const Zone::Ptr& zone)
110 {
111 	Zone::Ptr azone = this;
112 
113 	while (azone) {
114 		if (azone == zone)
115 			return true;
116 
117 		azone = azone->GetParent();
118 	}
119 
120 	return false;
121 }
122 
IsGlobal() const123 bool Zone::IsGlobal() const
124 {
125 	return GetGlobal();
126 }
127 
IsSingleInstance() const128 bool Zone::IsSingleInstance() const
129 {
130 	Array::Ptr endpoints = GetEndpointsRaw();
131 	return !endpoints || endpoints->GetLength() < 2;
132 }
133 
GetLocalZone()134 Zone::Ptr Zone::GetLocalZone()
135 {
136 	Endpoint::Ptr local = Endpoint::GetLocalEndpoint();
137 
138 	if (!local)
139 		return nullptr;
140 
141 	return local->GetZone();
142 }
143 
ValidateEndpointsRaw(const Lazy<Array::Ptr> & lvalue,const ValidationUtils & utils)144 void Zone::ValidateEndpointsRaw(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
145 {
146 	ObjectImpl<Zone>::ValidateEndpointsRaw(lvalue, utils);
147 
148 	if (lvalue() && lvalue()->GetLength() > 2) {
149 		Log(LogWarning, "Zone")
150 			<< "The Zone object '" << GetName() << "' has more than two endpoints."
151 			<< " Due to a known issue this type of configuration is strongly"
152 			<< " discouraged and may cause Icinga to use excessive amounts of CPU time.";
153 	}
154 }
155