]> granicus.if.org Git - icinga2/commitdiff
Implement some dynamic macros.
authorGunnar Beutner <gunnar.beutner@netways.de>
Sat, 9 Feb 2013 17:39:43 +0000 (18:39 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Sat, 9 Feb 2013 17:39:43 +0000 (18:39 +0100)
Move check-specific code to service-check.cpp

12 files changed:
lib/base/process.cpp
lib/icinga/Makefile.am
lib/icinga/host.cpp
lib/icinga/host.h
lib/icinga/icinga.vcxproj
lib/icinga/pluginchecktask.cpp
lib/icinga/pluginnotificationtask.cpp
lib/icinga/service-check.cpp [new file with mode: 0644]
lib/icinga/service-comment.cpp
lib/icinga/service-downtime.cpp
lib/icinga/service.cpp
lib/icinga/service.h

index 1f76f3832d598d78f4cc7c47ad0074ef443759bc..9564b403c170123f7ea7882b7725ae109f4497d5 100644 (file)
@@ -65,7 +65,7 @@ void Process::WorkerThreadProc(void)
 #ifndef _MSC_VER
                        fd_set readfds;
                        int nfds = 0;
-                       
+
                        FD_ZERO(&readfds);
 
                        int fd;
@@ -221,4 +221,3 @@ int Process::GetFD(void) const
 {
        return fileno(m_FP);
 }
-
index 31b3a51daae733e26aef63b3d41b6c11822711a4..72358dbacd5d1d433c1e68789a832cf0cdbd8290 100644 (file)
@@ -31,6 +31,7 @@ libicinga_la_SOURCES =  \
        pluginnotificationtask.cpp \
        pluginnotificationtask.h \
        service.cpp \
+       service-check.cpp \
        service-comment.cpp \
        service-downtime.cpp \
        service-notification.cpp \
index a0bf5ea20b25b28f77f222ee9092baeadaa403a6..cd856970889cd2a22b2678cf493e21ec833c546e 100644 (file)
@@ -424,3 +424,23 @@ set<Service::Ptr> Host::GetParentServices(void) const
 
        return parents;
 }
+
+Dynamic::Ptr Host::CalculateDynamicMacros(void) const
+{
+       Dictionary::Ptr macros = boost::make_shared<Dictionary>();
+
+       macros->Set("HOSTNAME", GetName());
+       macros->Set("HOSTDISPLAYNAME", GetDisplayName());
+       macros->Set("HOSTSTATE", "DERP");
+
+       Service::Ptr hostcheck = GetHostCheckService();
+
+       if (hostcheck) {
+               macros->Set("HOSTSTATEID", 99);
+               macros->Set("HOSTSTATETYPE", Service::StateTypeToString(hostcheck->GetStateType());
+               macros->Set("HOSTATTEMPT", hostcheck->GetCurrentAttempt());
+               macros->Set("MAXHOSTATTEMPT", hostcheck->GetMaxAttempts());
+       }
+
+       return macros;
+}
index 224414a6184bd1cf63b150e9872e98e03c210895..e4f5b29a4022ffbaf5b81fbc22506574274e69c7 100644 (file)
@@ -51,6 +51,8 @@ public:
        Dictionary::Ptr GetServiceDependencies(void) const;
        String GetHostCheck(void) const;
 
+       Dynamic::Ptr CalculateDynamicMacros(void) const;
+
        shared_ptr<Service> GetHostCheckService(void) const;
        set<Host::Ptr> GetParentHosts(void) const;
        set<shared_ptr<Service> > GetParentServices(void) const;
index dbb7a8fbf8e67cc30fe7fce2b8573446ce2ec835..0f96cf6cafabf4209ccce74dcce55ebba494ea93 100644 (file)
@@ -39,6 +39,7 @@
     <ClCompile Include="pluginnotificationtask.cpp" />
     <ClCompile Include="service-notification.cpp" />
     <ClCompile Include="service.cpp" />
+    <ClCompile Include="service-check.cpp" />
     <ClCompile Include="service-comment.cpp" />
     <ClCompile Include="service-downtime.cpp" />
     <ClCompile Include="servicegroup.cpp" />
index bf9188195c10e398ea0af5a41dc49a6cbc43e1b8..cb477473310e14d501c1f50e665b412aabb09707 100644 (file)
@@ -42,7 +42,9 @@ void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value
 
        vector<Dictionary::Ptr> macroDicts;
        macroDicts.push_back(service->GetMacros());
+       macroDicts.push_back(service->CalculateDynamicMacros());
        macroDicts.push_back(service->GetHost()->GetMacros());
+       macroDicts.push_back(service->GetHost()->CalculateDynamicMacros());
        macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros());
        String command = MacroProcessor::ResolveMacros(checkCommand, macroDicts);
 
