Convert Comment/Downtime to config objects

fixes #9777
This commit is contained in:
Gunnar Beutner 2015-08-20 17:18:48 +02:00 committed by Michael Friedrich
parent de8aae90e4
commit 050c520b2a
85 changed files with 1178 additions and 1547 deletions

View File

@ -78,7 +78,7 @@ void Application::OnConfigLoaded(void)
/**
* Destructor for the application class.
*/
void Application::Stop(void)
void Application::Stop(bool runtimeRemoved)
{
m_ShuttingDown = true;
@ -102,7 +102,7 @@ void Application::Stop(void)
} else
ClosePidFile(true);
ObjectImpl<Application>::Stop();
ObjectImpl<Application>::Stop(runtimeRemoved);
}
Application::~Application(void)

View File

@ -138,7 +138,7 @@ public:
protected:
virtual void OnConfigLoaded(void) override;
virtual void Stop(void) override;
virtual void Stop(bool runtimeRemoved) override;
void RunEventLoop(void);

View File

@ -374,9 +374,9 @@ void ConfigObject::Unregister(void)
dtype->UnregisterObject(this);
}
void ConfigObject::Start(void)
void ConfigObject::Start(bool runtimeCreated)
{
ObjectImpl<ConfigObject>::Start();
ObjectImpl<ConfigObject>::Start(runtimeCreated);
ASSERT(!OwnsLock());
ObjectLock olock(this);
@ -384,13 +384,13 @@ void ConfigObject::Start(void)
SetStartCalled(true);
}
void ConfigObject::Activate(void)
void ConfigObject::Activate(bool runtimeCreated)
{
CONTEXT("Activating object '" + GetName() + "' of type '" + GetType()->GetName() + "'");
ASSERT(!OwnsLock());
Start();
Start(runtimeCreated);
ASSERT(GetStartCalled());
@ -405,9 +405,9 @@ void ConfigObject::Activate(void)
NotifyActive();
}
void ConfigObject::Stop(void)
void ConfigObject::Stop(bool runtimeRemoved)
{
ObjectImpl<ConfigObject>::Stop();
ObjectImpl<ConfigObject>::Stop(runtimeRemoved);
ASSERT(!OwnsLock());
ObjectLock olock(this);
@ -415,7 +415,7 @@ void ConfigObject::Stop(void)
SetStopCalled(true);
}
void ConfigObject::Deactivate(void)
void ConfigObject::Deactivate(bool runtimeRemoved)
{
CONTEXT("Deactivating object '" + GetName() + "' of type '" + GetType()->GetName() + "'");
@ -432,7 +432,7 @@ void ConfigObject::Deactivate(void)
SetActive(false, true);
}
Stop();
Stop(runtimeRemoved);
ASSERT(GetStopCalled());

View File

@ -60,12 +60,12 @@ public:
void Register(void);
void Unregister(void);
void Activate(void);
void Deactivate(void);
void Activate(bool runtimeCreated = false);
void Deactivate(bool runtimeRemoved = false);
void SetAuthority(bool authority);
virtual void Start(void) override;
virtual void Stop(void) override;
virtual void Start(bool runtimeCreated = false) override;
virtual void Stop(bool runtimeRemoved = false) override;
virtual void Pause(void);
virtual void Resume(void);

View File

@ -55,10 +55,10 @@ public:
m_DebugInfo = di;
}
inline virtual void Start(void)
inline virtual void Start(bool runtimeCreated)
{ }
inline virtual void Stop(void)
inline virtual void Stop(bool runtimeRemoved)
{ }
private:

View File

@ -165,7 +165,7 @@ void ConfigWriter::EmitIdentifier(std::ostream& fp, const String& identifier, bo
}
void ConfigWriter::EmitConfigItem(std::ostream& fp, const String& type, const String& name, bool isTemplate,
const Array::Ptr& imports, const Dictionary::Ptr& attrs)
bool ignoreOnError, const Array::Ptr& imports, const Dictionary::Ptr& attrs)
{
if (isTemplate)
fp << "template ";
@ -175,6 +175,10 @@ void ConfigWriter::EmitConfigItem(std::ostream& fp, const String& type, const St
EmitIdentifier(fp, type, false);
fp << " ";
EmitString(fp, name);
if (ignoreOnError)
fp << " ignore_on_error";
fp << " ";
EmitScope(fp, 1, attrs, imports);
}

View File

@ -50,7 +50,7 @@ public:
static void EmitIdentifier(std::ostream& fp, const String& identifier, bool inAssignment);
static void EmitConfigItem(std::ostream& fp, const String& type, const String& name, bool isTemplate,
const Array::Ptr& imports, const Dictionary::Ptr& attrs);
bool ignoreOnError, const Array::Ptr& imports, const Dictionary::Ptr& attrs);
static void EmitComment(std::ostream& fp, const String& text);
static void EmitFunctionCall(std::ostream& fp, const String& name, const Array::Ptr& arguments);

View File

