]> granicus.if.org Git - icinga2/blob - lib/icinga/externalcommandprocessor.cpp
Merge pull request #6727 from Icinga/feature/cluster-config-sync-stage
[icinga2] / lib / icinga / externalcommandprocessor.cpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #include "icinga/externalcommandprocessor.hpp"
4 #include "icinga/host.hpp"
5 #include "icinga/service.hpp"
6 #include "icinga/user.hpp"
7 #include "icinga/hostgroup.hpp"
8 #include "icinga/servicegroup.hpp"
9 #include "icinga/pluginutility.hpp"
10 #include "icinga/icingaapplication.hpp"
11 #include "icinga/checkcommand.hpp"
12 #include "icinga/eventcommand.hpp"
13 #include "icinga/notificationcommand.hpp"
14 #include "icinga/compatutility.hpp"
15 #include "remote/apifunction.hpp"
16 #include "base/convert.hpp"
17 #include "base/logger.hpp"
18 #include "base/objectlock.hpp"
19 #include "base/application.hpp"
20 #include "base/utility.hpp"
21 #include "base/exception.hpp"
22 #include <fstream>
23 #include <boost/thread/once.hpp>
24
25 using namespace icinga;
26
27 boost::signals2::signal<void(double, const String&, const std::vector<String>&)> ExternalCommandProcessor::OnNewExternalCommand;
28
29 void ExternalCommandProcessor::Execute(const String& line)
30 {
31         if (line.IsEmpty())
32                 return;
33
34         if (line[0] != '[')
35                 BOOST_THROW_EXCEPTION(std::invalid_argument("Missing timestamp in command: " + line));
36
37         size_t pos = line.FindFirstOf("]");
38
39         if (pos == String::NPos)
40                 BOOST_THROW_EXCEPTION(std::invalid_argument("Missing timestamp in command: " + line));
41
42         String timestamp = line.SubStr(1, pos - 1);
43         String args = line.SubStr(pos + 2, String::NPos);
44
45         double ts = Convert::ToDouble(timestamp);
46
47         if (ts == 0)
48                 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid timestamp in command: " + line));
49
50         std::vector<String> argv = args.Split(";");
51
52         if (argv.empty())
53                 BOOST_THROW_EXCEPTION(std::invalid_argument("Missing arguments in command: " + line));
54
55         std::vector<String> argvExtra(argv.begin() + 1, argv.end());
56         Execute(ts, argv[0], argvExtra);
57 }
58
59 void ExternalCommandProcessor::Execute(double time, const String& command, const std::vector<String>& arguments)
60 {
61         ExternalCommandInfo eci;
62
63         static boost::once_flag once = BOOST_ONCE_INIT;
64
65         boost::call_once(once, []() {
66                 RegisterCommands();
67         });
68
69         {
70                 boost::mutex::scoped_lock lock(GetMutex());
71
72                 auto it = GetCommands().find(command);
73
74                 if (it == GetCommands().end())
75                         BOOST_THROW_EXCEPTION(std::invalid_argument("The external command '" + command + "' does not exist."));
76
77                 eci = it->second;
78         }
79
80         if (arguments.size() < eci.MinArgs)
81                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected " + Convert::ToString(eci.MinArgs) + " arguments"));
82
83         size_t argnum = std::min(arguments.size(), eci.MaxArgs);
84
85         std::vector<String> realArguments;
86         realArguments.resize(argnum);
87
88         if (argnum > 0) {
89                 std::copy(arguments.begin(), arguments.begin() + argnum - 1, realArguments.begin());
90
91                 String last_argument;
92                 for (std::vector<String>::size_type i = argnum - 1; i < arguments.size(); i++) {
93                         if (!last_argument.IsEmpty())
94                                 last_argument += ";";
95
96                         last_argument += arguments[i];
97                 }
98
99                 realArguments[argnum - 1] = last_argument;
100         }
101
102         OnNewExternalCommand(time, command, realArguments);
103
104         eci.Callback(time, realArguments);
105 }
106
107 void ExternalCommandProcessor::RegisterCommand(const String& command, const ExternalCommandCallback& callback, size_t minArgs, size_t maxArgs)
108 {
109         boost::mutex::scoped_lock lock(GetMutex());
110         ExternalCommandInfo eci;
111         eci.Callback = callback;
112         eci.MinArgs = minArgs;
113         eci.MaxArgs = (maxArgs == UINT_MAX) ? minArgs : maxArgs;
114         GetCommands()[command] = eci;
115 }
116
117 void ExternalCommandProcessor::RegisterCommands()
118 {
119         RegisterCommand("PROCESS_HOST_CHECK_RESULT", &ExternalCommandProcessor::ProcessHostCheckResult, 3);
120         RegisterCommand("PROCESS_SERVICE_CHECK_RESULT", &ExternalCommandProcessor::ProcessServiceCheckResult, 4);
121         RegisterCommand("SCHEDULE_HOST_CHECK", &ExternalCommandProcessor::ScheduleHostCheck, 2);
122         RegisterCommand("SCHEDULE_FORCED_HOST_CHECK", &ExternalCommandProcessor::ScheduleForcedHostCheck, 2);
123         RegisterCommand("SCHEDULE_SVC_CHECK", &ExternalCommandProcessor::ScheduleSvcCheck, 3);
124         RegisterCommand("SCHEDULE_FORCED_SVC_CHECK", &ExternalCommandProcessor::ScheduleForcedSvcCheck, 3);
125         RegisterCommand("ENABLE_HOST_CHECK", &ExternalCommandProcessor::EnableHostCheck, 1);
126         RegisterCommand("DISABLE_HOST_CHECK", &ExternalCommandProcessor::DisableHostCheck, 1);
127         RegisterCommand("ENABLE_SVC_CHECK", &ExternalCommandProcessor::EnableSvcCheck, 2);
128         RegisterCommand("DISABLE_SVC_CHECK", &ExternalCommandProcessor::DisableSvcCheck, 2);
129         RegisterCommand("SHUTDOWN_PROCESS", &ExternalCommandProcessor::ShutdownProcess);
130         RegisterCommand("RESTART_PROCESS", &ExternalCommandProcessor::RestartProcess);
131         RegisterCommand("SCHEDULE_FORCED_HOST_SVC_CHECKS", &ExternalCommandProcessor::ScheduleForcedHostSvcChecks, 2);
132         RegisterCommand("SCHEDULE_HOST_SVC_CHECKS", &ExternalCommandProcessor::ScheduleHostSvcChecks, 2);
133         RegisterCommand("ENABLE_HOST_SVC_CHECKS", &ExternalCommandProcessor::EnableHostSvcChecks, 1);
134         RegisterCommand("DISABLE_HOST_SVC_CHECKS", &ExternalCommandProcessor::DisableHostSvcChecks, 1);
135         RegisterCommand("ACKNOWLEDGE_SVC_PROBLEM", &ExternalCommandProcessor::AcknowledgeSvcProblem, 7);
136         RegisterCommand("ACKNOWLEDGE_SVC_PROBLEM_EXPIRE", &ExternalCommandProcessor::AcknowledgeSvcProblemExpire, 8);
137         RegisterCommand("REMOVE_SVC_ACKNOWLEDGEMENT", &ExternalCommandProcessor::RemoveSvcAcknowledgement, 2);
138         RegisterCommand("ACKNOWLEDGE_HOST_PROBLEM", &ExternalCommandProcessor::AcknowledgeHostProblem, 6);
139         RegisterCommand("ACKNOWLEDGE_HOST_PROBLEM_EXPIRE", &ExternalCommandProcessor::AcknowledgeHostProblemExpire, 7);
140         RegisterCommand("REMOVE_HOST_ACKNOWLEDGEMENT", &ExternalCommandProcessor::RemoveHostAcknowledgement, 1);
141         RegisterCommand("DISABLE_HOST_FLAP_DETECTION", &ExternalCommandProcessor::DisableHostFlapping, 1);
142         RegisterCommand("ENABLE_HOST_FLAP_DETECTION", &ExternalCommandProcessor::EnableHostFlapping, 1);
143         RegisterCommand("DISABLE_SVC_FLAP_DETECTION", &ExternalCommandProcessor::DisableSvcFlapping, 2);
144         RegisterCommand("ENABLE_SVC_FLAP_DETECTION", &ExternalCommandProcessor::EnableSvcFlapping, 2);
145         RegisterCommand("ENABLE_HOSTGROUP_SVC_CHECKS", &ExternalCommandProcessor::EnableHostgroupSvcChecks, 1);
146         RegisterCommand("DISABLE_HOSTGROUP_SVC_CHECKS", &ExternalCommandProcessor::DisableHostgroupSvcChecks, 1);
147         RegisterCommand("ENABLE_SERVICEGROUP_SVC_CHECKS", &ExternalCommandProcessor::EnableServicegroupSvcChecks, 1);
148         RegisterCommand("DISABLE_SERVICEGROUP_SVC_CHECKS", &ExternalCommandProcessor::DisableServicegroupSvcChecks, 1);
149         RegisterCommand("ENABLE_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::EnablePassiveHostChecks, 1);
150         RegisterCommand("DISABLE_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::DisablePassiveHostChecks, 1);
151         RegisterCommand("ENABLE_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::EnablePassiveSvcChecks, 2);
152         RegisterCommand("DISABLE_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::DisablePassiveSvcChecks, 2);
153         RegisterCommand("ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::EnableServicegroupPassiveSvcChecks, 1);
154         RegisterCommand("DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::DisableServicegroupPassiveSvcChecks, 1);
155         RegisterCommand("ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::EnableHostgroupPassiveSvcChecks, 1);
156         RegisterCommand("DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::DisableHostgroupPassiveSvcChecks, 1);
157         RegisterCommand("PROCESS_FILE", &ExternalCommandProcessor::ProcessFile, 2);
158         RegisterCommand("SCHEDULE_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleSvcDowntime, 9);
159         RegisterCommand("DEL_SVC_DOWNTIME", &ExternalCommandProcessor::DelSvcDowntime, 1);
160         RegisterCommand("SCHEDULE_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleHostDowntime, 8);
161         RegisterCommand("SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleAndPropagateHostDowntime, 8);
162         RegisterCommand("SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleAndPropagateTriggeredHostDowntime, 8);
163         RegisterCommand("DEL_HOST_DOWNTIME", &ExternalCommandProcessor::DelHostDowntime, 1);
164         RegisterCommand("DEL_DOWNTIME_BY_HOST_NAME", &ExternalCommandProcessor::DelDowntimeByHostName, 1, 4);
165         RegisterCommand("SCHEDULE_HOST_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleHostSvcDowntime, 8);
166         RegisterCommand("SCHEDULE_HOSTGROUP_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleHostgroupHostDowntime, 8);
167         RegisterCommand("SCHEDULE_HOSTGROUP_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleHostgroupSvcDowntime, 8);
168         RegisterCommand("SCHEDULE_SERVICEGROUP_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleServicegroupHostDowntime, 8);
169         RegisterCommand("SCHEDULE_SERVICEGROUP_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleServicegroupSvcDowntime, 8);
170         RegisterCommand("ADD_HOST_COMMENT", &ExternalCommandProcessor::AddHostComment, 4);
171         RegisterCommand("DEL_HOST_COMMENT", &ExternalCommandProcessor::DelHostComment, 1);
172         RegisterCommand("ADD_SVC_COMMENT", &ExternalCommandProcessor::AddSvcComment, 5);
173         RegisterCommand("DEL_SVC_COMMENT", &ExternalCommandProcessor::DelSvcComment, 1);
174         RegisterCommand("DEL_ALL_HOST_COMMENTS", &ExternalCommandProcessor::DelAllHostComments, 1);
175         RegisterCommand("DEL_ALL_SVC_COMMENTS", &ExternalCommandProcessor::DelAllSvcComments, 2);
176         RegisterCommand("SEND_CUSTOM_HOST_NOTIFICATION", &ExternalCommandProcessor::SendCustomHostNotification, 4);
177         RegisterCommand("SEND_CUSTOM_SVC_NOTIFICATION", &ExternalCommandProcessor::SendCustomSvcNotification, 5);
178         RegisterCommand("DELAY_HOST_NOTIFICATION", &ExternalCommandProcessor::DelayHostNotification, 2);
179         RegisterCommand("DELAY_SVC_NOTIFICATION", &ExternalCommandProcessor::DelaySvcNotification, 3);
180         RegisterCommand("ENABLE_HOST_NOTIFICATIONS", &ExternalCommandProcessor::EnableHostNotifications, 1);
181         RegisterCommand("DISABLE_HOST_NOTIFICATIONS", &ExternalCommandProcessor::DisableHostNotifications, 1);
182         RegisterCommand("ENABLE_SVC_NOTIFICATIONS", &ExternalCommandProcessor::EnableSvcNotifications, 2);
183         RegisterCommand("DISABLE_SVC_NOTIFICATIONS", &ExternalCommandProcessor::DisableSvcNotifications, 2);
184         RegisterCommand("ENABLE_HOST_SVC_NOTIFICATIONS", &ExternalCommandProcessor::EnableHostSvcNotifications, 1);
185         RegisterCommand("DISABLE_HOST_SVC_NOTIFICATIONS", &ExternalCommandProcessor::DisableHostSvcNotifications, 1);
186         RegisterCommand("DISABLE_HOSTGROUP_HOST_CHECKS", &ExternalCommandProcessor::DisableHostgroupHostChecks, 1);
187         RegisterCommand("DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::DisableHostgroupPassiveHostChecks, 1);
188         RegisterCommand("DISABLE_SERVICEGROUP_HOST_CHECKS", &ExternalCommandProcessor::DisableServicegroupHostChecks, 1);
189         RegisterCommand("DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::DisableServicegroupPassiveHostChecks, 1);
190         RegisterCommand("ENABLE_HOSTGROUP_HOST_CHECKS", &ExternalCommandProcessor::EnableHostgroupHostChecks, 1);
191         RegisterCommand("ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::EnableHostgroupPassiveHostChecks, 1);
192         RegisterCommand("ENABLE_SERVICEGROUP_HOST_CHECKS", &ExternalCommandProcessor::EnableServicegroupHostChecks, 1);
193         RegisterCommand("ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::EnableServicegroupPassiveHostChecks, 1);
194         RegisterCommand("ENABLE_NOTIFICATIONS", &ExternalCommandProcessor::EnableNotifications);
195         RegisterCommand("DISABLE_NOTIFICATIONS", &ExternalCommandProcessor::DisableNotifications);
196         RegisterCommand("ENABLE_FLAP_DETECTION", &ExternalCommandProcessor::EnableFlapDetection);
197         RegisterCommand("DISABLE_FLAP_DETECTION", &ExternalCommandProcessor::DisableFlapDetection);
198         RegisterCommand("ENABLE_EVENT_HANDLERS", &ExternalCommandProcessor::EnableEventHandlers);
199         RegisterCommand("DISABLE_EVENT_HANDLERS", &ExternalCommandProcessor::DisableEventHandlers);
200         RegisterCommand("ENABLE_PERFORMANCE_DATA", &ExternalCommandProcessor::EnablePerformanceData);
201         RegisterCommand("DISABLE_PERFORMANCE_DATA", &ExternalCommandProcessor::DisablePerformanceData);
202         RegisterCommand("START_EXECUTING_SVC_CHECKS", &ExternalCommandProcessor::StartExecutingSvcChecks);
203         RegisterCommand("STOP_EXECUTING_SVC_CHECKS", &ExternalCommandProcessor::StopExecutingSvcChecks);
204         RegisterCommand("START_EXECUTING_HOST_CHECKS", &ExternalCommandProcessor::StartExecutingHostChecks);
205         RegisterCommand("STOP_EXECUTING_HOST_CHECKS", &ExternalCommandProcessor::StopExecutingHostChecks);
206         RegisterCommand("CHANGE_NORMAL_SVC_CHECK_INTERVAL", &ExternalCommandProcessor::ChangeNormalSvcCheckInterval, 3);
207         RegisterCommand("CHANGE_NORMAL_HOST_CHECK_INTERVAL", &ExternalCommandProcessor::ChangeNormalHostCheckInterval, 2);
208         RegisterCommand("CHANGE_RETRY_SVC_CHECK_INTERVAL", &ExternalCommandProcessor::ChangeRetrySvcCheckInterval, 3);
209         RegisterCommand("CHANGE_RETRY_HOST_CHECK_INTERVAL", &ExternalCommandProcessor::ChangeRetryHostCheckInterval, 2);
210         RegisterCommand("ENABLE_HOST_EVENT_HANDLER", &ExternalCommandProcessor::EnableHostEventHandler, 1);
211         RegisterCommand("DISABLE_HOST_EVENT_HANDLER", &ExternalCommandProcessor::DisableHostEventHandler, 1);
212         RegisterCommand("ENABLE_SVC_EVENT_HANDLER", &ExternalCommandProcessor::EnableSvcEventHandler, 2);
213         RegisterCommand("DISABLE_SVC_EVENT_HANDLER", &ExternalCommandProcessor::DisableSvcEventHandler, 2);
214         RegisterCommand("CHANGE_HOST_EVENT_HANDLER", &ExternalCommandProcessor::ChangeHostEventHandler, 2);
215         RegisterCommand("CHANGE_SVC_EVENT_HANDLER", &ExternalCommandProcessor::ChangeSvcEventHandler, 3);
216         RegisterCommand("CHANGE_HOST_CHECK_COMMAND", &ExternalCommandProcessor::ChangeHostCheckCommand, 2);
217         RegisterCommand("CHANGE_SVC_CHECK_COMMAND", &ExternalCommandProcessor::ChangeSvcCheckCommand, 3);
218         RegisterCommand("CHANGE_MAX_HOST_CHECK_ATTEMPTS", &ExternalCommandProcessor::ChangeMaxHostCheckAttempts, 2);
219         RegisterCommand("CHANGE_MAX_SVC_CHECK_ATTEMPTS", &ExternalCommandProcessor::ChangeMaxSvcCheckAttempts, 3);
220         RegisterCommand("CHANGE_HOST_CHECK_TIMEPERIOD", &ExternalCommandProcessor::ChangeHostCheckTimeperiod, 2);
221         RegisterCommand("CHANGE_SVC_CHECK_TIMEPERIOD", &ExternalCommandProcessor::ChangeSvcCheckTimeperiod, 3);
222         RegisterCommand("CHANGE_CUSTOM_HOST_VAR", &ExternalCommandProcessor::ChangeCustomHostVar, 3);
223         RegisterCommand("CHANGE_CUSTOM_SVC_VAR", &ExternalCommandProcessor::ChangeCustomSvcVar, 4);
224         RegisterCommand("CHANGE_CUSTOM_USER_VAR", &ExternalCommandProcessor::ChangeCustomUserVar, 3);
225         RegisterCommand("CHANGE_CUSTOM_CHECKCOMMAND_VAR", &ExternalCommandProcessor::ChangeCustomCheckcommandVar, 3);
226         RegisterCommand("CHANGE_CUSTOM_EVENTCOMMAND_VAR", &ExternalCommandProcessor::ChangeCustomEventcommandVar, 3);
227         RegisterCommand("CHANGE_CUSTOM_NOTIFICATIONCOMMAND_VAR", &ExternalCommandProcessor::ChangeCustomNotificationcommandVar, 3);
228
229         RegisterCommand("ENABLE_HOSTGROUP_HOST_NOTIFICATIONS", &ExternalCommandProcessor::EnableHostgroupHostNotifications, 1);
230         RegisterCommand("ENABLE_HOSTGROUP_SVC_NOTIFICATIONS", &ExternalCommandProcessor::EnableHostgroupSvcNotifications, 1);
231         RegisterCommand("DISABLE_HOSTGROUP_HOST_NOTIFICATIONS", &ExternalCommandProcessor::DisableHostgroupHostNotifications, 1);
232         RegisterCommand("DISABLE_HOSTGROUP_SVC_NOTIFICATIONS", &ExternalCommandProcessor::DisableHostgroupSvcNotifications, 1);
233         RegisterCommand("ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS", &ExternalCommandProcessor::EnableServicegroupHostNotifications, 1);
234         RegisterCommand("DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS", &ExternalCommandProcessor::DisableServicegroupHostNotifications, 1);
235         RegisterCommand("ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS", &ExternalCommandProcessor::EnableServicegroupSvcNotifications, 1);
236         RegisterCommand("DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS", &ExternalCommandProcessor::DisableServicegroupSvcNotifications, 1);
237 }
238
239 void ExternalCommandProcessor::ExecuteFromFile(const String& line, std::deque< std::vector<String> >& file_queue)
240 {
241         if (line.IsEmpty())
242                 return;
243
244         if (line[0] != '[')
245                 BOOST_THROW_EXCEPTION(std::invalid_argument("Missing timestamp in command: " + line));
246
247         size_t pos = line.FindFirstOf("]");
248
249         if (pos == String::NPos)
250                 BOOST_THROW_EXCEPTION(std::invalid_argument("Missing timestamp in command: " + line));
251
252         String timestamp = line.SubStr(1, pos - 1);
253         String args = line.SubStr(pos + 2, String::NPos);
254
255         double ts = Convert::ToDouble(timestamp);
256
257         if (ts == 0)
258                 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid timestamp in command: " + line));
259
260         std::vector<String> argv = args.Split(";");
261
262         if (argv.empty())
263                 BOOST_THROW_EXCEPTION(std::invalid_argument("Missing arguments in command: " + line));
264
265         std::vector<String> argvExtra(argv.begin() + 1, argv.end());
266
267         if (argv[0] == "PROCESS_FILE") {
268                 Log(LogDebug, "ExternalCommandProcessor")
269                         << "Enqueing external command file " << argvExtra[0];
270                 file_queue.push_back(argvExtra);
271         } else {
272                 Execute(ts, argv[0], argvExtra);
273         }
274 }
275
276 void ExternalCommandProcessor::ProcessHostCheckResult(double time, const std::vector<String>& arguments)
277 {
278         Host::Ptr host = Host::GetByName(arguments[0]);
279
280         if (!host)
281                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot process passive host check result for non-existent host '" + arguments[0] + "'"));
282
283         if (!host->GetEnablePassiveChecks())
284                 BOOST_THROW_EXCEPTION(std::invalid_argument("Got passive check result for host '" + arguments[0] + "' which has passive checks disabled."));
285
286         int exitStatus = Convert::ToDouble(arguments[1]);
287         CheckResult::Ptr result = new CheckResult();
288         std::pair<String, String> co = PluginUtility::ParseCheckOutput(arguments[2]);
289         result->SetOutput(co.first);
290         result->SetPerformanceData(PluginUtility::SplitPerfdata(co.second));
291
292         ServiceState state;
293
294         if (exitStatus == 0)
295                 state = ServiceOK;
296         else if (exitStatus == 1)
297                 state = ServiceCritical;
298         else
299                 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid status code: " + arguments[1]));
300
301         result->SetState(state);
302
303         result->SetScheduleStart(time);
304         result->SetScheduleEnd(time);
305         result->SetExecutionStart(time);
306         result->SetExecutionEnd(time);
307
308         /* Mark this check result as passive. */
309         result->SetActive(false);
310
311         Log(LogNotice, "ExternalCommandProcessor")
312                 << "Processing passive check result for host '" << arguments[0] << "'";
313
314         host->ProcessCheckResult(result);
315 }
316
317 void ExternalCommandProcessor::ProcessServiceCheckResult(double time, const std::vector<String>& arguments)
318 {
319         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
320
321         if (!service)
322                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot process passive service check result for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
323
324         if (!service->GetEnablePassiveChecks())
325                 BOOST_THROW_EXCEPTION(std::invalid_argument("Got passive check result for service '" + arguments[1] + "' which has passive checks disabled."));
326
327         int exitStatus = Convert::ToDouble(arguments[2]);
328         CheckResult::Ptr result = new CheckResult();
329         String output = CompatUtility::UnEscapeString(arguments[3]);
330         std::pair<String, String> co = PluginUtility::ParseCheckOutput(output);
331         result->SetOutput(co.first);
332         result->SetPerformanceData(PluginUtility::SplitPerfdata(co.second));
333         result->SetState(PluginUtility::ExitStatusToState(exitStatus));
334
335         result->SetScheduleStart(time);
336         result->SetScheduleEnd(time);
337         result->SetExecutionStart(time);
338         result->SetExecutionEnd(time);
339
340         /* Mark this check result as passive. */
341         result->SetActive(false);
342
343         Log(LogNotice, "ExternalCommandProcessor")
344                 << "Processing passive check result for service '" << arguments[1] << "'";
345
346         service->ProcessCheckResult(result);
347 }
348
349 void ExternalCommandProcessor::ScheduleHostCheck(double, const std::vector<String>& arguments)
350 {
351         Host::Ptr host = Host::GetByName(arguments[0]);
352
353         if (!host)
354                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot reschedule host check for non-existent host '" + arguments[0] + "'"));
355
356         double planned_check = Convert::ToDouble(arguments[1]);
357
358         if (planned_check > host->GetNextCheck()) {
359                 Log(LogNotice, "ExternalCommandProcessor")
360                         << "Ignoring reschedule request for host '"
361                         << arguments[0] << "' (next check is already sooner than requested check time)";
362                 return;
363         }
364
365         Log(LogNotice, "ExternalCommandProcessor")
366                 << "Rescheduling next check for host '" << arguments[0] << "'";
367
368         if (planned_check < Utility::GetTime())
369                 planned_check = Utility::GetTime();
370
371         host->SetNextCheck(planned_check);
372
373         /* trigger update event for DB IDO */
374         Checkable::OnNextCheckUpdated(host);
375 }
376
377 void ExternalCommandProcessor::ScheduleForcedHostCheck(double, const std::vector<String>& arguments)
378 {
379         Host::Ptr host = Host::GetByName(arguments[0]);
380
381         if (!host)
382                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot reschedule forced host check for non-existent host '" + arguments[0] + "'"));
383
384         Log(LogNotice, "ExternalCommandProcessor")
385                 << "Rescheduling next check for host '" << arguments[0] << "'";
386
387         host->SetForceNextCheck(true);
388         host->SetNextCheck(Convert::ToDouble(arguments[1]));
389
390         /* trigger update event for DB IDO */
391         Checkable::OnNextCheckUpdated(host);
392 }
393
394 void ExternalCommandProcessor::ScheduleSvcCheck(double, const std::vector<String>& arguments)
395 {
396         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
397
398         if (!service)
399                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot reschedule service check for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
400
401         double planned_check = Convert::ToDouble(arguments[2]);
402
403         if (planned_check > service->GetNextCheck()) {
404                 Log(LogNotice, "ExternalCommandProcessor")
405                         << "Ignoring reschedule request for service '"
406                         << arguments[1] << "' (next check is already sooner than requested check time)";
407                 return;
408         }
409
410         Log(LogNotice, "ExternalCommandProcessor")
411                 << "Rescheduling next check for service '" << arguments[1] << "'";
412
413         if (planned_check < Utility::GetTime())
414                 planned_check = Utility::GetTime();
415
416         service->SetNextCheck(planned_check);
417
418         /* trigger update event for DB IDO */
419         Checkable::OnNextCheckUpdated(service);
420 }
421
422 void ExternalCommandProcessor::ScheduleForcedSvcCheck(double, const std::vector<String>& arguments)
423 {
424         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
425
426         if (!service)
427                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot reschedule forced service check for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
428
429         Log(LogNotice, "ExternalCommandProcessor")
430                 << "Rescheduling next check for service '" << arguments[1] << "'";
431
432         service->SetForceNextCheck(true);
433         service->SetNextCheck(Convert::ToDouble(arguments[2]));
434
435         /* trigger update event for DB IDO */
436         Checkable::OnNextCheckUpdated(service);
437 }
438
439 void ExternalCommandProcessor::EnableHostCheck(double, const std::vector<String>& arguments)
440 {
441         Host::Ptr host = Host::GetByName(arguments[0]);
442
443         if (!host)
444                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable host checks for non-existent host '" + arguments[0] + "'"));
445
446         Log(LogNotice, "ExternalCommandProcessor")
447                 << "Enabling active checks for host '" << arguments[0] << "'";
448
449         host->ModifyAttribute("enable_active_checks", true);
450 }
451
452 void ExternalCommandProcessor::DisableHostCheck(double, const std::vector<String>& arguments)
453 {
454         Host::Ptr host = Host::GetByName(arguments[0]);
455
456         if (!host)
457                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable host check non-existent host '" + arguments[0] + "'"));
458
459         Log(LogNotice, "ExternalCommandProcessor")
460                 << "Disabling active checks for host '" << arguments[0] << "'";
461
462         host->ModifyAttribute("enable_active_checks", false);
463 }
464
465 void ExternalCommandProcessor::EnableSvcCheck(double, const std::vector<String>& arguments)
466 {
467         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
468
469         if (!service)
470                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable service check for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
471
472         Log(LogNotice, "ExternalCommandProcessor")
473                 << "Enabling active checks for service '" << arguments[1] << "'";
474
475         service->ModifyAttribute("enable_active_checks", true);
476 }
477
478 void ExternalCommandProcessor::DisableSvcCheck(double, const std::vector<String>& arguments)
479 {
480         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
481
482         if (!service)
483                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable service check for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
484
485         Log(LogNotice, "ExternalCommandProcessor")
486                 << "Disabling active checks for service '" << arguments[1] << "'";
487
488         service->ModifyAttribute("enable_active_checks", false);
489 }
490
491 void ExternalCommandProcessor::ShutdownProcess(double, const std::vector<String>&)
492 {
493         Log(LogNotice, "ExternalCommandProcessor", "Shutting down Icinga via external command.");
494         Application::RequestShutdown();
495 }
496
497 void ExternalCommandProcessor::RestartProcess(double, const std::vector<String>&)
498 {
499         Log(LogNotice, "ExternalCommandProcessor", "Restarting Icinga via external command.");
500         Application::RequestRestart();
501 }
502
503 void ExternalCommandProcessor::ScheduleForcedHostSvcChecks(double, const std::vector<String>& arguments)
504 {
505         double planned_check = Convert::ToDouble(arguments[1]);
506
507         Host::Ptr host = Host::GetByName(arguments[0]);
508
509         if (!host)
510                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot reschedule forced host service checks for non-existent host '" + arguments[0] + "'"));
511
512         for (const Service::Ptr& service : host->GetServices()) {
513                 Log(LogNotice, "ExternalCommandProcessor")
514                         << "Rescheduling next check for service '" << service->GetName() << "'";
515
516                 service->SetNextCheck(planned_check);
517                 service->SetForceNextCheck(true);
518
519                 /* trigger update event for DB IDO */
520                 Checkable::OnNextCheckUpdated(service);
521         }
522 }
523
524 void ExternalCommandProcessor::ScheduleHostSvcChecks(double, const std::vector<String>& arguments)
525 {
526         double planned_check = Convert::ToDouble(arguments[1]);
527
528         Host::Ptr host = Host::GetByName(arguments[0]);
529
530         if (!host)
531                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot reschedule host service checks for non-existent host '" + arguments[0] + "'"));
532
533         if (planned_check < Utility::GetTime())
534                 planned_check = Utility::GetTime();
535
536         for (const Service::Ptr& service : host->GetServices()) {
537                 if (planned_check > service->GetNextCheck()) {
538                         Log(LogNotice, "ExternalCommandProcessor")
539                                 << "Ignoring reschedule request for service '"
540                                 << service->GetName() << "' (next check is already sooner than requested check time)";
541                         continue;
542                 }
543
544                 Log(LogNotice, "ExternalCommandProcessor")
545                         << "Rescheduling next check for service '" << service->GetName() << "'";
546
547                 service->SetNextCheck(planned_check);
548
549                 /* trigger update event for DB IDO */
550                 Checkable::OnNextCheckUpdated(service);
551         }
552 }
553
554 void ExternalCommandProcessor::EnableHostSvcChecks(double, const std::vector<String>& arguments)
555 {
556         Host::Ptr host = Host::GetByName(arguments[0]);
557
558         if (!host)
559                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable host service checks for non-existent host '" + arguments[0] + "'"));
560
561         for (const Service::Ptr& service : host->GetServices()) {
562                 Log(LogNotice, "ExternalCommandProcessor")
563                         << "Enabling active checks for service '" << service->GetName() << "'";
564
565                 service->ModifyAttribute("enable_active_checks", true);
566         }
567 }
568
569 void ExternalCommandProcessor::DisableHostSvcChecks(double, const std::vector<String>& arguments)
570 {
571         Host::Ptr host = Host::GetByName(arguments[0]);
572
573         if (!host)
574                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable host service checks for non-existent host '" + arguments[0] + "'"));
575
576         for (const Service::Ptr& service : host->GetServices()) {
577                 Log(LogNotice, "ExternalCommandProcessor")
578                         << "Disabling active checks for service '" << service->GetName() << "'";
579
580                 service->ModifyAttribute("enable_active_checks", false);
581         }
582 }
583
584 void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const std::vector<String>& arguments)
585 {
586         bool sticky = (Convert::ToLong(arguments[2]) == 2 ? true : false);
587         bool notify = (Convert::ToLong(arguments[3]) > 0 ? true : false);
588         bool persistent = (Convert::ToLong(arguments[4]) > 0 ? true : false);
589
590         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
591
592         if (!service)
593                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge service problem for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
594
595         if (service->GetState() == ServiceOK)
596                 BOOST_THROW_EXCEPTION(std::invalid_argument("The service '" + arguments[1] + "' is OK."));
597
598         Log(LogNotice, "ExternalCommandProcessor")
599                 << "Setting acknowledgement for service '" << service->GetName() << "'" << (notify ? "" : ". Disabled notification");
600
601         Comment::AddComment(service, CommentAcknowledgement, arguments[5], arguments[6], persistent, 0);
602         service->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, persistent);
603 }
604
605 void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const std::vector<String>& arguments)
606 {
607         bool sticky = (Convert::ToLong(arguments[2]) == 2 ? true : false);
608         bool notify = (Convert::ToLong(arguments[3]) > 0 ? true : false);
609         bool persistent = (Convert::ToLong(arguments[4]) > 0 ? true : false);
610         double timestamp = Convert::ToDouble(arguments[5]);
611
612         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
613
614         if (!service)
615                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge service problem with expire time for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
616
617         if (service->GetState() == ServiceOK)
618                 BOOST_THROW_EXCEPTION(std::invalid_argument("The service '" + arguments[1] + "' is OK."));
619
620         if (timestamp != 0 && timestamp <= Utility::GetTime())
621                 BOOST_THROW_EXCEPTION(std::invalid_argument("Acknowledgement expire time must be in the future for service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
622
623         Log(LogNotice, "ExternalCommandProcessor")
624                 << "Setting timed acknowledgement for service '" << service->GetName() << "'" << (notify ? "" : ". Disabled notification");
625
626         Comment::AddComment(service, CommentAcknowledgement, arguments[6], arguments[7], persistent, timestamp);
627         service->AcknowledgeProblem(arguments[6], arguments[7], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, persistent, timestamp);
628 }
629
630 void ExternalCommandProcessor::RemoveSvcAcknowledgement(double, const std::vector<String>& arguments)
631 {
632         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
633
634         if (!service)
635                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot remove service acknowledgement for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
636
637         Log(LogNotice, "ExternalCommandProcessor")
638                 << "Removing acknowledgement for service '" << service->GetName() << "'";
639
640         {
641                 ObjectLock olock(service);
642                 service->ClearAcknowledgement();
643         }
644
645         service->RemoveCommentsByType(CommentAcknowledgement);
646 }
647
648 void ExternalCommandProcessor::AcknowledgeHostProblem(double, const std::vector<String>& arguments)
649 {
650         bool sticky = (Convert::ToLong(arguments[1]) == 2 ? true : false);
651         bool notify = (Convert::ToLong(arguments[2]) > 0 ? true : false);
652         bool persistent = (Convert::ToLong(arguments[3]) > 0 ? true : false);
653
654         Host::Ptr host = Host::GetByName(arguments[0]);
655
656         if (!host)
657                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge host problem for non-existent host '" + arguments[0] + "'"));
658
659         Log(LogNotice, "ExternalCommandProcessor")
660                 << "Setting acknowledgement for host '" << host->GetName() << "'" << (notify ? "" : ". Disabled notification");
661
662         if (host->GetState() == HostUp)
663                 BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK."));
664
665         Comment::AddComment(host, CommentAcknowledgement, arguments[4], arguments[5], persistent, 0);
666         host->AcknowledgeProblem(arguments[4], arguments[5], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, persistent);
667 }
668
669 void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const std::vector<String>& arguments)
670 {
671         bool sticky = (Convert::ToLong(arguments[1]) == 2 ? true : false);
672         bool notify = (Convert::ToLong(arguments[2]) > 0 ? true : false);
673         bool persistent = (Convert::ToLong(arguments[3]) > 0 ? true : false);
674         double timestamp = Convert::ToDouble(arguments[4]);
675
676         Host::Ptr host = Host::GetByName(arguments[0]);
677
678         if (!host)
679                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot acknowledge host problem with expire time for non-existent host '" + arguments[0] + "'"));
680
681         Log(LogNotice, "ExternalCommandProcessor")
682                 << "Setting timed acknowledgement for host '" << host->GetName() << "'" << (notify ? "" : ". Disabled notification");
683
684         if (host->GetState() == HostUp)
685                 BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK."));
686
687         if (timestamp != 0 && timestamp <= Utility::GetTime())
688                 BOOST_THROW_EXCEPTION(std::invalid_argument("Acknowledgement expire time must be in the future for host '" + arguments[0] + "'"));
689
690         Comment::AddComment(host, CommentAcknowledgement, arguments[5], arguments[6], persistent, timestamp);
691         host->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, notify, persistent, timestamp);
692 }
693
694 void ExternalCommandProcessor::RemoveHostAcknowledgement(double, const std::vector<String>& arguments)
695 {
696         Host::Ptr host = Host::GetByName(arguments[0]);
697
698         if (!host)
699                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot remove acknowledgement for non-existent host '" + arguments[0] + "'"));
700
701         Log(LogNotice, "ExternalCommandProcessor")
702                 << "Removing acknowledgement for host '" << host->GetName() << "'";
703
704         {
705                 ObjectLock olock(host);
706                 host->ClearAcknowledgement();
707         }
708         host->RemoveCommentsByType(CommentAcknowledgement);
709 }
710
711 void ExternalCommandProcessor::EnableHostgroupSvcChecks(double, const std::vector<String>& arguments)
712 {
713         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
714
715         if (!hg)
716                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable hostgroup service checks for non-existent hostgroup '" + arguments[0] + "'"));
717
718         for (const Host::Ptr& host : hg->GetMembers()) {
719                 for (const Service::Ptr& service : host->GetServices()) {
720                         Log(LogNotice, "ExternalCommandProcessor")
721                                 << "Enabling active checks for service '" << service->GetName() << "'";
722
723                         service->ModifyAttribute("enable_active_checks", true);
724                 }
725         }
726 }
727
728 void ExternalCommandProcessor::DisableHostgroupSvcChecks(double, const std::vector<String>& arguments)
729 {
730         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
731
732         if (!hg)
733                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable hostgroup service checks for non-existent hostgroup '" + arguments[0] + "'"));
734
735         for (const Host::Ptr& host : hg->GetMembers()) {
736                 for (const Service::Ptr& service : host->GetServices()) {
737                         Log(LogNotice, "ExternalCommandProcessor")
738                                 << "Disabling active checks for service '" << service->GetName() << "'";
739
740                         service->ModifyAttribute("enable_active_checks", false);
741                 }
742         }
743 }
744
745 void ExternalCommandProcessor::EnableServicegroupSvcChecks(double, const std::vector<String>& arguments)
746 {
747         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
748
749         if (!sg)
750                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable servicegroup service checks for non-existent servicegroup '" + arguments[0] + "'"));
751
752         for (const Service::Ptr& service : sg->GetMembers()) {
753                 Log(LogNotice, "ExternalCommandProcessor")
754                         << "Enabling active checks for service '" << service->GetName() << "'";
755
756                 service->ModifyAttribute("enable_active_checks", true);
757         }
758 }
759
760 void ExternalCommandProcessor::DisableServicegroupSvcChecks(double, const std::vector<String>& arguments)
761 {
762         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
763
764         if (!sg)
765                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable servicegroup service checks for non-existent servicegroup '" + arguments[0] + "'"));
766
767         for (const Service::Ptr& service : sg->GetMembers()) {
768                 Log(LogNotice, "ExternalCommandProcessor")
769                         << "Disabling active checks for service '" << service->GetName() << "'";
770
771                 service->ModifyAttribute("enable_active_checks", false);
772         }
773 }
774
775 void ExternalCommandProcessor::EnablePassiveHostChecks(double, const std::vector<String>& arguments)
776 {
777         Host::Ptr host = Host::GetByName(arguments[0]);
778
779         if (!host)
780                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable passive host checks for non-existent host '" + arguments[0] + "'"));
781
782         Log(LogNotice, "ExternalCommandProcessor")
783                 << "Enabling passive checks for host '" << arguments[0] << "'";
784
785         host->ModifyAttribute("enable_passive_checks", true);
786 }
787
788 void ExternalCommandProcessor::DisablePassiveHostChecks(double, const std::vector<String>& arguments)
789 {
790         Host::Ptr host = Host::GetByName(arguments[0]);
791
792         if (!host)
793                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable passive host checks for non-existent host '" + arguments[0] + "'"));
794
795         Log(LogNotice, "ExternalCommandProcessor")
796                 << "Disabling passive checks for host '" << arguments[0] << "'";
797
798         host->ModifyAttribute("enable_passive_checks", false);
799 }
800
801 void ExternalCommandProcessor::EnablePassiveSvcChecks(double, const std::vector<String>& arguments)
802 {
803         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
804
805         if (!service)
806                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable service checks for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
807
808         Log(LogNotice, "ExternalCommandProcessor")
809                 << "Enabling passive checks for service '" << arguments[1] << "'";
810
811         service->ModifyAttribute("enable_passive_checks", true);
812 }
813
814 void ExternalCommandProcessor::DisablePassiveSvcChecks(double, const std::vector<String>& arguments)
815 {
816         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
817
818         if (!service)
819                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable service checks for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
820
821         Log(LogNotice, "ExternalCommandProcessor")
822                 << "Disabling passive checks for service '" << arguments[1] << "'";
823
824         service->ModifyAttribute("enable_passive_checks", false);
825 }
826
827 void ExternalCommandProcessor::EnableServicegroupPassiveSvcChecks(double, const std::vector<String>& arguments)
828 {
829         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
830
831         if (!sg)
832                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable servicegroup passive service checks for non-existent servicegroup '" + arguments[0] + "'"));
833
834         for (const Service::Ptr& service : sg->GetMembers()) {
835                 Log(LogNotice, "ExternalCommandProcessor")
836                         << "Enabling passive checks for service '" << service->GetName() << "'";
837
838                 service->ModifyAttribute("enable_passive_checks", true);
839         }
840 }
841
842 void ExternalCommandProcessor::DisableServicegroupPassiveSvcChecks(double, const std::vector<String>& arguments)
843 {
844         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
845
846         if (!sg)
847                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable servicegroup passive service checks for non-existent servicegroup '" + arguments[0] + "'"));
848
849         for (const Service::Ptr& service : sg->GetMembers()) {
850                 Log(LogNotice, "ExternalCommandProcessor")
851                         << "Disabling passive checks for service '" << service->GetName() << "'";
852
853                 service->ModifyAttribute("enable_passive_checks", false);
854         }
855 }
856
857 void ExternalCommandProcessor::EnableHostgroupPassiveSvcChecks(double, const std::vector<String>& arguments)
858 {
859         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
860
861         if (!hg)
862                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable hostgroup passive service checks for non-existent hostgroup '" + arguments[0] + "'"));
863
864         for (const Host::Ptr& host : hg->GetMembers()) {
865                 for (const Service::Ptr& service : host->GetServices()) {
866                         Log(LogNotice, "ExternalCommandProcessor")
867                                 << "Enabling passive checks for service '" << service->GetName() << "'";
868
869                         service->ModifyAttribute("enable_passive_checks", true);
870                 }
871         }
872 }
873
874 void ExternalCommandProcessor::DisableHostgroupPassiveSvcChecks(double, const std::vector<String>& arguments)
875 {
876         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
877
878         if (!hg)
879                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable hostgroup passive service checks for non-existent hostgroup '" + arguments[0] + "'"));
880
881         for (const Host::Ptr& host : hg->GetMembers()) {
882                 for (const Service::Ptr& service : host->GetServices()) {
883                         Log(LogNotice, "ExternalCommandProcessor")
884                                 << "Disabling passive checks for service '" << service->GetName() << "'";
885
886                         service->ModifyAttribute("enable_passive_checks", false);
887                 }
888         }
889 }
890
891 void ExternalCommandProcessor::ProcessFile(double, const std::vector<String>& arguments)
892 {
893         std::deque< std::vector<String> > file_queue;
894         file_queue.push_back(arguments);
895
896         while (!file_queue.empty()) {
897                 std::vector<String> argument = file_queue.front();
898                 file_queue.pop_front();
899
900                 String file = argument[0];
901                 int to_delete = Convert::ToLong(argument[1]);
902
903                 std::ifstream ifp;
904                 ifp.exceptions(std::ifstream::badbit);
905
906                 ifp.open(file.CStr(), std::ifstream::in);
907
908                 while (ifp.good()) {
909                         std::string line;
910                         std::getline(ifp, line);
911
912                         try {
913                                 Log(LogNotice, "compat")
914                                         << "Executing external command: " << line;
915
916                                 ExecuteFromFile(line, file_queue);
917                         } catch (const std::exception& ex) {
918                                 Log(LogWarning, "ExternalCommandProcessor")
919                                         << "External command failed: " << DiagnosticInformation(ex);
920                         }
921                 }
922
923                 ifp.close();
924
925                 if (to_delete > 0)
926                         (void) unlink(file.CStr());
927         }
928 }
929
930 void ExternalCommandProcessor::ScheduleSvcDowntime(double, const std::vector<String>& arguments)
931 {
932         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
933
934         if (!service)
935                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot schedule service downtime for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
936
937         String triggeredBy;
938         int triggeredByLegacy = Convert::ToLong(arguments[5]);
939         int is_fixed = Convert::ToLong(arguments[4]);
940         if (triggeredByLegacy != 0)
941                 triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
942
943         Log(LogNotice, "ExternalCommandProcessor")
944                 << "Creating downtime for service " << service->GetName();
945         (void) Downtime::AddDowntime(service, arguments[7], arguments[8],
946                 Convert::ToDouble(arguments[2]), Convert::ToDouble(arguments[3]),
947                 Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[6]));
948 }
949
950 void ExternalCommandProcessor::DelSvcDowntime(double, const std::vector<String>& arguments)
951 {
952         int id = Convert::ToLong(arguments[0]);
953         Log(LogNotice, "ExternalCommandProcessor")
954                 << "Removing downtime ID " << arguments[0];
955         String rid = Downtime::GetDowntimeIDFromLegacyID(id);
956         Downtime::RemoveDowntime(rid, true);
957 }
958
959 void ExternalCommandProcessor::ScheduleHostDowntime(double, const std::vector<String>& arguments)
960 {
961         Host::Ptr host = Host::GetByName(arguments[0]);
962
963         if (!host)
964                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot schedule host downtime for non-existent host '" + arguments[0] + "'"));
965
966         String triggeredBy;
967         int triggeredByLegacy = Convert::ToLong(arguments[4]);
968         int is_fixed = Convert::ToLong(arguments[3]);
969         if (triggeredByLegacy != 0)
970                 triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
971
972         Log(LogNotice, "ExternalCommandProcessor")
973                 << "Creating downtime for host " << host->GetName();
974
975         (void) Downtime::AddDowntime(host, arguments[6], arguments[7],
976                 Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
977                 Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
978 }
979
980 void ExternalCommandProcessor::ScheduleAndPropagateHostDowntime(double, const std::vector<String>& arguments)
981 {
982         Host::Ptr host = Host::GetByName(arguments[0]);
983
984         if (!host)
985                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot schedule and propagate host downtime for non-existent host '" + arguments[0] + "'"));
986
987         String triggeredBy;
988         int triggeredByLegacy = Convert::ToLong(arguments[4]);
989         int is_fixed = Convert::ToLong(arguments[3]);
990         if (triggeredByLegacy != 0)
991                 triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
992
993         Log(LogNotice, "ExternalCommandProcessor")
994                 << "Creating downtime for host " << host->GetName();
995
996         (void) Downtime::AddDowntime(host, arguments[6], arguments[7],
997                 Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
998                 Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
999
1000         /* Schedule downtime for all child hosts */
1001         for (const Checkable::Ptr& child : host->GetAllChildren()) {
1002                 Host::Ptr host;
1003                 Service::Ptr service;
1004                 tie(host, service) = GetHostService(child);
1005
1006                 /* ignore all service children */
1007                 if (service)
1008                         continue;
1009
1010                 (void) Downtime::AddDowntime(child, arguments[6], arguments[7],
1011                         Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1012                         Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
1013         }
1014 }
1015
1016 void ExternalCommandProcessor::ScheduleAndPropagateTriggeredHostDowntime(double, const std::vector<String>& arguments)
1017 {
1018         Host::Ptr host = Host::GetByName(arguments[0]);
1019
1020         if (!host)
1021                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot schedule and propagate triggered host downtime for non-existent host '" + arguments[0] + "'"));
1022
1023         String triggeredBy;
1024         int triggeredByLegacy = Convert::ToLong(arguments[4]);
1025         int is_fixed = Convert::ToLong(arguments[3]);
1026         if (triggeredByLegacy != 0)
1027                 triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
1028
1029         Log(LogNotice, "ExternalCommandProcessor")
1030                 << "Creating downtime for host " << host->GetName();
1031
1032         String parentDowntime = Downtime::AddDowntime(host, arguments[6], arguments[7],
1033                 Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1034                 Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
1035
1036         /* Schedule downtime for all child hosts and explicitely trigger them through the parent host's downtime */
1037         for (const Checkable::Ptr& child : host->GetAllChildren()) {
1038                 Host::Ptr host;
1039                 Service::Ptr service;
1040                 tie(host, service) = GetHostService(child);
1041
1042                 /* ignore all service children */
1043                 if (service)
1044                         continue;
1045
1046                 (void) Downtime::AddDowntime(child, arguments[6], arguments[7],
1047                         Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1048                         Convert::ToBool(is_fixed), parentDowntime, Convert::ToDouble(arguments[5]));
1049         }
1050 }
1051
1052 void ExternalCommandProcessor::DelHostDowntime(double, const std::vector<String>& arguments)
1053 {
1054         int id = Convert::ToLong(arguments[0]);
1055         Log(LogNotice, "ExternalCommandProcessor")
1056                 << "Removing downtime ID " << arguments[0];
1057         String rid = Downtime::GetDowntimeIDFromLegacyID(id);
1058         Downtime::RemoveDowntime(rid, true);
1059 }
1060
1061 void ExternalCommandProcessor::DelDowntimeByHostName(double, const std::vector<String>& arguments)
1062 {
1063         Host::Ptr host = Host::GetByName(arguments[0]);
1064
1065         if (!host)
1066                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot schedule host services downtime for non-existent host '" + arguments[0] + "'"));
1067
1068         String serviceName;
1069         if (arguments.size() >= 2)
1070                 serviceName = arguments[1];
1071
1072         String startTime;
1073         if (arguments.size() >= 3)
1074                 startTime = arguments[2];
1075
1076         String commentString;
1077         if (arguments.size() >= 4)
1078                 commentString = arguments[3];
1079
1080         if (arguments.size() > 5)
1081                 Log(LogWarning, "ExternalCommandProcessor")
1082                         << ("Ignoring additional parameters for host '" + arguments[0] + "' downtime deletion.");
1083
1084         for (const Downtime::Ptr& downtime : host->GetDowntimes()) {
1085                 Log(LogNotice, "ExternalCommandProcessor")
1086                         << "Removing downtime '" << downtime->GetName() << "'.";
1087
1088                 Downtime::RemoveDowntime(downtime->GetName(), true);
1089         }
1090
1091         for (const Service::Ptr& service : host->GetServices()) {
1092                 if (!serviceName.IsEmpty() && serviceName != service->GetName())
1093                         continue;
1094
1095                 for (const Downtime::Ptr& downtime : service->GetDowntimes()) {
1096                         if (!startTime.IsEmpty() && downtime->GetStartTime() != Convert::ToDouble(startTime))
1097                                 continue;
1098
1099                         if (!commentString.IsEmpty() && downtime->GetComment() != commentString)
1100                                 continue;
1101
1102                         Log(LogNotice, "ExternalCommandProcessor")
1103                                 << "Removing downtime '" << downtime->GetName() << "'.";
1104
1105                         Downtime::RemoveDowntime(downtime->GetName(), true);
1106                 }
1107         }
1108 }
1109
1110 void ExternalCommandProcessor::ScheduleHostSvcDowntime(double, const std::vector<String>& arguments)
1111 {
1112         Host::Ptr host = Host::GetByName(arguments[0]);
1113
1114         if (!host)
1115                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot schedule host services downtime for non-existent host '" + arguments[0] + "'"));
1116
1117         String triggeredBy;
1118         int triggeredByLegacy = Convert::ToLong(arguments[4]);
1119         int is_fixed = Convert::ToLong(arguments[3]);
1120         if (triggeredByLegacy != 0)
1121                 triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
1122
1123         Log(LogNotice, "ExternalCommandProcessor")
1124                 << "Creating downtime for host " << host->GetName();
1125
1126         (void) Downtime::AddDowntime(host, arguments[6], arguments[7],
1127                 Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1128                 Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
1129
1130         for (const Service::Ptr& service : host->GetServices()) {
1131                 Log(LogNotice, "ExternalCommandProcessor")
1132                         << "Creating downtime for service " << service->GetName();
1133                 (void) Downtime::AddDowntime(service, arguments[6], arguments[7],
1134                         Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1135                         Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
1136         }
1137 }
1138
1139 void ExternalCommandProcessor::ScheduleHostgroupHostDowntime(double, const std::vector<String>& arguments)
1140 {
1141         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
1142
1143         if (!hg)
1144                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot schedule hostgroup host downtime for non-existent hostgroup '" + arguments[0] + "'"));
1145
1146         String triggeredBy;
1147         int triggeredByLegacy = Convert::ToLong(arguments[4]);
1148         int is_fixed = Convert::ToLong(arguments[3]);
1149         if (triggeredByLegacy != 0)
1150                 triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
1151
1152         for (const Host::Ptr& host : hg->GetMembers()) {
1153                 Log(LogNotice, "ExternalCommandProcessor")
1154                         <<  "Creating downtime for host " << host->GetName();
1155
1156                 (void) Downtime::AddDowntime(host, arguments[6], arguments[7],
1157                         Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1158                         Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
1159         }
1160 }
1161
1162 void ExternalCommandProcessor::ScheduleHostgroupSvcDowntime(double, const std::vector<String>& arguments)
1163 {
1164         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
1165
1166         if (!hg)
1167                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot schedule hostgroup service downtime for non-existent hostgroup '" + arguments[0] + "'"));
1168
1169         String triggeredBy;
1170         int triggeredByLegacy = Convert::ToLong(arguments[4]);
1171         int is_fixed = Convert::ToLong(arguments[3]);
1172         if (triggeredByLegacy != 0)
1173                 triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
1174
1175         /* Note: we can't just directly create downtimes for all the services by iterating
1176          * over all hosts in the host group - otherwise we might end up creating multiple
1177          * downtimes for some services. */
1178
1179         std::set<Service::Ptr> services;
1180
1181         for (const Host::Ptr& host : hg->GetMembers()) {
1182                 for (const Service::Ptr& service : host->GetServices()) {
1183                         services.insert(service);
1184                 }
1185         }
1186
1187         for (const Service::Ptr& service : services) {
1188                 Log(LogNotice, "ExternalCommandProcessor")
1189                         << "Creating downtime for service " << service->GetName();
1190                 (void) Downtime::AddDowntime(service, arguments[6], arguments[7],
1191                         Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1192                         Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
1193         }
1194 }
1195
1196 void ExternalCommandProcessor::ScheduleServicegroupHostDowntime(double, const std::vector<String>& arguments)
1197 {
1198         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1199
1200         if (!sg)
1201                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot schedule servicegroup host downtime for non-existent servicegroup '" + arguments[0] + "'"));
1202
1203         String triggeredBy;
1204         int triggeredByLegacy = Convert::ToLong(arguments[4]);
1205         int is_fixed = Convert::ToLong(arguments[3]);
1206         if (triggeredByLegacy != 0)
1207                 triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
1208
1209         /* Note: we can't just directly create downtimes for all the hosts by iterating
1210          * over all services in the service group - otherwise we might end up creating multiple
1211          * downtimes for some hosts. */
1212
1213         std::set<Host::Ptr> hosts;
1214
1215         for (const Service::Ptr& service : sg->GetMembers()) {
1216                 Host::Ptr host = service->GetHost();
1217                 hosts.insert(host);
1218         }
1219
1220         for (const Host::Ptr& host : hosts) {
1221                 Log(LogNotice, "ExternalCommandProcessor")
1222                         << "Creating downtime for host " << host->GetName();
1223                 (void) Downtime::AddDowntime(host, arguments[6], arguments[7],
1224                         Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1225                         Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
1226         }
1227 }
1228
1229 void ExternalCommandProcessor::ScheduleServicegroupSvcDowntime(double, const std::vector<String>& arguments)
1230 {
1231         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1232
1233         if (!sg)
1234                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot schedule servicegroup service downtime for non-existent servicegroup '" + arguments[0] + "'"));
1235
1236         String triggeredBy;
1237         int triggeredByLegacy = Convert::ToLong(arguments[4]);
1238         int is_fixed = Convert::ToLong(arguments[3]);
1239         if (triggeredByLegacy != 0)
1240                 triggeredBy = Downtime::GetDowntimeIDFromLegacyID(triggeredByLegacy);
1241
1242         for (const Service::Ptr& service : sg->GetMembers()) {
1243                 Log(LogNotice, "ExternalCommandProcessor")
1244                         << "Creating downtime for service " << service->GetName();
1245                 (void) Downtime::AddDowntime(service, arguments[6], arguments[7],
1246                         Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1247                         Convert::ToBool(is_fixed), triggeredBy, Convert::ToDouble(arguments[5]));
1248         }
1249 }
1250
1251 void ExternalCommandProcessor::AddHostComment(double, const std::vector<String>& arguments)
1252 {
1253         Host::Ptr host = Host::GetByName(arguments[0]);
1254
1255         if (!host)
1256                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot add host comment for non-existent host '" + arguments[0] + "'"));
1257
1258         if (arguments[2].IsEmpty() || arguments[3].IsEmpty())
1259                 BOOST_THROW_EXCEPTION(std::invalid_argument("Author and comment must not be empty"));
1260
1261         Log(LogNotice, "ExternalCommandProcessor")
1262                 << "Creating comment for host " << host->GetName();
1263         (void) Comment::AddComment(host, CommentUser, arguments[2], arguments[3], false, 0);
1264 }
1265
1266 void ExternalCommandProcessor::DelHostComment(double, const std::vector<String>& arguments)
1267 {
1268         int id = Convert::ToLong(arguments[0]);
1269         Log(LogNotice, "ExternalCommandProcessor")
1270                 << "Removing comment ID " << arguments[0];
1271         String rid = Comment::GetCommentIDFromLegacyID(id);
1272         Comment::RemoveComment(rid);
1273 }
1274
1275 void ExternalCommandProcessor::AddSvcComment(double, const std::vector<String>& arguments)
1276 {
1277         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1278
1279         if (!service)
1280                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot add service comment for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1281
1282         if (arguments[3].IsEmpty() || arguments[4].IsEmpty())
1283                 BOOST_THROW_EXCEPTION(std::invalid_argument("Author and comment must not be empty"));
1284
1285         Log(LogNotice, "ExternalCommandProcessor")
1286                 << "Creating comment for service " << service->GetName();
1287         (void) Comment::AddComment(service, CommentUser, arguments[3], arguments[4], false, 0);
1288 }
1289
1290 void ExternalCommandProcessor::DelSvcComment(double, const std::vector<String>& arguments)
1291 {
1292         int id = Convert::ToLong(arguments[0]);
1293         Log(LogNotice, "ExternalCommandProcessor")
1294                 << "Removing comment ID " << arguments[0];
1295
1296         String rid = Comment::GetCommentIDFromLegacyID(id);
1297         Comment::RemoveComment(rid);
1298 }
1299
1300 void ExternalCommandProcessor::DelAllHostComments(double, const std::vector<String>& arguments)
1301 {
1302         Host::Ptr host = Host::GetByName(arguments[0]);
1303
1304         if (!host)
1305                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot delete all host comments for non-existent host '" + arguments[0] + "'"));
1306
1307         Log(LogNotice, "ExternalCommandProcessor")
1308                 << "Removing all comments for host " << host->GetName();
1309         host->RemoveAllComments();
1310 }
1311
1312 void ExternalCommandProcessor::DelAllSvcComments(double, const std::vector<String>& arguments)
1313 {
1314         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1315
1316         if (!service)
1317                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot delete all service comments for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1318
1319         Log(LogNotice, "ExternalCommandProcessor")
1320                 << "Removing all comments for service " << service->GetName();
1321         service->RemoveAllComments();
1322 }
1323
1324 void ExternalCommandProcessor::SendCustomHostNotification(double, const std::vector<String>& arguments)
1325 {
1326         Host::Ptr host = Host::GetByName(arguments[0]);
1327
1328         if (!host)
1329                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot send custom host notification for non-existent host '" + arguments[0] + "'"));
1330
1331         int options = Convert::ToLong(arguments[1]);
1332
1333         Log(LogNotice, "ExternalCommandProcessor")
1334                 << "Sending custom notification for host " << host->GetName();
1335         if (options & 2) {
1336                 host->SetForceNextNotification(true);
1337         }
1338
1339         Checkable::OnNotificationsRequested(host, NotificationCustom,
1340                 host->GetLastCheckResult(), arguments[2], arguments[3], nullptr);
1341 }
1342
1343 void ExternalCommandProcessor::SendCustomSvcNotification(double, const std::vector<String>& arguments)
1344 {
1345         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1346
1347         if (!service)
1348                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot send custom service notification for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1349
1350         int options = Convert::ToLong(arguments[2]);
1351
1352         Log(LogNotice, "ExternalCommandProcessor")
1353                 << "Sending custom notification for service " << service->GetName();
1354
1355         if (options & 2) {
1356                 service->SetForceNextNotification(true);
1357         }
1358
1359         Service::OnNotificationsRequested(service, NotificationCustom,
1360                 service->GetLastCheckResult(), arguments[3], arguments[4], nullptr);
1361 }
1362
1363 void ExternalCommandProcessor::DelayHostNotification(double, const std::vector<String>& arguments)
1364 {
1365         Host::Ptr host = Host::GetByName(arguments[0]);
1366
1367         if (!host)
1368                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot delay host notification for non-existent host '" + arguments[0] + "'"));
1369
1370         Log(LogNotice, "ExternalCommandProcessor")
1371                 << "Delaying notifications for host '" << host->GetName() << "'";
1372
1373         for (const Notification::Ptr& notification : host->GetNotifications()) {
1374                 notification->SetNextNotification(Convert::ToDouble(arguments[1]));
1375         }
1376 }
1377
1378 void ExternalCommandProcessor::DelaySvcNotification(double, const std::vector<String>& arguments)
1379 {
1380         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1381
1382         if (!service)
1383                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot delay service notification for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1384
1385         Log(LogNotice, "ExternalCommandProcessor")
1386                 << "Delaying notifications for service " << service->GetName();
1387
1388         for (const Notification::Ptr& notification : service->GetNotifications()) {
1389                 notification->SetNextNotification(Convert::ToDouble(arguments[2]));
1390         }
1391 }
1392
1393 void ExternalCommandProcessor::EnableHostNotifications(double, const std::vector<String>& arguments)
1394 {
1395         Host::Ptr host = Host::GetByName(arguments[0]);
1396
1397         if (!host)
1398                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable host notifications for non-existent host '" + arguments[0] + "'"));
1399
1400         Log(LogNotice, "ExternalCommandProcessor")
1401                 << "Enabling notifications for host '" << arguments[0] << "'";
1402
1403         host->ModifyAttribute("enable_notifications", true);
1404 }
1405
1406 void ExternalCommandProcessor::DisableHostNotifications(double, const std::vector<String>& arguments)
1407 {
1408         Host::Ptr host = Host::GetByName(arguments[0]);
1409
1410         if (!host)
1411                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable host notifications for non-existent host '" + arguments[0] + "'"));
1412
1413         Log(LogNotice, "ExternalCommandProcessor")
1414                 << "Disabling notifications for host '" << arguments[0] << "'";
1415
1416         host->ModifyAttribute("enable_notifications", false);
1417 }
1418
1419 void ExternalCommandProcessor::EnableSvcNotifications(double, const std::vector<String>& arguments)
1420 {
1421         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1422
1423         if (!service)
1424                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable service notifications for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1425
1426         Log(LogNotice, "ExternalCommandProcessor")
1427                 << "Enabling notifications for service '" << arguments[1] << "'";
1428
1429         service->ModifyAttribute("enable_notifications", true);
1430 }
1431
1432 void ExternalCommandProcessor::DisableSvcNotifications(double, const std::vector<String>& arguments)
1433 {
1434         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1435
1436         if (!service)
1437                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable service notifications for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1438
1439         Log(LogNotice, "ExternalCommandProcessor")
1440                 << "Disabling notifications for service '" << arguments[1] << "'";
1441
1442         service->ModifyAttribute("enable_notifications", false);
1443 }
1444
1445 void ExternalCommandProcessor::EnableHostSvcNotifications(double, const std::vector<String>& arguments)
1446 {
1447         Host::Ptr host = Host::GetByName(arguments[0]);
1448
1449         if (!host)
1450                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable notifications for all services for non-existent host '" + arguments[0] + "'"));
1451
1452         Log(LogNotice, "ExternalCommandProcessor")
1453                 << "Enabling notifications for all services on host '" << arguments[0] << "'";
1454
1455         for (const Service::Ptr& service : host->GetServices()) {
1456                 Log(LogNotice, "ExternalCommandProcessor")
1457                         << "Enabling notifications for service '" << service->GetName() << "'";
1458
1459                 service->ModifyAttribute("enable_notifications", true);
1460         }
1461 }
1462
1463 void ExternalCommandProcessor::DisableHostSvcNotifications(double, const std::vector<String>& arguments)
1464 {
1465         Host::Ptr host = Host::GetByName(arguments[0]);
1466
1467         if (!host)
1468                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable notifications for all services  for non-existent host '" + arguments[0] + "'"));
1469
1470         Log(LogNotice, "ExternalCommandProcessor")
1471                 << "Disabling notifications for all services on host '" << arguments[0] << "'";
1472
1473         for (const Service::Ptr& service : host->GetServices()) {
1474                 Log(LogNotice, "ExternalCommandProcessor")
1475                         << "Disabling notifications for service '" << service->GetName() << "'";
1476
1477                 service->ModifyAttribute("enable_notifications", false);
1478         }
1479 }
1480
1481 void ExternalCommandProcessor::DisableHostgroupHostChecks(double, const std::vector<String>& arguments)
1482 {
1483         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
1484
1485         if (!hg)
1486                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable hostgroup host checks for non-existent hostgroup '" + arguments[0] + "'"));
1487
1488         for (const Host::Ptr& host : hg->GetMembers()) {
1489                 Log(LogNotice, "ExternalCommandProcessor")
1490                         << "Disabling active checks for host '" << host->GetName() << "'";
1491
1492                 host->ModifyAttribute("enable_active_checks", false);
1493         }
1494 }
1495
1496 void ExternalCommandProcessor::DisableHostgroupPassiveHostChecks(double, const std::vector<String>& arguments)
1497 {
1498         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
1499
1500         if (!hg)
1501                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable hostgroup passive host checks for non-existent hostgroup '" + arguments[0] + "'"));
1502
1503         for (const Host::Ptr& host : hg->GetMembers()) {
1504                 Log(LogNotice, "ExternalCommandProcessor")
1505                         << "Disabling passive checks for host '" << host->GetName() << "'";
1506
1507                 host->ModifyAttribute("enable_passive_checks", false);
1508         }
1509 }
1510
1511 void ExternalCommandProcessor::DisableServicegroupHostChecks(double, const std::vector<String>& arguments)
1512 {
1513         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1514
1515         if (!sg)
1516                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable servicegroup host checks for non-existent servicegroup '" + arguments[0] + "'"));
1517
1518         for (const Service::Ptr& service : sg->GetMembers()) {
1519                 Host::Ptr host = service->GetHost();
1520
1521                 Log(LogNotice, "ExternalCommandProcessor")
1522                         << "Disabling active checks for host '" << host->GetName() << "'";
1523
1524                 host->ModifyAttribute("enable_active_checks", false);
1525         }
1526 }
1527
1528 void ExternalCommandProcessor::DisableServicegroupPassiveHostChecks(double, const std::vector<String>& arguments)
1529 {
1530         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1531
1532         if (!sg)
1533                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable servicegroup passive host checks for non-existent servicegroup '" + arguments[0] + "'"));
1534
1535         for (const Service::Ptr& service : sg->GetMembers()) {
1536                 Host::Ptr host = service->GetHost();
1537
1538                 Log(LogNotice, "ExternalCommandProcessor")
1539                         << "Disabling passive checks for host '" << host->GetName() << "'";
1540
1541                 host->ModifyAttribute("enable_passive_checks", false);
1542         }
1543 }
1544
1545 void ExternalCommandProcessor::EnableHostgroupHostChecks(double, const std::vector<String>& arguments)
1546 {
1547         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
1548
1549         if (!hg)
1550                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable hostgroup host checks for non-existent hostgroup '" + arguments[0] + "'"));
1551
1552         for (const Host::Ptr& host : hg->GetMembers()) {
1553                 Log(LogNotice, "ExternalCommandProcessor")
1554                         << "Enabling active checks for host '" << host->GetName() << "'";
1555
1556                 host->ModifyAttribute("enable_active_checks", true);
1557         }
1558 }
1559
1560 void ExternalCommandProcessor::EnableHostgroupPassiveHostChecks(double, const std::vector<String>& arguments)
1561 {
1562         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
1563
1564         if (!hg)
1565                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable hostgroup passive host checks for non-existent hostgroup '" + arguments[0] + "'"));
1566
1567         for (const Host::Ptr& host : hg->GetMembers()) {
1568                 Log(LogNotice, "ExternalCommandProcessor")
1569                         << "Enabling passive checks for host '" << host->GetName() << "'";
1570
1571                 host->ModifyAttribute("enable_passive_checks", true);
1572         }
1573 }
1574
1575 void ExternalCommandProcessor::EnableServicegroupHostChecks(double, const std::vector<String>& arguments)
1576 {
1577         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1578
1579         if (!sg)
1580                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable servicegroup host checks for non-existent servicegroup '" + arguments[0] + "'"));
1581
1582         for (const Service::Ptr& service : sg->GetMembers()) {
1583                 Host::Ptr host = service->GetHost();
1584
1585                 Log(LogNotice, "ExternalCommandProcessor")
1586                         << "Enabling active checks for host '" << host->GetName() << "'";
1587
1588                 host->ModifyAttribute("enable_active_checks", true);
1589         }
1590 }
1591
1592 void ExternalCommandProcessor::EnableServicegroupPassiveHostChecks(double, const std::vector<String>& arguments)
1593 {
1594         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1595
1596         if (!sg)
1597                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable servicegroup passive host checks for non-existent servicegroup '" + arguments[0] + "'"));
1598
1599         for (const Service::Ptr& service : sg->GetMembers()) {
1600                 Host::Ptr host = service->GetHost();
1601
1602                 Log(LogNotice, "ExternalCommandProcessor")
1603                         << "Enabling passive checks for host '" << host->GetName() << "'";
1604
1605                 host->ModifyAttribute("enable_passive_checks", true);
1606         }
1607 }
1608
1609 void ExternalCommandProcessor::EnableHostFlapping(double, const std::vector<String>& arguments)
1610 {
1611         Host::Ptr host = Host::GetByName(arguments[0]);
1612
1613         if (!host)
1614                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable host flapping for non-existent host '" + arguments[0] + "'"));
1615
1616         Log(LogNotice, "ExternalCommandProcessor")
1617                 << "Enabling flapping detection for host '" << arguments[0] << "'";
1618
1619         host->ModifyAttribute("enable_flapping", true);
1620 }
1621
1622 void ExternalCommandProcessor::DisableHostFlapping(double, const std::vector<String>& arguments)
1623 {
1624         Host::Ptr host = Host::GetByName(arguments[0]);
1625
1626         if (!host)
1627                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable host flapping for non-existent host '" + arguments[0] + "'"));
1628
1629         Log(LogNotice, "ExternalCommandProcessor")
1630                 << "Disabling flapping detection for host '" << arguments[0] << "'";
1631
1632         host->ModifyAttribute("enable_flapping", false);
1633 }
1634
1635 void ExternalCommandProcessor::EnableSvcFlapping(double, const std::vector<String>& arguments)
1636 {
1637         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1638
1639         if (!service)
1640                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable service flapping for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1641
1642         Log(LogNotice, "ExternalCommandProcessor")
1643                 << "Enabling flapping detection for service '" << arguments[1] << "'";
1644
1645         service->ModifyAttribute("enable_flapping", true);
1646 }
1647
1648 void ExternalCommandProcessor::DisableSvcFlapping(double, const std::vector<String>& arguments)
1649 {
1650         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1651
1652         if (!service)
1653                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable service flapping for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1654
1655         Log(LogNotice, "ExternalCommandProcessor")
1656                 << "Disabling flapping detection for service '" << arguments[1] << "'";
1657
1658         service->ModifyAttribute("enable_flapping", false);
1659 }
1660
1661 void ExternalCommandProcessor::EnableNotifications(double, const std::vector<String>&)
1662 {
1663         Log(LogNotice, "ExternalCommandProcessor", "Globally enabling notifications.");
1664
1665         IcingaApplication::GetInstance()->ModifyAttribute("enable_notifications", true);
1666 }
1667
1668 void ExternalCommandProcessor::DisableNotifications(double, const std::vector<String>&)
1669 {
1670         Log(LogNotice, "ExternalCommandProcessor", "Globally disabling notifications.");
1671
1672         IcingaApplication::GetInstance()->ModifyAttribute("enable_notifications", false);
1673 }
1674
1675 void ExternalCommandProcessor::EnableFlapDetection(double, const std::vector<String>&)
1676 {
1677         Log(LogNotice, "ExternalCommandProcessor", "Globally enabling flap detection.");
1678
1679         IcingaApplication::GetInstance()->ModifyAttribute("enable_flapping", true);
1680 }
1681
1682 void ExternalCommandProcessor::DisableFlapDetection(double, const std::vector<String>&)
1683 {
1684         Log(LogNotice, "ExternalCommandProcessor", "Globally disabling flap detection.");
1685
1686         IcingaApplication::GetInstance()->ModifyAttribute("enable_flapping", false);
1687 }
1688
1689 void ExternalCommandProcessor::EnableEventHandlers(double, const std::vector<String>&)
1690 {
1691         Log(LogNotice, "ExternalCommandProcessor", "Globally enabling event handlers.");
1692
1693         IcingaApplication::GetInstance()->ModifyAttribute("enable_event_handlers", true);
1694 }
1695
1696 void ExternalCommandProcessor::DisableEventHandlers(double, const std::vector<String>&)
1697 {
1698         Log(LogNotice, "ExternalCommandProcessor", "Globally disabling event handlers.");
1699
1700         IcingaApplication::GetInstance()->ModifyAttribute("enable_event_handlers", false);
1701 }
1702
1703 void ExternalCommandProcessor::EnablePerformanceData(double, const std::vector<String>&)
1704 {
1705         Log(LogNotice, "ExternalCommandProcessor", "Globally enabling performance data processing.");
1706
1707         IcingaApplication::GetInstance()->ModifyAttribute("enable_perfdata", true);
1708 }
1709
1710 void ExternalCommandProcessor::DisablePerformanceData(double, const std::vector<String>&)
1711 {
1712         Log(LogNotice, "ExternalCommandProcessor", "Globally disabling performance data processing.");
1713
1714         IcingaApplication::GetInstance()->ModifyAttribute("enable_perfdata", false);
1715 }
1716
1717 void ExternalCommandProcessor::StartExecutingSvcChecks(double, const std::vector<String>&)
1718 {
1719         Log(LogNotice, "ExternalCommandProcessor", "Globally enabling service checks.");
1720
1721         IcingaApplication::GetInstance()->ModifyAttribute("enable_service_checks", true);
1722 }
1723
1724 void ExternalCommandProcessor::StopExecutingSvcChecks(double, const std::vector<String>&)
1725 {
1726         Log(LogNotice, "ExternalCommandProcessor", "Globally disabling service checks.");
1727
1728         IcingaApplication::GetInstance()->ModifyAttribute("enable_service_checks", false);
1729 }
1730
1731 void ExternalCommandProcessor::StartExecutingHostChecks(double, const std::vector<String>&)
1732 {
1733         Log(LogNotice, "ExternalCommandProcessor", "Globally enabling host checks.");
1734
1735         IcingaApplication::GetInstance()->ModifyAttribute("enable_host_checks", true);
1736 }
1737
1738 void ExternalCommandProcessor::StopExecutingHostChecks(double, const std::vector<String>&)
1739 {
1740         Log(LogNotice, "ExternalCommandProcessor", "Globally disabling host checks.");
1741
1742         IcingaApplication::GetInstance()->ModifyAttribute("enable_host_checks", false);
1743 }
1744
1745 void ExternalCommandProcessor::ChangeNormalSvcCheckInterval(double, const std::vector<String>& arguments)
1746 {
1747         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1748
1749         if (!service)
1750                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot update check interval for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1751
1752         double interval = Convert::ToDouble(arguments[2]);
1753
1754         Log(LogNotice, "ExternalCommandProcessor")
1755                 << "Updating check interval for service '" << arguments[1] << "'";
1756
1757         service->ModifyAttribute("check_interval", interval * 60);
1758 }
1759
1760 void ExternalCommandProcessor::ChangeNormalHostCheckInterval(double, const std::vector<String>& arguments)
1761 {
1762         Host::Ptr host = Host::GetByName(arguments[0]);
1763
1764         if (!host)
1765                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot update check interval for non-existent host '" + arguments[0] + "'"));
1766
1767         Log(LogNotice, "ExternalCommandProcessor")
1768                 << "Updating check interval for host '" << arguments[0] << "'";
1769
1770         double interval = Convert::ToDouble(arguments[1]);
1771
1772         host->ModifyAttribute("check_interval", interval * 60);
1773 }
1774
1775 void ExternalCommandProcessor::ChangeRetrySvcCheckInterval(double, const std::vector<String>& arguments)
1776 {
1777         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1778
1779         if (!service)
1780                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot update retry interval for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1781
1782         double interval = Convert::ToDouble(arguments[2]);
1783
1784         Log(LogNotice, "ExternalCommandProcessor")
1785                 << "Updating retry interval for service '" << arguments[1] << "'";
1786
1787         service->ModifyAttribute("retry_interval", interval * 60);
1788 }
1789
1790 void ExternalCommandProcessor::ChangeRetryHostCheckInterval(double, const std::vector<String>& arguments)
1791 {
1792         Host::Ptr host = Host::GetByName(arguments[0]);
1793
1794         if (!host)
1795                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot update retry interval for non-existent host '" + arguments[0] + "'"));
1796
1797         Log(LogNotice, "ExternalCommandProcessor")
1798                 << "Updating retry interval for host '" << arguments[0] << "'";
1799
1800         double interval = Convert::ToDouble(arguments[1]);
1801
1802         host->ModifyAttribute("retry_interval", interval * 60);
1803 }
1804
1805 void ExternalCommandProcessor::EnableHostEventHandler(double, const std::vector<String>& arguments)
1806 {
1807         Host::Ptr host = Host::GetByName(arguments[0]);
1808
1809         if (!host)
1810                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable event handler for non-existent host '" + arguments[0] + "'"));
1811
1812         Log(LogNotice, "ExternalCommandProcessor")
1813                 << "Enabling event handler for host '" << arguments[0] << "'";
1814
1815         host->ModifyAttribute("enable_event_handler", true);
1816 }
1817
1818 void ExternalCommandProcessor::DisableHostEventHandler(double, const std::vector<String>& arguments)
1819 {
1820         Host::Ptr host = Host::GetByName(arguments[0]);
1821
1822         if (!host)
1823                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable event handler for non-existent host '" + arguments[0] + "'"));
1824
1825         Log(LogNotice, "ExternalCommandProcessor")
1826                 << "Disabling event handler for host '" << arguments[0] << "'";
1827
1828         host->ModifyAttribute("enable_event_handler", false);
1829 }
1830
1831 void ExternalCommandProcessor::EnableSvcEventHandler(double, const std::vector<String>& arguments)
1832 {
1833         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1834
1835         if (!service)
1836                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable event handler for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1837
1838         Log(LogNotice, "ExternalCommandProcessor")
1839                 << "Enabling event handler for service '" << arguments[1] << "'";
1840
1841         service->ModifyAttribute("enable_event_handler", true);
1842 }
1843
1844 void ExternalCommandProcessor::DisableSvcEventHandler(double, const std::vector<String>& arguments)
1845 {
1846         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1847
1848         if (!service)
1849                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable event handler for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1850
1851         Log(LogNotice, "ExternalCommandProcessor")
1852                 << "Disabling event handler for service '" << arguments[1] + "'";
1853
1854         service->ModifyAttribute("enable_event_handler", false);
1855 }
1856
1857 void ExternalCommandProcessor::ChangeHostEventHandler(double, const std::vector<String>& arguments)
1858 {
1859         Host::Ptr host = Host::GetByName(arguments[0]);
1860
1861         if (!host)
1862                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change event handler for non-existent host '" + arguments[0] + "'"));
1863
1864         if (arguments[1].IsEmpty()) {
1865                 Log(LogNotice, "ExternalCommandProcessor")
1866                         << "Unsetting event handler for host '" << arguments[0] << "'";
1867
1868                 host->ModifyAttribute("event_command", "");
1869         } else {
1870                 EventCommand::Ptr command = EventCommand::GetByName(arguments[1]);
1871
1872                 if (!command)
1873                         BOOST_THROW_EXCEPTION(std::invalid_argument("Event command '" + arguments[1] + "' does not exist."));
1874
1875                 Log(LogNotice, "ExternalCommandProcessor")
1876                         << "Changing event handler for host '" << arguments[0] << "' to '" << arguments[1] << "'";
1877
1878                 host->ModifyAttribute("event_command", command->GetName());
1879         }
1880 }
1881
1882 void ExternalCommandProcessor::ChangeSvcEventHandler(double, const std::vector<String>& arguments)
1883 {
1884         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1885
1886         if (!service)
1887                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change event handler for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1888
1889         if (arguments[2].IsEmpty()) {
1890                 Log(LogNotice, "ExternalCommandProcessor")
1891                         << "Unsetting event handler for service '" << arguments[1] << "'";
1892
1893                 service->ModifyAttribute("event_command", "");
1894         } else {
1895                 EventCommand::Ptr command = EventCommand::GetByName(arguments[2]);
1896
1897                 if (!command)
1898                         BOOST_THROW_EXCEPTION(std::invalid_argument("Event command '" + arguments[2] + "' does not exist."));
1899
1900                 Log(LogNotice, "ExternalCommandProcessor")
1901                         << "Changing event handler for service '" << arguments[1] << "' to '" << arguments[2] << "'";
1902
1903                 service->ModifyAttribute("event_command", command->GetName());
1904         }
1905 }
1906
1907 void ExternalCommandProcessor::ChangeHostCheckCommand(double, const std::vector<String>& arguments)
1908 {
1909         Host::Ptr host = Host::GetByName(arguments[0]);
1910
1911         if (!host)
1912                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change check command for non-existent host '" + arguments[0] + "'"));
1913
1914         CheckCommand::Ptr command = CheckCommand::GetByName(arguments[1]);
1915
1916         if (!command)
1917                 BOOST_THROW_EXCEPTION(std::invalid_argument("Check command '" + arguments[1] + "' does not exist."));
1918
1919         Log(LogNotice, "ExternalCommandProcessor")
1920                 << "Changing check command for host '" << arguments[0] << "' to '" << arguments[1] << "'";
1921
1922         host->ModifyAttribute("check_command", command->GetName());
1923 }
1924
1925 void ExternalCommandProcessor::ChangeSvcCheckCommand(double, const std::vector<String>& arguments)
1926 {
1927         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1928
1929         if (!service)
1930                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change check command for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1931
1932         CheckCommand::Ptr command = CheckCommand::GetByName(arguments[2]);
1933
1934         if (!command)
1935                 BOOST_THROW_EXCEPTION(std::invalid_argument("Check command '" + arguments[2] + "' does not exist."));
1936
1937         Log(LogNotice, "ExternalCommandProcessor")
1938                 << "Changing check command for service '" << arguments[1] << "' to '" << arguments[2] << "'";
1939
1940         service->ModifyAttribute("check_command", command->GetName());
1941 }
1942
1943 void ExternalCommandProcessor::ChangeMaxHostCheckAttempts(double, const std::vector<String>& arguments)
1944 {
1945         Host::Ptr host = Host::GetByName(arguments[0]);
1946
1947         if (!host)
1948                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change max check attempts for non-existent host '" + arguments[0] + "'"));
1949
1950         int attempts = Convert::ToLong(arguments[1]);
1951
1952         Log(LogNotice, "ExternalCommandProcessor")
1953                 << "Changing max check attempts for host '" << arguments[0] << "' to '" << arguments[1] << "'";
1954
1955         host->ModifyAttribute("max_check_attempts", attempts);
1956 }
1957
1958 void ExternalCommandProcessor::ChangeMaxSvcCheckAttempts(double, const std::vector<String>& arguments)
1959 {
1960         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1961
1962         if (!service)
1963                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change max check attempts for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1964
1965         int attempts = Convert::ToLong(arguments[2]);
1966
1967         Log(LogNotice, "ExternalCommandProcessor")
1968                 << "Changing max check attempts for service '" << arguments[1] << "' to '" << arguments[2] << "'";
1969
1970         service->ModifyAttribute("max_check_attempts", attempts);
1971 }
1972
1973 void ExternalCommandProcessor::ChangeHostCheckTimeperiod(double, const std::vector<String>& arguments)
1974 {
1975         Host::Ptr host = Host::GetByName(arguments[0]);
1976
1977         if (!host)
1978                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change check period for non-existent host '" + arguments[0] + "'"));
1979
1980         TimePeriod::Ptr tp = TimePeriod::GetByName(arguments[1]);
1981
1982         if (!tp)
1983                 BOOST_THROW_EXCEPTION(std::invalid_argument("Time period '" + arguments[1] + "' does not exist."));
1984
1985         Log(LogNotice, "ExternalCommandProcessor")
1986                 << "Changing check period for host '" << arguments[0] << "' to '" << arguments[1] << "'";
1987
1988         host->ModifyAttribute("check_period", tp->GetName());
1989 }
1990
1991 void ExternalCommandProcessor::ChangeSvcCheckTimeperiod(double, const std::vector<String>& arguments)
1992 {
1993         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1994
1995         if (!service)
1996                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change check period for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
1997
1998         TimePeriod::Ptr tp = TimePeriod::GetByName(arguments[2]);
1999
2000         if (!tp)
2001                 BOOST_THROW_EXCEPTION(std::invalid_argument("Time period '" + arguments[2] + "' does not exist."));
2002
2003         Log(LogNotice, "ExternalCommandProcessor")
2004                 << "Changing check period for service '" << arguments[1] << "' to '" << arguments[2] << "'";
2005
2006         service->ModifyAttribute("check_period", tp->GetName());
2007 }
2008
2009 void ExternalCommandProcessor::ChangeCustomHostVar(double, const std::vector<String>& arguments)
2010 {
2011         Host::Ptr host = Host::GetByName(arguments[0]);
2012
2013         if (!host)
2014                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent host '" + arguments[0] + "'"));
2015
2016         Log(LogNotice, "ExternalCommandProcessor")
2017                 << "Changing custom var '" << arguments[1] << "' for host '" << arguments[0] << "' to value '" << arguments[2] << "'";
2018
2019         host->ModifyAttribute("vars." + arguments[1], arguments[2]);
2020 }
2021
2022 void ExternalCommandProcessor::ChangeCustomSvcVar(double, const std::vector<String>& arguments)
2023 {
2024         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
2025
2026         if (!service)
2027                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'"));
2028
2029         Log(LogNotice, "ExternalCommandProcessor")
2030                 << "Changing custom var '" << arguments[2] << "' for service '" << arguments[1] << "' on host '"
2031                 << arguments[0] << "' to value '" << arguments[3] << "'";
2032
2033         service->ModifyAttribute("vars." + arguments[2], arguments[3]);
2034 }
2035
2036 void ExternalCommandProcessor::ChangeCustomUserVar(double, const std::vector<String>& arguments)
2037 {
2038         User::Ptr user = User::GetByName(arguments[0]);
2039
2040         if (!user)
2041                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent user '" + arguments[0] + "'"));
2042
2043         Log(LogNotice, "ExternalCommandProcessor")
2044                 << "Changing custom var '" << arguments[1] << "' for user '" << arguments[0] << "' to value '" << arguments[2] << "'";
2045
2046         user->ModifyAttribute("vars." + arguments[1], arguments[2]);
2047 }
2048
2049 void ExternalCommandProcessor::ChangeCustomCheckcommandVar(double, const std::vector<String>& arguments)
2050 {
2051         CheckCommand::Ptr command = CheckCommand::GetByName(arguments[0]);
2052
2053         if (!command)
2054                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent command '" + arguments[0] + "'"));
2055
2056         ChangeCustomCommandVarInternal(command, arguments[1], arguments[2]);
2057 }
2058
2059 void ExternalCommandProcessor::ChangeCustomEventcommandVar(double, const std::vector<String>& arguments)
2060 {
2061         EventCommand::Ptr command = EventCommand::GetByName(arguments[0]);
2062
2063         if (!command)
2064                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent command '" + arguments[0] + "'"));
2065
2066         ChangeCustomCommandVarInternal(command, arguments[1], arguments[2]);
2067 }
2068
2069 void ExternalCommandProcessor::ChangeCustomNotificationcommandVar(double, const std::vector<String>& arguments)
2070 {
2071         NotificationCommand::Ptr command = NotificationCommand::GetByName(arguments[0]);
2072
2073         if (!command)
2074                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent command '" + arguments[0] + "'"));
2075
2076         ChangeCustomCommandVarInternal(command, arguments[1], arguments[2]);
2077 }
2078
2079 void ExternalCommandProcessor::ChangeCustomCommandVarInternal(const Command::Ptr& command, const String& name, const Value& value)
2080 {
2081         Log(LogNotice, "ExternalCommandProcessor")
2082                 << "Changing custom var '" << name << "' for command '" << command->GetName() << "' to value '" << value << "'";
2083
2084         command->ModifyAttribute("vars." + name, value);
2085 }
2086
2087 void ExternalCommandProcessor::EnableHostgroupHostNotifications(double, const std::vector<String>& arguments)
2088 {
2089         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
2090
2091         if (!hg)
2092                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable host notifications for non-existent hostgroup '" + arguments[0] + "'"));
2093
2094         for (const Host::Ptr& host : hg->GetMembers()) {
2095                 Log(LogNotice, "ExternalCommandProcessor")
2096                         << "Enabling notifications for host '" << host->GetName() << "'";
2097
2098                 host->ModifyAttribute("enable_notifications", true);
2099         }
2100 }
2101
2102 void ExternalCommandProcessor::EnableHostgroupSvcNotifications(double, const std::vector<String>& arguments)
2103 {
2104         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
2105
2106         if (!hg)
2107                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable service notifications for non-existent hostgroup '" + arguments[0] + "'"));
2108
2109         for (const Host::Ptr& host : hg->GetMembers()) {
2110                 for (const Service::Ptr& service : host->GetServices()) {
2111                         Log(LogNotice, "ExternalCommandProcessor")
2112                                 << "Enabling notifications for service '" << service->GetName() << "'";
2113
2114                         service->ModifyAttribute("enable_notifications", true);
2115                 }
2116         }
2117 }
2118
2119 void ExternalCommandProcessor::DisableHostgroupHostNotifications(double, const std::vector<String>& arguments)
2120 {
2121         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
2122
2123         if (!hg)
2124                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable host notifications for non-existent hostgroup '" + arguments[0] + "'"));
2125
2126         for (const Host::Ptr& host : hg->GetMembers()) {
2127                 Log(LogNotice, "ExternalCommandProcessor")
2128                         << "Disabling notifications for host '" << host->GetName() << "'";
2129
2130                 host->ModifyAttribute("enable_notifications", false);
2131         }
2132 }
2133
2134 void ExternalCommandProcessor::DisableHostgroupSvcNotifications(double, const std::vector<String>& arguments)
2135 {
2136         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
2137
2138         if (!hg)
2139                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable service notifications for non-existent hostgroup '" + arguments[0] + "'"));
2140
2141         for (const Host::Ptr& host : hg->GetMembers()) {
2142                 for (const Service::Ptr& service : host->GetServices()) {
2143                         Log(LogNotice, "ExternalCommandProcessor")
2144                                 << "Disabling notifications for service '" << service->GetName() << "'";
2145
2146                         service->ModifyAttribute("enable_notifications", false);
2147                 }
2148         }
2149 }
2150
2151 void ExternalCommandProcessor::EnableServicegroupHostNotifications(double, const std::vector<String>& arguments)
2152 {
2153         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
2154
2155         if (!sg)
2156                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable host notifications for non-existent servicegroup '" + arguments[0] + "'"));
2157
2158         for (const Service::Ptr& service : sg->GetMembers()) {
2159                 Host::Ptr host = service->GetHost();
2160
2161                 Log(LogNotice, "ExternalCommandProcessor")
2162                         << "Enabling notifications for host '" << host->GetName() << "'";
2163
2164                 host->ModifyAttribute("enable_notifications", true);
2165         }
2166 }
2167
2168 void ExternalCommandProcessor::EnableServicegroupSvcNotifications(double, const std::vector<String>& arguments)
2169 {
2170         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
2171
2172         if (!sg)
2173                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot enable service notifications for non-existent servicegroup '" + arguments[0] + "'"));
2174
2175         for (const Service::Ptr& service : sg->GetMembers()) {
2176                 Log(LogNotice, "ExternalCommandProcessor")
2177                         << "Enabling notifications for service '" << service->GetName() << "'";
2178
2179                 service->ModifyAttribute("enable_notifications", true);
2180         }
2181 }
2182
2183 void ExternalCommandProcessor::DisableServicegroupHostNotifications(double, const std::vector<String>& arguments)
2184 {
2185         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
2186
2187         if (!sg)
2188                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable host notifications for non-existent servicegroup '" + arguments[0] + "'"));
2189
2190         for (const Service::Ptr& service : sg->GetMembers()) {
2191                 Host::Ptr host = service->GetHost();
2192
2193                 Log(LogNotice, "ExternalCommandProcessor")
2194                         << "Disabling notifications for host '" << host->GetName() << "'";
2195
2196                 host->ModifyAttribute("enable_notifications", false);
2197         }
2198 }
2199
2200 void ExternalCommandProcessor::DisableServicegroupSvcNotifications(double, const std::vector<String>& arguments)
2201 {
2202         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
2203
2204         if (!sg)
2205                 BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot disable service notifications for non-existent servicegroup '" + arguments[0] + "'"));
2206
2207         for (const Service::Ptr& service : sg->GetMembers()) {
2208                 Log(LogNotice, "ExternalCommandProcessor")
2209                         << "Disabling notifications for service '" << service->GetName() << "'";
2210
2211                 service->ModifyAttribute("enable_notifications", false);
2212         }
2213 }
2214
2215 boost::mutex& ExternalCommandProcessor::GetMutex()
2216 {
2217         static boost::mutex mtx;
2218         return mtx;
2219 }
2220
2221 std::map<String, ExternalCommandInfo>& ExternalCommandProcessor::GetCommands()
2222 {
2223         static std::map<String, ExternalCommandInfo> commands;
2224         return commands;
2225 }
2226