1 /******************************************************************************
3 * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
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. *
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. *
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 ******************************************************************************/
20 #include "i2-icinga.h"
22 using namespace icinga;
24 REGISTER_TYPE(Service);
26 Service::Service(const Dictionary::Ptr& serializedObject)
27 : DynamicObject(serializedObject), m_CheckRunning(false)
30 RegisterAttribute("display_name", Attribute_Config, &m_DisplayName);
31 RegisterAttribute("macros", Attribute_Config, &m_Macros);
32 RegisterAttribute("hostdependencies", Attribute_Config, &m_HostDependencies);
33 RegisterAttribute("servicedependencies", Attribute_Config, &m_ServiceDependencies);
34 RegisterAttribute("servicegroups", Attribute_Config, &m_ServiceGroups);
36 RegisterAttribute("check_command", Attribute_Config, &m_CheckCommand);
37 RegisterAttribute("max_check_attempts", Attribute_Config, &m_MaxCheckAttempts);
38 RegisterAttribute("check_interval", Attribute_Config, &m_CheckInterval);
39 RegisterAttribute("retry_interval", Attribute_Config, &m_RetryInterval);
40 RegisterAttribute("checkers", Attribute_Config, &m_Checkers);
42 RegisterAttribute("next_check", Attribute_Replicated, &m_NextCheck);
43 RegisterAttribute("current_checker", Attribute_Replicated, &m_CurrentChecker);
44 RegisterAttribute("check_attempt", Attribute_Replicated, &m_CheckAttempt);
45 RegisterAttribute("state", Attribute_Replicated, &m_State);
46 RegisterAttribute("state_type", Attribute_Replicated, &m_StateType);
47 RegisterAttribute("last_state", Attribute_Replicated, &m_LastState);
48 RegisterAttribute("last_state_type", Attribute_Replicated, &m_LastStateType);
49 RegisterAttribute("last_result", Attribute_Replicated, &m_LastResult);
50 RegisterAttribute("last_state_change", Attribute_Replicated, &m_LastStateChange);
51 RegisterAttribute("last_hard_state_change", Attribute_Replicated, &m_LastHardStateChange);
52 RegisterAttribute("enable_active_checks", Attribute_Replicated, &m_EnableActiveChecks);
53 RegisterAttribute("enable_passive_checks", Attribute_Replicated, &m_EnablePassiveChecks);
54 RegisterAttribute("force_next_check", Attribute_Replicated, &m_ForceNextCheck);
56 RegisterAttribute("short_name", Attribute_Config, &m_ShortName);
57 RegisterAttribute("host_name", Attribute_Config, &m_HostName);
59 RegisterAttribute("acknowledgement", Attribute_Replicated, &m_Acknowledgement);
60 RegisterAttribute("acknowledgement_expiry", Attribute_Replicated, &m_AcknowledgementExpiry);
62 RegisterAttribute("comments", Attribute_Replicated, &m_Comments);
64 RegisterAttribute("downtimes", Attribute_Replicated, &m_Downtimes);
66 RegisterAttribute("enable_notifications", Attribute_Replicated, &m_EnableNotifications);
67 RegisterAttribute("last_notification", Attribute_Replicated, &m_LastNotification);
68 RegisterAttribute("notification_interval", Attribute_Config, &m_NotificationInterval);
70 SetSchedulingOffset(rand());
73 Service::~Service(void)
75 ServiceGroup::InvalidateMembersCache();
76 Host::InvalidateServicesCache();
77 Service::InvalidateDowntimesCache();
78 Service::InvalidateCommentsCache();
82 * @threadsafety Always.
84 void Service::OnRegistrationCompleted(void)
88 DynamicObject::OnRegistrationCompleted();
90 InvalidateNotificationsCache();
94 * @threadsafety Always.
96 String Service::GetDisplayName(void) const
98 if (m_DisplayName.IsEmpty())
99 return GetShortName();
101 return m_DisplayName;
105 * @threadsafety Always.
107 Service::Ptr Service::GetByName(const String& name)
109 DynamicObject::Ptr configObject = DynamicObject::GetObject("Service", name);
111 return dynamic_pointer_cast<Service>(configObject);
115 * @threadsafety Always.
117 Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName)
119 if (!hostName.IsEmpty()) {
120 Host::Ptr host = Host::GetByName(hostName);
123 return Service::Ptr();
125 return host->GetServiceByShortName(serviceName);
127 return Service::GetByName(serviceName);
132 * @threadsafety Always.
134 Host::Ptr Service::GetHost(void) const
136 return Host::GetByName(m_HostName);
140 * @threadsafety Always.
142 Dictionary::Ptr Service::GetMacros(void) const
148 * @threadsafety Always.
150 Dictionary::Ptr Service::GetHostDependencies(void) const
152 return m_HostDependencies;
156 * @threadsafety Always.
158 Dictionary::Ptr Service::GetServiceDependencies(void) const
160 return m_ServiceDependencies;
164 * @threadsafety Always.
166 Dictionary::Ptr Service::GetGroups(void) const
168 return m_ServiceGroups;
172 * @threadsafety Always.
174 String Service::GetHostName(void) const
180 * @threadsafety Always.
182 String Service::GetShortName(void) const
184 if (m_ShortName.IsEmpty())
191 * @threadsafety Always.
193 bool Service::IsReachable(void) const
197 BOOST_FOREACH(const Service::Ptr& service, GetParentServices()) {
198 /* ignore ourselves */
199 if (service->GetName() == GetName())
202 ObjectLock olock(service);
204 /* ignore pending services */
205 if (!service->GetLastCheckResult())
208 /* ignore soft states */
209 if (service->GetStateType() == StateTypeSoft)
212 /* ignore services states OK and Warning */
213 if (service->GetState() == StateOK ||
214 service->GetState() == StateWarning)
220 BOOST_FOREACH(const Host::Ptr& host, GetParentHosts()) {
221 Service::Ptr hc = host->GetHostCheckService();
223 /* ignore hosts that don't have a hostcheck */
227 /* ignore ourselves */
228 if (hc->GetName() == GetName())
231 ObjectLock olock(hc);
233 /* ignore soft states */
234 if (hc->GetStateType() == StateTypeSoft)
237 /* ignore hosts that are up */
238 if (hc->GetState() == StateOK)
248 * @threadsafety Always.
250 AcknowledgementType Service::GetAcknowledgement(void)
254 if (m_Acknowledgement.IsEmpty())
255 return AcknowledgementNone;
257 int ivalue = static_cast<int>(m_Acknowledgement);
258 AcknowledgementType avalue = static_cast<AcknowledgementType>(ivalue);
260 if (avalue != AcknowledgementNone) {
261 double expiry = GetAcknowledgementExpiry();
263 if (expiry != 0 && expiry < Utility::GetTime()) {
264 avalue = AcknowledgementNone;
265 SetAcknowledgement(avalue);
266 SetAcknowledgementExpiry(0);
274 * @threadsafety Always.
276 void Service::SetAcknowledgement(AcknowledgementType acknowledgement)
278 m_Acknowledgement = acknowledgement;
279 Touch("acknowledgement");
283 * @threadsafety Always.
285 bool Service::IsAcknowledged(void)
287 return GetAcknowledgement() != AcknowledgementNone;
291 * @threadsafety Always.
293 double Service::GetAcknowledgementExpiry(void) const
295 if (m_AcknowledgementExpiry.IsEmpty())
298 return static_cast<double>(m_AcknowledgementExpiry);
302 * @threadsafety Always.
304 void Service::SetAcknowledgementExpiry(double timestamp)
306 m_AcknowledgementExpiry = timestamp;
307 Touch("acknowledgement_expiry");
311 * @threadsafety Always.
313 void Service::AcknowledgeProblem(AcknowledgementType type, double expiry)
315 ObjectLock olock(this);
317 SetAcknowledgement(type);
318 SetAcknowledgementExpiry(expiry);
320 RequestNotifications(NotificationAcknowledgement, GetLastCheckResult());
324 * @threadsafety Always.
326 void Service::ClearAcknowledgement(void)
328 ObjectLock olock(this);
330 SetAcknowledgement(AcknowledgementNone);
331 SetAcknowledgementExpiry(0);
335 * @threadsafety Always.
337 void Service::OnAttributeChanged(const String& name)
341 Service::Ptr self = GetSelf();
343 if (name == "current_checker")
344 OnCheckerChanged(self);
345 else if (name == "next_check")
346 OnNextCheckChanged(self);
347 else if (name == "servicegroups")
348 ServiceGroup::InvalidateMembersCache();
349 else if (name == "host_name" || name == "short_name") {
350 Host::InvalidateServicesCache();
352 UpdateSlaveNotifications();
353 } else if (name == "downtimes")
354 Service::InvalidateDowntimesCache();
355 else if (name == "comments")
356 Service::InvalidateCommentsCache();
357 else if (name == "notifications")
358 UpdateSlaveNotifications();
359 else if (name == "check_interval") {
360 ConfigItem::Ptr item = ConfigItem::GetObject("Service", GetName());
362 /* update the next check timestamp if we're the owner of this service */
363 if (item && !IsAbstract())
369 * @threadsafety Always.
371 set<Host::Ptr> Service::GetParentHosts(void) const
373 set<Host::Ptr> parents;
375 Host::Ptr host = GetHost();
377 /* The service's host is implicitly a parent. */
379 parents.insert(host);
381 Dictionary::Ptr dependencies = GetHostDependencies();
384 ObjectLock olock(dependencies);
387 BOOST_FOREACH(tie(key, tuples::ignore), dependencies) {
388 Host::Ptr host = Host::GetByName(key);
393 parents.insert(host);
401 * @threadsafety Always.
403 set<Service::Ptr> Service::GetParentServices(void) const
405 set<Service::Ptr> parents;
407 Host::Ptr host = GetHost();
408 Dictionary::Ptr dependencies = GetServiceDependencies();
410 if (host && dependencies) {
413 BOOST_FOREACH(tie(key, value), dependencies) {
414 Service::Ptr service = host->GetServiceByShortName(value);
419 if (service->GetName() == GetName())
422 parents.insert(service);
430 * @threadsafety Always.
432 Dictionary::Ptr Service::CalculateDynamicMacros(void) const
434 Dictionary::Ptr macros = boost::make_shared<Dictionary>();
439 ObjectLock olock(this);
440 macros->Set("SERVICEDESC", GetShortName());
441 macros->Set("SERVICEDISPLAYNAME", GetDisplayName());
442 macros->Set("SERVICESTATE", StateToString(GetState()));
443 macros->Set("SERVICESTATEID", GetState());
444 macros->Set("SERVICESTATETYPE", StateTypeToString(GetStateType()));
445 macros->Set("SERVICEATTEMPT", GetCurrentCheckAttempt());
446 macros->Set("MAXSERVICEATTEMPT", GetMaxCheckAttempts());
447 macros->Set("SERVICECHECKCOMMAND", "check_i2");
448 macros->Set("LASTSERVICESTATE", StateToString(GetLastState()));
449 macros->Set("LASTSERVICESTATEID", GetLastState());
450 macros->Set("LASTSERVICESTATETYPE", StateTypeToString(GetLastStateType()));
451 macros->Set("LASTSERVICESTATECHANGE", (time_t)GetLastStateChange());
453 cr = GetLastCheckResult();
457 assert(cr->IsSealed());
459 macros->Set("SERVICELATENCY", Service::CalculateLatency(cr));
460 macros->Set("SERVICEEXECUTIONTIME", Service::CalculateExecutionTime(cr));
462 macros->Set("SERVICEOUTPUT", cr->Get("output"));
463 macros->Set("SERVICEPERFDATA", cr->Get("performance_data_raw"));
465 macros->Set("LASTSERVICECHECK", (time_t)cr->Get("schedule_start"));
473 Dictionary::Ptr Service::CalculateAllMacros(void) const
475 vector<Dictionary::Ptr> macroDicts;
476 macroDicts.push_back(GetMacros());
478 Host::Ptr host = GetHost();
480 macroDicts.push_back(CalculateDynamicMacros());
483 macroDicts.push_back(host->GetMacros());
484 macroDicts.push_back(host->CalculateDynamicMacros());
487 IcingaApplication::Ptr app = IcingaApplication::GetInstance();
488 macroDicts.push_back(app->GetMacros());
490 macroDicts.push_back(IcingaApplication::CalculateDynamicMacros());
492 return MacroProcessor::MergeMacroDicts(macroDicts);