@ -44,9 +44,9 @@ void FileLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
/**
* Constructor for the FileLogger class.
*/
void FileLogger::Start(void)
void FileLogger::Start(bool runtimeCreated)
{
ObjectImpl<FileLogger>::Start();
ObjectImpl<FileLogger>::Start(runtimeCreated);
ReopenLogFile();

View File

@ -39,7 +39,7 @@ public:
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
void ReopenLogFile(void);

View File

@ -52,22 +52,22 @@ void Logger::StaticInitialize(void)
/**
* Constructor for the Logger class.
*/
void Logger::Start(void)
void Logger::Start(bool runtimeCreated)
{
ObjectImpl<Logger>::Start();
ObjectImpl<Logger>::Start(runtimeCreated);
boost::mutex::scoped_lock lock(m_Mutex);
m_Loggers.insert(this);
}
void Logger::Stop(void)
void Logger::Stop(bool runtimeRemoved)
{
{
boost::mutex::scoped_lock lock(m_Mutex);
m_Loggers.erase(this);
}
ObjectImpl<Logger>::Stop();
ObjectImpl<Logger>::Stop(runtimeRemoved);
}
std::set<Logger::Ptr> Logger::GetLoggers(void)

View File

@ -93,8 +93,8 @@ public:
static void StaticInitialize(void);
protected:
virtual void Start(void) override;
virtual void Stop(void) override;
virtual void Start(bool runtimeCreated) override;
virtual void Stop(bool runtimeRemoved) override;
private:
static boost::mutex m_Mutex;

View File

@ -37,9 +37,9 @@ StreamLogger::StreamLogger(void)
: m_Stream(NULL), m_OwnsStream(false)
{ }
void StreamLogger::Stop(void)
void StreamLogger::Stop(bool runtimeRemoved)
{
ObjectImpl<StreamLogger>::Stop();
ObjectImpl<StreamLogger>::Stop(runtimeRemoved);
// make sure we flush the log data on shutdown, even if we don't call the destructor
if (m_Stream)

View File

@ -40,7 +40,7 @@ public:
StreamLogger(void);
virtual void Stop(void) override;
virtual void Stop(bool runtimeRemoved) override;
~StreamLogger(void);
void BindStream(std::ostream *stream, bool ownsStream);

View File

@ -72,9 +72,9 @@ void CheckerComponent::OnConfigLoaded(void)
Checkable::OnNextCheckChanged.connect(bind(&CheckerComponent::NextCheckChangedHandler, this, _1));
}
void CheckerComponent::Start(void)
void CheckerComponent::Start(bool runtimeCreated)
{
ObjectImpl<CheckerComponent>::Start();
ObjectImpl<CheckerComponent>::Start(runtimeCreated);
m_Thread = boost::thread(boost::bind(&CheckerComponent::CheckThreadProc, this));
@ -84,7 +84,7 @@ void CheckerComponent::Start(void)
m_ResultTimer->Start();
}
void CheckerComponent::Stop(void)
void CheckerComponent::Stop(bool runtimeRemoved)
{
Log(LogInformation, "CheckerComponent", "Checker stopped.");
@ -97,7 +97,7 @@ void CheckerComponent::Stop(void)
m_ResultTimer->Stop();
m_Thread.join();
ObjectImpl<CheckerComponent>::Stop();
ObjectImpl<CheckerComponent>::Stop(runtimeRemoved);
}
void CheckerComponent::CheckThreadProc(void)

View File

@ -71,8 +71,8 @@ public:
CheckerComponent(void);
virtual void OnConfigLoaded(void) override;
virtual void Start(void) override;
virtual void Stop(void) override;
virtual void Start(bool runtimeCreated) override;
virtual void Stop(bool runtimeRemoved) override;
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
unsigned long GetIdleCheckables(void);

View File

@ -54,9 +54,9 @@ void CheckResultReader::StatsFunc(const Dictionary::Ptr& status, const Array::Pt
/**
* @threadsafety Always.
*/
void CheckResultReader::Start(void)
void CheckResultReader::Start(bool runtimeCreated)
{
ObjectImpl<CheckResultReader>::Start();
ObjectImpl<CheckResultReader>::Start(runtimeCreated);
m_ReadTimer = new Timer();
m_ReadTimer->OnTimerExpired.connect(boost::bind(&CheckResultReader::ReadTimerHandler, this));

View File

@ -41,7 +41,7 @@ public:
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
protected:
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
Timer::Ptr m_ReadTimer;

View File

@ -57,14 +57,14 @@ void CompatLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
/**
* @threadsafety Always.
*/
void CompatLogger::Start(void)
void CompatLogger::Start(bool runtimeCreated)
{
ObjectImpl<CompatLogger>::Start();
ObjectImpl<CompatLogger>::Start(runtimeCreated);
Checkable::OnNewCheckResult.connect(bind(&CompatLogger::CheckResultHandler, this, _1, _2));
Checkable::OnNotificationSentToUser.connect(bind(&CompatLogger::NotificationSentHandler, this, _1, _2, _3, _4, _5, _6, _7, _8));
Checkable::OnDowntimeTriggered.connect(boost::bind(&CompatLogger::TriggerDowntimeHandler, this, _1, _2));
Checkable::OnDowntimeRemoved.connect(boost::bind(&CompatLogger::RemoveDowntimeHandler, this, _1, _2));
Downtime::OnDowntimeTriggered.connect(boost::bind(&CompatLogger::TriggerDowntimeHandler, this, _1));
Downtime::OnDowntimeRemoved.connect(boost::bind(&CompatLogger::RemoveDowntimeHandler, this, _1));
Checkable::OnEventCommandExecuted.connect(bind(&CompatLogger::EventCommandHandler, this, _1));
Checkable::OnFlappingChanged.connect(boost::bind(&CompatLogger::FlappingChangedHandler, this, _1));
@ -147,11 +147,11 @@ void CompatLogger::CheckResultHandler(const Checkable::Ptr& checkable, const Che
/**
* @threadsafety Always.
*/
void CompatLogger::TriggerDowntimeHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime)
void CompatLogger::TriggerDowntimeHandler(const Downtime::Ptr& downtime)
{
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
tie(host, service) = GetHostService(downtime->GetCheckable());
if (!downtime)
return;
@ -183,11 +183,11 @@ void CompatLogger::TriggerDowntimeHandler(const Checkable::Ptr& checkable, const
/**
* @threadsafety Always.
*/
void CompatLogger::RemoveDowntimeHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime)
void CompatLogger::RemoveDowntimeHandler(const Downtime::Ptr& downtime)
{
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
tie(host, service) = GetHostService(downtime->GetCheckable());
if (!downtime)
return;

View File

@ -44,7 +44,7 @@ public:
virtual void ValidateRotationMethod(const String& value, const ValidationUtils& utils) override;
protected:
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
void WriteLine(const String& line);
@ -56,8 +56,8 @@ private:
const String& author, const String& comment_text, const String& command_name);
void FlappingChangedHandler(const Checkable::Ptr& checkable);
void EnableFlappingChangedHandler(const Checkable::Ptr& checkable);
void TriggerDowntimeHandler(const Checkable::Ptr& service, const Downtime::Ptr& downtime);
void RemoveDowntimeHandler(const Checkable::Ptr& service, const Downtime::Ptr& downtime);
void TriggerDowntimeHandler(const Downtime::Ptr& downtime);
void RemoveDowntimeHandler(const Downtime::Ptr& downtime);
void ExternalCommandHandler(const String& command, const std::vector<String>& arguments);
void EventCommandHandler(const Checkable::Ptr& service);

View File

@ -46,9 +46,9 @@ void ExternalCommandListener::StatsFunc(const Dictionary::Ptr& status, const Arr
/**
* Starts the component.
*/
void ExternalCommandListener::Start(void)
void ExternalCommandListener::Start(bool runtimeCreated)
{
ObjectImpl<ExternalCommandListener>::Start();
ObjectImpl<ExternalCommandListener>::Start(runtimeCreated);
#ifndef _WIN32
m_CommandThread = boost::thread(boost::bind(&ExternalCommandListener::CommandPipeThread, this, GetCommandPath()));

View File

@ -42,7 +42,7 @@ public:
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
protected:
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
#ifndef _WIN32

View File

@ -70,9 +70,9 @@ void StatusDataWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr
/**
* Starts the component.
*/
void StatusDataWriter::Start(void)
void StatusDataWriter::Start(bool runtimeCreated)
{
ObjectImpl<StatusDataWriter>::Start();
ObjectImpl<StatusDataWriter>::Start(runtimeCreated);
m_ObjectsCacheOutdated = true;
@ -88,17 +88,11 @@ void StatusDataWriter::Start(void)
void StatusDataWriter::DumpComments(std::ostream& fp, const Checkable::Ptr& checkable)
{
Dictionary::Ptr comments = checkable->GetComments();
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
ObjectLock olock(comments);
BOOST_FOREACH(const Dictionary::Pair& kv, comments) {
Comment::Ptr comment = kv.second;
BOOST_FOREACH(const Comment::Ptr& comment, checkable->GetComments()) {
if (comment->IsExpired())
continue;
@ -160,17 +154,11 @@ void StatusDataWriter::DumpCommand(std::ostream& fp, const Command::Ptr& command
void StatusDataWriter::DumpDowntimes(std::ostream& fp, const Checkable::Ptr& checkable)
{
Dictionary::Ptr downtimes = checkable->GetDowntimes();
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
ObjectLock olock(downtimes);
BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
Downtime::Ptr downtime = kv.second;
BOOST_FOREACH(const Downtime::Ptr& downtime, checkable->GetDowntimes()) {
if (downtime->IsExpired())
continue;
@ -180,7 +168,7 @@ void StatusDataWriter::DumpDowntimes(std::ostream& fp, const Checkable::Ptr& che
else
fp << "hostdowntime {" "\n";
Downtime::Ptr triggeredByObj = Service::GetDowntimeByID(downtime->GetTriggeredBy());
Downtime::Ptr triggeredByObj = Downtime::GetByName(downtime->GetTriggeredBy());
int triggeredByLegacy = 0;
if (triggeredByObj)
triggeredByLegacy = triggeredByObj->GetLegacyId();
@ -830,8 +818,8 @@ void StatusDataWriter::StatusTimerHandler(void)
"\t" "passive_host_check_stats=" << CIB::GetPassiveHostChecksStatistics(60) << "," << CIB::GetPassiveHostChecksStatistics(5 * 60) << "," << CIB::GetPassiveHostChecksStatistics(15 * 60) << "\n"
"\t" "active_scheduled_service_check_stats=" << CIB::GetActiveServiceChecksStatistics(60) << "," << CIB::GetActiveServiceChecksStatistics(5 * 60) << "," << CIB::GetActiveServiceChecksStatistics(15 * 60) << "\n"
"\t" "passive_service_check_stats=" << CIB::GetPassiveServiceChecksStatistics(60) << "," << CIB::GetPassiveServiceChecksStatistics(5 * 60) << "," << CIB::GetPassiveServiceChecksStatistics(15 * 60) << "\n"
"\t" "next_downtime_id=" << Service::GetNextDowntimeID() << "\n"
"\t" "next_comment_id=" << Service::GetNextCommentID() << "\n";
"\t" "next_downtime_id=" << Downtime::GetNextDowntimeID() << "\n"
"\t" "next_comment_id=" << Comment::GetNextCommentID() << "\n";
statusfp << "\t" "}" "\n"
"\n";

View File

@ -47,7 +47,7 @@ public:
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
protected:
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
Timer::Ptr m_StatusTimer;

View File

@ -224,7 +224,19 @@ ConfigObject::Ptr ConfigItem::Commit(bool discard)
dobj->SetShortName(item_name);
dobj->SetName(name);
dobj->OnConfigLoaded();
try {
dobj->OnConfigLoaded();
} catch (const std::exception& ex) {
if (m_IgnoreOnError) {
Log(LogWarning, "ConfigObject")
<< "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex);
return ConfigObject::Ptr();
}
throw;
}
{
boost::mutex::scoped_lock lock(m_Mutex);
@ -342,6 +354,24 @@ ConfigItem::Ptr ConfigItem::GetByTypeAndName(const String& type, const String& n
return it2->second;
}
void ConfigItem::OnAllConfigLoadedWrapper(void)
{
try {
m_Object->OnAllConfigLoaded();
} catch (const std::exception& ex) {
if (m_IgnoreOnError) {
Log(LogWarning, "ConfigObject")
<< "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex);
Unregister();
return;
}
throw;
}
}
bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector<ConfigItem::Ptr>& newItems)
{
typedef std::pair<ConfigItem::Ptr, bool> ItemPair;
@ -429,7 +459,7 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector<ConfigItem::Ptr>& ne
continue;
if (item->m_Type == type)
upq.Enqueue(boost::bind(&ConfigObject::OnAllConfigLoaded, item->m_Object));
upq.Enqueue(boost::bind(&ConfigItem::OnAllConfigLoadedWrapper, item));
}
completed_types.insert(type);
@ -498,8 +528,11 @@ bool ConfigItem::CommitItems(WorkQueue& upq)
return true;
}
bool ConfigItem::ActivateItems(WorkQueue& upq, bool restoreState)
bool ConfigItem::ActivateItems(WorkQueue& upq, bool restoreState, bool runtimeCreated)
{
static boost::mutex mtx;
boost::mutex::scoped_lock lock(mtx);
if (restoreState) {
/* restore the previous program state */
try {
@ -521,7 +554,7 @@ bool ConfigItem::ActivateItems(WorkQueue& upq, bool restoreState)
Log(LogDebug, "ConfigItem")
<< "Activating object '" << object->GetName() << "' of type '" << object->GetType()->GetName() << "'";
#endif /* I2_DEBUG */
upq.Enqueue(boost::bind(&ConfigObject::Activate, object));
upq.Enqueue(boost::bind(&ConfigObject::Activate, object, runtimeCreated));
}
}

View File

@ -68,7 +68,7 @@ public:
const String& name);
static bool CommitItems(WorkQueue& upq);
static bool ActivateItems(WorkQueue& upq, bool restoreState);
static bool ActivateItems(WorkQueue& upq, bool restoreState, bool runtimeCreated = false);
static bool CommitAndActivate(void);
@ -103,6 +103,8 @@ private:
const String& name);
static bool CommitNewItems(WorkQueue& upq, std::vector<ConfigItem::Ptr>& newItems);
void OnAllConfigLoadedWrapper(void);
};
}

View File

@ -56,9 +56,9 @@ void DbConnection::OnConfigLoaded(void)
boost::call_once(m_OnceFlag, InitializeDbTimer);
}
void DbConnection::Start(void)
void DbConnection::Start(bool runtimeCreated)
{
ObjectImpl<DbConnection>::Start();
ObjectImpl<DbConnection>::Start(runtimeCreated);
DbObject::OnQuery.connect(boost::bind(&DbConnection::ExecuteQuery, this, _1));
ConfigObject::OnActiveChanged.connect(boost::bind(&DbConnection::UpdateObject, this, _1));

View File

@ -78,7 +78,7 @@ public:
protected:
virtual void OnConfigLoaded(void) override;
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
virtual void Resume(void) override;
virtual void Pause(void) override;

View File

@ -43,11 +43,11 @@ INITIALIZE_ONCE(&DbEvents::StaticInitialize);
void DbEvents::StaticInitialize(void)
{
/* Status */
Checkable::OnCommentAdded.connect(boost::bind(&DbEvents::AddComment, _1, _2));
Checkable::OnCommentRemoved.connect(boost::bind(&DbEvents::RemoveComment, _1, _2));
Checkable::OnDowntimeAdded.connect(boost::bind(&DbEvents::AddDowntime, _1, _2, true));
Checkable::OnDowntimeRemoved.connect(boost::bind(&DbEvents::RemoveDowntime, _1, _2));
Checkable::OnDowntimeTriggered.connect(boost::bind(&DbEvents::TriggerDowntime, _1, _2));
Comment::OnCommentAdded.connect(boost::bind(&DbEvents::AddComment, _1));
Comment::OnCommentRemoved.connect(boost::bind(&DbEvents::RemoveComment, _1));
Downtime::OnDowntimeAdded.connect(boost::bind(&DbEvents::AddDowntime, _1, true));
Downtime::OnDowntimeRemoved.connect(boost::bind(&DbEvents::RemoveDowntime, _1));
Downtime::OnDowntimeTriggered.connect(boost::bind(&DbEvents::TriggerDowntime, _1));
Checkable::OnAcknowledgementSet.connect(boost::bind(&DbEvents::AddAcknowledgement, _1, _4));
Checkable::OnAcknowledgementCleared.connect(boost::bind(&DbEvents::RemoveAcknowledgement, _1));
@ -64,8 +64,8 @@ void DbEvents::StaticInitialize(void)
Checkable::OnReachabilityChanged.connect(boost::bind(&DbEvents::ReachabilityChangedHandler, _1, _2, _3));
/* History */
Checkable::OnCommentAdded.connect(boost::bind(&DbEvents::AddCommentHistory, _1, _2));
Checkable::OnDowntimeAdded.connect(boost::bind(&DbEvents::AddDowntimeHistory, _1, _2));
Comment::OnCommentAdded.connect(boost::bind(&DbEvents::AddCommentHistory, _1));
Downtime::OnDowntimeAdded.connect(boost::bind(&DbEvents::AddDowntimeHistory, _1));
Checkable::OnAcknowledgementSet.connect(boost::bind(&DbEvents::AddAcknowledgementHistory, _1, _2, _3, _4, _5, _6));
Checkable::OnNotificationSentToAllUsers.connect(boost::bind(&DbEvents::AddNotificationHistory, _1, _2, _3, _4, _5, _6, _7));
@ -76,8 +76,8 @@ void DbEvents::StaticInitialize(void)
Checkable::OnNotificationSentToUser.connect(boost::bind(&DbEvents::AddNotificationSentLogHistory, _1, _2, _3, _4, _5, _6, _7));
Checkable::OnFlappingChanged.connect(boost::bind(&DbEvents::AddFlappingChangedLogHistory, _1));
Checkable::OnEnableFlappingChanged.connect(boost::bind(&DbEvents::AddEnableFlappingChangedLogHistory, _1));
Checkable::OnDowntimeTriggered.connect(boost::bind(&DbEvents::AddTriggerDowntimeLogHistory, _1, _2));
Checkable::OnDowntimeRemoved.connect(boost::bind(&DbEvents::AddRemoveDowntimeLogHistory, _1, _2));
Downtime::OnDowntimeTriggered.connect(boost::bind(&DbEvents::AddTriggerDowntimeLogHistory, _1));
Downtime::OnDowntimeRemoved.connect(boost::bind(&DbEvents::AddRemoveDowntimeLogHistory, _1));
Checkable::OnFlappingChanged.connect(boost::bind(&DbEvents::AddFlappingChangedHistory, _1));
Checkable::OnEnableFlappingChanged.connect(boost::bind(&DbEvents::AddEnableFlappingChangedHistory, _1));
@ -303,45 +303,30 @@ void DbEvents::EnableChangedHandlerInternal(const Checkable::Ptr& checkable, con
/* comments */
void DbEvents::AddComments(const Checkable::Ptr& checkable)
{
/* dump all comments */
Dictionary::Ptr comments = checkable->GetComments();
if (comments->GetLength() > 0)
RemoveComments(checkable);
ObjectLock olock(comments);
BOOST_FOREACH(const Dictionary::Pair& kv, comments) {
AddComment(checkable, kv.second);
BOOST_FOREACH(const Comment::Ptr& comment, checkable->GetComments()) {
AddComment(comment);
}
}
void DbEvents::AddComment(const Checkable::Ptr& checkable, const Comment::Ptr& comment)
void DbEvents::AddComment(const Comment::Ptr& comment)
{
AddCommentInternal(checkable, comment, false);
AddCommentInternal(comment, false);
}
void DbEvents::AddCommentHistory(const Checkable::Ptr& checkable, const Comment::Ptr& comment)
void DbEvents::AddCommentHistory(const Comment::Ptr& comment)
{
AddCommentInternal(checkable, comment, true);
AddCommentInternal(comment, true);
}
void DbEvents::AddCommentInternal(const Checkable::Ptr& checkable, const Comment::Ptr& comment, bool historical)
void DbEvents::AddCommentInternal(const Comment::Ptr& comment, bool historical)
{
if (!comment) {
Log(LogWarning, "DbEvents", "comment does not exist. not adding it.");
return;
}
Log(LogDebug, "DbEvents")
<< "adding service comment (id = " << comment->GetLegacyId() << ") for '" << checkable->GetName() << "'";
/* add the service comment */
AddCommentByType(checkable, comment, historical);
AddCommentByType(comment, historical);
}
void DbEvents::AddCommentByType(const ConfigObject::Ptr& object, const Comment::Ptr& comment, bool historical)
void DbEvents::AddCommentByType(const Comment::Ptr& comment, bool historical)
{
Checkable::Ptr checkable = comment->GetCheckable();
unsigned long entry_time = static_cast<long>(comment->GetEntryTime());
unsigned long entry_time_usec = (comment->GetEntryTime() - entry_time) * 1000 * 1000;
@ -349,13 +334,13 @@ void DbEvents::AddCommentByType(const ConfigObject::Ptr& object, const Comment::
fields1->Set("entry_time", DbValue::FromTimestamp(entry_time));
fields1->Set("entry_time_usec", entry_time_usec);
fields1->Set("entry_type", comment->GetEntryType());
fields1->Set("object_id", object);
fields1->Set("object_id", checkable);
if (object->GetType() == ConfigType::GetByName("Host")) {
if (checkable->GetType() == ConfigType::GetByName("Host")) {
fields1->Set("comment_type", 2);
/* requires idoutils 1.10 schema fix */
fields1->Set("internal_comment_id", comment->GetLegacyId());
} else if (object->GetType() == ConfigType::GetByName("Service")) {
} else if (checkable->GetType() == ConfigType::GetByName("Service")) {
fields1->Set("comment_type", 1);
fields1->Set("internal_comment_id", comment->GetLegacyId());
} else {
@ -404,15 +389,9 @@ void DbEvents::RemoveComments(const Checkable::Ptr& checkable)
DbObject::OnQuery(query1);
}
void DbEvents::RemoveComment(const Checkable::Ptr& checkable, const Comment::Ptr& comment)
void DbEvents::RemoveComment(const Comment::Ptr& comment)
{
if (!comment) {
Log(LogWarning, "DbEvents", "comment does not exist. not deleting it.");
return;
}
Log(LogDebug, "DbEvents")
<< "removing service comment (id = " << comment->GetLegacyId() << ") for '" << checkable->GetName() << "'";
Checkable::Ptr checkable = comment->GetCheckable();
/* Status */
DbQuery query1;
@ -451,51 +430,39 @@ void DbEvents::RemoveComment(const Checkable::Ptr& checkable, const Comment::Ptr
/* downtimes */
void DbEvents::AddDowntimes(const Checkable::Ptr& checkable)
{
/* dump all downtimes */
Dictionary::Ptr downtimes = checkable->GetDowntimes();
RemoveDowntimes(checkable);
if (downtimes->GetLength() > 0)
RemoveDowntimes(checkable);
ObjectLock olock(downtimes);
BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
AddDowntime(checkable, kv.second, false);
BOOST_FOREACH(const Downtime::Ptr& downtime, checkable->GetDowntimes()) {
AddDowntime(downtime, false);
}
}
void DbEvents::AddDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool remove_existing)
void DbEvents::AddDowntime(const Downtime::Ptr& downtime, bool remove_existing)
{
/*
* make sure to delete any old downtime to avoid multiple inserts from
* configured ScheduledDowntime dumps and CreateNextDowntime() calls
*/
if (remove_existing)
RemoveDowntime(checkable, downtime);
AddDowntimeInternal(checkable, downtime, false);
RemoveDowntime(downtime);
AddDowntimeInternal(downtime, false);
}
void DbEvents::AddDowntimeHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime)
void DbEvents::AddDowntimeHistory(const Downtime::Ptr& downtime)
{
AddDowntimeInternal(checkable, downtime, true);
AddDowntimeInternal(downtime, true);
}
void DbEvents::AddDowntimeInternal(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool historical)
void DbEvents::AddDowntimeInternal(const Downtime::Ptr& downtime, bool historical)
{
if (!downtime) {
Log(LogWarning, "DbEvents", "downtime does not exist. not adding it.");
return;
}
Log(LogDebug, "DbEvents")
<< "adding service downtime (id = " << downtime->GetLegacyId() << ") for '" << checkable->GetName() << "'";
/* add the downtime */
AddDowntimeByType(checkable, downtime, historical);
AddDowntimeByType(downtime, historical);
}
void DbEvents::AddDowntimeByType(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool historical)
void DbEvents::AddDowntimeByType(const Downtime::Ptr& downtime, bool historical)
{
Checkable::Ptr checkable = downtime->GetCheckable();
Dictionary::Ptr fields1 = new Dictionary();
fields1->Set("entry_time", DbValue::FromTimestamp(downtime->GetEntryTime()));
fields1->Set("object_id", checkable);
@ -514,7 +481,7 @@ void DbEvents::AddDowntimeByType(const Checkable::Ptr& checkable, const Downtime
fields1->Set("author_name", downtime->GetAuthor());
fields1->Set("comment_data", downtime->GetComment());
fields1->Set("triggered_by_id", Service::GetDowntimeByID(downtime->GetTriggeredBy()));
fields1->Set("triggered_by_id", Downtime::GetByName(downtime->GetTriggeredBy()));
fields1->Set("is_fixed", downtime->GetFixed() ? 1 : 0);
fields1->Set("duration", downtime->GetDuration());
fields1->Set("scheduled_start_time", DbValue::FromTimestamp(downtime->GetStartTime()));
@ -544,9 +511,6 @@ void DbEvents::AddDowntimeByType(const Checkable::Ptr& checkable, const Downtime
void DbEvents::RemoveDowntimes(const Checkable::Ptr& checkable)
{
Log(LogDebug, "DbEvents")
<< "removing service downtimes for '" << checkable->GetName() << "'";
DbQuery query1;
query1.Table = "scheduleddowntime";
query1.Type = DbQueryDelete;
@ -556,15 +520,9 @@ void DbEvents::RemoveDowntimes(const Checkable::Ptr& checkable)
DbObject::OnQuery(query1);
}
void DbEvents::RemoveDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime)
void DbEvents::RemoveDowntime(const Downtime::Ptr& downtime)
{
if (!downtime) {
Log(LogWarning, "DbEvents", "downtime does not exist. not adding it.");
return;
}
Log(LogDebug, "DbEvents")
<< "removing service downtime (id = " << downtime->GetLegacyId() << ") for '" << checkable->GetName() << "'";
Checkable::Ptr checkable = downtime->GetCheckable();
/* Status */
DbQuery query1;
@ -632,15 +590,9 @@ void DbEvents::RemoveDowntime(const Checkable::Ptr& checkable, const Downtime::P
DbObject::OnQuery(query4);
}
void DbEvents::TriggerDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime)
void DbEvents::TriggerDowntime(const Downtime::Ptr& downtime)
{
if (!downtime) {
Log(LogWarning, "DbEvents", "downtime does not exist. not updating it.");
return;
}
Log(LogDebug, "DbEvents")
<< "updating triggered service downtime (id = " << downtime->GetLegacyId() << ") for '" << checkable->GetName() << "'";
Checkable::Ptr checkable = downtime->GetCheckable();
double now = Utility::GetTime();
std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(now);
@ -1036,10 +988,9 @@ void DbEvents::AddCheckResultLogHistory(const Checkable::Ptr& checkable, const C
AddLogHistory(checkable, msgbuf.str(), type);
}
void DbEvents::AddTriggerDowntimeLogHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime)
void DbEvents::AddTriggerDowntimeLogHistory(const Downtime::Ptr& downtime)
{
if (!downtime)
return;
Checkable::Ptr checkable = downtime->GetCheckable();
Host::Ptr host;
Service::Ptr service;
@ -1065,10 +1016,9 @@ void DbEvents::AddTriggerDowntimeLogHistory(const Checkable::Ptr& checkable, con
AddLogHistory(checkable, msgbuf.str(), LogEntryTypeInfoMessage);
}
void DbEvents::AddRemoveDowntimeLogHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime)
void DbEvents::AddRemoveDowntimeLogHistory(const Downtime::Ptr& downtime)
{
if (!downtime)
return;
Checkable::Ptr checkable = downtime->GetCheckable();
String downtime_output;
String downtime_state_str;

View File

@ -61,11 +61,11 @@ class DbEvents
public:
static void StaticInitialize(void);
static void AddCommentByType(const ConfigObject::Ptr& object, const Comment::Ptr& comment, bool historical);
static void AddCommentByType(const Comment::Ptr& comment, bool historical);
static void AddComments(const Checkable::Ptr& checkable);
static void RemoveComments(const Checkable::Ptr& checkable);
static void AddDowntimeByType(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool historical);
static void AddDowntimeByType(const Downtime::Ptr& downtime, bool historical);
static void AddDowntimes(const Checkable::Ptr& checkable);
static void RemoveDowntimes(const Checkable::Ptr& checkable);
@ -82,12 +82,12 @@ public:
static void EnablePerfdataChangedHandler(const Checkable::Ptr& checkable);
static void EnableFlappingChangedHandler(const Checkable::Ptr& checkable);
static void AddComment(const Checkable::Ptr& checkable, const Comment::Ptr& comment);
static void RemoveComment(const Checkable::Ptr& checkable, const Comment::Ptr& comment);
static void AddComment(const Comment::Ptr& comment);
static void RemoveComment(const Comment::Ptr& comment);
static void AddDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool remove_existing);
static void RemoveDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime);
static void TriggerDowntime(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime);
static void AddDowntime(const Downtime::Ptr& downtime, bool remove_existing);
static void RemoveDowntime(const Downtime::Ptr& downtime);
static void TriggerDowntime(const Downtime::Ptr& downtime);
static void AddAcknowledgement(const Checkable::Ptr& checkable, AcknowledgementType type);
static void RemoveAcknowledgement(const Checkable::Ptr& checkable);
@ -96,8 +96,8 @@ public:
static void ReachabilityChangedHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, std::set<Checkable::Ptr> children);
/* comment, downtime, acknowledgement history */
static void AddCommentHistory(const Checkable::Ptr& checkable, const Comment::Ptr& comment);
static void AddDowntimeHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime);
static void AddCommentHistory(const Comment::Ptr& comment);
static void AddDowntimeHistory(const Downtime::Ptr& downtime);
static void AddAcknowledgementHistory(const Checkable::Ptr& checkable, const String& author, const String& comment,
AcknowledgementType type, bool notify, double expiry);
@ -111,8 +111,8 @@ public:
/* logentries */
static void AddCheckResultLogHistory(const Checkable::Ptr& checkable, const CheckResult::Ptr &cr);
static void AddTriggerDowntimeLogHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime);
static void AddRemoveDowntimeLogHistory(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime);
static void AddTriggerDowntimeLogHistory(const Downtime::Ptr& downtime);
static void AddRemoveDowntimeLogHistory(const Downtime::Ptr& downtime);
static void AddNotificationSentLogHistory(const Notification::Ptr& notification, const Checkable::Ptr& checkable,
const User::Ptr& user, NotificationType notification_type, const CheckResult::Ptr& cr, const String& author,
const String& comment_text);
@ -130,8 +130,8 @@ public:
private:
DbEvents(void);
static void AddCommentInternal(const Checkable::Ptr& checkable, const Comment::Ptr& comment, bool historical);
static void AddDowntimeInternal(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, bool historical);
static void AddCommentInternal(const Comment::Ptr& comment, bool historical);
static void AddDowntimeInternal(const Downtime::Ptr& downtime, bool historical);
static void EnableChangedHandlerInternal(const Checkable::Ptr& checkable, const String& fieldName, bool enabled);
};

View File

@ -33,9 +33,9 @@ REGISTER_APIFUNCTION(HelloWorld, demo, &Demo::DemoMessageHandler);
/**
* Starts the component.
*/
void Demo::Start(void)
void Demo::Start(bool runtimeCreated)
{
ObjectImpl<Demo>::Start();
ObjectImpl<Demo>::Start(runtimeCreated);
m_DemoTimer = new Timer();
m_DemoTimer->SetInterval(5);

View File

@ -36,7 +36,7 @@ public:
DECLARE_OBJECT(Demo);
DECLARE_OBJECTNAME(Demo);
virtual void Start(void);
virtual void Start(bool runtimeCreated);
static Value DemoMessageHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);

View File

@ -215,7 +215,7 @@ Dictionary::Ptr ApiActions::AcknowledgeProblem(const ConfigObject::Ptr& object,
return ApiActions::CreateResult(409, "Service " + checkable->GetName() + " is OK.");
}
checkable->AddComment(CommentAcknowledgement, HttpUtility::GetLastParameter(params, "author"),
Comment::AddComment(checkable, CommentAcknowledgement, HttpUtility::GetLastParameter(params, "author"),
HttpUtility::GetLastParameter(params, "comment"), timestamp);
checkable->AcknowledgeProblem(HttpUtility::GetLastParameter(params, "author"),
HttpUtility::GetLastParameter(params, "comment"), sticky, notify, timestamp);
@ -250,11 +250,11 @@ Dictionary::Ptr ApiActions::AddComment(const ConfigObject::Ptr& object,
if (!params->Contains("author") || !params->Contains("comment"))
return ApiActions::CreateResult(403, "Comments require author and comment.");
String comment_id = checkable->AddComment(CommentUser,
String comment_id = Comment::AddComment(checkable, CommentUser,
HttpUtility::GetLastParameter(params, "author"),
HttpUtility::GetLastParameter(params, "comment"), 0);
Comment::Ptr comment = Checkable::GetCommentByID(comment_id);
Comment::Ptr comment = Comment::GetByName(comment_id);
int legacy_id = comment->GetLegacyId();
Dictionary::Ptr additional = new Dictionary();
@ -287,7 +287,7 @@ Dictionary::Ptr ApiActions::RemoveCommentByID(const ConfigObject::Ptr& object,
String comment_id = HttpUtility::GetLastParameter(params, "comment_id");
Service::RemoveComment(comment_id);
Comment::RemoveComment(comment_id);
return ApiActions::CreateResult(200, "Successfully removed comment '" + comment_id + "'.");
}
@ -311,21 +311,15 @@ Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object,
if (params->Contains("fixed"))
fixed = HttpUtility::GetLastParameter(params, "fixed");
int triggeredByLegacy = 0;
if (params->Contains("trigger_id"))
triggeredByLegacy = HttpUtility::GetLastParameter(params, "trigger_id");
String triggeredBy;
if (triggeredByLegacy)
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
String downtime_id = checkable->AddDowntime(HttpUtility::GetLastParameter(params, "author"),
HttpUtility::GetLastParameter(params, "comment"), HttpUtility::GetLastParameter(params, "start_time"),
HttpUtility::GetLastParameter(params, "end_time"), fixed, triggeredBy,
String downtime_id = Downtime::AddDowntime(checkable,
HttpUtility::GetLastParameter(params, "author"),
HttpUtility::GetLastParameter(params, "comment"),
HttpUtility::GetLastParameter(params, "start_time"),
HttpUtility::GetLastParameter(params, "end_time"), fixed,
HttpUtility::GetLastParameter(params, "trigger_id"),
HttpUtility::GetLastParameter(params, "duration"));
Downtime::Ptr downtime = Checkable::GetDowntimeByID(downtime_id);
Downtime::Ptr downtime = Downtime::GetByName(downtime_id);
int legacy_id = downtime->GetLegacyId();
Dictionary::Ptr additional = new Dictionary();
@ -357,7 +351,7 @@ Dictionary::Ptr ApiActions::RemoveDowntimeByID(const ConfigObject::Ptr& object,
String downtime_id = HttpUtility::GetLastParameter(params, "downtime_id");
Service::RemoveDowntime(downtime_id, true);
Downtime::RemoveDowntime(downtime_id, true);
return ApiActions::CreateResult(200, "Successfully removed downtime '" + downtime_id + "'.");
}

View File

@ -39,12 +39,12 @@ void ApiEvents::StaticInitialize(void)
Checkable::OnAcknowledgementSet.connect(&ApiEvents::AcknowledgementSetHandler);
Checkable::OnAcknowledgementCleared.connect(&ApiEvents::AcknowledgementClearedHandler);
Checkable::OnCommentAdded.connect(&ApiEvents::CommentAddedHandler);
Checkable::OnCommentRemoved.connect(&ApiEvents::CommentRemovedHandler);
Comment::OnCommentAdded.connect(&ApiEvents::CommentAddedHandler);
Comment::OnCommentRemoved.connect(&ApiEvents::CommentRemovedHandler);
Checkable::OnDowntimeAdded.connect(&ApiEvents::DowntimeAddedHandler);
Checkable::OnDowntimeRemoved.connect(&ApiEvents::DowntimeRemovedHandler);
Checkable::OnDowntimeTriggered.connect(&ApiEvents::DowntimeTriggeredHandler);
Downtime::OnDowntimeAdded.connect(&ApiEvents::DowntimeAddedHandler);
Downtime::OnDowntimeRemoved.connect(&ApiEvents::DowntimeRemovedHandler);
Downtime::OnDowntimeTriggered.connect(&ApiEvents::DowntimeTriggeredHandler);
}
void ApiEvents::CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, const MessageOrigin::Ptr& origin)
@ -243,7 +243,7 @@ void ApiEvents::AcknowledgementClearedHandler(const Checkable::Ptr& checkable, c
result->Set("acknowledgement_type", AcknowledgementNone);
}
void ApiEvents::CommentAddedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin)
void ApiEvents::CommentAddedHandler(const Comment::Ptr& comment)
{
std::vector<EventQueue::Ptr> queues = EventQueue::GetQueuesForType("CommentAdded");
@ -256,22 +256,14 @@ void ApiEvents::CommentAddedHandler(const Checkable::Ptr& checkable, const Comme
result->Set("type", "CommentAdded");
result->Set("timestamp", Utility::GetTime());
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
result->Set("host", host->GetName());
if (service)
result->Set("service", service->GetShortName());
result->Set("comment", Serialize(comment));
result->Set("comment", Serialize(comment, FAConfig | FAState));
BOOST_FOREACH(const EventQueue::Ptr& queue, queues) {
queue->ProcessEvent(result);
}
}
void ApiEvents::CommentRemovedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin)
void ApiEvents::CommentRemovedHandler(const Comment::Ptr& comment)
{
std::vector<EventQueue::Ptr> queues = EventQueue::GetQueuesForType("CommentRemoved");
@ -284,20 +276,14 @@ void ApiEvents::CommentRemovedHandler(const Checkable::Ptr& checkable, const Com
result->Set("type", "CommentRemoved");
result->Set("timestamp", Utility::GetTime());
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
result->Set("host", host->GetName());
if (service)
result->Set("service", service->GetShortName());
result->Set("comment", Serialize(comment, FAConfig | FAState));
BOOST_FOREACH(const EventQueue::Ptr& queue, queues) {
queue->ProcessEvent(result);
}
}
void ApiEvents::DowntimeAddedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin)
void ApiEvents::DowntimeAddedHandler(const Downtime::Ptr& downtime)
{
std::vector<EventQueue::Ptr> queues = EventQueue::GetQueuesForType("DowntimeAdded");
@ -310,22 +296,14 @@ void ApiEvents::DowntimeAddedHandler(const Checkable::Ptr& checkable, const Down
result->Set("type", "DowntimeAdded");
result->Set("timestamp", Utility::GetTime());
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
result->Set("host", host->GetName());
if (service)
result->Set("service", service->GetShortName());
result->Set("downtime", Serialize(downtime));
result->Set("downtime", Serialize(downtime, FAConfig | FAState));
BOOST_FOREACH(const EventQueue::Ptr& queue, queues) {
queue->ProcessEvent(result);
}
}
void ApiEvents::DowntimeRemovedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin)
void ApiEvents::DowntimeRemovedHandler(const Downtime::Ptr& downtime)
{
std::vector<EventQueue::Ptr> queues = EventQueue::GetQueuesForType("DowntimeRemoved");
@ -338,20 +316,14 @@ void ApiEvents::DowntimeRemovedHandler(const Checkable::Ptr& checkable, const Do
result->Set("type", "DowntimeRemoved");
result->Set("timestamp", Utility::GetTime());
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
result->Set("host", host->GetName());
if (service)
result->Set("service", service->GetShortName());
result->Set("downtime", Serialize(downtime, FAConfig | FAState));
BOOST_FOREACH(const EventQueue::Ptr& queue, queues) {
queue->ProcessEvent(result);
}
}
void ApiEvents::DowntimeTriggeredHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime)
void ApiEvents::DowntimeTriggeredHandler(const Downtime::Ptr& downtime)
{
std::vector<EventQueue::Ptr> queues = EventQueue::GetQueuesForType("DowntimeTriggered");
@ -364,14 +336,6 @@ void ApiEvents::DowntimeTriggeredHandler(const Checkable::Ptr& checkable, const
result->Set("type", "DowntimeTriggered");
result->Set("timestamp", Utility::GetTime());
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
result->Set("host", host->GetName());
if (service)
result->Set("service", service->GetShortName());
result->Set("downtime", Serialize(downtime));
BOOST_FOREACH(const EventQueue::Ptr& queue, queues) {

View File

@ -49,12 +49,12 @@ public:
bool notify, double expiry, const MessageOrigin::Ptr& origin);
static void AcknowledgementClearedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin);
static void CommentAddedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin);
static void CommentRemovedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin);
static void CommentAddedHandler(const Comment::Ptr& comment);
static void CommentRemovedHandler(const Comment::Ptr& comment);
static void DowntimeAddedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin);
static void DowntimeRemovedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin);
static void DowntimeTriggeredHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime);
static void DowntimeAddedHandler(const Downtime::Ptr& downtime);
static void DowntimeRemovedHandler(const Downtime::Ptr& downtime);
static void DowntimeTriggeredHandler(const Downtime::Ptr& downtime);
};
}

View File

@ -18,6 +18,7 @@
******************************************************************************/
#include "icinga/service.hpp"
#include "remote/configobjectutility.hpp"
#include "base/configtype.hpp"
#include "base/objectlock.hpp"
#include "base/timer.hpp"
@ -27,218 +28,36 @@
using namespace icinga;
static int l_NextCommentID = 1;
static boost::mutex l_CommentMutex;
static std::map<int, String> l_LegacyCommentsCache;
static std::map<String, Checkable::Ptr> l_CommentsCache;
static Timer::Ptr l_CommentsExpireTimer;
boost::signals2::signal<void (const Checkable::Ptr&, const Comment::Ptr&, const MessageOrigin::Ptr&)> Checkable::OnCommentAdded;
boost::signals2::signal<void (const Checkable::Ptr&, const Comment::Ptr&, const MessageOrigin::Ptr&)> Checkable::OnCommentRemoved;
int Checkable::GetNextCommentID(void)
{
boost::mutex::scoped_lock lock(l_CommentMutex);
return l_NextCommentID;
}
String Checkable::AddComment(CommentType entryType, const String& author,
const String& text, double expireTime, const String& id, const MessageOrigin::Ptr& origin)
{
String uid;
if (id.IsEmpty())
uid = Utility::NewUniqueID();
else
uid = id;
Comment::Ptr comment = new Comment();
comment->SetId(uid);;
comment->SetEntryTime(Utility::GetTime());
comment->SetEntryType(entryType);
comment->SetAuthor(author);
comment->SetText(text);
comment->SetExpireTime(expireTime);
int legacy_id;
{
boost::mutex::scoped_lock lock(l_CommentMutex);
legacy_id = l_NextCommentID++;
}
comment->SetLegacyId(legacy_id);
GetComments()->Set(uid, comment);
{
boost::mutex::scoped_lock lock(l_CommentMutex);
l_LegacyCommentsCache[legacy_id] = uid;
l_CommentsCache[uid] = this;
}
OnCommentAdded(this, comment, origin);
return uid;
}
void Checkable::RemoveAllComments(void)
{
std::vector<String> ids;
Dictionary::Ptr comments = GetComments();
{
ObjectLock olock(comments);
BOOST_FOREACH(const Dictionary::Pair& kv, comments) {
ids.push_back(kv.first);
}
}
BOOST_FOREACH(const String& id, ids) {
RemoveComment(id);
}
}
void Checkable::RemoveComment(const String& id, const MessageOrigin::Ptr& origin)
{
Checkable::Ptr owner = GetOwnerByCommentID(id);
if (!owner)
return;
Dictionary::Ptr comments = owner->GetComments();
ObjectLock olock(owner);
Comment::Ptr comment = comments->Get(id);
if (!comment)
return;
int legacy_id = comment->GetLegacyId();
comments->Remove(id);
{
boost::mutex::scoped_lock lock(l_CommentMutex);
l_LegacyCommentsCache.erase(legacy_id);
l_CommentsCache.erase(id);
}
OnCommentRemoved(owner, comment, origin);
}
String Checkable::GetCommentIDFromLegacyID(int id)
{
boost::mutex::scoped_lock lock(l_CommentMutex);
std::map<int, String>::iterator it = l_LegacyCommentsCache.find(id);
if (it == l_LegacyCommentsCache.end())
return Empty;
return it->second;
}
Checkable::Ptr Checkable::GetOwnerByCommentID(const String& id)
{
boost::mutex::scoped_lock lock(l_CommentMutex);
return l_CommentsCache[id];
}
Comment::Ptr Checkable::GetCommentByID(const String& id)
{
Checkable::Ptr owner = GetOwnerByCommentID(id);
if (!owner)
return Comment::Ptr();
Dictionary::Ptr comments = owner->GetComments();
if (comments)
return comments->Get(id);
return Comment::Ptr();
}
void Checkable::AddCommentsToCache(void)
{
#ifdef I2_DEBUG
Log(LogDebug, "Checkable", "Updating Checkable comments cache.");
#endif /* I2_DEBUG */
Dictionary::Ptr comments = GetComments();
ObjectLock olock(comments);
boost::mutex::scoped_lock lock(l_CommentMutex);
BOOST_FOREACH(const Dictionary::Pair& kv, comments) {
Comment::Ptr comment = kv.second;
int legacy_id = comment->GetLegacyId();
if (legacy_id >= l_NextCommentID)
l_NextCommentID = legacy_id + 1;
l_LegacyCommentsCache[legacy_id] = kv.first;
l_CommentsCache[kv.first] = this;
BOOST_FOREACH(const Comment::Ptr& comment, GetComments()) {
Comment::RemoveComment(comment->GetName());
}
}
void Checkable::RemoveCommentsByType(int type)
{
Dictionary::Ptr comments = GetComments();
std::vector<String> removedComments;
{
ObjectLock olock(comments);
BOOST_FOREACH(const Dictionary::Pair& kv, comments) {
Comment::Ptr comment = kv.second;
if (comment->GetEntryType() == type)
removedComments.push_back(kv.first);
}
}
BOOST_FOREACH(const String& id, removedComments) {
RemoveComment(id);
BOOST_FOREACH(const Comment::Ptr& comment, GetComments()) {
if (comment->GetEntryType() == type)
Comment::RemoveComment(comment->GetName());
}
}
void Checkable::RemoveExpiredComments(void)
std::set<Comment::Ptr> Checkable::GetComments(void) const
{
Dictionary::Ptr comments = GetComments();
std::vector<String> expiredComments;
{
ObjectLock olock(comments);
BOOST_FOREACH(const Dictionary::Pair& kv, comments) {
Comment::Ptr comment = kv.second;
if (comment->IsExpired())
expiredComments.push_back(kv.first);
}
}
BOOST_FOREACH(const String& id, expiredComments) {
RemoveComment(id);
}
boost::mutex::scoped_lock lock(m_CommentMutex);
return m_Comments;
}
void Checkable::CommentsExpireTimerHandler(void)
void Checkable::RegisterComment(const Comment::Ptr& comment)
{
BOOST_FOREACH(const Host::Ptr& host, ConfigType::GetObjectsByType<Host>()) {
host->RemoveExpiredComments();
}
BOOST_FOREACH(const Service::Ptr& service, ConfigType::GetObjectsByType<Service>()) {
service->RemoveExpiredComments();
}
boost::mutex::scoped_lock lock(m_CommentMutex);
m_Comments.insert(comment);
}
void Checkable::UnregisterComment(const Comment::Ptr& comment)
{
boost::mutex::scoped_lock lock(m_CommentMutex);
m_Comments.erase(comment);
}

View File

@ -21,344 +21,29 @@
#include "base/configtype.hpp"
#include "base/objectlock.hpp"
#include "base/logger.hpp"
#include "base/timer.hpp"
#include "base/utility.hpp"
#include "base/convert.hpp"
#include <boost/foreach.hpp>
using namespace icinga;
static int l_NextDowntimeID = 1;
static boost::mutex l_DowntimeMutex;
static std::map<int, String> l_LegacyDowntimesCache;
static std::map<String, Checkable::Ptr> l_DowntimesCache;
static Timer::Ptr l_DowntimesExpireTimer;
boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&, const MessageOrigin::Ptr&)> Checkable::OnDowntimeAdded;
boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&, const MessageOrigin::Ptr&)> Checkable::OnDowntimeRemoved;
boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&)> Checkable::OnDowntimeTriggered;
INITIALIZE_ONCE(&Checkable::StartDowntimesExpiredTimer);
int Checkable::GetNextDowntimeID(void)
{
boost::mutex::scoped_lock lock(l_DowntimeMutex);
return l_NextDowntimeID;
}
String Checkable::AddDowntime(const String& author, const String& comment,
double startTime, double endTime, bool fixed,
const String& triggeredBy, double duration, const String& scheduledBy,
const String& id, const MessageOrigin::Ptr& origin)
{
String uid;
if (id.IsEmpty())
uid = Utility::NewUniqueID();
else
uid = id;
Downtime::Ptr downtime = new Downtime();
downtime->SetId(uid);
downtime->SetEntryTime(Utility::GetTime());
downtime->SetAuthor(author);
downtime->SetComment(comment);
downtime->SetStartTime(startTime);
downtime->SetEndTime(endTime);
downtime->SetFixed(fixed);
downtime->SetDuration(duration);
downtime->SetTriggeredBy(triggeredBy);
downtime->SetScheduledBy(scheduledBy);
if (!triggeredBy.IsEmpty()) {
Downtime::Ptr triggerDowntime = GetDowntimeByID(triggeredBy);
if (triggerDowntime)
downtime->SetTriggeredByLegacyId(triggerDowntime->GetLegacyId());
}
int legacy_id;
{
boost::mutex::scoped_lock lock(l_DowntimeMutex);
legacy_id = l_NextDowntimeID++;
}
downtime->SetLegacyId(legacy_id);
if (!triggeredBy.IsEmpty()) {
Checkable::Ptr otherOwner = GetOwnerByDowntimeID(triggeredBy);
Dictionary::Ptr otherDowntimes = otherOwner->GetDowntimes();
Downtime::Ptr otherDowntime = otherDowntimes->Get(triggeredBy);
Dictionary::Ptr triggers = otherDowntime->GetTriggers();
triggers->Set(triggeredBy, triggeredBy);
}
GetDowntimes()->Set(uid, downtime);
{
boost::mutex::scoped_lock lock(l_DowntimeMutex);
l_LegacyDowntimesCache[legacy_id] = uid;
l_DowntimesCache[uid] = this;
}
Log(LogNotice, "Checkable")
<< "Added downtime with ID '" << downtime->GetLegacyId()
<< "' between '" << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", startTime)
<< "' and '" << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", endTime) << "'.";
OnDowntimeAdded(this, downtime, origin);
/* if this object is already in a NOT-OK state trigger
* this downtime now *after* it has been added (important
* for DB IDO, etc.)
*/
if (GetStateRaw() != ServiceOK) {
Log(LogNotice, "Checkable")
<< "Checkable '" << GetName() << "' already in a NOT-OK state."
<< " Triggering downtime now.";
TriggerDowntime(uid);
}
return uid;
}
void Checkable::RemoveDowntime(const String& id, bool cancelled, const MessageOrigin::Ptr& origin)
{
Checkable::Ptr owner = GetOwnerByDowntimeID(id);
if (!owner)
return;
Dictionary::Ptr downtimes = owner->GetDowntimes();
Downtime::Ptr downtime = downtimes->Get(id);
if (!downtime)
return;
int legacy_id = downtime->GetLegacyId();
String config_owner = downtime->GetConfigOwner();
if (!config_owner.IsEmpty()) {
Log(LogWarning, "Checkable")
<< "Cannot remove downtime with ID '" << legacy_id << "'. It is owned by scheduled downtime object '" << config_owner << "'";
return;
}
downtimes->Remove(id);
{
boost::mutex::scoped_lock lock(l_DowntimeMutex);
l_LegacyDowntimesCache.erase(legacy_id);
l_DowntimesCache.erase(id);
}
downtime->SetWasCancelled(cancelled);
Log(LogNotice, "Checkable")
<< "Removed downtime with ID '" << downtime->GetLegacyId() << "' from service '" << owner->GetName() << "'.";
OnDowntimeRemoved(owner, downtime, origin);
}
void Checkable::RemoveAllDowntimes(void)
{
std::vector<String> ids;
Dictionary::Ptr downtimes = GetDowntimes();
{
ObjectLock olock(downtimes);
BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
ids.push_back(kv.first);
}
}
BOOST_FOREACH(const String& id, ids) {
RemoveDowntime(id, true);
BOOST_FOREACH(const Downtime::Ptr& downtime, GetDowntimes()) {
Downtime::RemoveDowntime(downtime->GetName(), true, true);
}
}
void Checkable::TriggerDowntimes(void)
{
Dictionary::Ptr downtimes = GetDowntimes();
std::vector<String> ids;
{
ObjectLock olock(downtimes);
BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
ids.push_back(kv.first);
}
}
BOOST_FOREACH(const String& id, ids) {
TriggerDowntime(id);
}
}
void Checkable::TriggerDowntime(const String& id)
{
Checkable::Ptr owner = GetOwnerByDowntimeID(id);
Downtime::Ptr downtime = GetDowntimeByID(id);
if (!downtime)
return;
if (downtime->IsActive() && downtime->IsTriggered()) {
Log(LogDebug, "Checkable")
<< "Not triggering downtime with ID '" << downtime->GetLegacyId() << "': already triggered.";
return;
}
if (downtime->IsExpired()) {
Log(LogDebug, "Checkable")
<< "Not triggering downtime with ID '" << downtime->GetLegacyId() << "': expired.";
return;
}
double now = Utility::GetTime();
if (now < downtime->GetStartTime() || now > downtime->GetEndTime()) {
Log(LogDebug, "Checkable")
<< "Not triggering downtime with ID '" << downtime->GetLegacyId() << "': current time is outside downtime window.";
return;
}
Log(LogNotice, "Checkable")
<< "Triggering downtime with ID '" << downtime->GetLegacyId() << "'.";
if (downtime->GetTriggerTime() == 0)
downtime->SetTriggerTime(Utility::GetTime());
Dictionary::Ptr triggers = downtime->GetTriggers();
{
ObjectLock olock(triggers);
BOOST_FOREACH(const Dictionary::Pair& kv, triggers) {
TriggerDowntime(kv.first);
}
}
OnDowntimeTriggered(owner, downtime);
}
String Checkable::GetDowntimeIDFromLegacyID(int id)
{
boost::mutex::scoped_lock lock(l_DowntimeMutex);
std::map<int, String>::iterator it = l_LegacyDowntimesCache.find(id);
if (it == l_LegacyDowntimesCache.end())
return Empty;
return it->second;
}
Checkable::Ptr Checkable::GetOwnerByDowntimeID(const String& id)
{
boost::mutex::scoped_lock lock(l_DowntimeMutex);
return l_DowntimesCache[id];
}
Downtime::Ptr Checkable::GetDowntimeByID(const String& id)
{
Checkable::Ptr owner = GetOwnerByDowntimeID(id);
if (!owner)
return Downtime::Ptr();
Dictionary::Ptr downtimes = owner->GetDowntimes();
if (downtimes)
return downtimes->Get(id);
return Downtime::Ptr();
}
void Checkable::StartDowntimesExpiredTimer(void)
{
l_DowntimesExpireTimer = new Timer();
l_DowntimesExpireTimer->SetInterval(60);
l_DowntimesExpireTimer->OnTimerExpired.connect(boost::bind(&Checkable::DowntimesExpireTimerHandler));
l_DowntimesExpireTimer->Start();
}
void Checkable::AddDowntimesToCache(void)
{
#ifdef I2_DEBUG
Log(LogDebug, "Checkable", "Updating Checkable downtimes cache.");
#endif /* I2_DEBUG */
Dictionary::Ptr downtimes = GetDowntimes();
boost::mutex::scoped_lock lock(l_DowntimeMutex);
ObjectLock olock(downtimes);
BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
Downtime::Ptr downtime = kv.second;
int legacy_id = downtime->GetLegacyId();
if (legacy_id >= l_NextDowntimeID)
l_NextDowntimeID = legacy_id + 1;
l_LegacyDowntimesCache[legacy_id] = kv.first;
l_DowntimesCache[kv.first] = this;
}
}
void Checkable::RemoveExpiredDowntimes(void)
{
Dictionary::Ptr downtimes = GetDowntimes();
std::vector<String> expiredDowntimes;
{
ObjectLock olock(downtimes);
BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
Downtime::Ptr downtime = kv.second;
if (downtime->IsExpired())
expiredDowntimes.push_back(kv.first);
}
}
BOOST_FOREACH(const String& id, expiredDowntimes) {
/* override config owner to clear expired downtimes once */
Downtime::Ptr downtime = GetDowntimeByID(id);
downtime->SetConfigOwner(Empty);
RemoveDowntime(id, false);
}
}
void Checkable::DowntimesExpireTimerHandler(void)
{
BOOST_FOREACH(const Host::Ptr& host, ConfigType::GetObjectsByType<Host>()) {
host->RemoveExpiredDowntimes();
}
BOOST_FOREACH(const Service::Ptr& service, ConfigType::GetObjectsByType<Service>()) {
service->RemoveExpiredDowntimes();
BOOST_FOREACH(const Downtime::Ptr& downtime, GetDowntimes()) {
downtime->TriggerDowntime();
}
}
bool Checkable::IsInDowntime(void) const
{
Dictionary::Ptr downtimes = GetDowntimes();
ObjectLock olock(downtimes);
BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
Downtime::Ptr downtime = kv.second;
BOOST_FOREACH(const Downtime::Ptr& downtime, GetDowntimes()) {
if (downtime->IsActive())
return true;
}
@ -369,13 +54,8 @@ bool Checkable::IsInDowntime(void) const
int Checkable::GetDowntimeDepth(void) const
{
int downtime_depth = 0;
Dictionary::Ptr downtimes = GetDowntimes();
ObjectLock olock(downtimes);
BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
Downtime::Ptr downtime = kv.second;
BOOST_FOREACH(const Downtime::Ptr& downtime, GetDowntimes()) {
if (downtime->IsActive())
downtime_depth++;
}
@ -383,3 +63,20 @@ int Checkable::GetDowntimeDepth(void) const
return downtime_depth;
}
std::set<Downtime::Ptr> Checkable::GetDowntimes(void) const
{
boost::mutex::scoped_lock lock(m_DowntimeMutex);
return m_Downtimes;
}
void Checkable::RegisterDowntime(const Downtime::Ptr& downtime)
{
boost::mutex::scoped_lock lock(m_DowntimeMutex);
m_Downtimes.insert(downtime);
}
void Checkable::UnregisterDowntime(const Downtime::Ptr& downtime)
{
boost::mutex::scoped_lock lock(m_DowntimeMutex);
m_Downtimes.erase(downtime);
}

View File

@ -88,13 +88,13 @@ std::set<Notification::Ptr> Checkable::GetNotifications(void) const
return m_Notifications;
}
void Checkable::AddNotification(const Notification::Ptr& notification)
void Checkable::RegisterNotification(const Notification::Ptr& notification)
{
boost::mutex::scoped_lock lock(m_NotificationMutex);
m_Notifications.insert(notification);
}
void Checkable::RemoveNotification(const Notification::Ptr& notification)
void Checkable::UnregisterNotification(const Notification::Ptr& notification)
{
boost::mutex::scoped_lock lock(m_NotificationMutex);
m_Notifications.erase(notification);

View File

@ -40,42 +40,14 @@ Checkable::Checkable(void)
SetSchedulingOffset(Utility::Random());
}
void Checkable::Start(void)
void Checkable::Start(bool runtimeCreated)
{
double now = Utility::GetTime();
if (GetNextCheck() < now + 300)
UpdateNextCheck();
ObjectImpl<Checkable>::Start();
}
void Checkable::OnStateLoaded(void)
{
AddDowntimesToCache();
AddCommentsToCache();
std::vector<String> ids;
Dictionary::Ptr downtimes = GetDowntimes();
{
ObjectLock dlock(downtimes);
BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
Downtime::Ptr downtime = kv.second;
if (downtime->GetScheduledBy().IsEmpty())
continue;
ids.push_back(kv.first);
}
}
BOOST_FOREACH(const String& id, ids) {
/* override config owner to clear downtimes once */
Downtime::Ptr downtime = GetDowntimeByID(id);
downtime->SetConfigOwner(Empty);
RemoveDowntime(id, true);
}
ObjectImpl<Checkable>::Start(runtimeCreated);
}
void Checkable::AddGroup(const String& name)

View File

@ -75,8 +75,6 @@ public:
void AddGroup(const String& name);
//bool IsHostCheck(void) const;
bool IsReachable(DependencyType dt = DependencyState, intrusive_ptr<Dependency> *failedDependency = NULL, int rstack = 0) const;
AcknowledgementType GetAcknowledgement(void);
@ -124,62 +122,37 @@ public:
static boost::signals2::signal<void (const Notification::Ptr&, const Checkable::Ptr&, const std::set<User::Ptr>&,
const NotificationType&, const CheckResult::Ptr&, const String&,
const String&)> OnNotificationSentToAllUsers;
static boost::signals2::signal<void (const Checkable::Ptr&, const Comment::Ptr&, const MessageOrigin::Ptr&)> OnCommentAdded;
static boost::signals2::signal<void (const Checkable::Ptr&, const Comment::Ptr&, const MessageOrigin::Ptr&)> OnCommentRemoved;
static boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&, const MessageOrigin::Ptr&)> OnDowntimeAdded;
static boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&, const MessageOrigin::Ptr&)> OnDowntimeRemoved;
static boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&)> OnDowntimeTriggered;
static boost::signals2::signal<void (const Checkable::Ptr&, const String&, const String&, AcknowledgementType,
bool, double, const MessageOrigin::Ptr&)> OnAcknowledgementSet;
static boost::signals2::signal<void (const Checkable::Ptr&, const MessageOrigin::Ptr&)> OnAcknowledgementCleared;
static boost::signals2::signal<void (const Checkable::Ptr&)> OnEventCommandExecuted;
/* Downtimes */
static int GetNextDowntimeID(void);
int GetDowntimeDepth(void) const;
String AddDowntime(const String& author, const String& comment,
double startTime, double endTime, bool fixed,
const String& triggeredBy, double duration,
const String& scheduledBy = String(), const String& id = String(),
const MessageOrigin::Ptr& origin = MessageOrigin::Ptr());
void RemoveAllDowntimes(void);
static void RemoveDowntime(const String& id, bool cancelled, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr());
void TriggerDowntimes(void);
static void TriggerDowntime(const String& id);
static String GetDowntimeIDFromLegacyID(int id);
static Checkable::Ptr GetOwnerByDowntimeID(const String& id);
static Downtime::Ptr GetDowntimeByID(const String& id);
static void StartDowntimesExpiredTimer(void);
bool IsInDowntime(void) const;
bool IsAcknowledged(void);
std::set<Downtime::Ptr> GetDowntimes(void) const;
void RegisterDowntime(const Downtime::Ptr& downtime);
void UnregisterDowntime(const Downtime::Ptr& downtime);
/* Comments */
static int GetNextCommentID(void);
String AddComment(CommentType entryType, const String& author,
const String& text, double expireTime, const String& id = String(), const MessageOrigin::Ptr& origin = MessageOrigin::Ptr());
void RemoveAllComments(void);
void RemoveCommentsByType(int type);
static void RemoveComment(const String& id, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr());
static String GetCommentIDFromLegacyID(int id);
static Checkable::Ptr GetOwnerByCommentID(const String& id);
static Comment::Ptr GetCommentByID(const String& id);
std::set<Comment::Ptr> GetComments(void) const;
void RegisterComment(const Comment::Ptr& comment);
void UnregisterComment(const Comment::Ptr& comment);
/* Notifications */
void SendNotifications(NotificationType type, const CheckResult::Ptr& cr, const String& author = "", const String& text = "");
std::set<Notification::Ptr> GetNotifications(void) const;
void AddNotification(const Notification::Ptr& notification);
void RemoveNotification(const Notification::Ptr& notification);
void RegisterNotification(const Notification::Ptr& notification);
void UnregisterNotification(const Notification::Ptr& notification);
void ResetNotificationNumbers(void);
@ -207,9 +180,7 @@ public:
virtual void ValidateCheckInterval(double value, const ValidationUtils& utils) override;
protected:
virtual void Start(void) override;
virtual void OnStateLoaded(void) override;
virtual void Start(bool runtimeCreated) override;
private:
mutable boost::mutex m_CheckableMutex;
@ -217,14 +188,12 @@ private:
long m_SchedulingOffset;
/* Downtimes */
static void DowntimesExpireTimerHandler(void);
void RemoveExpiredDowntimes(void);
void AddDowntimesToCache(void);
std::set<Downtime::Ptr> m_Downtimes;
mutable boost::mutex m_DowntimeMutex;
/* Comments */
static void CommentsExpireTimerHandler(void);
void RemoveExpiredComments(void);
void AddCommentsToCache(void);
std::set<Comment::Ptr> m_Comments;
mutable boost::mutex m_CommentMutex;
/* Notifications */
std::set<Notification::Ptr> m_Notifications;

View File

@ -137,12 +137,6 @@ abstract class Checkable : CustomVarObject
default {{{ return AcknowledgementNone; }}}
};
[state] double acknowledgement_expiry;
[state, no_user_modify] Dictionary::Ptr comments {
default {{{ return new Dictionary(); }}}
};
[state, no_user_modify] Dictionary::Ptr downtimes {
default {{{ return new Dictionary(); }}}
};
[state] bool force_next_notification;
[state] int flapping_positive;
[state] int flapping_negative;

View File

@ -44,10 +44,6 @@ REGISTER_APIFUNCTION(SetNextCheck, event, &ClusterEvents::NextCheckChangedAPIHan
REGISTER_APIFUNCTION(SetNextNotification, event, &ClusterEvents::NextNotificationChangedAPIHandler);
REGISTER_APIFUNCTION(SetForceNextCheck, event, &ClusterEvents::ForceNextCheckChangedAPIHandler);
REGISTER_APIFUNCTION(SetForceNextNotification, event, &ClusterEvents::ForceNextNotificationChangedAPIHandler);
REGISTER_APIFUNCTION(AddComment, event, &ClusterEvents::CommentAddedAPIHandler);
REGISTER_APIFUNCTION(RemoveComment, event, &ClusterEvents::CommentRemovedAPIHandler);
REGISTER_APIFUNCTION(AddDowntime, event, &ClusterEvents::DowntimeAddedAPIHandler);
REGISTER_APIFUNCTION(RemoveDowntime, event, &ClusterEvents::DowntimeRemovedAPIHandler);
REGISTER_APIFUNCTION(SetAcknowledgement, event, &ClusterEvents::AcknowledgementSetAPIHandler);
REGISTER_APIFUNCTION(ClearAcknowledgement, event, &ClusterEvents::AcknowledgementClearedAPIHandler);
REGISTER_APIFUNCTION(UpdateRepository, event, &ClusterEvents::UpdateRepositoryAPIHandler);
@ -63,10 +59,6 @@ void ClusterEvents::StaticInitialize(void)
Checkable::OnForceNextCheckChanged.connect(&ClusterEvents::ForceNextCheckChangedHandler);
Checkable::OnForceNextNotificationChanged.connect(&ClusterEvents::ForceNextNotificationChangedHandler);
Checkable::OnCommentAdded.connect(&ClusterEvents::CommentAddedHandler);
Checkable::OnCommentRemoved.connect(&ClusterEvents::CommentRemovedHandler);
Checkable::OnDowntimeAdded.connect(&ClusterEvents::DowntimeAddedHandler);
Checkable::OnDowntimeRemoved.connect(&ClusterEvents::DowntimeRemovedHandler);
Checkable::OnAcknowledgementSet.connect(&ClusterEvents::AcknowledgementSetHandler);
Checkable::OnAcknowledgementCleared.connect(&ClusterEvents::AcknowledgementClearedHandler);
@ -423,273 +415,6 @@ Value ClusterEvents::ForceNextNotificationChangedAPIHandler(const MessageOrigin:
return Empty;
}
void ClusterEvents::CommentAddedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin)
{
ApiListener::Ptr listener = ApiListener::GetInstance();
if (!listener)
return;
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
Dictionary::Ptr params = new Dictionary();
params->Set("host", host->GetName());
if (service)
params->Set("service", service->GetShortName());
params->Set("comment", Serialize(comment));
Dictionary::Ptr message = new Dictionary();
message->Set("jsonrpc", "2.0");
message->Set("method", "event::AddComment");
message->Set("params", params);
listener->RelayMessage(origin, checkable, message, true);
}
Value ClusterEvents::CommentAddedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
{
Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
if (!endpoint) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'comment added' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
return Empty;
}
if (!params)
return Empty;
Host::Ptr host = Host::GetByName(params->Get("host"));
if (!host)
return Empty;
Checkable::Ptr checkable;
if (params->Contains("service"))
checkable = host->GetServiceByShortName(params->Get("service"));
else
checkable = host;
if (!checkable)
return Empty;
if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'comment added' message from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
return Empty;
}
Comment::Ptr comment = new Comment();
Deserialize(comment, params->Get("comment"), true);
checkable->AddComment(comment->GetEntryType(), comment->GetAuthor(),
comment->GetText(), comment->GetExpireTime(), comment->GetId(), origin);
return Empty;
}
void ClusterEvents::CommentRemovedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin)
{
ApiListener::Ptr listener = ApiListener::GetInstance();
if (!listener)
return;
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
Dictionary::Ptr params = new Dictionary();
params->Set("host", host->GetName());
if (service)
params->Set("service", service->GetShortName());
params->Set("id", comment->GetId());
Dictionary::Ptr message = new Dictionary();
message->Set("jsonrpc", "2.0");
message->Set("method", "event::RemoveComment");
message->Set("params", params);
listener->RelayMessage(origin, checkable, message, true);
}
Value ClusterEvents::CommentRemovedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
{
Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
if (!endpoint) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'comment removed' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
return Empty;
}
if (!params)
return Empty;
Host::Ptr host = Host::GetByName(params->Get("host"));
if (!host)
return Empty;
Checkable::Ptr checkable;
if (params->Contains("service"))
checkable = host->GetServiceByShortName(params->Get("service"));
else
checkable = host;
if (!checkable)
return Empty;
if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'comment removed' message from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
return Empty;
}
checkable->RemoveComment(params->Get("id"), origin);
return Empty;
}
void ClusterEvents::DowntimeAddedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin)
{
ApiListener::Ptr listener = ApiListener::GetInstance();
if (!listener)
return;
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
Dictionary::Ptr params = new Dictionary();
params->Set("host", host->GetName());
if (service)
params->Set("service", service->GetShortName());
params->Set("downtime", Serialize(downtime));
Dictionary::Ptr message = new Dictionary();
message->Set("jsonrpc", "2.0");
message->Set("method", "event::AddDowntime");
message->Set("params", params);
listener->RelayMessage(origin, checkable, message, true);
}
Value ClusterEvents::DowntimeAddedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
{
Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
if (!endpoint) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'downtime added' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
return Empty;
}
if (!params)
return Empty;
Host::Ptr host = Host::GetByName(params->Get("host"));
if (!host)
return Empty;
Checkable::Ptr checkable;
if (params->Contains("service"))
checkable = host->GetServiceByShortName(params->Get("service"));
else
checkable = host;
if (!checkable)
return Empty;
if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'downtime added' message from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
return Empty;
}
Downtime::Ptr downtime = new Downtime();
Deserialize(downtime, params->Get("downtime"), true);
checkable->AddDowntime(downtime->GetAuthor(), downtime->GetComment(),
downtime->GetStartTime(), downtime->GetEndTime(),
downtime->GetFixed(), downtime->GetTriggeredBy(),
downtime->GetDuration(), downtime->GetScheduledBy(),
downtime->GetId(), origin);
return Empty;
}
void ClusterEvents::DowntimeRemovedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin)
{
ApiListener::Ptr listener = ApiListener::GetInstance();
if (!listener)
return;
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
Dictionary::Ptr params = new Dictionary();
params->Set("host", host->GetName());
if (service)
params->Set("service", service->GetShortName());
params->Set("id", downtime->GetId());
Dictionary::Ptr message = new Dictionary();
message->Set("jsonrpc", "2.0");
message->Set("method", "event::RemoveDowntime");
message->Set("params", params);
listener->RelayMessage(origin, checkable, message, true);
}
Value ClusterEvents::DowntimeRemovedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
{
Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
if (!endpoint) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'downtime removed' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
return Empty;
}
if (!params)
return Empty;
Host::Ptr host = Host::GetByName(params->Get("host"));
if (!host)
return Empty;
Checkable::Ptr checkable;
if (params->Contains("service"))
checkable = host->GetServiceByShortName(params->Get("service"));
else
checkable = host;
if (!checkable)
return Empty;
if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'downtime removed' message from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
return Empty;
}
checkable->RemoveDowntime(params->Get("id"), false, origin);
return Empty;
}
void ClusterEvents::AcknowledgementSetHandler(const Checkable::Ptr& checkable,
const String& author, const String& comment, AcknowledgementType type,
bool notify, double expiry, const MessageOrigin::Ptr& origin)

