mirror of https://github.com/Icinga/icinga2.git
Put running downtimes in effect
If Icinga2 was restarted with a newly configured downtime that should be in effect at the time of restart, the should-be-running segment of it was not put into effect. Add new LegacyTimePeriod::FindRunningSegment() and ScheduledDowntime::FindRunningSegment() functions, call the latter in ScheduledDowntime::CreateNextDowntime() before trying the old ScheduledDowntime::FindNextSegment().
This commit is contained in:
parent
e76ec0d42e
commit
3b4dc854cf
|
@ -388,6 +388,56 @@ void LegacyTimePeriod::ProcessTimeRanges(const String& timeranges, tm *reference
|
|||
}
|
||||
}
|
||||
|
||||
Dictionary::Ptr LegacyTimePeriod::FindRunningSegment(const String& daydef, const String& timeranges, tm *reference)
|
||||
{
|
||||
tm begin, end, iter;
|
||||
time_t tsend, tsiter, tsref;
|
||||
int stride;
|
||||
|
||||
tsref = mktime(reference);
|
||||
|
||||
ParseTimeRange(daydef, &begin, &end, &stride, reference);
|
||||
|
||||
iter = begin;
|
||||
|
||||
tsend = mktime(&end);
|
||||
|
||||
do {
|
||||
if (IsInTimeRange(&begin, &end, stride, &iter)) {
|
||||
Array::Ptr segments = new Array();
|
||||
ProcessTimeRanges(timeranges, &iter, segments);
|
||||
|
||||
Dictionary::Ptr bestSegment;
|
||||
double bestEnd;
|
||||
|
||||
ObjectLock olock(segments);
|
||||
for (const Dictionary::Ptr& segment : segments) {
|
||||
double begin = segment->Get("begin");
|
||||
double end = segment->Get("end");
|
||||
|
||||
if (begin >= tsref || end < tsref)
|
||||
continue;
|
||||
|
||||
if (!bestSegment || end > bestEnd) {
|
||||
bestSegment = segment;
|
||||
bestEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestSegment)
|
||||
return bestSegment;
|
||||
}
|
||||
|
||||
iter.tm_mday++;
|
||||
iter.tm_hour = 0;
|
||||
iter.tm_min = 0;
|
||||
iter.tm_sec = 0;
|
||||
tsiter = mktime(&iter);
|
||||
} while (tsiter < tsend);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Dictionary::Ptr LegacyTimePeriod::FindNextSegment(const String& daydef, const String& timeranges, tm *reference)
|
||||
{
|
||||
tm begin, end, iter, ref;
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
static Dictionary::Ptr ProcessTimeRange(const String& timerange, tm *reference);
|
||||
static void ProcessTimeRanges(const String& timeranges, tm *reference, const Array::Ptr& result);
|
||||
static Dictionary::Ptr FindNextSegment(const String& daydef, const String& timeranges, tm *reference);
|
||||
static Dictionary::Ptr FindRunningSegment(const String& daydef, const String& timeranges, tm *reference);
|
||||
|
||||
private:
|
||||
LegacyTimePeriod();
|
||||
|
|
|
@ -117,6 +117,67 @@ Checkable::Ptr ScheduledDowntime::GetCheckable() const
|
|||
return host->GetServiceByShortName(GetServiceName());
|
||||
}
|
||||
|
||||
std::pair<double, double> ScheduledDowntime::FindRunningSegment(double minEnd)
|
||||
{
|
||||
time_t refts = Utility::GetTime();
|
||||
tm reference = Utility::LocalTime(refts);
|
||||
|
||||
Log(LogDebug, "ScheduledDowntime")
|
||||
<< "Finding running scheduled downtime segment for time " << refts
|
||||
<< " (minEnd " << (minEnd > 0 ? Utility::FormatDateTime("%c", minEnd) : "-") << ")";
|
||||
|
||||
Dictionary::Ptr ranges = GetRanges();
|
||||
|
||||
if (!ranges)
|
||||
return std::make_pair(0, 0);
|
||||
|
||||
Array::Ptr segments = new Array();
|
||||
|
||||
Dictionary::Ptr bestSegment;
|
||||
double bestBegin, bestEnd;
|
||||
double now = Utility::GetTime();
|
||||
|
||||
ObjectLock olock(ranges);
|
||||
|
||||
/* Find the longest lasting (and longer than minEnd, if given) segment that's already running */
|
||||
for (const Dictionary::Pair& kv : ranges) {
|
||||
Log(LogDebug, "ScheduledDowntime")
|
||||
<< "Evaluating (running?) segment: " << kv.first << ": " << kv.second;
|
||||
|
||||
Dictionary::Ptr segment = LegacyTimePeriod::FindRunningSegment(kv.first, kv.second, &reference);
|
||||
|
||||
if (!segment)
|
||||
continue;
|
||||
|
||||
double begin = segment->Get("begin");
|
||||
double end = segment->Get("end");
|
||||
|
||||
Log(LogDebug, "ScheduledDowntime")
|
||||
<< "Considering (running?) segment: " << Utility::FormatDateTime("%c", begin) << " -> " << Utility::FormatDateTime("%c", end);
|
||||
|
||||
if (begin >= now || end < now) {
|
||||
Log(LogDebug, "ScheduledDowntime") << "not running.";
|
||||
continue;
|
||||
}
|
||||
if (minEnd && end <= minEnd) {
|
||||
Log(LogDebug, "ScheduledDowntime") << "ending too early.";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!bestSegment || end > bestEnd) {
|
||||
Log(LogDebug, "ScheduledDowntime") << "(best match yet)";
|
||||
bestSegment = segment;
|
||||
bestBegin = begin;
|
||||
bestEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestSegment)
|
||||
return std::make_pair(bestBegin, bestEnd);
|
||||
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
|
||||
std::pair<double, double> ScheduledDowntime::FindNextSegment()
|
||||
{
|
||||
time_t refts = Utility::GetTime();
|
||||
|
@ -133,10 +194,12 @@ std::pair<double, double> ScheduledDowntime::FindNextSegment()
|
|||
Array::Ptr segments = new Array();
|
||||
|
||||
Dictionary::Ptr bestSegment;
|
||||
double bestBegin;
|
||||
double bestBegin, bestEnd;
|
||||
double now = Utility::GetTime();
|
||||
|
||||
ObjectLock olock(ranges);
|
||||
|
||||
/* Find the segment starting earliest */
|
||||
for (const Dictionary::Pair& kv : ranges) {
|
||||
Log(LogDebug, "ScheduledDowntime")
|
||||
<< "Evaluating segment: " << kv.first << ": " << kv.second;
|
||||
|
@ -146,24 +209,29 @@ std::pair<double, double> ScheduledDowntime::FindNextSegment()
|
|||
if (!segment)
|
||||
continue;
|
||||
|
||||
Log(LogDebug, "ScheduledDowntime")
|
||||
<< "Considering segment: " << Utility::FormatDateTime("%c", segment->Get("begin")) << " -> " << Utility::FormatDateTime("%c", segment->Get("end"));
|
||||
|
||||
double begin = segment->Get("begin");
|
||||
double end = segment->Get("end");
|
||||
|
||||
if (begin < now)
|
||||
Log(LogDebug, "ScheduledDowntime")
|
||||
<< "Considering segment: " << Utility::FormatDateTime("%c", begin) << " -> " << Utility::FormatDateTime("%c", end);
|
||||
|
||||
if (begin < now) {
|
||||
Log(LogDebug, "ScheduledDowntime") << "already running.";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!bestSegment || begin < bestBegin) {
|
||||
Log(LogDebug, "ScheduledDowntime") << "(best match yet)";
|
||||
bestSegment = segment;
|
||||
bestBegin = begin;
|
||||
bestEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestSegment)
|
||||
return std::make_pair(bestSegment->Get("begin"), bestSegment->Get("end"));
|
||||
else
|
||||
return std::make_pair(0, 0);
|
||||
return std::make_pair(bestBegin, bestEnd);
|
||||
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
|
||||
void ScheduledDowntime::CreateNextDowntime()
|
||||
|
@ -175,7 +243,13 @@ void ScheduledDowntime::CreateNextDowntime()
|
|||
return;
|
||||
}
|
||||
|
||||
double minEnd = 0;
|
||||
|
||||
for (const Downtime::Ptr& downtime : GetCheckable()->GetDowntimes()) {
|
||||
double end = downtime->GetEndTime();
|
||||
if (end > minEnd)
|
||||
minEnd = end;
|
||||
|
||||
if (downtime->GetScheduledBy() != GetName() ||
|
||||
downtime->GetStartTime() < Utility::GetTime())
|
||||
continue;
|
||||
|
@ -187,10 +261,12 @@ void ScheduledDowntime::CreateNextDowntime()
|
|||
Log(LogDebug, "ScheduledDowntime")
|
||||
<< "Creating new Downtime for ScheduledDowntime \"" << GetName() << "\"";
|
||||
|
||||
std::pair<double, double> segment = FindNextSegment();
|
||||
|
||||
if (segment.first == 0 && segment.second == 0)
|
||||
return;
|
||||
std::pair<double, double> segment = FindRunningSegment(minEnd);
|
||||
if (segment.first == 0 && segment.second == 0) {
|
||||
segment = FindNextSegment();
|
||||
if (segment.first == 0 && segment.second == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
String downtimeName = Downtime::AddDowntime(GetCheckable(), GetAuthor(), GetComment(),
|
||||
segment.first, segment.second,
|
||||
|
|
|
@ -58,6 +58,7 @@ protected:
|
|||
private:
|
||||
static void TimerProc();
|
||||
|
||||
std::pair<double, double> FindRunningSegment(double minEnd = 0);
|
||||
std::pair<double, double> FindNextSegment();
|
||||
void CreateNextDowntime();
|
||||
|
||||
|
|
Loading…
Reference in New Issue