]> granicus.if.org Git - icinga2/blob - lib/icinga/host.cpp
Access custom attributes as ${host,service,user}.vars.<name>$.
[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, bool reachable)
138 {
139         if (!reachable)
140                 return HostUnreachable;
141
142         switch (state) {
143                 case StateOK:
144                 case StateWarning:
145                         return HostUp;
146                 default:
147                         return HostDown;
148         }
149 }
150
151 HostState Host::GetState(void) const
152 {
153         ASSERT(!OwnsLock());
154
155         if (!IsReachable())
156                 return HostUnreachable;
157
158         switch (GetStateRaw()) {
159                 case StateOK:
160                 case StateWarning:
161                         return HostUp;
162                 default:
163                         return HostDown;
164         }
165
166 }
167
168 HostState Host::GetLastState(void) const
169 {
170         ASSERT(!OwnsLock());
171
172         if (!IsReachable())
173                 return HostUnreachable;
174
175         switch (GetLastStateRaw()) {
176                 case StateOK:
177                 case StateWarning:
178                         return HostUp;
179                 default:
180                         return HostDown;
181         }
182 }
183
184 HostState Host::GetLastHardState(void) const
185 {
186         ASSERT(!OwnsLock());
187
188         if (!IsReachable())
189                 return HostUnreachable;
190
191         switch (GetLastHardStateRaw()) {
192                 case StateOK:
193                 case StateWarning:
194                         return HostUp;
195                 default:
196                         return HostDown;
197         }
198 }
199
200 double Host::GetLastStateUp(void) const
201 {
202         ASSERT(!OwnsLock());
203
204         if (GetLastStateOK() > GetLastStateWarning())
205                 return GetLastStateOK();
206         else
207                 return GetLastStateWarning();
208 }
209
210 double Host::GetLastStateDown(void) const
211 {
212         ASSERT(!OwnsLock());
213
214         return GetLastStateCritical();
215 }
216
217 HostState Host::StateFromString(const String& state)
218 {
219         if (state == "UP")
220                 return HostUp;
221         else if (state == "DOWN")
222                 return HostDown;
223         else if (state == "UNREACHABLE")
224                 return HostUnreachable;
225         else
226                 return HostUnreachable;
227 }
228
229 String Host::StateToString(HostState state)
230 {
231         switch (state) {
232                 case HostUp:
233                         return "UP";
234                 case HostDown:
235                         return "DOWN";
236                 case HostUnreachable:
237                         return "UNREACHABLE";
238                 default:
239                         return "INVALID";
240         }
241 }
242
243 StateType Host::StateTypeFromString(const String& type)
244 {
245         if (type == "SOFT")
246                 return StateTypeSoft;
247         else
248                 return StateTypeHard;
249 }
250
251 String Host::StateTypeToString(StateType type)
252 {
253         if (type == StateTypeSoft)
254                 return "SOFT";
255         else
256                 return "HARD";
257 }
258
259 bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
260 {
261         String key;
262         Dictionary::Ptr vars;
263
264         /* require prefix for object macros */
265         if (macro.SubStr(0, 5) == "host.") {
266                 key = macro.SubStr(5);
267
268                 if (key.SubStr(0, 5) == "vars.") {
269                         vars = GetVars();
270                         String vars_key = key.SubStr(5);
271
272                         if (vars && vars->Contains(vars_key)) {
273                                 *result = vars->Get(vars_key);
274                                 return true;
275                         }
276                 }
277                 else if (key == "name") {
278                         *result = GetName();
279                         return true;
280                 }
281                 else if (key == "displaymane") {
282                         *result = GetDisplayName();
283                         return true;
284                 }
285
286                 CheckResult::Ptr cr = GetLastCheckResult();
287
288                 if (key == "state") {
289                         switch (GetState()) {
290                                 case HostUnreachable:
291                                         *result = "UNREACHABLE";
292                                         break;
293                                 case HostUp:
294                                         *result = "UP";
295                                         break;
296                                 case HostDown:
297                                         *result = "DOWN";
298                                         break;
299                                 default:
300                                         ASSERT(0);
301                         }
302
303                         return true;
304                 } else if (key == "stateid") {
305                         *result = Convert::ToString(GetState());
306                         return true;
307                 } else if (key == "statetype") {
308                         *result = StateTypeToString(GetStateType());
309                         return true;
310                 } else if (key == "attempt") {
311                         *result = Convert::ToString(GetCheckAttempt());
312                         return true;
313                 } else if (key == "maxattempt") {
314                         *result = Convert::ToString(GetMaxCheckAttempts());
315                         return true;
316                 } else if (key == "laststate") {
317                         *result = StateToString(GetLastState());
318                         return true;
319                 } else if (key == "laststateid") {
320                         *result = Convert::ToString(GetLastState());
321                         return true;
322                 } else if (key == "laststatetype") {
323                         *result = StateTypeToString(GetLastStateType());
324                         return true;
325                 } else if (key == "laststatechange") {
326                         *result = Convert::ToString((long)GetLastStateChange());
327                         return true;
328                 } else if (key == "durationsec") {
329                         *result = Convert::ToString((long)(Utility::GetTime() - GetLastStateChange()));
330                         return true;
331                 } else if (key == "checkcommand") {
332                         CheckCommand::Ptr commandObj = GetCheckCommand();
333
334                         if (commandObj)
335                                 *result = commandObj->GetName();
336                         else
337                                 *result = "";
338
339                         return true;
340                 } else if (key == "totalservices" || key == "totalservicesok" || key == "totalserviceswarning"
341                             || key == "totalservicesunknown" || key == "totalservicescritical") {
342                                 int filter = -1;
343                                 int count = 0;
344
345                                 if (key == "totalservicesok")
346                                         filter = StateOK;
347                                 else if (key == "totalserviceswarning")
348                                         filter = StateWarning;
349                                 else if (key == "totalservicesunknown")
350                                         filter = StateUnknown;
351                                 else if (key == "totalservicescritical")
352                                         filter = StateCritical;
353
354                                 BOOST_FOREACH(const Service::Ptr& service, GetServices()) {
355                                         if (filter != -1 && service->GetState() != filter)
356                                                 continue;
357
358                                         count++;
359                                 }
360
361                                 *result = Convert::ToString(count);
362                                 return true;
363                         }
364
365
366                 if (cr) {
367                         if (key == "latency") {
368                                 *result = Convert::ToString(Service::CalculateLatency(cr));
369                                 return true;
370                         } else if (key == "executiontime") {
371                                 *result = Convert::ToString(Service::CalculateExecutionTime(cr));
372                                 return true;
373                         } else if (key == "output") {
374                                 *result = cr->GetOutput();
375                                 return true;
376                         } else if (key == "perfdata") {
377                                 *result = PluginUtility::FormatPerfdata(cr->GetPerformanceData());
378                                 return true;
379                         } else if (key == "lastcheck") {
380                                 *result = Convert::ToString((long)cr->GetScheduleStart());
381                                 return true;
382                         }
383                 }
384         } else {
385                 vars = GetVars();
386
387                 if (vars && vars->Contains(macro)) {
388                         *result = vars->Get(macro);
389                         return true;
390                 }
391         }
392
393         return false;
394 }