View File

@ -52,18 +52,6 @@ public:
static void ForceNextNotificationChangedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin);
static Value ForceNextNotificationChangedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);
static void CommentAddedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin);
static Value CommentAddedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);
static void CommentRemovedHandler(const Checkable::Ptr& checkable, const Comment::Ptr& comment, const MessageOrigin::Ptr& origin);
static Value CommentRemovedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);
static void DowntimeAddedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin);
static Value DowntimeAddedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);
static void DowntimeRemovedHandler(const Checkable::Ptr& checkable, const Downtime::Ptr& downtime, const MessageOrigin::Ptr& origin);
static Value DowntimeRemovedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);
static void AcknowledgementSetHandler(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type,
bool notify, double expiry, const MessageOrigin::Ptr& origin);
static Value AcknowledgementSetAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params);

View File

@ -19,16 +19,229 @@
#include "icinga/comment.hpp"
#include "icinga/comment.tcpp"
#include "icinga/host.hpp"
#include "remote/configobjectutility.hpp"
#include "base/utility.hpp"
#include "base/configtype.hpp"
#include "base/timer.hpp"
#include <boost/foreach.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
using namespace icinga;
static int l_NextCommentID = 1;
static boost::mutex l_CommentMutex;
static std::map<int, String> l_LegacyCommentsCache;
static Timer::Ptr l_CommentsExpireTimer;
boost::signals2::signal<void (const Comment::Ptr&)> Comment::OnCommentAdded;
boost::signals2::signal<void (const Comment::Ptr&)> Comment::OnCommentRemoved;
INITIALIZE_ONCE(&Comment::StaticInitialize);
REGISTER_TYPE(Comment);
void Comment::StaticInitialize(void)
{
l_CommentsExpireTimer = new Timer();
l_CommentsExpireTimer->SetInterval(60);
l_CommentsExpireTimer->OnTimerExpired.connect(boost::bind(&Comment::CommentsExpireTimerHandler));
l_CommentsExpireTimer->Start();
}
String CommentNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
{
Comment::Ptr comment = dynamic_pointer_cast<Comment>(context);
if (!comment)
return "";
String name = comment->GetHostName();
if (!comment->GetServiceName().IsEmpty())
name += "!" + comment->GetServiceName();
name += "!" + shortName;
return name;
}
Dictionary::Ptr CommentNameComposer::ParseName(const String& name) const
{
std::vector<String> tokens;
boost::algorithm::split(tokens, name, boost::is_any_of("!"));
if (tokens.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid Comment name."));
Dictionary::Ptr result = new Dictionary();
result->Set("host_name", tokens[0]);
if (tokens.size() > 2) {
result->Set("service_name", tokens[1]);
result->Set("name", tokens[2]);
} else {
result->Set("name", tokens[1]);
}
return result;
}
void Comment::OnAllConfigLoaded(void)
{
ConfigObject::OnAllConfigLoaded();
Host::Ptr host = Host::GetByName(GetHostName());
if (GetServiceName().IsEmpty())
m_Checkable = host;
else
m_Checkable = host->GetServiceByShortName(GetServiceName());
if (!m_Checkable)
BOOST_THROW_EXCEPTION(ScriptError("Comment '" + GetName() + "' references a host/service which doesn't exist.", GetDebugInfo()));
}
void Comment::Start(bool runtimeCreated)
{
ObjectImpl<Comment>::Start(runtimeCreated);
{
boost::mutex::scoped_lock lock(l_CommentMutex);
SetLegacyId(l_NextCommentID);
l_LegacyCommentsCache[l_NextCommentID] = GetName();
l_NextCommentID++;
}
GetCheckable()->RegisterComment(this);
if (runtimeCreated)
OnCommentAdded(this);
}
void Comment::Stop(bool runtimeRemoved)
{
GetCheckable()->UnregisterComment(this);
if (runtimeRemoved)
OnCommentRemoved(this);
ObjectImpl<Comment>::Stop(runtimeRemoved);
}
Checkable::Ptr Comment::GetCheckable(void) const
{
return m_Checkable;
}
bool Comment::IsExpired(void) const
{
double expire_time = GetExpireTime();
return (expire_time != 0 && expire_time < Utility::GetTime());
}
int Comment::GetNextCommentID(void)
{
boost::mutex::scoped_lock lock(l_CommentMutex);
return l_NextCommentID;
}
String Comment::AddComment(const Checkable::Ptr& checkable, CommentType entryType, const String& author,
const String& text, double expireTime, const String& id, const MessageOrigin::Ptr& origin)
{
String fullName;
if (id.IsEmpty())
fullName = checkable->GetName() + "!" + Utility::NewUniqueID();
else
fullName = id;
Dictionary::Ptr attrs = new Dictionary();
attrs->Set("author", author);
attrs->Set("text", text);
attrs->Set("expire_time", expireTime);
attrs->Set("entry_type", entryType);
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
attrs->Set("host_name", host->GetName());
if (service)
attrs->Set("service_name", service->GetShortName());
String config = ConfigObjectUtility::CreateObjectConfig(Comment::TypeInstance, fullName, true, Array::Ptr(), attrs);
Array::Ptr errors = new Array();
if (!ConfigObjectUtility::CreateObject(Comment::TypeInstance, fullName, config, errors)) {
ObjectLock olock(errors);
BOOST_FOREACH(const String& error, errors) {
Log(LogCritical, "Comment", error);
}
BOOST_THROW_EXCEPTION(std::runtime_error("Could not create comment."));
}
Comment::Ptr comment = Comment::GetByName(fullName);
Log(LogNotice, "Comment")
<< "Added comment '" << comment->GetName() << "'.";
return fullName;
}
void Comment::RemoveComment(const String& id, const MessageOrigin::Ptr& origin)
{
Comment::Ptr comment = Comment::GetByName(id);
if (!comment)
return;
int legacy_id = comment->GetLegacyId();
Log(LogNotice, "Comment")
<< "Removed comment '" << comment->GetName() << "' from object '" << comment->GetCheckable()->GetName() << "'.";
Array::Ptr errors = new Array();
if (!ConfigObjectUtility::DeleteObject(comment, false, errors)) {
ObjectLock olock(errors);
BOOST_FOREACH(const String& error, errors) {
Log(LogCritical, "Comment", error);
}
BOOST_THROW_EXCEPTION(std::runtime_error("Could not remove comment."));
}
}
String Comment::GetCommentIDFromLegacyID(int id)
{
boost::mutex::scoped_lock lock(l_CommentMutex);
std::map<int, String>::iterator it = l_LegacyCommentsCache.find(id);
if (it == l_LegacyCommentsCache.end())
return Empty;
return it->second;
}
void Comment::CommentsExpireTimerHandler(void)
{
std::vector<Comment::Ptr> comments;
BOOST_FOREACH(const Comment::Ptr& comment, ConfigType::GetObjectsByType<Comment>()) {
comments.push_back(comment);
}
BOOST_FOREACH(const Comment::Ptr& comment, comments) {
if (comment->IsExpired())
RemoveComment(comment->GetName());
}
}

View File

@ -22,12 +22,15 @@
#include "icinga/i2-icinga.hpp"
#include "icinga/comment.thpp"
#include "remote/messageorigin.hpp"
namespace icinga
{
class Checkable;
/**
* A service comment.
* A comment.
*
* @ingroup icinga
*/
@ -35,8 +38,36 @@ class I2_ICINGA_API Comment : public ObjectImpl<Comment>
{
public:
DECLARE_OBJECT(Comment);
DECLARE_OBJECTNAME(Comment);
static boost::signals2::signal<void (const Comment::Ptr&)> OnCommentAdded;
static boost::signals2::signal<void (const Comment::Ptr&)> OnCommentRemoved;
intrusive_ptr<Checkable> GetCheckable(void) const;
bool IsExpired(void) const;
static int GetNextCommentID(void);
static String AddComment(const intrusive_ptr<Checkable>& checkable, CommentType entryType,
const String& author, const String& text, double expireTime,
const String& id = String(), const MessageOrigin::Ptr& origin = MessageOrigin::Ptr());
static void RemoveComment(const String& id, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr());
static String GetCommentIDFromLegacyID(int id);
static void StaticInitialize(void);
protected:
virtual void OnAllConfigLoaded(void) override;
virtual void Start(bool runtimeCreated) override;
virtual void Stop(bool runtimeRemoved) override;
private:
intrusive_ptr<Checkable> m_Checkable;
static void CommentsExpireTimerHandler(void);
};
}

View File

@ -17,6 +17,10 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "base/configobject.hpp"
#include "base/utility.hpp"
#impl_include "icinga/service.hpp"
library icinga;
namespace icinga
@ -35,17 +39,56 @@ enum CommentType
CommentFlapping = 3,
CommentAcknowledgement = 4
};
class I2_ICINGA_API CommentNameComposer : public NameComposer
{
public:
virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
virtual Dictionary::Ptr ParseName(const String& name) const;
};
}}}
class Comment
class Comment : ConfigObject < CommentNameComposer
{
[state] String id;
[state] double entry_time;
[state, enum] CommentType entry_type;
[state] String author;
[state] String text;
[state] double expire_time;
[state] int legacy_id;
load_after Host;
load_after Service;
[config, protected, required, navigation(host)] name(Host) host_name {
navigate {{{
return Host::GetByName(GetHostName());
}}}
};
[config, protected, navigation(service)] String service_name {
track {{{
if (!oldValue.IsEmpty()) {
Service::Ptr service = Service::GetByNamePair(GetHostName(), oldValue);
DependencyGraph::RemoveDependency(this, service.get());
}
if (!newValue.IsEmpty()) {
Service::Ptr service = Service::GetByNamePair(GetHostName(), newValue);
DependencyGraph::RemoveDependency(this, service.get());
}
}}}
navigate {{{
if (GetServiceName().IsEmpty())
return Service::Ptr();
Host::Ptr host = Host::GetByName(GetHostName());
return host->GetServiceByShortName(GetServiceName());
}}}
};
[config] double entry_time {
default {{{ return Utility::GetTime(); }}}
};
[config, enum] CommentType entry_type {
default {{{ return CommentUser; }}}
};
[config, required] String author;
[config, required] String text;
[config] double expire_time;
int legacy_id;
};
}

