Per von Zweigbergk <pvz@itassistans.se>
Petr Ruzicka <petr.ruzicka@gmail.com>
Phil Hutchinson <phil@volumedia.co.uk>
+Philipp Dallig <philipp.dallig@gmail.com>
Ralph Breier <ralph.breier@roedl.com>
Reto Zeder <reto.zeder@arcade.ch>
Ricardo Bartels <ricardo@bitchbrothers.com>
## <a id="timeperiods"></a> Time Periods
-Time Periods define time ranges in Icinga where event actions are
-triggered, for example whether a service check is executed or not within
+[Time Periods](6-object-types.md#objecttype-timeperiod) define
+time ranges in Icinga where event actions are triggered, for
+example whether a service check is executed or not within
the `check_period` attribute. Or a notification should be sent to
users or not, filtered by the `period` and `notification_period`
configuration attributes for `Notification` and `User` objects.
period = "workhours"
}
+### <a id="timeperiods-includes-excludes"></a> Time Periods Inclusion and Exclusion
+
+Sometimes it is necessary to exclude certain time ranges from
+your default time period definitions. For example if you don't
+want to send out any notification during the holiday season,
+or if you only want to allow small time windows for executed checks.
+
+The [TimePeriod object](6-object-types.md#objecttype-timeperiod)
+provides the `includes` and `excludes` attributes to solve this issue.
+`prefer_includes` defines whether included or excluded time periods are
+preferred.
+
+The following example defines a time period called `holidays` where
+notifications should be supressed:
+
+ object TimePeriod "holidays" {
+ import "legacy-timeperiod"
+
+ ranges = {
+ "january 1" = "00:00-24:00" //new year's day
+ "july 4" = "00:00-24:00" //independence day
+ "december 25" = "00:00-24:00" //christmas
+ "december 31" = "18:00-24:00" //new year's eve (6pm+)
+ "2017-04-16" = "00:00-24:00" //easter 2017
+ "monday -1 may" = "00:00-24:00" //memorial day (last monday in may)
+ "monday 1 september" = "00:00-24:00" //labor day (1st monday in september)
+ "thursday 4 november" = "00:00-24:00" //thanksgiving (4th thursday in november)
+ }
+ }
+
+In addition to that the time period `weekends` defines an additional
+time window which should be excluded from notifications:
+
+ object TimePeriod "weekends-excluded" {
+ import "legacy-timeperiod"
+
+ ranges = {
+ "saturday" = "00:00-09:00,18:00-24:00"
+ "sunday" = "00:00-09:00,18:00-24:00"
+ }
+ }
+
+The time period `prod-notification` defines the default time ranges
+and adds the excluded time period names as an array.
+
+ object TimePeriod "prod-notification" {
+ import "legacy-timeperiod"
+
+ excludes = [ "holidays", "weekends-excluded" ]
+
+ ranges = {
+ "monday" = "00:00-24:00"
+ "tuesday" = "00:00-24:00"
+ "wednesday" = "00:00-24:00"
+ "thursday" = "00:00-24:00"
+ "friday" = "00:00-24:00"
+ "saturday" = "00:00-24:00"
+ "sunday" = "00:00-24:00"
+ }
+ }
+
## <a id="use-functions-object-config"></a> Use Functions in Object Configuration
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 whether to prefer timeperiods `includes` or `excludes`. 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.
if (tp && !tp->IsInside(Utility::GetTime())) {
Log(LogNotice, "CheckerComponent")
- << "Skipping check for object '" << checkable->GetName() << "': not in check_period";
+ << "Skipping check for object '" << checkable->GetName()
+ << "': not in check period '" << tp->GetName() << "'";
check = false;
}
}
if (tp && !tp->IsInside(Utility::GetTime())) {
Log(LogNotice, "Notification")
- << "Not sending notifications for notification object '" << GetName() << "': not in timeperiod";
+ << "Not sending notifications for notification object '" << GetName()
+ << "': not in timeperiod '" << tp->GetName() << "'";
return;
}
if (tp && !tp->IsInside(Utility::GetTime())) {
Log(LogNotice, "Notification")
<< "Not sending notifications for notification object '"
- << GetName() << " and user '" << user->GetName() << "': user not in timeperiod";
+ << GetName() << " and user '" << user->GetName()
+ << "': user period not in timeperiod '" << tp->GetName() << "'";
return false;
}
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;
}
+
}
}
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);
Dump();
}
+void TimePeriod::RemoveSegment(const Dictionary::Ptr& segment)
+{
+ RemoveSegment(segment->Get("begin"), segment->Get("end"));
+}
+
void TimePeriod::PurgeSegments(double end)
{
ASSERT(OwnsLock());
SetSegments(newSegments);
}
+void TimePeriod::Merge(const TimePeriod::Ptr& timeperiod, bool include)
+{
+ Log(LogDebug, "TimePeriod")
+ << "Merge TimePeriod '" << GetName() << "' with '" << timeperiod->GetName() << "' "
+ << "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) {
}
}
}
+
+ bool preferInclude = GetPreferIncludes();
+
+ /* First handle the non preferred timeranges */
+ Array::Ptr timeranges = preferInclude ? GetExcludes() : GetIncludes();
+
+ if (timeranges) {
+ ObjectLock olock(timeranges);
+ BOOST_FOREACH(const String& name, timeranges) {
+ const TimePeriod::Ptr timeperiod = TimePeriod::GetByName(name);
+
+ if (timeperiod)
+ Merge(timeperiod, !preferInclude);
+ }
+ }
+
+ /* Preferred timeranges must be handled at the end */
+ timeranges = preferInclude ? GetIncludes() : GetExcludes();
+
+ if (timeranges) {
+ ObjectLock olock(timeranges);
+ BOOST_FOREACH(const String& name, timeranges) {
+ const TimePeriod::Ptr timeperiod = TimePeriod::GetByName(name);
+
+ if (timeperiod)
+ Merge(timeperiod, preferInclude);
+ }
+ }
}
bool TimePeriod::GetIsInside(void) const
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);
};
[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;