index 8bec5e77cc3147cdd23f255de36bd83bff794fe1..7901bf8713c79986d90c35822e9f1cdf3ac50298 100644 (file)
@@ -47,7 +47,9 @@ void PluginNotificationTask::ScriptFunc(const ScriptTask::Ptr& task, const vecto
        vector<Dictionary::Ptr> macroDicts;
        macroDicts.push_back(notification->GetMacros());
        macroDicts.push_back(notification->GetService()->GetMacros());
+       macroDicts.push_back(notification->GetService()->CalculateDynamicMacros());
        macroDicts.push_back(notification->GetService()->GetHost()->GetMacros());
+       macroDicts.push_back(notification->GetService()->GetHost()->CalculateDynamicMacros());
        macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros());
        String command = MacroProcessor::ResolveMacros(notificationCommand, macroDicts);
 
diff --git a/lib/icinga/service-check.cpp b/lib/icinga/service-check.cpp
new file mode 100644 (file)
index 0000000..41653fa
--- /dev/null
@@ -0,0 +1,527 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "i2-icinga.h"
+
+using namespace icinga;
+
+const int Service::DefaultMaxCheckAttempts = 3;
+const int Service::DefaultCheckInterval = 5 * 60;
+const int Service::CheckIntervalDivisor = 5;
+
+boost::signal<void (const Service::Ptr&, const CheckResultMessage&)> Service::OnCheckResultReceived;
+boost::signal<void (const Service::Ptr&, const String&)> Service::OnCheckerChanged;
+boost::signal<void (const Service::Ptr&, const Value&)> Service::OnNextCheckChanged;
+
+String Service::GetCheckCommand(void) const
+{
+       return Get("check_command");
+}
+
+long Service::GetMaxCheckAttempts(void) const
+{
+       Value value = Get("max_check_attempts");
+
+       if (value.IsEmpty())
+               return DefaultMaxCheckAttempts;
+
+       return value;
+}
+
+double Service::GetCheckInterval(void) const
+{
+       Value value = Get("check_interval");
+
+       if (value.IsEmpty())
+               return DefaultCheckInterval;
+
+       return value;
+}
+
+double Service::GetRetryInterval(void) const
+{
+       Value value = Get("retry_interval");
+
+       if (value.IsEmpty())
+               return GetCheckInterval() / CheckIntervalDivisor;
+
+       return value;
+}
+
+Dictionary::Ptr Service::GetCheckers(void) const
+{
+       return Get("checkers");
+}
+
+void Service::SetSchedulingOffset(long offset)
+{
+       Set("scheduling_offset", offset);
+}
+
+long Service::GetSchedulingOffset(void)
+{
+       Value value = Get("scheduling_offset");
+
+       if (value.IsEmpty()) {
+               value = rand();
+               SetSchedulingOffset(value);
+       }
+
+       return value;
+}
+
+void Service::SetFirstCheck(bool first)
+{
+       Set("first_check", first ? 1 : 0);
+}
+
+bool Service::GetFirstCheck(void) const
+{
+       Value value = Get("first_check");
+
+       if (value.IsEmpty())
+               return true;
+
+       return static_cast<long>(value);
+}
+
+
+void Service::SetNextCheck(double nextCheck)
+{
+       Set("next_check", nextCheck);
+}
+
+double Service::GetNextCheck(void)
+{
+       Value value = Get("next_check");
+
+       if (value.IsEmpty()) {
+               UpdateNextCheck();
+
+               value = Get("next_check");
+
+               if (value.IsEmpty())
+                       BOOST_THROW_EXCEPTION(runtime_error("Failed to schedule next check."));
+       }
+
+       return value;
+}
+
+void Service::UpdateNextCheck(void)
+{
+       double interval;
+
+       if (GetStateType() == StateTypeSoft)
+               interval = GetRetryInterval();
+       else
+               interval = GetCheckInterval();
+
+       double now = Utility::GetTime();
+       double adj = 0;
+
+       if (interval > 1)
+               adj = fmod(now + GetSchedulingOffset(), interval);
+
+       SetNextCheck(now - adj + interval);
+}
+
+void Service::SetChecker(const String& checker)
+{
+       Set("checker", checker);
+}
+
+String Service::GetChecker(void) const
+{
+       return Get("checker");
+}
+
+void Service::SetCurrentCheckAttempt(long attempt)
+{
+       Set("check_attempt", attempt);
+}
+
+long Service::GetCurrentCheckAttempt(void) const
+{
+       Value value = Get("check_attempt");
+
+       if (value.IsEmpty())
+               return 1;
+
+       return value;
+}
+
+void Service::SetState(ServiceState state)
+{
+       Set("state", static_cast<long>(state));
+}
+
+ServiceState Service::GetState(void) const
+{
+       Value value = Get("state");
+
+       if (value.IsEmpty())
+               return StateUnknown;
+
+       int ivalue = static_cast<int>(value);
+       return static_cast<ServiceState>(ivalue);
+}
+
+void Service::SetStateType(ServiceStateType type)
+{
+       Set("state_type", static_cast<long>(type));
+}
+
+ServiceStateType Service::GetStateType(void) const
+{
+       Value value = Get("state_type");
+
+       if (value.IsEmpty())
+               return StateTypeSoft;
+
+       int ivalue = static_cast<int>(value);
+       return static_cast<ServiceStateType>(ivalue);
+}
+
+void Service::SetLastCheckResult(const Dictionary::Ptr& result)
+{
+       Set("last_result", result);
+}
+
+Dictionary::Ptr Service::GetLastCheckResult(void) const
+{
+       return Get("last_result");
+}
+
+void Service::SetLastStateChange(double ts)
+{
+       Set("last_state_change", static_cast<long>(ts));
+}
+
+double Service::GetLastStateChange(void) const
+{
+       Value value = Get("last_state_change");
+
+       if (value.IsEmpty())
+               return IcingaApplication::GetInstance()->GetStartTime();
+
+       return value;
+}
+
+void Service::SetLastHardStateChange(double ts)
+{
+       Set("last_hard_state_change", ts);
+}
+
+double Service::GetLastHardStateChange(void) const
+{
+       Value value = Get("last_hard_state_change");
+
+       if (value.IsEmpty())
+               value = IcingaApplication::GetInstance()->GetStartTime();
+
+       return value;
+}
+
+bool Service::GetEnableActiveChecks(void) const
+{
+       Value value = Get("enable_active_checks");
+
+       if (value.IsEmpty())
+               return true;
+
+       return static_cast<bool>(value);
+}
+
+void Service::SetEnableActiveChecks(bool enabled)
+{
+       Set("enable_active_checks", enabled ? 1 : 0);
+}
+
+bool Service::GetEnablePassiveChecks(void) const
+{
+       Value value = Get("enable_passive_checks");
+
+       if (value.IsEmpty())
+               return true;
+
+       return static_cast<bool>(value);
+}
+
+void Service::SetEnablePassiveChecks(bool enabled)
+{
+       Set("enable_passive_checks", enabled ? 1 : 0);
+}
+
+bool Service::GetForceNextCheck(void) const
+{
+       Value value = Get("force_next_check");
+
+       if (value.IsEmpty())
+               return false;
+
+       return static_cast<bool>(value);
+}
+
+void Service::SetForceNextCheck(bool forced)
+{
+       Set("force_next_check", forced ? 1 : 0);
+}
+
+void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
+{
+       ServiceState old_state = GetState();
+       ServiceStateType old_stateType = GetStateType();
+
+       long attempt = GetCurrentCheckAttempt();
+
+       if (cr->Get("state") == StateOK) {
+               if (GetState() == StateOK)
+                       SetStateType(StateTypeHard);
+
+               attempt = 1;
+       } else {
+               if (attempt >= GetMaxCheckAttempts()) {
+                       SetStateType(StateTypeHard);
+                       attempt = 1;
+               } else if (GetStateType() == StateTypeSoft || GetState() == StateOK) {
+                       SetStateType(StateTypeSoft);
+                       attempt++;
+               }
+       }
+
+       SetCurrentCheckAttempt(attempt);
+
+       int state = cr->Get("state");
+       SetState(static_cast<ServiceState>(state));
+
+       SetLastCheckResult(cr);
+
+       double now = Utility::GetTime();
+
+       if (old_state != GetState()) {
+               SetLastStateChange(now);
+
+               /* remove acknowledgements */
+               if (GetAcknowledgement() == AcknowledgementNormal ||
+                   (GetAcknowledgement() == AcknowledgementSticky && GetStateType() == StateTypeHard && GetState() == StateOK)) {
+                       SetAcknowledgement(AcknowledgementNone);
+                       SetAcknowledgementExpiry(0);
+               }
+
+               /* reschedule service dependencies */
+               BOOST_FOREACH(const Service::Ptr& parent, GetParentServices()) {
+                       parent->SetNextCheck(Utility::GetTime());
+               }
+
+               /* reschedule host dependencies */
+               BOOST_FOREACH(const Host::Ptr& parent, GetParentHosts()) {
+                       Service::Ptr service = parent->GetHostCheckService();
+
+                       if (service)
+                               service->SetNextCheck(Utility::GetTime());
+               }
+       }
+
+       if (GetState() != StateOK)
+               TriggerDowntimes();
+
+       if (GetStateType() == StateTypeHard && (old_state != GetState() || old_stateType == StateTypeSoft)) {
+               SetLastHardStateChange(now);
+
+               /* Make sure the notification component sees the updated
+                * state/state_type attributes. */
+               DynamicObject::FlushTx();
+
+               RequestNotifications(NotificationStateChange);
+       }
+}
+
+ServiceState Service::StateFromString(const String& state)
+{
+       if (state == "ok")
+               return StateOK;
+       else if (state == "warning")
+               return StateWarning;
+       else if (state == "critical")
+               return StateCritical;
+       else if (state == "uncheckable")
+               return StateUncheckable;
+       else
+               return StateUnknown;
+}
+
+String Service::StateToString(ServiceState state)
+{
+       switch (state) {
+               case StateOK:
+                       return "ok";
+               case StateWarning:
+                       return "warning";
+               case StateCritical:
+                       return "critical";
+               case StateUncheckable:
+                       return "uncheckable";
+               case StateUnknown:
+               default:
+                       return "unknown";
+       }
+}
+
+ServiceStateType Service::StateTypeFromString(const String& type)
+{
+       if (type == "soft")
+               return StateTypeSoft;
+       else
+               return StateTypeHard;
+}
+
+String Service::StateTypeToString(ServiceStateType type)
+{
+       if (type == StateTypeSoft)
+               return "soft";
+       else
+               return "hard";
+}
+
+bool Service::IsAllowedChecker(const String& checker) const
+{
+       Dictionary::Ptr checkers = GetCheckers();
+
+       if (!checkers)
+               return true;
+
+       Value pattern;
+       BOOST_FOREACH(tie(tuples::ignore, pattern), checkers) {
+               if (Utility::Match(pattern, checker))
+                       return true;
+       }
+
+       return false;
+}
+
+void Service::BeginExecuteCheck(const function<void (void)>& callback)
+{
+       /* don't run another check if there is one pending */
+       if (!Get("current_task").IsEmpty()) {
+               /* we need to call the callback anyway */
+               callback();
+
+               return;
+       }
+
+       /* keep track of scheduling info in case the check type doesn't provide its own information */
+       Dictionary::Ptr scheduleInfo = boost::make_shared<Dictionary>();
+       scheduleInfo->Set("schedule_start", GetNextCheck());
+       scheduleInfo->Set("execution_start", Utility::GetTime());
+
+       try {
+               vector<Value> arguments;
+               arguments.push_back(static_cast<Service::Ptr>(GetSelf()));
+               ScriptTask::Ptr task;
+               task = InvokeMethod("check", arguments, boost::bind(&Service::CheckCompletedHandler, this, scheduleInfo, _1, callback));
+
+               if (!task->IsFinished())
+                       Set("current_task", task);
+       } catch (...) {
+               /* something went wrong while setting up the method call -
+                * reschedule the service and call the callback anyway. */
+
+               UpdateNextCheck();
+
+               callback();
+
+               throw;
+       }
+}
+
+void Service::CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo,
+    const ScriptTask::Ptr& task, const function<void (void)>& callback)
+{
+       Set("current_task", Empty);
+
+       scheduleInfo->Set("execution_end", Utility::GetTime());
+       scheduleInfo->Set("schedule_end", Utility::GetTime());
+
+       Dictionary::Ptr result;
+
+       try {
+               Value vresult = task->GetResult();
+
+               if (vresult.IsObjectType<Dictionary>())
+                       result = vresult;
+       } catch (const exception& ex) {
+               stringstream msgbuf;
+               msgbuf << "Exception occured during check for service '"
+                      << GetName() << "': " << diagnostic_information(ex);
+               String message = msgbuf.str();
+
+               Logger::Write(LogWarning, "icinga", message);
+
+               result = boost::make_shared<Dictionary>();
+               result->Set("state", StateUnknown);
+               result->Set("output", message);
+       }
+
+       if (result) {
+               if (!result->Contains("schedule_start"))
+                       result->Set("schedule_start", scheduleInfo->Get("schedule_start"));
+
+               if (!result->Contains("schedule_end"))
+                       result->Set("schedule_end", scheduleInfo->Get("schedule_end"));
+
+               if (!result->Contains("execution_start"))
+                       result->Set("execution_start", scheduleInfo->Get("execution_start"));
+
+               if (!result->Contains("execution_end"))
+                       result->Set("execution_end", scheduleInfo->Get("execution_end"));
+
+               if (!result->Contains("active"))
+                       result->Set("active", 1);
+
+               ProcessCheckResult(result);
+       }
+
+       /* figure out when the next check is for this service; the call to
+        * ApplyCheckResult() should've already done this but lets do it again
+        * just in case there was no check result. */
+       UpdateNextCheck();
+
+       callback();
+}
+
+void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
+{
+       ApplyCheckResult(cr);
+
+       /* flush the current transaction so other instances see the service's
+        * new state when they receive the CheckResult message */
+       DynamicObject::FlushTx();
+
+       RequestMessage rm;
+       rm.SetMethod("checker::CheckResult");
+
+       /* TODO: add _old_ state to message */
+       CheckResultMessage params;
+       params.SetService(GetName());
+       params.SetCheckResult(cr);
+
+       rm.SetParams(params);
+
+       EndpointManager::GetInstance()->SendMulticastMessage(rm);
+}
index 321e10fa4327e1046b96dfb47a727adc14813a7b..1b1619fb0a7a514cbb510201495a496ede822ee4 100644 (file)
@@ -32,6 +32,13 @@ int Service::GetNextCommentID(void)
        return m_NextCommentID;
 }
 