View File

@ -123,9 +123,9 @@ void Dependency::OnAllConfigLoaded(void)
m_Parent->AddReverseDependency(this);
}
void Dependency::Stop(void)
void Dependency::Stop(bool runtimeRemoved)
{
ObjectImpl<Dependency>::Stop();
ObjectImpl<Dependency>::Stop(runtimeRemoved);
GetChild()->RemoveDependency(this);
GetParent()->RemoveReverseDependency(this);

View File

@ -59,7 +59,7 @@ public:
protected:
virtual void OnConfigLoaded(void) override;
virtual void OnAllConfigLoaded(void) override;
virtual void Stop(void) override;
virtual void Stop(bool runtimeRemoved) override;
private:
Checkable::Ptr m_Parent;

View File

@ -19,12 +19,137 @@
#include "icinga/downtime.hpp"
#include "icinga/downtime.tcpp"
#include "icinga/host.hpp"
#include "remote/configobjectutility.hpp"
#include "base/configtype.hpp"
#include "base/utility.hpp"
#include "base/timer.hpp"
#include <boost/foreach.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
using namespace icinga;
static int l_NextDowntimeID = 1;
static boost::mutex l_DowntimeMutex;
static std::map<int, String> l_LegacyDowntimesCache;
static Timer::Ptr l_DowntimesExpireTimer;
boost::signals2::signal<void (const Downtime::Ptr&)> Downtime::OnDowntimeAdded;
boost::signals2::signal<void (const Downtime::Ptr&)> Downtime::OnDowntimeRemoved;
boost::signals2::signal<void (const Downtime::Ptr&)> Downtime::OnDowntimeTriggered;
INITIALIZE_ONCE(&Downtime::StaticInitialize);
REGISTER_TYPE(Downtime);
void Downtime::StaticInitialize(void)
{
l_DowntimesExpireTimer = new Timer();
l_DowntimesExpireTimer->SetInterval(60);
l_DowntimesExpireTimer->OnTimerExpired.connect(boost::bind(&Downtime::DowntimesExpireTimerHandler));
l_DowntimesExpireTimer->Start();
}
String DowntimeNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
{
Downtime::Ptr downtime = dynamic_pointer_cast<Downtime>(context);
if (!downtime)
return "";
String name = downtime->GetHostName();
if (!downtime->GetServiceName().IsEmpty())
name += "!" + downtime->GetServiceName();
name += "!" + shortName;
return name;
}
Dictionary::Ptr DowntimeNameComposer::ParseName(const String& name) const
{
std::vector<String> tokens;
boost::algorithm::split(tokens, name, boost::is_any_of("!"));
if (tokens.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid Downtime name."));
Dictionary::Ptr result = new Dictionary();
result->Set("host_name", tokens[0]);
if (tokens.size() > 2) {
result->Set("service_name", tokens[1]);
result->Set("name", tokens[2]);
} else {
result->Set("name", tokens[1]);
}
return result;
}
void Downtime::OnAllConfigLoaded(void)
{
ObjectImpl<Downtime>::OnAllConfigLoaded();
Host::Ptr host = Host::GetByName(GetHostName());
if (GetServiceName().IsEmpty())
m_Checkable = host;
else
m_Checkable = host->GetServiceByShortName(GetServiceName());
if (!m_Checkable)
BOOST_THROW_EXCEPTION(ScriptError("Downtime '" + GetName() + "' references a host/service which doesn't exist.", GetDebugInfo()));
}
void Downtime::Start(bool runtimeCreated)
{
ObjectImpl<Downtime>::Start(runtimeCreated);
{
boost::mutex::scoped_lock lock(l_DowntimeMutex);
SetLegacyId(l_NextDowntimeID);
l_LegacyDowntimesCache[l_NextDowntimeID] = GetName();
l_NextDowntimeID++;
}
Checkable::Ptr checkable = GetCheckable();
checkable->RegisterDowntime(this);
if (runtimeCreated)
OnDowntimeAdded(this);
/* if this object is already in a NOT-OK state trigger
* this downtime now *after* it has been added (important
* for DB IDO, etc.)
*/
if (checkable->GetStateRaw() != ServiceOK) {
Log(LogNotice, "Downtime")
<< "Checkable '" << checkable->GetName() << "' already in a NOT-OK state."
<< " Triggering downtime now.";
TriggerDowntime();
}
}
void Downtime::Stop(bool runtimeRemoved)
{
GetCheckable()->UnregisterDowntime(this);
if (runtimeRemoved)
OnDowntimeRemoved(this);
ObjectImpl<Downtime>::Stop(runtimeRemoved);
}
Checkable::Ptr Downtime::GetCheckable(void) const
{
return m_Checkable;
}
bool Downtime::IsActive(void) const
{
double now = Utility::GetTime();
@ -57,3 +182,189 @@ bool Downtime::IsExpired(void) const
{
return (GetEndTime() < Utility::GetTime());
}
int Downtime::GetNextDowntimeID(void)
{
boost::mutex::scoped_lock lock(l_DowntimeMutex);
return l_NextDowntimeID;
}
String Downtime::AddDowntime(const Checkable::Ptr& checkable, const String& author,
const String& comment, double startTime, double endTime, bool fixed,
const String& triggeredBy, double duration,
const String& scheduledDowntime, const String& scheduledBy,
const String& id, const MessageOrigin::Ptr& origin)
{
String fullName;
if (id.IsEmpty())
fullName = checkable->GetName() + "!" + Utility::NewUniqueID();
else
fullName = id;
Dictionary::Ptr attrs = new Dictionary();
attrs->Set("author", author);
attrs->Set("comment", comment);
attrs->Set("start_time", startTime);
attrs->Set("end_time", endTime);
attrs->Set("fixed", fixed);
attrs->Set("duration", duration);
attrs->Set("triggered_by", triggeredBy);
attrs->Set("scheduled_by", scheduledBy);
attrs->Set("config_owner", scheduledDowntime);
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
attrs->Set("host_name", host->GetName());
if (service)
attrs->Set("service_name", service->GetShortName());
String config = ConfigObjectUtility::CreateObjectConfig(Downtime::TypeInstance, fullName, true, Array::Ptr(), attrs);
Array::Ptr errors = new Array();
if (!ConfigObjectUtility::CreateObject(Downtime::TypeInstance, fullName, config, errors)) {
ObjectLock olock(errors);
BOOST_FOREACH(const String& error, errors) {
Log(LogCritical, "Downtime", error);
}
BOOST_THROW_EXCEPTION(std::runtime_error("Could not create downtime."));
}
if (!triggeredBy.IsEmpty()) {
Downtime::Ptr triggerDowntime = Downtime::GetByName(triggeredBy);
Array::Ptr triggers = triggerDowntime->GetTriggers();
if (!triggers->Contains(triggeredBy))
triggers->Add(triggeredBy);
}
Downtime::Ptr downtime = Downtime::GetByName(fullName);
Log(LogNotice, "Downtime")
<< "Added downtime '" << downtime->GetName()
<< "' between '" << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", startTime)
<< "' and '" << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", endTime) << "'.";
return fullName;
}
void Downtime::RemoveDowntime(const String& id, bool cancelled, bool expired, const MessageOrigin::Ptr& origin)
{
Downtime::Ptr downtime = Downtime::GetByName(id);
if (!downtime)
return;
String config_owner = downtime->GetConfigOwner();
if (!config_owner.IsEmpty() && !expired) {
Log(LogWarning, "Downtime")
<< "Cannot remove downtime '" << downtime->GetName() << "'. It is owned by scheduled downtime object '" << config_owner << "'";
return;
}
downtime->SetWasCancelled(cancelled);
Log(LogNotice, "Downtime")
<< "Removed downtime '" << downtime->GetName() << "' from object '" << downtime->GetCheckable()->GetName() << "'.";
Array::Ptr errors = new Array();
if (!ConfigObjectUtility::DeleteObject(downtime, false, errors)) {
ObjectLock olock(errors);
BOOST_FOREACH(const String& error, errors) {
Log(LogCritical, "Downtime", error);
}
BOOST_THROW_EXCEPTION(std::runtime_error("Could not remove downtime."));
}
}
void Downtime::TriggerDowntime(void)
{
if (IsActive() && IsTriggered()) {
Log(LogDebug, "Downtime")
<< "Not triggering downtime '" << GetName() << "': already triggered.";
return;
}
if (IsExpired()) {
Log(LogDebug, "Downtime")
<< "Not triggering downtime '" << GetName() << "': expired.";
return;
}
double now = Utility::GetTime();
if (now < GetStartTime() || now > GetEndTime()) {
Log(LogDebug, "Downtime")
<< "Not triggering downtime '" << GetName() << "': current time is outside downtime window.";
return;
}
Log(LogNotice, "Downtime")
<< "Triggering downtime '" << GetName() << "'.";
if (GetTriggerTime() == 0)
SetTriggerTime(Utility::GetTime());
Array::Ptr triggers = GetTriggers();
{
ObjectLock olock(triggers);
BOOST_FOREACH(const String& id, triggers) {
Downtime::GetByName(id)->TriggerDowntime();
}
}
OnDowntimeTriggered(this);
}
String Downtime::GetDowntimeIDFromLegacyID(int id)
{
boost::mutex::scoped_lock lock(l_DowntimeMutex);
std::map<int, String>::iterator it = l_LegacyDowntimesCache.find(id);
if (it == l_LegacyDowntimesCache.end())
return Empty;
return it->second;
}
void Downtime::DowntimesExpireTimerHandler(void)
{
std::vector<Downtime::Ptr> downtimes;
BOOST_FOREACH(const Downtime::Ptr& downtime, ConfigType::GetObjectsByType<Downtime>()) {
downtimes.push_back(downtime);
}
BOOST_FOREACH(const Downtime::Ptr& downtime, downtimes) {
if (downtime->IsExpired())
RemoveDowntime(downtime->GetName(), false, true);
}
}
void Downtime::ValidateStartTime(double value, const ValidationUtils& utils)
{
ObjectImpl<Downtime>::ValidateStartTime(value, utils);
if (value <= 0)
BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("start_time"), "Start time must be greater than 0."));
}
void Downtime::ValidateEndTime(double value, const ValidationUtils& utils)
{
ObjectImpl<Downtime>::ValidateEndTime(value, utils);
if (value <= 0)
BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("end_time"), "End time must be greater than 0."));
}

