From: Gunnar Beutner Date: Tue, 29 Jan 2013 15:29:09 +0000 (+0100) Subject: Implemented comments. X-Git-Tag: v0.0.2~624 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c7550971fee68c5452ed31f565a772fbae89f8fc;p=icinga2 Implemented comments. Fixes #3558 --- diff --git a/components/compat/compatcomponent.cpp b/components/compat/compatcomponent.cpp index 514ab0d0e..43fb808d9 100644 --- a/components/compat/compatcomponent.cpp +++ b/components/compat/compatcomponent.cpp @@ -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(owner); + comments = service->GetComments(); + + host = service->GetHost(); + } else { + host = dynamic_pointer_cast(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(comment->Get("entry_time")) << "\n" + << "\t" << "entry_type=" << static_cast(comment->Get("entry_type")) << "\n" + << "\t" << "persistent=" << 1 << "\n" + << "\t" << "author=" << static_cast(comment->Get("author")) << "\n" + << "\t" << "comment_data=" << static_cast(comment->Get("text")) << "\n" + << "\t" << "expires=" << (static_cast(comment->Get("expire_time")) != 0 ? 1 : 0) << "\n" + << "\t" << "expire_time=" << static_cast(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"; diff --git a/components/compat/compatcomponent.h b/components/compat/compatcomponent.h index 693c559e9..55a1ffaa9 100644 --- a/components/compat/compatcomponent.h +++ b/components/compat/compatcomponent.h @@ -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); diff --git a/lib/icinga/Makefile.am b/lib/icinga/Makefile.am index 307d42d52..8ef08fc17 100644 --- a/lib/icinga/Makefile.am +++ b/lib/icinga/Makefile.am @@ -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 index 000000000..d1b24e187 --- /dev/null +++ b/lib/icinga/commentprocessor.cpp @@ -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 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(); + 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(); + + 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 index 000000000..eac7fb48d --- /dev/null +++ b/lib/icinga/commentprocessor.h @@ -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 m_CommentCache; + static bool m_CommentCacheValid; + + CommentProcessor(void); + + static void AddCommentsToCache(const DynamicObject::Ptr& owner); + static void ValidateCommentCache(void); +}; + +} + +#endif /* DOWNTIMEPROCESSOR_H */ diff --git a/lib/icinga/downtimeprocessor.cpp b/lib/icinga/downtimeprocessor.cpp index 9e276e1f9..0f2617254 100644 --- a/lib/icinga/downtimeprocessor.cpp +++ b/lib/icinga/downtimeprocessor.cpp @@ -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)); diff --git a/lib/icinga/downtimeprocessor.h b/lib/icinga/downtimeprocessor.h index d74807338..530a59686 100644 --- a/lib/icinga/downtimeprocessor.h +++ b/lib/icinga/downtimeprocessor.h @@ -24,8 +24,7 @@ namespace icinga { /** - * Common Information Base class. Holds some statistics (and will likely be - * removed/refactored). + * Downtime processor. * * @ingroup icinga */ diff --git a/lib/icinga/externalcommandprocessor.cpp b/lib/icinga/externalcommandprocessor.cpp index 9348fd2b3..139e52e90 100644 --- a/lib/icinga/externalcommandprocessor.cpp +++ b/lib/icinga/externalcommandprocessor.cpp @@ -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& 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& 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& 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& 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& 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& 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); +} + diff --git a/lib/icinga/externalcommandprocessor.h b/lib/icinga/externalcommandprocessor.h index e875a874f..a1e8dbe5f 100644 --- a/lib/icinga/externalcommandprocessor.h +++ b/lib/icinga/externalcommandprocessor.h @@ -65,6 +65,12 @@ public: static void ScheduleHostgroupSvcDowntime(double time, const vector& arguments); static void ScheduleServicegroupHostDowntime(double time, const vector& arguments); static void ScheduleServicegroupSvcDowntime(double time, const vector& arguments); + static void AddHostComment(double time, const vector& arguments); + static void DelHostComment(double time, const vector& arguments); + static void AddSvcComment(double time, const vector& arguments); + static void DelSvcComment(double time, const vector& arguments); + static void DelAllHostComments(double time, const vector& arguments); + static void DelAllSvcComments(double time, const vector& arguments); private: typedef function& arguments)> Callback; diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index 4d38481d4..142261742 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -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"); diff --git a/lib/icinga/host.h b/lib/icinga/host.h index 8ebc67d85..d3d07175a 100644 --- a/lib/icinga/host.h +++ b/lib/icinga/host.h @@ -48,6 +48,7 @@ public: set GetParents(void); Dictionary::Ptr GetMacros(void) const; Dictionary::Ptr GetDowntimes(void) const; + Dictionary::Ptr GetComments(void) const; AcknowledgementType GetAcknowledgement(void); void SetAcknowledgement(AcknowledgementType acknowledgement); diff --git a/lib/icinga/i2-icinga.h b/lib/icinga/i2-icinga.h index 3bc8b5f0e..bc11049b9 100644 --- a/lib/icinga/i2-icinga.h +++ b/lib/icinga/i2-icinga.h @@ -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" diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index e51785161..2227d15ca 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -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"); diff --git a/lib/icinga/service.h b/lib/icinga/service.h index 489f886c2..69c5c0348 100644 --- a/lib/icinga/service.h +++ b/lib/icinga/service.h @@ -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;