2013-02-09 18:39:43 +01:00
/******************************************************************************
* Icinga 2 *
2015-01-22 12:00:23 +01:00
* Copyright ( C ) 2012 - 2015 Icinga Development Team ( http : //www.icinga.org) *
2013-02-09 18:39:43 +01:00
* *
* 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 . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-05-25 16:23:35 +02:00
# include "icinga/checkable.hpp"
# include "icinga/service.hpp"
# include "icinga/host.hpp"
# include "icinga/checkcommand.hpp"
# include "icinga/icingaapplication.hpp"
# include "icinga/cib.hpp"
2014-11-13 11:23:57 +01:00
# include "icinga/apievents.hpp"
2014-05-25 16:23:35 +02:00
# include "remote/messageorigin.hpp"
2014-11-13 11:23:57 +01:00
# include "remote/apilistener.hpp"
2014-05-25 16:23:35 +02:00
# include "base/objectlock.hpp"
2014-10-19 14:21:12 +02:00
# include "base/logger.hpp"
2014-05-25 16:23:35 +02:00
# include "base/convert.hpp"
# include "base/utility.hpp"
# include "base/context.hpp"
2013-03-16 21:18:53 +01:00
# include <boost/foreach.hpp>
2013-02-09 18:39:43 +01:00
using namespace icinga ;
2014-05-03 20:02:22 +02:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , const CheckResult : : Ptr & , const MessageOrigin & ) > Checkable : : OnNewCheckResult ;
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , const CheckResult : : Ptr & , StateType , const MessageOrigin & ) > Checkable : : OnStateChange ;
2014-12-12 15:53:10 +01:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , const CheckResult : : Ptr & , std : : set < Checkable : : Ptr > , const MessageOrigin & ) > Checkable : : OnReachabilityChanged ;
2014-04-03 15:36:13 +02:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , NotificationType , const CheckResult : : Ptr & , const String & , const String & ) > Checkable : : OnNotificationsRequested ;
2014-05-03 20:02:22 +02:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , double , const MessageOrigin & ) > Checkable : : OnNextCheckChanged ;
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , bool , const MessageOrigin & ) > Checkable : : OnForceNextCheckChanged ;
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , bool , const MessageOrigin & ) > Checkable : : OnForceNextNotificationChanged ;
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , bool , const MessageOrigin & ) > Checkable : : OnEnableActiveChecksChanged ;
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , bool , const MessageOrigin & ) > Checkable : : OnEnablePassiveChecksChanged ;
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , bool , const MessageOrigin & ) > Checkable : : OnEnableNotificationsChanged ;
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , bool , const MessageOrigin & ) > Checkable : : OnEnableFlappingChanged ;
2014-08-26 12:02:55 +02:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , double , const MessageOrigin & ) > Checkable : : OnCheckIntervalChanged ;
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , double , const MessageOrigin & ) > Checkable : : OnRetryIntervalChanged ;
2014-08-26 13:13:12 +02:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , const CheckCommand : : Ptr & , const MessageOrigin & ) > Checkable : : OnCheckCommandChanged ;
2014-08-26 13:18:02 +02:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , int , const MessageOrigin & ) > Checkable : : OnMaxCheckAttemptsChanged ;
2014-08-26 13:25:15 +02:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , const TimePeriod : : Ptr & , const MessageOrigin & ) > Checkable : : OnCheckPeriodChanged ;
2014-04-03 15:36:13 +02:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , FlappingState ) > Checkable : : OnFlappingChanged ;
CheckCommand : : Ptr Checkable : : GetCheckCommand ( void ) const
2013-02-09 18:39:43 +01:00
{
2013-11-26 12:56:42 +01:00
String command ;
if ( ! GetOverrideCheckCommand ( ) . IsEmpty ( ) )
command = GetOverrideCheckCommand ( ) ;
else
command = GetCheckCommandRaw ( ) ;
return CheckCommand : : GetByName ( command ) ;
}
2014-08-26 13:13:12 +02:00
void Checkable : : SetCheckCommand ( const CheckCommand : : Ptr & command , const MessageOrigin & origin )
2013-11-26 12:56:42 +01:00
{
SetOverrideCheckCommand ( command - > GetName ( ) ) ;
2014-08-26 13:13:12 +02:00
2014-11-08 21:17:16 +01:00
OnCheckCommandChanged ( this , command , origin ) ;
2013-02-09 18:39:43 +01:00
}
2014-04-03 15:36:13 +02:00
TimePeriod : : Ptr Checkable : : GetCheckPeriod ( void ) const
2013-03-13 16:04:53 +01:00
{
2013-11-26 13:43:56 +01:00
String tp ;
if ( ! GetOverrideCheckPeriod ( ) . IsEmpty ( ) )
tp = GetOverrideCheckPeriod ( ) ;
else
tp = GetCheckPeriodRaw ( ) ;
return TimePeriod : : GetByName ( tp ) ;
}
2014-08-26 13:25:15 +02:00
void Checkable : : SetCheckPeriod ( const TimePeriod : : Ptr & tp , const MessageOrigin & origin )
2013-11-26 13:43:56 +01:00
{
SetOverrideCheckPeriod ( tp - > GetName ( ) ) ;
2014-08-26 13:25:15 +02:00
2014-11-08 21:17:16 +01:00
OnCheckPeriodChanged ( this , tp , origin ) ;
2013-03-13 16:04:53 +01:00
}
2014-04-03 15:36:13 +02:00
double Checkable : : GetCheckInterval ( void ) const
2013-02-09 18:39:43 +01:00
{
2013-10-26 09:41:45 +02:00
if ( ! GetOverrideCheckInterval ( ) . IsEmpty ( ) )
return GetOverrideCheckInterval ( ) ;
2013-10-16 13:02:21 +02:00
else
2013-10-26 09:41:45 +02:00
return GetCheckIntervalRaw ( ) ;
2013-10-16 13:02:21 +02:00
}
2013-02-09 18:39:43 +01:00
2014-08-26 12:02:55 +02:00
void Checkable : : SetCheckInterval ( double interval , const MessageOrigin & origin )
2013-10-16 13:02:21 +02:00
{
2013-10-26 09:41:45 +02:00
SetOverrideCheckInterval ( interval ) ;
2014-08-26 12:02:55 +02:00
2014-11-08 21:17:16 +01:00
OnCheckIntervalChanged ( this , interval , origin ) ;
2013-02-09 18:39:43 +01:00
}
2014-04-03 15:36:13 +02:00
double Checkable : : GetRetryInterval ( void ) const
2013-02-09 18:39:43 +01:00
{
2013-10-26 09:41:45 +02:00
if ( ! GetOverrideRetryInterval ( ) . IsEmpty ( ) )
return GetOverrideRetryInterval ( ) ;
2013-10-16 13:02:21 +02:00
else
2013-10-26 09:41:45 +02:00
return GetRetryIntervalRaw ( ) ;
2013-10-16 13:02:21 +02:00
}
2013-02-09 18:39:43 +01:00
2014-08-26 12:02:55 +02:00
void Checkable : : SetRetryInterval ( double interval , const MessageOrigin & origin )
2013-10-16 13:02:21 +02:00
{
2013-10-26 09:41:45 +02:00
SetOverrideRetryInterval ( interval ) ;
2014-08-26 12:02:55 +02:00
2014-11-08 21:17:16 +01:00
OnRetryIntervalChanged ( this , interval , origin ) ;
2013-02-09 18:39:43 +01:00
}
2014-04-03 15:36:13 +02:00
void Checkable : : SetSchedulingOffset ( long offset )
2013-02-09 18:39:43 +01:00
{
2013-02-26 10:13:54 +01:00
m_SchedulingOffset = offset ;
2013-02-09 18:39:43 +01:00
}
2014-04-03 15:36:13 +02:00
long Checkable : : GetSchedulingOffset ( void )
2013-02-09 18:39:43 +01:00
{
2013-02-26 10:13:54 +01:00
return m_SchedulingOffset ;
2013-02-09 18:39:43 +01:00
}
2014-05-03 20:02:22 +02:00
void Checkable : : SetNextCheck ( double nextCheck , const MessageOrigin & origin )
2013-02-09 18:39:43 +01:00
{
2013-10-26 09:41:45 +02:00
SetNextCheckRaw ( nextCheck ) ;
2013-08-20 11:06:04 +02:00
2014-11-08 21:17:16 +01:00
OnNextCheckChanged ( this , nextCheck , origin ) ;
2013-02-09 18:39:43 +01:00
}
2014-04-03 15:36:13 +02:00
double Checkable : : GetNextCheck ( void )
2013-02-09 18:39:43 +01:00
{
2013-10-26 09:41:45 +02:00
return GetNextCheckRaw ( ) ;
2013-02-09 18:39:43 +01:00
}
2014-04-03 15:36:13 +02:00
void Checkable : : UpdateNextCheck ( void )
2013-02-09 18:39:43 +01:00
{
double interval ;
2013-11-15 12:50:23 +01:00
if ( GetStateType ( ) = = StateTypeSoft & & GetLastCheckResult ( ) ! = NULL )
2013-02-09 18:39:43 +01:00
interval = GetRetryInterval ( ) ;
else
interval = GetCheckInterval ( ) ;
double now = Utility : : GetTime ( ) ;
double adj = 0 ;
if ( interval > 1 )
2013-03-20 15:25:53 +01:00
adj = fmod ( now * 100 + GetSchedulingOffset ( ) , interval * 100 ) / 100.0 ;
2013-02-09 18:39:43 +01:00
SetNextCheck ( now - adj + interval ) ;
}
2014-04-03 15:36:13 +02:00
bool Checkable : : HasBeenChecked ( void ) const
2013-07-05 09:35:49 +02:00
{
2013-11-01 00:13:30 +01:00
return GetLastCheckResult ( ) ! = NULL ;
2013-07-05 09:35:49 +02:00
}
2014-04-03 15:36:13 +02:00
double Checkable : : GetLastCheck ( void ) const
2013-07-05 09:35:49 +02:00
{
2013-11-09 14:22:38 +01:00
CheckResult : : Ptr cr = GetLastCheckResult ( ) ;
2013-07-05 09:35:49 +02:00
double schedule_end = - 1 ;
2013-10-26 09:41:45 +02:00
if ( cr )
2013-11-09 14:22:38 +01:00
schedule_end = cr - > GetScheduleEnd ( ) ;
2013-07-05 09:35:49 +02:00
return schedule_end ;
}
2014-04-03 15:36:13 +02:00
bool Checkable : : GetEnableActiveChecks ( void ) const
2013-02-09 18:39:43 +01:00
{
2013-10-26 09:41:45 +02:00
if ( ! GetOverrideEnableActiveChecks ( ) . IsEmpty ( ) )
return GetOverrideEnableActiveChecks ( ) ;
2013-10-16 11:46:54 +02:00
else
2013-10-26 09:41:45 +02:00
return GetEnableActiveChecksRaw ( ) ;
2013-02-09 18:39:43 +01:00
}
2014-05-03 20:02:22 +02:00
void Checkable : : SetEnableActiveChecks ( bool enabled , const MessageOrigin & origin )
2013-02-09 18:39:43 +01:00
{
2013-10-26 09:41:45 +02:00
SetOverrideEnableActiveChecks ( enabled ) ;
2013-08-28 11:12:20 +02:00
2014-11-08 21:17:16 +01:00
OnEnableActiveChecksChanged ( this , enabled , origin ) ;
2013-02-09 18:39:43 +01:00
}
2014-04-03 15:36:13 +02:00
bool Checkable : : GetEnablePassiveChecks ( void ) const
2013-02-09 18:39:43 +01:00
{
2013-10-26 09:41:45 +02:00
if ( ! GetOverrideEnablePassiveChecks ( ) . IsEmpty ( ) )
return GetOverrideEnablePassiveChecks ( ) ;
2013-10-16 11:46:54 +02:00
else
2013-10-26 09:41:45 +02:00
return GetEnablePassiveChecksRaw ( ) ;
2013-02-09 18:39:43 +01:00
}
2014-05-03 20:02:22 +02:00
void Checkable : : SetEnablePassiveChecks ( bool enabled , const MessageOrigin & origin )
2013-02-09 18:39:43 +01:00
{
2013-10-26 09:41:45 +02:00
SetOverrideEnablePassiveChecks ( enabled ) ;
2013-08-28 11:12:20 +02:00
2014-11-08 21:17:16 +01:00
OnEnablePassiveChecksChanged ( this , enabled , origin ) ;
2013-02-09 18:39:43 +01:00
}
2014-04-03 15:36:13 +02:00
bool Checkable : : GetForceNextCheck ( void ) const
2013-02-09 18:39:43 +01:00
{
2013-10-26 09:41:45 +02:00
return GetForceNextCheckRaw ( ) ;
2013-02-09 18:39:43 +01:00
}
2014-05-03 20:02:22 +02:00
void Checkable : : SetForceNextCheck ( bool forced , const MessageOrigin & origin )
2013-02-09 18:39:43 +01:00
{
2013-10-26 09:41:45 +02:00
SetForceNextCheckRaw ( forced ) ;
2013-08-28 11:12:20 +02:00
2014-11-08 21:17:16 +01:00
OnForceNextCheckChanged ( this , forced , origin ) ;
2013-02-09 18:39:43 +01:00
}
2014-04-03 15:36:13 +02:00
int Checkable : : GetMaxCheckAttempts ( void ) const
2013-11-26 13:27:41 +01:00
{
if ( ! GetOverrideMaxCheckAttempts ( ) . IsEmpty ( ) )
return GetOverrideMaxCheckAttempts ( ) ;
else
return GetMaxCheckAttemptsRaw ( ) ;
}
2014-08-26 13:18:02 +02:00
void Checkable : : SetMaxCheckAttempts ( int attempts , const MessageOrigin & origin )
2013-11-26 13:27:41 +01:00
{
SetOverrideMaxCheckAttempts ( attempts ) ;
2014-08-26 13:18:02 +02:00
2014-11-08 21:17:16 +01:00
OnMaxCheckAttemptsChanged ( this , attempts , origin ) ;
2013-11-26 13:27:41 +01:00
}
2014-05-03 20:02:22 +02:00
void Checkable : : ProcessCheckResult ( const CheckResult : : Ptr & cr , const MessageOrigin & origin )
2013-02-09 18:39:43 +01:00
{
2014-03-12 10:05:36 +01:00
{
ObjectLock olock ( this ) ;
m_CheckRunning = false ;
}
2013-03-19 16:20:13 +01:00
double now = Utility : : GetTime ( ) ;
2013-11-09 14:22:38 +01:00
if ( cr - > GetScheduleStart ( ) = = 0 )
cr - > SetScheduleStart ( now ) ;
2013-03-19 16:20:13 +01:00
2013-11-09 14:22:38 +01:00
if ( cr - > GetScheduleEnd ( ) = = 0 )
cr - > SetScheduleEnd ( now ) ;
2013-03-19 16:20:13 +01:00
2013-11-09 14:22:38 +01:00
if ( cr - > GetExecutionStart ( ) = = 0 )
cr - > SetExecutionStart ( now ) ;
2013-03-19 16:20:13 +01:00
2013-11-09 14:22:38 +01:00
if ( cr - > GetExecutionEnd ( ) = = 0 )
cr - > SetExecutionEnd ( now ) ;
2013-03-19 16:20:13 +01:00
2014-05-03 20:02:22 +02:00
if ( origin . IsLocal ( ) )
2014-03-21 10:08:42 +01:00
cr - > SetCheckSource ( IcingaApplication : : GetInstance ( ) - > GetNodeName ( ) ) ;
2013-09-27 07:34:08 +02:00
2014-11-13 11:23:57 +01:00
Endpoint : : Ptr command_endpoint = GetCommandEndpoint ( ) ;
2015-01-18 22:15:35 +01:00
if ( command_endpoint & & GetExtension ( " agent_check " ) ) {
/* agent checks go through the api */
2014-11-13 11:23:57 +01:00
ApiListener : : Ptr listener = ApiListener : : GetInstance ( ) ;
if ( listener ) {
2015-01-18 22:15:35 +01:00
/* send message back to its origin */
2014-11-13 11:23:57 +01:00
Dictionary : : Ptr message = ApiEvents : : MakeCheckResultMessage ( this , cr ) ;
listener - > SyncSendMessage ( command_endpoint , message ) ;
2015-01-18 22:15:35 +01:00
/* HA cluster zone nodes must also process the check result locally
* by fetching the real host / service object if existing
*/
Host : : Ptr tempHost ;
Service : : Ptr tempService ;
tie ( tempHost , tempService ) = GetHostService ( this ) ;
Host : : Ptr realHost = Host : : GetByName ( tempHost - > GetName ( ) ) ;
if ( realHost ) {
Value agent_service_name = GetExtension ( " agent_service_name " ) ;
if ( ! agent_service_name . IsEmpty ( ) ) {
Checkable : : Ptr realCheckable ;
realCheckable = realHost - > GetServiceByShortName ( agent_service_name ) ;
if ( realCheckable ) {
realCheckable - > ProcessCheckResult ( cr , origin ) ;
}
}
}
2014-11-13 11:23:57 +01:00
}
return ;
2015-01-18 22:15:35 +01:00
2014-11-13 11:23:57 +01:00
}
2013-03-06 11:03:50 +01:00
bool reachable = IsReachable ( ) ;
2014-02-27 11:05:55 +01:00
bool notification_reachable = IsReachable ( DependencyNotification ) ;
2013-03-06 11:03:50 +01:00
2013-03-07 16:00:10 +01:00
ASSERT ( ! OwnsLock ( ) ) ;
2013-03-02 09:07:47 +01:00
ObjectLock olock ( this ) ;
2013-11-09 14:22:38 +01:00
CheckResult : : Ptr old_cr = GetLastCheckResult ( ) ;
2014-04-03 15:36:13 +02:00
ServiceState old_state = GetStateRaw ( ) ;
2013-03-07 12:04:20 +01:00
StateType old_stateType = GetStateType ( ) ;
2013-10-26 09:41:45 +02:00
long old_attempt = GetCheckAttempt ( ) ;
2014-07-22 14:13:21 +02:00
bool recovery = false ;
2013-02-09 18:39:43 +01:00
2013-11-09 14:22:38 +01:00
if ( old_cr & & cr - > GetExecutionStart ( ) < old_cr - > GetExecutionStart ( ) )
2013-09-12 17:39:29 +02:00
return ;
2013-03-25 18:36:15 +01:00
/* The ExecuteCheck function already sets the old state, but we need to do it again
2013-03-08 14:43:48 +01:00
* in case this was a passive check result . */
2014-04-03 15:36:13 +02:00
SetLastStateRaw ( old_state ) ;
2013-03-07 12:04:20 +01:00
SetLastStateType ( old_stateType ) ;
2013-03-19 13:04:30 +01:00
SetLastReachable ( reachable ) ;
2013-03-07 12:04:20 +01:00
2014-03-10 08:56:31 +01:00
long attempt = 1 ;
2013-02-09 18:39:43 +01:00
2014-12-12 15:53:10 +01:00
std : : set < Checkable : : Ptr > children = GetChildren ( ) ;
2014-03-06 11:39:32 +01:00
if ( ! old_cr ) {
SetStateType ( StateTypeHard ) ;
2014-04-08 09:11:54 +02:00
} else if ( cr - > GetState ( ) = = ServiceOK ) {
2014-07-16 11:48:36 +02:00
if ( old_state = = ServiceOK & & old_stateType = = StateTypeSoft ) {
2013-03-20 15:25:53 +01:00
SetStateType ( StateTypeHard ) ; // SOFT OK -> HARD OK
2014-07-16 11:48:36 +02:00
recovery = true ;
}
2013-02-09 18:39:43 +01:00
2014-07-22 14:13:21 +02:00
if ( old_state ! = ServiceOK )
recovery = true ; // NOT OK -> SOFT/HARD OK
2013-07-18 17:04:09 +02:00
ResetNotificationNumbers ( ) ;
2013-07-18 18:16:39 +02:00
SetLastStateOK ( Utility : : GetTime ( ) ) ;
2014-12-12 15:53:10 +01:00
/* update reachability for child objects in OK state */
if ( ! children . empty ( ) )
OnReachabilityChanged ( this , cr , children , origin ) ;
2013-02-09 18:39:43 +01:00
} else {
2013-03-19 13:04:30 +01:00
if ( old_attempt > = GetMaxCheckAttempts ( ) ) {
2013-02-09 18:39:43 +01:00
SetStateType ( StateTypeHard ) ;
2014-04-08 09:11:54 +02:00
} else if ( old_stateType = = StateTypeSoft | | old_state = = ServiceOK ) {
2013-02-09 18:39:43 +01:00
SetStateType ( StateTypeSoft ) ;
2013-03-19 13:04:30 +01:00
attempt = old_attempt + 1 ;
} else {
attempt = old_attempt ;
2013-02-09 18:39:43 +01:00
}
2013-02-24 01:10:34 +01:00
2013-11-09 14:22:38 +01:00
switch ( cr - > GetState ( ) ) {
2014-04-08 09:11:54 +02:00
case ServiceOK :
2013-12-17 07:55:46 +01:00
/* Nothing to do here. */
break ;
2014-04-08 09:11:54 +02:00
case ServiceWarning :
2013-11-09 14:22:38 +01:00
SetLastStateWarning ( Utility : : GetTime ( ) ) ;
break ;
2014-04-08 09:11:54 +02:00
case ServiceCritical :
2013-11-09 14:22:38 +01:00
SetLastStateCritical ( Utility : : GetTime ( ) ) ;
break ;
2014-04-08 09:11:54 +02:00
case ServiceUnknown :
2013-11-09 14:22:38 +01:00
SetLastStateUnknown ( Utility : : GetTime ( ) ) ;
break ;
}
2014-12-12 15:53:10 +01:00
/* update reachability for child objects in NOT-OK state */
if ( ! children . empty ( ) )
OnReachabilityChanged ( this , cr , children , origin ) ;
2013-02-09 18:39:43 +01:00
}
2013-07-18 18:28:23 +02:00
if ( ! reachable )
SetLastStateUnreachable ( Utility : : GetTime ( ) ) ;
2013-10-26 09:41:45 +02:00
SetCheckAttempt ( attempt ) ;
2013-02-09 18:39:43 +01:00
2014-04-03 15:36:13 +02:00
ServiceState new_state = cr - > GetState ( ) ;
SetStateRaw ( new_state ) ;
2013-02-09 18:39:43 +01:00
2014-04-03 15:36:13 +02:00
bool stateChange = ( old_state ! = new_state ) ;
2013-06-21 10:20:29 +02:00
if ( stateChange ) {
2013-02-09 18:39:43 +01:00
SetLastStateChange ( now ) ;
/* remove acknowledgements */
if ( GetAcknowledgement ( ) = = AcknowledgementNormal | |
2014-04-08 09:11:54 +02:00
( GetAcknowledgement ( ) = = AcknowledgementSticky & & new_state = = ServiceOK ) ) {
2013-08-29 13:48:18 +02:00
ClearAcknowledgement ( ) ;
2013-02-09 18:39:43 +01:00
}
2014-04-03 15:36:13 +02:00
/* reschedule direct parents */
BOOST_FOREACH ( const Checkable : : Ptr & parent , GetParents ( ) ) {
if ( parent . get ( ) = = this )
continue ;
2013-03-04 15:52:42 +01:00
ObjectLock olock ( parent ) ;
2013-02-09 18:39:43 +01:00
parent - > SetNextCheck ( Utility : : GetTime ( ) ) ;
}
}
2013-06-19 10:57:07 +02:00
bool remove_acknowledgement_comments = false ;
if ( GetAcknowledgement ( ) = = AcknowledgementNone )
remove_acknowledgement_comments = true ;
2013-03-20 15:25:53 +01:00
bool hardChange = ( GetStateType ( ) = = StateTypeHard & & old_stateType = = StateTypeSoft ) ;
2014-04-03 15:36:13 +02:00
if ( stateChange & & old_stateType = = StateTypeHard & & GetStateType ( ) = = StateTypeHard )
2013-03-21 11:37:34 +01:00
hardChange = true ;
2015-01-08 16:18:11 +01:00
bool is_volatile = GetVolatile ( ) ;
2013-06-13 12:24:20 +02:00
2015-01-08 16:18:11 +01:00
if ( hardChange | | is_volatile ) {
2014-04-03 15:36:13 +02:00
SetLastHardStateRaw ( new_state ) ;
2013-03-02 09:07:47 +01:00
SetLastHardStateChange ( now ) ;
2013-07-05 09:35:49 +02:00
}
2013-03-02 09:07:47 +01:00
2014-04-08 09:11:54 +02:00
if ( new_state ! = ServiceOK )
2013-02-09 18:39:43 +01:00
TriggerDowntimes ( ) ;
2014-05-26 20:56:34 +02:00
Host : : Ptr host ;
Service : : Ptr service ;
2014-11-08 21:17:16 +01:00
tie ( host , service ) = GetHostService ( this ) ;
2014-05-26 20:56:34 +02:00
CheckableType checkable_type = CheckableHost ;
if ( service )
checkable_type = CheckableService ;
/* statistics for external tools */
Checkable : : UpdateStatistics ( cr , checkable_type ) ;
2013-02-09 18:39:43 +01:00
2013-03-18 12:55:41 +01:00
bool in_downtime = IsInDowntime ( ) ;
2014-02-27 11:05:55 +01:00
bool send_notification = hardChange & & notification_reachable & & ! in_downtime & & ! IsAcknowledged ( ) ;
2013-03-18 12:55:41 +01:00
2014-03-10 13:54:16 +01:00
if ( ! old_cr )
send_notification = false ; /* Don't send notifications for the initial state change */
2014-04-08 09:11:54 +02:00
if ( old_state = = ServiceOK & & old_stateType = = StateTypeSoft )
2013-03-20 15:25:53 +01:00
send_notification = false ; /* Don't send notifications for SOFT-OK -> HARD-OK. */
2015-01-08 16:18:11 +01:00
if ( is_volatile & & old_state = = ServiceOK & & new_state = = ServiceOK )
send_notification = false ; /* Don't send notifications for volatile OK -> OK changes. */
2013-10-26 09:41:45 +02:00
bool send_downtime_notification = ( GetLastInDowntime ( ) ! = in_downtime ) ;
SetLastInDowntime ( in_downtime ) ;
2013-03-06 11:03:50 +01:00
2013-03-02 09:07:47 +01:00
olock . Unlock ( ) ;
2013-02-09 18:39:43 +01:00
2013-06-19 10:57:07 +02:00
if ( remove_acknowledgement_comments )
RemoveCommentsByType ( CommentAcknowledgement ) ;
2014-11-08 21:17:16 +01:00
Dictionary : : Ptr vars_after = new Dictionary ( ) ;
2014-04-03 15:36:13 +02:00
vars_after - > Set ( " state " , new_state ) ;
2013-03-19 13:04:30 +01:00
vars_after - > Set ( " state_type " , GetStateType ( ) ) ;
2013-10-26 09:41:45 +02:00
vars_after - > Set ( " attempt " , GetCheckAttempt ( ) ) ;
2013-03-19 13:04:30 +01:00
vars_after - > Set ( " reachable " , reachable ) ;
if ( old_cr )
2013-11-09 14:22:38 +01:00
cr - > SetVarsBefore ( old_cr - > GetVarsAfter ( ) ) ;
2013-03-19 13:04:30 +01:00
2013-11-09 14:22:38 +01:00
cr - > SetVarsAfter ( vars_after ) ;
2013-03-19 13:04:30 +01:00
2013-03-07 15:00:26 +01:00
olock . Lock ( ) ;
SetLastCheckResult ( cr ) ;
2013-06-21 10:20:29 +02:00
bool was_flapping , is_flapping ;
was_flapping = IsFlapping ( ) ;
2013-09-06 15:29:00 +02:00
if ( GetStateType ( ) = = StateTypeHard )
UpdateFlappingStatus ( stateChange ) ;
2013-06-21 10:20:29 +02:00
is_flapping = IsFlapping ( ) ;
2013-03-07 15:00:26 +01:00
olock . Unlock ( ) ;
2014-10-19 17:52:17 +02:00
// Log(LogDebug, "Checkable")
// << "Flapping: Checkable " << GetName()
// << " was: " << (was_flapping)
// << " is: " << is_flapping)
// << " threshold: " << GetFlappingThreshold()
// << "% current: " + GetFlappingCurrent()) << "%.";
2013-07-01 17:25:30 +02:00
2014-11-08 21:17:16 +01:00
OnNewCheckResult ( this , cr , origin ) ;
2014-03-09 18:06:24 +01:00
/* signal status updates to for example db_ido */
2014-11-08 21:17:16 +01:00
OnStateChanged ( this ) ;
2013-03-02 09:07:47 +01:00
2014-05-25 12:45:29 +02:00
String old_state_str = ( service ? Service : : StateToString ( old_state ) : Host : : StateToString ( Host : : CalculateState ( old_state ) ) ) ;
String new_state_str = ( service ? Service : : StateToString ( new_state ) : Host : : StateToString ( Host : : CalculateState ( new_state ) ) ) ;
2015-01-08 16:18:11 +01:00
if ( hardChange | | is_volatile ) {
2014-11-08 21:17:16 +01:00
OnStateChange ( this , cr , StateTypeHard , origin ) ;
2014-10-19 17:52:17 +02:00
Log ( LogNotice , " Checkable " )
2015-01-08 16:18:11 +01:00
< < " State Change: Checkable " < < GetName ( ) < < " hard state change from " < < old_state_str < < " to " < < new_state_str < < " detected. " < < ( is_volatile ? " Checkable is volatile. " : " " ) ;
2014-05-22 23:47:03 +02:00
} else if ( stateChange ) {
2014-11-08 21:17:16 +01:00
OnStateChange ( this , cr , StateTypeSoft , origin ) ;
2014-10-19 17:52:17 +02:00
Log ( LogNotice , " Checkable " )
< < " State Change: Checkable " < < GetName ( ) < < " soft state change from " < < old_state_str < < " to " < < new_state_str < < " detected. " ;
2014-05-22 23:47:03 +02:00
}
2013-09-25 18:01:08 +02:00
2015-01-08 16:18:11 +01:00
if ( GetStateType ( ) = = StateTypeSoft | | hardChange | | recovery | | is_volatile )
2013-06-13 11:33:00 +02:00
ExecuteEventHandler ( ) ;
2013-03-18 12:55:41 +01:00
if ( send_downtime_notification )
2014-11-08 21:17:16 +01:00
OnNotificationsRequested ( this , in_downtime ? NotificationDowntimeStart : NotificationDowntimeEnd , cr , " " , " " ) ;
2013-03-18 12:55:41 +01:00
2013-07-01 14:29:07 +02:00
if ( ! was_flapping & & is_flapping ) {
2014-11-08 21:17:16 +01:00
OnNotificationsRequested ( this , NotificationFlappingStart , cr , " " , " " ) ;
2013-07-01 17:25:30 +02:00
2014-10-19 17:52:17 +02:00
Log ( LogNotice , " Checkable " )
< < " Flapping: Checkable " < < GetName ( ) < < " started flapping ( " < < GetFlappingThreshold ( ) < < " % < " < < GetFlappingCurrent ( ) < < " %). " ;
2014-11-08 21:17:16 +01:00
OnFlappingChanged ( this , FlappingStarted ) ;
2013-08-20 11:06:04 +02:00
} else if ( was_flapping & & ! is_flapping ) {
2014-11-08 21:17:16 +01:00
OnNotificationsRequested ( this , NotificationFlappingEnd , cr , " " , " " ) ;
2013-07-01 17:25:30 +02:00
2014-10-19 17:52:17 +02:00
Log ( LogNotice , " Checkable " )
< < " Flapping: Checkable " < < GetName ( ) < < " stopped flapping ( " < < GetFlappingThreshold ( ) < < " % >= " < < GetFlappingCurrent ( ) < < " %). " ;
2014-11-08 21:17:16 +01:00
OnFlappingChanged ( this , FlappingStopped ) ;
2013-08-20 11:06:04 +02:00
} else if ( send_notification )
2014-11-08 21:17:16 +01:00
OnNotificationsRequested ( this , recovery ? NotificationRecovery : NotificationProblem , cr , " " , " " ) ;
2013-02-09 18:39:43 +01:00
}
2014-04-12 04:21:09 +02:00
bool Checkable : : IsCheckPending ( void ) const
{
ObjectLock olock ( this ) ;
return m_CheckRunning ;
}
2015-01-18 22:15:35 +01:00
void Checkable : : ExecuteRemoteCheck ( const Dictionary : : Ptr & resolvedMacros )
{
CONTEXT ( " Executing remote check for object ' " + GetName ( ) + " ' " ) ;
double scheduled_start = GetNextCheck ( ) ;
double before_check = Utility : : GetTime ( ) ;
CheckResult : : Ptr cr = new CheckResult ( ) ;
cr - > SetScheduleStart ( scheduled_start ) ;
cr - > SetExecutionStart ( before_check ) ;
GetCheckCommand ( ) - > Execute ( this , cr , resolvedMacros , true ) ;
}
void Checkable : : ExecuteCheck ( )
2013-02-09 18:39:43 +01:00
{
2014-04-03 15:36:13 +02:00
CONTEXT ( " Executing check for object ' " + GetName ( ) + " ' " ) ;
2013-11-19 07:49:41 +01:00
2013-03-07 16:00:10 +01:00
ASSERT ( ! OwnsLock ( ) ) ;
2013-02-24 01:10:34 +01:00
2014-03-13 14:09:52 +01:00
UpdateNextCheck ( ) ;
2013-03-19 14:13:58 +01:00
bool reachable = IsReachable ( ) ;
2013-03-06 11:03:50 +01:00
{
ObjectLock olock ( this ) ;
/* don't run another check if there is one pending */
2013-03-25 18:36:15 +01:00
if ( m_CheckRunning )
2013-03-06 11:03:50 +01:00
return ;
m_CheckRunning = true ;
2013-03-08 14:43:48 +01:00
2014-04-03 15:36:13 +02:00
SetLastStateRaw ( GetStateRaw ( ) ) ;
2013-03-08 14:43:48 +01:00
SetLastStateType ( GetLastStateType ( ) ) ;
2013-03-19 14:13:58 +01:00
SetLastReachable ( reachable ) ;
2013-02-09 18:39:43 +01:00
}
/* keep track of scheduling info in case the check type doesn't provide its own information */
2013-11-15 14:26:38 +01:00
double scheduled_start = GetNextCheck ( ) ;
2013-11-09 14:22:38 +01:00
double before_check = Utility : : GetTime ( ) ;
2013-02-24 01:10:34 +01:00
2015-01-18 22:15:35 +01:00
CheckResult : : Ptr cr = new CheckResult ( ) ;
2013-03-25 18:36:15 +01:00
2015-01-18 22:15:35 +01:00
cr - > SetScheduleStart ( scheduled_start ) ;
cr - > SetExecutionStart ( before_check ) ;
2013-02-09 18:39:43 +01:00
2014-11-13 11:23:57 +01:00
Endpoint : : Ptr endpoint = GetCommandEndpoint ( ) ;
2015-01-18 22:15:35 +01:00
bool local = ! endpoint | | endpoint = = Endpoint : : GetLocalEndpoint ( ) ;
2014-11-13 11:23:57 +01:00
2015-01-18 22:15:35 +01:00
if ( local ) {
GetCheckCommand ( ) - > Execute ( this , cr , NULL , false ) ;
} else {
Dictionary : : Ptr macros = new Dictionary ( ) ;
GetCheckCommand ( ) - > Execute ( this , cr , macros , false ) ;
2014-11-13 11:23:57 +01:00
if ( endpoint - > IsConnected ( ) ) {
2015-01-18 22:15:35 +01:00
/* perform check on remote endpoint */
2014-11-13 11:23:57 +01:00
Dictionary : : Ptr message = new Dictionary ( ) ;
message - > Set ( " jsonrpc " , " 2.0 " ) ;
message - > Set ( " method " , " event::ExecuteCommand " ) ;
Host : : Ptr host ;
Service : : Ptr service ;
tie ( host , service ) = GetHostService ( this ) ;
Dictionary : : Ptr params = new Dictionary ( ) ;
message - > Set ( " params " , params ) ;
params - > Set ( " command_type " , " check_command " ) ;
params - > Set ( " command " , GetCheckCommand ( ) - > GetName ( ) ) ;
params - > Set ( " host " , host - > GetName ( ) ) ;
if ( service )
params - > Set ( " service " , service - > GetShortName ( ) ) ;
params - > Set ( " macros " , macros ) ;
ApiListener : : Ptr listener = ApiListener : : GetInstance ( ) ;
if ( listener )
listener - > SyncSendMessage ( endpoint , message ) ;
2015-01-18 22:15:35 +01:00
2014-11-13 11:23:57 +01:00
} else if ( Application : : GetInstance ( ) - > GetStartTime ( ) < Utility : : GetTime ( ) - 30 ) {
2015-01-18 22:15:35 +01:00
/* fail to perform check on unconnected endpoint */
cr - > SetState ( ServiceUnknown ) ;
cr - > SetOutput ( " Remote Icinga instance ' " + endpoint - > GetName ( ) +
" ' " + " is not connected to ' " + Endpoint : : GetLocalEndpoint ( ) - > GetName ( ) + " ' " ) ;
ProcessCheckResult ( cr ) ;
2014-11-13 11:23:57 +01:00
}
{
ObjectLock olock ( this ) ;
m_CheckRunning = false ;
}
}
2013-02-09 18:39:43 +01:00
}
2013-02-11 23:37:39 +01:00
2014-05-26 20:56:34 +02:00
void Checkable : : UpdateStatistics ( const CheckResult : : Ptr & cr , CheckableType type )
2013-02-11 23:37:39 +01:00
{
2013-11-09 14:22:38 +01:00
time_t ts = cr - > GetScheduleEnd ( ) ;
2014-05-26 20:56:34 +02:00
if ( type = = CheckableHost ) {
if ( cr - > GetActive ( ) )
CIB : : UpdateActiveHostChecksStatistics ( ts , 1 ) ;
else
CIB : : UpdatePassiveHostChecksStatistics ( ts , 1 ) ;
} else if ( type = = CheckableService ) {
if ( cr - > GetActive ( ) )
CIB : : UpdateActiveServiceChecksStatistics ( ts , 1 ) ;
else
CIB : : UpdatePassiveServiceChecksStatistics ( ts , 1 ) ;
} else {
2014-05-28 13:45:45 +02:00
Log ( LogWarning , " Checkable " , " Unknown checkable type for statistic update. " ) ;
2014-05-26 20:56:34 +02:00
}
2013-02-11 23:37:39 +01:00
}
2013-02-24 01:10:34 +01:00
2014-04-03 15:36:13 +02:00
double Checkable : : CalculateExecutionTime ( const CheckResult : : Ptr & cr )
2013-02-24 01:10:34 +01:00
{
2013-11-09 14:22:38 +01:00
if ( ! cr )
return 0 ;
2013-02-24 01:10:34 +01:00
2013-11-09 14:22:38 +01:00
return cr - > GetExecutionEnd ( ) - cr - > GetExecutionStart ( ) ;
2013-02-24 01:10:34 +01:00
}
2014-04-03 15:36:13 +02:00
double Checkable : : CalculateLatency ( const CheckResult : : Ptr & cr )
2013-02-24 01:10:34 +01:00
{
2013-11-09 14:22:38 +01:00
if ( ! cr )
return 0 ;
2013-02-24 01:10:34 +01:00
2013-11-09 14:22:38 +01:00
double latency = ( cr - > GetScheduleEnd ( ) - cr - > GetScheduleStart ( ) ) - CalculateExecutionTime ( cr ) ;
2013-09-12 11:36:31 +02:00
if ( latency < 0 )
latency = 0 ;
return latency ;
2013-02-24 01:10:34 +01:00
}