]> granicus.if.org Git - icinga2/blob - lib/icinga/checkable.cpp
Merge pull request #6577 from Icinga/fix/setup-api-including-users-file
[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                         Zone::Ptr cmdZone = endpoint->GetZone();
62
63                         if (cmdZone != checkableZone && cmdZone->GetParent() != checkableZone) {
64                                 BOOST_THROW_EXCEPTION(ValidationError(this, { "command_endpoint" },
65                                         "Command endpoint must be in zone '" + checkableZone->GetName() + "' or in a direct child zone thereof."));
66                         }
67                 } else {
68                         BOOST_THROW_EXCEPTION(ValidationError(this, { "command_endpoint" },
69                                 "Command endpoint must not be set."));
70                 }
71         }
72 }
73
74 void Checkable::Start(bool runtimeCreated)
75 {
76         double now = Utility::GetTime();
77
78         if (GetNextCheck() < now + 60) {
79                 double delta = std::min(GetCheckInterval(), 60.0);
80                 delta *= (double)std::rand() / RAND_MAX;
81                 SetNextCheck(now + delta);
82         }
83
84         ObjectImpl<Checkable>::Start(runtimeCreated);
85 }
86
87 void Checkable::AddGroup(const String& name)
88 {
89         boost::mutex::scoped_lock lock(m_CheckableMutex);
90
91         Array::Ptr groups;
92         auto *host = dynamic_cast<Host *>(this);
93
94         if (host)
95                 groups = host->GetGroups();
96         else
97                 groups = static_cast<Service *>(this)->GetGroups();
98
99         if (groups && groups->Contains(name))
100                 return;
101
102         if (!groups)
103                 groups = new Array();
104
105         groups->Add(name);
106 }
107
108 AcknowledgementType Checkable::GetAcknowledgement()
109 {
110         auto avalue = static_cast<AcknowledgementType>(GetAcknowledgementRaw());
111
112         if (avalue != AcknowledgementNone) {
113                 double expiry = GetAcknowledgementExpiry();
114
115                 if (expiry != 0 && expiry < Utility::GetTime()) {
116                         avalue = AcknowledgementNone;
117                         ClearAcknowledgement();
118                 }
119         }
120
121         return avalue;
122 }
123
124 bool Checkable::IsAcknowledged() const
125 {
126         return const_cast<Checkable *>(this)->GetAcknowledgement() != AcknowledgementNone;
127 }
128
129 void Checkable::AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify, bool persistent, double expiry, const MessageOrigin::Ptr& origin)
130 {
131         SetAcknowledgementRaw(type);
132         SetAcknowledgementExpiry(expiry);
133
134         if (notify && !IsPaused())
135                 OnNotificationsRequested(this, NotificationAcknowledgement, GetLastCheckResult(), author, comment, nullptr);
136
137         OnAcknowledgementSet(this, author, comment, type, notify, persistent, expiry, origin);
138 }
139
140 void Checkable::ClearAcknowledgement(const MessageOrigin::Ptr& origin)
141 {
142         SetAcknowledgementRaw(AcknowledgementNone);
143         SetAcknowledgementExpiry(0);
144
145         OnAcknowledgementCleared(this, origin);
146 }
147
148 Endpoint::Ptr Checkable::GetCommandEndpoint() const
149 {
150         return Endpoint::GetByName(GetCommandEndpointRaw());
151 }
152
153 int Checkable::GetSeverity() const
154 {
155         /* overridden in Host/Service class. */
156         return 0;
157 }
158
159 void Checkable::NotifyFixedDowntimeStart(const Downtime::Ptr& downtime)
160 {
161         if (!downtime->GetFixed())
162                 return;
163
164         NotifyDowntimeInternal(downtime);
165 }
166
167 void Checkable::NotifyFlexibleDowntimeStart(const Downtime::Ptr& downtime)
168 {
169         if (downtime->GetFixed())
170                 return;
171
172         NotifyDowntimeInternal(downtime);
173 }
174
175 void Checkable::NotifyDowntimeInternal(const Downtime::Ptr& downtime)
176 {
177         Checkable::Ptr checkable = downtime->GetCheckable();
178
179         if (!checkable->IsPaused())
180                 OnNotificationsRequested(checkable, NotificationDowntimeStart, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
181 }
182
183 void Checkable::NotifyDowntimeEnd(const Downtime::Ptr& downtime)
184 {
185         /* don't send notifications for flexible downtimes which never triggered */
186         if (!downtime->GetFixed() && !downtime->IsTriggered())
187                 return;
188
189         Checkable::Ptr checkable = downtime->GetCheckable();
190
191         if (!checkable->IsPaused())
192                 OnNotificationsRequested(checkable, NotificationDowntimeEnd, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
193 }
194
195 void Checkable::ValidateCheckInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
196 {
197         ObjectImpl<Checkable>::ValidateCheckInterval(lvalue, utils);
198
199         if (lvalue() <= 0)
200                 BOOST_THROW_EXCEPTION(ValidationError(this, { "check_interval" }, "Interval must be greater than 0."));
201 }
202
203 void Checkable::ValidateRetryInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
204 {
205         ObjectImpl<Checkable>::ValidateRetryInterval(lvalue, utils);
206
207         if (lvalue() <= 0)
208                 BOOST_THROW_EXCEPTION(ValidationError(this, { "retry_interval" }, "Interval must be greater than 0."));
209 }
210
211 void Checkable::ValidateMaxCheckAttempts(const Lazy<int>& lvalue, const ValidationUtils& utils)
212 {
213         ObjectImpl<Checkable>::ValidateMaxCheckAttempts(lvalue, utils);
214
215         if (lvalue() <= 0)
216                 BOOST_THROW_EXCEPTION(ValidationError(this, { "max_check_attempts" }, "Value must be greater than 0."));
217 }