+Dictionary::Ptr Service::GetComments(void) const
+{
+       Service::ValidateCommentCache();
+
+       return Get("comments");
+}
+
 String Service::AddComment(CommentType entryType, const String& author,
     const String& text, double expireTime)
 {
index 43fcbf83ab96a0b3f9362d098fcf1f26d0e2e918..c9a18c9a79744d7d33725a2933ddea98c975ae5c 100644 (file)
@@ -32,6 +32,13 @@ int Service::GetNextDowntimeID(void)
        return m_NextDowntimeID;
 }
 
+Dictionary::Ptr Service::GetDowntimes(void) const
+{
+       Service::ValidateDowntimeCache();
+
+       return Get("downtimes");
+}
+
 String Service::AddDowntime(const String& author, const String& comment,
     double startTime, double endTime, bool fixed,
     const String& triggeredBy, double duration)
index a614d886b15b07deb810b1a21c70e609459003e1..2fe15cfb37023b4ede4d68f7dd09078c9fe1adc2 100644 (file)
@@ -45,14 +45,6 @@ static AttributeDescription serviceAttributes[] = {
 
 REGISTER_TYPE(Service, serviceAttributes);
 
-const int Service::DefaultMaxCheckAttempts = 3;
-const int Service::DefaultCheckInterval = 5 * 60;
-const int Service::CheckIntervalDivisor = 5;
-
-boost::signal<void (const Service::Ptr&, const CheckResultMessage&)> Service::OnCheckResultReceived;
-boost::signal<void (const Service::Ptr&, const String&)> Service::OnCheckerChanged;
-boost::signal<void (const Service::Ptr&, const Value&)> Service::OnNextCheckChanged;
-
 Service::Service(const Dictionary::Ptr& serializedObject)
        : DynamicObject(serializedObject)
 {
@@ -120,55 +112,6 @@ Dictionary::Ptr Service::GetMacros(void) const
        return Get("macros");
 }
 
-Dictionary::Ptr Service::GetDowntimes(void) const
-{
-       Service::ValidateDowntimeCache();
-
-       return Get("downtimes");
-}
-
-Dictionary::Ptr Service::GetComments(void) const
-{
-       Service::ValidateCommentCache();
-
-       return Get("comments");
-}
-
-String Service::GetCheckCommand(void) const
-{
-       return Get("check_command");
-}
-
-long Service::GetMaxCheckAttempts(void) const
-{
-       Value value = Get("max_check_attempts");
-
-       if (value.IsEmpty())
-               return DefaultMaxCheckAttempts;
-
-       return value;
-}
-
-double Service::GetCheckInterval(void) const
-{
-       Value value = Get("check_interval");
-
-       if (value.IsEmpty())
-               return DefaultCheckInterval;
-
-       return value;
-}
-
-double Service::GetRetryInterval(void) const
-{
-       Value value = Get("retry_interval");
-
-       if (value.IsEmpty())
-               return GetCheckInterval() / CheckIntervalDivisor;
-
-       return value;
-}
-
 Dictionary::Ptr Service::GetHostDependencies(void) const
 {
        return Get("hostdependencies");
@@ -184,11 +127,6 @@ Dictionary::Ptr Service::GetGroups(void) const
        return Get("servicegroups");
 }
 
-Dictionary::Ptr Service::GetCheckers(void) const
-{
-       return Get("checkers");
-}
-
 String Service::GetShortName(void) const
 {
        Value value = Get("short_name");
@@ -229,220 +167,6 @@ bool Service::IsReachable(void) const
        return true;
 }
 
-void Service::SetSchedulingOffset(long offset)
-{
-       Set("scheduling_offset", offset);
-}
-
-long Service::GetSchedulingOffset(void)
-{
-       Value value = Get("scheduling_offset");
-
-       if (value.IsEmpty()) {
-               value = rand();
-               SetSchedulingOffset(value);
-       }
-
-       return value;
-}
-
-void Service::SetFirstCheck(bool first)
-{
-       Set("first_check", first ? 1 : 0);
-}
-
-bool Service::GetFirstCheck(void) const
-{
-       Value value = Get("first_check");
-
-       if (value.IsEmpty())
-               return true;
-
-       return static_cast<long>(value);
-}
-
-
-void Service::SetNextCheck(double nextCheck)
-{
-       Set("next_check", nextCheck);
-}
-
-double Service::GetNextCheck(void)
-{
-       Value value = Get("next_check");
-
-       if (value.IsEmpty()) {
-               UpdateNextCheck();
-
-               value = Get("next_check");
-
-               if (value.IsEmpty())
-                       BOOST_THROW_EXCEPTION(runtime_error("Failed to schedule next check."));
-       }
-
-       return value;
-}
-
-void Service::UpdateNextCheck(void)
-{
-       double interval;
-
-       if (GetStateType() == StateTypeSoft)
-               interval = GetRetryInterval();
-       else
-               interval = GetCheckInterval();
-
-       double now = Utility::GetTime();
-       double adj = 0;
-
-       if (interval > 1)
-               adj = fmod(now + GetSchedulingOffset(), interval);
-
-       SetNextCheck(now - adj + interval);
-}
-
-void Service::SetChecker(const String& checker)
-{
-       Set("checker", checker);
-}
-
-String Service::GetChecker(void) const
-{
-       return Get("checker");
-}
-
-void Service::SetCurrentCheckAttempt(long attempt)
-{
-       Set("check_attempt", attempt);
-}
-
-long Service::GetCurrentCheckAttempt(void) const
-{
-       Value value = Get("check_attempt");
-
-       if (value.IsEmpty())
-               return 1;
-
-       return value;
-}
-
-void Service::SetState(ServiceState state)
-{
-       Set("state", static_cast<long>(state));
-}
-
-ServiceState Service::GetState(void) const
-{
-       Value value = Get("state");
-
-       if (value.IsEmpty())
-               return StateUnknown;
-
-       int ivalue = static_cast<int>(value);
-       return static_cast<ServiceState>(ivalue);
-}
-
-void Service::SetStateType(ServiceStateType type)
-{
-       Set("state_type", static_cast<long>(type));
-}
-
-ServiceStateType Service::GetStateType(void) const
-{
-       Value value = Get("state_type");
-
-       if (value.IsEmpty())
-               return StateTypeSoft;
-
-       int ivalue = static_cast<int>(value);
-       return static_cast<ServiceStateType>(ivalue);
-}
-
-void Service::SetLastCheckResult(const Dictionary::Ptr& result)
-{
-       Set("last_result", result);
-}
-
-Dictionary::Ptr Service::GetLastCheckResult(void) const
-{
-       return Get("last_result");
-}
-
-void Service::SetLastStateChange(double ts)
-{
-       Set("last_state_change", static_cast<long>(ts));
-}
-
-double Service::GetLastStateChange(void) const
-{
-       Value value = Get("last_state_change");
-
-       if (value.IsEmpty())
-               return IcingaApplication::GetInstance()->GetStartTime();
-
-       return value;
-}
-
-void Service::SetLastHardStateChange(double ts)
-{
-       Set("last_hard_state_change", ts);
-}
-
-double Service::GetLastHardStateChange(void) const
-{
-       Value value = Get("last_hard_state_change");
-
-       if (value.IsEmpty())
-               value = IcingaApplication::GetInstance()->GetStartTime();
-
-       return value;
-}
-
-bool Service::GetEnableActiveChecks(void) const
-{
-       Value value = Get("enable_active_checks");
-
-       if (value.IsEmpty())
-               return true;
-
-       return static_cast<bool>(value);
-}
-
-void Service::SetEnablePassiveChecks(bool enabled)
-{
-       Set("enable_passive_checks", enabled ? 1 : 0);
-}
-
-bool Service::GetEnablePassiveChecks(void) const
-{
-       Value value = Get("enable_passive_checks");
-
-       if (value.IsEmpty())
-               return true;
-
-       return static_cast<bool>(value);
-}
-
-void Service::SetEnableActiveChecks(bool enabled)
-{
-       Set("enable_active_checks", enabled ? 1 : 0);
-}
-
-bool Service::GetForceNextCheck(void) const
-{
-       Value value = Get("force_next_check");
-
-       if (value.IsEmpty())
-               return false;
-
-       return static_cast<bool>(value);
-}
-
-void Service::SetForceNextCheck(bool forced)
-{
-       Set("force_next_check", forced ? 1 : 0);
-}
-
 AcknowledgementType Service::GetAcknowledgement(void)
 {
        Value value = Get("acknowledgement");
@@ -486,138 +210,6 @@ void Service::SetAcknowledgementExpiry(double timestamp)
        Set("acknowledgement_expiry", timestamp);
 }
 
-void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
-{
-       ServiceState old_state = GetState();
-       ServiceStateType old_stateType = GetStateType();
-
-       long attempt = GetCurrentCheckAttempt();
-
-       if (cr->Get("state") == StateOK) {
-               if (GetState() == StateOK)
-                       SetStateType(StateTypeHard);
-
-               attempt = 1;
-       } else {
-               if (attempt >= GetMaxCheckAttempts()) {
-                       SetStateType(StateTypeHard);
-                       attempt = 1;
-               } else if (GetStateType() == StateTypeSoft || GetState() == StateOK) {
-                       SetStateType(StateTypeSoft);
-                       attempt++;
-               }
-       }
-
-       SetCurrentCheckAttempt(attempt);
-
-       int state = cr->Get("state");
-       SetState(static_cast<ServiceState>(state));
-
-       SetLastCheckResult(cr);
-
-       double now = Utility::GetTime();
-
-       if (old_state != GetState()) {
-               SetLastStateChange(now);
-
-               /* remove acknowledgements */
-               if (GetAcknowledgement() == AcknowledgementNormal ||
-                   (GetAcknowledgement() == AcknowledgementSticky && GetStateType() == StateTypeHard && GetState() == StateOK)) {
-                       SetAcknowledgement(AcknowledgementNone);
-                       SetAcknowledgementExpiry(0);
-               }
-
-               /* reschedule service dependencies */
-               BOOST_FOREACH(const Service::Ptr& parent, GetParentServices()) {
-                       parent->SetNextCheck(Utility::GetTime());
-               }
-
-               /* reschedule host dependencies */
-               BOOST_FOREACH(const Host::Ptr& parent, GetParentHosts()) {
-                       Service::Ptr service = parent->GetHostCheckService();
-
-                       if (service)
-                               service->SetNextCheck(Utility::GetTime());
-               }
-       }
-
-       if (GetState() != StateOK)
-               TriggerDowntimes();
-
-       if (GetStateType() == StateTypeHard && (old_state != GetState() || old_stateType == StateTypeSoft)) {
-               SetLastHardStateChange(now);
-
-               /* Make sure the notification component sees the updated
-                * state/state_type attributes. */
-               DynamicObject::FlushTx();
-
-               RequestNotifications(NotificationStateChange);
-       }
-}
-
-ServiceState Service::StateFromString(const String& state)
-{
-       if (state == "ok")
-               return StateOK;
-       else if (state == "warning")
-               return StateWarning;
-       else if (state == "critical")
-               return StateCritical;
-       else if (state == "uncheckable")
-               return StateUncheckable;
-       else
-               return StateUnknown;
-}
-
-String Service::StateToString(ServiceState state)
-{
-       switch (state) {
-               case StateOK:
-                       return "ok";
-               case StateWarning:
-                       return "warning";
-               case StateCritical:
-                       return "critical";
-               case StateUncheckable:
-                       return "uncheckable";
-               case StateUnknown:
-               default:
-                       return "unknown";
-       }
-}
-
-ServiceStateType Service::StateTypeFromString(const String& type)
-{
-       if (type == "soft")
-               return StateTypeSoft;
-       else
-               return StateTypeHard;
-}
-
-String Service::StateTypeToString(ServiceStateType type)
-{
-       if (type == StateTypeSoft)
-               return "soft";
-       else
-               return "hard";
-}
-
-bool Service::IsAllowedChecker(const String& checker) const
-{
-       Dictionary::Ptr checkers = GetCheckers();
-
-       if (!checkers)
-               return true;
-
-       Value pattern;
-       BOOST_FOREACH(tie(tuples::ignore, pattern), checkers) {
-               if (Utility::Match(pattern, checker))
-                       return true;
-       }
-
-       return false;
-}
-
 void Service::OnAttributeChanged(const String& name, const Value& oldValue)
 {
        if (name == "checker")
@@ -636,117 +228,6 @@ void Service::OnAttributeChanged(const String& name, const Value& oldValue)
                UpdateSlaveNotifications();
 }
 
-void Service::BeginExecuteCheck(const function<void (void)>& callback)
-{
-       /* don't run another check if there is one pending */
-       if (!Get("current_task").IsEmpty()) {
-               /* we need to call the callback anyway */
-               callback();
-
-               return;
-       }
-
-       /* keep track of scheduling info in case the check type doesn't provide its own information */
-       Dictionary::Ptr scheduleInfo = boost::make_shared<Dictionary>();
-       scheduleInfo->Set("schedule_start", GetNextCheck());
-       scheduleInfo->Set("execution_start", Utility::GetTime());
-
-       try {
-               vector<Value> arguments;
-               arguments.push_back(static_cast<Service::Ptr>(GetSelf()));
-               ScriptTask::Ptr task;
-               task = InvokeMethod("check", arguments, boost::bind(&Service::CheckCompletedHandler, this, scheduleInfo, _1, callback));
-
-               if (!task->IsFinished())
-                       Set("current_task", task);
-       } catch (...) {
-               /* something went wrong while setting up the method call -
-                * reschedule the service and call the callback anyway. */
-
-               UpdateNextCheck();
-
-               callback();
-
-               throw;
-       }
-}
-
-void Service::CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo,
-    const ScriptTask::Ptr& task, const function<void (void)>& callback)
-{
-       Set("current_task", Empty);
-
-       scheduleInfo->Set("execution_end", Utility::GetTime());
-       scheduleInfo->Set("schedule_end", Utility::GetTime());
-
-       Dictionary::Ptr result;
-
-       try {
-               Value vresult = task->GetResult();
-
-               if (vresult.IsObjectType<Dictionary>())
-                       result = vresult;
-       } catch (const exception& ex) {
-               stringstream msgbuf;
-               msgbuf << "Exception occured during check for service '"
-                      << GetName() << "': " << diagnostic_information(ex);
-               String message = msgbuf.str();
-
-               Logger::Write(LogWarning, "icinga", message);
-
-               result = boost::make_shared<Dictionary>();
-               result->Set("state", StateUnknown);
-               result->Set("output", message);
-       }
-
-       if (result) {
-               if (!result->Contains("schedule_start"))
-                       result->Set("schedule_start", scheduleInfo->Get("schedule_start"));
-
-               if (!result->Contains("schedule_end"))
-                       result->Set("schedule_end", scheduleInfo->Get("schedule_end"));
-
-               if (!result->Contains("execution_start"))
-                       result->Set("execution_start", scheduleInfo->Get("execution_start"));
-
-               if (!result->Contains("execution_end"))
-                       result->Set("execution_end", scheduleInfo->Get("execution_end"));
-
-               if (!result->Contains("active"))
-                       result->Set("active", 1);
-
-               ProcessCheckResult(result);
-       }
-
-       /* figure out when the next check is for this service; the call to
-        * ApplyCheckResult() should've already done this but lets do it again
-        * just in case there was no check result. */
-       UpdateNextCheck();
-
-       callback();
-}
-
-void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
-{
-       ApplyCheckResult(cr);
-
-       /* flush the current transaction so other instances see the service's
-        * new state when they receive the CheckResult message */
-       DynamicObject::FlushTx();
-
-       RequestMessage rm;
-       rm.SetMethod("checker::CheckResult");
-
-       /* TODO: add _old_ state to message */
-       CheckResultMessage params;
-       params.SetService(GetName());
-       params.SetCheckResult(cr);
-
-       rm.SetParams(params);
-
-       EndpointManager::GetInstance()->SendMulticastMessage(rm);
-}
-
 set<Host::Ptr> Service::GetParentHosts(void) const
 {
        set<Host::Ptr> parents;
@@ -787,3 +268,18 @@ set<Service::Ptr> Service::GetParentServices(void) const
 
        return parents;
 }
