]> granicus.if.org Git - icinga2/commitdiff
Implemented comments.
authorGunnar Beutner <gunnar.beutner@netways.de>
Tue, 29 Jan 2013 15:29:09 +0000 (16:29 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 29 Jan 2013 15:29:09 +0000 (16:29 +0100)
Fixes #3558

14 files changed:
components/compat/compatcomponent.cpp
components/compat/compatcomponent.h
lib/icinga/Makefile.am
lib/icinga/commentprocessor.cpp [new file with mode: 0644]
lib/icinga/commentprocessor.h [new file with mode: 0644]
lib/icinga/downtimeprocessor.cpp
lib/icinga/downtimeprocessor.h
lib/icinga/externalcommandprocessor.cpp
lib/icinga/externalcommandprocessor.h
lib/icinga/host.cpp
lib/icinga/host.h
lib/icinga/i2-icinga.h
lib/icinga/service.cpp
lib/icinga/service.h

index 514ab0d0e1d295e61d55475964ca6b0fb1cc8894..43fb808d99f3371cfff8bbc7d3043be52bda88dd 100644 (file)
@@ -159,6 +159,48 @@ void CompatComponent::ProcessCommand(const String& command)
 }
 #endif /* _WIN32 */
 
+void CompatComponent::DumpComments(ofstream& fp, const DynamicObject::Ptr& owner)
+{
+       Service::Ptr service;
+       Host::Ptr host;
+       Dictionary::Ptr comments;
+
+       if (owner->GetType() == DynamicType::GetByName("Service")) {
+               service = dynamic_pointer_cast<Service>(owner);
+               comments = service->GetComments();
+
+               host = service->GetHost();
+       } else {
+               host = dynamic_pointer_cast<Host>(owner);
+               comments = host->GetComments();
+       }
+
+       if (!comments)
+               return;
+
+       String id;
+       Dictionary::Ptr comment;
+       BOOST_FOREACH(tie(id, comment), comments) {
+               if (!service)
+                       fp << "hostcomment {" << "\n";
+               else
+                       fp << "servicecomment {" << "\n"
+                          << "\t" << "service_description=" << service->GetAlias() << "\n";
+
+               fp << "\t" << "host_name=" << host->GetName() << "\n"
+                  << "\t" << "comment_id=" << id << "\n"
+                  << "\t" << "entry_time=" << static_cast<double>(comment->Get("entry_time")) << "\n"
+                  << "\t" << "entry_type=" << static_cast<long>(comment->Get("entry_type")) << "\n"
+                  << "\t" << "persistent=" << 1 << "\n"
+                  << "\t" << "author=" << static_cast<String>(comment->Get("author")) << "\n"
+                  << "\t" << "comment_data=" << static_cast<String>(comment->Get("text")) << "\n"
+                  << "\t" << "expires=" << (static_cast<double>(comment->Get("expire_time")) != 0 ? 1 : 0) << "\n"
+                  << "\t" << "expire_time=" << static_cast<double>(comment->Get("expire_time")) << "\n"
+                  << "\t" << "}" << "\n"
+                  << "\n";
+       }
+}
+
 void CompatComponent::DumpDowntimes(ofstream& fp, const DynamicObject::Ptr& owner)
 {
        Service::Ptr service;
@@ -237,6 +279,7 @@ void CompatComponent::DumpHostStatus(ofstream& fp, const Host::Ptr& host)
           << "\n";
 
        DumpDowntimes(fp, host);
+       DumpComments(fp, host);
 }
 
 void CompatComponent::DumpHostObject(ofstream& fp, const Host::Ptr& host)
@@ -317,6 +360,7 @@ void CompatComponent::DumpServiceStatus(ofstream& fp, const Service::Ptr& servic
           << "\n";
 
        DumpDowntimes(fp, service);
+       DumpComments(fp, service);
 }
 
 void CompatComponent::DumpServiceObject(ofstream& fp, const Service::Ptr& service)
@@ -376,6 +420,7 @@ void CompatComponent::StatusTimerHandler(void)
                 << "\t" << "active_scheduled_service_check_stats=" << CIB::GetActiveChecksStatistics(60) << "," << CIB::GetActiveChecksStatistics(5 * 60) << "," << CIB::GetActiveChecksStatistics(15 * 60) << "\n"
                 << "\t" << "passive_service_check_stats=" << CIB::GetPassiveChecksStatistics(60) << "," << CIB::GetPassiveChecksStatistics(5 * 60) << "," << CIB::GetPassiveChecksStatistics(15 * 60) << "\n"
                 << "\t" << "next_downtime_id=" << DowntimeProcessor::GetNextDowntimeID() << "\n"
