From 3c0b8b9d5a783ed1832da8baecca7dc8f7ced18e Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 9 Aug 2013 15:30:28 +0200 Subject: [PATCH] ido: Add preliminary support for downtimes. --- lib/icinga/service-downtime.cpp | 9 ++ lib/icinga/service.h | 13 +++ lib/ido/servicedbobject.cpp | 148 +++++++++++++++++++++++++++++++- lib/ido/servicedbobject.h | 8 +- 4 files changed, 175 insertions(+), 3 deletions(-) diff --git a/lib/icinga/service-downtime.cpp b/lib/icinga/service-downtime.cpp index 87059158a..f23117f1f 100644 --- a/lib/icinga/service-downtime.cpp +++ b/lib/icinga/service-downtime.cpp @@ -40,6 +40,7 @@ static Timer::Ptr l_DowntimesCacheTimer; static Timer::Ptr l_DowntimesExpireTimer; boost::signals2::signal Service::OnDowntimeChanged; +boost::signals2::signal Service::OnDowntimesChanged; void Service::DowntimeRequestHandler(const RequestMessage& request) { @@ -131,6 +132,8 @@ String Service::AddDowntime(const String& author, const String& comment, l_DowntimesCache[id] = GetSelf(); } + OnDowntimesChanged(GetSelf(), id, DowntimeChangedAdded); + return id; } @@ -164,6 +167,8 @@ void Service::RemoveDowntime(const String& id) owner->Touch("downtimes"); } + + OnDowntimesChanged(owner, id, DowntimeChangedDeleted); } void Service::TriggerDowntimes(void) @@ -226,6 +231,8 @@ void Service::TriggerDowntime(const String& id) EndpointManager::GetInstance()->SendMulticastMessage(rm); owner->Touch("downtimes"); + + OnDowntimesChanged(owner, Empty, DowntimeChangedUpdated); } String Service::GetDowntimeIDFromLegacyID(int id) @@ -402,6 +409,8 @@ void Service::RemoveExpiredDowntimes(void) ObjectLock olock(this); Touch("downtimes"); } + + OnDowntimesChanged(GetSelf(), Empty, DowntimeChangedDeleted); } } diff --git a/lib/icinga/service.h b/lib/icinga/service.h index 3bd47c6a4..a338001f7 100644 --- a/lib/icinga/service.h +++ b/lib/icinga/service.h @@ -97,6 +97,18 @@ enum CommentChangedType CommentChangedDeleted = 2 }; +/** + * The state of a changed downtime + * + * @ingroup icinga + */ +enum DowntimeChangedType +{ + DowntimeChangedAdded = 0, + DowntimeChangedUpdated = 1, + DowntimeChangedDeleted = 2 +}; + class CheckCommand; class EventCommand; @@ -245,6 +257,7 @@ public: static boost::signals2::signal OnDowntimeChanged; static boost::signals2::signal OnFlappingChanged; static boost::signals2::signal OnCommentsChanged; + static boost::signals2::signal OnDowntimesChanged; virtual bool ResolveMacro(const String& macro, const Dictionary::Ptr& cr, String *result) const; diff --git a/lib/ido/servicedbobject.cpp b/lib/ido/servicedbobject.cpp index 93222e8c0..2a6f94f2d 100644 --- a/lib/ido/servicedbobject.cpp +++ b/lib/ido/servicedbobject.cpp @@ -40,6 +40,7 @@ INITIALIZE_ONCE(ServiceDbObject, &ServiceDbObject::StaticInitialize); void ServiceDbObject::StaticInitialize(void) { Service::OnCommentsChanged.connect(boost::bind(&ServiceDbObject::CommentsChangedHandler, _1, _2, _3)); + Service::OnDowntimesChanged.connect(boost::bind(&ServiceDbObject::DowntimesChangedHandler, _1, _2, _3)); } ServiceDbObject::ServiceDbObject(const DbType::Ptr& type, const String& name1, const String& name2) @@ -366,10 +367,10 @@ void ServiceDbObject::AddCommentByType(const DynamicObject::Ptr& object, const D fields1->Set("entry_time", DbValue::FromTimestamp(entry_time)); fields1->Set("entry_time_usec", entry_time_usec); fields1->Set("entry_type", comment->Get("entry_type")); + fields1->Set("object_id", object); if (object->GetType() == DynamicType::GetByName("Host")) { fields1->Set("comment_type", 2); - fields1->Set("object_id", static_pointer_cast(object)); /* this is obviously bullshit, but otherwise we would hit * the unique constraint on the table for the same service * comment. dynamically incremented/decremented numbers as @@ -378,7 +379,6 @@ void ServiceDbObject::AddCommentByType(const DynamicObject::Ptr& object, const D fields1->Set("internal_comment_id", 0); } else if (object->GetType() == DynamicType::GetByName("Service")) { fields1->Set("comment_type", 1); - fields1->Set("object_id", static_pointer_cast(object)); fields1->Set("internal_comment_id", comment->Get("legacy_id")); } else { Log(LogDebug, "ido", "unknown object type for adding comment."); @@ -427,6 +427,150 @@ void ServiceDbObject::DeleteComments(const Service::Ptr& service) query2.WhereCriteria->Set("object_id", host); OnQuery(query2); } +} + +void ServiceDbObject::DowntimesChangedHandler(const Service::Ptr& svcfilter, const String& id, DowntimeChangedType type) +{ + if (type == DowntimeChangedUpdated || type == DowntimeChangedDeleted) { + /* we cannot determine which downtime id is deleted + * ido schema does not store legacy id + */ + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) { + Service::Ptr service = static_pointer_cast(object); + + if (svcfilter && svcfilter != service) + continue; + + Host::Ptr host = service->GetHost(); + + if (!host) + continue; + + /* delete all downtimes associated for this host/service */ + DeleteDowntimes(service); + + /* dump all downtimes */ + AddDowntimes(service); + } + } else if (type == DowntimeChangedAdded) { + Dictionary::Ptr downtime = Service::GetDowntimeByID(id); + AddDowntime(svcfilter, downtime); + } else { + Log(LogDebug, "ido", "invalid downtime change type: " + type); + } +} + +void ServiceDbObject::AddDowntimes(const Service::Ptr& service) +{ + /* dump all downtimes */ + Dictionary::Ptr downtimes = service->GetDowntimes(); + + if (!downtimes) + return; + + ObjectLock olock(downtimes); + + String downtime_id; + Dictionary::Ptr downtime; + BOOST_FOREACH(boost::tie(downtime_id, downtime), downtimes) { + AddDowntime(service, downtime); + } +} + +void ServiceDbObject::AddDowntime(const Service::Ptr& service, const Dictionary::Ptr& downtime) +{ + Host::Ptr host = service->GetHost(); + + if (!host) + return; + + if (!downtime) { + Log(LogWarning, "ido", "downtime does not exist. not adding it."); + return; + } + + Log(LogDebug, "ido", "adding service downtime (id = " + downtime->Get("legacy_id") + ") for '" + service->GetName() + "'"); + + /* add the service downtime */ + AddDowntimeByType(service, downtime); + + /* add the hostcheck service downtime to the host as well */ + if (host->GetHostCheckService() == service) { + Log(LogDebug, "ido", "adding host downtime (id = " + downtime->Get("legacy_id") + ") for '" + host->GetName() + "'"); + AddDowntimeByType(host, downtime); + } +} +void ServiceDbObject::AddDowntimeByType(const DynamicObject::Ptr& object, const Dictionary::Ptr& downtime) +{ + unsigned long entry_time = static_cast(downtime->Get("entry_time")); + unsigned long entry_time_usec = (downtime->Get("entry_time") - entry_time) * 1000 * 1000; + + Dictionary::Ptr fields1 = boost::make_shared(); + fields1->Set("entry_time", DbValue::FromTimestamp(entry_time)); + fields1->Set("object_id", object); + + if (object->GetType() == DynamicType::GetByName("Host")) { + fields1->Set("downtime_type", 2); + /* this is obviously bullshit, but otherwise we would hit + * the unique constraint on the table for the same service + * downtime. dynamically incremented/decremented numbers as + * unique constraint - wtf? + */ + fields1->Set("internal_downtime_id", 0); + } else if (object->GetType() == DynamicType::GetByName("Service")) { + fields1->Set("downtime_type", 1); + fields1->Set("internal_downtime_id", downtime->Get("legacy_id")); + } else { + Log(LogDebug, "ido", "unknown object type for adding downtime."); + return; + } + + fields1->Set("author_name", downtime->Get("author")); + fields1->Set("triggered_by_id", downtime->Get("triggered_by")); + fields1->Set("is_fixed", downtime->Get("is_fixed")); + fields1->Set("duration", downtime->Get("duration")); + fields1->Set("scheduled_start_time", DbValue::FromTimestamp(downtime->Get("start_time"))); + fields1->Set("scheduled_end_time", DbValue::FromTimestamp(downtime->Get("end_time"))); + fields1->Set("was_started", Empty); + fields1->Set("actual_start_time", Empty); + fields1->Set("actual_start_time_usec", Empty); + fields1->Set("is_in_effect", Empty); + fields1->Set("trigger_time", DbValue::FromTimestamp(downtime->Get("trigger_time"))); + fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */ + + DbQuery query1; + query1.Table = "scheduleddowntime"; + query1.Type = DbQueryInsert; + query1.Fields = fields1; + OnQuery(query1); +} + +void ServiceDbObject::DeleteDowntimes(const Service::Ptr& service) +{ + /* delete all downtimes associated for this host/service */ + Log(LogDebug, "ido", "delete downtimes for '" + service->GetName() + "'"); + + Host::Ptr host = service->GetHost(); + + if (!host) + return; + + DbQuery query1; + query1.Table = "scheduleddowntime"; + query1.Type = DbQueryDelete; + query1.WhereCriteria = boost::make_shared(); + query1.WhereCriteria->Set("object_id", service); + OnQuery(query1); + + /* delete hostcheck service's host downtimes */ + if (host->GetHostCheckService() == service) { + DbQuery query2; + query2.Table = "scheduleddowntime"; + query2.Type = DbQueryDelete; + query2.WhereCriteria = boost::make_shared(); + query2.WhereCriteria->Set("object_id", host); + OnQuery(query2); + } } diff --git a/lib/ido/servicedbobject.h b/lib/ido/servicedbobject.h index 99b052d99..080cd9079 100644 --- a/lib/ido/servicedbobject.h +++ b/lib/ido/servicedbobject.h @@ -50,12 +50,18 @@ protected: virtual void OnConfigUpdate(void); virtual void OnStatusUpdate(void); +private: static void CommentsChangedHandler(const Service::Ptr& service, const String& id, CommentChangedType type); - static void AddComments(const Service::Ptr& service); static void AddComment(const Service::Ptr& service, const Dictionary::Ptr& comment); static void AddCommentByType(const DynamicObject::Ptr& object, const Dictionary::Ptr& comment); static void DeleteComments(const Service::Ptr& service); + + static void DowntimesChangedHandler(const Service::Ptr& service, const String& id, DowntimeChangedType type); + static void AddDowntimes(const Service::Ptr& service); + static void AddDowntime(const Service::Ptr& service, const Dictionary::Ptr& downtime); + static void AddDowntimeByType(const DynamicObject::Ptr& object, const Dictionary::Ptr& downtime); + static void DeleteDowntimes(const Service::Ptr& service); }; } -- 2.50.1