View File

@ -22,12 +22,15 @@
#include "icinga/i2-icinga.hpp"
#include "icinga/downtime.thpp"
#include "remote/messageorigin.hpp"
namespace icinga
{
class Checkable;
/**
* A service downtime.
* A downtime.
*
* @ingroup icinga
*/
@ -35,11 +38,46 @@ class I2_ICINGA_API Downtime : public ObjectImpl<Downtime>
{
public:
DECLARE_OBJECT(Downtime);
DECLARE_OBJECTNAME(Downtime);
static boost::signals2::signal<void (const Downtime::Ptr&)> OnDowntimeAdded;
static boost::signals2::signal<void (const Downtime::Ptr&)> OnDowntimeRemoved;
static boost::signals2::signal<void (const Downtime::Ptr&)> OnDowntimeTriggered;
intrusive_ptr<Checkable> GetCheckable(void) const;
bool IsActive(void) const;
bool IsTriggered(void) const;
bool IsExpired(void) const;
static int GetNextDowntimeID(void);
static String AddDowntime(const intrusive_ptr<Checkable>& checkable, const String& author,
const String& comment, double startTime, double endTime, bool fixed,
const String& triggeredBy, double duration, const String& scheduledDowntime = String(),
const String& scheduledBy = String(), const String& id = String(),
const MessageOrigin::Ptr& origin = MessageOrigin::Ptr());
static void RemoveDowntime(const String& id, bool cancelled, bool expired = false, const MessageOrigin::Ptr& origin = MessageOrigin::Ptr());
void TriggerDowntime(void);
static String GetDowntimeIDFromLegacyID(int id);
static void StaticInitialize(void);
protected:
virtual void OnAllConfigLoaded(void) override;
virtual void Start(bool runtimeCreated) override;
virtual void Stop(bool runtimeRemoved) override;
virtual void ValidateStartTime(double value, const ValidationUtils& utils) override;
virtual void ValidateEndTime(double value, const ValidationUtils& utils) override;
private:
intrusive_ptr<Checkable> m_Checkable;
static void DowntimesExpireTimerHandler(void);
};
}

