1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2 
3 #include "remote/zone.hpp"
4 #include "remote/apilistener.hpp"
5 #include "base/configtype.hpp"
6 #include "base/utility.hpp"
7 #include "base/convert.hpp"
8 
9 using namespace icinga;
10 
11 std::atomic<bool> ApiListener::m_UpdatedObjectAuthority (false);
12 
UpdateObjectAuthority()13 void ApiListener::UpdateObjectAuthority()
14 {
15 	/* Always run this, even if there is no 'api' feature enabled. */
16 	if (auto listener = ApiListener::GetInstance()) {
17 		Log(LogNotice, "ApiListener")
18 			<< "Updating object authority for objects at endpoint '" << listener->GetIdentity() << "'.";
19 	} else {
20 		Log(LogNotice, "ApiListener")
21 			<< "Updating object authority for local objects.";
22 	}
23 
24 	Zone::Ptr my_zone = Zone::GetLocalZone();
25 
26 	std::vector<Endpoint::Ptr> endpoints;
27 	Endpoint::Ptr my_endpoint;
28 
29 	if (my_zone) {
30 		my_endpoint = Endpoint::GetLocalEndpoint();
31 
32 		int num_total = 0;
33 
34 		for (const Endpoint::Ptr& endpoint : my_zone->GetEndpoints()) {
35 			num_total++;
36 
37 			if (endpoint != my_endpoint && !endpoint->GetConnected())
38 				continue;
39 
40 			endpoints.push_back(endpoint);
41 		}
42 
43 		double startTime = Application::GetStartTime();
44 
45 		/* 30 seconds cold startup, don't update any authority to give the secondary endpoint time to reconnect. */
46 		if (num_total > 1 && endpoints.size() <= 1 && (startTime == 0 || Utility::GetTime() - startTime < 30))
47 			return;
48 
49 		std::sort(endpoints.begin(), endpoints.end(),
50 			[](const ConfigObject::Ptr& a, const ConfigObject::Ptr& b) {
51 				return a->GetName() < b->GetName();
52 			}
53 		);
54 	}
55 
56 	for (const Type::Ptr& type : Type::GetAllTypes()) {
57 		auto *dtype = dynamic_cast<ConfigType *>(type.get());
58 
59 		if (!dtype)
60 			continue;
61 
62 		for (const ConfigObject::Ptr& object : dtype->GetObjects()) {
63 			if (!object->IsActive() || object->GetHAMode() != HARunOnce)
64 				continue;
65 
66 			bool authority;
67 
68 			if (!my_zone)
69 				authority = true;
70 			else
71 				authority = endpoints[Utility::SDBM(object->GetName()) % endpoints.size()] == my_endpoint;
72 
73 #ifdef I2_DEBUG
74 // 			//Enable on demand, causes heavy logging on each run.
75 //			Log(LogDebug, "ApiListener")
76 //				<< "Setting authority '" << Convert::ToString(authority) << "' for object '" << object->GetName() << "' of type '" << object->GetReflectionType()->GetName() << "'.";
77 #endif /* I2_DEBUG */
78 
79 			object->SetAuthority(authority);
80 		}
81 	}
82 
83 	m_UpdatedObjectAuthority.store(true);
84 }
85