diff --git a/doc/12-icinga2-api.md b/doc/12-icinga2-api.md
index 959f8e6d9..f05b94ece 100644
--- a/doc/12-icinga2-api.md
+++ b/doc/12-icinga2-api.md
@@ -1381,6 +1381,7 @@ Send a `POST` request to the URL endpoint `/v1/actions/schedule-downtime`.
end\_time | Timestamp | **Required.** Timestamp marking the end of the 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.
+ all\_services | Boolean | **Optional for host downtimes.** Sets downtime for [all services](12-icinga2-api.md#icinga2-api-actions-schedule-downtime-host-all-services) for the matched host objects. If `child_options` are set, all child hosts and their services will schedule a downtime too. Defaults 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| 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`.
@@ -1417,6 +1418,17 @@ like this:
"filter": "host.name==\"icinga2-satellite1.localdomain\" && service.name==\"ping4\""
```
+#### Schedule Host Downtime(s) with all Services
+
+Schedule a downtime for one (or multiple) hosts and all of their services.
+Note the `all_services` attribute.
+
+```
+$ curl -k -s -u root:icinga -H 'Accept: application/json' \
+ -X POST 'https://localhost:5665/v1/actions/schedule-downtime' \
+ -d "$(jo -p pretty=true type=Host filter="match(\"*satellite*\", host.name)" all_services=true author=icingaadmin comment="Cluster upgrade maintenance" fixed=true start_time=$(date +%s -d "+0 hour") end_time=$(date +%s -d "+1 hour"))"
+```
+
### remove-downtime
Remove the downtime using its `name` attribute , returns `OK` if the
diff --git a/doc/16-upgrading-icinga-2.md b/doc/16-upgrading-icinga-2.md
index 4cd2c0d32..a0b016e3d 100644
--- a/doc/16-upgrading-icinga-2.md
+++ b/doc/16-upgrading-icinga-2.md
@@ -172,6 +172,11 @@ constant in [constants.conf](04-configuring-icinga-2.md#constants-conf) instead.
### REST API
+#### Actions
+
+The [schedule-downtime](12-icinga2-api.md#icinga2-api-actions-schedule-downtime-host-all-services)
+action supports the `all_services` parameter for Host types. Defaults to false.
+
#### Config Packages
Deployed configuration packages require an active stage, with many previous
diff --git a/lib/icinga/apiactions.cpp b/lib/icinga/apiactions.cpp
index a9939b9e3..757b37eca 100644
--- a/lib/icinga/apiactions.cpp
+++ b/lib/icinga/apiactions.cpp
@@ -338,6 +338,10 @@ Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object,
double startTime = HttpUtility::GetLastParameter(params, "start_time");
double endTime = HttpUtility::GetLastParameter(params, "end_time");
+ Host::Ptr host;
+ Service::Ptr service;
+ tie(host, service) = GetHostService(checkable);
+
DowntimeChildOptions childOptions = DowntimeNoChildren;
if (params->Contains("child_options")) {
try {
@@ -357,6 +361,33 @@ Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object,
{ "legacy_id", downtime->GetLegacyId() }
});
+ /* Schedule downtime for all services for the host type. */
+ bool allServices = false;
+
+ if (params->Contains("all_services"))
+ allServices = HttpUtility::GetLastParameter(params, "all_services");
+
+ if (allServices && !service) {
+ ArrayData serviceDowntimes;
+
+ for (const Service::Ptr& hostService : host->GetServices()) {
+ Log(LogNotice, "ApiActions")
+ << "Creating downtime for service " << hostService->GetName() << " on host " << host->GetName();
+
+ String serviceDowntimeName = Downtime::AddDowntime(hostService, author, comment, startTime, endTime,
+ fixed, triggerName, duration);
+
+ Downtime::Ptr serviceDowntime = Downtime::GetByName(serviceDowntimeName);
+
+ serviceDowntimes.push_back(new Dictionary({
+ { "name", serviceDowntimeName },
+ { "legacy_id", serviceDowntime->GetLegacyId() }
+ }));
+ }
+
+ additional->Set("service_downtimes", new Array(std::move(serviceDowntimes)));
+ }
+
/* Schedule downtime for all child objects. */
if (childOptions != DowntimeNoChildren) {
/* 'DowntimeTriggeredChildren' schedules child downtimes triggered by the parent downtime.
@@ -382,10 +413,38 @@ Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object,
Downtime::Ptr childDowntime = Downtime::GetByName(childDowntimeName);
- childDowntimes.push_back(new Dictionary({
+ Dictionary::Ptr childAdditional = new Dictionary({
{ "name", childDowntimeName },
{ "legacy_id", childDowntime->GetLegacyId() }
- }));
+ });
+
+ /* For a host, also schedule all service downtimes if requested. */
+ Host::Ptr childHost;
+ Service::Ptr childService;
+ tie(childHost, childService) = GetHostService(child);
+
+ if (allServices && !childService) {
+ ArrayData childServiceDowntimes;
+
+ for (const Service::Ptr& hostService : host->GetServices()) {
+ Log(LogNotice, "ApiActions")
+ << "Creating downtime for service " << hostService->GetName() << " on child host " << host->GetName();
+
+ String serviceDowntimeName = Downtime::AddDowntime(hostService, author, comment, startTime, endTime,
+ fixed, triggerName, duration);
+
+ Downtime::Ptr serviceDowntime = Downtime::GetByName(serviceDowntimeName);
+
+ childServiceDowntimes.push_back(new Dictionary({
+ { "name", serviceDowntimeName },
+ { "legacy_id", serviceDowntime->GetLegacyId() }
+ }));
+ }
+
+ childAdditional->Set("service_downtimes", new Array(std::move(childServiceDowntimes)));
+ }
+
+ childDowntimes.push_back(childAdditional);
}
additional->Set("child_downtimes", new Array(std::move(childDowntimes)));