Implement notification conditions.

Fixes #2841
This commit is contained in:
Gunnar Beutner 2013-06-26 09:08:50 +02:00
parent 46b3f033cf
commit d2b31f6a06
7 changed files with 149 additions and 18 deletions

View File

@ -52,15 +52,15 @@ static bool LoadConfigFiles(bool validateOnly)
ConfigCompilerContext::SetContext(&context); ConfigCompilerContext::SetContext(&context);
BOOST_FOREACH(const String& configPath, g_AppParams["config"].as<std::vector<String> >()) {
ConfigCompiler::CompileFile(configPath);
}
String name, fragment; String name, fragment;
BOOST_FOREACH(boost::tie(name, fragment), ConfigFragmentRegistry::GetInstance()->GetItems()) { BOOST_FOREACH(boost::tie(name, fragment), ConfigFragmentRegistry::GetInstance()->GetItems()) {
ConfigCompiler::CompileText(name, fragment); ConfigCompiler::CompileText(name, fragment);
} }
BOOST_FOREACH(const String& configPath, g_AppParams["config"].as<std::vector<String> >()) {
ConfigCompiler::CompileFile(configPath);
}
ConfigCompilerContext::SetContext(NULL); ConfigCompilerContext::SetContext(NULL);
bool hasError = false; bool hasError = false;

View File

@ -18,6 +18,7 @@
******************************************************************************/ ******************************************************************************/
#include "base/scriptvariable.h" #include "base/scriptvariable.h"
#include "base/logger_fwd.h"
using namespace icinga; using namespace icinga;
@ -25,7 +26,11 @@ Registry<String> ScriptVariable::m_Registry;
Value ScriptVariable::Get(const String& name) Value ScriptVariable::Get(const String& name)
{ {
return m_Registry.GetItem(name); Value value = m_Registry.GetItem(name);
if (value.IsEmpty())
Log(LogWarning, "icinga", "Tried to access empty variable: " + name);
return value;
} }
void ScriptVariable::Set(const String& name, const Value& value) void ScriptVariable::Set(const String& name, const Value& value)

View File

