diff --git a/doc/09-object-types.md b/doc/09-object-types.md
index d04f78156..4945b18ec 100644
--- a/doc/09-object-types.md
+++ b/doc/09-object-types.md
@@ -1385,6 +1385,7 @@ Configuration Attributes:
fixed | Boolean | **Optional.** Whether this is a fixed downtime. Defaults to `true`.
duration | Duration | **Optional.** How long the downtime lasts. Only has an effect for flexible (non-fixed) downtimes.
ranges | Dictionary | **Required.** A dictionary containing information which days and durations apply to this timeperiod.
+ child\_options | String | **Optional.** Schedule child downtimes. `DowntimeNoChildren` does not do anything, `DowntimeTriggeredChildren` schedules child downtimes triggered by this downtime, `DowntimeNonTriggeredChildren` schedules non-triggered downtimes. Defaults to `DowntimeNoChildren`.
ScheduledDowntime objects have composite names, i.e. their names are based
on the `host_name` and `service_name` attributes and the
diff --git a/doc/12-icinga2-api.md b/doc/12-icinga2-api.md
index 722b88a2b..c26ef937d 100644
--- a/doc/12-icinga2-api.md
+++ b/doc/12-icinga2-api.md
@@ -1117,7 +1117,7 @@ Send a `POST` request to the URL endpoint `/v1/actions/schedule-downtime`.
fixed | Boolean | **Optional.** Defaults to `true`. If true, the downtime is `fixed` otherwise `flexible`. See [downtimes](08-advanced-topics.md#downtimes) for more information.
duration | Number | **Required for flexible downtimes.** Duration of the downtime in seconds if `fixed` is set to false.
trigger\_name | String | **Optional.** Sets the trigger for a triggered downtime. See [downtimes](08-advanced-topics.md#downtimes) for more information on triggered downtimes.
- child\_options | Number | **Optional.** Schedule child downtimes. `0` does not do anything, `1` schedules child downtimes triggered by this downtime, `2` schedules non-triggered downtimes. Defaults to `0`.
+ child\_options| String | **Optional.** Schedule child downtimes. `DowntimeNoChildren` does not do anything, `DowntimeTriggeredChildren` schedules child downtimes triggered by this downtime, `DowntimeNonTriggeredChildren` schedules non-triggered downtimes. Defaults to `DowntimeNoChildren`.
In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
diff --git a/doc/16-upgrading-icinga-2.md b/doc/16-upgrading-icinga-2.md
index ab5bd649b..f483ff0e3 100644
--- a/doc/16-upgrading-icinga-2.md
+++ b/doc/16-upgrading-icinga-2.md
@@ -49,6 +49,11 @@ New [Icinga constants](17-language-reference.md#icinga-constants) have been adde
The keywords `namespace` and `using` are now [reserved](17-language-reference.md#reserved-keywords) for the namespace functionality provided
with v2.10. Read more about how it works [here](17-language-reference.md#namespaces).
+### API: schedule-downtime Action
+
+The attribute `child_options` was previously accepting 0,1,2 for specific child downtime settings.
+This behaviour stays intact, but the new proposed way are specific constants as values (`DowntimeNoChildren`, `DowntimeTriggeredChildren`, `DowntimeNonTriggeredChildren`).
+
## Upgrading to v2.9
### Deprecation and Removal Notes
diff --git a/lib/icinga/apiactions.cpp b/lib/icinga/apiactions.cpp
index 2a373eb1c..0c28fe944 100644
--- a/lib/icinga/apiactions.cpp
+++ b/lib/icinga/apiactions.cpp
@@ -366,30 +366,30 @@ Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object,
});
/* Schedule downtime for all child objects. */
- int childOptions = 0;
+ DowntimeChildOptions childOptions = DowntimeNoChildren;
if (params->Contains("child_options"))
- childOptions = HttpUtility::GetLastParameter(params, "child_options");
+ childOptions = Downtime::ChildOptionsFromValue(HttpUtility::GetLastParameter(params, "child_options"));
- if (childOptions > 0) {
- /* '1' schedules child downtimes triggered by the parent downtime.
- * '2' schedules non-triggered downtimes for all children.
+ if (childOptions != DowntimeNoChildren) {
+ /* 'DowntimeTriggeredChildren' schedules child downtimes triggered by the parent downtime.
+ * 'DowntimeNonTriggeredChildren' schedules non-triggered downtimes for all children.
*/
- if (childOptions == 1)
+ if (childOptions == DowntimeTriggeredChildren)
triggerName = downtimeName;
- Log(LogCritical, "ApiActions")
+ Log(LogNotice, "ApiActions")
<< "Processing child options " << childOptions << " for downtime " << downtimeName;
ArrayData childDowntimes;
for (const Checkable::Ptr& child : checkable->GetAllChildren()) {
- Log(LogCritical, "ApiActions")
+ Log(LogNotice, "ApiActions")
<< "Scheduling downtime for child object " << child->GetName();
String childDowntimeName = Downtime::AddDowntime(child, author, comment, startTime, endTime,
fixed, triggerName, duration);
- Log(LogCritical, "ApiActions")
+ Log(LogNotice, "ApiActions")
<< "Add child downtime '" << childDowntimeName << "'.";
Downtime::Ptr childDowntime = Downtime::GetByName(childDowntimeName);
diff --git a/lib/icinga/downtime.cpp b/lib/icinga/downtime.cpp
index 8c3584a4b..6e5bc0210 100644
--- a/lib/icinga/downtime.cpp
+++ b/lib/icinga/downtime.cpp
@@ -42,6 +42,15 @@ boost::signals2::signal Downtime::OnDowntimeTrigger
REGISTER_TYPE(Downtime);
+INITIALIZE_ONCE(&Downtime::StaticInitialize);
+
+void Downtime::StaticInitialize()
+{
+ ScriptGlobal::Set("DowntimeNoChildren", "DowntimeNoChildren");
+ ScriptGlobal::Set("DowntimeTriggeredChildren", "DowntimeTriggeredChildren");
+ ScriptGlobal::Set("DowntimeNonTriggeredChildren", "DowntimeNonTriggeredChildren");
+}
+
String DowntimeNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
{
Downtime::Ptr downtime = dynamic_pointer_cast(context);
@@ -420,3 +429,20 @@ void Downtime::ValidateEndTime(const Lazy& lvalue, const ValidationUt
if (lvalue() <= 0)
BOOST_THROW_EXCEPTION(ValidationError(this, { "end_time" }, "End time must be greater than 0."));
}
+
+DowntimeChildOptions Downtime::ChildOptionsFromValue(const Value& options)
+{
+ if (options == "DowntimeNoChildren")
+ return DowntimeNoChildren;
+ else if (options == "DowntimeTriggeredChildren")
+ return DowntimeTriggeredChildren;
+ else if (options == "DowntimeNonTriggeredChildren")
+ return DowntimeNonTriggeredChildren;
+ else if (options.IsNumber()) {
+ int number = options;
+ if (number >= 0 && number <= 2)
+ return static_cast(number);
+ }
+
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid child option specified"));
+}
diff --git a/lib/icinga/downtime.hpp b/lib/icinga/downtime.hpp
index 6d4ba0a21..c4646eabb 100644
--- a/lib/icinga/downtime.hpp
+++ b/lib/icinga/downtime.hpp
@@ -28,6 +28,13 @@
namespace icinga
{
+enum DowntimeChildOptions
+{
+ DowntimeNoChildren,
+ DowntimeTriggeredChildren,
+ DowntimeNonTriggeredChildren
+};
+
/**
* A downtime.
*
@@ -51,6 +58,8 @@ public:
bool IsExpired() const;
bool HasValidConfigOwner() const;
+ static void StaticInitialize();
+
static int GetNextDowntimeID();
static String AddDowntime(const intrusive_ptr& checkable, const String& author,
@@ -65,6 +74,8 @@ public:
static String GetDowntimeIDFromLegacyID(int id);
+ static DowntimeChildOptions ChildOptionsFromValue(const Value& options);
+
protected:
void OnAllConfigLoaded() override;
void Start(bool runtimeCreated) override;
diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp
index 6a715fc40..80d7617ba 100644
--- a/lib/icinga/scheduleddowntime.cpp
+++ b/lib/icinga/scheduleddowntime.cpp
@@ -191,9 +191,35 @@ void ScheduledDowntime::CreateNextDowntime()
return;
}
- Downtime::AddDowntime(GetCheckable(), GetAuthor(), GetComment(),
+ String downtimeName = Downtime::AddDowntime(GetCheckable(), GetAuthor(), GetComment(),
segment.first, segment.second,
GetFixed(), String(), GetDuration(), GetName(), GetName());
+
+ Downtime::Ptr downtime = Downtime::GetByName(downtimeName);
+
+ int childOptions = Downtime::ChildOptionsFromValue(GetChildOptions());
+ if (childOptions > 0) {
+ /* 'DowntimeTriggeredChildren' schedules child downtimes triggered by the parent downtime.
+ * 'DowntimeNonTriggeredChildren' schedules non-triggered downtimes for all children.
+ */
+ String triggerName;
+ if (childOptions == 1)
+ triggerName = downtimeName;
+
+ Log(LogNotice, "ScheduledDowntime")
+ << "Processing child options " << childOptions << " for downtime " << downtimeName;
+
+ for (const Checkable::Ptr& child : GetCheckable()->GetAllChildren()) {
+ Log(LogNotice, "ScheduledDowntime")
+ << "Scheduling downtime for child object " << child->GetName();
+
+ String childDowntimeName = Downtime::AddDowntime(child, GetAuthor(), GetComment(),
+ segment.first, segment.second, GetFixed(), triggerName, GetDuration(), GetName(), GetName());
+
+ Log(LogNotice, "ScheduledDowntime")
+ << "Add child downtime '" << childDowntimeName << "'.";
+ }
+ }
}
void ScheduledDowntime::ValidateRanges(const Lazy& lvalue, const ValidationUtils& utils)
@@ -226,3 +252,13 @@ void ScheduledDowntime::ValidateRanges(const Lazy& lvalue, cons
}
}
+void ScheduledDowntime::ValidateChildOptions(const Lazy& lvalue, const ValidationUtils& utils)
+{
+ ObjectImpl::ValidateChildOptions(lvalue, utils);
+
+ try {
+ Downtime::ChildOptionsFromValue(lvalue());
+ } catch (const std::exception&) {
+ BOOST_THROW_EXCEPTION(ValidationError(this, { "child_options" }, "Invalid child_options specified"));
+ }
+}
\ No newline at end of file
diff --git a/lib/icinga/scheduleddowntime.hpp b/lib/icinga/scheduleddowntime.hpp
index 86138fa04..7fbcd1e12 100644
--- a/lib/icinga/scheduleddowntime.hpp
+++ b/lib/icinga/scheduleddowntime.hpp
@@ -49,6 +49,7 @@ public:
static void EvaluateApplyRules(const intrusive_ptr& service);
void ValidateRanges(const Lazy& lvalue, const ValidationUtils& utils) override;
+ void ValidateChildOptions(const Lazy& lvalue, const ValidationUtils& utils) override;
protected:
void OnAllConfigLoaded() override;
diff --git a/lib/icinga/scheduleddowntime.ti b/lib/icinga/scheduleddowntime.ti
index e119eaa11..e2d2aca30 100644
--- a/lib/icinga/scheduleddowntime.ti
+++ b/lib/icinga/scheduleddowntime.ti
@@ -77,6 +77,10 @@ class ScheduledDowntime : CustomVarObject < ScheduledDowntimeNameComposer
default {{{ return true; }}}
};
+ [config] Value child_options {
+ default {{{ return "DowntimeNoChildren"; }}}
+ };
+
[config, required] Dictionary::Ptr ranges;
};