]> granicus.if.org Git - icinga2/blob - lib/icinga/host.cpp
Graphite/PerfdataWriter: Add host perfdata.
[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 bool Host::IsReachable(DependencyType dt, shared_ptr<Dependency> *failedDependency) const
83 {
84         ASSERT(!OwnsLock());
85
86         Service::Ptr hc = GetCheckService();
87         if (!hc)
88                 return true;
89
90         return hc->IsReachable(dt, failedDependency);
91 }
92
93 std::set<Service::Ptr> Host::GetServices(void) const
94 {
95         boost::mutex::scoped_lock lock(m_ServicesMutex);
96
97         std::set<Service::Ptr> services;
98         typedef std::pair<String, Service::Ptr> ServicePair;
99         BOOST_FOREACH(const ServicePair& kv, m_Services) {
100                 services.insert(kv.second);
101         }
102
103         return services;
104 }
105
106 void Host::AddService(const Service::Ptr& service)
107 {
108         boost::mutex::scoped_lock lock(m_ServicesMutex);
109
110         m_Services[service->GetShortName()] = service;
111 }
112
113 void Host::RemoveService(const Service::Ptr& service)
114 {
115         boost::mutex::scoped_lock lock(m_ServicesMutex);
116
117         m_Services.erase(service->GetShortName());
118 }
119
120 int Host::GetTotalServices(void) const
121 {
122         return GetServices().size();
123 }
124
125 Service::Ptr Host::GetServiceByShortName(const Value& name) const
126 {
127         if (name.IsEmpty()) {
128                 Service::Ptr hc = GetCheckService();
129
130                 if (!hc)
131                         BOOST_THROW_EXCEPTION(std::invalid_argument("Host does not have a host check service: " + GetName()));
132
133                 return hc;
134         } else if (name.IsScalar()) {
135                 {
136                         boost::mutex::scoped_lock lock(m_ServicesMutex);
137
138                         std::map<String, Service::Ptr>::const_iterator it = m_Services.find(name);
139
140                         if (it != m_Services.end())
141                                 return it->second;
142                 }
143
144                 return Service::Ptr();
145         } else if (name.IsObjectType<Dictionary>()) {
146                 Dictionary::Ptr dict = name;
147                 String short_name;
148
149                 return Service::GetByNamePair(dict->Get("host"), dict->Get("service"));
150         } else {
151                 BOOST_THROW_EXCEPTION(std::invalid_argument("Host/Service name pair is invalid: " + JsonSerialize(name)));
152         }
153 }
154
155 Service::Ptr Host::GetCheckService(void) const
156 {
157         String host_check = GetCheck();
158
159         if (host_check.IsEmpty())
160                 return Service::Ptr();
161
162         return GetServiceByShortName(host_check);
163 }
164
165 std::set<Host::Ptr> Host::GetParentHosts(void) const
166 {
167         std::set<Host::Ptr> result;
168         Service::Ptr hc = GetCheckService();
169
170         if (hc)
171                 result = hc->GetParentHosts();
172
173         return result;
174 }
175
176 std::set<Host::Ptr> Host::GetChildHosts(void) const
177 {
178         std::set<Host::Ptr> result;
179         Service::Ptr hc = GetCheckService();
180
181         if (hc)
182                 result = hc->GetChildHosts();
183
184         return result;
185 }
186
187 std::set<Service::Ptr> Host::GetParentServices(void) const
188 {
189         std::set<Service::Ptr> result;
190         Service::Ptr hc = GetCheckService();
191
192         if (hc)
193                 result = hc->GetParentServices();
194
195         return result;
196 }
197
198 std::set<Service::Ptr> Host::GetChildServices(void) const
199 {
200         std::set<Service::Ptr> result;
201         Service::Ptr hc = GetCheckService();
202
203         if (hc)
204                 result = hc->GetChildServices();
205
206         return result;
207 }
208
209 HostState Host::CalculateState(ServiceState state, bool reachable)
210 {
211         if (!reachable)
212                 return HostUnreachable;
213
214         switch (state) {
215                 case StateOK:
216                 case StateWarning:
217                         return HostUp;
218                 default:
219                         return HostDown;
220         }
221 }
222
223 HostState Host::GetState(void) const
224 {
225         ASSERT(!OwnsLock());
226
227         if (!IsReachable())
228                 return HostUnreachable;
229
230         Service::Ptr hc = GetCheckService();
231
232         if (!hc)
233                 return HostUp;
234
235         switch (hc->GetState()) {
236                 case StateOK:
237                 case StateWarning:
238                         return HostUp;
239                 default:
240                         return HostDown;
241         }
242
243 }
244
245 HostState Host::GetLastState(void) const
246 {
247         ASSERT(!OwnsLock());
248
249         if (!IsReachable())
250                 return HostUnreachable;
251
252         Service::Ptr hc = GetCheckService();
253
254         if (!hc)
255                 return HostUp;
256
257         switch (hc->GetLastState()) {
258                 case StateOK:
259                 case StateWarning:
260                         return HostUp;
261                 default:
262                         return HostDown;
263         }
264 }
265
266 HostState Host::GetLastHardState(void) const
267 {
268         ASSERT(!OwnsLock());
269
270         if (!IsReachable())
271                 return HostUnreachable;
272
273         Service::Ptr hc = GetCheckService();
274
275         if (!hc)
276                 return HostUp;
277
278         switch (hc->GetLastHardState()) {
279                 case StateOK:
280                 case StateWarning:
281                         return HostUp;
282                 default:
283                         return HostDown;
284         }
285 }
286
287 double Host::GetLastStateUp(void) const
288 {
289         ASSERT(!OwnsLock());
290
291         Service::Ptr hc = GetCheckService();
292
293         if (!hc)
294                 return 0;
295
296         if (hc->GetLastStateOK() > hc->GetLastStateWarning())
297                 return hc->GetLastStateOK();
298         else
299                 return hc->GetLastStateWarning();
300 }
301
302 double Host::GetLastStateDown(void) const
303 {
304         ASSERT(!OwnsLock());
305
306         Service::Ptr hc = GetCheckService();
307
308         if (!hc)
309                 return 0;
310
311         return hc->GetLastStateCritical();
312 }
313
314 double Host::GetLastStateUnreachable(void) const
315 {
316         ASSERT(!OwnsLock());
317
318         Service::Ptr hc = GetCheckService();
319
320         if (!hc)
321                 return 0;
322
323         return hc->GetLastStateUnreachable();
324 }
325
326 double Host::GetLastStateChange(void) const
327 {
328         Service::Ptr hc = GetCheckService();
329
330         if (!hc)
331                 return Application::GetStartTime();
332
333         return hc->GetLastStateChange();
334 }
335
336
337 double Host::GetLastHardStateChange(void) const
338 {
339         Service::Ptr hc = GetCheckService();
340
341         if (!hc)
342                 return Application::GetStartTime();
343
344         return hc->GetLastHardStateChange();
345 }
346
347 StateType Host::GetLastStateType(void) const
348 {
349         Service::Ptr hc = GetCheckService();
350
351         if (!hc)
352                 return StateTypeHard;
353
354         return hc->GetLastStateType();
355 }
356
357 StateType Host::GetStateType(void) const
358 {
359         Service::Ptr hc = GetCheckService();
360
361         if (!hc)
362                 return StateTypeHard;
363
364         return hc->GetStateType();
365 }
366
367 HostState Host::StateFromString(const String& state)
368 {
369         if (state == "UP")
370                 return HostUp;
371         else if (state == "DOWN")
372                 return HostDown;
373         else if (state == "UNREACHABLE")
374                 return HostUnreachable;
375         else
376                 return HostUnreachable;
377 }
378
379 String Host::StateToString(HostState state)
380 {
381         switch (state) {
382                 case HostUp:
383                         return "UP";
384                 case HostDown:
385                         return "DOWN";
386                 case HostUnreachable:
387                         return "UNREACHABLE";
388                 default:
389                         return "INVALID";
390         }
391 }
392
393 StateType Host::StateTypeFromString(const String& type)
394 {
395         if (type == "SOFT")
396                 return StateTypeSoft;
397         else
398                 return StateTypeHard;
399 }
400
401 String Host::StateTypeToString(StateType type)
402 {
403         if (type == StateTypeSoft)
404                 return "SOFT";
405         else
406                 return "HARD";
407 }
408
409 bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
410 {
411         if (macro == "HOSTNAME") {
412                 *result = GetName();
413                 return true;
414         }
415         else if (macro == "HOSTDISPLAYNAME" || macro == "HOSTALIAS") {
416                 *result = GetDisplayName();
417                 return true;
418         }
419
420         Service::Ptr hc = GetCheckService();
421         CheckResult::Ptr hccr;
422
423         if (hc) {
424                 ServiceState state = hc->GetState();
425                 bool reachable = IsReachable();
426
427                 if (macro == "HOSTSTATE") {
428                         HostState hstate = CalculateState(state, reachable);
429
430                         switch (hstate) {
431                                 case HostUnreachable:
432                                         *result = "UNREACHABLE";
433                                         break;
434                                 case HostUp:
435                                         *result = "UP";
436                                         break;
437                                 case HostDown:
438                                         *result = "DOWN";
439                                         break;
440                                 default:
441                                         ASSERT(0);
442                         }
443
444                         return true;
445                 } else if (macro == "HOSTSTATEID") {
446                         *result = Convert::ToString(state);
447                         return true;
448                 } else if (macro == "HOSTSTATETYPE") {
449                         *result = Service::StateTypeToString(hc->GetStateType());
450                         return true;
451                 } else if (macro == "HOSTATTEMPT") {
452                         *result = Convert::ToString(hc->GetCheckAttempt());
453                         return true;
454                 } else if (macro == "MAXHOSTATTEMPT") {
455                         *result = Convert::ToString(hc->GetMaxCheckAttempts());
456                         return true;
457                 } else if (macro == "LASTHOSTSTATE") {
458                         *result = StateToString(GetLastState());
459                         return true;
460                 } else if (macro == "LASTHOSTSTATEID") {
461                         *result = Convert::ToString(GetLastState());
462                         return true;
463                 } else if (macro == "LASTHOSTSTATETYPE") {
464                         *result = Service::StateTypeToString(GetLastStateType());
465                         return true;
466                 } else if (macro == "LASTHOSTSTATECHANGE") {
467                         *result = Convert::ToString((long)hc->GetLastStateChange());
468                         return true;
469                 } else if (macro == "HOSTDURATIONSEC") {
470                         *result = Convert::ToString((long)(Utility::GetTime() - hc->GetLastStateChange()));
471                         return true;
472                 }
473
474                 hccr = hc->GetLastCheckResult();
475         }
476
477         if (hccr) {
478                 if (macro == "HOSTLATENCY") {
479                         *result = Convert::ToString(Service::CalculateLatency(hccr));
480                         return true;
481                 } else if (macro == "HOSTEXECUTIONTIME") {
482                         *result = Convert::ToString(Service::CalculateExecutionTime(hccr));
483                         return true;
484                 } else if (macro == "HOSTOUTPUT") {
485                         *result = hccr->GetOutput();
486                         return true;
487                 } else if (macro == "HOSTPERFDATA") {
488                         *result = PluginUtility::FormatPerfdata(hccr->GetPerformanceData());
489                         return true;
490                 } else if (macro == "HOSTCHECKCOMMAND") {
491                         CheckCommand::Ptr commandObj = hc->GetCheckCommand();
492
493                         if (commandObj)
494                                 *result = commandObj->GetName();
495                         else
496                                 *result = "";
497
498                         return true;
499                 } else if (macro == "LASTHOSTCHECK") {
500                         *result = Convert::ToString((long)hccr->GetScheduleStart());
501                         return true;
502                 }
503         }
504
505         if (macro.SubStr(0, 5) == "_HOST") {
506                 Dictionary::Ptr custom = GetCustom();
507                 *result = custom ? custom->Get(macro.SubStr(5)) : "";
508                 return true;
509         }
510
511         Dictionary::Ptr macros = GetMacros();
512
513         String name = macro;
514
515         if (name == "HOSTADDRESS")
516                 name = "address";
517         else if (macro == "HOSTADDRESS6")
518                 name = "address6";
519
520         if (macros && macros->Contains(name)) {
521                 *result = macros->Get(name);
522                 return true;
523         }
524
525         if (macro == "HOSTADDRESS" || macro == "HOSTADDRESS6") {
526                 *result = GetName();
527                 return true;
528         }
529
530         return false;
531 }