diff --git a/itl/types.conf b/itl/types.conf
index 9f3956897..0344b3ecd 100644
--- a/itl/types.conf
+++ b/itl/types.conf
@@ -113,6 +113,10 @@ type Host {
%attribute dictionary "macros" {
%attribute string "*"
+ },
+
+ %attribute dictionary "users" {
+ %attribute string "*"
}
}
},
@@ -194,11 +198,16 @@ type Service {
%attribute dictionary "notifications" {
%attribute string "*",
%attribute dictionary "*" {
- %require "notification",
- %attribute string "notification",
+ %attribute dictionary "templates" {
+ %attribute string "*"
+ },
%attribute dictionary "macros" {
%attribute string "*"
+ },
+
+ %attribute dictionary "users" {
+ %attribute string "*"
}
}
}
@@ -247,3 +256,10 @@ type Script {
%require "code",
%attribute string "code"
}
+
+type User {
+ %attribute dictionary "macros" {
+ %attribute string "*"
+ }
+}
+
diff --git a/lib/icinga/Makefile.am b/lib/icinga/Makefile.am
index 9e09a230c..9dba6e9f5 100644
--- a/lib/icinga/Makefile.am
+++ b/lib/icinga/Makefile.am
@@ -40,7 +40,9 @@ libicinga_la_SOURCES = \
service-notification.cpp \
service.h \
servicegroup.cpp \
- servicegroup.h
+ servicegroup.h \
+ user.cpp \
+ user.h
libicinga_la_CPPFLAGS = \
-DI2_ICINGA_BUILD \
diff --git a/lib/icinga/i2-icinga.h b/lib/icinga/i2-icinga.h
index d31ac7bd0..cb6f9c66d 100644
--- a/lib/icinga/i2-icinga.h
+++ b/lib/icinga/i2-icinga.h
@@ -46,6 +46,8 @@ using boost::algorithm::is_any_of;
#include "endpointmanager.h"
#include "icingaapplication.h"
+#include "user.h"
+
#include "notification.h"
#include "notificationrequestmessage.h"
diff --git a/lib/icinga/icinga.vcxproj b/lib/icinga/icinga.vcxproj
index a81ea70f7..44201f776 100644
--- a/lib/icinga/icinga.vcxproj
+++ b/lib/icinga/icinga.vcxproj
@@ -44,6 +44,7 @@
+
@@ -62,6 +63,7 @@
+
{C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}
diff --git a/lib/icinga/notification.cpp b/lib/icinga/notification.cpp
index dd7d67e98..4e8e574e9 100644
--- a/lib/icinga/notification.cpp
+++ b/lib/icinga/notification.cpp
@@ -70,6 +70,22 @@ Dictionary::Ptr Notification::GetMacros(void) const
return Get("macros");
}
+set Notification::GetUsers(void) const
+{
+ set result;
+
+ Dictionary::Ptr users = Get("users");
+
+ if (users) {
+ String name;
+ BOOST_FOREACH(tie(tuples::ignore, name), users) {
+ result.insert(User::GetByName(name));
+ }
+ }
+
+ return result;
+}
+
String Notification::NotificationTypeToString(NotificationType type)
{
switch (type) {
@@ -100,11 +116,13 @@ void Notification::BeginExecuteNotification(const Notification::Ptr& self, Notif
macroDicts.push_back(notificationMacros);
Service::Ptr service;
+ set users;
{
ObjectLock olock(self);
macroDicts.push_back(self->GetMacros());
service = self->GetService();
+ users = self->GetUsers();
}
Host::Ptr host;
@@ -136,15 +154,45 @@ void Notification::BeginExecuteNotification(const Notification::Ptr& self, Notif
Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
- vector arguments;
- arguments.push_back(self);
- arguments.push_back(macros);
- arguments.push_back(type);
+ int count = 0;
+
+ BOOST_FOREACH(const User::Ptr& user, users) {
+ BeginExecuteNotificationHelper(self, macros, type, user);
+ count++;
+ }
+
+ if (count == 0) {
+ /* Send a notification even if there are no users specified. */
+ BeginExecuteNotificationHelper(self, macros, type, User::Ptr());
+ }
+}
+
+void Notification::BeginExecuteNotificationHelper(const Notification::Ptr& self, const Dictionary::Ptr& notificationMacros, NotificationType type, const User::Ptr& user)
+{
+ vector macroDicts;
+
+ if (user) {
+ {
+ ObjectLock olock(self);
+ macroDicts.push_back(user->GetMacros());
+ }
+
+ macroDicts.push_back(User::CalculateDynamicMacros(user));
+ }
+
+ macroDicts.push_back(notificationMacros);
+
+ Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
ScriptTask::Ptr task;
{
ObjectLock olock(self);
+
+ vector arguments;
+ arguments.push_back(self);
+ arguments.push_back(macros);
+ arguments.push_back(type);
task = self->MakeMethodTask("notify", arguments);
if (!task) {
diff --git a/lib/icinga/notification.h b/lib/icinga/notification.h
index 4aa16a1a2..176fbee8f 100644
--- a/lib/icinga/notification.h
+++ b/lib/icinga/notification.h
@@ -60,6 +60,7 @@ public:
shared_ptr GetService(void) const;
Value GetNotificationCommand(void) const;
Dictionary::Ptr GetMacros(void) const;
+ set GetUsers(void) const;
static void BeginExecuteNotification(const Notification::Ptr& self, NotificationType type);
@@ -72,6 +73,9 @@ private:
set m_Tasks;
void NotificationCompletedHandler(const ScriptTask::Ptr& task);
+
+ static void BeginExecuteNotificationHelper(const Notification::Ptr& self,
+ const Dictionary::Ptr& notificationMacros, NotificationType type, const User::Ptr& user);
};
}
diff --git a/lib/icinga/service-notification.cpp b/lib/icinga/service-notification.cpp
index 36ade2b66..e2a97ff6a 100644
--- a/lib/icinga/service-notification.cpp
+++ b/lib/icinga/service-notification.cpp
@@ -49,7 +49,16 @@ void Service::SendNotifications(NotificationType type)
Logger::Write(LogInformation, "icinga", "Service '" + GetName() + "' does not have any notifications.");
BOOST_FOREACH(const Notification::Ptr& notification, notifications) {
- Notification::BeginExecuteNotification(notification, type);
+ try {
+ Notification::BeginExecuteNotification(notification, type);
+ } catch (const exception& ex) {
+ stringstream msgbuf;
+ msgbuf << "Exception occured during notification for service '"
+ << GetName() << "': " << diagnostic_information(ex);
+ String message = msgbuf.str();
+
+ Logger::Write(LogWarning, "icinga", message);
+ }
}
SetLastNotification(Utility::GetTime());
@@ -105,6 +114,10 @@ static void CopyNotificationAttributes(TDict notificationDesc, const ConfigItemB
if (!macros.IsEmpty())
builder->AddExpression("macros", OperatorPlus, macros);
+ Value users = notificationDesc->Get("users");
+ if (!users.IsEmpty())
+ builder->AddExpression("users", OperatorPlus, users);
+
/*Value notificationInterval = notificationDesc->Get("notification_interval");
if (!notificationInterval.IsEmpty())
builder->AddExpression("notification_interval", OperatorSet, notificationInterval);*/
diff --git a/lib/icinga/user.cpp b/lib/icinga/user.cpp
new file mode 100644
index 000000000..5c5ba8502
--- /dev/null
+++ b/lib/icinga/user.cpp
@@ -0,0 +1,63 @@
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "i2-icinga.h"
+
+using namespace icinga;
+
+REGISTER_TYPE(User, NULL);
+
+User::User(const Dictionary::Ptr& properties)
+ : DynamicObject(properties)
+{ }
+
+bool User::Exists(const String& name)
+{
+ return (DynamicObject::GetObject("User", name));
+}
+
+User::Ptr User::GetByName(const String& name)
+{
+ DynamicObject::Ptr configObject = DynamicObject::GetObject("User", name);
+
+ if (!configObject)
+ BOOST_THROW_EXCEPTION(invalid_argument("User '" + name + "' does not exist."));
+
+ return dynamic_pointer_cast(configObject);
+}
+
+Dictionary::Ptr User::GetMacros(void) const
+{
+ return Get("macros");
+}
+
+Dictionary::Ptr User::CalculateDynamicMacros(const User::Ptr& self)
+{
+ Dictionary::Ptr macros = boost::make_shared();
+
+ {
+ ObjectLock olock(self);
+ macros->Set("CONTACTNAME", self->GetName());
+ macros->Set("CONTACTALIAS", self->GetName());
+ }
+
+ macros->Seal();
+
+ return macros;
+}
diff --git a/lib/icinga/user.h b/lib/icinga/user.h
new file mode 100644
index 000000000..70dad242f
--- /dev/null
+++ b/lib/icinga/user.h
@@ -0,0 +1,48 @@
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#ifndef USER_H
+#define USER_H
+
+namespace icinga
+{
+
+/**
+ * A User.
+ *
+ * @ingroup icinga
+ */
+class I2_ICINGA_API User : public DynamicObject
+{
+public:
+ typedef shared_ptr Ptr;
+ typedef weak_ptr WeakPtr;
+
+ User(const Dictionary::Ptr& properties);
+
+ static bool Exists(const String& name);
+ static User::Ptr GetByName(const String& name);
+
+ Dictionary::Ptr GetMacros(void) const;
+ static Dictionary::Ptr CalculateDynamicMacros(const User::Ptr& self);
+};
+
+}
+
+#endif /* USER_H */