]> granicus.if.org Git - icinga2/blob - lib/icinga/checkable.cpp
Merge pull request #7113 from Elias481/fix/incorrect-usage-of-global-namespace-6874...
[icinga2] / lib / icinga / checkable.cpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #include "icinga/checkable.hpp"
4 #include "icinga/checkable-ti.cpp"
5 #include "icinga/host.hpp"
6 #include "icinga/service.hpp"
7 #include "base/objectlock.hpp"
8 #include "base/utility.hpp"
9 #include "base/exception.hpp"
10
11 using namespace icinga;
12
13 REGISTER_TYPE_WITH_PROTOTYPE(Checkable, Checkable::GetPrototype());
14 INITIALIZE_ONCE(&Checkable::StaticInitialize);
15
16 boost::signals2::signal<void (const Checkable::Ptr&, const String&, const String&, AcknowledgementType, bool, bool, double, const MessageOrigin::Ptr&)> Checkable::OnAcknowledgementSet;
17 boost::signals2::signal<void (const Checkable::Ptr&, const MessageOrigin::Ptr&)> Checkable::OnAcknowledgementCleared;
18
19 void Checkable::StaticInitialize()
20 {
21         /* fixed downtime start */
22         Downtime::OnDowntimeStarted.connect(std::bind(&Checkable::NotifyFixedDowntimeStart, _1));
23         /* flexible downtime start */
24         Downtime::OnDowntimeTriggered.connect(std::bind(&Checkable::NotifyFlexibleDowntimeStart, _1));
25         /* fixed/flexible downtime end */
26         Downtime::OnDowntimeRemoved.connect(std::bind(&Checkable::NotifyDowntimeEnd, _1));
27 }
28
29 Checkable::Checkable()
30 {
31         SetSchedulingOffset(Utility::Random());
32 }
33
34 void Checkable::OnAllConfigLoaded()
35 {
36         ObjectImpl<Checkable>::OnAllConfigLoaded();
37
38         Endpoint::Ptr endpoint = GetCommandEndpoint();
39
40         if (endpoint) {
41                 Zone::Ptr checkableZone = static_pointer_cast<Zone>(GetZone());
42
43                 if (checkableZone) {
44                         Zone::Ptr cmdZone = endpoint->GetZone();
45
46                         if (cmdZone != checkableZone && cmdZone->GetParent() != checkableZone) {
47                                 BOOST_THROW_EXCEPTION(ValidationError(this, { "command_endpoint" },
48                                         "Command endpoint must be in zone '" + checkableZone->GetName() + "' or in a direct child zone thereof."));
49                         }
50                 } else {
51                         BOOST_THROW_EXCEPTION(ValidationError(this, { "command_endpoint" },
52                                 "Command endpoint must not be set."));
53                 }
54         }
55 }
56
57 void Checkable::Start(bool runtimeCreated)
58 {
59         double now = Utility::GetTime();
60
61         if (GetNextCheck() < now + 60) {
62                 double delta = std::min(GetCheckInterval(), 60.0);
63                 delta *= (double)std::rand() / RAND_MAX;
64                 SetNextCheck(now + delta);
65         }
66
67         ObjectImpl<Checkable>::Start(runtimeCreated);
68 }
69
70 void Checkable::AddGroup(const String& name)
71 {
72         boost::mutex::scoped_lock lock(m_CheckableMutex);
73
74         Array::Ptr groups;
75         auto *host = dynamic_cast<Host *>(this);
76
77         if (host)
78                 groups = host->GetGroups();
79         else
80                 groups = static_cast<Service *>(this)->GetGroups();
81
82         if (groups && groups->Contains(name))
83                 return;
84
85         if (!groups)
86                 groups = new Array();
87
88         groups->Add(name);
89 }
90
91 AcknowledgementType Checkable::GetAcknowledgement()
92 {
93         auto avalue = static_cast<AcknowledgementType>(GetAcknowledgementRaw());
94
95         if (avalue != AcknowledgementNone) {
96                 double expiry = GetAcknowledgementExpiry();
97
98                 if (expiry != 0 && expiry < Utility::GetTime()) {
99                         avalue = AcknowledgementNone;
100                         ClearAcknowledgement();
101                 }
102         }
103
104         return avalue;
105 }
106
107 bool Checkable::IsAcknowledged() const
108 {
109         return const_cast<Checkable *>(this)->GetAcknowledgement() != AcknowledgementNone;
110 }
111
112 void Checkable::AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify, bool persistent, double expiry, const MessageOrigin::Ptr& origin)
113 {
114         SetAcknowledgementRaw(type);
115         SetAcknowledgementExpiry(expiry);
116
117         if (notify && !IsPaused())
118                 OnNotificationsRequested(this, NotificationAcknowledgement, GetLastCheckResult(), author, comment, nullptr);
119
120         OnAcknowledgementSet(this, author, comment, type, notify, persistent, expiry, origin);
121 }
122
123 void Checkable::ClearAcknowledgement(const MessageOrigin::Ptr& origin)
124 {
125         SetAcknowledgementRaw(AcknowledgementNone);
126         SetAcknowledgementExpiry(0);
127
128         OnAcknowledgementCleared(this, origin);
129 }
130
131 Endpoint::Ptr Checkable::GetCommandEndpoint() const
132 {
133         return Endpoint::GetByName(GetCommandEndpointRaw());
134 }
135
136 int Checkable::GetSeverity() const
137 {
138         /* overridden in Host/Service class. */
139         return 0;
140 }
141
142 bool Checkable::GetProblem() const
143 {
144         return !IsStateOK(GetStateRaw());
145 }
146
147 bool Checkable::GetHandled() const
148 {
149         return GetProblem() && (IsInDowntime() || IsAcknowledged());
150 }
151
152 void Checkable::NotifyFixedDowntimeStart(const Downtime::Ptr& downtime)
153 {
154         if (!downtime->GetFixed())
155                 return;
156
157         NotifyDowntimeInternal(downtime);
158 }
159
160 void Checkable::NotifyFlexibleDowntimeStart(const Downtime::Ptr& downtime)
161 {
162         if (downtime->GetFixed())
163                 return;
164
165         NotifyDowntimeInternal(downtime);
166 }
167
168 void Checkable::NotifyDowntimeInternal(const Downtime::Ptr& downtime)
169 {
170         Checkable::Ptr checkable = downtime->GetCheckable();
171
172         if (!checkable->IsPaused())
173                 OnNotificationsRequested(checkable, NotificationDowntimeStart, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
174 }
175
176 void Checkable::NotifyDowntimeEnd(const Downtime::Ptr& downtime)
177 {
178         /* don't send notifications for flexible downtimes which never triggered */
179         if (!downtime->GetFixed() && !downtime->IsTriggered())
180                 return;
181
182         Checkable::Ptr checkable = downtime->GetCheckable();
183
184         if (!checkable->IsPaused())
185                 OnNotificationsRequested(checkable, NotificationDowntimeEnd, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
186 }
187
188 void Checkable::ValidateCheckInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
189 {
190         ObjectImpl<Checkable>::ValidateCheckInterval(lvalue, utils);
191
192         if (lvalue() <= 0)
193                 BOOST_THROW_EXCEPTION(ValidationError(this, { "check_interval" }, "Interval must be greater than 0."));
194 }
195
196 void Checkable::ValidateRetryInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
197 {
198         ObjectImpl<Checkable>::ValidateRetryInterval(lvalue, utils);
199
200         if (lvalue() <= 0)
201                 BOOST_THROW_EXCEPTION(ValidationError(this, { "retry_interval" }, "Interval must be greater than 0."));
202 }
203
204 void Checkable::ValidateMaxCheckAttempts(const Lazy<int>& lvalue, const ValidationUtils& utils)
205 {
206         ObjectImpl<Checkable>::ValidateMaxCheckAttempts(lvalue, utils);
207
208         if (lvalue() <= 0)
209                 BOOST_THROW_EXCEPTION(ValidationError(this, { "max_check_attempts" }, "Value must be greater than 0."));
210 }