Implemented LAST*STATE* macros.

This commit is contained in:
Gunnar Beutner 2013-03-07 12:04:20 +01:00
parent 68bd651195
commit 02be9010e7
12 changed files with 266 additions and 117 deletions

View File

@ -81,7 +81,7 @@ void NotificationComponent::NotificationTimerHandler(void)
}
if (send_notification)
service->RequestNotifications(NotificationProblem);
service->RequestNotifications(NotificationProblem, service->GetLastCheckResult());
}
}
@ -103,10 +103,14 @@ void NotificationComponent::SendNotificationsRequestHandler(const Endpoint::Ptr&
if (!params.Get("type", &type))
return;
Dictionary::Ptr cr;
if (!params.Get("check_result", &cr))
return;
Service::Ptr service = Service::GetByName(svc);
if (!service)
return;
service->SendNotifications(static_cast<NotificationType>(type));
service->SendNotifications(static_cast<NotificationType>(type), cr);
}

View File

@ -1111,7 +1111,7 @@ void ExternalCommandProcessor::SendCustomHostNotification(double, const vector<S
Logger::Write(LogInformation, "icinga", "Sending custom notification for host " + host->GetName());
Service::Ptr service = host->GetHostCheckService();
if (service)
service->RequestNotifications(NotificationCustom);
service->RequestNotifications(NotificationCustom, service->GetLastCheckResult());
}
void ExternalCommandProcessor::SendCustomSvcNotification(double, const vector<String>& arguments)
@ -1122,7 +1122,7 @@ void ExternalCommandProcessor::SendCustomSvcNotification(double, const vector<St
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Sending custom notification for service " + service->GetName());
service->RequestNotifications(NotificationCustom);
service->RequestNotifications(NotificationCustom, service->GetLastCheckResult());
}
void ExternalCommandProcessor::DelayHostNotification(double, const vector<String>& arguments)

View File

@ -506,15 +506,107 @@ set<Service::Ptr> Host::GetParentServices(void) const
return parents;
}
HostState Host::GetState(void) const
{
assert(!OwnsLock());
if (!IsReachable())
return HostUnreachable;
Service::Ptr hc = GetHostCheckService();
if (!hc)
return HostUp;
switch (hc->GetState()) {
case StateOK:
case StateWarning:
return HostUp;
default:
return HostDown;
}
}
StateType Host::GetStateType(void) const
{
Service::Ptr hc = GetHostCheckService();
if (!hc)
return StateTypeHard;
return hc->GetStateType();
}
HostState Host::GetLastState(void) const
{
assert(!OwnsLock());
if (!IsReachable())
return HostUnreachable;
Service::Ptr hc = GetHostCheckService();
if (!hc)
return HostUp;
switch (hc->GetLastState()) {
case StateOK:
case StateWarning:
return HostUp;
default:
return HostDown;
}
}
StateType Host::GetLastStateType(void) const
{
Service::Ptr hc = GetHostCheckService();
if (!hc)
return StateTypeHard;
return hc->GetLastStateType();
}
String Host::HostStateToString(HostState state)
{
switch (state) {
case HostUp:
return "UP";
case HostDown:
return "DOWN";
case HostUnreachable:
return "UNREACHABLE";
default:
return "INVALID";
}
}
Dictionary::Ptr Host::CalculateDynamicMacros(void) const
{
assert(!OwnsLock());
Dictionary::Ptr macros = boost::make_shared<Dictionary>();
macros->Set("HOSTNAME", GetName());
macros->Set("HOSTDISPLAYNAME", GetDisplayName());
macros->Set("HOSTALIAS", GetName());
{
ObjectLock olock(this);
macros->Set("HOSTNAME", GetName());
macros->Set("HOSTDISPLAYNAME", GetDisplayName());
macros->Set("HOSTALIAS", GetName());
HostState state = GetState();
macros->Set("HOSTSTATE", HostStateToString(GetState()));
macros->Set("HOSTSTATEID", GetState());
HostState lastState = GetLastState();
StateType lastStateType = GetLastStateType();
macros->Set("LASTHOSTSTATE", HostStateToString(lastState));
macros->Set("LASTHOSTSTATEID", lastState);
macros->Set("LASTHOSTSTATETYPE", Service::StateTypeToString(lastStateType));
}
Dictionary::Ptr cr;
@ -523,32 +615,12 @@ Dictionary::Ptr Host::CalculateDynamicMacros(void) const
if (hc) {
ObjectLock olock(hc);
String state;
int stateid;
switch (hc->GetState()) {
case StateOK:
case StateWarning:
state = "UP";
stateid = 0;
break;
default:
state = "DOWN";
stateid = 1;
break;
}
if (!IsReachable()) {
state = "UNREACHABLE";
stateid = 2;
}
macros->Set("HOSTSTATE", state);
macros->Set("HOSTSTATEID", stateid);
macros->Set("HOSTSTATETYPE", Service::StateTypeToString(hc->GetStateType()));
macros->Set("HOSTATTEMPT", hc->GetCurrentCheckAttempt());
macros->Set("MAXHOSTATTEMPT", hc->GetMaxCheckAttempts());
macros->Set("LASTHOSTSTATECHANGE", (time_t)hc->GetLastStateChange());
cr = hc->GetLastCheckResult();
}
@ -558,6 +630,8 @@ Dictionary::Ptr Host::CalculateDynamicMacros(void) const
macros->Set("HOSTOUTPUT", cr->Get("output"));
macros->Set("HOSTPERFDATA", cr->Get("performance_data_raw"));
macros->Set("LASTHOSTCHECK", (time_t)cr->Get("schedule_start"));
}
macros->Seal();

