]> granicus.if.org Git - icinga2/blob - lib/icinga/checkable.cpp
Merge pull request #5964 from fedepires/fix/opentsdbwriter-host-tag-5963
[icinga2] / lib / icinga / checkable.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2018 Icinga Development Team (https://www.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 + 300)
77                 UpdateNextCheck();
78
79         ObjectImpl<Checkable>::Start(runtimeCreated);
80 }
81
82 void Checkable::AddGroup(const String& name)
83 {
84         boost::mutex::scoped_lock lock(m_CheckableMutex);
85
86         Array::Ptr groups;
87         auto *host = dynamic_cast<Host *>(this);
88
89         if (host)
90                 groups = host->GetGroups();
91         else
92                 groups = static_cast<Service *>(this)->GetGroups();
93
94         if (groups && groups->Contains(name))
95                 return;
96
97         if (!groups)
98                 groups = new Array();
99
100         groups->Add(name);
101 }
102
103 AcknowledgementType Checkable::GetAcknowledgement()
104 {
105         auto avalue = static_cast<AcknowledgementType>(GetAcknowledgementRaw());
106
107         if (avalue != AcknowledgementNone) {
108                 double expiry = GetAcknowledgementExpiry();
109
110                 if (expiry != 0 && expiry < Utility::GetTime()) {
111                         avalue = AcknowledgementNone;
112                         ClearAcknowledgement();
113                 }
114         }
115
116         return avalue;
117 }
118
119 bool Checkable::IsAcknowledged() const
120 {
121         return const_cast<Checkable *>(this)->GetAcknowledgement() != AcknowledgementNone;
122 }
123
124 void Checkable::AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify, bool persistent, double expiry, const MessageOrigin::Ptr& origin)
125 {
126         SetAcknowledgementRaw(type);
127         SetAcknowledgementExpiry(expiry);
128
129         if (notify && !IsPaused())
130                 OnNotificationsRequested(this, NotificationAcknowledgement, GetLastCheckResult(), author, comment, nullptr);
131
132         OnAcknowledgementSet(this, author, comment, type, notify, persistent, expiry, origin);
133 }
134
135 void Checkable::ClearAcknowledgement(const MessageOrigin::Ptr& origin)
136 {
137         SetAcknowledgementRaw(AcknowledgementNone);
138         SetAcknowledgementExpiry(0);
139
140         OnAcknowledgementCleared(this, origin);
141 }
142
143 Endpoint::Ptr Checkable::GetCommandEndpoint() const
144 {
145         return Endpoint::GetByName(GetCommandEndpointRaw());
146 }
147
148 int Checkable::GetSeverity() const
149 {
150         /* overridden in Host/Service class. */
151         return 0;
152 }
153
154 void Checkable::NotifyFixedDowntimeStart(const Downtime::Ptr& downtime)
155 {
156         if (!downtime->GetFixed())
157                 return;
158
159         NotifyDowntimeInternal(downtime);
160 }
161
162 void Checkable::NotifyFlexibleDowntimeStart(const Downtime::Ptr& downtime)
163 {
164         if (downtime->GetFixed())
165                 return;
166
167         NotifyDowntimeInternal(downtime);
168 }
169
170 void Checkable::NotifyDowntimeInternal(const Downtime::Ptr& downtime)
171 {
172         Checkable::Ptr checkable = downtime->GetCheckable();
173
174         if (!checkable->IsPaused())
175                 OnNotificationsRequested(checkable, NotificationDowntimeStart, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
176 }
177
178 void Checkable::NotifyDowntimeEnd(const Downtime::Ptr& downtime)
179 {
180         /* don't send notifications for flexible downtimes which never triggered */
181         if (!downtime->GetFixed() && !downtime->IsTriggered())
182                 return;
183
184         Checkable::Ptr checkable = downtime->GetCheckable();
185
186         if (!checkable->IsPaused())
187                 OnNotificationsRequested(checkable, NotificationDowntimeEnd, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
188 }
189
190 void Checkable::ValidateCheckInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
191 {
192         ObjectImpl<Checkable>::ValidateCheckInterval(lvalue, utils);
193
194         if (lvalue() <= 0)
195                 BOOST_THROW_EXCEPTION(ValidationError(this, { "check_interval" }, "Interval must be greater than 0."));
196 }
197
198 void Checkable::ValidateMaxCheckAttempts(const Lazy<int>& lvalue, const ValidationUtils& utils)
199 {
200         ObjectImpl<Checkable>::ValidateMaxCheckAttempts(lvalue, utils);
201
202         if (lvalue() <= 0)
203                 BOOST_THROW_EXCEPTION(ValidationError(this, { "max_check_attempts" }, "Value must be greater than 0."));
204 }