]> granicus.if.org Git - icinga2/blob - lib/icinga/externalcommandprocessor.cpp
Implement service shortnames.
[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 "i2-icinga.h"
21
22 using namespace icinga;
23
24 bool I2_EXPORT ExternalCommandProcessor::m_Initialized;
25 map<String, ExternalCommandProcessor::Callback> I2_EXPORT ExternalCommandProcessor::m_Commands;
26
27 void ExternalCommandProcessor::Execute(const String& line)
28 {
29         if (line.IsEmpty())
30                 return;
31
32         if (line[0] != '[')
33                 BOOST_THROW_EXCEPTION(invalid_argument("Missing timestamp in command: " + line));
34
35         size_t pos = line.FindFirstOf("]");
36
37         if (pos == String::NPos)
38                 BOOST_THROW_EXCEPTION(invalid_argument("Missing timestamp in command: " + line));
39
40         String timestamp = line.SubStr(1, pos - 1);
41         String args = line.SubStr(pos + 2, String::NPos);
42
43         double ts = Convert::ToDouble(timestamp);
44
45         if (ts == 0)
46                 BOOST_THROW_EXCEPTION(invalid_argument("Invalid timestamp in command: " + line));
47
48         vector<String> argv = args.Split(is_any_of(";"));
49
50         if (argv.size() == 0)
51                 BOOST_THROW_EXCEPTION(invalid_argument("Missing arguments in command: " + line));
52
53         vector<String> argvExtra(argv.begin() + 1, argv.end());
54         Execute(ts, argv[0], argvExtra);
55 }
56
57 void ExternalCommandProcessor::Execute(double time, const String& command, const vector<String>& arguments)
58 {
59         if (!m_Initialized) {
60                 RegisterCommand("PROCESS_SERVICE_CHECK_RESULT", &ExternalCommandProcessor::ProcessServiceCheckResult);
61                 RegisterCommand("SCHEDULE_SVC_CHECK", &ExternalCommandProcessor::ScheduleSvcCheck);
62                 RegisterCommand("SCHEDULE_FORCED_SVC_CHECK", &ExternalCommandProcessor::ScheduleForcedSvcCheck);
63                 RegisterCommand("ENABLE_SVC_CHECK", &ExternalCommandProcessor::EnableSvcCheck);
64                 RegisterCommand("DISABLE_SVC_CHECK", &ExternalCommandProcessor::DisableSvcCheck);
65                 RegisterCommand("SHUTDOWN_PROCESS", &ExternalCommandProcessor::ShutdownProcess);
66                 RegisterCommand("SCHEDULE_FORCED_HOST_SVC_CHECKS", &ExternalCommandProcessor::ScheduleForcedHostSvcChecks);
67                 RegisterCommand("SCHEDULE_HOST_SVC_CHECKS", &ExternalCommandProcessor::ScheduleHostSvcChecks);
68                 RegisterCommand("ENABLE_HOST_SVC_CHECKS", &ExternalCommandProcessor::EnableHostSvcChecks);
69                 RegisterCommand("DISABLE_HOST_SVC_CHECKS", &ExternalCommandProcessor::DisableHostSvcChecks);
70                 RegisterCommand("ACKNOWLEDGE_SVC_PROBLEM", &ExternalCommandProcessor::AcknowledgeSvcProblem);
71                 RegisterCommand("ACKNOWLEDGE_SVC_PROBLEM_EXPIRE", &ExternalCommandProcessor::AcknowledgeSvcProblemExpire);
72                 RegisterCommand("REMOVE_SVC_ACKNOWLEDGEMENT", &ExternalCommandProcessor::RemoveHostAcknowledgement);
73                 RegisterCommand("ACKNOWLEDGE_HOST_PROBLEM", &ExternalCommandProcessor::AcknowledgeHostProblem);
74                 RegisterCommand("ACKNOWLEDGE_HOST_PROBLEM_EXPIRE", &ExternalCommandProcessor::AcknowledgeHostProblemExpire);
75                 RegisterCommand("REMOVE_HOST_ACKNOWLEDGEMENT", &ExternalCommandProcessor::RemoveHostAcknowledgement);
76                 RegisterCommand("ENABLE_HOSTGROUP_SVC_CHECKS", &ExternalCommandProcessor::EnableHostgroupSvcChecks);
77                 RegisterCommand("DISABLE_HOSTGROUP_SVC_CHECKS", &ExternalCommandProcessor::DisableHostgroupSvcChecks);
78                 RegisterCommand("ENABLE_SERVICEGROUP_SVC_CHECKS", &ExternalCommandProcessor::EnableServicegroupSvcChecks);
79                 RegisterCommand("DISABLE_SERVICEGROUP_SVC_CHECKS", &ExternalCommandProcessor::DisableServicegroupSvcChecks);
80                 RegisterCommand("ENABLE_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::EnablePassiveSvcChecks);
81                 RegisterCommand("DISABLE_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::DisablePassiveSvcChecks);
82                 RegisterCommand("ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::EnableServicegroupPassiveSvcChecks);
83                 RegisterCommand("DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::DisableServicegroupPassiveSvcChecks);
84                 RegisterCommand("ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::EnableHostgroupPassiveSvcChecks);
85                 RegisterCommand("DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS", &ExternalCommandProcessor::DisableHostgroupPassiveSvcChecks);
86                 RegisterCommand("PROCESS_FILE", &ExternalCommandProcessor::ProcessFile);
87                 RegisterCommand("SCHEDULE_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleSvcDowntime);
88                 RegisterCommand("DEL_SVC_DOWNTIME", &ExternalCommandProcessor::DelSvcDowntime);
89                 RegisterCommand("SCHEDULE_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleHostDowntime);
90                 RegisterCommand("DEL_HOST_DOWNTIME", &ExternalCommandProcessor::DelHostDowntime);
91                 RegisterCommand("SCHEDULE_HOST_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleHostSvcDowntime);
92                 RegisterCommand("SCHEDULE_HOSTGROUP_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleHostgroupHostDowntime);
93                 RegisterCommand("SCHEDULE_HOSTGROUP_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleHostgroupSvcDowntime);
94                 RegisterCommand("SCHEDULE_SERVICEGROUP_HOST_DOWNTIME", &ExternalCommandProcessor::ScheduleServicegroupHostDowntime);
95                 RegisterCommand("SCHEDULE_SERVICEGROUP_SVC_DOWNTIME", &ExternalCommandProcessor::ScheduleServicegroupSvcDowntime);
96                 RegisterCommand("ADD_HOST_COMMENT", &ExternalCommandProcessor::AddHostComment);
97                 RegisterCommand("DEL_HOST_COMMENT", &ExternalCommandProcessor::DelHostComment);
98                 RegisterCommand("ADD_SVC_COMMENT", &ExternalCommandProcessor::AddSvcComment);
99                 RegisterCommand("DEL_SVC_COMMENT", &ExternalCommandProcessor::DelSvcComment);
100                 RegisterCommand("DEL_ALL_HOST_COMMENTS", &ExternalCommandProcessor::DelAllHostComments);
101                 RegisterCommand("DEL_ALL_SVC_COMMENTS", &ExternalCommandProcessor::DelAllSvcComments);
102
103                 m_Initialized = true;
104         }
105
106         map<String, ExternalCommandProcessor::Callback>::iterator it;
107         it = m_Commands.find(command);
108
109         if (it == m_Commands.end())
110                 BOOST_THROW_EXCEPTION(invalid_argument("The external command '" + command + "' does not exist."));
111
112         it->second(time, arguments);
113 }
114
115 void ExternalCommandProcessor::RegisterCommand(const String& command, const ExternalCommandProcessor::Callback& callback)
116 {
117         m_Commands[command] = callback;
118 }
119
120 void ExternalCommandProcessor::ProcessServiceCheckResult(double time, const vector<String>& arguments)
121 {
122         if (arguments.size() < 4)
123                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 4 arguments."));
124
125         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
126
127         if (!service->GetEnablePassiveChecks())
128                 BOOST_THROW_EXCEPTION(invalid_argument("Got passive check result for service '" + arguments[1] + "' which has passive checks disabled."));
129
130         int exitStatus = Convert::ToDouble(arguments[2]);
131         Dictionary::Ptr result = PluginCheckTask::ParseCheckOutput(arguments[3]);
132         result->Set("state", PluginCheckTask::ExitStatusToState(exitStatus));
133
134         result->Set("schedule_start", time);
135         result->Set("schedule_end", time);
136         result->Set("execution_start", time);
137         result->Set("execution_end", time);
138         result->Set("active", 0);
139
140         Logger::Write(LogInformation, "icinga", "Processing passive check result for service '" + arguments[1] + "'");
141         service->ProcessCheckResult(result);
142
143         /* Reschedule the next check. The side effect of this is that for as long
144          * as we receive passive results for a service we won't execute any
145          * active checks. */
146         service->SetNextCheck(Utility::GetTime() + service->GetCheckInterval());
147 }
148
149 void ExternalCommandProcessor::ScheduleSvcCheck(double, const vector<String>& arguments)
150 {
151         if (arguments.size() < 3)
152                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 3 arguments."));
153
154         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
155
156         double planned_check = Convert::ToDouble(arguments[2]);
157
158         if (planned_check > service->GetNextCheck()) {
159                 Logger::Write(LogInformation, "icinga", "Ignoring reschedule request for service '" +
160                     arguments[1] + "' (next check is already sooner than requested check time)");
161                 return;
162         }
163
164         Logger::Write(LogInformation, "icinga", "Rescheduling next check for service '" + arguments[1] + "'");
165         service->SetNextCheck(planned_check);
166 }
167
168 void ExternalCommandProcessor::ScheduleForcedSvcCheck(double, const vector<String>& arguments)
169 {
170         if (arguments.size() < 3)
171                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 3 arguments."));
172
173         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
174
175         Logger::Write(LogInformation, "icinga", "Rescheduling next check for service '" + arguments[1] + "'");
176         service->SetForceNextCheck(true);
177         service->SetNextCheck(Convert::ToDouble(arguments[2]));
178 }
179
180 void ExternalCommandProcessor::EnableSvcCheck(double, const vector<String>& arguments)
181 {
182         if (arguments.size() < 2)
183                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
184
185         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
186
187         Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + arguments[1] + "'");
188         service->SetEnableActiveChecks(true);
189 }
190
191 void ExternalCommandProcessor::DisableSvcCheck(double, const vector<String>& arguments)
192 {
193         if (arguments.size() < 2)
194                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
195
196         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
197
198         Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + arguments[1] + "'");
199         service->SetEnableActiveChecks(false);
200 }
201
202 void ExternalCommandProcessor::ShutdownProcess(double, const vector<String>&)
203 {
204         Logger::Write(LogInformation, "icinga", "Shutting down Icinga via external command.");
205         Application::RequestShutdown();
206 }
207
208 void ExternalCommandProcessor::ScheduleForcedHostSvcChecks(double, const vector<String>& arguments)
209 {
210         if (arguments.size() < 2)
211                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
212
213         if (!Host::Exists(arguments[0]))
214                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
215
216         double planned_check = Convert::ToDouble(arguments[1]);
217
218         Host::Ptr host = Host::GetByName(arguments[0]);
219
220         BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
221                 Logger::Write(LogInformation, "icinga", "Rescheduling next check for service '" + service->GetName() + "'");
222                 service->SetNextCheck(planned_check);
223                 service->SetForceNextCheck(true);
224         }
225 }
226
227 void ExternalCommandProcessor::ScheduleHostSvcChecks(double, const vector<String>& arguments)
228 {
229         if (arguments.size() < 2)
230                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
231
232         if (!Host::Exists(arguments[0]))
233                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
234
235         double planned_check = Convert::ToDouble(arguments[1]);
236
237         Host::Ptr host = Host::GetByName(arguments[0]);
238
239         BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
240                 if (planned_check > service->GetNextCheck()) {
241                         Logger::Write(LogInformation, "icinga", "Ignoring reschedule request for service '" +
242                             service->GetName() + "' (next check is already sooner than requested check time)");
243                         continue;
244                 }
245
246                 Logger::Write(LogInformation, "icinga", "Rescheduling next check for service '" + service->GetName() + "'");
247                 service->SetNextCheck(planned_check);
248         }
249 }
250
251 void ExternalCommandProcessor::EnableHostSvcChecks(double, const vector<String>& arguments)
252 {
253         if (arguments.size() < 1)
254                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
255
256         if (!Host::Exists(arguments[0]))
257                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
258
259         Host::Ptr host = Host::GetByName(arguments[0]);
260
261         BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
262                 Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
263                 service->SetEnableActiveChecks(true);
264         }
265 }
266
267 void ExternalCommandProcessor::DisableHostSvcChecks(double, const vector<String>& arguments)
268 {
269         if (arguments.size() < 1)
270                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 arguments."));
271
272         if (!Host::Exists(arguments[0]))
273                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
274
275         Host::Ptr host = Host::GetByName(arguments[0]);
276
277         BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
278                 Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
279                 service->SetEnableActiveChecks(false);
280         }
281 }
282
283 void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const vector<String>& arguments)
284 {
285         if (arguments.size() < 7)
286                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 7 arguments."));
287
288         if (!Service::Exists(arguments[1]))
289                 BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
290
291         bool sticky = Convert::ToBool(arguments[2]);
292
293         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
294
295         if (service->GetState() == StateOK)
296                 BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' is OK."));
297
298         Logger::Write(LogInformation, "icinga", "Setting acknowledgement for service '" + service->GetName() + "'");
299         service->SetAcknowledgement(sticky ? AcknowledgementSticky : AcknowledgementNormal);
300         service->SetAcknowledgementExpiry(0);
301 }
302
303 void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const vector<String>& arguments)
304 {
305         if (arguments.size() < 8)
306                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 8 arguments."));
307
308         if (!Service::Exists(arguments[1]))
309                 BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
310
311         bool sticky = Convert::ToBool(arguments[2]);
312         double timestamp = Convert::ToDouble(arguments[5]);
313
314         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
315
316         if (service->GetState() == StateOK)
317                 BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' is OK."));
318
319         Logger::Write(LogInformation, "icinga", "Setting timed acknowledgement for service '" + service->GetName() + "'");
320         service->SetAcknowledgement(sticky ? AcknowledgementSticky : AcknowledgementNormal);
321         service->SetAcknowledgementExpiry(timestamp);
322 }
323
324 void ExternalCommandProcessor::RemoveSvcAcknowledgement(double, const vector<String>& arguments)
325 {
326         if (arguments.size() < 2)
327                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
328
329         if (!Service::Exists(arguments[1]))
330                 BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
331
332         Service::Ptr service = Service::GetByName(arguments[1]);
333
334         Logger::Write(LogInformation, "icinga", "Removing acknowledgement for service '" + service->GetName() + "'");
335         service->SetAcknowledgement(AcknowledgementNone);
336         service->SetAcknowledgementExpiry(0);
337 }
338
339 void ExternalCommandProcessor::AcknowledgeHostProblem(double, const vector<String>& arguments)
340 {
341         if (arguments.size() < 6)
342                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 6 arguments."));
343
344         if (!Host::Exists(arguments[0]))
345                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
346
347         bool sticky = Convert::ToBool(arguments[0]);
348
349         Host::Ptr host = Host::GetByName(arguments[0]);
350
351         if (host->IsUp())
352                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' is OK."));
353
354         Logger::Write(LogInformation, "icinga", "Setting acknowledgement for host '" + host->GetName() + "'");
355         host->SetAcknowledgement(sticky ? AcknowledgementSticky : AcknowledgementNormal);
356         host->SetAcknowledgementExpiry(0);
357 }
358
359 void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const vector<String>& arguments)
360 {
361         if (arguments.size() < 7)
362                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 7 arguments."));
363
364         if (!Host::Exists(arguments[0]))
365                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
366
367         bool sticky = Convert::ToBool(arguments[1]);
368         double timestamp = Convert::ToDouble(arguments[4]);
369
370         Host::Ptr host = Host::GetByName(arguments[0]);
371
372         if (host->IsUp())
373                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' is OK."));
374
375         Logger::Write(LogInformation, "icinga", "Setting timed acknowledgement for host '" + host->GetName() + "'");
376         host->SetAcknowledgement(sticky ? AcknowledgementSticky : AcknowledgementNormal);
377         host->SetAcknowledgementExpiry(timestamp);
378 }
379
380 void ExternalCommandProcessor::RemoveHostAcknowledgement(double, const vector<String>& arguments)
381 {
382         if (arguments.size() < 1)
383                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
384
385         if (!Host::Exists(arguments[0]))
386                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
387
388         Host::Ptr host = Host::GetByName(arguments[0]);
389
390         Logger::Write(LogInformation, "icinga", "Removing acknowledgement for host '" + host->GetName() + "'");
391         host->SetAcknowledgement(AcknowledgementNone);
392         host->SetAcknowledgementExpiry(0);
393 }
394
395 void ExternalCommandProcessor::EnableHostgroupSvcChecks(double, const vector<String>& arguments)
396 {
397         if (arguments.size() < 1)
398                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
399
400         if (!HostGroup::Exists(arguments[0]))
401                 BOOST_THROW_EXCEPTION(invalid_argument("The host group '" + arguments[0] + "' does not exist."));
402
403         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
404
405         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
406                 BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
407                         Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
408                         service->SetEnableActiveChecks(true);
409                 }
410         }
411 }
412
413 void ExternalCommandProcessor::DisableHostgroupSvcChecks(double, const vector<String>& arguments)
414 {
415         if (arguments.size() < 1)
416                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
417
418         if (!HostGroup::Exists(arguments[0]))
419                 BOOST_THROW_EXCEPTION(invalid_argument("The host group '" + arguments[0] + "' does not exist."));
420
421         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
422
423         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
424                 BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
425                         Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
426                         service->SetEnableActiveChecks(false);
427                 }
428         }
429 }
430
431 void ExternalCommandProcessor::EnableServicegroupSvcChecks(double, const vector<String>& arguments)
432 {
433         if (arguments.size() < 1)
434                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
435
436         if (!ServiceGroup::Exists(arguments[0]))
437                 BOOST_THROW_EXCEPTION(invalid_argument("The service group '" + arguments[0] + "' does not exist."));
438
439         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
440
441         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
442                 Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
443                 service->SetEnableActiveChecks(true);
444         }
445 }
446
447 void ExternalCommandProcessor::DisableServicegroupSvcChecks(double, const vector<String>& arguments)
448 {
449         if (arguments.size() < 1)
450                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
451
452         if (!ServiceGroup::Exists(arguments[0]))
453                 BOOST_THROW_EXCEPTION(invalid_argument("The service group '" + arguments[0] + "' does not exist."));
454
455         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
456
457         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
458                 Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
459                 service->SetEnableActiveChecks(false);
460         }
461 }
462
463 void ExternalCommandProcessor::EnablePassiveSvcChecks(double, const vector<String>& arguments)
464 {
465         if (arguments.size() < 2)
466                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
467
468         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
469
470         Logger::Write(LogInformation, "icinga", "Enabling passive checks for service '" + arguments[1] + "'");
471         service->SetEnablePassiveChecks(true);
472 }
473
474 void ExternalCommandProcessor::DisablePassiveSvcChecks(double, const vector<String>& arguments)
475 {
476         if (arguments.size() < 2)
477                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
478
479         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
480
481         Logger::Write(LogInformation, "icinga", "Disabling passive checks for service '" + arguments[1] + "'");
482         service->SetEnablePassiveChecks(false);
483 }
484
485 void ExternalCommandProcessor::EnableServicegroupPassiveSvcChecks(double, const vector<String>& arguments)
486 {
487         if (arguments.size() < 1)
488                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
489
490         if (!ServiceGroup::Exists(arguments[0]))
491                 BOOST_THROW_EXCEPTION(invalid_argument("The service group '" + arguments[0] + "' does not exist."));
492
493         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
494
495         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
496                 Logger::Write(LogInformation, "icinga", "Enabling passive checks for service '" + service->GetName() + "'");
497                 service->SetEnablePassiveChecks(true);
498         }
499 }
500
501 void ExternalCommandProcessor::DisableServicegroupPassiveSvcChecks(double, const vector<String>& arguments)
502 {
503         if (arguments.size() < 1)
504                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
505
506         if (!ServiceGroup::Exists(arguments[0]))
507                 BOOST_THROW_EXCEPTION(invalid_argument("The service group '" + arguments[0] + "' does not exist."));
508
509         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
510
511         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
512                 Logger::Write(LogInformation, "icinga", "Disabling passive checks for service '" + service->GetName() + "'");
513                 service->SetEnablePassiveChecks(true);
514         }
515 }
516
517 void ExternalCommandProcessor::EnableHostgroupPassiveSvcChecks(double, const vector<String>& arguments)
518 {
519         if (arguments.size() < 1)
520                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
521
522         if (!HostGroup::Exists(arguments[0]))
523                 BOOST_THROW_EXCEPTION(invalid_argument("The host group '" + arguments[0] + "' does not exist."));
524
525         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
526
527         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
528                 BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
529                         Logger::Write(LogInformation, "icinga", "Enabling passive checks for service '" + service->GetName() + "'");
530                         service->SetEnablePassiveChecks(true);
531                 }
532         }
533 }
534
535 void ExternalCommandProcessor::DisableHostgroupPassiveSvcChecks(double, const vector<String>& arguments)
536 {
537         if (arguments.size() < 1)
538                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
539
540         if (!HostGroup::Exists(arguments[0]))
541                 BOOST_THROW_EXCEPTION(invalid_argument("The host group '" + arguments[0] + "' does not exist."));
542
543         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
544
545         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
546                 BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
547                         Logger::Write(LogInformation, "icinga", "Disabling passive checks for service '" + service->GetName() + "'");
548                         service->SetEnablePassiveChecks(false);
549                 }
550         }
551 }
552
553 void ExternalCommandProcessor::ProcessFile(double, const vector<String>& arguments)
554 {
555         if (arguments.size() < 2)
556                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
557
558         String file = arguments[0];
559         bool del = Convert::ToBool(arguments[1]);
560
561         ifstream ifp;
562         ifp.exceptions(ifstream::badbit);
563
564         ifp.open(file.CStr(), ifstream::in);
565
566         while(ifp.good()) {
567                 std::string line;
568                 std::getline(ifp, line);
569
570                 try {
571                         Logger::Write(LogInformation, "compat", "Executing external command: " + line);
572
573                         Execute(line);
574                 } catch (const exception& ex) {
575                         stringstream msgbuf;
576                         msgbuf << "External command failed: " << diagnostic_information(ex);
577                         Logger::Write(LogWarning, "icinga", msgbuf.str());
578                 }
579         }
580
581         ifp.close();
582
583         if (del)
584                 (void) unlink(file.CStr());
585 }
586
587 void ExternalCommandProcessor::ScheduleSvcDowntime(double, const vector<String>& arguments)
588 {
589         if (arguments.size() < 9)
590                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 9 arguments."));
591
592         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
593
594         String triggeredBy;
595         int triggeredByLegacy = Convert::ToLong(arguments[5]);
596         if (triggeredByLegacy != 0)
597                 triggeredBy = DowntimeProcessor::GetIDFromLegacyID(triggeredByLegacy);
598
599         Logger::Write(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
600         (void) DowntimeProcessor::AddDowntime(service, arguments[7], arguments[8],
601             Convert::ToDouble(arguments[2]), Convert::ToDouble(arguments[3]),
602             Convert::ToBool(arguments[4]), triggeredBy, Convert::ToDouble(arguments[6]));
603 }
604
605 void ExternalCommandProcessor::DelSvcDowntime(double, const vector<String>& arguments)
606 {
607         if (arguments.size() < 1)
608                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
609
610         int id = Convert::ToLong(arguments[0]);
611         Logger::Write(LogInformation, "icinga", "Removing downtime ID " + arguments[0]);
612         String rid = DowntimeProcessor::GetIDFromLegacyID(id);
613         DowntimeProcessor::RemoveDowntime(rid);
614 }
615
616 void ExternalCommandProcessor::ScheduleHostDowntime(double, const vector<String>& arguments)
617 {
618         if (arguments.size() < 8)
619                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 8 arguments."));
620
621         if (!Host::Exists(arguments[0]))
622                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
623
624         Host::Ptr host = Host::GetByName(arguments[0]);
625
626         String triggeredBy;
627         int triggeredByLegacy = Convert::ToLong(arguments[4]);
628         if (triggeredByLegacy != 0)
629                 triggeredBy = DowntimeProcessor::GetIDFromLegacyID(triggeredByLegacy);
630
631         Logger::Write(LogInformation, "icinga", "Creating downtime for host " + host->GetName());
632         (void) DowntimeProcessor::AddDowntime(host, arguments[6], arguments[7],
633             Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
634             Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
635 }
636
637 void ExternalCommandProcessor::DelHostDowntime(double, const vector<String>& arguments)
638 {
639         if (arguments.size() < 1)
640                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
641
642         int id = Convert::ToLong(arguments[0]);
643         Logger::Write(LogInformation, "icinga", "Removing downtime ID " + arguments[0]);
644         String rid = DowntimeProcessor::GetIDFromLegacyID(id);
645         DowntimeProcessor::RemoveDowntime(rid);
646 }
647
648 void ExternalCommandProcessor::ScheduleHostSvcDowntime(double, const vector<String>& arguments)
649 {
650         if (arguments.size() < 8)
651                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 8 argument."));
652
653         if (!Host::Exists(arguments[0]))
654                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
655
656         Host::Ptr host = Host::GetByName(arguments[0]);
657
658         String triggeredBy;
659         int triggeredByLegacy = Convert::ToLong(arguments[4]);
660         if (triggeredByLegacy != 0)
661                 triggeredBy = DowntimeProcessor::GetIDFromLegacyID(triggeredByLegacy);
662
663         Logger::Write(LogInformation, "icinga", "Creating downtime for host " + host->GetName());
664         (void) DowntimeProcessor::AddDowntime(host, arguments[6], arguments[7],
665             Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
666             Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
667
668         BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
669                 Logger::Write(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
670                 (void) DowntimeProcessor::AddDowntime(service, arguments[6], arguments[7],
671                     Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
672                     Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
673         }
674 }
675
676 void ExternalCommandProcessor::ScheduleHostgroupHostDowntime(double, const vector<String>& arguments)
677 {
678         if (arguments.size() < 8)
679                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 8 arguments."));
680
681         if (!HostGroup::Exists(arguments[0]))
682                 BOOST_THROW_EXCEPTION(invalid_argument("The host group '" + arguments[0] + "' does not exist."));
683
684         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
685
686         String triggeredBy;
687         int triggeredByLegacy = Convert::ToLong(arguments[4]);
688         if (triggeredByLegacy != 0)
689                 triggeredBy = DowntimeProcessor::GetIDFromLegacyID(triggeredByLegacy);
690
691         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
692                 Logger::Write(LogInformation, "icinga", "Creating downtime for host " + host->GetName());
693                 (void) DowntimeProcessor::AddDowntime(host, arguments[6], arguments[7],
694                     Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
695                     Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
696         }
697 }
698
699 void ExternalCommandProcessor::ScheduleHostgroupSvcDowntime(double, const vector<String>& arguments)
700 {
701         if (arguments.size() < 8)
702                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 8 arguments."));
703
704         if (!HostGroup::Exists(arguments[0]))
705                 BOOST_THROW_EXCEPTION(invalid_argument("The host group '" + arguments[0] + "' does not exist."));
706
707         HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
708
709         String triggeredBy;
710         int triggeredByLegacy = Convert::ToLong(arguments[4]);
711         if (triggeredByLegacy != 0)
712                 triggeredBy = DowntimeProcessor::GetIDFromLegacyID(triggeredByLegacy);
713
714         /* Note: we can't just directly create downtimes for all the services by iterating
715          * over all hosts in the host group - otherwise we might end up creating multiple
716          * downtimes for some services. */
717
718         set<Service::Ptr> services;
719
720         BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
721                 BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
722                         services.insert(service);
723                 }
724         }
725
726         BOOST_FOREACH(const Service::Ptr& service, services) {
727                 Logger::Write(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
728                 (void) DowntimeProcessor::AddDowntime(service, arguments[6], arguments[7],
729                     Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
730                     Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
731         }
732 }
733
734 void ExternalCommandProcessor::ScheduleServicegroupHostDowntime(double, const vector<String>& arguments)
735 {
736         if (arguments.size() < 8)
737                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 8 arguments."));
738
739         if (!ServiceGroup::Exists(arguments[0]))
740                 BOOST_THROW_EXCEPTION(invalid_argument("The host group '" + arguments[0] + "' does not exist."));
741
742         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
743
744         String triggeredBy;
745         int triggeredByLegacy = Convert::ToLong(arguments[4]);
746         if (triggeredByLegacy != 0)
747                 triggeredBy = DowntimeProcessor::GetIDFromLegacyID(triggeredByLegacy);
748
749         /* Note: we can't just directly create downtimes for all the hosts by iterating
750          * over all services in the service group - otherwise we might end up creating multiple
751          * downtimes for some hosts. */
752
753         set<Host::Ptr> hosts;
754
755         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
756                 hosts.insert(service->GetHost());
757         }
758
759         BOOST_FOREACH(const Host::Ptr& host, hosts) {
760                 Logger::Write(LogInformation, "icinga", "Creating downtime for host " + host->GetName());
761                 (void) DowntimeProcessor::AddDowntime(host, arguments[6], arguments[7],
762                     Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
763                     Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
764         }
765 }
766
767 void ExternalCommandProcessor::ScheduleServicegroupSvcDowntime(double, const vector<String>& arguments)
768 {
769         if (arguments.size() < 8)
770                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 8 arguments."));
771
772         if (!ServiceGroup::Exists(arguments[0]))
773                 BOOST_THROW_EXCEPTION(invalid_argument("The host group '" + arguments[0] + "' does not exist."));
774
775         ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
776
777         String triggeredBy;
778         int triggeredByLegacy = Convert::ToLong(arguments[4]);
779         if (triggeredByLegacy != 0)
780                 triggeredBy = DowntimeProcessor::GetIDFromLegacyID(triggeredByLegacy);
781
782         BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
783                 Logger::Write(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
784                 (void) DowntimeProcessor::AddDowntime(service, arguments[6], arguments[7],
785                     Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
786                     Convert::ToBool(arguments[3]), triggeredBy, Convert::ToDouble(arguments[5]));
787         }
788 }
789
790 void ExternalCommandProcessor::AddHostComment(double, const vector<String>& arguments)
791 {
792         if (arguments.size() < 4)
793                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 4 arguments."));
794
795         if (!Host::Exists(arguments[0]))
796                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
797
798         Host::Ptr host = Host::GetByName(arguments[0]);
799
800         Logger::Write(LogInformation, "icinga", "Creating comment for host " + host->GetName());
801         (void) CommentProcessor::AddComment(host, Comment_User, arguments[2], arguments[3], 0);
802 }
803
804 void ExternalCommandProcessor::DelHostComment(double, const vector<String>& arguments)
805 {
806         if (arguments.size() < 1)
807                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
808
809         int id = Convert::ToLong(arguments[0]);
810         Logger::Write(LogInformation, "icinga", "Removing comment ID " + arguments[0]);
811         String rid = CommentProcessor::GetIDFromLegacyID(id);
812         CommentProcessor::RemoveComment(rid);
813 }
814
815 void ExternalCommandProcessor::AddSvcComment(double, const vector<String>& arguments)
816 {
817         if (arguments.size() < 5)
818                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 5 arguments."));
819
820         if (!Service::Exists(arguments[1]))
821                 BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
822
823         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
824
825         Logger::Write(LogInformation, "icinga", "Creating comment for service " + service->GetName());
826         (void) CommentProcessor::AddComment(service, Comment_User, arguments[3], arguments[4], 0);
827 }
828
829 void ExternalCommandProcessor::DelSvcComment(double, const vector<String>& arguments)
830 {
831         if (arguments.size() < 1)
832                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
833
834         int id = Convert::ToLong(arguments[0]);
835         Logger::Write(LogInformation, "icinga", "Removing comment ID " + arguments[0]);
836
837         String rid = CommentProcessor::GetIDFromLegacyID(id);
838         CommentProcessor::RemoveComment(rid);
839 }
840
841 void ExternalCommandProcessor::DelAllHostComments(double, const vector<String>& arguments)
842 {
843         if (arguments.size() < 1)
844                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 1 argument."));
845
846         if (!Host::Exists(arguments[0]))
847                 BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' does not exist."));
848
849         Host::Ptr host = Host::GetByName(arguments[0]);
850
851         Logger::Write(LogInformation, "icinga", "Removing all comments for host " + host->GetName());
852         CommentProcessor::RemoveAllComments(host);
853 }
854
855 void ExternalCommandProcessor::DelAllSvcComments(double, const vector<String>& arguments)
856 {
857         if (arguments.size() < 2)
858                 BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
859
860         if (!Service::Exists(arguments[1]))
861                 BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
862
863         Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
864
865         Logger::Write(LogInformation, "icinga", "Removing all comments for service " + service->GetName());
866         CommentProcessor::RemoveAllComments(service);
867 }