mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-23 13:45:04 +02:00
Merge pull request #8218 from efuss/redundancy_group
Introduce redundancy groups for Dependency Objects
This commit is contained in:
commit
50018c1d2b
@ -2738,6 +2738,27 @@ apply Dependency "internet" to Service {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Redundancy Groups <a id="dependencies-redundancy-groups"></a>
|
||||||
|
|
||||||
|
Sometimes you want dependencies to accumulate,
|
||||||
|
i.e. to consider the parent reachable only if no dependency is violated.
|
||||||
|
Sometimes you want them to be regarded as redundant,
|
||||||
|
i.e. to consider the parent unreachable only if no dependency is fulfilled.
|
||||||
|
Think of a host connected to both a network and a storage switch vs. a host connected to redundant routers.
|
||||||
|
|
||||||
|
Sometimes you even want a mixture of both.
|
||||||
|
Think of a service like SSH depeding on both LDAP and DNS to function,
|
||||||
|
while operating redundant LDAP servers as well as redundant DNS resolvers.
|
||||||
|
|
||||||
|
Before v2.12, Icinga regarded all dependecies as cumulative.
|
||||||
|
In v2.12 and v2.13, Icinga regarded all dependencies redundant.
|
||||||
|
The latter led to unrelated services being inadvertantly regarded to be redundant to each other.
|
||||||
|
|
||||||
|
v2.14 restored the former behavior and allowed to override it.
|
||||||
|
I.e. all dependecies are regarded as essential for the parent by default.
|
||||||
|
Specifying the `redundancy_group` attribute for two dependecies of a child object with the equal value
|
||||||
|
causes them to be regarded as redundant (only inside that redundancy group).
|
||||||
|
|
||||||
<!-- Keep this for compatibility -->
|
<!-- Keep this for compatibility -->
|
||||||
<a id="dependencies-apply-custom-attríbutes"></a>
|
<a id="dependencies-apply-custom-attríbutes"></a>
|
||||||
|
|
||||||
|
@ -201,6 +201,7 @@ Configuration Attributes:
|
|||||||
parent\_service\_name | Object name | **Optional.** The parent service. If omitted, this dependency object is treated as host dependency.
|
parent\_service\_name | Object name | **Optional.** The parent service. If omitted, this dependency object is treated as host dependency.
|
||||||
child\_host\_name | Object name | **Required.** The child host.
|
child\_host\_name | Object name | **Required.** The child host.
|
||||||
child\_service\_name | Object name | **Optional.** The child service. If omitted, this dependency object is treated as host dependency.
|
child\_service\_name | Object name | **Optional.** The child service. If omitted, this dependency object is treated as host dependency.
|
||||||
|
redundancy\_group | String | **Optional.** Puts the dependency into a group of [mutually redundant ones](03-monitoring-basics.md#dependencies-redundancy-groups).
|
||||||
disable\_checks | Boolean | **Optional.** Whether to disable checks (i.e., don't schedule active checks and drop passive results) when this dependency fails. Defaults to false.
|
disable\_checks | Boolean | **Optional.** Whether to disable checks (i.e., don't schedule active checks and drop passive results) when this dependency fails. Defaults to false.
|
||||||
disable\_notifications | Boolean | **Optional.** Whether to disable notifications when this dependency fails. Defaults to true.
|
disable\_notifications | Boolean | **Optional.** Whether to disable notifications when this dependency fails. Defaults to true.
|
||||||
ignore\_soft\_states | Boolean | **Optional.** Whether to ignore soft states for the reachability calculation. Defaults to true.
|
ignore\_soft\_states | Boolean | **Optional.** Whether to ignore soft states for the reachability calculation. Defaults to true.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "icinga/service.hpp"
|
#include "icinga/service.hpp"
|
||||||
#include "icinga/dependency.hpp"
|
#include "icinga/dependency.hpp"
|
||||||
#include "base/logger.hpp"
|
#include "base/logger.hpp"
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
@ -74,25 +75,42 @@ bool Checkable::IsReachable(DependencyType dt, Dependency::Ptr *failedDependency
|
|||||||
|
|
||||||
auto deps = GetDependencies();
|
auto deps = GetDependencies();
|
||||||
|
|
||||||
int countDeps = deps.size();
|
std::unordered_map<std::string, Dependency::Ptr> violated; // key: redundancy group, value: nullptr if satisfied, violating dependency otherwise
|
||||||
int countFailed = 0;
|
|
||||||
|
|
||||||
for (const Dependency::Ptr& dep : deps) {
|
for (const Dependency::Ptr& dep : deps) {
|
||||||
if (!dep->IsAvailable(dt)) {
|
std::string redundancy_group = dep->GetRedundancyGroup();
|
||||||
countFailed++;
|
|
||||||
|
|
||||||
if (failedDependency)
|
if (!dep->IsAvailable(dt)) {
|
||||||
*failedDependency = dep;
|
if (redundancy_group.empty()) {
|
||||||
|
Log(LogDebug, "Checkable")
|
||||||
|
<< "Non-redundant dependency '" << dep->GetName() << "' failed for checkable '" << GetName() << "': Marking as unreachable.";
|
||||||
|
|
||||||
|
if (failedDependency)
|
||||||
|
*failedDependency = dep;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tentatively mark this dependency group as failed unless it is already marked;
|
||||||
|
// so it either passed before (don't overwrite) or already failed (so don't care)
|
||||||
|
// note that std::unordered_map::insert() will not overwrite an existing entry
|
||||||
|
violated.insert(std::make_pair(redundancy_group, dep));
|
||||||
|
} else if (!redundancy_group.empty()) {
|
||||||
|
violated[redundancy_group] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there are dependencies, and all of them failed, mark as unreachable. */
|
auto violator = std::find_if(violated.begin(), violated.end(), [](auto& v) { return v.second != nullptr; });
|
||||||
if (countDeps > 0 && countFailed == countDeps) {
|
if (violator != violated.end()) {
|
||||||
Log(LogDebug, "Checkable")
|
Log(LogDebug, "Checkable")
|
||||||
<< "All dependencies have failed for checkable '" << GetName() << "': Marking as unreachable.";
|
<< "All dependencies in redundancy group '" << violator->first << "' have failed for checkable '" << GetName() << "': Marking as unreachable.";
|
||||||
|
|
||||||
|
if (failedDependency)
|
||||||
|
*failedDependency = violator->second;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failedDependency)
|
if (failedDependency)
|
||||||
*failedDependency = nullptr;
|
*failedDependency = nullptr;
|
||||||
|
|
||||||
|
@ -77,6 +77,8 @@ class Dependency : CustomVarObject < DependencyNameComposer
|
|||||||
}}}
|
}}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[config] String redundancy_group;
|
||||||
|
|
||||||
[config, navigation] name(TimePeriod) period (PeriodRaw) {
|
[config, navigation] name(TimePeriod) period (PeriodRaw) {
|
||||||
navigate {{{
|
navigate {{{
|
||||||
return TimePeriod::GetByName(GetPeriodRaw());
|
return TimePeriod::GetByName(GetPeriodRaw());
|
||||||
|
@ -70,14 +70,26 @@ BOOST_AUTO_TEST_CASE(multi_parent)
|
|||||||
|
|
||||||
/* Test the reachability from this point.
|
/* Test the reachability from this point.
|
||||||
* parentHost1 is DOWN, parentHost2 is UP.
|
* parentHost1 is DOWN, parentHost2 is UP.
|
||||||
* Expected result: childHost is reachable.
|
* Expected result: childHost is unreachable.
|
||||||
*/
|
*/
|
||||||
parentHost1->SetStateRaw(ServiceCritical); // parent Host 1 DOWN
|
parentHost1->SetStateRaw(ServiceCritical); // parent Host 1 DOWN
|
||||||
parentHost2->SetStateRaw(ServiceOK); // parent Host 2 UP
|
parentHost2->SetStateRaw(ServiceOK); // parent Host 2 UP
|
||||||
|
|
||||||
|
BOOST_CHECK(childHost->IsReachable() == false);
|
||||||
|
|
||||||
|
/* The only DNS server is DOWN.
|
||||||
|
* Expected result: childHost is unreachable.
|
||||||
|
*/
|
||||||
|
dep1->SetRedundancyGroup("DNS");
|
||||||
|
BOOST_CHECK(childHost->IsReachable() == false);
|
||||||
|
|
||||||
|
/* 1/2 DNS servers is DOWN.
|
||||||
|
* Expected result: childHost is reachable.
|
||||||
|
*/
|
||||||
|
dep2->SetRedundancyGroup("DNS");
|
||||||
BOOST_CHECK(childHost->IsReachable() == true);
|
BOOST_CHECK(childHost->IsReachable() == true);
|
||||||
|
|
||||||
/* parentHost1 is DOWN, parentHost2 is DOWN.
|
/* Both DNS servers are DOWN.
|
||||||
* Expected result: childHost is unreachable.
|
* Expected result: childHost is unreachable.
|
||||||
*/
|
*/
|
||||||
parentHost1->SetStateRaw(ServiceCritical); // parent Host 1 DOWN
|
parentHost1->SetStateRaw(ServiceCritical); // parent Host 1 DOWN
|
||||||
|
Loading…
x
Reference in New Issue
Block a user