+
+Dynamic::Ptr Service::CalculateDynamicMacros(void) const
+{
+       Dictionary::Ptr macros = boost::make_shared<Dictionary>();
+
+       macros->Set("SERVICEDESC", GetShortName());
+       macros->Set("SERVICEDISPLAYNAME", GetDisplayName());
+       macros->Set("SERVICESTATE", StateToString(GetState()));
+       macros->Set("SERVICESTATEID", GetState());
+       macros->Set("SERVICESTATETYPE", StateTypeToString(GetStateType()));
+       macros->Set("SERVICEATTEMPT", GetCurrentAttempt());
+       macros->Set("MAXSERVICEATTEMPT", GetMaxAttempts());
+
+       return macros;
+}
index dfda3399b2950e9503003f1675e55da9cfdf5432..bc9f4506caf05b79ca99deb37cbd27593be3241a 100644 (file)
@@ -101,23 +101,27 @@ public:
        String GetDisplayName(void) const;
        Host::Ptr GetHost(void) const;
        Dictionary::Ptr GetMacros(void) const;
-       Dictionary::Ptr GetDowntimes(void) const;
-       Dictionary::Ptr GetComments(void) const;
-       String GetCheckCommand(void) const;
-       long GetMaxCheckAttempts(void) const;
-       double GetCheckInterval(void) const;
-       double GetRetryInterval(void) const;
        Dictionary::Ptr GetHostDependencies(void) const;
        Dictionary::Ptr GetServiceDependencies(void) const;
        Dictionary::Ptr GetGroups(void) const;
