1 /******************************************************************************
3 * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
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. *
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. *
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 ******************************************************************************/
20 #include "icinga/clusterevents.hpp"
21 #include "icinga/service.hpp"
22 #include "remote/apilistener.hpp"
23 #include "remote/endpoint.hpp"
24 #include "remote/messageorigin.hpp"
25 #include "remote/zone.hpp"
26 #include "remote/apifunction.hpp"
27 #include "remote/eventqueue.hpp"
28 #include "base/application.hpp"
29 #include "base/configtype.hpp"
30 #include "base/utility.hpp"
31 #include "base/perfdatavalue.hpp"
32 #include "base/exception.hpp"
33 #include "base/initialize.hpp"
34 #include "base/serializer.hpp"
35 #include "base/json.hpp"
38 using namespace icinga;
40 INITIALIZE_ONCE(&ClusterEvents::StaticInitialize);
42 REGISTER_APIFUNCTION(CheckResult, event, &ClusterEvents::CheckResultAPIHandler);
43 REGISTER_APIFUNCTION(SetNextCheck, event, &ClusterEvents::NextCheckChangedAPIHandler);
44 REGISTER_APIFUNCTION(SetNextNotification, event, &ClusterEvents::NextNotificationChangedAPIHandler);
45 REGISTER_APIFUNCTION(SetForceNextCheck, event, &ClusterEvents::ForceNextCheckChangedAPIHandler);
46 REGISTER_APIFUNCTION(SetForceNextNotification, event, &ClusterEvents::ForceNextNotificationChangedAPIHandler);
47 REGISTER_APIFUNCTION(SetAcknowledgement, event, &ClusterEvents::AcknowledgementSetAPIHandler);
48 REGISTER_APIFUNCTION(ClearAcknowledgement, event, &ClusterEvents::AcknowledgementClearedAPIHandler);
49 REGISTER_APIFUNCTION(ExecuteCommand, event, &ClusterEvents::ExecuteCommandAPIHandler);
50 REGISTER_APIFUNCTION(SendNotifications, event, &ClusterEvents::SendNotificationsAPIHandler);
51 REGISTER_APIFUNCTION(NotificationSentUser, event, &ClusterEvents::NotificationSentUserAPIHandler);
52 REGISTER_APIFUNCTION(NotificationSentToAllUsers, event, &ClusterEvents::NotificationSentToAllUsersAPIHandler);
54 void ClusterEvents::StaticInitialize(void)
56 Checkable::OnNewCheckResult.connect(&ClusterEvents::CheckResultHandler);
57 Checkable::OnNextCheckChanged.connect(&ClusterEvents::NextCheckChangedHandler);
58 Notification::OnNextNotificationChanged.connect(&ClusterEvents::NextNotificationChangedHandler);
59 Checkable::OnForceNextCheckChanged.connect(&ClusterEvents::ForceNextCheckChangedHandler);
60 Checkable::OnForceNextNotificationChanged.connect(&ClusterEvents::ForceNextNotificationChangedHandler);
61 Checkable::OnNotificationsRequested.connect(&ClusterEvents::SendNotificationsHandler);
62 Checkable::OnNotificationSentToUser.connect(&ClusterEvents::NotificationSentUserHandler);
63 Checkable::OnNotificationSentToAllUsers.connect(&ClusterEvents::NotificationSentToAllUsersHandler);
65 Checkable::OnAcknowledgementSet.connect(&ClusterEvents::AcknowledgementSetHandler);
66 Checkable::OnAcknowledgementCleared.connect(&ClusterEvents::AcknowledgementClearedHandler);
69 Dictionary::Ptr ClusterEvents::MakeCheckResultMessage(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
71 Dictionary::Ptr message = new Dictionary();
72 message->Set("jsonrpc", "2.0");
73 message->Set("method", "event::CheckResult");
77 tie(host, service) = GetHostService(checkable);
79 Dictionary::Ptr params = new Dictionary();
80 params->Set("host", host->GetName());
82 params->Set("service", service->GetShortName());
84 Value agent_service_name = checkable->GetExtension("agent_service_name");
86 if (!agent_service_name.IsEmpty())
87 params->Set("service", agent_service_name);
89 params->Set("cr", Serialize(cr));
91 message->Set("params", params);
96 void ClusterEvents::CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, const MessageOrigin::Ptr& origin)
98 ApiListener::Ptr listener = ApiListener::GetInstance();
103 Dictionary::Ptr message = MakeCheckResultMessage(checkable, cr);
104 listener->RelayMessage(origin, checkable, message, true);
107 Value ClusterEvents::CheckResultAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
109 Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
112 Log(LogNotice, "ClusterEvents")
113 << "Discarding 'check result' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
123 if (params->Contains("cr")) {
124 cr = new CheckResult();
125 Dictionary::Ptr vcr = params->Get("cr");
127 if (vcr && vcr->Contains("performance_data")) {
128 vperf = vcr->Get("performance_data");
131 vcr->Remove("performance_data");
133 Deserialize(cr, vcr, true);
140 Array::Ptr rperf = new Array();
143 ObjectLock olock(vperf);
144 for (const Value& vp : vperf) {
147 if (vp.IsObjectType<Dictionary>()) {
148 PerfdataValue::Ptr val = new PerfdataValue();
149 Deserialize(val, vp, true);
156 cr->SetPerformanceData(rperf);
158 Host::Ptr host = Host::GetByName(params->Get("host"));
163 Checkable::Ptr checkable;
165 if (params->Contains("service"))
166 checkable = host->GetServiceByShortName(params->Get("service"));
173 if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable) && endpoint != checkable->GetCommandEndpoint()) {
174 Log(LogNotice, "ClusterEvents")
175 << "Discarding 'check result' message for checkable '" << checkable->GetName()
176 << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
180 if (!checkable->IsPaused() && Zone::GetLocalZone() == checkable->GetZone() && endpoint == checkable->GetCommandEndpoint())
181 checkable->ProcessCheckResult(cr);
183 checkable->ProcessCheckResult(cr, origin);
188 void ClusterEvents::NextCheckChangedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin)
190 ApiListener::Ptr listener = ApiListener::GetInstance();
196 Service::Ptr service;
197 tie(host, service) = GetHostService(checkable);
199 Dictionary::Ptr params = new Dictionary();
200 params->Set("host", host->GetName());
202 params->Set("service", service->GetShortName());
203 params->Set("next_check", checkable->GetNextCheck());
205 Dictionary::Ptr message = new Dictionary();
206 message->Set("jsonrpc", "2.0");
207 message->Set("method", "event::SetNextCheck");
208 message->Set("params", params);
210 listener->RelayMessage(origin, checkable, message, true);
213 Value ClusterEvents::NextCheckChangedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
215 Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
218 Log(LogNotice, "ClusterEvents")
219 << "Discarding 'next check changed' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
226 Host::Ptr host = Host::GetByName(params->Get("host"));
231 Checkable::Ptr checkable;
233 if (params->Contains("service"))
234 checkable = host->GetServiceByShortName(params->Get("service"));
241 if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) {
242 Log(LogNotice, "ClusterEvents")
243 << "Discarding 'next check changed' message for checkable '" << checkable->GetName()
244 << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
248 double nextCheck = params->Get("next_check");
250 if (nextCheck < Application::GetStartTime() + 60)
253 checkable->SetNextCheck(params->Get("next_check"), false, origin);
258 void ClusterEvents::NextNotificationChangedHandler(const Notification::Ptr& notification, const MessageOrigin::Ptr& origin)
260 ApiListener::Ptr listener = ApiListener::GetInstance();
265 Dictionary::Ptr params = new Dictionary();
266 params->Set("notification", notification->GetName());
267 params->Set("next_notification", notification->GetNextNotification());
269 Dictionary::Ptr message = new Dictionary();
270 message->Set("jsonrpc", "2.0");
271 message->Set("method", "event::SetNextNotification");
272 message->Set("params", params);
274 listener->RelayMessage(origin, notification, message, true);
277 Value ClusterEvents::NextNotificationChangedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
279 Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
282 Log(LogNotice, "ClusterEvents")
283 << "Discarding 'next notification changed' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
290 Notification::Ptr notification = Notification::GetByName(params->Get("notification"));
295 if (origin->FromZone && !origin->FromZone->CanAccessObject(notification)) {
296 Log(LogNotice, "ClusterEvents")
297 << "Discarding 'next notification changed' message for notification '" << notification->GetName()
298 << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
302 double nextNotification = params->Get("next_notification");
304 if (nextNotification < Utility::GetTime())
307 notification->SetNextNotification(nextNotification, false, origin);
312 void ClusterEvents::ForceNextCheckChangedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin)
314 ApiListener::Ptr listener = ApiListener::GetInstance();
320 Service::Ptr service;
321 tie(host, service) = GetHostService(checkable);
323 Dictionary::Ptr params = new Dictionary();
324 params->Set("host", host->GetName());
326 params->Set("service", service->GetShortName());
327 params->Set("forced", checkable->GetForceNextCheck());
329 Dictionary::Ptr message = new Dictionary();
330 message->Set("jsonrpc", "2.0");
331 message->Set("method", "event::SetForceNextCheck");
332 message->Set("params", params);
334 listener->RelayMessage(origin, checkable, message, true);
337 Value ClusterEvents::ForceNextCheckChangedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
339 Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
342 Log(LogNotice, "ClusterEvents")
343 << "Discarding 'force next check changed' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
350 Host::Ptr host = Host::GetByName(params->Get("host"));
355 Checkable::Ptr checkable;
357 if (params->Contains("service"))
358 checkable = host->GetServiceByShortName(params->Get("service"));
365 if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) {
366 Log(LogNotice, "ClusterEvents")
367 << "Discarding 'force next check' message for checkable '" << checkable->GetName()
368 << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
372 checkable->SetForceNextCheck(params->Get("forced"), false, origin);
377 void ClusterEvents::ForceNextNotificationChangedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin)
379 ApiListener::Ptr listener = ApiListener::GetInstance();
385 Service::Ptr service;
386 tie(host, service) = GetHostService(checkable);
388 Dictionary::Ptr params = new Dictionary();
389 params->Set("host", host->GetName());
391 params->Set("service", service->GetShortName());
392 params->Set("forced", checkable->GetForceNextNotification());
394 Dictionary::Ptr message = new Dictionary();
395 message->Set("jsonrpc", "2.0");
396 message->Set("method", "event::SetForceNextNotification");
397 message->Set("params", params);
399 listener->RelayMessage(origin, checkable, message, true);
402 Value ClusterEvents::ForceNextNotificationChangedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
404 Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
407 Log(LogNotice, "ClusterEvents")
408 << "Discarding 'force next notification changed' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
415 Host::Ptr host = Host::GetByName(params->Get("host"));
420 Checkable::Ptr checkable;
422 if (params->Contains("service"))
423 checkable = host->GetServiceByShortName(params->Get("service"));
430 if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) {
431 Log(LogNotice, "ClusterEvents")
432 << "Discarding 'force next notification' message for checkable '" << checkable->GetName()
433 << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
437 checkable->SetForceNextNotification(params->Get("forced"), false, origin);
442 void ClusterEvents::AcknowledgementSetHandler(const Checkable::Ptr& checkable,
443 const String& author, const String& comment, AcknowledgementType type,
444 bool notify, bool persistent, double expiry, const MessageOrigin::Ptr& origin)
446 ApiListener::Ptr listener = ApiListener::GetInstance();
452 Service::Ptr service;
453 tie(host, service) = GetHostService(checkable);
455 Dictionary::Ptr params = new Dictionary();
456 params->Set("host", host->GetName());
458 params->Set("service", service->GetShortName());
459 params->Set("author", author);
460 params->Set("comment", comment);
461 params->Set("acktype", type);
462 params->Set("notify", notify);
463 params->Set("expiry", expiry);
465 Dictionary::Ptr message = new Dictionary();
466 message->Set("jsonrpc", "2.0");
467 message->Set("method", "event::SetAcknowledgement");
468 message->Set("params", params);
470 listener->RelayMessage(origin, checkable, message, true);
473 Value ClusterEvents::AcknowledgementSetAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
475 Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
478 Log(LogNotice, "ClusterEvents")
479 << "Discarding 'acknowledgement set' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
486 Host::Ptr host = Host::GetByName(params->Get("host"));
491 Checkable::Ptr checkable;
493 if (params->Contains("service"))
494 checkable = host->GetServiceByShortName(params->Get("service"));
501 if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) {
502 Log(LogNotice, "ClusterEvents")
503 << "Discarding 'acknowledgement set' message for checkable '" << checkable->GetName()
504 << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
508 checkable->AcknowledgeProblem(params->Get("author"), params->Get("comment"),
509 static_cast<AcknowledgementType>(static_cast<int>(params->Get("acktype"))),
510 params->Get("notify"), params->Get("persistent"), params->Get("expiry"), origin);
515 void ClusterEvents::AcknowledgementClearedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin)
517 ApiListener::Ptr listener = ApiListener::GetInstance();
523 Service::Ptr service;
524 tie(host, service) = GetHostService(checkable);
526 Dictionary::Ptr params = new Dictionary();
527 params->Set("host", host->GetName());
529 params->Set("service", service->GetShortName());
531 Dictionary::Ptr message = new Dictionary();
532 message->Set("jsonrpc", "2.0");
533 message->Set("method", "event::ClearAcknowledgement");
534 message->Set("params", params);
536 listener->RelayMessage(origin, checkable, message, true);
539 Value ClusterEvents::AcknowledgementClearedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
541 Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
544 Log(LogNotice, "ClusterEvents")
545 << "Discarding 'acknowledgement cleared' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
552 Host::Ptr host = Host::GetByName(params->Get("host"));
557 Checkable::Ptr checkable;
559 if (params->Contains("service"))
560 checkable = host->GetServiceByShortName(params->Get("service"));
567 if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) {
568 Log(LogNotice, "ClusterEvents")
569 << "Discarding 'acknowledgement cleared' message for checkable '" << checkable->GetName()
570 << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
574 checkable->ClearAcknowledgement(origin);
579 Value ClusterEvents::ExecuteCommandAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
581 Endpoint::Ptr sourceEndpoint = origin->FromClient->GetEndpoint();
583 if (!sourceEndpoint || (origin->FromZone && !Zone::GetLocalZone()->IsChildOf(origin->FromZone))) {
584 Log(LogNotice, "ClusterEvents")
585 << "Discarding 'execute command' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
589 ApiListener::Ptr listener = ApiListener::GetInstance();
592 Log(LogCritical, "ApiListener", "No instance available.");
596 if (!listener->GetAcceptCommands()) {
597 Log(LogWarning, "ApiListener")
598 << "Ignoring command. '" << listener->GetName() << "' does not accept commands.";
600 Host::Ptr host = new Host();
601 Dictionary::Ptr attrs = new Dictionary();
603 attrs->Set("__name", params->Get("host"));
604 attrs->Set("type", "Host");
605 attrs->Set("enable_active_checks", false);
607 Deserialize(host, attrs, false, FAConfig);
609 if (params->Contains("service"))
610 host->SetExtension("agent_service_name", params->Get("service"));
612 CheckResult::Ptr cr = new CheckResult();
613 cr->SetState(ServiceUnknown);
614 cr->SetOutput("Endpoint '" + Endpoint::GetLocalEndpoint()->GetName() + "' does not accept commands.");
615 Dictionary::Ptr message = MakeCheckResultMessage(host, cr);
616 listener->SyncSendMessage(sourceEndpoint, message);
621 /* use a virtual host object for executing the command */
622 Host::Ptr host = new Host();
623 Dictionary::Ptr attrs = new Dictionary();
625 attrs->Set("__name", params->Get("host"));
626 attrs->Set("type", "Host");
628 Deserialize(host, attrs, false, FAConfig);
630 if (params->Contains("service"))
631 host->SetExtension("agent_service_name", params->Get("service"));
633 String command = params->Get("command");
634 String command_type = params->Get("command_type");
636 if (command_type == "check_command") {
637 if (!CheckCommand::GetByName(command)) {
638 CheckResult::Ptr cr = new CheckResult();
639 cr->SetState(ServiceUnknown);
640 cr->SetOutput("Check command '" + command + "' does not exist.");
641 Dictionary::Ptr message = MakeCheckResultMessage(host, cr);
642 listener->SyncSendMessage(sourceEndpoint, message);
645 } else if (command_type == "event_command") {
646 if (!EventCommand::GetByName(command)) {
647 Log(LogWarning, "ClusterEvents")
648 << "Event command '" << command << "' does not exist.";
654 attrs->Set(command_type, params->Get("command"));
655 attrs->Set("command_endpoint", sourceEndpoint->GetName());
657 Deserialize(host, attrs, false, FAConfig);
659 host->SetExtension("agent_check", true);
661 Dictionary::Ptr macros = params->Get("macros");
663 if (command_type == "check_command") {
665 host->ExecuteRemoteCheck(macros);
666 } catch (const std::exception& ex) {
667 CheckResult::Ptr cr = new CheckResult();
668 cr->SetState(ServiceUnknown);
670 String output = "Exception occured while checking '" + host->GetName() + "': " + DiagnosticInformation(ex);
671 cr->SetOutput(output);
673 double now = Utility::GetTime();
674 cr->SetScheduleStart(now);
675 cr->SetScheduleEnd(now);
676 cr->SetExecutionStart(now);
677 cr->SetExecutionEnd(now);
679 Dictionary::Ptr message = MakeCheckResultMessage(host, cr);
680 listener->SyncSendMessage(sourceEndpoint, message);
682 Log(LogCritical, "checker", output);
684 } else if (command_type == "event_command") {
685 host->ExecuteEventHandler(macros, true);
691 void ClusterEvents::SendNotificationsHandler(const Checkable::Ptr& checkable, NotificationType type,
692 const CheckResult::Ptr& cr, const String& author, const String& text, const MessageOrigin::Ptr& origin)
694 ApiListener::Ptr listener = ApiListener::GetInstance();
699 Dictionary::Ptr message = MakeCheckResultMessage(checkable, cr);
700 message->Set("method", "event::SendNotifications");
702 Dictionary::Ptr params = message->Get("params");
703 params->Set("type", type);
704 params->Set("author", author);
705 params->Set("text", text);
707 listener->RelayMessage(origin, nullptr, message, true);
710 Value ClusterEvents::SendNotificationsAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
712 Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
715 Log(LogNotice, "ClusterEvents")
716 << "Discarding 'send notification' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
723 Host::Ptr host = Host::GetByName(params->Get("host"));
728 Checkable::Ptr checkable;
730 if (params->Contains("service"))
731 checkable = host->GetServiceByShortName(params->Get("service"));
738 if (origin->FromZone && origin->FromZone != Zone::GetLocalZone()) {
739 Log(LogNotice, "ClusterEvents")
740 << "Discarding 'send custom notification' message for checkable '" << checkable->GetName()
741 << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
748 if (params->Contains("cr")) {
749 cr = new CheckResult();
750 Dictionary::Ptr vcr = params->Get("cr");
752 if (vcr && vcr->Contains("performance_data")) {
753 vperf = vcr->Get("performance_data");
756 vcr->Remove("performance_data");
758 Deserialize(cr, vcr, true);
762 NotificationType type = static_cast<NotificationType>(static_cast<int>(params->Get("type")));
763 String author = params->Get("author");
764 String text = params->Get("text");
766 Checkable::OnNotificationsRequested(checkable, type, cr, author, text, origin);
771 void ClusterEvents::NotificationSentUserHandler(const Notification::Ptr& notification, const Checkable::Ptr& checkable, const User::Ptr& user,
772 NotificationType notificationType, const CheckResult::Ptr& cr, const String& author, const String& commentText, const String& command,
773 const MessageOrigin::Ptr& origin)
775 ApiListener::Ptr listener = ApiListener::GetInstance();
781 Service::Ptr service;
782 tie(host, service) = GetHostService(checkable);
784 Dictionary::Ptr params = new Dictionary();
785 params->Set("host", host->GetName());
787 params->Set("service", service->GetShortName());
788 params->Set("notification", notification->GetName());
789 params->Set("user", user->GetName());
790 params->Set("type", notificationType);
791 params->Set("cr", Serialize(cr));
792 params->Set("author", author);
793 params->Set("text", commentText);
794 params->Set("command", command);
796 Dictionary::Ptr message = new Dictionary();
797 message->Set("jsonrpc", "2.0");
798 message->Set("method", "event::NotificationSentUser");
799 message->Set("params", params);
801 listener->RelayMessage(origin, nullptr, message, true);
804 Value ClusterEvents::NotificationSentUserAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
806 Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
809 Log(LogNotice, "ClusterEvents")
810 << "Discarding 'sent notification to user' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
817 Host::Ptr host = Host::GetByName(params->Get("host"));
822 Checkable::Ptr checkable;
824 if (params->Contains("service"))
825 checkable = host->GetServiceByShortName(params->Get("service"));
832 if (origin->FromZone && origin->FromZone != Zone::GetLocalZone()) {
833 Log(LogNotice, "ClusterEvents")
834 << "Discarding 'send notification to user' message for checkable '" << checkable->GetName()
835 << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
842 if (params->Contains("cr")) {
843 cr = new CheckResult();
844 Dictionary::Ptr vcr = params->Get("cr");
846 if (vcr && vcr->Contains("performance_data")) {
847 vperf = vcr->Get("performance_data");
850 vcr->Remove("performance_data");
852 Deserialize(cr, vcr, true);
856 NotificationType type = static_cast<NotificationType>(static_cast<int>(params->Get("type")));
857 String author = params->Get("author");
858 String text = params->Get("text");
860 Notification::Ptr notification = Notification::GetByName(params->Get("notification"));
865 User::Ptr user = User::GetByName(params->Get("user"));
870 String command = params->Get("command");
872 Checkable::OnNotificationSentToUser(notification, checkable, user, type, cr, author, text, command, origin);
877 void ClusterEvents::NotificationSentToAllUsersHandler(const Notification::Ptr& notification, const Checkable::Ptr& checkable, const std::set<User::Ptr>& users,
878 NotificationType notificationType, const CheckResult::Ptr& cr, const String& author, const String& commentText, const MessageOrigin::Ptr& origin)
880 ApiListener::Ptr listener = ApiListener::GetInstance();
886 Service::Ptr service;
887 tie(host, service) = GetHostService(checkable);
889 Dictionary::Ptr params = new Dictionary();
890 params->Set("host", host->GetName());
892 params->Set("service", service->GetShortName());
893 params->Set("notification", notification->GetName());
895 Array::Ptr ausers = new Array();
896 for (const User::Ptr& user : users) {
897 ausers->Add(user->GetName());
899 params->Set("users", ausers);
901 params->Set("type", notificationType);
902 params->Set("cr", Serialize(cr));
903 params->Set("author", author);
904 params->Set("text", commentText);
906 params->Set("last_notification", notification->GetLastNotification());
907 params->Set("next_notification", notification->GetNextNotification());
908 params->Set("notification_number", notification->GetNotificationNumber());
909 params->Set("last_problem_notification", notification->GetLastProblemNotification());
910 params->Set("no_more_notifications", notification->GetNoMoreNotifications());
912 Dictionary::Ptr message = new Dictionary();
913 message->Set("jsonrpc", "2.0");
914 message->Set("method", "event::NotificationSentToAllUsers");
915 message->Set("params", params);
917 listener->RelayMessage(origin, nullptr, message, true);
920 Value ClusterEvents::NotificationSentToAllUsersAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
922 Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint();
925 Log(LogNotice, "ClusterEvents")
926 << "Discarding 'sent notification to all users' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed).";
933 Host::Ptr host = Host::GetByName(params->Get("host"));
938 Checkable::Ptr checkable;
940 if (params->Contains("service"))
941 checkable = host->GetServiceByShortName(params->Get("service"));
948 if (origin->FromZone && origin->FromZone != Zone::GetLocalZone()) {
949 Log(LogNotice, "ClusterEvents")
950 << "Discarding 'sent notification to all users' message for checkable '" << checkable->GetName()
951 << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
958 if (params->Contains("cr")) {
959 cr = new CheckResult();
960 Dictionary::Ptr vcr = params->Get("cr");
962 if (vcr && vcr->Contains("performance_data")) {
963 vperf = vcr->Get("performance_data");
966 vcr->Remove("performance_data");
968 Deserialize(cr, vcr, true);
972 NotificationType type = static_cast<NotificationType>(static_cast<int>(params->Get("type")));
973 String author = params->Get("author");
974 String text = params->Get("text");
976 Notification::Ptr notification = Notification::GetByName(params->Get("notification"));
981 Array::Ptr ausers = params->Get("users");
986 std::set<User::Ptr> users;
989 ObjectLock olock(ausers);
990 for (const String& auser : ausers) {
991 User::Ptr user = User::GetByName(auser);
1000 notification->SetLastNotification(params->Get("last_notification"));
1001 notification->SetNextNotification(params->Get("next_notification"));
1002 notification->SetNotificationNumber(params->Get("notification_number"));
1003 notification->SetLastProblemNotification(params->Get("last_problem_notification"));
1004 notification->SetNoMoreNotifications(params->Get("no_more_notifications"));
1006 Array::Ptr notifiedProblemUsers = new Array();
1007 for (const User::Ptr& user : users) {
1008 notifiedProblemUsers->Add(user->GetName());
1011 notification->SetNotifiedProblemUsers(notifiedProblemUsers);
1013 Checkable::OnNotificationSentToAllUsers(notification, checkable, users, type, cr, author, text, origin);