View File

@ -25,6 +25,29 @@ namespace icinga
class Service;
/**
* The state of a host.
*
* @ingroup icinga
*/
enum HostState
{
HostUp = 0,
HostDown = 1,
HostUnreachable = 2
};
/**
* The state type of a host or service.
*
* @ingroup icinga
*/
enum StateType
{
StateTypeSoft = 0,
StateTypeHard = 1
};
/**
* An Icinga host.
*
@ -65,6 +88,14 @@ public:
static void ValidateServiceDictionary(const ScriptTask::Ptr& task,
const std::vector<icinga::Value>& arguments);
HostState GetState(void) const;
StateType GetStateType(void) const;
HostState GetLastState(void) const;
StateType GetLastStateType(void) const;
static String HostStateToString(HostState state);
protected:
virtual void OnRegistrationCompleted(void);
virtual void OnAttributeChanged(const String& name);

View File

@ -161,38 +161,11 @@ String Notification::NotificationTypeToString(NotificationType type)
/**
* @threadsafety Always.
*/
void Notification::BeginExecuteNotification(NotificationType type)
void Notification::BeginExecuteNotification(NotificationType type, const Dictionary::Ptr& cr)
{
assert(!OwnsLock());
vector<Dictionary::Ptr> macroDicts;
Dictionary::Ptr notificationMacros = boost::make_shared<Dictionary>();
notificationMacros->Set("NOTIFICATIONTYPE", NotificationTypeToString(type));
macroDicts.push_back(notificationMacros);
macroDicts.push_back(GetMacros());
Service::Ptr service = GetService();
if (service) {
macroDicts.push_back(service->GetMacros());
macroDicts.push_back(service->CalculateDynamicMacros());
Host::Ptr host = service->GetHost();
if (host) {
macroDicts.push_back(host->GetMacros());
macroDicts.push_back(host->CalculateDynamicMacros());
}
}
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
macroDicts.push_back(app->GetMacros());
macroDicts.push_back(IcingaApplication::CalculateDynamicMacros());
Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
Dictionary::Ptr macros = cr->Get("macros");
set<User::Ptr> allUsers;

View File

@ -63,7 +63,7 @@ public:
set<User::Ptr> GetUsers(void) const;
set<UserGroup::Ptr> GetGroups(void) const;
void BeginExecuteNotification(NotificationType type);
void BeginExecuteNotification(NotificationType type, const Dictionary::Ptr& cr);
static String NotificationTypeToString(NotificationType type);

View File

@ -44,3 +44,15 @@ void NotificationRequestMessage::SetType(NotificationType type)
{
Set("type", type);
}
Dictionary::Ptr NotificationRequestMessage::GetCheckResult(void) const
{
Dictionary::Ptr cr;
Get("check_result", &cr);
return cr;
}
void NotificationRequestMessage::SetCheckResult(const Dictionary::Ptr& cr)
{
Set("check_result", cr);
}

View File

@ -39,6 +39,9 @@ public:
NotificationType GetType(void) const;
void SetType(NotificationType type);
Dictionary::Ptr GetCheckResult(void) const;
void SetCheckResult(const Dictionary::Ptr& cr);
};
}