-       Dictionary::Ptr GetCheckers(void) const;
        String GetShortName(void) const;
 
+       Dynamic::Ptr CalculateDynamicMacros(void) const;
+
        set<Host::Ptr> GetParentHosts(void) const;
        set<Service::Ptr> GetParentServices(void) const;
 
        bool IsReachable(void) const;
-       bool IsInDowntime(void) const;
+
+       AcknowledgementType GetAcknowledgement(void);
+       void SetAcknowledgement(AcknowledgementType acknowledgement);
+
+       /* Checks */
+       Dictionary::Ptr GetCheckers(void) const;
+       String GetCheckCommand(void) const;
+       long GetMaxCheckAttempts(void) const;
+       double GetCheckInterval(void) const;
+       double GetRetryInterval(void) const;
 
        long GetSchedulingOffset(void);
        void SetSchedulingOffset(long offset);
@@ -161,9 +165,6 @@ public:
        bool GetForceNextCheck(void) const;
        void SetForceNextCheck(bool forced);
 
-       AcknowledgementType GetAcknowledgement(void);
-       void SetAcknowledgement(AcknowledgementType acknowledgement);
-
        double GetAcknowledgementExpiry(void) const;
        void SetAcknowledgementExpiry(double timestamp);
 
@@ -185,6 +186,8 @@ public:
        /* Downtimes */
        static int GetNextDowntimeID(void);
 
+       Dictionary::Ptr GetDowntimes(void) const;
+
        String AddDowntime(const String& author, const String& comment,
            double startTime, double endTime, bool fixed,
            const String& triggeredBy, double duration);
@@ -204,9 +207,13 @@ public:
        static void InvalidateDowntimeCache(void);
        static void ValidateDowntimeCache(void);
 
+       bool IsInDowntime(void) const;
+
        /* Comments */
        static int GetNextCommentID(void);
 
+       Dictionary::Ptr GetComments(void) const;
+
        String AddComment(CommentType entryType, const String& author,
            const String& text, double expireTime);