]> granicus.if.org Git - icinga2/blob - lib/icinga/host.cpp
Remove the HostUnreachable state.
[icinga2] / lib / icinga / host.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
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/host.h"
21 #include "icinga/service.h"
22 #include "icinga/hostgroup.h"
23 #include "icinga/icingaapplication.h"
24 #include "icinga/pluginutility.h"
25 #include "base/dynamictype.h"
26 #include "base/objectlock.h"
27 #include "base/logger_fwd.h"
28 #include "base/timer.h"
29 #include "base/convert.h"
30 #include "base/utility.h"
31 #include "base/scriptfunction.h"
32 #include "base/debug.h"
33 #include "base/serializer.h"
34 #include "config/configitembuilder.h"
35 #include "config/configcompilercontext.h"
36 #include <boost/foreach.hpp>
37
38 using namespace icinga;
39
40 REGISTER_TYPE(Host);
41
42 void Host::OnConfigLoaded(void)
43 {
44         DynamicObject::OnConfigLoaded();
45
46         ASSERT(!OwnsLock());
47
48         Array::Ptr groups = GetGroups();
49
50         if (groups) {
51                 ObjectLock olock(groups);
52
53                 BOOST_FOREACH(const String& name, groups) {
54                         HostGroup::Ptr hg = HostGroup::GetByName(name);
55
56                         if (hg)
57                                 hg->AddMember(GetSelf());
58                 }
59         }
60 }
61
62 void Host::Stop(void)
63 {
64         DynamicObject::Stop();
65
66         Array::Ptr groups = GetGroups();
67
68         if (groups) {
69                 ObjectLock olock(groups);
70
71                 BOOST_FOREACH(const String& name, groups) {
72                         HostGroup::Ptr hg = HostGroup::GetByName(name);
73
74                         if (hg)
75                                 hg->RemoveMember(GetSelf());
76                 }
77         }
78
79         // TODO: unregister slave services/notifications?
80 }
81
82 std::set<Service::Ptr> Host::GetServices(void) const
83 {
84         boost::mutex::scoped_lock lock(m_ServicesMutex);
85
86         std::set<Service::Ptr> services;
87         typedef std::pair<String, Service::Ptr> ServicePair;
88         BOOST_FOREACH(const ServicePair& kv, m_Services) {
89                 services.insert(kv.second);
90         }
91
92         return services;
93 }
94
95 void Host::AddService(const Service::Ptr& service)
96 {
97         boost::mutex::scoped_lock lock(m_ServicesMutex);
98
99         m_Services[service->GetShortName()] = service;
100 }
101
102 void Host::RemoveService(const Service::Ptr& service)
103 {
104         boost::mutex::scoped_lock lock(m_ServicesMutex);
105
106         m_Services.erase(service->GetShortName());
107 }
108
109 int Host::GetTotalServices(void) const
110 {
111         return GetServices().size();
112 }
113
114 Service::Ptr Host::GetServiceByShortName(const Value& name)
115 {
116         if (name.IsScalar()) {
117                 {
118                         boost::mutex::scoped_lock lock(m_ServicesMutex);
119
120                         std::map<String, Service::Ptr>::const_iterator it = m_Services.find(name);
121
122                         if (it != m_Services.end())
123                                 return it->second;
124                 }
125
126                 return Service::Ptr();
127         } else if (name.IsObjectType<Dictionary>()) {
128                 Dictionary::Ptr dict = name;
129                 String short_name;
130
131                 return Service::GetByNamePair(dict->Get("host"), dict->Get("service"));
132         } else {
133                 BOOST_THROW_EXCEPTION(std::invalid_argument("Host/Service name pair is invalid: " + JsonSerialize(name)));
134         }
135 }
136
137 HostState Host::CalculateState(ServiceState state)
138 {
139         switch (state) {
140                 case StateOK:
141                 case StateWarning:
142                         return HostUp;
143                 default:
144                         return HostDown;
145         }
146 }
147
148 HostState Host::GetState(void) const
149 {
150         ASSERT(!OwnsLock());
151
152         return CalculateState(GetStateRaw());
153 }
154
155 HostState Host::GetLastState(void) const
156 {
157         ASSERT(!OwnsLock());
158
159         return CalculateState(GetLastStateRaw());
160 }
161
162 HostState Host::GetLastHardState(void) const
163 {
164         ASSERT(!OwnsLock());
165
166         return CalculateState(GetLastHardStateRaw());
167 }
168
169 double Host::GetLastStateUp(void) const
170 {
171         ASSERT(!OwnsLock());
172
173         if (GetLastStateOK() > GetLastStateWarning())
174                 return GetLastStateOK();
175         else
176                 return GetLastStateWarning();
177 }
178
179 double Host::GetLastStateDown(void) const
180 {
181         ASSERT(!OwnsLock());
182
183         return GetLastStateCritical();
184 }
185
186 HostState Host::StateFromString(const String& state)
187 {
188         if (state == "UP")
189                 return HostUp;
190         else
191                 return HostDown;
192 }
193
194 String Host::StateToString(HostState state)
195 {
196         switch (state) {
197                 case HostUp:
198                         return "UP";
199                 case HostDown:
200                         return "DOWN";
201                 default:
202                         return "INVALID";
203         }
204 }
205
206 StateType Host::StateTypeFromString(const String& type)
207 {
208         if (type == "SOFT")
209                 return StateTypeSoft;
210         else
211                 return StateTypeHard;
212 }
213
214 String Host::StateTypeToString(StateType type)
215 {
216         if (type == StateTypeSoft)
217                 return "SOFT";
218         else
219                 return "HARD";
220 }
221
222 bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
223 {
224         String key;
225         Dictionary::Ptr vars;
226
227         /* special treatment for address macros providing name fallback */
228         if (macro == "address" || macro == "address6") {
229                 vars = GetVars();
230
231                 String value;
232                 if (vars && vars->Contains(macro))
233                         value = vars->Get(macro);
234
235                 if (value.IsEmpty()) {
236                         *result = GetName();
237                         return true;
238                 } else {
239                         *result = value;
240                         return true;
241                 }
242         }
243         else if (macro == "host.vars.address" || macro == "host.vars.address6") {
244                 key = macro.SubStr(10);
245                 vars = GetVars();
246
247                 String value;
248                 if (vars && vars->Contains(key))
249                         value = vars->Get(key);
250
251                 if (value.IsEmpty()) {
252                         *result = GetName();
253                         return true;
254                 } else {
255                         *result = value;
256                         return true;
257                 }
258         }
259
260         /* require prefix for object macros */
261         if (macro.SubStr(0, 5) == "host.") {
262                 key = macro.SubStr(5);
263
264                 if (key.SubStr(0, 5) == "vars.") {
265                         vars = GetVars();
266                         String vars_key = key.SubStr(5);
267
268                         if (vars && vars->Contains(vars_key)) {
269                                 *result = vars->Get(vars_key);
270                                 return true;
271                         }
272                 }
273                 else if (key == "name") {
274                         *result = GetName();
275                         return true;
276                 }
277                 else if (key == "displaymane") {
278                         *result = GetDisplayName();
279                         return true;
280                 }
281
282                 CheckResult::Ptr cr = GetLastCheckResult();
283
284                 if (key == "state") {
285                         *result = StateToString(GetState());
286                         return true;
287                 } else if (key == "stateid") {
288                         *result = Convert::ToString(GetState());
289                         return true;
290                 } else if (key == "statetype") {
291                         *result = StateTypeToString(GetStateType());
292                         return true;
293                 } else if (key == "attempt") {
294                         *result = Convert::ToString(GetCheckAttempt());
295                         return true;
296                 } else if (key == "maxattempt") {
297                         *result = Convert::ToString(GetMaxCheckAttempts());
298                         return true;
299                 } else if (key == "laststate") {
300                         *result = StateToString(GetLastState());
301                         return true;
302                 } else if (key == "laststateid") {
303                         *result = Convert::ToString(GetLastState());
304                         return true;
305                 } else if (key == "laststatetype") {
306                         *result = StateTypeToString(GetLastStateType());
307                         return true;
308                 } else if (key == "laststatechange") {
309                         *result = Convert::ToString((long)GetLastStateChange());
310                         return true;
311                 } else if (key == "durationsec") {
312                         *result = Convert::ToString((long)(Utility::GetTime() - GetLastStateChange()));
313                         return true;
314                 } else if (key == "checkcommand") {
315                         CheckCommand::Ptr commandObj = GetCheckCommand();
316
317                         if (commandObj)
318                                 *result = commandObj->GetName();
319                         else
320                                 *result = "";
321
322                         return true;
323                 } else if (key == "totalservices" || key == "totalservicesok" || key == "totalserviceswarning"
324                             || key == "totalservicesunknown" || key == "totalservicescritical") {
325                                 int filter = -1;
326                                 int count = 0;
327
328                                 if (key == "totalservicesok")
329                                         filter = StateOK;
330                                 else if (key == "totalserviceswarning")
331                                         filter = StateWarning;
332                                 else if (key == "totalservicesunknown")
333                                         filter = StateUnknown;
334                                 else if (key == "totalservicescritical")
335                                         filter = StateCritical;
336
337                                 BOOST_FOREACH(const Service::Ptr& service, GetServices()) {
338                                         if (filter != -1 && service->GetState() != filter)
339                                                 continue;
340
341                                         count++;
342                                 }
343
344                                 *result = Convert::ToString(count);
345                                 return true;
346                         }
347
348
349                 if (cr) {
350                         if (key == "latency") {
351                                 *result = Convert::ToString(Service::CalculateLatency(cr));
352                                 return true;
353                         } else if (key == "executiontime") {
354                                 *result = Convert::ToString(Service::CalculateExecutionTime(cr));
355                                 return true;
356                         } else if (key == "output") {
357                                 *result = cr->GetOutput();
358                                 return true;
359                         } else if (key == "perfdata") {
360                                 *result = PluginUtility::FormatPerfdata(cr->GetPerformanceData());
361                                 return true;
362                         } else if (key == "lastcheck") {
363                                 *result = Convert::ToString((long)cr->GetScheduleStart());
364                                 return true;
365                         }
366                 }
367         } else {
368                 vars = GetVars();
369
370                 if (vars && vars->Contains(macro)) {
371                         *result = vars->Get(macro);
372                         return true;
373                 }
374         }
375
376         return false;
377 }