View File

@ -17,31 +17,73 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "base/configobject.hpp"
#include "base/utility.hpp"
#impl_include "icinga/service.hpp"
library icinga;
namespace icinga
{
class Downtime
code {{{
class I2_ICINGA_API DowntimeNameComposer : public NameComposer
{
[state] String id;
[state] double entry_time;
[state] String author;
[state] String comment;
[state] double start_time;
[state] double end_time;
[state] double trigger_time;
[state] bool fixed;
[state] double duration;
[state] int triggered_by_legacy_id;
[state] String triggered_by;
[state] String scheduled_by;
[state] Dictionary::Ptr triggers {
default {{{ return new Dictionary(); }}}
public:
virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
virtual Dictionary::Ptr ParseName(const String& name) const;
};
}}}
class Downtime : ConfigObject < DowntimeNameComposer
{
load_after Host;
load_after Service;
[config, protected, required, navigation(host)] name(Host) host_name {
navigate {{{
return Host::GetByName(GetHostName());
}}}
};
[state] int legacy_id;
[config, protected, navigation(service)] String service_name {
track {{{
if (!oldValue.IsEmpty()) {
Service::Ptr service = Service::GetByNamePair(GetHostName(), oldValue);
DependencyGraph::RemoveDependency(this, service.get());
}
if (!newValue.IsEmpty()) {
Service::Ptr service = Service::GetByNamePair(GetHostName(), newValue);
DependencyGraph::RemoveDependency(this, service.get());
}
}}}
navigate {{{
if (GetServiceName().IsEmpty())
return Service::Ptr();
Host::Ptr host = Host::GetByName(GetHostName());
return host->GetServiceByShortName(GetServiceName());
}}}
};
[state] double entry_time {
default {{{ return Utility::GetTime(); }}}
};
[config, required] String author;
[config, required] String comment;
[config] double start_time;
[config] double end_time;
[state] double trigger_time;
[config] bool fixed;
[config] double duration;
[state] name(Downtime) triggered_by;
[config] String scheduled_by;
[config] Array::Ptr triggers {
default {{{ return new Array(); }}}
};
int legacy_id;
[state] bool was_cancelled;
[state] String config_owner;
[config] String config_owner;
};
}

View File

@ -602,7 +602,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const std::vector<S
Log(LogNotice, "ExternalCommandProcessor")
<< "Setting acknowledgement for service '" << service->GetName() << "'" << (notify ? "" : ". Disabled notification");
service->AddComment(CommentAcknowledgement, arguments[5], arguments[6], 0);
Comment::AddComment(service, CommentAcknowledgement, arguments[5], arguments[6], 0);
service->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify);
}
@ -623,7 +623,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const std::ve
Log(LogNotice, "ExternalCommandProcessor")
<< "Setting timed acknowledgement for service '" << service->GetName() << "'" << (notify ? "" : ". Disabled notification");
service->AddComment(CommentAcknowledgement, arguments[6], arguments[7], timestamp);
Comment::AddComment(service, CommentAcknowledgement, arguments[6], arguments[7], timestamp);
service->AcknowledgeProblem(arguments[6], arguments[7], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, timestamp);
}
@ -661,7 +661,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblem(double, const std::vector<
if (host->GetState() == HostUp)
BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK."));
host->AddComment(CommentAcknowledgement, arguments[4], arguments[5], 0);
Comment::AddComment(host, CommentAcknowledgement, arguments[4], arguments[5], 0);
host->AcknowledgeProblem(arguments[4], arguments[5], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify);
}
@ -682,7 +682,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const std::v
if (host->GetState() == HostUp)
BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK."));
host->AddComment(CommentAcknowledgement, arguments[5], arguments[6], timestamp);
Comment::AddComment(host, CommentAcknowledgement, arguments[5], arguments[6], timestamp);
host->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, timestamp);
}
@ -925,11 +925,11 @@ void ExternalCommandProcessor::ScheduleSvcDowntime(double, const std::vector<Str
int triggeredByLegacy = Convert::ToLong(arguments[5]);
int is_fixed = Convert::ToLong(arguments[4]);
if (triggeredByLegacy != 0)
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
Log(LogNotice, "ExternalCommandProcessor")
<< "Creating downtime for service " << service->GetName();
(void) service->AddDowntime(arguments[7], arguments[8],
(void) Downtime::AddDowntime(service, arguments[7], arguments[8],
Convert::ToDouble(arguments[2]), Convert::ToDouble(arguments[3]),
Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[6]));
}
@ -939,8 +939,8 @@ void ExternalCommandProcessor::DelSvcDowntime(double, const std::vector<String>&
int id = Convert::ToLong(arguments[0]);
Log(LogNotice, "ExternalCommandProcessor")
<< "Removing downtime ID " << arguments[0];
String rid = Service::GetDowntimeIDFromLegacyID(id);
Service::RemoveDowntime(rid, true);
String rid = Downtime::GetDowntimeIDFromLegacyID(id);
Downtime::RemoveDowntime(rid, true);
}
void ExternalCommandProcessor::ScheduleHostDowntime(double, const std::vector<String>& arguments)
@ -954,12 +954,12 @@ void ExternalCommandProcessor::ScheduleHostDowntime(double, const std::vector<St
int triggeredByLegacy = Convert::ToLong(arguments[4]);
int is_fixed = Convert::ToLong(arguments[3]);
if (triggeredByLegacy != 0)
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
Log(LogNotice, "ExternalCommandProcessor")
<< "Creating downtime for host " << host->GetName();
(void) host->AddDowntime(arguments[6], arguments[7],
(void) Downtime::AddDowntime(host, arguments[6], arguments[7],
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
}
@ -969,8 +969,8 @@ void ExternalCommandProcessor::DelHostDowntime(double, const std::vector<String>
int id = Convert::ToLong(arguments[0]);
Log(LogNotice, "ExternalCommandProcessor")
<< "Removing downtime ID " << arguments[0];
String rid = Service::GetDowntimeIDFromLegacyID(id);
Service::RemoveDowntime(rid, true);
String rid = Downtime::GetDowntimeIDFromLegacyID(id);
Downtime::RemoveDowntime(rid, true);
}
void ExternalCommandProcessor::DelDowntimeByHostName(double, const std::vector<String>& arguments)
@ -996,42 +996,30 @@ void ExternalCommandProcessor::DelDowntimeByHostName(double, const std::vector<S
Log(LogWarning, "ExternalCommandProcessor")
<< ("Ignoring additional parameters for host '" + arguments[0] + "' downtime deletion.");
std::vector<String> ids;
BOOST_FOREACH(const Downtime::Ptr& downtime, host->GetDowntimes()) {
Log(LogNotice, "ExternalCommandProcessor")
<< "Removing downtime '" << downtime->GetName() << "'.";
Dictionary::Ptr hostDowntimes = host->GetDowntimes();
{
ObjectLock dhlock(hostDowntimes);
BOOST_FOREACH(const Dictionary::Pair& kv, hostDowntimes) {
ids.push_back(kv.first);
}
Downtime::RemoveDowntime(downtime->GetName(), true);
}
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
if (!serviceName.IsEmpty() && serviceName != service->GetName())
continue;
Dictionary::Ptr serviceDowntimes = service->GetDowntimes();
{
ObjectLock dslock(serviceDowntimes);
BOOST_FOREACH(const Dictionary::Pair& kv, serviceDowntimes) {
ids.push_back(kv.first);
}
BOOST_FOREACH(const Downtime::Ptr& downtime, service->GetDowntimes()) {
if (!startTime.IsEmpty() && downtime->GetStartTime() != Convert::ToDouble(startTime))
continue;
if (!commentString.IsEmpty() && downtime->GetComment() != commentString)
continue;
Log(LogNotice, "ExternalCommandProcessor")
<< "Removing downtime '" << downtime->GetName() << "'.";
Downtime::RemoveDowntime(downtime->GetName(), true);
}
}
BOOST_FOREACH(const String& id, ids) {
Downtime::Ptr downtime = Service::GetDowntimeByID(id);
if (!startTime.IsEmpty() && downtime->GetStartTime() != Convert::ToDouble(startTime))
continue;
if (!commentString.IsEmpty() && downtime->GetComment() != commentString)
continue;
Log(LogNotice, "ExternalCommandProcessor")
<< "Removing downtime ID " << id;
Service::RemoveDowntime(id, true);
}
}
void ExternalCommandProcessor::ScheduleHostSvcDowntime(double, const std::vector<String>& arguments)
@ -1045,19 +1033,19 @@ void ExternalCommandProcessor::ScheduleHostSvcDowntime(double, const std::vector
int triggeredByLegacy = Convert::ToLong(arguments[4]);
int is_fixed = Convert::ToLong(arguments[3]);
if (triggeredByLegacy != 0)
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
Log(LogNotice, "ExternalCommandProcessor")
<< "Creating downtime for host " << host->GetName();
(void) host->AddDowntime(arguments[6], arguments[7],
(void) Downtime::AddDowntime(host, arguments[6], arguments[7],
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Log(LogNotice, "ExternalCommandProcessor")
<< "Creating downtime for service " << service->GetName();
(void) service->AddDowntime(arguments[6], arguments[7],
(void) Downtime::AddDowntime(service, arguments[6], arguments[7],
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
}
@ -1074,13 +1062,13 @@ void ExternalCommandProcessor::ScheduleHostgroupHostDowntime(double, const std::
int triggeredByLegacy = Convert::ToLong(arguments[4]);
int is_fixed = Convert::ToLong(arguments[3]);
if (triggeredByLegacy != 0)
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
Log(LogNotice, "ExternalCommandProcessor")
<< "Creating downtime for host " << host->GetName();
(void) host->AddDowntime(arguments[6], arguments[7],
(void) Downtime::AddDowntime(host, arguments[6], arguments[7],
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
}
@ -1097,7 +1085,7 @@ void ExternalCommandProcessor::ScheduleHostgroupSvcDowntime(double, const std::v
int triggeredByLegacy = Convert::ToLong(arguments[4]);
int is_fixed = Convert::ToLong(arguments[3]);
if (triggeredByLegacy != 0)
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
/* Note: we can't just directly create downtimes for all the services by iterating
* over all hosts in the host group - otherwise we might end up creating multiple
@ -1114,7 +1102,7 @@ void ExternalCommandProcessor::ScheduleHostgroupSvcDowntime(double, const std::v
BOOST_FOREACH(const Service::Ptr& service, services) {
Log(LogNotice, "ExternalCommandProcessor")
<< "Creating downtime for service " << service->GetName();
(void) service->AddDowntime(arguments[6], arguments[7],
(void) Downtime::AddDowntime(service, arguments[6], arguments[7],
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
}
@ -1131,7 +1119,7 @@ void ExternalCommandProcessor::ScheduleServicegroupHostDowntime(double, const st
int triggeredByLegacy = Convert::ToLong(arguments[4]);
int is_fixed = Convert::ToLong(arguments[3]);
if (triggeredByLegacy != 0)
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
/* Note: we can't just directly create downtimes for all the hosts by iterating
* over all services in the service group - otherwise we might end up creating multiple
@ -1147,7 +1135,7 @@ void ExternalCommandProcessor::ScheduleServicegroupHostDowntime(double, const st
BOOST_FOREACH(const Host::Ptr& host, hosts) {
Log(LogNotice, "ExternalCommandProcessor")
<< "Creating downtime for host " << host->GetName();
(void) host->AddDowntime(arguments[6], arguments[7],
(void) Downtime::AddDowntime(host, arguments[6], arguments[7],
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
}
@ -1164,12 +1152,12 @@ void ExternalCommandProcessor::ScheduleServicegroupSvcDowntime(double, const std
int triggeredByLegacy = Convert::ToLong(arguments[4]);
int is_fixed = Convert::ToLong(arguments[3]);
if (triggeredByLegacy != 0)
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
Log(LogNotice, "ExternalCommandProcessor")
<< "Creating downtime for service " << service->GetName();
(void) service->AddDowntime(arguments[6], arguments[7],
(void) Downtime::AddDowntime(service, arguments[6], arguments[7],
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
}
@ -1184,7 +1172,7 @@ void ExternalCommandProcessor::AddHostComment(double, const std::vector<String>&
Log(LogNotice, "ExternalCommandProcessor")
<< "Creating comment for host " << host->GetName();
(void) host->AddComment(CommentUser, arguments[2], arguments[3], 0);
(void) Comment::AddComment(host, CommentUser, arguments[2], arguments[3], 0);
}
void ExternalCommandProcessor::DelHostComment(double, const std::vector<String>& arguments)
@ -1192,8 +1180,8 @@ void ExternalCommandProcessor::DelHostComment(double, const std::vector<String>&
int id = Convert::ToLong(arguments[0]);
Log(LogNotice, "ExternalCommandProcessor")
<< "Removing comment ID " << arguments[0];
String rid = Service::GetCommentIDFromLegacyID(id);
Service::RemoveComment(rid);
String rid = Comment::GetCommentIDFromLegacyID(id);
Comment::RemoveComment(rid);
}
void ExternalCommandProcessor::AddSvcComment(double, const std::vector<String>& arguments)
@ -1205,7 +1193,7 @@ void ExternalCommandProcessor::AddSvcComment(double, const std::vector<String>&
Log(LogNotice, "ExternalCommandProcessor")
<< "Creating comment for service " << service->GetName();
(void) service->AddComment(CommentUser, arguments[3], arguments[4], 0);
(void) Comment::AddComment(service, CommentUser, arguments[3], arguments[4], 0);
}
void ExternalCommandProcessor::DelSvcComment(double, const std::vector<String>& arguments)
@ -1214,8 +1202,8 @@ void ExternalCommandProcessor::DelSvcComment(double, const std::vector<String>&
Log(LogNotice, "ExternalCommandProcessor")
<< "Removing comment ID " << arguments[0];
String rid = Service::GetCommentIDFromLegacyID(id);
Service::RemoveComment(rid);
String rid = Comment::GetCommentIDFromLegacyID(id);
Comment::RemoveComment(rid);
}
void ExternalCommandProcessor::DelAllHostComments(double, const std::vector<String>& arguments)

View File

@ -71,9 +71,9 @@ void Host::CreateChildObjects(const Type::Ptr& childType)
Service::EvaluateApplyRules(this);
}
void Host::Stop(void)
void Host::Stop(bool runtimeRemoved)
{
ObjectImpl<Host>::Stop();
ObjectImpl<Host>::Stop(runtimeRemoved);
Array::Ptr groups = GetGroups();

View File

@ -66,7 +66,7 @@ public:
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const override;
protected:
virtual void Stop(void) override;
virtual void Stop(bool runtimeRemoved) override;
virtual void OnAllConfigLoaded(void) override;
virtual void CreateChildObjects(const Type::Ptr& childType) override;

View File

@ -56,9 +56,9 @@ void IcingaStatusWriter::StatsFunc(const Dictionary::Ptr& status, const Array::P
/**
* Starts the component.
*/
void IcingaStatusWriter::Start(void)
void IcingaStatusWriter::Start(bool runtimeCreated)
{
ObjectImpl<IcingaStatusWriter>::Start();
ObjectImpl<IcingaStatusWriter>::Start(runtimeCreated);
/* TODO: remove in versions > 2.4 */
Log(LogWarning, "IcingaStatusWriter", "This feature was deprecated in 2.4 and will be removed in future Icinga 2 releases.");

View File

@ -39,7 +39,7 @@ public:
static Dictionary::Ptr GetStatusData(void);
protected:
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
Timer::Ptr m_StatusTimer;

View File

@ -99,48 +99,52 @@ void Notification::StaticInitialize(void)
void Notification::OnConfigLoaded(void)
{
ObjectImpl<Notification>::OnConfigLoaded();
SetTypeFilter(FilterArrayToInt(GetTypes(), ~0));
SetStateFilter(FilterArrayToInt(GetStates(), ~0));
}
void Notification::OnAllConfigLoaded(void)
{
Checkable::Ptr obj = GetCheckable();
ObjectImpl<Notification>::OnAllConfigLoaded();
if (!obj)
Host::Ptr host = Host::GetByName(GetHostName());
if (GetServiceName().IsEmpty())
m_Checkable = host;
else
m_Checkable = host->GetServiceByShortName(GetServiceName());
if (!m_Checkable)
BOOST_THROW_EXCEPTION(ScriptError("Notification object refers to a host/service which doesn't exist.", GetDebugInfo()));
obj->AddNotification(this);
m_Checkable->RegisterNotification(this);
}
void Notification::Start(void)
void Notification::Start(bool runtimeCreated)
{
ObjectImpl<Notification>::Start();
ObjectImpl<Notification>::Start(runtimeCreated);
Checkable::Ptr obj = GetCheckable();
if (obj)
obj->AddNotification(this);
obj->RegisterNotification(this);
}
void Notification::Stop(void)
void Notification::Stop(bool runtimeRemoved)
{
ObjectImpl<Notification>::Stop();
ObjectImpl<Notification>::Stop(runtimeRemoved);
Checkable::Ptr obj = GetCheckable();
if (obj)
obj->RemoveNotification(this);
obj->UnregisterNotification(this);
}
Checkable::Ptr Notification::GetCheckable(void) const
{
Host::Ptr host = Host::GetByName(GetHostName());
if (GetServiceName().IsEmpty())
return host;
else
return host->GetServiceByShortName(GetServiceName());
return m_Checkable;
}
NotificationCommand::Ptr Notification::GetCommand(void) const

View File

@ -118,10 +118,12 @@ public:
protected:
virtual void OnConfigLoaded(void) override;
virtual void OnAllConfigLoaded(void) override;
virtual void Start(void) override;
virtual void Stop(void) override;
virtual void Start(bool runtimeCreated) override;
virtual void Stop(bool runtimeRemoved) override;
private:
intrusive_ptr<Checkable> m_Checkable;
void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = "");
static bool EvaluateApplyRuleInstance(const intrusive_ptr<Checkable>& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule);

View File

@ -96,11 +96,11 @@ void ScheduledDowntime::OnAllConfigLoaded(void)
BOOST_THROW_EXCEPTION(ScriptError("ScheduledDowntime '" + GetName() + "' references a host/service which doesn't exist.", GetDebugInfo()));
}
void ScheduledDowntime::Start(void)
void ScheduledDowntime::Start(bool runtimeCreated)
{
ObjectImpl<ScheduledDowntime>::Start();
ObjectImpl<ScheduledDowntime>::Start(runtimeCreated);
CreateNextDowntime();
Utility::QueueAsyncCallback(boost::bind(&ScheduledDowntime::CreateNextDowntime, this));
}
void ScheduledDowntime::TimerProc(void)
@ -168,20 +168,13 @@ std::pair<double, double> ScheduledDowntime::FindNextSegment(void)
void ScheduledDowntime::CreateNextDowntime(void)
{
Dictionary::Ptr downtimes = GetCheckable()->GetDowntimes();
BOOST_FOREACH(const Downtime::Ptr& downtime, GetCheckable()->GetDowntimes()) {
if (downtime->GetScheduledBy() != GetName() ||
downtime->GetStartTime() < Utility::GetTime())
continue;
{
ObjectLock dlock(downtimes);
BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
Downtime::Ptr downtime = kv.second;
if (downtime->GetScheduledBy() != GetName() ||
downtime->GetStartTime() < Utility::GetTime())
continue;
/* We've found a downtime that is owned by us and that hasn't started yet - we're done. */
return;
}
/* We've found a downtime that is owned by us and that hasn't started yet - we're done. */
return;
}
std::pair<double, double> segment = FindNextSegment();
@ -196,12 +189,9 @@ void ScheduledDowntime::CreateNextDowntime(void)
return;
}
String uid = GetCheckable()->AddDowntime(GetAuthor(), GetComment(),
Downtime::AddDowntime(GetCheckable(), GetAuthor(), GetComment(),
segment.first, segment.second,
GetFixed(), String(), GetDuration(), GetName());
Downtime::Ptr downtime = Checkable::GetDowntimeByID(uid);
downtime->SetConfigOwner(GetName());
GetFixed(), String(), GetDuration(), GetName(), GetName());
}
void ScheduledDowntime::ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils)

View File

@ -57,7 +57,7 @@ public:
protected:
virtual void OnAllConfigLoaded(void) override;
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
static void TimerProc(void);

View File

@ -44,9 +44,9 @@ void TimePeriod::StaticInitialize(void)
l_UpdateTimer->Start();
}
void TimePeriod::Start(void)
void TimePeriod::Start(bool runtimeCreated)
{
ObjectImpl<TimePeriod>::Start();
ObjectImpl<TimePeriod>::Start(runtimeCreated);
/* Pre-fill the time period for the next 24 hours. */
double now = Utility::GetTime();

View File

@ -39,7 +39,7 @@ public:
static void StaticInitialize(void);
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
void UpdateRegion(double begin, double end, bool clearExisting);

View File

@ -60,9 +60,9 @@ void User::OnAllConfigLoaded(void)
}
}
void User::Stop(void)
void User::Stop(bool runtimeRemoved)
{
ObjectImpl<User>::Stop();
ObjectImpl<User>::Stop(runtimeRemoved);
Array::Ptr groups = GetGroups();

View File

@ -48,7 +48,7 @@ public:
virtual void ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) override;
protected:
virtual void Stop(void) override;
virtual void Stop(bool runtimeRemoved) override;
virtual void OnConfigLoaded(void) override;
virtual void OnAllConfigLoaded(void) override;

View File

@ -65,34 +65,9 @@ String CommentsTable::GetPrefix(void) const
void CommentsTable::FetchRows(const AddRowFunction& addRowFn)
{
BOOST_FOREACH(const Host::Ptr& host, ConfigType::GetObjectsByType<Host>()) {
Dictionary::Ptr comments = host->GetComments();
ObjectLock olock(comments);
String id;
Comment::Ptr comment;
BOOST_FOREACH(tie(id, comment), comments) {
if (Host::GetOwnerByCommentID(id) == host) {
if (!addRowFn(comment, LivestatusGroupByNone, Empty))
return;
}
}
}
BOOST_FOREACH(const Service::Ptr& service, ConfigType::GetObjectsByType<Service>()) {
Dictionary::Ptr comments = service->GetComments();
ObjectLock olock(comments);
String id;
Comment::Ptr comment;
BOOST_FOREACH(tie(id, comment), comments) {
if (Service::GetOwnerByCommentID(id) == service) {
if (!addRowFn(comment, LivestatusGroupByNone, Empty))
return;
}
}
BOOST_FOREACH(const Comment::Ptr& comment, ConfigType::GetObjectsByType<Comment>()) {
if (!addRowFn(comment, LivestatusGroupByNone, Empty))
return;
}
}
@ -100,7 +75,7 @@ Object::Ptr CommentsTable::HostAccessor(const Value& row, const Column::ObjectAc
{
Comment::Ptr comment = static_cast<Comment::Ptr>(row);
Checkable::Ptr checkable = Checkable::GetOwnerByCommentID(comment->GetId());
Checkable::Ptr checkable = comment->GetCheckable();
Host::Ptr host;
Service::Ptr service;
@ -113,7 +88,7 @@ Object::Ptr CommentsTable::ServiceAccessor(const Value& row, const Column::Objec
{
Comment::Ptr comment = static_cast<Comment::Ptr>(row);
Checkable::Ptr checkable = Checkable::GetOwnerByCommentID(comment->GetId());
Checkable::Ptr checkable = comment->GetCheckable();
Host::Ptr host;
Service::Ptr service;
@ -165,7 +140,7 @@ Value CommentsTable::EntryTimeAccessor(const Value& row)
Value CommentsTable::TypeAccessor(const Value& row)
{
Comment::Ptr comment = static_cast<Comment::Ptr>(row);
Checkable::Ptr checkable = Checkable::GetOwnerByCommentID(comment->GetId());
Checkable::Ptr checkable = comment->GetCheckable();
if (!checkable)
return Empty;
@ -179,7 +154,7 @@ Value CommentsTable::TypeAccessor(const Value& row)
Value CommentsTable::IsServiceAccessor(const Value& row)
{
Comment::Ptr comment = static_cast<Comment::Ptr>(row);
Checkable::Ptr checkable = Checkable::GetOwnerByCommentID(comment->GetId());
Checkable::Ptr checkable = comment->GetCheckable();
if (!checkable)
return Empty;

View File

@ -65,34 +65,9 @@ String DowntimesTable::GetPrefix(void) const
void DowntimesTable::FetchRows(const AddRowFunction& addRowFn)
{
BOOST_FOREACH(const Host::Ptr& host, ConfigType::GetObjectsByType<Host>()) {
Dictionary::Ptr downtimes = host->GetDowntimes();
ObjectLock olock(downtimes);
String id;
Downtime::Ptr downtime;
BOOST_FOREACH(boost::tie(id, downtime), downtimes) {
if (Host::GetOwnerByDowntimeID(id) == host) {
if (!addRowFn(downtime, LivestatusGroupByNone, Empty))
return;
}
}
}
BOOST_FOREACH(const Service::Ptr& service, ConfigType::GetObjectsByType<Service>()) {
Dictionary::Ptr downtimes = service->GetDowntimes();
ObjectLock olock(downtimes);
String id;
Downtime::Ptr downtime;
BOOST_FOREACH(boost::tie(id, downtime), downtimes) {
if (Service::GetOwnerByDowntimeID(id) == service) {
if (!addRowFn(downtime, LivestatusGroupByNone, Empty))
return;
}
}
BOOST_FOREACH(const Downtime::Ptr& downtime, ConfigType::GetObjectsByType<Downtime>()) {
if (!addRowFn(downtime, LivestatusGroupByNone, Empty))
return;
}
}
@ -100,7 +75,7 @@ Object::Ptr DowntimesTable::HostAccessor(const Value& row, const Column::ObjectA
{
Downtime::Ptr downtime = static_cast<Downtime::Ptr>(row);
Checkable::Ptr checkable = Checkable::GetOwnerByDowntimeID(downtime->GetId());
Checkable::Ptr checkable = downtime->GetCheckable();
Host::Ptr host;
Service::Ptr service;
@ -113,7 +88,7 @@ Object::Ptr DowntimesTable::ServiceAccessor(const Value& row, const Column::Obje
{
Downtime::Ptr downtime = static_cast<Downtime::Ptr>(row);
Checkable::Ptr checkable = Checkable::GetOwnerByDowntimeID(downtime->GetId());
Checkable::Ptr checkable = downtime->GetCheckable();
Host::Ptr host;
Service::Ptr service;
@ -160,7 +135,7 @@ Value DowntimesTable::TypeAccessor(const Value& row)
Value DowntimesTable::IsServiceAccessor(const Value& row)
{
Downtime::Ptr downtime = static_cast<Downtime::Ptr>(row);
Checkable::Ptr checkable = Checkable::GetOwnerByDowntimeID(downtime->GetId());
Checkable::Ptr checkable = downtime->GetCheckable();
return (dynamic_pointer_cast<Host>(checkable) ? 0 : 1);
}
@ -197,5 +172,12 @@ Value DowntimesTable::TriggeredByAccessor(const Value& row)
{
Downtime::Ptr downtime = static_cast<Downtime::Ptr>(row);
return downtime->GetTriggeredByLegacyId();
String triggerDowntimeName = downtime->GetTriggeredBy();
Downtime::Ptr triggerDowntime = Downtime::GetByName(triggerDowntimeName);
if (triggerDowntime)
return triggerDowntime->GetLegacyId();
return Empty;
}

View File

@ -902,26 +902,16 @@ Value HostsTable::DowntimesAccessor(const Value& row)
if (!host)
return Empty;
Dictionary::Ptr downtimes = host->GetDowntimes();
Array::Ptr ids = new Array();
ObjectLock olock(downtimes);
String id;
Downtime::Ptr downtime;
BOOST_FOREACH(tie(id, downtime), downtimes) {
if (!downtime)
continue;
Array::Ptr results = new Array();
BOOST_FOREACH(const Downtime::Ptr& downtime, host->GetDowntimes()) {
if (downtime->IsExpired())
continue;
ids->Add(downtime->GetLegacyId());
results->Add(downtime->GetLegacyId());
}
return ids;
return results;
}
Value HostsTable::DowntimesWithInfoAccessor(const Value& row)
@ -931,19 +921,9 @@ Value HostsTable::DowntimesWithInfoAccessor(const Value& row)
if (!host)
return Empty;
Dictionary::Ptr downtimes = host->GetDowntimes();
Array::Ptr ids = new Array();
ObjectLock olock(downtimes);
String id;
Downtime::Ptr downtime;
BOOST_FOREACH(tie(id, downtime), downtimes) {
if (!downtime)
continue;
Array::Ptr results = new Array();
BOOST_FOREACH(const Downtime::Ptr& downtime, host->GetDowntimes()) {
if (downtime->IsExpired())
continue;
@ -951,10 +931,10 @@ Value HostsTable::DowntimesWithInfoAccessor(const Value& row)
downtime_info->Add(downtime->GetLegacyId());
downtime_info->Add(downtime->GetAuthor());
downtime_info->Add(downtime->GetComment());
ids->Add(downtime_info);
results->Add(downtime_info);
}
return ids;
return results;
}
Value HostsTable::CommentsAccessor(const Value& row)
@ -964,26 +944,15 @@ Value HostsTable::CommentsAccessor(const Value& row)
if (!host)
return Empty;
Dictionary::Ptr comments = host->GetComments();
Array::Ptr ids = new Array();
ObjectLock olock(comments);
String id;
Comment::Ptr comment;
BOOST_FOREACH(tie(id, comment), comments) {
if (!comment)
continue;
Array::Ptr results = new Array();
BOOST_FOREACH(const Comment::Ptr& comment, host->GetComments()) {
if (comment->IsExpired())
continue;
ids->Add(comment->GetLegacyId());
results->Add(comment->GetLegacyId());
}
return ids;
return results;
}
Value HostsTable::CommentsWithInfoAccessor(const Value& row)
@ -993,19 +962,9 @@ Value HostsTable::CommentsWithInfoAccessor(const Value& row)
if (!host)
return Empty;
Dictionary::Ptr comments = host->GetComments();
Array::Ptr ids = new Array();
ObjectLock olock(comments);
String id;
Comment::Ptr comment;
BOOST_FOREACH(tie(id, comment), comments) {
if (!comment)
continue;
Array::Ptr results = new Array();
BOOST_FOREACH(const Comment::Ptr& comment, host->GetComments()) {
if (comment->IsExpired())
continue;
@ -1013,10 +972,10 @@ Value HostsTable::CommentsWithInfoAccessor(const Value& row)
comment_info->Add(comment->GetLegacyId());
comment_info->Add(comment->GetAuthor());
comment_info->Add(comment->GetText());
ids->Add(comment_info);
results->Add(comment_info);
}
return ids;
return results;
}
Value HostsTable::CommentsWithExtraInfoAccessor(const Value& row)
@ -1026,19 +985,9 @@ Value HostsTable::CommentsWithExtraInfoAccessor(const Value& row)
if (!host)
return Empty;
Dictionary::Ptr comments = host->GetComments();
Array::Ptr ids = new Array();
ObjectLock olock(comments);
String id;
Comment::Ptr comment;
BOOST_FOREACH(tie(id, comment), comments) {
if (!comment)
continue;
Array::Ptr results = new Array();
BOOST_FOREACH(const Comment::Ptr& comment, host->GetComments()) {
if (comment->IsExpired())
continue;
@ -1048,10 +997,10 @@ Value HostsTable::CommentsWithExtraInfoAccessor(const Value& row)
comment_info->Add(comment->GetText());
comment_info->Add(comment->GetEntryType());
comment_info->Add(static_cast<int>(comment->GetEntryTime()));
ids->Add(comment_info);
results->Add(comment_info);
}
return ids;
return results;
}
Value HostsTable::CustomVariableNamesAccessor(const Value& row)

View File

@ -62,9 +62,9 @@ void LivestatusListener::StatsFunc(const Dictionary::Ptr& status, const Array::P
/**
* Starts the component.
*/
void LivestatusListener::Start(void)
void LivestatusListener::Start(bool runtimeCreated)
{
ObjectImpl<LivestatusListener>::Start();
ObjectImpl<LivestatusListener>::Start(runtimeCreated);
if (GetSocketType() == "tcp") {
TcpSocket::Ptr socket = new TcpSocket();
@ -119,9 +119,9 @@ void LivestatusListener::Start(void)
}
}
void LivestatusListener::Stop(void)
void LivestatusListener::Stop(bool runtimeRemoved)
{
ObjectImpl<LivestatusListener>::Stop();
ObjectImpl<LivestatusListener>::Stop(runtimeRemoved);
m_Listener->Close();

View File

@ -48,8 +48,8 @@ public:
virtual void ValidateSocketType(const String& value, const ValidationUtils& utils) override;
protected:
virtual void Start(void) override;
virtual void Stop(void) override;
virtual void Start(bool runtimeCreated) override;
virtual void Stop(bool runtimeRemoved) override;
private:
void ServerThreadProc(void);

View File

@ -940,26 +940,16 @@ Value ServicesTable::DowntimesAccessor(const Value& row)
if (!service)
return Empty;
Dictionary::Ptr downtimes = service->GetDowntimes();
Array::Ptr ids = new Array();
ObjectLock olock(downtimes);
String id;
Downtime::Ptr downtime;
BOOST_FOREACH(tie(id, downtime), downtimes) {
if (!downtime)
continue;
Array::Ptr results = new Array();
BOOST_FOREACH(const Downtime::Ptr& downtime, service->GetDowntimes()) {
if (downtime->IsExpired())
continue;
ids->Add(downtime->GetLegacyId());
results->Add(downtime->GetLegacyId());
}
return ids;
return results;
}
Value ServicesTable::DowntimesWithInfoAccessor(const Value& row)
@ -969,19 +959,9 @@ Value ServicesTable::DowntimesWithInfoAccessor(const Value& row)
if (!service)
return Empty;
Dictionary::Ptr downtimes = service->GetDowntimes();
Array::Ptr ids = new Array();
ObjectLock olock(downtimes);
String id;
Downtime::Ptr downtime;
BOOST_FOREACH(tie(id, downtime), downtimes) {
if (!downtime)
continue;
Array::Ptr results = new Array();
BOOST_FOREACH(const Downtime::Ptr& downtime, service->GetDowntimes()) {
if (downtime->IsExpired())
continue;
@ -989,10 +969,10 @@ Value ServicesTable::DowntimesWithInfoAccessor(const Value& row)
downtime_info->Add(downtime->GetLegacyId());
downtime_info->Add(downtime->GetAuthor());
downtime_info->Add(downtime->GetComment());
ids->Add(downtime_info);
results->Add(downtime_info);
}
return ids;
return results;
}
Value ServicesTable::CommentsAccessor(const Value& row)
@ -1002,26 +982,16 @@ Value ServicesTable::CommentsAccessor(const Value& row)
if (!service)
return Empty;
Dictionary::Ptr comments = service->GetComments();
Array::Ptr ids = new Array();
ObjectLock olock(comments);
String id;
Comment::Ptr comment;
BOOST_FOREACH(tie(id, comment), comments) {
if (!comment)
continue;
Array::Ptr results = new Array();
BOOST_FOREACH(const Comment::Ptr& comment, service->GetComments()) {
if (comment->IsExpired())
continue;
ids->Add(comment->GetLegacyId());
results->Add(comment->GetLegacyId());
}
return ids;
return results;
}
Value ServicesTable::CommentsWithInfoAccessor(const Value& row)
@ -1031,19 +1001,9 @@ Value ServicesTable::CommentsWithInfoAccessor(const Value& row)
if (!service)
return Empty;
Dictionary::Ptr comments = service->GetComments();
Array::Ptr ids = new Array();
ObjectLock olock(comments);
String id;
Comment::Ptr comment;
BOOST_FOREACH(tie(id, comment), comments) {
if (!comment)
continue;
Array::Ptr results = new Array();
BOOST_FOREACH(const Comment::Ptr& comment, service->GetComments()) {
if (comment->IsExpired())
continue;
@ -1051,10 +1011,10 @@ Value ServicesTable::CommentsWithInfoAccessor(const Value& row)
comment_info->Add(comment->GetLegacyId());
comment_info->Add(comment->GetAuthor());
comment_info->Add(comment->GetText());
ids->Add(comment_info);
results->Add(comment_info);
}
return ids;
return results;
}
Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row)
@ -1064,19 +1024,9 @@ Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row)
if (!service)
return Empty;
Dictionary::Ptr comments = service->GetComments();
Array::Ptr ids = new Array();
ObjectLock olock(comments);
String id;
Comment::Ptr comment;
BOOST_FOREACH(tie(id, comment), comments) {
if (!comment)
continue;
Array::Ptr results = new Array();
BOOST_FOREACH(const Comment::Ptr& comment, service->GetComments()) {
if (comment->IsExpired())
continue;
@ -1086,10 +1036,10 @@ Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row)
comment_info->Add(comment->GetText());
comment_info->Add(comment->GetEntryType());
comment_info->Add(static_cast<int>(comment->GetEntryTime()));
ids->Add(comment_info);
results->Add(comment_info);
}
return ids;
return results;
}
Value ServicesTable::CustomVariableNamesAccessor(const Value& row)

View File

@ -49,9 +49,9 @@ void NotificationComponent::StatsFunc(const Dictionary::Ptr& status, const Array
/**
* Starts the component.
*/
void NotificationComponent::Start(void)
void NotificationComponent::Start(bool runtimeCreated)
{
ObjectImpl<NotificationComponent>::Start();
ObjectImpl<NotificationComponent>::Start(runtimeCreated);
Checkable::OnNotificationsRequested.connect(boost::bind(&NotificationComponent::SendNotificationsHandler, this, _1,
_2, _3, _4, _5));

View File

@ -39,7 +39,7 @@ public:
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
Timer::Ptr m_NotificationTimer;

View File

@ -38,9 +38,9 @@ using namespace icinga;
REGISTER_TYPE(GelfWriter);
void GelfWriter::Start(void)
void GelfWriter::Start(bool runtimeCreated)
{
ObjectImpl<GelfWriter>::Start();
ObjectImpl<GelfWriter>::Start(runtimeCreated);
m_ReconnectTimer = new Timer();
m_ReconnectTimer->SetInterval(10);

View File

@ -42,7 +42,7 @@ public:
DECLARE_OBJECTNAME(GelfWriter);
protected:
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
Stream::Ptr m_Stream;

View File

@ -58,9 +58,9 @@ void GraphiteWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
status->Set("graphitewriter", nodes);
}
void GraphiteWriter::Start(void)
void GraphiteWriter::Start(bool runtimeCreated)
{
ObjectImpl<GraphiteWriter>::Start();
ObjectImpl<GraphiteWriter>::Start(runtimeCreated);
m_ReconnectTimer = new Timer();
m_ReconnectTimer->SetInterval(10);

View File

@ -47,7 +47,7 @@ public:
virtual void ValidateServiceNameTemplate(const String& value, const ValidationUtils& utils) override;
protected:
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
Stream::Ptr m_Stream;

View File

@ -58,9 +58,9 @@ void OpenTsdbWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
status->Set("opentsdbwriter", nodes);
}
void OpenTsdbWriter::Start(void)
void OpenTsdbWriter::Start(bool runtimeCreated)
{
ObjectImpl<OpenTsdbWriter>::Start();
ObjectImpl<OpenTsdbWriter>::Start(runtimeCreated);
m_ReconnectTimer = new Timer();
m_ReconnectTimer->SetInterval(10);

View File

@ -44,7 +44,7 @@ public:
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
protected:
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
Stream::Ptr m_Stream;

View File

@ -49,9 +49,9 @@ void PerfdataWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
status->Set("perfdatawriter", nodes);
}
void PerfdataWriter::Start(void)
void PerfdataWriter::Start(bool runtimeCreated)
{
ObjectImpl<PerfdataWriter>::Start();
ObjectImpl<PerfdataWriter>::Start(runtimeCreated);
Checkable::OnNewCheckResult.connect(boost::bind(&PerfdataWriter::CheckResultHandler, this, _1, _2));

View File

@ -46,7 +46,7 @@ public:
virtual void ValidateServiceFormatTemplate(const String& value, const ValidationUtils& utils) override;
protected:
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
void CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr);

View File

@ -97,7 +97,7 @@ void ApiListener::OnAllConfigLoaded(void)
/**
* Starts the component.
*/
void ApiListener::Start(void)
void ApiListener::Start(bool runtimeCreated)
{
SyncZoneDirs();
@ -107,7 +107,7 @@ void ApiListener::Start(void)
return;
}
ObjectImpl<ApiListener>::Start();
ObjectImpl<ApiListener>::Start(runtimeCreated);
{
boost::mutex::scoped_lock(m_LogLock);

View File

@ -89,7 +89,7 @@ public:
protected:
virtual void OnConfigLoaded(void) override;
virtual void OnAllConfigLoaded(void) override;
virtual void Start(void) override;
virtual void Start(bool runtimeCreated) override;
private:
boost::shared_ptr<SSL_CTX> m_SSLContext;

View File

@ -52,7 +52,7 @@ String ConfigObjectUtility::EscapeName(const String& name)
}
String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const String& fullName,
const Array::Ptr& templates, const Dictionary::Ptr& attrs)
bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs)
{
NameComposer *nc = dynamic_cast<NameComposer *>(type.get());
Dictionary::Ptr nameParts;
@ -78,7 +78,7 @@ String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const Stri
allAttrs->Set("version", Utility::GetTime());
std::ostringstream config;
ConfigWriter::EmitConfigItem(config, type->GetName(), name, false, templates, allAttrs);
ConfigWriter::EmitConfigItem(config, type->GetName(), name, false, ignoreOnError, templates, allAttrs);
ConfigWriter::EmitRaw(config, "\n");
return config.str();
@ -111,7 +111,7 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
WorkQueue upq;
if (!ConfigItem::CommitItems(upq) || !ConfigItem::ActivateItems(upq, false)) {
if (!ConfigItem::CommitItems(upq) || !ConfigItem::ActivateItems(upq, false, true)) {
if (errors) {
BOOST_FOREACH(const boost::exception_ptr& ex, upq.GetExceptions()) {
errors->Add(DiagnosticInformation(ex));
@ -161,7 +161,7 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
/* mark this object for cluster delete event */
object->SetExtension("ConfigObjectDeleted", true);
/* triggers signal for DB IDO and other interfaces */
object->Deactivate();
object->Deactivate(true);
if (item)
item->Unregister();

View File

@ -40,15 +40,15 @@ class I2_REMOTE_API ConfigObjectUtility
public:
static String GetConfigDir(void);
static String GetObjectConfigPath(const Type::Ptr& type, const String& fullName);
static String CreateObjectConfig(const Type::Ptr& type, const String& fullName,
const Array::Ptr& templates, const Dictionary::Ptr& attrs);
bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs);
static bool CreateObject(const Type::Ptr& type, const String& fullName,
const String& config, const Array::Ptr& errors);
static bool DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors);
private:
static String EscapeName(const String& name);
static bool DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors);

View File

@ -22,6 +22,7 @@
#include "remote/httputility.hpp"
#include "remote/filterutility.hpp"
#include "remote/apiaction.hpp"
#include "base/configtype.hpp"
#include <boost/algorithm/string.hpp>
#include <set>
@ -56,7 +57,12 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
String status;
Array::Ptr errors = new Array();
String config = ConfigObjectUtility::CreateObjectConfig(type, name, templates, attrs);
bool ignoreOnError = false;
if (params->Contains("ignore_on_error"))
ignoreOnError = HttpUtility::GetLastParameter(params, "ignore_on_error");
String config = ConfigObjectUtility::CreateObjectConfig(type, name, ignoreOnError, templates, attrs);
if (!ConfigObjectUtility::CreateObject(type, name, config, errors)) {
result1->Set("errors", errors);
@ -64,8 +70,16 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
return true;
}
ConfigType::Ptr dtype = ConfigType::GetByName(type->GetName());
ConfigObject::Ptr obj = dtype->GetObject(name);
result1->Set("code", 200);
result1->Set("status", "Object was created");
if (obj)
result1->Set("status", "Object was created");
else if (!obj && ignoreOnError)
result1->Set("status", "Object was not created but 'ignore_on_error' was set to true");
Array::Ptr results = new Array();
results->Add(result1);

View File

@ -874,12 +874,12 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
/* start/stop */
if (needs_tracking) {
m_Header << "virtual void Start(void) override;" << std::endl
<< "virtual void Stop(void) override;" << std::endl;
m_Header << "virtual void Start(bool runtimeCreated = false) override;" << std::endl
<< "virtual void Stop(bool runtimeRemoved = false) override;" << std::endl;
m_Impl << "void ObjectImpl<" << klass.Name << ">::Start(void)" << std::endl
m_Impl << "void ObjectImpl<" << klass.Name << ">::Start(bool runtimeCreated)" << std::endl
<< "{" << std::endl
<< "\t" << klass.Parent << "::Start();" << std::endl << std::endl;
<< "\t" << klass.Parent << "::Start(runtimeCreated);" << std::endl << std::endl;
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
if (!(it->Type.IsName))
@ -889,9 +889,9 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
}
m_Impl << "}" << std::endl << std::endl
<< "void ObjectImpl<" << klass.Name << ">::Stop(void)" << std::endl
<< "void ObjectImpl<" << klass.Name << ">::Stop(bool runtimeRemoved)" << std::endl
<< "{" << std::endl
<< "\t" << klass.Parent << "::Stop();" << std::endl << std::endl;
<< "\t" << klass.Parent << "::Stop(runtimeRemoved);" << std::endl << std::endl;
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
if (!(it->Type.IsName))