]> granicus.if.org Git - icinga2/commitdiff
Implement the CheckResultReader type.
authorGunnar Beutner <gunnar.beutner@netways.de>
Tue, 19 Mar 2013 15:20:13 +0000 (16:20 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 19 Mar 2013 15:20:46 +0000 (16:20 +0100)
components/compat/Makefile.am
components/compat/checkresultreader.cpp [new file with mode: 0644]
components/compat/checkresultreader.h [new file with mode: 0644]
components/compat/compat-type.conf
components/compat/compatlog.h
lib/icinga/service-check.cpp
lib/icinga/service.cpp

index 70638ce99e98947d84c90173ef34b4deb0bd1802..a974fae35247f61ce43493c6ca7483d095bf7d9c 100644 (file)
@@ -10,6 +10,8 @@ EXTRA_DIST = \
        $(top_builddir)/tools/mkembedconfig $< $@
 
 libcompat_la_SOURCES = \
+       checkresultreader.cpp \
+       checkresultreader.h \
        compatcomponent.cpp \
        compatcomponent.h \
        compatlog.cpp \
diff --git a/components/compat/checkresultreader.cpp b/components/compat/checkresultreader.cpp
new file mode 100644 (file)
index 0000000..3e580cf
--- /dev/null
@@ -0,0 +1,150 @@
+/******************************************************************************
+ * 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 "compat/checkresultreader.h"
+#include "icinga/service.h"
+#include "icinga/pluginchecktask.h"
+#include "base/dynamictype.h"
+#include "base/objectlock.h"
+#include "base/logger_fwd.h"
+#include "base/convert.h"
+#include "base/application.h"
+#include <boost/smart_ptr/make_shared.hpp>
+#include <fstream>
+
+using namespace icinga;
+
+REGISTER_TYPE(CheckResultReader);
+
+CheckResultReader::CheckResultReader(const Dictionary::Ptr& properties)
+       : DynamicObject(properties)
+{
+       RegisterAttribute("spool_dir", Attribute_Config, &m_SpoolDir);
+}
+
+/**
+ * @threadsafety Always.
+ */
+void CheckResultReader::Start(void)
+{
+       m_ReadTimer = boost::make_shared<Timer>();
+       m_ReadTimer->OnTimerExpired.connect(boost::bind(&CheckResultReader::ReadTimerHandler, this));
+       m_ReadTimer->SetInterval(5);
+       m_ReadTimer->Start();
+}
+
+/**
+ * @threadsafety Always.
+ */
+CheckResultReader::Ptr CheckResultReader::GetByName(const String& name)
+{
+       DynamicObject::Ptr configObject = DynamicObject::GetObject("CheckResultReader", name);
+
+       return dynamic_pointer_cast<CheckResultReader>(configObject);
+}
+
+/**
+ * @threadsafety Always.
+ */
+String CheckResultReader::GetSpoolDir(void) const
+{
+       if (!m_SpoolDir.IsEmpty())
+               return m_SpoolDir;
+       else
+               return Application::GetLocalStateDir() + "/lib/icinga2/spool/checkresults/";
+}
+
+/**
+ * @threadsafety Always.
+ */
+void CheckResultReader::ReadTimerHandler(void) const
+{
+       Utility::Glob(GetSpoolDir() + "/c??????.ok", boost::bind(&CheckResultReader::ProcessCheckResultFile, this, _1));
+}
+
+void CheckResultReader::ProcessCheckResultFile(const String& path) const
+{
+       String crfile = String(path.Begin(), path.End() - 3); /* Remove the ".ok" extension. */
+
+       std::ifstream fp;
+       fp.exceptions(std::ifstream::badbit);
+       fp.open(crfile.CStr());
+
+       std::map<String, String> attrs;
+
+       while (fp.good()) {
+               std::string line;
+               std::getline(fp, line);
+
+               if (line.empty() || line[0] == '#')
+                       continue; /* Ignore comments and empty lines. */
+
+               int pos = line.find_first_of('=');
+
+               if (pos == std::string::npos)
+                       continue; /* Ignore invalid lines. */
+
+               String key = line.substr(0, pos);
+               String value = line.substr(pos + 1);
+
+               attrs[key] = value;
+       }
+
+       /* Remove the checkresult files. */
+       (void)unlink(path.CStr());
+       (void)unlink(crfile.CStr());
+
+       Host::Ptr host = Host::GetByName(attrs["host_name"]);
+
+       if (!host) {
+               Log(LogWarning, "compat", "Ignoring checkresult file for host '" + attrs["host_name"] +
+                   "': Host does not exist.");
+
+               return;
+       }
+
+       Service::Ptr service = host->GetServiceByShortName(attrs["service_description"]);
+
+       if (!service) {
+               Log(LogWarning, "compat", "Ignoring checkresult file for host '" + attrs["host_name"] +
+                   "', service '" + attrs["service_description"] + "': Service does not exist.");
+
+               return;
+       }
+
+       Dictionary::Ptr result = PluginCheckTask::ParseCheckOutput(attrs["output"]);
+       result->Set("state", PluginCheckTask::ExitStatusToState(Convert::ToLong(attrs["return_code"])));
+       result->Set("execution_start", Convert::ToDouble(attrs["start_time"]));
+       result->Set("execution_end", Convert::ToDouble(attrs["finish_time"]));
+       result->Set("active", 1);
+
+       service->ProcessCheckResult(result);
+
+       Log(LogDebug, "compat", "Processed checkresult file for host '" + attrs["host_name"] +
+                   "', service '" + attrs["service_description"] + "'");
+
+       {
+               ObjectLock olock(service);
+
+               /* Reschedule the next check. The side effect of this is that for as long
+                * as we receive check result files for a service we won't execute any
+                * active checks. */
+               service->SetNextCheck(Utility::GetTime() + service->GetCheckInterval());
+       }
+}
diff --git a/components/compat/checkresultreader.h b/components/compat/checkresultreader.h
new file mode 100644 (file)
index 0000000..2b6695f
--- /dev/null
@@ -0,0 +1,61 @@
+/******************************************************************************
+ * 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.             *
+ ******************************************************************************/
+
+#ifndef CHECKRESULTREADER_H
+#define CHECKRESULTREADER_H
+
+#include "remoting/endpoint.h"
+#include "base/dynamicobject.h"
+#include "base/timer.h"
+#include <fstream>
+
+namespace icinga
+{
+
+/**
+ * An Icinga checkresult reader.
+ *
+ * @ingroup compat
+ */
+class CheckResultReader : public DynamicObject
+{
+public:
+       typedef shared_ptr<CheckResultReader> Ptr;
+       typedef weak_ptr<CheckResultReader> WeakPtr;
+
+       CheckResultReader(const Dictionary::Ptr& properties);
+
+       static CheckResultReader::Ptr GetByName(const String& name);
+
+       String GetSpoolDir(void) const;
+
+protected:
+       virtual void Start(void);
+
+private:
+       Attribute<String> m_SpoolDir;
+
+       Timer::Ptr m_ReadTimer;
+       void ReadTimerHandler(void) const;
+       void ProcessCheckResultFile(const String& path) const;
+};
+
+}
+
+#endif /* CHECKRESULTREADER_H */
index cbffdac5d397d14bed2e10ad72a2447c3a0bb836..83e56f4f570bad0f7eaa396fae53ffdf5c916a87 100644 (file)
@@ -27,3 +27,7 @@ type CompatLog {
        %attribute string "path_prefix",
        %attribute number "rotation_interval"
 }
+
+type CheckResultReader {
+       %attribute string "spool_dir"
+}
index db2310f4d2bb7c22d47abd068a84228783a4d164..5ac710484a51d642b83d50bc2da4e56912b77005 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef COMPATLOG_H
 #define COMPATLOG_H
 
-#include "icinga/i2-icinga.h"
 #include "remoting/endpoint.h"
 #include "base/dynamicobject.h"
 #include "base/timer.h"
@@ -34,7 +33,7 @@ namespace icinga
  *
  * @ingroup compat
  */
-class I2_ICINGA_API CompatLog : public DynamicObject
+class CompatLog : public DynamicObject
 {
 public:
        typedef shared_ptr<CompatLog> Ptr;
index 64603cef8e53bff415dc400bcfe7f150046bed37..0e0b444bfbd034dbb15c47cf4a68837e20af0fb1 100644 (file)
@@ -409,6 +409,20 @@ void Service::SetForceNextCheck(bool forced)
  */
 void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
 {
+       double now = Utility::GetTime();
+
+       if (!cr->Contains("schedule_start"))
+               cr->Set("schedule_start", now);
+
+       if (!cr->Contains("schedule_end"))
+               cr->Set("schedule_end", now);
+
+       if (!cr->Contains("execution_start"))
+               cr->Set("execution_start", now);
+
+       if (!cr->Contains("execution_end"))
+               cr->Set("execution_end", now);
+
        bool reachable = IsReachable();
 
        Host::Ptr host = GetHost();
@@ -467,8 +481,6 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
        int state = cr->Get("state");
        SetState(static_cast<ServiceState>(state));
 
-       double now = Utility::GetTime();
-
        if (old_state != GetState()) {
                SetLastStateChange(now);
 
index 1b14e8860933cd89b0d45944271ead205afb80f9..fe1590a71fb35fecde7e92aefbcf2bc87b80e7f3 100644 (file)
@@ -475,7 +475,7 @@ Dictionary::Ptr Service::CalculateDynamicMacros(const Dictionary::Ptr& crOverrid
                macros->Set("SERVICEOUTPUT", cr->Get("output"));
                macros->Set("SERVICEPERFDATA", cr->Get("performance_data_raw"));
 
-               macros->Set("LASTSERVICECHECK", (long)cr->Get("schedule_start"));
+               macros->Set("LASTSERVICECHECK", (long)cr->Get("execution_end"));
        }
 
        macros->Seal();