@ -231,6 +231,8 @@ type Service {
%attribute number "end", %attribute number "end",
}, },
%attribute number "type_filter",
%attribute number "state_filter"
} }
} }
} }
@ -241,6 +243,44 @@ type ServiceGroup {
%attribute string "action_url" %attribute string "action_url"
} }
set StateOK = (0)
set StateWarning = (1)
set StateCritical = (2)
set StateUnknown = (3)
set StateUncheckable = (4)
/*
* Converting states to their filter values: 1<<state
*/
set StateFilterOK = (1<<StateOK)
set StateFilterWarning = (1<<StateWarning)
set StateFilterCritical = (1<<StateCritical)
set StateFilterUnknown = (1<<StateUnknown)
set StateFilterUncheckable = (1<<StateUncheckable)
set NotificationDowntimeStart = (0)
set NotificationDowntimeEnd = (1)
set NotificationDowntimeRemoved = (2)
set NotificationCustom = (3)
set NotificationAcknowledgement = (4)
set NotificationProblem = (5)
set NotificationRecovery = (6)
set NotificationFlappingStart = (7)
set NotificationFlappingEnd = (8)
/*
* Converting notification types to their filter values: 1<<type
*/
set NotificationFilterDowntimeStart = (1<<NotificationDowntimeStart)
set NotificationFilterDowntimeEnd = (1<<NotificationDowntimeEnd)
set NotificationFilterDowntimeRemoved = (1<<NotificationDowntimeRemoved)
set NotificationFilterCustom = (1<<NotificationCustom)
set NotificationFilterAcknowledgement = (1<<NotificationAcknowledgement)
set NotificationFilterProblem = (1<<NotificationProblem)
set NotificationFilterRecovery = (1<<NotificationRecovery)
set NotificationFilterFlappingStart = (1<<NotificationFlappingStart)
set NotificationFilterFlappingEnd = (1<<NotificationFlappingEnd)
type Notification { type Notification {
%require "host_name", %require "host_name",
%attribute string "host_name", %attribute string "host_name",
@ -265,7 +305,10 @@ type Notification {
%attribute name(NotificationCommand) "notification_command", %attribute name(NotificationCommand) "notification_command",
%attribute number "notification_interval", %attribute number "notification_interval",
%attribute name(TimePeriod) "notification_period" %attribute name(TimePeriod) "notification_period",
%attribute number "type_filter",
%attribute number "state_filter"
} }
type User { type User {
@ -277,7 +320,11 @@ type User {
%attribute array "groups" { %attribute array "groups" {
%attribute name(UserGroup) "*" %attribute name(UserGroup) "*"
} },
%attribute number "type_filter",
%attribute number "state_filter"
} }
type UserGroup { type UserGroup {

View File

@ -25,6 +25,7 @@
#include "base/objectlock.h" #include "base/objectlock.h"
#include "base/logger_fwd.h" #include "base/logger_fwd.h"
#include "base/utility.h" #include "base/utility.h"
#include "base/convert.h"
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/exception/diagnostic_information.hpp> #include <boost/exception/diagnostic_information.hpp>
@ -45,6 +46,8 @@ Notification::Notification(const Dictionary::Ptr& serializedUpdate)
RegisterAttribute("users", Attribute_Config, &m_Users); RegisterAttribute("users", Attribute_Config, &m_Users);
RegisterAttribute("groups", Attribute_Config, &m_Groups); RegisterAttribute("groups", Attribute_Config, &m_Groups);
RegisterAttribute("times", Attribute_Config, &m_Times); RegisterAttribute("times", Attribute_Config, &m_Times);
RegisterAttribute("type_filter", Attribute_Config, &m_TypeFilter);
RegisterAttribute("state_filter", Attribute_Config, &m_StateFilter);
RegisterAttribute("host_name", Attribute_Config, &m_HostName); RegisterAttribute("host_name", Attribute_Config, &m_HostName);
RegisterAttribute("service", Attribute_Config, &m_Service); RegisterAttribute("service", Attribute_Config, &m_Service);
RegisterAttribute("export_macros", Attribute_Config, &m_ExportMacros); RegisterAttribute("export_macros", Attribute_Config, &m_ExportMacros);
@ -139,6 +142,22 @@ Dictionary::Ptr Notification::GetTimes(void) const
return m_Times; return m_Times;
} }
unsigned long Notification::GetTypeFilter(void) const
{
if (m_TypeFilter.IsEmpty())
return ~(unsigned long)0; /* All states. */
else
return m_TypeFilter;
}
unsigned long Notification::GetStateFilter(void) const
{
if (m_StateFilter.IsEmpty())
return ~(unsigned long)0; /* All states. */
else
return m_StateFilter;
}
double Notification::GetNotificationInterval(void) const double Notification::GetNotificationInterval(void) const
{ {
if (m_NotificationInterval.IsEmpty()) if (m_NotificationInterval.IsEmpty())
@ -238,6 +257,24 @@ void Notification::BeginExecuteNotification(NotificationType type, const Diction
Log(LogInformation, "icinga", "Not sending notifications for notification object '" + GetName() + "': after escalation range"); Log(LogInformation, "icinga", "Not sending notifications for notification object '" + GetName() + "': after escalation range");
return; return;
} }
unsigned long ftype = 1 << type;
Log(LogDebug, "icinga", "FType=" + Convert::ToString(ftype) + ", TypeFilter=" + Convert::ToString(GetTypeFilter()));
if (!(ftype & GetTypeFilter())) {
Log(LogInformation, "icinga", "Not sending notifications for notification object '" + GetName() + "': type filter does not match");
return;
}
unsigned long fstate = 1 << GetService()->GetState();
Log(LogDebug, "icinga", "FState=" + Convert::ToString(fstate) + ", StateFilter=" + Convert::ToString(GetStateFilter()));
if (!(fstate & GetStateFilter())) {
Log(LogInformation, "icinga", "Not sending notifications for notification object '" + GetName() + "': state filter does not match");
return;
}
} }
{ {
@ -262,11 +299,11 @@ void Notification::BeginExecuteNotification(NotificationType type, const Diction
} }
} }
void Notification::ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const Dictionary::Ptr& cr, bool ignore_timeperiod) void Notification::ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const Dictionary::Ptr& cr, bool force)
{ {
ASSERT(!OwnsLock()); ASSERT(!OwnsLock());
if (!ignore_timeperiod) { if (!force) {
TimePeriod::Ptr tp = user->GetNotificationPeriod(); TimePeriod::Ptr tp = user->GetNotificationPeriod();
if (tp && !tp->IsInside(Utility::GetTime())) { if (tp && !tp->IsInside(Utility::GetTime())) {
@ -274,6 +311,22 @@ void Notification::ExecuteNotificationHelper(NotificationType type, const User::
GetName() + " and user '" + user->GetName() + "': user not in timeperiod"); GetName() + " and user '" + user->GetName() + "': user not in timeperiod");
return; return;
} }
unsigned long ftype = 1 << type;
if (!(ftype & user->GetTypeFilter())) {
Log(LogInformation, "icinga", "Not sending notifications for notification object '" +
GetName() + " and user '" + user->GetName() + "': type filter does not match");
return;
}
unsigned long fstate = 1 << GetService()->GetState();
if (!(fstate & user->GetStateFilter())) {
Log(LogInformation, "icinga", "Not sending notifications for notification object '" +
GetName() + " and user '" + user->GetName() + "': state filter does not match");
return;
}
} }
try { try {

View File

@ -36,15 +36,15 @@ namespace icinga
*/ */
enum NotificationType enum NotificationType
{ {
NotificationDowntimeStart, NotificationDowntimeStart = 0,
NotificationDowntimeEnd, NotificationDowntimeEnd = 1,
NotificationDowntimeRemoved, NotificationDowntimeRemoved = 2,
NotificationCustom, NotificationCustom = 3,
NotificationAcknowledgement, NotificationAcknowledgement = 4,
NotificationProblem, NotificationProblem = 5,
NotificationRecovery, NotificationRecovery = 6,
NotificationFlappingStart, NotificationFlappingStart = 7 ,
NotificationFlappingEnd, NotificationFlappingEnd = 8,
}; };
class Service; class Service;
@ -75,6 +75,8 @@ public:
std::set<User::Ptr> GetUsers(void) const; std::set<User::Ptr> GetUsers(void) const;
std::set<UserGroup::Ptr> GetGroups(void) const; std::set<UserGroup::Ptr> GetGroups(void) const;
Dictionary::Ptr GetTimes(void) const; Dictionary::Ptr GetTimes(void) const;
unsigned long GetTypeFilter(void) const;
unsigned long GetStateFilter(void) const;
double GetLastNotification(void) const; double GetLastNotification(void) const;
void SetLastNotification(double time); void SetLastNotification(double time);
@ -102,6 +104,8 @@ private:
Attribute<Array::Ptr> m_Users; Attribute<Array::Ptr> m_Users;
Attribute<Array::Ptr> m_Groups; Attribute<Array::Ptr> m_Groups;
Attribute<Dictionary::Ptr> m_Times; Attribute<Dictionary::Ptr> m_Times;
Attribute<long> m_TypeFilter;
Attribute<long> m_StateFilter;
Attribute<String> m_HostName; Attribute<String> m_HostName;
Attribute<String> m_Service; Attribute<String> m_Service;

View File

@ -34,6 +34,8 @@ User::User(const Dictionary::Ptr& serializedUpdate)
RegisterAttribute("macros", Attribute_Config, &m_Macros); RegisterAttribute("macros", Attribute_Config, &m_Macros);
RegisterAttribute("groups", Attribute_Config, &m_Groups); RegisterAttribute("groups", Attribute_Config, &m_Groups);
RegisterAttribute("notification_period", Attribute_Config, &m_NotificationPeriod); RegisterAttribute("notification_period", Attribute_Config, &m_NotificationPeriod);
RegisterAttribute("type_filter", Attribute_Config, &m_TypeFilter);
RegisterAttribute("state_filter", Attribute_Config, &m_StateFilter);
} }
User::~User(void) User::~User(void)
@ -79,6 +81,22 @@ TimePeriod::Ptr User::GetNotificationPeriod(void) const
return TimePeriod::GetByName(m_NotificationPeriod); return TimePeriod::GetByName(m_NotificationPeriod);
} }
unsigned long User::GetTypeFilter(void) const
{
if (m_TypeFilter.IsEmpty())
return ~(unsigned long)0; /* All states. */
else
return m_TypeFilter;
}
unsigned long User::GetStateFilter(void) const
{
if (m_StateFilter.IsEmpty())
return ~(unsigned long)0; /* All states. */
else
return m_StateFilter;
}
bool User::ResolveMacro(const String& macro, const Dictionary::Ptr& cr, String *result) const bool User::ResolveMacro(const String& macro, const Dictionary::Ptr& cr, String *result) const
{ {
if (macro == "CONTACTNAME") { if (macro == "CONTACTNAME") {

View File

@ -48,6 +48,8 @@ public:
String GetDisplayName(void) const; String GetDisplayName(void) const;
Array::Ptr GetGroups(void) const; Array::Ptr GetGroups(void) const;
TimePeriod::Ptr GetNotificationPeriod(void) const; TimePeriod::Ptr GetNotificationPeriod(void) const;
unsigned long GetTypeFilter(void) const;
unsigned long GetStateFilter(void) const;
Dictionary::Ptr GetMacros(void) const; Dictionary::Ptr GetMacros(void) const;
@ -61,6 +63,8 @@ private:
Attribute<Dictionary::Ptr> m_Macros; Attribute<Dictionary::Ptr> m_Macros;
Attribute<String> m_NotificationPeriod; Attribute<String> m_NotificationPeriod;
Attribute<Array::Ptr> m_Groups; Attribute<Array::Ptr> m_Groups;
Attribute<long> m_TypeFilter;
Attribute<long> m_StateFilter;
}; };
} }