]> granicus.if.org Git - icinga2/blob - lib/icinga/checkable.cpp
fe2fed9e31330b32ad8ab0ff81f353bb05c040bb
[icinga2] / lib / icinga / checkable.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2018 Icinga Development Team (https://icinga.com/)      *
4  *                                                                            *
5  * This program is free software; you can redistribute it and/or              *
6  * modify it under the terms of the GNU General Public License                *
7  * as published by the Free Software Foundation; either version 2             *
8  * of the License, or (at your option) any later version.                     *
9  *                                                                            *
10  * This program is distributed in the hope that it will be useful,            *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
13  * GNU General Public License for more details.                               *
14  *                                                                            *
15  * You should have received a copy of the GNU General Public License          *
16  * along with this program; if not, write to the Free Software Foundation     *
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
18  ******************************************************************************/
19
20 #include "icinga/checkable.hpp"
21 #include "icinga/checkable-ti.cpp"
22 #include "icinga/host.hpp"
23 #include "icinga/service.hpp"
24 #include "base/objectlock.hpp"
25 #include "base/utility.hpp"
26 #include "base/exception.hpp"
27
28 using namespace icinga;
29
30 REGISTER_TYPE_WITH_PROTOTYPE(Checkable, Checkable::GetPrototype());
31 INITIALIZE_ONCE(&Checkable::StaticInitialize);
32
33 boost::signals2::signal<void (const Checkable::Ptr&, const String&, const String&, AcknowledgementType, bool, bool, double, const MessageOrigin::Ptr&)> Checkable::OnAcknowledgementSet;
34 boost::signals2::signal<void (const Checkable::Ptr&, const MessageOrigin::Ptr&)> Checkable::OnAcknowledgementCleared;
35
36 void Checkable::StaticInitialize()
37 {
38         /* fixed downtime start */
39         Downtime::OnDowntimeStarted.connect(std::bind(&Checkable::NotifyFixedDowntimeStart, _1));
40         /* flexible downtime start */
41         Downtime::OnDowntimeTriggered.connect(std::bind(&Checkable::NotifyFlexibleDowntimeStart, _1));
42         /* fixed/flexible downtime end */
43         Downtime::OnDowntimeRemoved.connect(std::bind(&Checkable::NotifyDowntimeEnd, _1));
44 }
45
46 Checkable::Checkable()
47 {
48         SetSchedulingOffset(Utility::Random());
49 }
50
51 void Checkable::OnAllConfigLoaded()
52 {
53         ObjectImpl<Checkable>::OnAllConfigLoaded();
54
55         Endpoint::Ptr endpoint = GetCommandEndpoint();
56
57         if (endpoint) {
58                 Zone::Ptr checkableZone = static_pointer_cast<Zone>(GetZone());
59
60                 if (!checkableZone)
61                         checkableZone = Zone::GetLocalZone();
62
63                 Zone::Ptr cmdZone = endpoint->GetZone();
64
65                 if (checkableZone && cmdZone != checkableZone && cmdZone->GetParent() != checkableZone) {
66                         BOOST_THROW_EXCEPTION(ValidationError(this, { "command_endpoint" },
67                                 "Command endpoint must be in zone '" + checkableZone->GetName() + "' or in a direct child zone thereof."));
68                 }
69         }
70 }
71
72 void Checkable::Start(bool runtimeCreated)
73 {
74         double now = Utility::GetTime();
75
76         if (GetNextCheck() < now + 60) {
77                 double delta = std::min(GetCheckInterval(), 60.0);
78                 delta *= (double)std::rand() / RAND_MAX;
79                 SetNextCheck(now + delta);
80         }
81
82         ObjectImpl<Checkable>::Start(runtimeCreated);
83 }
84
85 void Checkable::AddGroup(const String& name)
86 {
87         boost::mutex::scoped_lock lock(m_CheckableMutex);
88
89         Array::Ptr groups;
90         auto *host = dynamic_cast<Host *>(this);
91
92         if (host)
93                 groups = host->GetGroups();
94         else
95                 groups = static_cast<Service *>(this)->GetGroups();
96
97         if (groups && groups->Contains(name))
98                 return;
99
100         if (!groups)
101                 groups = new Array();
102
103         groups->Add(name);
104 }
105
106 AcknowledgementType Checkable::GetAcknowledgement()
107 {
108         auto avalue = static_cast<AcknowledgementType>(GetAcknowledgementRaw());
109
110         if (avalue != AcknowledgementNone) {
111                 double expiry = GetAcknowledgementExpiry();
112
113                 if (expiry != 0 && expiry < Utility::GetTime()) {
114                         avalue = AcknowledgementNone;
115                         ClearAcknowledgement();
116                 }
117         }
118
119         return avalue;
120 }
121
122 bool Checkable::IsAcknowledged() const
123 {
124         return const_cast<Checkable *>(this)->GetAcknowledgement() != AcknowledgementNone;
125 }
126
127 void Checkable::AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify, bool persistent, double expiry, const MessageOrigin::Ptr& origin)
128 {
129         SetAcknowledgementRaw(type);
130         SetAcknowledgementExpiry(expiry);
131
132         if (notify && !IsPaused())
133                 OnNotificationsRequested(this, NotificationAcknowledgement, GetLastCheckResult(), author, comment, nullptr);
134
135         OnAcknowledgementSet(this, author, comment, type, notify, persistent, expiry, origin);
136 }
137
138 void Checkable::ClearAcknowledgement(const MessageOrigin::Ptr& origin)
139 {
140         SetAcknowledgementRaw(AcknowledgementNone);
141         SetAcknowledgementExpiry(0);
142
143         OnAcknowledgementCleared(this, origin);
144 }
145
146 Endpoint::Ptr Checkable::GetCommandEndpoint() const
147 {
148         return Endpoint::GetByName(GetCommandEndpointRaw());
149 }
150
151 int Checkable::GetSeverity() const
152 {
153         /* overridden in Host/Service class. */
154         return 0;
155 }
156
157 void Checkable::NotifyFixedDowntimeStart(const Downtime::Ptr& downtime)
158 {
159         if (!downtime->GetFixed())
160                 return;
161
162         NotifyDowntimeInternal(downtime);
163 }
164
165 void Checkable::NotifyFlexibleDowntimeStart(const Downtime::Ptr& downtime)
166 {
167         if (downtime->GetFixed())
168                 return;
169
170         NotifyDowntimeInternal(downtime);
171 }
172
173 void Checkable::NotifyDowntimeInternal(const Downtime::Ptr& downtime)
174 {
175         Checkable::Ptr checkable = downtime->GetCheckable();
176
177         if (!checkable->IsPaused())
178                 OnNotificationsRequested(checkable, NotificationDowntimeStart, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
179 }
180
181 void Checkable::NotifyDowntimeEnd(const Downtime::Ptr& downtime)
182 {
183         /* don't send notifications for flexible downtimes which never triggered */
184         if (!downtime->GetFixed() && !downtime->IsTriggered())
185                 return;
186
187         Checkable::Ptr checkable = downtime->GetCheckable();
188
189         if (!checkable->IsPaused())
190                 OnNotificationsRequested(checkable, NotificationDowntimeEnd, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
191 }
192
193 void Checkable::ValidateCheckInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
194 {
195         ObjectImpl<Checkable>::ValidateCheckInterval(lvalue, utils);
196
197         if (lvalue() <= 0)
198                 BOOST_THROW_EXCEPTION(ValidationError(this, { "check_interval" }, "Interval must be greater than 0."));
199 }
200
201 void Checkable::ValidateMaxCheckAttempts(const Lazy<int>& lvalue, const ValidationUtils& utils)
202 {
203         ObjectImpl<Checkable>::ValidateMaxCheckAttempts(lvalue, utils);
204
205         if (lvalue() <= 0)
206                 BOOST_THROW_EXCEPTION(ValidationError(this, { "max_check_attempts" }, "Value must be greater than 0."));
207 }