+                << "\t" << "next_comment_id=" << CommentProcessor::GetNextCommentID() << "\n"
                 << "\t" << "}" << "\n"
                 << "\n";
 
index 693c559e9347de4ed14b3e5a2786f2206b5dd621..55a1ffaa99d75a217f6bec33a6d24ed4b5e6932e 100644 (file)
@@ -47,6 +47,7 @@ private:
        String GetCommandPath(void) const;
 
        void DumpDowntimes(ofstream& fp, const DynamicObject::Ptr& owner);
+       void DumpComments(ofstream& fp, const DynamicObject::Ptr& owner);
        void DumpHostStatus(ofstream& fp, const Host::Ptr& host);
        void DumpHostObject(ofstream& fp, const Host::Ptr& host);
 
index 307d42d5201bbf0b56a213d8564a4e23ce230f87..8ef08fc17feb19778e23bf6b65b3157a557ed0c0 100644 (file)
@@ -8,6 +8,8 @@ libicinga_la_SOURCES =  \
        acknowledgement.h \
        cib.cpp \
        cib.h \
+       commentprocessor.cpp \
+       commentprocessor.h \
        downtimeprocessor.cpp \
        downtimeprocessor.h \
        externalcommandprocessor.cpp \
diff --git a/lib/icinga/commentprocessor.cpp b/lib/icinga/commentprocessor.cpp
new file mode 100644 (file)
index 0000000..d1b24e1
--- /dev/null
@@ -0,0 +1,144 @@
+/******************************************************************************
+ * 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;
+
+int CommentProcessor::m_NextCommentID = 1;
+map<int, DynamicObject::WeakPtr> CommentProcessor::m_CommentCache;
+bool CommentProcessor::m_CommentCacheValid;
+
+int CommentProcessor::GetNextCommentID(void)
+{
+       return m_NextCommentID;
+}
+
+int CommentProcessor::AddComment(const DynamicObject::Ptr& owner,
+    CommentType entryType, const String& author, const String& text,
+    double expireTime)
+{
+       Dictionary::Ptr comment = boost::make_shared<Dictionary>();
+       comment->Set("entry_time", Utility::GetTime());
+       comment->Set("entry_type", entryType);
+       comment->Set("author", author);
+       comment->Set("text", text);
+       comment->Set("expire_time", expireTime);
+
+       Dictionary::Ptr comments = owner->Get("comments");
+
+       if (!comments)
+               comments = boost::make_shared<Dictionary>();
+
+       int id = m_NextCommentID;
+       m_NextCommentID++;
+
+       comments->Set(Convert::ToString(id), comment);
+       owner->Set("comments", comments);
+
+       return id;
+}
+
+void CommentProcessor::RemoveAllComments(const DynamicObject::Ptr& owner)
+{
+       owner->Set("comments", Empty);
+}
+
+void CommentProcessor::RemoveComment(int id)
+{
+       DynamicObject::Ptr owner = GetOwnerByCommentID(id);
+
+       if (!owner)
+               throw_exception(invalid_argument("Comment ID does not exist."));
+
+       Dictionary::Ptr comments = owner->Get("comments");
+
+       if (comments) {
+               comments->Remove(Convert::ToString(id));
+               owner->Touch("comments");
+       }
+}
+
+DynamicObject::Ptr CommentProcessor::GetOwnerByCommentID(int id)
+{
+       ValidateCommentCache();
+
+       return m_CommentCache[id].lock();
+}
+
+Dictionary::Ptr CommentProcessor::GetCommentByID(int id)
+{
+       DynamicObject::Ptr owner = GetOwnerByCommentID(id);
+
+       if (!owner)
+               throw_exception(invalid_argument("Comment ID does not exist."));
+
+       Dictionary::Ptr comments = owner->Get("comments");
+
+       if (comments) {
+               Dictionary::Ptr comment = comments->Get(Convert::ToString(id));
+               return comment;
+       }
+
+       return Dictionary::Ptr();
+}
+
+void CommentProcessor::InvalidateCommentCache(void)
+{
+       m_CommentCacheValid = false;
+       m_CommentCache.clear();
+}
+
+void CommentProcessor::AddCommentsToCache(const DynamicObject::Ptr& owner)
+{
+       Dictionary::Ptr comments = owner->Get("comments");
+
+       if (!comments)
+               return;
+
+       String sid;
+       BOOST_FOREACH(tie(sid, tuples::ignore), comments) {
+               int id = Convert::ToLong(sid);
+
+               if (id > m_NextCommentID)
+                       m_NextCommentID = id;
+
+               m_CommentCache[id] = owner;
+       }
+}
+
+void CommentProcessor::ValidateCommentCache(void)
+{
+       if (m_CommentCacheValid)
+               return;
+
+       m_CommentCache.clear();
+
+       DynamicObject::Ptr object;
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) {
+               AddCommentsToCache(object);
+       }
+
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) {
+               AddCommentsToCache(object);
+       }
+
+       m_CommentCacheValid = true;
+}
+
diff --git a/lib/icinga/commentprocessor.h b/lib/icinga/commentprocessor.h
new file mode 100644 (file)
index 0000000..eac7fb4
--- /dev/null
@@ -0,0 +1,70 @@
+/******************************************************************************
+ * 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 COMMENTPROCESSOR_H
+#define COMMENTPROCESSOR_H
+
+namespace icinga
+{
+
+enum CommentType
+{
+       Comment_User = 1,
+       Comment_Downtime = 2,
+       Comment_Flapping = 3,
+       Comment_Acknowledgement = 4
+};
+
+/**
+ * Comment processor.
+ *
+ * @ingroup icinga
+ */
+class I2_ICINGA_API CommentProcessor
+{
+public:
+       static int GetNextCommentID(void);
+
+       static int AddComment(const DynamicObject::Ptr& owner,
+           CommentType entryType, const String& author, const String& text,
+           double expireTime);
+
+       static void RemoveAllComments(const DynamicObject::Ptr& owner);
+       static void RemoveComment(int id);
+
+       static DynamicObject::Ptr GetOwnerByCommentID(int id);
+       static Dictionary::Ptr GetCommentByID(int id);
+
+       static void InvalidateCommentCache(void);
+
+private:
+       static int m_NextCommentID;
+
+       static map<int, DynamicObject::WeakPtr> m_CommentCache;
+       static bool m_CommentCacheValid;
+
+       CommentProcessor(void);
+
+       static void AddCommentsToCache(const DynamicObject::Ptr& owner);
+       static void ValidateCommentCache(void);
+};
+
+}
+
+#endif /* DOWNTIMEPROCESSOR_H */
index 9e276e1f983034b168d6c1cb94e5e9c711d0cb3a..0f26172545c5f7fb2c9f17553c340c2dfcd18e02 100644 (file)
@@ -62,13 +62,13 @@ int DowntimeProcessor::AddDowntime(const DynamicObject::Ptr& owner,
 
 void DowntimeProcessor::RemoveDowntime(int id)
 {
-       DynamicObject::Ptr dto = GetOwnerByDowntimeID(id);
+       DynamicObject::Ptr owner = GetOwnerByDowntimeID(id);
 
-       Dictionary::Ptr downtimes = dto->Get("downtimes");
+       Dictionary::Ptr downtimes = owner->Get("downtimes");
 
        if (downtimes) {
                downtimes->Remove(Convert::ToString(id));
-               dto->Touch("downtimes");
+               owner->Touch("downtimes");
        }
 }
 
@@ -76,15 +76,17 @@ DynamicObject::Ptr DowntimeProcessor::GetOwnerByDowntimeID(int id)
 {
        ValidateDowntimeCache();
 
-       DynamicObject::Ptr dto = m_DowntimeCache[id].lock();
-       return dto;
+       return m_DowntimeCache[id].lock();
 }
 
 Dictionary::Ptr DowntimeProcessor::GetDowntimeByID(int id)
 {
-       DynamicObject::Ptr dto = GetOwnerByDowntimeID(id);
+       DynamicObject::Ptr owner = GetOwnerByDowntimeID(id);
+
+       if (!owner)
+               throw_exception(invalid_argument("Downtime ID does not exist."));
 
-       Dictionary::Ptr downtimes = dto->Get("downtimes");
+       Dictionary::Ptr downtimes = owner->Get("downtimes");
 
        if (downtimes) {
                Dictionary::Ptr downtime = downtimes->Get(Convert::ToString(id));
index d74807338a9fc1eee02c1045ee906e8cb9cff77f..530a59686e86537dc7b9d0eda31a77259092d5ee 100644 (file)
@@ -24,8 +24,7 @@ namespace icinga
 {
 
 /**
- * Common Information Base class. Holds some statistics (and will likely be
- * removed/refactored).
+ * Downtime processor.
  *
  * @ingroup icinga
  */
index 9348fd2b3ca048ff44627758136a28f3aa445038..139e52e908c23184f1999411eb959c54f68739ac 100644 (file)
@@ -94,6 +94,12 @@ void ExternalCommandProcessor::Execute(double time, const String& command, const
                RegisterCommand("SCHEDULE_HOSTGROUP_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleHostgroupSvcDowntime);
                RegisterCommand("SCHEDULE_SERVICEGROUP_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleServicegroupHostDowntime);
                RegisterCommand("SCHEDULE_SERVICEGROUP_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleServicegroupSvcDowntime);
+               RegisterCommand("ADD_HOST_COMMENT", &ExternalCommandProcessor::AddHostComment);
+               RegisterCommand("DEL_HOST_COMMENT", &ExternalCommandProcessor::DelHostComment);
+               RegisterCommand("ADD_SVC_COMMENT", &ExternalCommandProcessor::AddSvcComment);
+               RegisterCommand("DEL_SVC_COMMENT", &ExternalCommandProcessor::DelSvcComment);
+               RegisterCommand("DEL_ALL_HOST_COMMENTS", &ExternalCommandProcessor::DelAllHostComments);
+               RegisterCommand("DEL_ALL_SVC_COMMENTS", &ExternalCommandProcessor::DelAllSvcComments);
 
                m_Initialized = true;
        }
@@ -729,3 +735,79 @@ void ExternalCommandProcessor::ScheduleServicegroupSvcDowntime(double time, cons
        }
 }
 
+void ExternalCommandProcessor::AddHostComment(double time, const vector<String>& arguments)
+{
+       if (arguments.size() < 4)
+               throw_exception(invalid_argument("Expected 4 arguments."));
+
+       if (!Host::Exists(arguments[0]))
+               throw_exception(invalid_argument("The host '" + arguments[0] + "' does not exist."));
+
+       Host::Ptr host = Host::GetByName(arguments[0]);
+
+       Logger::Write(LogInformation, "icinga", "Creating comment for host " + host->GetName());
+       (void) CommentProcessor::AddComment(host, Comment_User, arguments[2], arguments[3], 0);
+}
+
+void ExternalCommandProcessor::DelHostComment(double time, const vector<String>& arguments)
+{
+       if (arguments.size() < 1)
+               throw_exception(invalid_argument("Expected 1 argument."));
+
+       String id = arguments[0];
+       Logger::Write(LogInformation, "icinga", "Removing comment ID " + id);
+       CommentProcessor::RemoveComment(Convert::ToLong(id));
+}
+
+void ExternalCommandProcessor::AddSvcComment(double time, const vector<String>& arguments)
+{
+       if (arguments.size() < 5)
+               throw_exception(invalid_argument("Expected 5 arguments."));
+
+       if (!Service::Exists(arguments[1]))
+               throw_exception(invalid_argument("The service '" + arguments[1] + "' does not exist."));
+
+       Service::Ptr service = Service::GetByName(arguments[1]);
+
+       Logger::Write(LogInformation, "icinga", "Creating comment for service " + service->GetName());
+       (void) CommentProcessor::AddComment(service, Comment_User, arguments[3], arguments[4], 0);
+}
+
+void ExternalCommandProcessor::DelSvcComment(double time, const vector<String>& arguments)
+{
+       if (arguments.size() < 1)
+               throw_exception(invalid_argument("Expected 1 argument."));
+
+       String id = arguments[0];
+       Logger::Write(LogInformation, "icinga", "Removing comment ID " + id);
+       CommentProcessor::RemoveComment(Convert::ToLong(id));
+}
+
+void ExternalCommandProcessor::DelAllHostComments(double time, const vector<String>& arguments)
+{
+       if (arguments.size() < 1)
+               throw_exception(invalid_argument("Expected 1 argument."));
+
+       if (!Host::Exists(arguments[0]))
+               throw_exception(invalid_argument("The host '" + arguments[0] + "' does not exist."));
+
+       Host::Ptr host = Host::GetByName(arguments[0]);
+
+       Logger::Write(LogInformation, "icinga", "Removing all comments for host " + host->GetName());
+       CommentProcessor::RemoveAllComments(host);
+}
+
+void ExternalCommandProcessor::DelAllSvcComments(double time, const vector<String>& arguments)
+{
+       if (arguments.size() < 2)
+               throw_exception(invalid_argument("Expected 2 arguments."));
+
+       if (!Service::Exists(arguments[1]))
+               throw_exception(invalid_argument("The service '" + arguments[1] + "' does not exist."));
+
+       Service::Ptr service = Service::GetByName(arguments[1]);
+
+       Logger::Write(LogInformation, "icinga", "Removing all comments for service " + service->GetName());
+       CommentProcessor::RemoveAllComments(service);
+}
+
index e875a874fd535e6673645f3d0bd7abd0f6e89820..a1e8dbe5faa32542122b1ec2f1d5ff6cf7e02c94 100644 (file)
@@ -65,6 +65,12 @@ public:
        static void ScheduleHostgroupSvcDowntime(double time, const vector<String>& arguments);
        static void ScheduleServicegroupHostDowntime(double time, const vector<String>& arguments);
        static void ScheduleServicegroupSvcDowntime(double time, const vector<String>& arguments);
+       static void AddHostComment(double time, const vector<String>& arguments);
+       static void DelHostComment(double time, const vector<String>& arguments);
+       static void AddSvcComment(double time, const vector<String>& arguments);
+       static void DelSvcComment(double time, const vector<String>& arguments);
+       static void DelAllHostComments(double time, const vector<String>& arguments);
+       static void DelAllSvcComments(double time, const vector<String>& arguments);
 
 private:
        typedef function<void (double time, const vector<String>& arguments)> Callback;
index 4d38481d4d4a4634bb046d48c397ab38c6441f1c..1422617421e56c0b7084f7b108c9ca60275297b3 100644 (file)
@@ -122,6 +122,11 @@ Dictionary::Ptr Host::GetDowntimes(void) const
        return Get("downtimes");
 }
 
+Dictionary::Ptr Host::GetComments(void) const
+{
+       return Get("comments");
+}
+
 bool Host::IsReachable(void)
 {
        Dictionary::Ptr dependencies = Get("dependencies");
index 8ebc67d85062badb33bae49104b2e355708ca104..d3d07175a76cb7abae6a9c507ebdba38b3b6eb70 100644 (file)
@@ -48,6 +48,7 @@ public:
        set<Host::Ptr> GetParents(void);
        Dictionary::Ptr GetMacros(void) const;
        Dictionary::Ptr GetDowntimes(void) const;
+       Dictionary::Ptr GetComments(void) const;
 
        AcknowledgementType GetAcknowledgement(void);
        void SetAcknowledgement(AcknowledgementType acknowledgement);
index 3bc8b5f0e045a7912d8da264502b89eccebda8ed..bc11049b9552ac909355cd6b7d0895a05c68620b 100644 (file)
@@ -50,6 +50,7 @@ using boost::algorithm::is_any_of;
 
 #include "acknowledgement.h"
 #include "downtimeprocessor.h"
+#include "commentprocessor.h"
 
 #include "host.h"
 #include "hostgroup.h"
index e517851612a815fed422a63e8eed89c1247a5a92..2227d15ca96533b4683d0b1d1700c9bce4854f2a 100644 (file)
@@ -122,6 +122,11 @@ Dictionary::Ptr Service::GetDowntimes(void) const
        return Get("downtimes");
 }
 
+Dictionary::Ptr Service::GetComments(void) const
+{
+       return Get("comments");
+}
+
 String Service::GetCheckCommand(void) const
 {
        return Get("check_command");
index 489f886c25fc3254c3a560929b67a8e67136e7c1..69c5c034826e3e4cd9356ee4173a1dbfa9ba00df 100644 (file)
@@ -77,6 +77,7 @@ public:
        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;
        long GetCheckInterval(void) const;