[icinga-checkins] icinga.org: icinga2/feature/timeperiod-exclude-7355: Implement exclude and include ability for timeranges

git at icinga.org git at icinga.org
Sat May 21 19:03:13 CEST 2016


Module: icinga2
Branch: feature/timeperiod-exclude-7355
Commit: 699644b5693bf19b059775f2095f38cee042d181
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=699644b5693bf19b059775f2095f38cee042d181

Author: Philipp Dallig <philipp.dallig at gmail.com>
Date:   Fri Mar 25 12:55:11 2016 +0100

Implement exclude and include ability for timeranges

With this change we can include and exclude timeranges in timeranges. I
think we need this feature to support holidays and so on

refs #7355

Signed-off-by: Michael Friedrich <michael.friedrich at netways.de>

---

 doc/6-object-types.md     |    3 ++
 lib/icinga/timeperiod.cpp |   71 +++++++++++++++++++++++++++++++++++++++++++--
 lib/icinga/timeperiod.hpp |    3 ++
 lib/icinga/timeperiod.ti  |    9 ++++++
 4 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/doc/6-object-types.md b/doc/6-object-types.md
index 1518a62..48c9a90 100644
--- a/doc/6-object-types.md
+++ b/doc/6-object-types.md
@@ -1380,6 +1380,9 @@ Configuration Attributes:
   display_name    |**Optional.** A short description of the time period.
   update          |**Required.** The "update" script method takes care of updating the internal representation of the time period. In virtually all cases you should import the "legacy-timeperiod" template to take care of this setting.
   ranges          |**Required.** A dictionary containing information which days and durations apply to this timeperiod.
+  prefer_includes |**Optional.** Boolean for prefer include or exclude timeperiods. Default to true.
+  excludes        |**Optional.** An array of timeperiods, which should exclude from your timerange.
+  includes        |**Optional.** An array of timeperiods, which should include into your timerange
 
 The `/etc/icinga2/conf.d/timeperiods.conf` file is usually used to define
 timeperiods including this one.
diff --git a/lib/icinga/timeperiod.cpp b/lib/icinga/timeperiod.cpp
index be2a6fd..c4807d0 100644
--- a/lib/icinga/timeperiod.cpp
+++ b/lib/icinga/timeperiod.cpp
@@ -77,15 +77,22 @@ void TimePeriod::AddSegment(double begin, double end)
 			if (segment->Get("begin") <= begin && segment->Get("end") >= end)
 				return; /* New segment is fully contained in this segment. */
 
-			if (segment->Get("begin") <= begin && segment->Get("end") >= begin) {
-				segment->Set("end", end); /* Extend an existing segment. */
+			if (segment->Get("begin") >= begin && segment->Get("end") <= end) {
+				segment->Set("begin", begin);
+				segment->Set("end", end); /* Extend an existing segment to both sides */
+				return;
+			}
+
+			if (segment->Get("end") >= begin && segment->Get("end") <= end) {
+				segment->Set("end", end); /* Extend an existing segment to right. */
 				return;
 			}
 
 			if (segment->Get("begin") >= begin && segment->Get("begin") <= end) {
-				segment->Set("begin", begin); /* Extend an existing segment. */
+				segment->Set("begin", begin); /* Extend an existing segment to left. */
 				return;
 			}
+
 		}
 	}
 
@@ -142,6 +149,19 @@ void TimePeriod::RemoveSegment(double begin, double end)
 			continue;
 		}
 
+		/* cut between */
+		if (segment->Get("begin") < begin && segment->Get("end") > end) {
+			Dictionary::Ptr firstsegment = new Dictionary();
+			firstsegment->Set("begin", segment->Get("begin"));
+			firstsegment->Set("end", begin);
+			Dictionary::Ptr secondsegment = new Dictionary();
+			secondsegment->Set("begin", end);
+			secondsegment->Set("end", segment->Get("end"));
+			newSegments->Add(firstsegment);
+			newSegments->Add(secondsegment);
+			continue;
+		}
+
 		/* Adjust the begin/end timestamps so as to not overlap with the specified range. */
 		if (segment->Get("begin") > begin && segment->Get("begin") < end)
 			segment->Set("begin", end);
