ido: Add preliminary support for downtimes.

This commit is contained in:
Gunnar Beutner 2013-08-09 15:30:28 +02:00
parent ffc3e85ba5
commit 3c0b8b9d5a
4 changed files with 176 additions and 4 deletions

View File

@ -40,6 +40,7 @@ static Timer::Ptr l_DowntimesCacheTimer;
static Timer::Ptr l_DowntimesExpireTimer; static Timer::Ptr l_DowntimesExpireTimer;
boost::signals2::signal<void (const Service::Ptr&, DowntimeState)> Service::OnDowntimeChanged; boost::signals2::signal<void (const Service::Ptr&, DowntimeState)> Service::OnDowntimeChanged;
boost::signals2::signal<void (const Service::Ptr&, const String&, DowntimeChangedType)> Service::OnDowntimesChanged;
void Service::DowntimeRequestHandler(const RequestMessage& request) void Service::DowntimeRequestHandler(const RequestMessage& request)
{ {
@ -131,6 +132,8 @@ String Service::AddDowntime(const String& author, const String& comment,
l_DowntimesCache[id] = GetSelf(); l_DowntimesCache[id] = GetSelf();
} }
OnDowntimesChanged(GetSelf(), id, DowntimeChangedAdded);
return id; return id;
} }
@ -164,6 +167,8 @@ void Service::RemoveDowntime(const String& id)
owner->Touch("downtimes"); owner->Touch("downtimes");
} }
OnDowntimesChanged(owner, id, DowntimeChangedDeleted);
} }
void Service::TriggerDowntimes(void) void Service::TriggerDowntimes(void)
@ -226,6 +231,8 @@ void Service::TriggerDowntime(const String& id)
EndpointManager::GetInstance()->SendMulticastMessage(rm); EndpointManager::GetInstance()->SendMulticastMessage(rm);
owner->Touch("downtimes"); owner->Touch("downtimes");
OnDowntimesChanged(owner, Empty, DowntimeChangedUpdated);
} }
String Service::GetDowntimeIDFromLegacyID(int id) String Service::GetDowntimeIDFromLegacyID(int id)
@ -402,6 +409,8 @@ void Service::RemoveExpiredDowntimes(void)
ObjectLock olock(this); ObjectLock olock(this);
Touch("downtimes"); Touch("downtimes");
} }
OnDowntimesChanged(GetSelf(), Empty, DowntimeChangedDeleted);
} }
} }

View File

@ -97,6 +97,18 @@ enum CommentChangedType
CommentChangedDeleted = 2 CommentChangedDeleted = 2
}; };
/**
* The state of a changed downtime
*
* @ingroup icinga
*/
enum DowntimeChangedType
{
DowntimeChangedAdded = 0,
DowntimeChangedUpdated = 1,
DowntimeChangedDeleted = 2
};
class CheckCommand; class CheckCommand;
class EventCommand; class EventCommand;
@ -245,6 +257,7 @@ public:
static boost::signals2::signal<void (const Service::Ptr&, DowntimeState)> OnDowntimeChanged; static boost::signals2::signal<void (const Service::Ptr&, DowntimeState)> OnDowntimeChanged;
static boost::signals2::signal<void (const Service::Ptr&, FlappingState)> OnFlappingChanged; static boost::signals2::signal<void (const Service::Ptr&, FlappingState)> OnFlappingChanged;
static boost::signals2::signal<void (const Service::Ptr&, const String&, CommentChangedType)> OnCommentsChanged; static boost::signals2::signal<void (const Service::Ptr&, const String&, CommentChangedType)> OnCommentsChanged;
static boost::signals2::signal<void (const Service::Ptr&, const String&, DowntimeChangedType)> OnDowntimesChanged;
virtual bool ResolveMacro(const String& macro, const Dictionary::Ptr& cr, String *result) const; virtual bool ResolveMacro(const String& macro, const Dictionary::Ptr& cr, String *result) const;

View File

@ -40,6 +40,7 @@ INITIALIZE_ONCE(ServiceDbObject, &ServiceDbObject::StaticInitialize);
void ServiceDbObject::StaticInitialize(void) void ServiceDbObject::StaticInitialize(void)
{ {
Service::OnCommentsChanged.connect(boost::bind(&ServiceDbObject::CommentsChangedHandler, _1, _2, _3)); 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) 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", DbValue::FromTimestamp(entry_time));
fields1->Set("entry_time_usec", entry_time_usec); fields1->Set("entry_time_usec", entry_time_usec);
fields1->Set("entry_type", comment->Get("entry_type")); fields1->Set("entry_type", comment->Get("entry_type"));
fields1->Set("object_id", object);
if (object->GetType() == DynamicType::GetByName("Host")) { if (object->GetType() == DynamicType::GetByName("Host")) {
fields1->Set("comment_type", 2); fields1->Set("comment_type", 2);
fields1->Set("object_id", static_pointer_cast<Host>(object));
/* this is obviously bullshit, but otherwise we would hit /* this is obviously bullshit, but otherwise we would hit
* the unique constraint on the table for the same service * the unique constraint on the table for the same service
* comment. dynamically incremented/decremented numbers as * 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); fields1->Set("internal_comment_id", 0);
} else if (object->GetType() == DynamicType::GetByName("Service")) { } else if (object->GetType() == DynamicType::GetByName("Service")) {
fields1->Set("comment_type", 1); fields1->Set("comment_type", 1);
fields1->Set("object_id", static_pointer_cast<Service>(object));
fields1->Set("internal_comment_id", comment->Get("legacy_id")); fields1->Set("internal_comment_id", comment->Get("legacy_id"));
} else { } else {
Log(LogDebug, "ido", "unknown object type for adding comment."); 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); query2.WhereCriteria->Set("object_id", host);
OnQuery(query2); 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<Service>(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<long>(downtime->Get("entry_time"));
unsigned long entry_time_usec = (downtime->Get("entry_time") - entry_time) * 1000 * 1000;
Dictionary::Ptr fields1 = boost::make_shared<Dictionary>();
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<Dictionary>();
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<Dictionary>();
query2.WhereCriteria->Set("object_id", host);
OnQuery(query2);
}
} }

View File

@ -50,12 +50,18 @@ protected:
virtual void OnConfigUpdate(void); virtual void OnConfigUpdate(void);
virtual void OnStatusUpdate(void); virtual void OnStatusUpdate(void);
private:
static void CommentsChangedHandler(const Service::Ptr& service, const String& id, CommentChangedType type); static void CommentsChangedHandler(const Service::Ptr& service, const String& id, CommentChangedType type);
static void AddComments(const Service::Ptr& service); static void AddComments(const Service::Ptr& service);
static void AddComment(const Service::Ptr& service, const Dictionary::Ptr& comment); static void AddComment(const Service::Ptr& service, const Dictionary::Ptr& comment);
static void AddCommentByType(const DynamicObject::Ptr& object, const Dictionary::Ptr& comment); static void AddCommentByType(const DynamicObject::Ptr& object, const Dictionary::Ptr& comment);
static void DeleteComments(const Service::Ptr& service); 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);
}; };
} }