API Action 'remove-downtime': Also remove child downtimes

This commit is contained in:
Noah Hilverling 2021-07-22 17:43:03 +02:00
parent 89472a9e51
commit 7217959206
7 changed files with 85 additions and 16 deletions

View File

@ -408,7 +408,7 @@ Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object,
<< "Creating downtime for service " << hostService->GetName() << " on host " << host->GetName(); << "Creating downtime for service " << hostService->GetName() << " on host " << host->GetName();
Downtime::Ptr serviceDowntime = Downtime::AddDowntime(hostService, author, comment, startTime, endTime, Downtime::Ptr serviceDowntime = Downtime::AddDowntime(hostService, author, comment, startTime, endTime,
fixed, triggerName, duration); fixed, triggerName, duration, String(), String(), downtimeName);
String serviceDowntimeName = serviceDowntime->GetName(); String serviceDowntimeName = serviceDowntime->GetName();
serviceDowntimes.push_back(new Dictionary({ serviceDowntimes.push_back(new Dictionary({
@ -490,6 +490,8 @@ Dictionary::Ptr ApiActions::RemoveDowntime(const ConfigObject::Ptr& object,
auto author (HttpUtility::GetLastParameter(params, "author")); auto author (HttpUtility::GetLastParameter(params, "author"));
Checkable::Ptr checkable = dynamic_pointer_cast<Checkable>(object); Checkable::Ptr checkable = dynamic_pointer_cast<Checkable>(object);
size_t childCount = 0;
if (checkable) { if (checkable) {
std::set<Downtime::Ptr> downtimes = checkable->GetDowntimes(); std::set<Downtime::Ptr> downtimes = checkable->GetDowntimes();
@ -499,8 +501,10 @@ Dictionary::Ptr ApiActions::RemoveDowntime(const ConfigObject::Ptr& object,
downtime->SetRemovedBy(author); downtime->SetRemovedBy(author);
} }
childCount += downtime->GetChildren().size();
try { try {
Downtime::RemoveDowntime(downtime->GetName(), true); Downtime::RemoveDowntime(downtime->GetName(), true, true);
} catch (const invalid_downtime_removal_error& error) { } catch (const invalid_downtime_removal_error& error) {
Log(LogWarning, "ApiActions") << error.what(); Log(LogWarning, "ApiActions") << error.what();
@ -508,7 +512,8 @@ Dictionary::Ptr ApiActions::RemoveDowntime(const ConfigObject::Ptr& object,
} }
} }
return ApiActions::CreateResult(200, "Successfully removed all downtimes for object '" + checkable->GetName() + "'."); return ApiActions::CreateResult(200, "Successfully removed all downtimes for object '" +
checkable->GetName() + "' and " + std::to_string(childCount) + " child downtimes.");
} }
Downtime::Ptr downtime = static_pointer_cast<Downtime>(object); Downtime::Ptr downtime = static_pointer_cast<Downtime>(object);
@ -521,12 +526,14 @@ Dictionary::Ptr ApiActions::RemoveDowntime(const ConfigObject::Ptr& object,
downtime->SetRemovedBy(author); downtime->SetRemovedBy(author);
} }
childCount += downtime->GetChildren().size();
try { try {
String downtimeName = downtime->GetName(); String downtimeName = downtime->GetName();
Downtime::RemoveDowntime(downtimeName, true, true);
Downtime::RemoveDowntime(downtimeName, true); return ApiActions::CreateResult(200, "Successfully removed downtime '" + downtimeName +
"' and " + std::to_string(childCount) + " child downtimes.");
return ApiActions::CreateResult(200, "Successfully removed downtime '" + downtimeName + "'.");
} catch (const invalid_downtime_removal_error& error) { } catch (const invalid_downtime_removal_error& error) {
Log(LogWarning, "ApiActions") << error.what(); Log(LogWarning, "ApiActions") << error.what();

View File

@ -12,7 +12,7 @@ using namespace icinga;
void Checkable::RemoveAllDowntimes() void Checkable::RemoveAllDowntimes()
{ {
for (const Downtime::Ptr& downtime : GetDowntimes()) { for (const Downtime::Ptr& downtime : GetDowntimes()) {
Downtime::RemoveDowntime(downtime->GetName(), true, true); Downtime::RemoveDowntime(downtime->GetName(), true, true, true);
} }
} }

View File

@ -114,6 +114,11 @@ void Downtime::Start(bool runtimeCreated)
checkable->RegisterDowntime(this); checkable->RegisterDowntime(this);
Downtime::Ptr parent = GetByName(GetParent());
if (parent)
parent->RegisterChild(this);
if (runtimeCreated) if (runtimeCreated)
OnDowntimeAdded(this); OnDowntimeAdded(this);
@ -141,6 +146,11 @@ void Downtime::Stop(bool runtimeRemoved)
{ {
GetCheckable()->UnregisterDowntime(this); GetCheckable()->UnregisterDowntime(this);
Downtime::Ptr parent = GetByName(GetParent());
if (parent)
parent->UnregisterChild(this);
if (runtimeRemoved) if (runtimeRemoved)
OnDowntimeRemoved(this); OnDowntimeRemoved(this);
@ -217,7 +227,7 @@ int Downtime::GetNextDowntimeID()
Downtime::Ptr Downtime::AddDowntime(const Checkable::Ptr& checkable, const String& author, Downtime::Ptr Downtime::AddDowntime(const Checkable::Ptr& checkable, const String& author,
const String& comment, double startTime, double endTime, bool fixed, const String& comment, double startTime, double endTime, bool fixed,
const String& triggeredBy, double duration, const String& triggeredBy, double duration,
const String& scheduledDowntime, const String& scheduledBy, const String& scheduledDowntime, const String& scheduledBy, const String& parent,
const String& id, const MessageOrigin::Ptr& origin) const String& id, const MessageOrigin::Ptr& origin)
{ {
String fullName; String fullName;
@ -237,6 +247,7 @@ Downtime::Ptr Downtime::AddDowntime(const Checkable::Ptr& checkable, const Strin
attrs->Set("duration", duration); attrs->Set("duration", duration);
attrs->Set("triggered_by", triggeredBy); attrs->Set("triggered_by", triggeredBy);
attrs->Set("scheduled_by", scheduledBy); attrs->Set("scheduled_by", scheduledBy);
attrs->Set("parent", parent);
attrs->Set("config_owner", scheduledDowntime); attrs->Set("config_owner", scheduledDowntime);
attrs->Set("entry_time", Utility::GetTime()); attrs->Set("entry_time", Utility::GetTime());
@ -319,7 +330,7 @@ Downtime::Ptr Downtime::AddDowntime(const Checkable::Ptr& checkable, const Strin
return downtime; return downtime;
} }
void Downtime::RemoveDowntime(const String& id, bool cancelled, bool expired, const MessageOrigin::Ptr& origin) void Downtime::RemoveDowntime(const String& id, bool includeChildren, bool cancelled, bool expired, const MessageOrigin::Ptr& origin)
{ {
Downtime::Ptr downtime = Downtime::GetByName(id); Downtime::Ptr downtime = Downtime::GetByName(id);
@ -333,6 +344,12 @@ void Downtime::RemoveDowntime(const String& id, bool cancelled, bool expired, co
"'. It is owned by scheduled downtime object '" + config_owner + "'")); "'. It is owned by scheduled downtime object '" + config_owner + "'"));
} }
if (includeChildren) {
for (const Downtime::Ptr& child : downtime->GetChildren()) {
Downtime::RemoveDowntime(child->GetName(), true, true);
}
}
downtime->SetWasCancelled(cancelled); downtime->SetWasCancelled(cancelled);
Array::Ptr errors = new Array(); Array::Ptr errors = new Array();
@ -371,6 +388,24 @@ void Downtime::RemoveDowntime(const String& id, bool cancelled, bool expired, co
msg << " (Reason: " << reason << ")."; msg << " (Reason: " << reason << ").";
} }
void Downtime::RegisterChild(const Downtime::Ptr& downtime)
{
std::unique_lock<std::mutex> lock(m_ChildrenMutex);
m_Children.insert(downtime);
}
void Downtime::UnregisterChild(const Downtime::Ptr& downtime)
{
std::unique_lock<std::mutex> lock(m_ChildrenMutex);
m_Children.erase(downtime);
}
std::set<Downtime::Ptr> Downtime::GetChildren() const
{
std::unique_lock<std::mutex> lock(m_ChildrenMutex);
return m_Children;
}
bool Downtime::CanBeTriggered() bool Downtime::CanBeTriggered()
{ {
if (IsInEffect() && IsTriggered()) if (IsInEffect() && IsTriggered())
@ -456,7 +491,7 @@ void Downtime::DowntimesExpireTimerHandler()
for (const Downtime::Ptr& downtime : downtimes) { for (const Downtime::Ptr& downtime : downtimes) {
/* Only remove downtimes which are activated after daemon start. */ /* Only remove downtimes which are activated after daemon start. */
if (downtime->IsActive() && (downtime->IsExpired() || !downtime->HasValidConfigOwner())) if (downtime->IsActive() && (downtime->IsExpired() || !downtime->HasValidConfigOwner()))
RemoveDowntime(downtime->GetName(), false, true); RemoveDowntime(downtime->GetName(), false, false, true);
} }
} }

View File

@ -48,10 +48,14 @@ public:
static Ptr AddDowntime(const intrusive_ptr<Checkable>& checkable, const String& author, static Ptr AddDowntime(const intrusive_ptr<Checkable>& checkable, const String& author,
const String& comment, double startTime, double endTime, bool fixed, const String& comment, double startTime, double endTime, bool fixed,
const String& triggeredBy, double duration, const String& scheduledDowntime = String(), const String& triggeredBy, double duration, const String& scheduledDowntime = String(),
const String& scheduledBy = String(), const String& id = String(), const String& scheduledBy = String(), const String& parent = String(), const String& id = String(),
const MessageOrigin::Ptr& origin = nullptr); const MessageOrigin::Ptr& origin = nullptr);
static void RemoveDowntime(const String& id, bool cancelled, bool expired = false, const MessageOrigin::Ptr& origin = nullptr); static void RemoveDowntime(const String& id, bool includeChildren, bool cancelled, bool expired = false, const MessageOrigin::Ptr& origin = nullptr);
void RegisterChild(const Downtime::Ptr& downtime);
void UnregisterChild(const Downtime::Ptr& downtime);
std::set<Downtime::Ptr> GetChildren() const;
void TriggerDowntime(); void TriggerDowntime();
@ -70,6 +74,9 @@ protected:
private: private:
ObjectImpl<Checkable>::Ptr m_Checkable; ObjectImpl<Checkable>::Ptr m_Checkable;
std::set<Downtime::Ptr> m_Children;
mutable std::mutex m_ChildrenMutex;
bool CanBeTriggered(); bool CanBeTriggered();
static void DowntimesStartTimerHandler(); static void DowntimesStartTimerHandler();

View File

@ -63,6 +63,7 @@ class Downtime : ConfigObject < DowntimeNameComposer
[config] Timestamp duration; [config] Timestamp duration;
[config] String triggered_by; [config] String triggered_by;
[config] String scheduled_by; [config] String scheduled_by;
[config] String parent;
[state] Array::Ptr triggers { [state] Array::Ptr triggers {
default {{{ return new Array(); }}} default {{{ return new Array(); }}}
}; };

View File

@ -986,7 +986,7 @@ void ExternalCommandProcessor::DelSvcDowntime(double, const std::vector<String>&
String rid = Downtime::GetDowntimeIDFromLegacyID(id); String rid = Downtime::GetDowntimeIDFromLegacyID(id);
try { try {
Downtime::RemoveDowntime(rid, true); Downtime::RemoveDowntime(rid, false, true);
Log(LogNotice, "ExternalCommandProcessor") Log(LogNotice, "ExternalCommandProcessor")
<< "Removed downtime ID " << arguments[0]; << "Removed downtime ID " << arguments[0];
@ -1094,7 +1094,7 @@ void ExternalCommandProcessor::DelHostDowntime(double, const std::vector<String>
String rid = Downtime::GetDowntimeIDFromLegacyID(id); String rid = Downtime::GetDowntimeIDFromLegacyID(id);
try { try {
Downtime::RemoveDowntime(rid, true); Downtime::RemoveDowntime(rid, false, true);
Log(LogNotice, "ExternalCommandProcessor") Log(LogNotice, "ExternalCommandProcessor")
<< "Removed downtime ID " << arguments[0]; << "Removed downtime ID " << arguments[0];
@ -1129,7 +1129,7 @@ void ExternalCommandProcessor::DelDowntimeByHostName(double, const std::vector<S
for (const Downtime::Ptr& downtime : host->GetDowntimes()) { for (const Downtime::Ptr& downtime : host->GetDowntimes()) {
try { try {
String downtimeName = downtime->GetName(); String downtimeName = downtime->GetName();
Downtime::RemoveDowntime(downtimeName, true); Downtime::RemoveDowntime(downtimeName, false, true);
Log(LogNotice, "ExternalCommandProcessor") Log(LogNotice, "ExternalCommandProcessor")
<< "Removed downtime '" << downtimeName << "'."; << "Removed downtime '" << downtimeName << "'.";
@ -1151,7 +1151,7 @@ void ExternalCommandProcessor::DelDowntimeByHostName(double, const std::vector<S
try { try {
String downtimeName = downtime->GetName(); String downtimeName = downtime->GetName();
Downtime::RemoveDowntime(downtimeName, true); Downtime::RemoveDowntime(downtimeName, false, true);
Log(LogNotice, "ExternalCommandProcessor") Log(LogNotice, "ExternalCommandProcessor")
<< "Removed downtime '" << downtimeName << "'."; << "Removed downtime '" << downtimeName << "'.";

View File

@ -1386,6 +1386,11 @@ bool IcingaDB::PrepareObject(const ConfigObject::Ptr& object, Dictionary::Ptr& a
attributes->Set("scheduled_by", scheduledBy); attributes->Set("scheduled_by", scheduledBy);
} }
auto parent (Downtime::GetByName(downtime->GetParent()));
if (parent) {
attributes->Set("parent_id", GetObjectIdentifier(parent));
}
return true; return true;
} }
@ -1739,6 +1744,13 @@ void IcingaDB::SendStartedDowntime(const Downtime::Ptr& downtime)
xAdd.emplace_back(GetObjectIdentifier(endpoint)); xAdd.emplace_back(GetObjectIdentifier(endpoint));
} }
auto parent (Downtime::GetByName(downtime->GetParent()));
if (parent) {
xAdd.emplace_back("parent_id");
xAdd.emplace_back(GetObjectIdentifier(parent));
}
m_Rcon->FireAndForgetQuery(std::move(xAdd), Prio::History); m_Rcon->FireAndForgetQuery(std::move(xAdd), Prio::History);
} }
@ -1812,6 +1824,13 @@ void IcingaDB::SendRemovedDowntime(const Downtime::Ptr& downtime)
xAdd.emplace_back(GetObjectIdentifier(endpoint)); xAdd.emplace_back(GetObjectIdentifier(endpoint));
} }
auto parent (Downtime::GetByName(downtime->GetParent()));
if (parent) {
xAdd.emplace_back("parent_id");
xAdd.emplace_back(GetObjectIdentifier(parent));
}
m_Rcon->FireAndForgetQuery(std::move(xAdd), Prio::History); m_Rcon->FireAndForgetQuery(std::move(xAdd), Prio::History);
} }