mirror of https://github.com/Icinga/icinga2.git
Validate configured TimePeriod ranges
Requires re-throwing the hidden exceptions inside the existing timeperiod code and validating the configured time range strings then. fixes #7576
This commit is contained in:
parent
1f05cc23d1
commit
2ed78e82a8
|
@ -179,6 +179,8 @@
|
|||
}
|
||||
|
||||
%type TimePeriod %inherits CustomVarObject {
|
||||
%validator "ValidateTimePeriodRanges",
|
||||
|
||||
%attribute %string "display_name",
|
||||
|
||||
%require "update",
|
||||
|
|
|
@ -289,7 +289,11 @@ void LegacyTimePeriod::ParseTimeRange(const String& timerange, tm *begin, tm *en
|
|||
String second = def.SubStr(pos + 1);
|
||||
second.Trim();
|
||||
|
||||
ParseTimeSpec(first, begin, NULL, reference);
|
||||
try {
|
||||
ParseTimeSpec(first, begin, NULL, reference);
|
||||
} catch (std::exception&) {
|
||||
throw;
|
||||
}
|
||||
|
||||
/* If the second definition starts with a number we need
|
||||
* to add the first word from the first definition, e.g.:
|
||||
|
@ -310,9 +314,17 @@ void LegacyTimePeriod::ParseTimeRange(const String& timerange, tm *begin, tm *en
|
|||
second = first.SubStr(0, xpos + 1) + second;
|
||||
}
|
||||
|
||||
ParseTimeSpec(second, NULL, end, reference);
|
||||
try {
|
||||
ParseTimeSpec(second, NULL, end, reference);
|
||||
} catch (std::exception&) {
|
||||
throw;
|
||||
}
|
||||
} else {
|
||||
ParseTimeSpec(def, begin, end, reference);
|
||||
try {
|
||||
ParseTimeSpec(def, begin, end, reference);
|
||||
} catch (std::exception&) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,7 +376,13 @@ void LegacyTimePeriod::ProcessTimeRangeRaw(const String& timerange, tm *referenc
|
|||
Dictionary::Ptr LegacyTimePeriod::ProcessTimeRange(const String& timestamp, tm *reference)
|
||||
{
|
||||
tm begin, end;
|
||||
ProcessTimeRangeRaw(timestamp, reference, &begin, &end);
|
||||
|
||||
try {
|
||||
ProcessTimeRangeRaw(timestamp, reference, &begin, &end);
|
||||
} catch (std::exception&) {
|
||||
throw;
|
||||
}
|
||||
|
||||
Dictionary::Ptr segment = new Dictionary();
|
||||
segment->Set("begin", (long)mktime(&begin));
|
||||
segment->Set("end", (long)mktime(&end));
|
||||
|
@ -378,7 +396,13 @@ void LegacyTimePeriod::ProcessTimeRanges(const String& timeranges, tm *reference
|
|||
boost::algorithm::split(ranges, timeranges, boost::is_any_of(","));
|
||||
|
||||
BOOST_FOREACH(const String& range, ranges) {
|
||||
Dictionary::Ptr segment = ProcessTimeRange(range, reference);
|
||||
Dictionary::Ptr segment;
|
||||
try {
|
||||
segment = ProcessTimeRange(range, reference);
|
||||
} catch (std::exception&) {
|
||||
throw;
|
||||
}
|
||||
|
||||
if (segment->Get("begin") >= segment->Get("end"))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Time period segment ends before it begins"));
|
||||
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
******************************************************************************/
|
||||
|
||||
#include "icinga/timeperiod.hpp"
|
||||
#include "icinga/legacytimeperiod.hpp"
|
||||
#include "base/dynamictype.hpp"
|
||||
#include "base/objectlock.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include "base/timer.hpp"
|
||||
#include "base/utility.hpp"
|
||||
|
@ -28,6 +30,7 @@
|
|||
using namespace icinga;
|
||||
|
||||
REGISTER_TYPE(TimePeriod);
|
||||
REGISTER_SCRIPTFUNCTION(ValidateTimePeriodRanges, &TimePeriod::ValidateRanges);
|
||||
|
||||
static Timer::Ptr l_UpdateTimer;
|
||||
|
||||
|
@ -297,3 +300,35 @@ void TimePeriod::Dump(void)
|
|||
|
||||
Log(LogDebug, "TimePeriod", "---");
|
||||
}
|
||||
|
||||
void TimePeriod::ValidateRanges(const String& location, const TimePeriod::Ptr& object)
|
||||
{
|
||||
Dictionary::Ptr ranges = object->GetRanges();
|
||||
|
||||
if (!ranges)
|
||||
return;
|
||||
|
||||
/* create a fake time environment to validate the definitions */
|
||||
time_t begin = Utility::GetTime();
|
||||
time_t end = begin + 24 * 60 * 60;
|
||||
tm reference = Utility::LocalTime(end);
|
||||
tm begin_tm, end_tm;
|
||||
Array::Ptr segments = new Array();
|
||||
|
||||
ObjectLock olock(ranges);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, ranges) {
|
||||
try {
|
||||
LegacyTimePeriod::ParseTimeSpec(kv.first, &begin_tm, &end_tm, &reference);
|
||||
} catch (std::exception&) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Invalid time specification.", object->GetDebugInfo()));
|
||||
}
|
||||
|
||||
try {
|
||||
LegacyTimePeriod::ProcessTimeRanges(kv.second, &reference, segments);
|
||||
} catch (std::exception&) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Invalid time range definition.", object->GetDebugInfo()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ public:
|
|||
bool IsInside(double ts) const;
|
||||
double FindNextTransition(double begin);
|
||||
|
||||
static void ValidateRanges(const String& location, const TimePeriod::Ptr& object);
|
||||
|
||||
private:
|
||||
void AddSegment(double s, double end);
|
||||
void AddSegment(const Dictionary::Ptr& segment);
|
||||
|
|
Loading…
Reference in New Issue