View File

@ -22,8 +22,8 @@
using namespace icinga;
const int Service::DefaultMaxCheckAttempts = 3;
const int Service::DefaultCheckInterval = 5 * 60;
const int Service::CheckIntervalDivisor = 5;
const double Service::DefaultCheckInterval = 5 * 60;
const double Service::CheckIntervalDivisor = 5.0;
signals2::signal<void (const Service::Ptr&)> Service::OnCheckerChanged;
signals2::signal<void (const Service::Ptr&)> Service::OnNextCheckChanged;
@ -191,10 +191,26 @@ ServiceState Service::GetState(void) const
return static_cast<ServiceState>(ivalue);
}
void Service::SetLastState(ServiceState state)
{
m_LastState = static_cast<long>(state);
Touch("last_state");
}
ServiceState Service::GetLastState(void) const
{
if (m_LastState.IsEmpty())
return StateUnknown;
int ivalue = static_cast<int>(m_LastState);
return static_cast<ServiceState>(ivalue);
}
/**
* @threadsafety Always.
*/
void Service::SetStateType(ServiceStateType type)
void Service::SetStateType(StateType type)
{
m_StateType = static_cast<long>(type);
Touch("state_type");
@ -203,13 +219,34 @@ void Service::SetStateType(ServiceStateType type)
/**
* @threadsafety Always.
*/
ServiceStateType Service::GetStateType(void) const
StateType Service::GetStateType(void) const
{
if (m_StateType.IsEmpty())
return StateTypeSoft;
int ivalue = static_cast<int>(m_StateType);
return static_cast<ServiceStateType>(ivalue);
return static_cast<StateType>(ivalue);
}
/**
* @threadsafety Always.
*/
void Service::SetLastStateType(StateType type)
{
m_LastStateType = static_cast<long>(type);
Touch("last_state_type");
}
/**
* @threadsafety Always.
*/
StateType Service::GetLastStateType(void) const
{
if (m_LastStateType.IsEmpty())
return StateTypeSoft;
int ivalue = static_cast<int>(m_LastStateType);
return static_cast<StateType>(ivalue);
}
/**
@ -340,10 +377,13 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
ObjectLock olock(this);
ServiceState old_state = GetState();
ServiceStateType old_stateType = GetStateType();
StateType old_stateType = GetStateType();
bool hardChange = false;
bool recovery;
SetLastState(old_state);
SetLastStateType(old_stateType);
long attempt = GetCurrentCheckAttempt();
if (cr->Get("state") == StateOK) {
@ -423,6 +463,9 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
* new state when they receive the CheckResult message */
Flush();
/* Update macros - these are used by event handlers and notifications. */
cr->Set("macros", CalculateAllMacros());
RequestMessage rm;
rm.SetMethod("checker::CheckResult");
@ -436,7 +479,7 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
EndpointManager::GetInstance()->SendMulticastMessage(rm);
if (send_notification)
RequestNotifications(recovery ? NotificationRecovery : NotificationProblem);
RequestNotifications(recovery ? NotificationRecovery : NotificationProblem, cr);
}
/**
@ -479,7 +522,7 @@ String Service::StateToString(ServiceState state)
/**
* @threadsafety Always.
*/
ServiceStateType Service::StateTypeFromString(const String& type)
StateType Service::StateTypeFromString(const String& type)
{
if (type == "SOFT")
return StateTypeSoft;
@ -490,7 +533,7 @@ ServiceStateType Service::StateTypeFromString(const String& type)
/**
* @threadsafety Always.
*/
String Service::StateTypeToString(ServiceStateType type)
String Service::StateTypeToString(StateType type)
{
if (type == StateTypeSoft)
return "SOFT";
@ -547,27 +590,7 @@ void Service::BeginExecuteCheck(const function<void (void)>& callback)
checkInfo->Set("schedule_start", GetNextCheck());
checkInfo->Set("execution_start", Utility::GetTime());
vector<Dictionary::Ptr> macroDicts;
macroDicts.push_back(GetMacros());
Value raw_command = GetCheckCommand();
Host::Ptr host = GetHost();
macroDicts.push_back(CalculateDynamicMacros());
if (host) {
macroDicts.push_back(host->GetMacros());
macroDicts.push_back(host->CalculateDynamicMacros());
}
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
macroDicts.push_back(app->GetMacros());
macroDicts.push_back(IcingaApplication::CalculateDynamicMacros());
Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
Dictionary::Ptr macros = CalculateAllMacros();
checkInfo->Set("macros", macros);
Service::Ptr self = GetSelf();
@ -648,17 +671,17 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& checkInfo,
if (result)
ProcessCheckResult(result);
/* figure out when the next check is for this service; the call to
* ProcessCheckResult() should've already done this but lets do it again
* just in case there was no check result. */
UpdateNextCheck();
{
ObjectLock olock(this);
m_CurrentTask.reset();
m_CheckRunning = false;
}
/* figure out when the next check is for this service; the call to
* ApplyCheckResult() should've already done this but lets do it again
* just in case there was no check result. */
UpdateNextCheck();
callback();
}

View File

@ -29,7 +29,7 @@ Timer::Ptr Service::m_NotificationsCacheTimer;
/**
* @threadsafety Always.
*/
void Service::RequestNotifications(NotificationType type)
void Service::RequestNotifications(NotificationType type, const Dictionary::Ptr& cr)
{
{
ObjectLock olock(this);
@ -44,6 +44,7 @@ void Service::RequestNotifications(NotificationType type)
params.SetService(GetName());
params.SetType(type);
params.SetCheckResult(cr);
Logger::Write(LogDebug, "icinga", "Sending notification anycast request for service '" + GetName() + "'");
EndpointManager::GetInstance()->SendAnycastMessage(Endpoint::Ptr(), msg);
@ -52,7 +53,7 @@ void Service::RequestNotifications(NotificationType type)
/**
* @threadsafety Always.
*/
void Service::SendNotifications(NotificationType type)
void Service::SendNotifications(NotificationType type, const Dictionary::Ptr& cr)
{
if (!GetEnableNotifications()) {
Logger::Write(LogInformation, "icinga", "Notifications are disabled for service '" + GetName() + "'.");
@ -68,7 +69,7 @@ void Service::SendNotifications(NotificationType type)
BOOST_FOREACH(const Notification::Ptr& notification, notifications) {
try {
notification->BeginExecuteNotification(type);
notification->BeginExecuteNotification(type, cr);
} catch (const exception& ex) {
stringstream msgbuf;
msgbuf << "Exception occured during notification for service '"

View File

@ -44,6 +44,8 @@ Service::Service(const Dictionary::Ptr& serializedObject)
RegisterAttribute("check_attempt", Attribute_Replicated, &m_CheckAttempt);
RegisterAttribute("state", Attribute_Replicated, &m_State);
RegisterAttribute("state_type", Attribute_Replicated, &m_StateType);
RegisterAttribute("last_state", Attribute_Replicated, &m_LastState);
RegisterAttribute("last_state_type", Attribute_Replicated, &m_LastStateType);
RegisterAttribute("last_result", Attribute_Replicated, &m_LastResult);
RegisterAttribute("last_state_change", Attribute_Replicated, &m_LastStateChange);
RegisterAttribute("last_hard_state_change", Attribute_Replicated, &m_LastHardStateChange);
@ -315,7 +317,7 @@ void Service::AcknowledgeProblem(AcknowledgementType type, double expiry)
SetAcknowledgement(type);
SetAcknowledgementExpiry(expiry);
RequestNotifications(NotificationAcknowledgement);
RequestNotifications(NotificationAcknowledgement, GetLastCheckResult());
}
/**
@ -443,6 +445,10 @@ Dictionary::Ptr Service::CalculateDynamicMacros(void) const
macros->Set("SERVICEATTEMPT", GetCurrentCheckAttempt());
macros->Set("MAXSERVICEATTEMPT", GetMaxCheckAttempts());
macros->Set("SERVICECHECKCOMMAND", "check_i2");
macros->Set("LASTSERVICESTATE", StateToString(GetLastState()));
macros->Set("LASTSERVICESTATEID", GetLastState());
macros->Set("LASTSERVICESTATETYPE", StateTypeToString(GetLastStateType()));
macros->Set("LASTSERVICESTATECHANGE", (time_t)GetLastStateChange());
cr = GetLastCheckResult();
}
@ -455,9 +461,33 @@ Dictionary::Ptr Service::CalculateDynamicMacros(void) const
macros->Set("SERVICEOUTPUT", cr->Get("output"));
macros->Set("SERVICEPERFDATA", cr->Get("performance_data_raw"));
macros->Set("LASTSERVICECHECK", (time_t)cr->Get("schedule_start"));
}
macros->Seal();
return macros;
}
Dictionary::Ptr Service::CalculateAllMacros(void) const
{
vector<Dictionary::Ptr> macroDicts;
macroDicts.push_back(GetMacros());
Host::Ptr host = GetHost();
macroDicts.push_back(CalculateDynamicMacros());
if (host) {
macroDicts.push_back(host->GetMacros());
macroDicts.push_back(host->CalculateDynamicMacros());
}
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
macroDicts.push_back(app->GetMacros());
macroDicts.push_back(IcingaApplication::CalculateDynamicMacros());
return MacroProcessor::MergeMacroDicts(macroDicts);
}

View File

@ -37,17 +37,6 @@ enum ServiceState
StateUncheckable,
};
/**
* The state type of a service.
*
* @ingroup icinga
*/
enum ServiceStateType
{
StateTypeSoft,
StateTypeHard
};
/**
* The acknowledgement type of a service.
*
@ -94,8 +83,8 @@ public:
static Service::Ptr GetByNamePair(const String& hostName, const String& serviceName);
static const int DefaultMaxCheckAttempts;
static const int DefaultCheckInterval;
static const int CheckIntervalDivisor;
static const double DefaultCheckInterval;
static const double CheckIntervalDivisor;
String GetDisplayName(void) const;
Host::Ptr GetHost(void) const;
@ -107,6 +96,7 @@ public:
String GetShortName(void) const;
Dictionary::Ptr CalculateDynamicMacros(void) const;
Dictionary::Ptr CalculateAllMacros(void) const;
set<Host::Ptr> GetParentHosts(void) const;
set<Service::Ptr> GetParentServices(void) const;
@ -141,8 +131,14 @@ public:
void SetState(ServiceState state);
ServiceState GetState(void) const;
void SetStateType(ServiceStateType type);
ServiceStateType GetStateType(void) const;
void SetStateType(StateType type);
StateType GetStateType(void) const;
void SetLastState(ServiceState state);
ServiceState GetLastState(void) const;
void SetLastStateType(StateType type);
StateType GetLastStateType(void) const;
void SetLastCheckResult(const Dictionary::Ptr& result);
Dictionary::Ptr GetLastCheckResult(void) const;
@ -179,8 +175,8 @@ public:
static ServiceState StateFromString(const String& state);
static String StateToString(ServiceState state);
static ServiceStateType StateTypeFromString(const String& state);
static String StateTypeToString(ServiceStateType state);
static StateType StateTypeFromString(const String& state);
static String StateTypeToString(StateType state);
static signals2::signal<void (const Service::Ptr&)> OnCheckerChanged;
static signals2::signal<void (const Service::Ptr&)> OnNextCheckChanged;
@ -236,8 +232,8 @@ public:
double GetNotificationInterval(void) const;
void RequestNotifications(NotificationType type);
void SendNotifications(NotificationType type);
void RequestNotifications(NotificationType type, const Dictionary::Ptr& cr);
void SendNotifications(NotificationType type, const Dictionary::Ptr& cr);
set<Notification::Ptr> GetNotifications(void) const;
@ -276,6 +272,8 @@ private:
Attribute<long> m_CheckAttempt;
Attribute<long> m_State;
Attribute<long> m_StateType;
Attribute<long> m_LastState;
Attribute<long> m_LastStateType;
Attribute<Dictionary::Ptr> m_LastResult;
Attribute<double> m_LastStateChange;
Attribute<double> m_LastHardStateChange;