]> granicus.if.org Git - icinga2/blob - lib/icinga/externalcommandprocessor.cpp
cluster: Fix duplicate acknowledgement comments.
[icinga2] / lib / icinga / externalcommandprocessor.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
4  *                                                                            *
5  * This program is free software; you can redistribute it and/or              *
6  * modify it under the terms of the GNU General Public License                *
7  * as published by the Free Software Foundation; either version 2             *
8  * of the License, or (at your option) any later version.                     *
9  *                                                                            *
10  * This program is distributed in the hope that it will be useful,            *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
13  * GNU General Public License for more details.                               *
14  *                                                                            *
15  * You should have received a copy of the GNU General Public License          *
16  * along with this program; if not, write to the Free Software Foundation     *
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
18  ******************************************************************************/
19
20 #include "icinga/externalcommandprocessor.h"
21 #include "icinga/host.h"
22 #include "icinga/service.h"
23 #include "icinga/user.h"
24 #include "icinga/hostgroup.h"
25 #include "icinga/servicegroup.h"
26 #include "icinga/pluginchecktask.h"
27 #include "base/convert.h"
28 #include "base/logger_fwd.h"
29 #include "base/objectlock.h"
30 #include "base/application.h"
31 #include "base/utility.h"
32 #include <fstream>
33 #include <boost/algorithm/string/classification.hpp>
34 #include <boost/foreach.hpp>
35 #include <boost/exception/diagnostic_information.hpp>
36 #include <boost/algorithm/string/split.hpp>
37
38 using namespace icinga;
39
40 boost::once_flag ExternalCommandProcessor::m_InitializeOnce = BOOST_ONCE_INIT;
41 boost::mutex ExternalCommandProcessor::m_Mutex;
42 std::map<String, ExternalCommandProcessor::Callback> ExternalCommandProcessor::m_Commands;
43
44 void ExternalCommandProcessor::Execute(const String& line)
45 {
46         if (line.IsEmpty())
47                 return;
48
49         if (line[0] != '[')
50                 BOOST_THROW_EXCEPTION(std::invalid_argument("Missing timestamp in command: " + line));
51
52         size_t pos = line.FindFirstOf("]");
53
54         if (pos == String::NPos)
55                 BOOST_THROW_EXCEPTION(std::invalid_argument("Missing timestamp in command: " + line));
56
57         String timestamp = line.SubStr(1, pos - 1);
58         String args = line.SubStr(pos + 2, String::NPos);
59
60         double ts = Convert::ToDouble(timestamp);
61
62         if (ts == 0)
63                 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid timestamp in command: " + line));
64
65         std::vector<String> argv;
66         boost::algorithm::split(argv, args, boost::is_any_of(";"));
67
68         if (argv.empty())
69                 BOOST_THROW_EXCEPTION(std::invalid_argument("Missing arguments in command: " + line));
70
71         std::vector<String> argvExtra(argv.begin() + 1, argv.end());
72         Execute(ts, argv[0], argvExtra);
73 }
74
75 void ExternalCommandProcessor::Execute(double time, const String& command, const std::vector<String>& arguments)
76 {
77         boost::call_once(m_InitializeOnce, &ExternalCommandProcessor::Initialize);
78
79         Callback callback;
80
81         {
82                 boost::mutex::scoped_lock lock(m_Mutex);
83
84                 std::map<String, ExternalCommandProcessor::Callback>::iterator it;
85                 it = m_Commands.find(command);
86
87                 if (it == m_Commands.end())
88                         BOOST_THROW_EXCEPTION(std::invalid_argument("The external command '" + command + "' does not exist."));
89
90                 callback = it->second;
91         }
92
93         callback(time, arguments);
94 }
95
96 void ExternalCommandProcessor::Initialize(void)
97 {
98         RegisterCommand("PROCESS_HOST_CHECK_RESULT", &ExternalCommandProcessor::ProcessHostCheckResult);
99         RegisterCommand("PROCESS_SERVICE_CHECK_RESULT", &ExternalCommandProcessor::ProcessServiceCheckResult);
100         RegisterCommand("SCHEDULE_HOST_CHECK", &ExternalCommandProcessor::ScheduleHostCheck);
101         RegisterCommand("SCHEDULE_FORCED_HOST_CHECK", &ExternalCommandProcessor::ScheduleForcedHostCheck);
102         RegisterCommand("SCHEDULE_SVC_CHECK", &ExternalCommandProcessor::ScheduleSvcCheck);
103         RegisterCommand("SCHEDULE_FORCED_SVC_CHECK", &ExternalCommandProcessor::ScheduleForcedSvcCheck);
104         RegisterCommand("ENABLE_HOST_CHECK", &ExternalCommandProcessor::EnableHostCheck);
105         RegisterCommand("DISABLE_HOST_CHECK", &ExternalCommandProcessor::DisableHostCheck);
106         RegisterCommand("ENABLE_SVC_CHECK", &ExternalCommandProcessor::EnableSvcCheck);
107         RegisterCommand("DISABLE_SVC_CHECK", &ExternalCommandProcessor::DisableSvcCheck);
108         RegisterCommand("SHUTDOWN_PROCESS", &ExternalCommandProcessor::ShutdownProcess);
109         RegisterCommand("SCHEDULE_FORCED_HOST_SVC_CHECKS", &ExternalCommandProcessor::ScheduleForcedHostSvcChecks);
110         RegisterCommand("SCHEDULE_HOST_SVC_CHECKS", &ExternalCommandProcessor::ScheduleHostSvcChecks);
111         RegisterCommand("ENABLE_HOST_SVC_CHECKS", &ExternalCommandProcessor::EnableHostSvcChecks);
112         RegisterCommand("DISABLE_HOST_SVC_CHECKS", &ExternalCommandProcessor::DisableHostSvcChecks);
113         RegisterCommand("ACKNOWLEDGE_SVC_PROBLEM", &ExternalCommandProcessor::AcknowledgeSvcProblem);
114         RegisterCommand("ACKNOWLEDGE_SVC_PROBLEM_EXPIRE", &ExternalCommandProcessor::AcknowledgeSvcProblemExpire);
115         RegisterCommand("REMOVE_SVC_ACKNOWLEDGEMENT", &ExternalCommandProcessor::RemoveSvcAcknowledgement);
116         RegisterCommand("ACKNOWLEDGE_HOST_PROBLEM", &ExternalCommandProcessor::AcknowledgeHostProblem);
117         RegisterCommand("ACKNOWLEDGE_HOST_PROBLEM_EXPIRE", &ExternalCommandProcessor::AcknowledgeHostProblemExpire);
118         RegisterCommand("REMOVE_HOST_ACKNOWLEDGEMENT", &ExternalCommandProcessor::RemoveHostAcknowledgement);
119         RegisterCommand("DISABLE_HOST_FLAP_DETECTION", &ExternalCommandProcessor::DisableHostFlapping);
120         RegisterCommand("ENABLE_HOST_FLAP_DETECTION", &ExternalCommandProcessor::EnableHostFlapping);
121         RegisterCommand("DISABLE_SVC_FLAP_DETECTION", &ExternalCommandProcessor::DisableSvcFlapping);
122         RegisterCommand("ENABLE_SVC_FLAP_DETECTION", &ExternalCommandProcessor::EnableSvcFlapping);
123         RegisterCommand("ENABLE_HOSTGROUP_SVC_CHECKS", &ExternalCommandProcessor::EnableHostgroupSvcChecks);
124         RegisterCommand("DISABLE_HOSTGROUP_SVC_CHECKS", &ExternalCommandProcessor::DisableHostgroupSvcChecks);
125         RegisterCommand("ENABLE_SERVICEGROUP_SVC_CHECKS", &ExternalCommandProcessor::EnableServicegroupSvcChecks);
126         RegisterCommand("DISABLE_SERVICEGROUP_SVC_CHECKS", &ExternalCommandProcessor::DisableServicegroupSvcChecks);
127         RegisterCommand("ENABLE_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::EnablePassiveHostChecks);
128         RegisterCommand("DISABLE_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::DisablePassiveHostChecks);
129         RegisterCommand("ENABLE_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::EnablePassiveSvcChecks);
130         RegisterCommand("DISABLE_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::DisablePassiveSvcChecks);
131         RegisterCommand("ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::EnableServicegroupPassiveSvcChecks);
132         RegisterCommand("DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::DisableServicegroupPassiveSvcChecks);
133         RegisterCommand("ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::EnableHostgroupPassiveSvcChecks);
134         RegisterCommand("DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::DisableHostgroupPassiveSvcChecks);
135         RegisterCommand("PROCESS_FILE", &ExternalCommandProcessor::ProcessFile);
136         RegisterCommand("SCHEDULE_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleSvcDowntime);
137         RegisterCommand("DEL_SVC_DOWNTIME", &ExternalCommandProcessor::DelSvcDowntime);
138         RegisterCommand("SCHEDULE_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleHostDowntime);
139         RegisterCommand("DEL_HOST_DOWNTIME", &ExternalCommandProcessor::DelHostDowntime);
140         RegisterCommand("SCHEDULE_HOST_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleHostSvcDowntime);
141         RegisterCommand("SCHEDULE_HOSTGROUP_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleHostgroupHostDowntime);
142         RegisterCommand("SCHEDULE_HOSTGROUP_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleHostgroupSvcDowntime);
143         RegisterCommand("SCHEDULE_SERVICEGROUP_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleServicegroupHostDowntime);
144         RegisterCommand("SCHEDULE_SERVICEGROUP_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleServicegroupSvcDowntime);
145         RegisterCommand("ADD_HOST_COMMENT", &ExternalCommandProcessor::AddHostComment);
146         RegisterCommand("DEL_HOST_COMMENT", &ExternalCommandProcessor::DelHostComment);
147         RegisterCommand("ADD_SVC_COMMENT", &ExternalCommandProcessor::AddSvcComment);
148         RegisterCommand("DEL_SVC_COMMENT", &ExternalCommandProcessor::DelSvcComment);
149         RegisterCommand("DEL_ALL_HOST_COMMENTS", &ExternalCommandProcessor::DelAllHostComments);
150         RegisterCommand("DEL_ALL_SVC_COMMENTS", &ExternalCommandProcessor::DelAllSvcComments);
151         RegisterCommand("SEND_CUSTOM_HOST_NOTIFICATION", &ExternalCommandProcessor::SendCustomHostNotification);
152         RegisterCommand("SEND_CUSTOM_SVC_NOTIFICATION", &ExternalCommandProcessor::SendCustomSvcNotification);
153         RegisterCommand("DELAY_HOST_NOTIFICATION", &ExternalCommandProcessor::DelayHostNotification);
154         RegisterCommand("DELAY_SVC_NOTIFICATION", &ExternalCommandProcessor::DelaySvcNotification);
155         RegisterCommand("ENABLE_HOST_NOTIFICATIONS", &ExternalCommandProcessor::EnableHostNotifications);
156         RegisterCommand("DISABLE_HOST_NOTIFICATIONS", &ExternalCommandProcessor::DisableHostNotifications);
157         RegisterCommand("ENABLE_SVC_NOTIFICATIONS", &ExternalCommandProcessor::EnableSvcNotifications);
158         RegisterCommand("DISABLE_SVC_NOTIFICATIONS", &ExternalCommandProcessor::DisableSvcNotifications);
159         RegisterCommand("DISABLE_HOSTGROUP_HOST_CHECKS", &ExternalCommandProcessor::DisableHostgroupHostChecks);
160         RegisterCommand("DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::DisableHostgroupPassiveHostChecks);
161         RegisterCommand("DISABLE_SERVICEGROUP_HOST_CHECKS", &ExternalCommandProcessor::DisableServicegroupHostChecks);
162         RegisterCommand("DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::DisableServicegroupPassiveHostChecks);
163         RegisterCommand("ENABLE_HOSTGROUP_HOST_CHECKS", &ExternalCommandProcessor::EnableHostgroupHostChecks);
164         RegisterCommand("ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::EnableHostgroupPassiveHostChecks);
165         RegisterCommand("ENABLE_SERVICEGROUP_HOST_CHECKS", &ExternalCommandProcessor::EnableServicegroupHostChecks);
166         RegisterCommand("ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS", &ExternalCommandProcessor::EnableServicegroupPassiveHostChecks);
167 }
168
169 void ExternalCommandProcessor::RegisterCommand(const String& command, const ExternalCommandProcessor::Callback& callback)
170 {
171         boost::mutex::scoped_lock lock(m_Mutex);
172         m_Commands[command] = callback;
173 }
174
175 void ExternalCommandProcessor::ProcessHostCheckResult(double time, const std::vector<String>& arguments)
176 {
177         if (arguments.size() < 3)
178                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 3 arguments."));
179
180         Host::Ptr host = Host::GetByName(arguments[0]);
181
182         Service::Ptr hc = host->GetHostCheckService();
183
184         if (!hc->GetEnablePassiveChecks())
185                 BOOST_THROW_EXCEPTION(std::invalid_argument("Got passive check result for host '" + arguments[0] + "' which has passive checks disabled."));
186
187         int exitStatus = Convert::ToDouble(arguments[1]);
188         Dictionary::Ptr result = PluginCheckTask::ParseCheckOutput(arguments[2]);
189         result->Set("state", PluginCheckTask::ExitStatusToState(exitStatus));
190
191         result->Set("schedule_start", time);
192         result->Set("schedule_end", time);
193         result->Set("execution_start", time);
194         result->Set("execution_end", time);
195         result->Set("active", 0);
196
197         Log(LogInformation, "icinga", "Processing passive check result for host '" + arguments[0] + "'");
198         hc->ProcessCheckResult(result);
199
200         {
201                 ObjectLock olock(hc);
202
203                 /* Reschedule the next check. The side effect of this is that for as long
204                  * as we receive passive results for a service we won't execute any
205                  * active checks. */
206                 hc->SetNextCheck(Utility::GetTime() + hc->GetCheckInterval());
207         }
208 }
209
210 void ExternalCommandProcessor::ProcessServiceCheckResult(double time, const std::vector<String>& arguments)
211 {
212         if (arguments.size() < 4)
213                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 4 arguments."));
214
215         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
216
217         if (!service->GetEnablePassiveChecks())
218                 BOOST_THROW_EXCEPTION(std::invalid_argument("Got passive check result for service '" + arguments[1] + "' which has passive checks disabled."));
219
220         int exitStatus = Convert::ToDouble(arguments[2]);
221         Dictionary::Ptr result = PluginCheckTask::ParseCheckOutput(arguments[3]);
222         result->Set("state", PluginCheckTask::ExitStatusToState(exitStatus));
223
224         result->Set("schedule_start", time);
225         result->Set("schedule_end", time);
226         result->Set("execution_start", time);
227         result->Set("execution_end", time);
228         result->Set("active", 0);
229
230         Log(LogInformation, "icinga", "Processing passive check result for service '" + arguments[1] + "'");
231         service->ProcessCheckResult(result);
232
233         {
234                 ObjectLock olock(service);
235
236                 /* Reschedule the next check. The side effect of this is that for as long
237                  * as we receive passive results for a service we won't execute any
238                  * active checks. */
239                 service->SetNextCheck(Utility::GetTime() + service->GetCheckInterval());
240         }
241 }
242
243 void ExternalCommandProcessor::ScheduleHostCheck(double, const std::vector<String>& arguments)
244 {
245         if (arguments.size() < 2)
246                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
247
248         Host::Ptr host = Host::GetByName(arguments[0]);
249
250         Service::Ptr hc = host->GetHostCheckService();
251
252         if (!hc) {
253                 Log(LogInformation, "icinga", "Ignoring request request for host '" +
254                     arguments[0] + "' (does not have a host check)");
255                 return;
256         }
257
258         double planned_check = Convert::ToDouble(arguments[1]);
259
260         if (planned_check > hc->GetNextCheck()) {
261                 Log(LogInformation, "icinga", "Ignoring reschedule request for host '" +
262                     arguments[0] + "' (next check is already sooner than requested check time)");
263                 return;
264         }
265
266         Log(LogInformation, "icinga", "Rescheduling next check for host '" + arguments[0] + "'");
267
268         {
269                 ObjectLock olock(hc);
270
271                 hc->SetNextCheck(planned_check);
272         }
273 }
274
275 void ExternalCommandProcessor::ScheduleForcedHostCheck(double, const std::vector<String>& arguments)
276 {
277         if (arguments.size() < 2)
278                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
279
280         Host::Ptr host = Host::GetByName(arguments[0]);
281
282         Service::Ptr hc = host->GetHostCheckService();
283
284         if (!hc) {
285                 Log(LogInformation, "icinga", "Ignoring request request for host '" +
286                     arguments[0] + "' (does not have a host check)");
287                 return;
288         }
289
290         Log(LogInformation, "icinga", "Rescheduling next check for host '" + arguments[0] + "'");
291
292         {
293                 ObjectLock olock(hc);
294
295                 hc->SetForceNextCheck(true);
296                 hc->SetNextCheck(Convert::ToDouble(arguments[1]));
297         }
298 }
299
300 void ExternalCommandProcessor::ScheduleSvcCheck(double, const std::vector<String>& arguments)
301 {
302         if (arguments.size() < 3)
303                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 3 arguments."));
304
305         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
306
307         double planned_check = Convert::ToDouble(arguments[2]);
308
309         if (planned_check > service->GetNextCheck()) {
310                 Log(LogInformation, "icinga", "Ignoring reschedule request for service '" +
311                     arguments[1] + "' (next check is already sooner than requested check time)");
312                 return;
313         }
314
315         Log(LogInformation, "icinga", "Rescheduling next check for service '" + arguments[1] + "'");
316
317         {
318                 ObjectLock olock(service);
319
320                 service->SetNextCheck(planned_check);
321         }
322 }
323
324 void ExternalCommandProcessor::ScheduleForcedSvcCheck(double, const std::vector<String>& arguments)
325 {
326         if (arguments.size() < 3)
327                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 3 arguments."));
328
329         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
330
331         Log(LogInformation, "icinga", "Rescheduling next check for service '" + arguments[1] + "'");
332
333         {
334                 ObjectLock olock(service);
335
336                 service->SetForceNextCheck(true);
337                 service->SetNextCheck(Convert::ToDouble(arguments[2]));
338         }
339 }
340
341 void ExternalCommandProcessor::EnableHostCheck(double, const std::vector<String>& arguments)
342 {
343         if (arguments.size() < 1)
344                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
345
346         Host::Ptr host = Host::GetByName(arguments[0]);
347
348         Log(LogInformation, "icinga", "Enabling active checks for host '" + arguments[0] + "'");
349         Service::Ptr hc = host->GetHostCheckService();
350
351         if (!hc)
352                 return;
353
354         {
355                 ObjectLock olock(hc);
356
357                 hc->SetEnableActiveChecks(true);
358         }
359 }
360
361 void ExternalCommandProcessor::DisableHostCheck(double, const std::vector<String>& arguments)
362 {
363         if (arguments.size() < 1)
364                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
365
366         Host::Ptr host = Host::GetByName(arguments[0]);
367
368         Log(LogInformation, "icinga", "Disabling active checks for host '" + arguments[0] + "'");
369         Service::Ptr hc = host->GetHostCheckService();
370
371         if (!hc)
372                 return;
373
374         {
375                 ObjectLock olock(hc);
376
377                 hc->SetEnableActiveChecks(false);
378         }
379 }
380
381 void ExternalCommandProcessor::EnableSvcCheck(double, const std::vector<String>& arguments)
382 {
383         if (arguments.size() < 2)
384                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
385
386         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
387
388         Log(LogInformation, "icinga", "Enabling active checks for service '" + arguments[1] + "'");
389
390         {
391                 ObjectLock olock(service);
392
393                 service->SetEnableActiveChecks(true);
394         }
395 }
396
397 void ExternalCommandProcessor::DisableSvcCheck(double, const std::vector<String>& arguments)
398 {
399         if (arguments.size() < 2)
400                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
401
402         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
403
404         Log(LogInformation, "icinga", "Disabling active checks for service '" + arguments[1] + "'");
405
406         {
407                 ObjectLock olock(service);
408
409                 service->SetEnableActiveChecks(false);
410         }
411 }
412
413 void ExternalCommandProcessor::ShutdownProcess(double, const std::vector<String>&)
414 {
415         Log(LogInformation, "icinga", "Shutting down Icinga via external command.");
416         Application::RequestShutdown();
417 }
418
419 void ExternalCommandProcessor::ScheduleForcedHostSvcChecks(double, const std::vector<String>& arguments)
420 {
421         if (arguments.size() < 2)
422                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
423
424         double planned_check = Convert::ToDouble(arguments[1]);
425
426         Host::Ptr host = Host::GetByName(arguments[0]);
427
428         BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
429                 Log(LogInformation, "icinga", "Rescheduling next check for service '" + service->GetName() + "'");
430
431                 {
432                         ObjectLock olock(service);
433
434                         service->SetNextCheck(planned_check);
435                         service->SetForceNextCheck(true);
436                 }
437         }
438 }
439
440 void ExternalCommandProcessor::ScheduleHostSvcChecks(double, const std::vector<String>& arguments)
441 {
442         if (arguments.size() < 2)
443                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
444
445         double planned_check = Convert::ToDouble(arguments[1]);
446
447         Host::Ptr host = Host::GetByName(arguments[0]);
448
449         BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
450                 if (planned_check > service->GetNextCheck()) {
451                         Log(LogInformation, "icinga", "Ignoring reschedule request for service '" +
452                             service->GetName() + "' (next check is already sooner than requested check time)");
453                         continue;
454                 }
455
456                 Log(LogInformation, "icinga", "Rescheduling next check for service '" + service->GetName() + "'");
457
458                 {
459                         ObjectLock olock(service);
460
461                         service->SetNextCheck(planned_check);
462                 }
463         }
464 }
465
466 void ExternalCommandProcessor::EnableHostSvcChecks(double, const std::vector<String>& arguments)
467 {
468         if (arguments.size() < 1)
469                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
470
471         Host::Ptr host = Host::GetByName(arguments[0]);
472
473         BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
474                 Log(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
475                 service->SetEnableActiveChecks(true);
476         }
477 }
478
479 void ExternalCommandProcessor::DisableHostSvcChecks(double, const std::vector<String>& arguments)
480 {
481         if (arguments.size() < 1)
482                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 arguments."));
483
484         Host::Ptr host = Host::GetByName(arguments[0]);
485
486         BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
487                 Log(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
488
489                 {
490                         ObjectLock olock(service);
491
492                         service->SetEnableActiveChecks(false);
493                 }
494         }
495 }
496
497 void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const std::vector<String>& arguments)
498 {
499         if (arguments.size() < 7)
500                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 7 arguments."));
501
502         bool sticky = Convert::ToBool(arguments[2]);
503
504         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
505
506         if (service->GetState() == StateOK)
507                 BOOST_THROW_EXCEPTION(std::invalid_argument("The service '" + arguments[1] + "' is OK."));
508
509         Log(LogInformation, "icinga", "Setting acknowledgement for service '" + service->GetName() + "'");
510
511         service->AddComment(CommentAcknowledgement, arguments[5], arguments[6], 0);
512         service->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal);
513 }
514
515 void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const std::vector<String>& arguments)
516 {
517         if (arguments.size() < 8)
518                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 8 arguments."));
519
520         bool sticky = Convert::ToBool(arguments[2]);
521         double timestamp = Convert::ToDouble(arguments[5]);
522
523         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
524
525         if (service->GetState() == StateOK)
526                 BOOST_THROW_EXCEPTION(std::invalid_argument("The service '" + arguments[1] + "' is OK."));
527
528         Log(LogInformation, "icinga", "Setting timed acknowledgement for service '" + service->GetName() + "'");
529
530         service->AddComment(CommentAcknowledgement, arguments[6], arguments[7], 0);
531         service->AcknowledgeProblem(arguments[6], arguments[7], sticky ? AcknowledgementSticky : AcknowledgementNormal, timestamp);
532 }
533
534 void ExternalCommandProcessor::RemoveSvcAcknowledgement(double, const std::vector<String>& arguments)
535 {
536         if (arguments.size() < 2)
537                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
538
539         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
540
541         Log(LogInformation, "icinga", "Removing acknowledgement for service '" + service->GetName() + "'");
542
543         service->ClearAcknowledgement();
544 }
545
546 void ExternalCommandProcessor::AcknowledgeHostProblem(double, const std::vector<String>& arguments)
547 {
548         if (arguments.size() < 6)
549                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 6 arguments."));
550
551         bool sticky = Convert::ToBool(arguments[1]);
552
553         Host::Ptr host = Host::GetByName(arguments[0]);
554
555         Log(LogInformation, "icinga", "Setting acknowledgement for host '" + host->GetName() + "'");
556         Service::Ptr service = host->GetHostCheckService();
557         if (service) {
558                 if (service->GetState() == StateOK)
559                         BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK."));
560
561                 service->AddComment(CommentAcknowledgement, arguments[4], arguments[5], 0);
562                 service->AcknowledgeProblem(arguments[4], arguments[5], sticky ? AcknowledgementSticky : AcknowledgementNormal);
563         }
564 }
565
566 void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const std::vector<String>& arguments)
567 {
568         if (arguments.size() < 7)
569                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 7 arguments."));
570
571         bool sticky = Convert::ToBool(arguments[1]);
572         double timestamp = Convert::ToDouble(arguments[4]);
573
574         Host::Ptr host = Host::GetByName(arguments[0]);
575
576         Log(LogInformation, "icinga", "Setting timed acknowledgement for host '" + host->GetName() + "'");
577         Service::Ptr service = host->GetHostCheckService();
578         if (service) {
579                 if (service->GetState() == StateOK)
580                         BOOST_THROW_EXCEPTION(std::invalid_argument("The host '" + arguments[0] + "' is OK."));
581
582                 service->AddComment(CommentAcknowledgement, arguments[5], arguments[6], 0);
583                 service->AcknowledgeProblem(arguments[5], arguments[6], sticky ? AcknowledgementSticky : AcknowledgementNormal, timestamp);
584         }
585 }
586
587 void ExternalCommandProcessor::RemoveHostAcknowledgement(double, const std::vector<String>& arguments)
588 {
589         if (arguments.size() < 1)
590                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
591
592         Host::Ptr host = Host::GetByName(arguments[0]);
593
594         Log(LogInformation, "icinga", "Removing acknowledgement for host '" + host->GetName() + "'");
595         Service::Ptr service = host->GetHostCheckService();
596         if (service)
597                 service->ClearAcknowledgement();
598 }
599
600 void ExternalCommandProcessor::EnableHostgroupSvcChecks(double, const std::vector<String>& arguments)
601 {
602         if (arguments.size() < 1)
603                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
604
605         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
606
607         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
608                 BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
609                         Log(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
610
611                         {
612                                 ObjectLock olock(service);
613
614                                 service->SetEnableActiveChecks(true);
615                         }
616                 }
617         }
618 }
619
620 void ExternalCommandProcessor::DisableHostgroupSvcChecks(double, const std::vector<String>& arguments)
621 {
622         if (arguments.size() < 1)
623                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
624
625         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
626
627         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
628                 BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
629                         Log(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
630
631                         {
632                                 ObjectLock olock(service);
633
634                                 service->SetEnableActiveChecks(false);
635                         }
636                 }
637         }
638 }
639
640 void ExternalCommandProcessor::EnableServicegroupSvcChecks(double, const std::vector<String>& arguments)
641 {
642         if (arguments.size() < 1)
643                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
644
645         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
646
647         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
648                 Log(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
649
650                 {
651                         ObjectLock olock(service);
652
653                         service->SetEnableActiveChecks(true);
654                 }
655         }
656 }
657
658 void ExternalCommandProcessor::DisableServicegroupSvcChecks(double, const std::vector<String>& arguments)
659 {
660         if (arguments.size() < 1)
661                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
662
663         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
664
665         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
666                 Log(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
667
668                 {
669                         ObjectLock olock(service);
670
671                         service->SetEnableActiveChecks(false);
672                 }
673         }
674 }
675
676 void ExternalCommandProcessor::EnablePassiveHostChecks(double, const std::vector<String>& arguments)
677 {
678         if (arguments.size() < 1)
679                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
680
681         Host::Ptr host = Host::GetByName(arguments[0]);
682
683         Log(LogInformation, "icinga", "Enabling passive checks for host '" + arguments[0] + "'");
684         Service::Ptr hc = host->GetHostCheckService();
685
686         if (!hc)
687                 return;
688
689         {
690                 ObjectLock olock(hc);
691
692                 hc->SetEnablePassiveChecks(true);
693         }
694 }
695
696 void ExternalCommandProcessor::DisablePassiveHostChecks(double, const std::vector<String>& arguments)
697 {
698         if (arguments.size() < 1)
699                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 arguments."));
700
701         Host::Ptr host = Host::GetByName(arguments[0]);
702
703         Log(LogInformation, "icinga", "Disabling passive checks for host '" + arguments[0] + "'");
704         Service::Ptr hc = host->GetHostCheckService();
705
706         if (!hc)
707                 return;
708
709         {
710                 ObjectLock olock(hc);
711
712                 hc->SetEnablePassiveChecks(false);
713         }
714 }
715
716 void ExternalCommandProcessor::EnablePassiveSvcChecks(double, const std::vector<String>& arguments)
717 {
718         if (arguments.size() < 2)
719                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
720
721         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
722
723         Log(LogInformation, "icinga", "Enabling passive checks for service '" + arguments[1] + "'");
724
725         {
726                 ObjectLock olock(service);
727
728                 service->SetEnablePassiveChecks(true);
729         }
730 }
731
732 void ExternalCommandProcessor::DisablePassiveSvcChecks(double, const std::vector<String>& arguments)
733 {
734         if (arguments.size() < 2)
735                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
736
737         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
738
739         Log(LogInformation, "icinga", "Disabling passive checks for service '" + arguments[1] + "'");
740
741         {
742                 ObjectLock olock(service);
743
744                 service->SetEnablePassiveChecks(false);
745         }
746 }
747
748 void ExternalCommandProcessor::EnableServicegroupPassiveSvcChecks(double, const std::vector<String>& arguments)
749 {
750         if (arguments.size() < 1)
751                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
752
753         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
754
755         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
756                 Log(LogInformation, "icinga", "Enabling passive checks for service '" + service->GetName() + "'");
757
758                 {
759                         ObjectLock olock(service);
760
761                         service->SetEnablePassiveChecks(true);
762                 }
763         }
764 }
765
766 void ExternalCommandProcessor::DisableServicegroupPassiveSvcChecks(double, const std::vector<String>& arguments)
767 {
768         if (arguments.size() < 1)
769                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
770
771         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
772
773         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
774                 Log(LogInformation, "icinga", "Disabling passive checks for service '" + service->GetName() + "'");
775
776                 {
777                         ObjectLock olock(service);
778
779                         service->SetEnablePassiveChecks(true);
780                 }
781         }
782 }
783
784 void ExternalCommandProcessor::EnableHostgroupPassiveSvcChecks(double, const std::vector<String>& arguments)
785 {
786         if (arguments.size() < 1)
787                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
788
789         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
790
791         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
792                 BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
793                         Log(LogInformation, "icinga", "Enabling passive checks for service '" + service->GetName() + "'");
794
795                         {
796                                 ObjectLock olock(service);
797
798                                 service->SetEnablePassiveChecks(true);
799                         }
800                 }
801         }
802 }
803
804 void ExternalCommandProcessor::DisableHostgroupPassiveSvcChecks(double, const std::vector<String>& arguments)
805 {
806         if (arguments.size() < 1)
807                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
808
809         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
810
811         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
812                 BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
813                         Log(LogInformation, "icinga", "Disabling passive checks for service '" + service->GetName() + "'");
814
815                         {
816                                 ObjectLock olock(service);
817
818                                 service->SetEnablePassiveChecks(false);
819                         }
820                 }
821         }
822 }
823
824 void ExternalCommandProcessor::ProcessFile(double, const std::vector<String>& arguments)
825 {
826         if (arguments.size() < 2)
827                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
828
829         String file = arguments[0];
830         bool del = Convert::ToBool(arguments[1]);
831
832         std::ifstream ifp;
833         ifp.exceptions(std::ifstream::badbit);
834
835         ifp.open(file.CStr(), std::ifstream::in);
836
837         while(ifp.good()) {
838                 std::string line;
839                 std::getline(ifp, line);
840
841                 try {
842                         Log(LogInformation, "compat", "Executing external command: " + line);
843
844                         Execute(line);
845                 } catch (const std::exception& ex) {
846                         std::ostringstream msgbuf;
847                         msgbuf << "External command failed: " << boost::diagnostic_information(ex);
848                         Log(LogWarning, "icinga", msgbuf.str());
849                 }
850         }
851
852         ifp.close();
853
854         if (del)
855                 (void) unlink(file.CStr());
856 }
857
858 void ExternalCommandProcessor::ScheduleSvcDowntime(double, const std::vector<String>& arguments)
859 {
860         if (arguments.size() < 9)
861                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 9 arguments."));
862
863         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
864
865         String triggeredBy;
866         int triggeredByLegacy = Convert::ToLong(arguments[5]);
867         if (triggeredByLegacy != 0)
868                 triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
869
870         Log(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
871         String comment_id = service->AddComment(CommentDowntime, arguments[7], arguments[8], Convert::ToDouble(arguments[3]));
872         (void) service->AddDowntime(comment_id,
873             Convert::ToDouble(arguments[2]), Convert::ToDouble(arguments[3]),
874             Convert::ToBool(arguments[4]), triggeredBy, Convert::ToDouble(arguments[6]));
875 }
876
877 void ExternalCommandProcessor::DelSvcDowntime(double, const std::vector<String>& arguments)
878 {
879         if (arguments.size() < 1)
880                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
881
882         int id = Convert::ToLong(arguments[0]);
883         Log(LogInformation, "icinga", "Removing downtime ID " + arguments[0]);
884         String rid = Service::GetDowntimeIDFromLegacyID(id);
885         Service::RemoveDowntime(rid);
886 }
887
888 void ExternalCommandProcessor::ScheduleHostDowntime(double, const std::vector<String>& arguments)
889 {
890         if (arguments.size() < 8)
891                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 8 arguments."));
892
893         Host::Ptr host = Host::GetByName(arguments[0]);
894
895         String triggeredBy;
896         int triggeredByLegacy = Convert::ToLong(arguments[4]);
897         if (triggeredByLegacy != 0)
898                 triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
899
900         Log(LogInformation, "icinga", "Creating downtime for host " + host->GetName());
901         Service::Ptr service = host->GetHostCheckService();
902         if (service) {
903                 String comment_id = service->AddComment(CommentDowntime, arguments[6], arguments[7], Convert::ToDouble(arguments[2]));
904                 (void) service->AddDowntime(comment_id,
905                     Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
906                     Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
907         }
908 }
909
910 void ExternalCommandProcessor::DelHostDowntime(double, const std::vector<String>& arguments)
911 {
912         if (arguments.size() < 1)
913                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
914
915         int id = Convert::ToLong(arguments[0]);
916         Log(LogInformation, "icinga", "Removing downtime ID " + arguments[0]);
917         String rid = Service::GetDowntimeIDFromLegacyID(id);
918         Service::RemoveDowntime(rid);
919 }
920
921 void ExternalCommandProcessor::ScheduleHostSvcDowntime(double, const std::vector<String>& arguments)
922 {
923         if (arguments.size() < 8)
924                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 8 argument."));
925
926         Host::Ptr host = Host::GetByName(arguments[0]);
927
928         String triggeredBy;
929         int triggeredByLegacy = Convert::ToLong(arguments[4]);
930         if (triggeredByLegacy != 0)
931                 triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
932
933         BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
934                 Log(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
935                 String comment_id = service->AddComment(CommentDowntime, arguments[6], arguments[7], Convert::ToDouble(arguments[2]));
936                 (void) service->AddDowntime(comment_id,
937                     Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
938                     Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
939         }
940 }
941
942 void ExternalCommandProcessor::ScheduleHostgroupHostDowntime(double, const std::vector<String>& arguments)
943 {
944         if (arguments.size() < 8)
945                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 8 arguments."));
946
947         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
948
949         String triggeredBy;
950         int triggeredByLegacy = Convert::ToLong(arguments[4]);
951         if (triggeredByLegacy != 0)
952                 triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
953
954         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
955                 Log(LogInformation, "icinga", "Creating downtime for host " + host->GetName());
956                 Service::Ptr service = host->GetHostCheckService();
957                 if (service) {
958                         String comment_id = service->AddComment(CommentDowntime, arguments[6], arguments[7], Convert::ToDouble(arguments[2]));
959                         (void) service->AddDowntime(comment_id,
960                             Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
961                             Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
962                 }
963         }
964 }
965
966 void ExternalCommandProcessor::ScheduleHostgroupSvcDowntime(double, const std::vector<String>& arguments)
967 {
968         if (arguments.size() < 8)
969                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 8 arguments."));
970
971         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
972
973         String triggeredBy;
974         int triggeredByLegacy = Convert::ToLong(arguments[4]);
975         if (triggeredByLegacy != 0)
976                 triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
977
978         /* Note: we can't just directly create downtimes for all the services by iterating
979          * over all hosts in the host group - otherwise we might end up creating multiple
980          * downtimes for some services. */
981
982         std::set<Service::Ptr> services;
983
984         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
985                 BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
986                         services.insert(service);
987                 }
988         }
989
990         BOOST_FOREACH(const Service::Ptr& service, services) {
991                 Log(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
992                 String comment_id = service->AddComment(CommentDowntime, arguments[6], arguments[7], Convert::ToDouble(arguments[2]));
993                 (void) service->AddDowntime(comment_id,
994                     Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
995                     Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
996         }
997 }
998
999 void ExternalCommandProcessor::ScheduleServicegroupHostDowntime(double, const std::vector<String>& arguments)
1000 {
1001         if (arguments.size() < 8)
1002                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 8 arguments."));
1003
1004         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1005
1006         String triggeredBy;
1007         int triggeredByLegacy = Convert::ToLong(arguments[4]);
1008         if (triggeredByLegacy != 0)
1009                 triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
1010
1011         /* Note: we can't just directly create downtimes for all the hosts by iterating
1012          * over all services in the service group - otherwise we might end up creating multiple
1013          * downtimes for some hosts. */
1014
1015         std::set<Service::Ptr> services;
1016
1017         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
1018                 Host::Ptr host = service->GetHost();
1019                 Service::Ptr hcService = host->GetHostCheckService();
1020                 if (hcService)
1021                         services.insert(hcService);
1022         }
1023
1024         BOOST_FOREACH(const Service::Ptr& service, services) {
1025                 Log(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
1026                 String comment_id = service->AddComment(CommentDowntime, arguments[6], arguments[7], Convert::ToDouble(arguments[2]));
1027                 (void) service->AddDowntime(comment_id,
1028                     Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1029                     Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
1030         }
1031 }
1032
1033 void ExternalCommandProcessor::ScheduleServicegroupSvcDowntime(double, const std::vector<String>& arguments)
1034 {
1035         if (arguments.size() < 8)
1036                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 8 arguments."));
1037
1038         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1039
1040         String triggeredBy;
1041         int triggeredByLegacy = Convert::ToLong(arguments[4]);
1042         if (triggeredByLegacy != 0)
1043                 triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
1044
1045         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
1046                 Log(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
1047                 String comment_id = service->AddComment(CommentDowntime, arguments[6], arguments[7], Convert::ToDouble(arguments[2]));
1048                 (void) service->AddDowntime(comment_id,
1049                     Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
1050                     Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
1051         }
1052 }
1053
1054 void ExternalCommandProcessor::AddHostComment(double, const std::vector<String>& arguments)
1055 {
1056         if (arguments.size() < 4)
1057                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 4 arguments."));
1058
1059         Host::Ptr host = Host::GetByName(arguments[0]);
1060
1061         Log(LogInformation, "icinga", "Creating comment for host " + host->GetName());
1062         Service::Ptr service = host->GetHostCheckService();
1063         if (service)
1064                 (void) service->AddComment(CommentUser, arguments[2], arguments[3], 0);
1065 }
1066
1067 void ExternalCommandProcessor::DelHostComment(double, const std::vector<String>& arguments)
1068 {
1069         if (arguments.size() < 1)
1070                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
1071
1072         int id = Convert::ToLong(arguments[0]);
1073         Log(LogInformation, "icinga", "Removing comment ID " + arguments[0]);
1074         String rid = Service::GetCommentIDFromLegacyID(id);
1075         Service::RemoveComment(rid);
1076 }
1077
1078 void ExternalCommandProcessor::AddSvcComment(double, const std::vector<String>& arguments)
1079 {
1080         if (arguments.size() < 5)
1081                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 5 arguments."));
1082
1083         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1084
1085         Log(LogInformation, "icinga", "Creating comment for service " + service->GetName());
1086         (void) service->AddComment(CommentUser, arguments[3], arguments[4], 0);
1087 }
1088
1089 void ExternalCommandProcessor::DelSvcComment(double, const std::vector<String>& arguments)
1090 {
1091         if (arguments.size() < 1)
1092                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
1093
1094         int id = Convert::ToLong(arguments[0]);
1095         Log(LogInformation, "icinga", "Removing comment ID " + arguments[0]);
1096
1097         String rid = Service::GetCommentIDFromLegacyID(id);
1098         Service::RemoveComment(rid);
1099 }
1100
1101 void ExternalCommandProcessor::DelAllHostComments(double, const std::vector<String>& arguments)
1102 {
1103         if (arguments.size() < 1)
1104                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
1105
1106         Host::Ptr host = Host::GetByName(arguments[0]);
1107
1108         Log(LogInformation, "icinga", "Removing all comments for host " + host->GetName());
1109         Service::Ptr service = host->GetHostCheckService();
1110         if (service)
1111                 service->RemoveAllComments();
1112 }
1113
1114 void ExternalCommandProcessor::DelAllSvcComments(double, const std::vector<String>& arguments)
1115 {
1116         if (arguments.size() < 2)
1117                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
1118
1119         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1120
1121         Log(LogInformation, "icinga", "Removing all comments for service " + service->GetName());
1122         service->RemoveAllComments();
1123 }
1124
1125 void ExternalCommandProcessor::SendCustomHostNotification(double, const std::vector<String>& arguments)
1126 {
1127         if (arguments.size() < 4)
1128                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 4 arguments."));
1129
1130         Host::Ptr host = Host::GetByName(arguments[0]);
1131         int options = Convert::ToLong(arguments[1]);
1132
1133         Log(LogInformation, "icinga", "Sending custom notification for host " + host->GetName());
1134         Service::Ptr service = host->GetHostCheckService();
1135         if (service) {
1136                 if (options & 2) {
1137                         ObjectLock olock(service);
1138                         service->SetForceNextNotification(true);
1139                 }
1140
1141                 Service::OnNotificationsRequested(service, NotificationCustom, service->GetLastCheckResult(), arguments[2], arguments[3]);
1142         }
1143 }
1144
1145 void ExternalCommandProcessor::SendCustomSvcNotification(double, const std::vector<String>& arguments)
1146 {
1147         if (arguments.size() < 5)
1148                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 5 arguments."));
1149
1150         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1151         int options = Convert::ToLong(arguments[2]);
1152
1153         Log(LogInformation, "icinga", "Sending custom notification for service " + service->GetName());
1154
1155         if (options & 2) {
1156                 ObjectLock olock(service);
1157                 service->SetForceNextNotification(true);
1158         }
1159
1160         Service::OnNotificationsRequested(service, NotificationCustom, service->GetLastCheckResult(), arguments[3], arguments[4]);
1161 }
1162
1163 void ExternalCommandProcessor::DelayHostNotification(double, const std::vector<String>& arguments)
1164 {
1165         if (arguments.size() < 2)
1166                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
1167
1168         Host::Ptr host = Host::GetByName(arguments[0]);
1169
1170         Log(LogInformation, "icinga", "Delaying notifications for host " + host->GetName());
1171         Service::Ptr hc = host->GetHostCheckService();
1172         if (!hc)
1173                 return;
1174
1175         BOOST_FOREACH(const Notification::Ptr& notification, hc->GetNotifications()) {
1176                 ObjectLock olock(notification);
1177
1178                 notification->SetNextNotification(Convert::ToDouble(arguments[1]));
1179         }
1180 }
1181
1182 void ExternalCommandProcessor::DelaySvcNotification(double, const std::vector<String>& arguments)
1183 {
1184         if (arguments.size() < 3)
1185                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 3 arguments."));
1186
1187         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1188
1189         Log(LogInformation, "icinga", "Delaying notifications for service " + service->GetName());
1190
1191         BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
1192                 ObjectLock olock(notification);
1193
1194                 notification->SetNextNotification(Convert::ToDouble(arguments[2]));
1195         }
1196 }
1197
1198 void ExternalCommandProcessor::EnableHostNotifications(double, const std::vector<String>& arguments)
1199 {
1200         if (arguments.size() < 1)
1201                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
1202
1203         Host::Ptr host = Host::GetByName(arguments[0]);
1204
1205         Log(LogInformation, "icinga", "Enabling notifications for host '" + arguments[0] + "'");
1206         Service::Ptr hc = host->GetHostCheckService();
1207
1208         if (!hc)
1209                 return;
1210
1211         {
1212                 ObjectLock olock(hc);
1213
1214                 hc->SetEnableNotifications(true);
1215         }
1216 }
1217
1218 void ExternalCommandProcessor::DisableHostNotifications(double, const std::vector<String>& arguments)
1219 {
1220         if (arguments.size() < 1)
1221                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
1222
1223         Host::Ptr host = Host::GetByName(arguments[0]);
1224
1225         Log(LogInformation, "icinga", "Disabling notifications for host '" + arguments[0] + "'");
1226         Service::Ptr hc = host->GetHostCheckService();
1227
1228         if (!hc)
1229                 return;
1230
1231         {
1232                 ObjectLock olock(hc);
1233
1234                 hc->SetEnableNotifications(false);
1235         }
1236 }
1237
1238 void ExternalCommandProcessor::EnableSvcNotifications(double, const std::vector<String>& arguments)
1239 {
1240         if (arguments.size() < 2)
1241                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
1242
1243         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1244
1245         Log(LogInformation, "icinga", "Enabling notifications for service '" + arguments[1] + "'");
1246
1247         {
1248                 ObjectLock olock(service);
1249
1250                 service->SetEnableNotifications(true);
1251         }
1252 }
1253
1254 void ExternalCommandProcessor::DisableSvcNotifications(double, const std::vector<String>& arguments)
1255 {
1256         if (arguments.size() < 2)
1257                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
1258
1259         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1260
1261         Log(LogInformation, "icinga", "Disabling notifications for service '" + arguments[1] + "'");
1262
1263         {
1264                 ObjectLock olock(service);
1265
1266                 service->SetEnableNotifications(false);
1267         }
1268 }
1269
1270 void ExternalCommandProcessor::DisableHostgroupHostChecks(double, const std::vector<String>& arguments)
1271 {
1272         if (arguments.size() < 1)
1273                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 arguments."));
1274
1275         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
1276
1277         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
1278                 Service::Ptr hc = host->GetHostCheckService();
1279
1280                 if (!hc)
1281                         continue;
1282
1283                 Log(LogInformation, "icinga", "Disabling active checks for host '" + host->GetName() + "'");
1284
1285                 {
1286                         ObjectLock olock(hc);
1287
1288                         hc->SetEnableActiveChecks(false);
1289                 }
1290         }
1291 }
1292
1293 void ExternalCommandProcessor::DisableHostgroupPassiveHostChecks(double, const std::vector<String>& arguments)
1294 {
1295         if (arguments.size() < 1)
1296                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 arguments."));
1297
1298         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
1299
1300         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
1301                 Service::Ptr hc = host->GetHostCheckService();
1302
1303                 if (!hc)
1304                         continue;
1305
1306                 Log(LogInformation, "icinga", "Disabling active checks for host '" + host->GetName() + "'");
1307
1308                 {
1309                         ObjectLock olock(hc);
1310
1311                         hc->SetEnablePassiveChecks(false);
1312                 }
1313         }
1314 }
1315
1316 void ExternalCommandProcessor::DisableServicegroupHostChecks(double, const std::vector<String>& arguments)
1317 {
1318         if (arguments.size() < 1)
1319                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 arguments."));
1320
1321         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1322
1323         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
1324                 Host::Ptr host = service->GetHost();
1325
1326                 if (!host)
1327                         continue;
1328
1329                 Service::Ptr hc = host->GetHostCheckService();
1330
1331                 if (!hc)
1332                         continue;
1333
1334                 Log(LogInformation, "icinga", "Disabling active checks for host '" + host->GetName() + "'");
1335
1336                 {
1337                         ObjectLock olock(hc);
1338
1339                         hc->SetEnableActiveChecks(false);
1340                 }
1341         }
1342 }
1343
1344 void ExternalCommandProcessor::DisableServicegroupPassiveHostChecks(double, const std::vector<String>& arguments)
1345 {
1346         if (arguments.size() < 1)
1347                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 arguments."));
1348
1349         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1350
1351         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
1352                 Host::Ptr host = service->GetHost();
1353
1354                 if (!host)
1355                         continue;
1356
1357                 Service::Ptr hc = host->GetHostCheckService();
1358
1359                 if (!hc)
1360                         continue;
1361
1362                 Log(LogInformation, "icinga", "Disabling active checks for host '" + host->GetName() + "'");
1363
1364                 {
1365                         ObjectLock olock(hc);
1366
1367                         hc->SetEnablePassiveChecks(false);
1368                 }
1369         }
1370 }
1371
1372 void ExternalCommandProcessor::EnableHostgroupHostChecks(double, const std::vector<String>& arguments)
1373 {
1374         if (arguments.size() < 1)
1375                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 arguments."));
1376
1377         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
1378
1379         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
1380                 Service::Ptr hc = host->GetHostCheckService();
1381
1382                 if (!hc)
1383                         continue;
1384
1385                 Log(LogInformation, "icinga", "Enabling active checks for host '" + host->GetName() + "'");
1386
1387                 {
1388                         ObjectLock olock(hc);
1389
1390                         hc->SetEnableActiveChecks(true);
1391                 }
1392         }
1393 }
1394
1395 void ExternalCommandProcessor::EnableHostgroupPassiveHostChecks(double, const std::vector<String>& arguments)
1396 {
1397         if (arguments.size() < 1)
1398                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 arguments."));
1399
1400 }
1401
1402 void ExternalCommandProcessor::EnableServicegroupHostChecks(double, const std::vector<String>& arguments)
1403 {
1404         if (arguments.size() < 1)
1405                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 arguments."));
1406
1407         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1408
1409         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
1410                 Host::Ptr host = service->GetHost();
1411
1412                 if (!host)
1413                         continue;
1414
1415                 Service::Ptr hc = host->GetHostCheckService();
1416
1417                 if (!hc)
1418                         continue;
1419
1420                 Log(LogInformation, "icinga", "Enabling active checks for host '" + host->GetName() + "'");
1421
1422                 {
1423                         ObjectLock olock(hc);
1424
1425                         hc->SetEnableActiveChecks(true);
1426                 }
1427         }
1428 }
1429
1430 void ExternalCommandProcessor::EnableServicegroupPassiveHostChecks(double, const std::vector<String>& arguments)
1431 {
1432         if (arguments.size() < 1)
1433                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 arguments."));
1434
1435         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
1436
1437         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
1438                 Host::Ptr host = service->GetHost();
1439
1440                 if (!host)
1441                         continue;
1442
1443                 Service::Ptr hc = host->GetHostCheckService();
1444
1445                 if (!hc)
1446                         continue;
1447
1448                 Log(LogInformation, "icinga", "Enabling active checks for host '" + host->GetName() + "'");
1449
1450                 {
1451                         ObjectLock olock(hc);
1452
1453                         hc->SetEnablePassiveChecks(false);
1454                 }
1455         }
1456 }
1457
1458 void ExternalCommandProcessor::EnableHostFlapping(double, const std::vector<String>& arguments)
1459 {
1460         if (arguments.size() < 1)
1461                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
1462
1463         Host::Ptr host = Host::GetByName(arguments[0]);
1464
1465         Log(LogInformation, "icinga", "Enabling flapping detection for host '" + arguments[0] + "'");
1466         Service::Ptr hc = host->GetHostCheckService();
1467
1468         if (!hc)
1469                 return;
1470
1471         {
1472                 ObjectLock olock(hc);
1473
1474                 hc->SetEnableFlapping(true);
1475         }
1476 }
1477
1478 void ExternalCommandProcessor::DisableHostFlapping(double, const std::vector<String>& arguments)
1479 {
1480         if (arguments.size() < 1)
1481                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 1 argument."));
1482
1483         Host::Ptr host = Host::GetByName(arguments[0]);
1484
1485         Log(LogInformation, "icinga", "Disabling flapping detection for host '" + arguments[0] + "'");
1486         Service::Ptr hc = host->GetHostCheckService();
1487
1488         if (!hc)
1489                 return;
1490
1491         {
1492                 ObjectLock olock(hc);
1493
1494                 hc->SetEnableFlapping(false);
1495         }
1496 }
1497
1498 void ExternalCommandProcessor::EnableSvcFlapping(double, const std::vector<String>& arguments)
1499 {
1500         if (arguments.size() < 2)
1501                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
1502
1503         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1504
1505         Log(LogInformation, "icinga", "Enabling flapping detection for service '" + arguments[1] + "'");
1506
1507         {
1508                 ObjectLock olock(service);
1509
1510                 service->SetEnableFlapping(true);
1511         }
1512 }
1513
1514 void ExternalCommandProcessor::DisableSvcFlapping(double, const std::vector<String>& arguments)
1515 {
1516         if (arguments.size() < 2)
1517                 BOOST_THROW_EXCEPTION(std::invalid_argument("Expected 2 arguments."));
1518
1519         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
1520
1521         Log(LogInformation, "icinga", "Disabling flapping detection for service '" + arguments[1] + "'");
1522
1523         {
1524                 ObjectLock olock(service);
1525
1526                 service->SetEnableFlapping(false);
1527         }
1528 }