Merge pull request #8913 from Icinga/feature/remove-child-downtimes

API Action "remove-downtime": Also remove child downtimes
This commit is contained in:
Noah Hilverling 2021-07-27 18:02:15 +02:00 committed by GitHub
commit 07145d2e61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 16 deletions

View File

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

View File

@ -12,7 +12,7 @@ using namespace icinga;
void Checkable::RemoveAllDowntimes()
{
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);
Downtime::Ptr parent = GetByName(GetParent());
if (parent)
parent->RegisterChild(this);
if (runtimeCreated)
OnDowntimeAdded(this);
@ -141,6 +146,11 @@ void Downtime::Stop(bool runtimeRemoved)
{
GetCheckable()->UnregisterDowntime(this);
Downtime::Ptr parent = GetByName(GetParent());
if (parent)
parent->UnregisterChild(this);
if (runtimeRemoved)
OnDowntimeRemoved(this);
@ -217,7 +227,7 @@ int Downtime::GetNextDowntimeID()
Downtime::Ptr 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& scheduledDowntime, const String& scheduledBy, const String& parent,
const String& id, const MessageOrigin::Ptr& origin)
{
String fullName;
@ -237,6 +247,7 @@ Downtime::Ptr Downtime::AddDowntime(const Checkable::Ptr& checkable, const Strin
attrs->Set("duration", duration);
attrs->Set("triggered_by", triggeredBy);
attrs->Set("scheduled_by", scheduledBy);
attrs->Set("parent", parent);
attrs->Set("config_owner", scheduledDowntime);
attrs->Set("entry_time", Utility::GetTime());
@ -319,7 +330,7 @@ Downtime::Ptr Downtime::AddDowntime(const Checkable::Ptr& checkable, const Strin
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);
@ -333,6 +344,12 @@ void Downtime::RemoveDowntime(const String& id, bool cancelled, bool expired, co
"'. 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);
Array::Ptr errors = new Array();
@ -371,6 +388,24 @@ void Downtime::RemoveDowntime(const String& id, bool cancelled, bool expired, co
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()
{
if (IsInEffect() && IsTriggered())
@ -456,7 +491,7 @@ void Downtime::DowntimesExpireTimerHandler()
for (const Downtime::Ptr& downtime : downtimes) {
/* Only remove downtimes which are activated after daemon start. */
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,
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 String& scheduledBy = String(), const String& parent = String(), const String& id = String(),
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();
@ -70,6 +74,9 @@ protected:
private:
ObjectImpl<Checkable>::Ptr m_Checkable;
std::set<Downtime::Ptr> m_Children;
mutable std::mutex m_ChildrenMutex;
bool CanBeTriggered();
static void DowntimesStartTimerHandler();

View File

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

View File

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

View File

@ -1386,6 +1386,11 @@ bool IcingaDB::PrepareObject(const ConfigObject::Ptr& object, Dictionary::Ptr& a
attributes->Set("scheduled_by", scheduledBy);
}
auto parent (Downtime::GetByName(downtime->GetParent()));
if (parent) {
attributes->Set("parent_id", GetObjectIdentifier(parent));
}
return true;
}
@ -1740,6 +1745,13 @@ void IcingaDB::SendStartedDowntime(const Downtime::Ptr& downtime)
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);
}
@ -1813,6 +1825,13 @@ void IcingaDB::SendRemovedDowntime(const Downtime::Ptr& downtime)
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);
}