@@ -157,6 +177,11 @@ void TimePeriod::RemoveSegment(double begin, double end)
 	Dump();
 }
 
+void TimePeriod::RemoveSegment(const Dictionary::Ptr& segment)
+{
+	RemoveSegment(segment->Get("begin"), segment->Get("end"));
+}
+
 void TimePeriod::PurgeSegments(double end)
 {
 	ASSERT(OwnsLock());
@@ -187,6 +212,23 @@ void TimePeriod::PurgeSegments(double end)
 	SetSegments(newSegments);
 }
 
+void TimePeriod::Merge(const TimePeriod::Ptr& timeperiod, bool include)
+{
+	Log(LogDebug, "TimePeriod")
+		<< "Merge TimePeriod '" << GetName() << "' with '" << timeperiod->GetName() << "'";
+	Log(LogDebug, "TimePeriod")
+		<< "Method: " << (include ? "include" : "exclude");
+
+	Array::Ptr segments = timeperiod->GetSegments();
+	if (segments) {
+		ObjectLock dlock(segments);
+		ObjectLock ilock(this);
+		BOOST_FOREACH(const Dictionary::Ptr& segment, segments) {
+			include ? AddSegment(segment) : RemoveSegment(segment);
+		}
+	}
+}
+
 void TimePeriod::UpdateRegion(double begin, double end, bool clearExisting)
 {
 	if (!clearExisting) {
@@ -215,6 +257,29 @@ void TimePeriod::UpdateRegion(double begin, double end, bool clearExisting)
 			}
 		}
 	}
+
+	bool prefer_include = GetPreferIncludes();
+	/* First handle the non prefered timerange */
+	Array::Ptr timeranges = prefer_include ? GetExcludes() : GetIncludes();
+	if (timeranges) {
+		ObjectLock olock(timeranges);
+		BOOST_FOREACH(const String& name , timeranges) {
+			const TimePeriod::Ptr timeperiod = TimePeriod::GetByName(name);
+			if (timeperiod)
+				Merge(timeperiod, !prefer_include);
+		}
+	}
+
+	/* Prefered timerange must be handle last */
+	timeranges = prefer_include ? GetIncludes() : GetExcludes();
+	if (timeranges) {
+		ObjectLock olock(timeranges);
+		BOOST_FOREACH(const String& name, timeranges) {
+			const TimePeriod::Ptr timeperiod = TimePeriod::GetByName(name);
+			if (timeperiod)
+				Merge(timeperiod, prefer_include);
+		}
+	}
 }
 
 bool TimePeriod::GetIsInside(void) const
diff --git a/lib/icinga/timeperiod.hpp b/lib/icinga/timeperiod.hpp
index 51100f5..9b6c881 100644
--- a/lib/icinga/timeperiod.hpp
+++ b/lib/icinga/timeperiod.hpp
@@ -54,8 +54,11 @@ private:
 	void AddSegment(double s, double end);
 	void AddSegment(const Dictionary::Ptr& segment);
 	void RemoveSegment(double begin, double end);
+	void RemoveSegment(const Dictionary::Ptr& segment);
 	void PurgeSegments(double end);
 
+	void Merge(const TimePeriod::Ptr& timeperiod, bool include = true);
+
 	void Dump(void);
 
 	static void UpdateTimerHandler(void);
diff --git a/lib/icinga/timeperiod.ti b/lib/icinga/timeperiod.ti
index 2b78b51..50b3a77 100644
--- a/lib/icinga/timeperiod.ti
+++ b/lib/icinga/timeperiod.ti
@@ -37,6 +37,15 @@ class TimePeriod : CustomVarObject
 	};
 	[config] Dictionary::Ptr ranges;
 	[config, required] Function::Ptr update;
+	[config] bool prefer_includes {
+		default {{{ return true; }}}
+	};
+	[config] array(name(TimePeriod)) excludes {
+		default {{{ return new Array(); }}}
+	};
+	[config] array(name(TimePeriod)) includes {
+		default {{{ return new Array(); }}}
+	};
 	[state, no_user_modify] Value valid_begin;
 	[state, no_user_modify] Value valid_end;
 	[state, no_user_modify] Array::Ptr segments;



More information about the icinga-checkins mailing list