service->AddDowntime(downtime->GetAuthor(), downtime->GetComment(),
downtime->GetStartTime(), downtime->GetEndTime(),
downtime->GetFixed(), downtime->GetTriggeredBy(),
- downtime->GetDuration(), downtime->GetId(), sender->GetName());
+ downtime->GetDuration(), downtime->GetScheduledBy(),
+ downtime->GetId(), sender->GetName());
AsyncRelayMessage(sender, message, true);
} else if (message->Get("method") == "cluster::RemoveDowntime") {
The `/etc/icinga2/conf.d/timeperiods.conf` file is usually used to define
timeperiods including this one.
+### <a id="objecttype-scheduleddowntime"></a> ScheduledDowntime
+
+ScheduledDowntime objects can be used to set up recurring downtimes for services.
+
+> **Best Practice**
+>
+> Rather than creating a `ScheduledDowntime` object for a specific service it is usually easier
+> to just create a `ScheduledDowntime` template and using the `scheduled_downtimes` attribute in the `Service`
+> object to associate these templates with a service.
+
+Example:
+
+ object ScheduledDowntime "some-downtime" {
+ host = "localhost",
+ service = "ping4",
+
+ author = "icingaadmin",
+ comment = "Some comment",
+
+ fixed = false,
+ duration = 30m,
+
+ ranges = {
+ "sunday" = "02:00-03:00"
+ }
+ }
+
+Attributes:
+
+ Name |Description
+ ----------------|----------------
+ host |**Required.** The name of the host this notification belongs to.
+ service |**Required.** The short name of the service this notification belongs to.
+ author |**Required.** The author of the downtime.
+ comment |**Required.** A comment for the downtime.
+ fixed |**Optional.** Whether this is a fixed downtime. Defaults to true.
+ duration |**Optional.** How long the downtime lasts. Only has an effect for flexible (non-fixed) downtimes.
+ ranges |**Required.** A dictionary containing information which days and durations apply to this timeperiod.
### <a id="objecttype-consolelogger"></a> ConsoleLogger
configure_file(icinga/icinga-classic-apache.conf.cmake ${CMAKE_CURRENT_BINARY_DIR}/icinga/icinga-classic-apache.conf)
install_if_not_exists(icinga2/icinga2.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2)
+install_if_not_exists(icinga2/conf.d/downtimes.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d)
install_if_not_exists(icinga2/conf.d/generic-host.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d)
install_if_not_exists(icinga2/conf.d/generic-service.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d)
install_if_not_exists(icinga2/conf.d/generic-user.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d)
--- /dev/null
+/**
+ * The example downtime templates.
+ */
+
+template ScheduledDowntime "backup-downtime" {
+ author = "icingaadmin",
+ comment = "Scheduled downtime for backup",
+
+ ranges = {
+ monday = "02:00-03:00",
+ tuesday = "02:00-03:00",
+ wednesday = "02:00-03:00",
+ thursday = "02:00-03:00",
+ friday = "02:00-03:00",
+ saturday = "02:00-03:00",
+ sunday = "02:00-03:00"
+ }
+}
+
services["load"] = {
templates = [ "generic-service" ],
- check_command = "load"
+ check_command = "load",
+
+ scheduled_downtimes["backup"] = {
+ templates = [ "backup-downtime" ]
+ }
},
services["processes"] = {
if (object) {
ASSERT(!object->IsActive());
+#ifdef _DEBUG
Log(LogDebug, "base", "Restoring object '" + name + "' of type '" + type + "'.");
+#endif /* _DEBUG */
Deserialize(object, update, attributeTypes);
object->OnStateLoaded();
}
return rand();
}
+
+tm Utility::LocalTime(time_t ts)
+{
+#ifdef _MSC_VER
+ tm *result = localtime(&ts);
+
+ if (temp == NULL) {
+ BOOST_THROW_EXCEPTION(posix_error()
+ << boost::errinfo_api_function("localtime")
+ << boost::errinfo_errno(errno));
+ }
+
+ return *result;
+#else /* _MSC_VER */
+ tm result;
+
+ if (localtime_r(&ts, &result) == NULL) {
+ BOOST_THROW_EXCEPTION(posix_error()
+ << boost::errinfo_api_function("localtime_r")
+ << boost::errinfo_errno(errno));
+ }
+
+ return result;
+#endif /* _MSC_VER */
+}
\ No newline at end of file
static int Random(void);
+ static tm LocalTime(time_t ts);
+
private:
Utility(void);
{
ASSERT(!OwnsLock());
+#ifdef _DEBUG
Log(LogDebug, "base", "Commit called for ConfigItem Type=" + GetType() + ", Name=" + GetName());
+#endif /* _DEBUG */
/* Make sure the type is valid. */
DynamicType::Ptr dtype = DynamicType::GetByName(GetType());
if (object->IsActive())
continue;
+#ifdef _DEBUG
Log(LogDebug, "config", "Activating object '" + object->GetName() + "' of type '" + object->GetType()->GetName() + "'");
+#endif /* _DEBUG */
object->Start();
ASSERT(object->IsActive());
)
include_directories(${Boost_INCLUDE_DIRS})
-target_link_libraries(db_ido ${Boost_LIBRARIES} base config icinga methods)
+target_link_libraries(db_ido ${Boost_LIBRARIES} base config icinga)
set_target_properties (
db_ido PROPERTIES
#include "db_ido/dbtype.h"
#include "db_ido/dbvalue.h"
#include "icinga/timeperiod.h"
-#include "methods/legacytimeperiod.h"
+#include "icinga/legacytimeperiod.h"
#include "base/utility.h"
#include "base/exception.h"
#include "base/objectlock.h"
if (wday == -1)
continue;
- tm reference;
-
-#ifdef _MSC_VER
- tm *temp = localtime(&refts);
-
- if (temp == NULL) {
- BOOST_THROW_EXCEPTION(posix_error()
- << boost::errinfo_api_function("localtime")
- << boost::errinfo_errno(errno));
- }
-
- reference = *temp;
-#else /* _MSC_VER */
- if (localtime_r(&refts, &reference) == NULL) {
- BOOST_THROW_EXCEPTION(posix_error()
- << boost::errinfo_api_function("localtime_r")
- << boost::errinfo_errno(errno));
- }
-#endif /* _MSC_VER */
+ tm reference = Utility::LocalTime(refts);
Array::Ptr segments = make_shared<Array>();
LegacyTimePeriod::ProcessTimeRanges(kv.second, &reference, segments);
mkclass_target(notificationcommand.ti notificationcommand.th)
mkclass_target(notification.ti notification.th)
mkclass_target(perfdatavalue.ti perfdatavalue.th)
+mkclass_target(scheduleddowntime.ti scheduleddowntime.th)
mkclass_target(servicegroup.ti servicegroup.th)
mkclass_target(service.ti service.th)
mkclass_target(timeperiod.ti timeperiod.th)
cib.cpp command.cpp command.th comment.cpp comment.th compatutility.cpp
domain.cpp domain.th downtime.cpp downtime.th eventcommand.cpp eventcommand.th
externalcommandprocessor.cpp host.cpp host.th hostgroup.cpp hostgroup.th
- icingaapplication.cpp icingaapplication.th macroprocessor.cpp macroresolver.cpp
- notificationcommand.cpp notificationcommand.th notification.cpp notification.th
- perfdatavalue.cpp perfdatavalue.th pluginutility.cpp service-check.cpp
+ icingaapplication.cpp icingaapplication.th legacytimeperiod.cpp
+ macroprocessor.cpp macroresolver.cpp notificationcommand.cpp notificationcommand.th
+ notification.cpp notification.th perfdatavalue.cpp perfdatavalue.th
+ pluginutility.cpp scheduleddowntime.cpp scheduleddowntime.th service-check.cpp
service-comment.cpp service.cpp service-downtime.cpp service-event.cpp
service-flapping.cpp service.th servicegroup.cpp servicegroup.th
service-notification.cpp timeperiod.cpp timeperiod.th user.cpp user.th
[state] bool fixed;
[state] double duration;
[state] String triggered_by;
+ [state] String scheduled_by;
[state] Dictionary::Ptr triggers {
default {{{ return make_shared<Dictionary>(); }}}
};
}
},
+ %attribute dictionary "scheduled_downtimes" {
+ %attribute dictionary "*" {
+ %attribute array "templates" {
+ %attribute name(ScheduledDowntime) "*"
+ },
+
+ %attribute any "*"
+ }
+ },
+
%attribute any "templates"
}
type Notification {
%require "host",
%attribute name(Host) "host",
+
+ %require "service",
%attribute string "service",
%attribute dictionary "macros" {
%attribute number "*"
}
}
+
+type ScheduledDowntime {
+ %require "host",
+ %attribute name(Host) "host",
+ %require "service",
+ %attribute string "service",
+
+ %require "author",
+ %attribute string "author",
+
+ %require "comment",
+ %attribute string "comment",
+
+ %attribute number "duration",
+ %attribute number "fixed",
+
+ %require "ranges",
+ %attribute dictionary "ranges" {
+ %attribute string "*"
+ },
+
+ %attribute any "templates"
+}
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
-#include "methods/legacytimeperiod.h"
+#include "icinga/legacytimeperiod.h"
#include "base/scriptfunction.h"
#include "base/convert.h"
#include "base/exception.h"
#include "base/objectlock.h"
#include "base/logger_fwd.h"
#include "base/debug.h"
+#include "base/utility.h"
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/foreach.hpp>
if (timespec.GetLength() == 10 && timespec[4] == '-' && timespec[7] == '-') {
int year = Convert::ToLong(timespec.SubStr(0, 4));
int month = Convert::ToLong(timespec.SubStr(5, 2));
- int day = Convert::ToLong(timespec.SubStr(7, 2));
+ int day = Convert::ToLong(timespec.SubStr(8, 2));
if (begin) {
begin->tm_year = year - 1900;
begin->tm_mon = month;
- begin->tm_mday = day;
+ begin->tm_mday = day + 1;
begin->tm_hour = 0;
begin->tm_min = 0;
begin->tm_sec = 0;
if (end) {
end->tm_year = year - 1900;
end->tm_mon = month;
- end->tm_mday = day;
+ end->tm_mday = day + 1;
end->tm_hour = 24;
end->tm_min = 0;
end->tm_sec = 0;
}
}
+Dictionary::Ptr LegacyTimePeriod::FindNextSegment(const String& daydef, const String& timeranges, tm *reference)
+{
+ tm begin, end, iter, ref;
+ time_t tsend, tsiter, tsref;
+ int stride;
+
+ for (int pass = 1; pass <= 2; pass++) {
+ if (pass == 1) {
+ ref = *reference;
+ } else {
+ ref = end;
+ ref.tm_mday++;
+ }
+
+ tsref = mktime(&ref);
+
+ ParseTimeRange(daydef, &begin, &end, &stride, &ref);
+
+ iter = begin;
+
+ tsend = mktime(&end);
+ tsiter = mktime(&iter);
+
+ do {
+ if (IsInTimeRange(&begin, &end, stride, &iter)) {
+ Array::Ptr segments = make_shared<Array>();
+ ProcessTimeRanges(timeranges, &iter, segments);
+
+ Dictionary::Ptr bestSegment;
+ double bestBegin;
+
+ BOOST_FOREACH(const Dictionary::Ptr& segment, segments) {
+ double begin = segment->Get("begin");
+
+ if (begin < tsref)
+ continue;
+
+ if (!bestSegment || begin < bestBegin) {
+ bestSegment = segment;
+ bestBegin = begin;
+ }
+ }
+
+ 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 Dictionary::Ptr();
+}
+
Array::Ptr LegacyTimePeriod::ScriptFunc(const TimePeriod::Ptr& tp, double begin, double end)
{
Array::Ptr segments = make_shared<Array>();
if (ranges) {
for (int i = 0; i <= (end - begin) / (24 * 60 * 60); i++) {
time_t refts = begin + i * 24 * 60 * 60;
- tm reference;
+ tm reference = Utility::LocalTime(refts);
+#ifdef _DEBUG
Log(LogDebug, "icinga", "Checking reference time " + Convert::ToString(static_cast<long>(refts)));
-
-#ifdef _MSC_VER
- tm *temp = localtime(&refts);
-
- if (temp == NULL) {
- BOOST_THROW_EXCEPTION(posix_error()
- << boost::errinfo_api_function("localtime")
- << boost::errinfo_errno(errno));
- }
-
- reference = *temp;
-#else /* _MSC_VER */
- if (localtime_r(&refts, &reference) == NULL) {
- BOOST_THROW_EXCEPTION(posix_error()
- << boost::errinfo_api_function("localtime_r")
- << boost::errinfo_errno(errno));
- }
-#endif /* _MSC_VER */
+#endif /* _DEBUG */
ObjectLock olock(ranges);
BOOST_FOREACH(const Dictionary::Pair& kv, ranges) {
if (!IsInDayDefinition(kv.first, &reference)) {
+#ifdef _DEBUG
Log(LogDebug, "icinga", "Not in day definition '" + kv.first + "'.");
+#endif /* _DEBUG */
continue;
}
+#ifdef _DEBUG
Log(LogDebug, "icinga", "In day definition '" + kv.first + "'.");
+#endif /* _DEBUG */
ProcessTimeRanges(kv.second, &reference, segments);
}
#ifndef LEGACYTIMEPERIOD_H
#define LEGACYTIMEPERIOD_H
-#include "methods/i2-methods.h"
+#include "icinga/i2-icinga.h"
#include "icinga/service.h"
#include "base/dictionary.h"
*
* @ingroup icinga
*/
-class I2_METHODS_API LegacyTimePeriod
+class I2_ICINGA_API LegacyTimePeriod
{
public:
static Array::Ptr ScriptFunc(const TimePeriod::Ptr& tp, double start, double end);
static void ProcessTimeRangeRaw(const String& timerange, tm *reference, tm *begin, tm *end);
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);
private:
LegacyTimePeriod(void);
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "icinga/scheduleddowntime.h"
+#include "icinga/legacytimeperiod.h"
+#include "base/timer.h"
+#include "base/dynamictype.h"
+#include "base/initialize.h"
+#include "base/utility.h"
+#include "base/objectlock.h"
+#include "base/convert.h"
+#include "base/logger_fwd.h"
+#include "base/exception.h"
+#include <boost/foreach.hpp>
+
+using namespace icinga;
+
+REGISTER_TYPE(ScheduledDowntime);
+
+INITIALIZE_ONCE(&ScheduledDowntime::StaticInitialize);
+
+static Timer::Ptr l_Timer;
+
+void ScheduledDowntime::StaticInitialize(void)
+{
+ l_Timer = make_shared<Timer>();
+ l_Timer->SetInterval(60);
+ l_Timer->OnTimerExpired.connect(boost::bind(&ScheduledDowntime::TimerProc));
+ l_Timer->Start();
+}
+
+void ScheduledDowntime::Start(void)
+{
+ DynamicObject::Start();
+
+ CreateNextDowntime();
+}
+
+void ScheduledDowntime::TimerProc(void)
+{
+ BOOST_FOREACH(const ScheduledDowntime::Ptr& sd, DynamicType::GetObjects<ScheduledDowntime>()) {
+ sd->CreateNextDowntime();
+ }
+}
+
+Service::Ptr ScheduledDowntime::GetService(void) const
+{
+ Host::Ptr host = Host::GetByName(GetHostRaw());
+
+ if (GetServiceRaw().IsEmpty())
+ return host->GetCheckService();
+ else
+ return host->GetServiceByShortName(GetServiceRaw());
+}
+
+std::pair<double, double> ScheduledDowntime::FindNextSegment(void)
+{
+ time_t refts = Utility::GetTime();
+ tm reference = Utility::LocalTime(refts);
+
+ Log(LogDebug, "icinga", "Finding next scheduled downtime segment for time " + Convert::ToString(static_cast<long>(refts)));
+
+ Dictionary::Ptr ranges = GetRanges();
+
+ Array::Ptr segments = make_shared<Array>();
+
+ Dictionary::Ptr bestSegment;
+ double bestBegin;
+ double now = Utility::GetTime();
+
+ ObjectLock olock(ranges);
+ BOOST_FOREACH(const Dictionary::Pair& kv, ranges) {
+ tm rangeref;
+
+ Dictionary::Ptr segment = LegacyTimePeriod::FindNextSegment(kv.first, kv.second, &reference);
+
+ if (!segment)
+ continue;
+
+ double begin = segment->Get("begin");
+
+ if (begin < now)
+ continue;
+
+ if (!bestSegment || begin < bestBegin) {
+ bestSegment = segment;
+ bestBegin = begin;
+ }
+ }
+
+ if (bestSegment)
+ return std::make_pair(bestSegment->Get("begin"), bestSegment->Get("end"));
+ else
+ return std::make_pair(0, 0);
+}
+
+void ScheduledDowntime::CreateNextDowntime(void)
+{
+ Dictionary::Ptr downtimes = GetService()->GetDowntimes();
+
+ {
+ ObjectLock dlock(downtimes);
+ BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
+ Downtime::Ptr downtime = kv.second;
+
+ if (downtime->GetScheduledBy() != GetName() ||
+ downtime->GetStartTime() < Utility::GetTime())
+ continue;
+
+ /* We've found a downtime that is owned by us and that hasn't started yet - we're done. */
+ return;
+ }
+ }
+
+ std::pair<double, double> segment = FindNextSegment();
+
+ if (segment.first == 0 && segment.second == 0) {
+ tm reference = Utility::LocalTime(Utility::GetTime());
+ reference.tm_mday++;
+ reference.tm_hour = 0;
+ reference.tm_min = 0;
+ reference.tm_sec = 0;
+
+ return;
+ }
+
+ GetService()->AddDowntime(GetAuthor(), GetComment(),
+ segment.first, segment.second,
+ GetFixed(), String(), GetDuration(), GetName());
+}
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#ifndef SCHEDULEDDOWNTIME_H
+#define SCHEDULEDDOWNTIME_H
+
+#include "icinga/i2-icinga.h"
+#include "icinga/scheduleddowntime.th"
+#include "icinga/service.h"
+#include <utility>
+
+namespace icinga
+{
+
+/**
+ * An Icinga scheduled downtime specification.
+ *
+ * @ingroup icinga
+ */
+class I2_ICINGA_API ScheduledDowntime : public ObjectImpl<ScheduledDowntime>
+{
+public:
+ DECLARE_PTR_TYPEDEFS(ScheduledDowntime);
+ DECLARE_TYPENAME(ScheduledDowntime);
+
+ static void StaticInitialize(void);
+
+ Service::Ptr GetService(void) const;
+
+protected:
+ virtual void Start(void);
+
+private:
+ static void TimerProc(void);
+
+ std::pair<double, double> FindNextSegment(void);
+ void CreateNextDowntime(void);
+};
+
+}
+
+#endif /* SCHEDULEDDOWNTIME_H */
--- /dev/null
+#include "base/dynamicobject.h"
+
+namespace icinga
+{
+
+class ScheduledDowntime : DynamicObject
+{
+ [config, protected] String host (HostRaw);
+ [config, protected] String service (ServiceRaw);
+
+ [config] String author;
+ [config] String comment;
+
+ [config] double duration;
+ [config] bool fixed {
+ default {{{ return true; }}}
+ };
+
+ [config] Dictionary::Ptr ranges;
+};
+
+}
void Service::AddCommentsToCache(void)
{
+#ifdef _DEBUG
Log(LogDebug, "icinga", "Updating Service comments cache.");
+#endif /* _DEBUG */
Dictionary::Ptr comments = GetComments();
******************************************************************************/
#include "icinga/service.h"
+#include "config/configitembuilder.h"
#include "base/dynamictype.h"
#include "base/objectlock.h"
#include "base/logger_fwd.h"
String Service::AddDowntime(const String& author, const String& comment,
double startTime, double endTime, bool fixed,
- const String& triggeredBy, double duration, const String& id, const String& authority)
+ const String& triggeredBy, double duration, const String& scheduledBy,
+ const String& id, const String& authority)
{
String uid;
downtime->SetFixed(fixed);
downtime->SetDuration(duration);
downtime->SetTriggeredBy(triggeredBy);
+ downtime->SetScheduledBy(scheduledBy);
int legacy_id;
Downtime::Ptr otherDowntime = otherDowntimes->Get(triggeredBy);
Dictionary::Ptr triggers = otherDowntime->GetTriggers();
- {
- ObjectLock olock(otherOwner);
- triggers->Set(triggeredBy, triggeredBy);
- }
+ triggers->Set(triggeredBy, triggeredBy);
}
GetDowntimes()->Set(uid, downtime);
l_DowntimesCache[uid] = GetSelf();
}
- Log(LogWarning, "icinga", "added downtime with ID '" + Convert::ToString(downtime->GetLegacyId()) + "'.");
+ Log(LogDebug, "icinga", "Added downtime with ID '" + Convert::ToString(downtime->GetLegacyId()) +
+ "' between '" + Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", startTime) + "' and '" + Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", endTime) + "'.");
OnDowntimeAdded(GetSelf(), downtime, authority);
downtime->SetWasCancelled(cancelled);
- Log(LogWarning, "icinga", "removed downtime with ID '" + Convert::ToString(downtime->GetLegacyId()) + "' from service '" + owner->GetName() + "'.");
+ Log(LogDebug, "icinga", "Removed downtime with ID '" + Convert::ToString(downtime->GetLegacyId()) + "' from service '" + owner->GetName() + "'.");
OnDowntimeRemoved(owner, downtime, authority);
}
void Service::AddDowntimesToCache(void)
{
+#ifdef _DEBUG
Log(LogDebug, "icinga", "Updating Service downtimes cache.");
+#endif /* _DEBUG */
Dictionary::Ptr downtimes = GetDowntimes();
return downtime_depth;
}
+
+void Service::UpdateSlaveScheduledDowntimes(void)
+{
+ ConfigItem::Ptr item = ConfigItem::GetObject("Service", GetName());
+
+ /* Don't create slave scheduled downtimes unless we own this object */
+ if (!item)
+ return;
+
+ /* Service scheduled downtime descs */
+ Dictionary::Ptr descs = GetScheduledDowntimeDescriptions();
+
+ if (!descs)
+ return;
+
+ ObjectLock olock(descs);
+
+ BOOST_FOREACH(const Dictionary::Pair& kv, descs) {
+ std::ostringstream namebuf;
+ namebuf << GetName() << ":" << kv.first;
+ String name = namebuf.str();
+
+ std::vector<String> path;
+ path.push_back("scheduled_downtimes");
+ path.push_back(kv.first);
+
+ DebugInfo di;
+ item->GetLinkedExpressionList()->FindDebugInfoPath(path, di);
+
+ if (di.Path.IsEmpty())
+ di = item->GetDebugInfo();
+
+ ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
+ builder->SetType("ScheduledDowntime");
+ builder->SetName(name);
+ builder->AddExpression("host", OperatorSet, GetHost()->GetName());
+ builder->AddExpression("service", OperatorSet, GetShortName());
+
+ Dictionary::Ptr scheduledDowntime = kv.second;
+
+ Array::Ptr templates = scheduledDowntime->Get("templates");
+
+ if (templates) {
+ ObjectLock tlock(templates);
+
+ BOOST_FOREACH(const Value& tmpl, templates) {
+ builder->AddParent(tmpl);
+ }
+ }
+
+ /* Clone attributes from the scheduled downtime expression list. */
+ ExpressionList::Ptr sd_exprl = make_shared<ExpressionList>();
+ item->GetLinkedExpressionList()->ExtractPath(path, sd_exprl);
+
+ builder->AddExpressionList(sd_exprl);
+
+ ConfigItem::Ptr scheduledDowntimeItem = builder->Compile();
+ scheduledDowntimeItem->Register();
+ DynamicObject::Ptr dobj = scheduledDowntimeItem->Commit();
+ dobj->OnConfigLoaded();
+ }
+}
{
VERIFY(GetHost());
- AddDowntimesToCache();
- AddCommentsToCache();
-
StartDowntimesExpiredTimer();
double now = Utility::GetTime();
m_Host->AddService(GetSelf());
UpdateSlaveNotifications();
+ UpdateSlaveScheduledDowntimes();
SetSchedulingOffset(Utility::Random());
}
+void Service::OnStateLoaded(void)
+{
+ AddDowntimesToCache();
+ AddCommentsToCache();
+
+ std::vector<String> ids;
+ Dictionary::Ptr downtimes = GetDowntimes();
+
+ {
+ ObjectLock dlock(downtimes);
+ BOOST_FOREACH(const Dictionary::Pair& kv, downtimes) {
+ Downtime::Ptr downtime = kv.second;
+
+ if (downtime->GetScheduledBy().IsEmpty())
+ continue;
+
+ ids.push_back(kv.first);
+ }
+ }
+
+ BOOST_FOREACH(const String& id, ids) {
+ RemoveDowntime(id, true);
+ }
+}
+
Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName)
{
if (!hostName.IsEmpty()) {
String AddDowntime(const String& author, const String& comment,
double startTime, double endTime, bool fixed,
const String& triggeredBy, double duration,
- const String& id = String(), const String& authority = String());
+ const String& scheduledBy = String(), const String& id = String(),
+ const String& authority = String());
static void RemoveDowntime(const String& id, bool cancelled, const String& = String());
bool IsInDowntime(void) const;
bool IsAcknowledged(void);
+ void UpdateSlaveScheduledDowntimes(void);
+
/* Comments */
static int GetNextCommentID(void);
virtual void Start(void);
virtual void OnConfigLoaded(void);
+ virtual void OnStateLoaded(void);
private:
Host::Ptr m_Host;
default {{{ return 30; }}}
};
[config] Dictionary::Ptr notifications (NotificationDescriptions);
+ [config] Dictionary::Ptr scheduled_downtimes (ScheduledDowntimeDescriptions);
[config] bool enable_active_checks (EnableActiveChecksRaw) {
default {{{ return true; }}}
};
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
add_library(methods SHARED
- icingachecktask.cpp legacytimeperiod.cpp nullchecktask.cpp
- nulleventtask.cpp pluginchecktask.cpp plugineventtask.cpp
- pluginnotificationtask.cpp randomchecktask.cpp timeperiodtask.cpp
+ icingachecktask.cpp nullchecktask.cpp nulleventtask.cpp
+ pluginchecktask.cpp plugineventtask.cpp pluginnotificationtask.cpp
+ randomchecktask.cpp timeperiodtask.cpp
)
target_link_libraries(methods ${Boost_LIBRARIES} base config icinga)