2013-01-29 14:50:51 +01:00
/******************************************************************************
* Icinga 2 *
2014-03-19 01:02:29 +01:00
* Copyright ( C ) 2012 - 2014 Icinga Development Team ( http : //www.icinga.org) *
2013-01-29 14:50:51 +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/service.hpp"
# include "base/dynamictype.hpp"
# include "base/objectlock.hpp"
# include "base/logger_fwd.hpp"
# include "base/timer.hpp"
# include "base/utility.hpp"
# include "base/convert.hpp"
2013-03-16 21:18:53 +01:00
# include <boost/foreach.hpp>
2013-01-29 14:50:51 +01:00
using namespace icinga ;
2013-03-18 11:02:18 +01:00
static int l_NextDowntimeID = 1 ;
static boost : : mutex l_DowntimeMutex ;
static std : : map < int , String > l_LegacyDowntimesCache ;
2014-04-03 15:36:13 +02:00
static std : : map < String , Checkable : : WeakPtr > l_DowntimesCache ;
2013-03-18 11:02:18 +01:00
static Timer : : Ptr l_DowntimesExpireTimer ;
2013-01-29 14:50:51 +01:00
2014-05-03 20:02:22 +02:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , const Downtime : : Ptr & , const MessageOrigin & ) > Checkable : : OnDowntimeAdded ;
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , const Downtime : : Ptr & , const MessageOrigin & ) > Checkable : : OnDowntimeRemoved ;
2014-04-03 15:36:13 +02:00
boost : : signals2 : : signal < void ( const Checkable : : Ptr & , const Downtime : : Ptr & ) > Checkable : : OnDowntimeTriggered ;
2013-06-28 16:08:43 +02:00
2014-05-09 19:26:31 +02:00
INITIALIZE_ONCE ( & Checkable : : StartDowntimesExpiredTimer ) ;
2014-04-03 15:36:13 +02:00
int Checkable : : GetNextDowntimeID ( void )
2013-01-29 14:50:51 +01:00
{
2013-03-18 11:02:18 +01:00
boost : : mutex : : scoped_lock lock ( l_DowntimeMutex ) ;
2013-03-02 09:07:47 +01:00
2013-03-18 11:02:18 +01:00
return l_NextDowntimeID ;
2013-01-29 14:50:51 +01:00
}
2014-04-03 15:36:13 +02:00
String Checkable : : AddDowntime ( const String & author , const String & comment ,
2013-02-09 01:16:43 +01:00
double startTime , double endTime , bool fixed ,
2013-11-13 14:56:31 +01:00
const String & triggeredBy , double duration , const String & scheduledBy ,
2014-05-03 20:02:22 +02:00
const String & id , const MessageOrigin & origin )
2013-01-29 14:50:51 +01:00
{
2013-08-28 16:08:22 +02:00
String uid ;
if ( id . IsEmpty ( ) )
uid = Utility : : NewUniqueID ( ) ;
else
uid = id ;
2013-11-09 22:08:26 +01:00
Downtime : : Ptr downtime = make_shared < Downtime > ( ) ;
downtime - > SetId ( uid ) ;
downtime - > SetEntryTime ( Utility : : GetTime ( ) ) ;
downtime - > SetAuthor ( author ) ;
downtime - > SetComment ( comment ) ;
downtime - > SetStartTime ( startTime ) ;
downtime - > SetEndTime ( endTime ) ;
downtime - > SetFixed ( fixed ) ;
downtime - > SetDuration ( duration ) ;
downtime - > SetTriggeredBy ( triggeredBy ) ;
2013-11-13 14:56:31 +01:00
downtime - > SetScheduledBy ( scheduledBy ) ;
2013-02-27 12:44:51 +01:00
2013-12-17 15:15:39 +01:00
if ( ! triggeredBy . IsEmpty ( ) ) {
Downtime : : Ptr triggerDowntime = GetDowntimeByID ( triggeredBy ) ;
2013-12-17 16:01:33 +01:00
if ( triggerDowntime )
downtime - > SetTriggeredByLegacyId ( triggerDowntime - > GetLegacyId ( ) ) ;
2013-12-17 15:15:39 +01:00
}
2013-02-27 12:44:51 +01:00
int legacy_id ;
{
2013-03-18 11:02:18 +01:00
boost : : mutex : : scoped_lock lock ( l_DowntimeMutex ) ;
legacy_id = l_NextDowntimeID + + ;
2013-02-27 12:44:51 +01:00
}
2013-11-09 22:08:26 +01:00
downtime - > SetLegacyId ( legacy_id ) ;
2013-01-29 14:50:51 +01:00
2013-01-31 13:57:14 +01:00
if ( ! triggeredBy . IsEmpty ( ) ) {
2014-04-03 15:36:13 +02:00
Checkable : : Ptr otherOwner = GetOwnerByDowntimeID ( triggeredBy ) ;
2013-10-26 09:41:45 +02:00
Dictionary : : Ptr otherDowntimes = otherOwner - > GetDowntimes ( ) ;
2013-11-09 22:08:26 +01:00
Downtime : : Ptr otherDowntime = otherDowntimes - > Get ( triggeredBy ) ;
Dictionary : : Ptr triggers = otherDowntime - > GetTriggers ( ) ;
2013-06-19 10:42:28 +02:00
2013-11-13 14:56:31 +01:00
triggers - > Set ( triggeredBy , triggeredBy ) ;
2013-01-31 13:57:14 +01:00
}
2013-02-09 01:16:43 +01:00
2013-10-26 09:41:45 +02:00
GetDowntimes ( ) - > Set ( uid , downtime ) ;
2013-01-29 15:00:06 +01:00
2013-07-11 08:58:11 +02:00
{
boost : : mutex : : scoped_lock lock ( l_DowntimeMutex ) ;
2013-08-28 16:08:22 +02:00
l_LegacyDowntimesCache [ legacy_id ] = uid ;
l_DowntimesCache [ uid ] = GetSelf ( ) ;
2013-07-11 08:58:11 +02:00
}
2014-05-22 23:47:03 +02:00
Log ( LogNotice , " icinga " , " Added downtime with ID ' " + Convert : : ToString ( downtime - > GetLegacyId ( ) ) +
2013-11-13 14:56:31 +01:00
" ' between ' " + Utility : : FormatDateTime ( " %Y-%m-%d %H:%M:%S " , startTime ) + " ' and ' " + Utility : : FormatDateTime ( " %Y-%m-%d %H:%M:%S " , endTime ) + " '. " ) ;
2013-09-17 19:37:10 +02:00
2014-05-03 20:02:22 +02:00
OnDowntimeAdded ( GetSelf ( ) , downtime , origin ) ;
2013-08-09 15:30:28 +02:00
2013-08-28 16:08:22 +02:00
return uid ;
2013-01-29 14:50:51 +01:00
}
2014-05-03 20:02:22 +02:00
void Checkable : : RemoveDowntime ( const String & id , bool cancelled , const MessageOrigin & origin )
2013-01-29 14:50:51 +01:00
{
2014-04-03 15:36:13 +02:00
Checkable : : Ptr owner = GetOwnerByDowntimeID ( id ) ;
2013-01-29 14:50:51 +01:00
2013-01-31 13:57:14 +01:00
if ( ! owner )
return ;
2013-02-09 01:16:43 +01:00
2013-03-02 09:07:47 +01:00
Dictionary : : Ptr downtimes = owner - > GetDowntimes ( ) ;
2013-01-29 14:50:51 +01:00
2013-11-09 22:08:26 +01:00
Downtime : : Ptr downtime = downtimes - > Get ( id ) ;
2013-06-28 13:40:01 +02:00
2013-08-29 09:36:44 +02:00
if ( ! downtime )
return ;
2013-11-09 22:08:26 +01:00
int legacy_id = downtime - > GetLegacyId ( ) ;
2013-06-28 13:40:01 +02:00
2014-05-04 16:57:11 +02:00
String config_owner = downtime - > GetConfigOwner ( ) ;
if ( ! config_owner . IsEmpty ( ) ) {
Log ( LogWarning , " icinga " , " Cannot remove downtime with ID ' " + Convert : : ToString ( legacy_id ) + " '. It is owned by scheduled downtime object ' " + config_owner + " ' " ) ;
return ;
}
2013-08-28 16:08:22 +02:00
downtimes - > Remove ( id ) ;
2013-08-09 15:30:28 +02:00
2013-08-28 16:08:22 +02:00
{
boost : : mutex : : scoped_lock lock ( l_DowntimeMutex ) ;
l_LegacyDowntimesCache . erase ( legacy_id ) ;
l_DowntimesCache . erase ( id ) ;
}
2013-09-17 19:37:10 +02:00
2013-11-09 22:08:26 +01:00
downtime - > SetWasCancelled ( cancelled ) ;
2013-09-17 19:37:10 +02:00
2014-05-22 23:47:03 +02:00
Log ( LogNotice , " icinga " , " Removed downtime with ID ' " + Convert : : ToString ( downtime - > GetLegacyId ( ) ) + " ' from service ' " + owner - > GetName ( ) + " '. " ) ;
2013-09-17 19:37:10 +02:00
2014-05-03 20:02:22 +02:00
OnDowntimeRemoved ( owner , downtime , origin ) ;
2013-01-31 13:57:14 +01:00
}
2014-04-03 15:36:13 +02:00
void Checkable : : TriggerDowntimes ( void )
2013-01-31 13:57:14 +01:00
{
2013-03-02 09:07:47 +01:00
Dictionary : : Ptr downtimes = GetDowntimes ( ) ;
2013-01-31 13:57:14 +01:00
2013-03-18 12:55:41 +01:00
std : : vector < String > ids ;
2013-02-27 12:44:51 +01:00
2013-03-18 12:55:41 +01:00
{
ObjectLock olock ( downtimes ) ;
2013-11-30 17:42:50 +01:00
BOOST_FOREACH ( const Dictionary : : Pair & kv , downtimes ) {
ids . push_back ( kv . first ) ;
2013-03-18 12:55:41 +01:00
}
}
BOOST_FOREACH ( const String & id , ids ) {
2013-01-31 13:57:14 +01:00
TriggerDowntime ( id ) ;
}
}
2014-04-03 15:36:13 +02:00
void Checkable : : TriggerDowntime ( const String & id )
2013-01-31 13:57:14 +01:00
{
2014-04-03 15:36:13 +02:00
Checkable : : Ptr owner = GetOwnerByDowntimeID ( id ) ;
2013-11-09 22:08:26 +01:00
Downtime : : Ptr downtime = GetDowntimeByID ( id ) ;
2013-01-31 13:57:14 +01:00
2013-02-27 12:44:51 +01:00
if ( ! downtime )
return ;
2013-11-09 22:16:53 +01:00
if ( downtime - > IsActive ( ) & & downtime - > IsTriggered ( ) ) {
2013-11-09 22:08:26 +01:00
Log ( LogDebug , " icinga " , " Not triggering downtime with ID ' " + Convert : : ToString ( downtime - > GetLegacyId ( ) ) + " ': already triggered. " ) ;
2013-09-17 19:37:10 +02:00
return ;
}
2013-11-09 22:16:53 +01:00
if ( downtime - > IsExpired ( ) ) {
2013-11-09 22:08:26 +01:00
Log ( LogDebug , " icinga " , " Not triggering downtime with ID ' " + Convert : : ToString ( downtime - > GetLegacyId ( ) ) + " ': expired. " ) ;
2013-09-17 19:37:10 +02:00
return ;
}
2014-05-22 23:47:03 +02:00
Log ( LogNotice , " icinga " , " Triggering downtime with ID ' " + Convert : : ToString ( downtime - > GetLegacyId ( ) ) + " '. " ) ;
2013-09-17 19:37:10 +02:00
2013-11-09 22:08:26 +01:00
if ( downtime - > GetTriggerTime ( ) = = 0 )
2013-11-09 22:16:53 +01:00
downtime - > SetTriggerTime ( Utility : : GetTime ( ) ) ;
2013-02-09 01:16:43 +01:00
2013-11-09 22:08:26 +01:00
Dictionary : : Ptr triggers = downtime - > GetTriggers ( ) ;
2013-03-04 15:52:42 +01:00
ObjectLock olock ( triggers ) ;
2013-11-30 17:42:50 +01:00
BOOST_FOREACH ( const Dictionary : : Pair & kv , triggers ) {
TriggerDowntime ( kv . first ) ;
2013-01-29 14:50:51 +01:00
}
2013-02-09 01:16:43 +01:00
2013-11-10 16:53:57 +01:00
OnDowntimeTriggered ( owner , downtime ) ;
2013-01-29 14:50:51 +01:00
}
2014-04-03 15:36:13 +02:00
String Checkable : : GetDowntimeIDFromLegacyID ( int id )
2013-01-30 09:59:22 +01:00
{
2013-03-18 11:02:18 +01:00
boost : : mutex : : scoped_lock lock ( l_DowntimeMutex ) ;
2013-02-09 01:16:43 +01:00
2013-03-18 11:02:18 +01:00
std : : map < int , String > : : iterator it = l_LegacyDowntimesCache . find ( id ) ;
2013-01-30 13:02:20 +01:00
2013-03-18 11:02:18 +01:00
if ( it = = l_LegacyDowntimesCache . end ( ) )
2013-01-31 13:57:14 +01:00
return Empty ;
2013-01-30 13:02:20 +01:00
return it - > second ;
2013-01-30 09:59:22 +01:00
}
2014-04-03 15:36:13 +02:00
Checkable : : Ptr Checkable : : GetOwnerByDowntimeID ( const String & id )
2013-01-29 14:50:51 +01:00
{
2013-03-18 11:02:18 +01:00
boost : : mutex : : scoped_lock lock ( l_DowntimeMutex ) ;
return l_DowntimesCache [ id ] . lock ( ) ;
2013-01-29 14:50:51 +01:00
}
2014-04-03 15:36:13 +02:00
Downtime : : Ptr Checkable : : GetDowntimeByID ( const String & id )
2013-01-29 14:50:51 +01:00
{
2014-04-03 15:36:13 +02:00
Checkable : : Ptr owner = GetOwnerByDowntimeID ( id ) ;
2013-01-29 16:29:09 +01:00
if ( ! owner )
2013-11-09 22:08:26 +01:00
return Downtime : : Ptr ( ) ;
2013-01-29 14:50:51 +01:00
2013-03-02 09:07:47 +01:00
Dictionary : : Ptr downtimes = owner - > GetDowntimes ( ) ;
2013-01-29 14:50:51 +01:00
2013-03-02 09:07:47 +01:00
if ( downtimes )
return downtimes - > Get ( id ) ;
2013-01-29 14:50:51 +01:00
2013-11-09 22:08:26 +01:00
return Downtime : : Ptr ( ) ;
2013-01-29 14:50:51 +01:00
}
2014-04-03 15:36:13 +02:00
void Checkable : : StartDowntimesExpiredTimer ( void )
2013-09-17 20:11:29 +02:00
{
2013-12-12 06:30:11 +01:00
l_DowntimesExpireTimer = make_shared < Timer > ( ) ;
l_DowntimesExpireTimer - > SetInterval ( 60 ) ;
2014-04-03 15:36:13 +02:00
l_DowntimesExpireTimer - > OnTimerExpired . connect ( boost : : bind ( & Checkable : : DowntimesExpireTimerHandler ) ) ;
2013-12-12 06:30:11 +01:00
l_DowntimesExpireTimer - > Start ( ) ;
2013-09-17 20:11:29 +02:00
}
2014-04-03 15:36:13 +02:00
void Checkable : : AddDowntimesToCache ( void )
2013-01-29 14:50:51 +01:00
{
2013-11-13 14:56:31 +01:00
# ifdef _DEBUG
2014-04-03 15:36:13 +02:00
Log ( LogDebug , " icinga " , " Updating Checkable downtimes cache. " ) ;
2013-11-13 14:56:31 +01:00
# endif /* _DEBUG */
2013-03-06 13:01:51 +01:00
2013-08-20 11:06:04 +02:00
Dictionary : : Ptr downtimes = GetDowntimes ( ) ;
2013-01-29 14:50:51 +01:00
2013-08-20 11:06:04 +02:00
boost : : mutex : : scoped_lock lock ( l_DowntimeMutex ) ;
2013-01-29 14:50:51 +01:00
2013-08-20 11:06:04 +02:00
ObjectLock olock ( downtimes ) ;
2013-01-29 14:50:51 +01:00
2013-11-30 17:42:50 +01:00
BOOST_FOREACH ( const Dictionary : : Pair & kv , downtimes ) {
Downtime : : Ptr downtime = kv . second ;
2013-11-09 22:08:26 +01:00
int legacy_id = downtime - > GetLegacyId ( ) ;
2013-02-27 12:44:51 +01:00
2013-08-20 11:06:04 +02:00
if ( legacy_id > = l_NextDowntimeID )
l_NextDowntimeID = legacy_id + 1 ;
2013-01-30 14:28:13 +01:00
2013-11-30 17:42:50 +01:00
l_LegacyDowntimesCache [ legacy_id ] = kv . first ;
l_DowntimesCache [ kv . first ] = GetSelf ( ) ;
2013-01-30 14:28:13 +01:00
}
}
2014-04-03 15:36:13 +02:00
void Checkable : : RemoveExpiredDowntimes ( void )
2013-01-30 14:28:13 +01:00
{
2013-03-02 09:07:47 +01:00
Dictionary : : Ptr downtimes = GetDowntimes ( ) ;
2013-01-30 14:28:13 +01:00
2013-03-16 21:18:53 +01:00
std : : vector < String > expiredDowntimes ;
2013-01-30 14:28:13 +01:00
2013-03-04 15:52:42 +01:00
{
ObjectLock olock ( downtimes ) ;
2013-02-27 12:44:51 +01:00
2013-11-30 17:42:50 +01:00
BOOST_FOREACH ( const Dictionary : : Pair & kv , downtimes ) {
Downtime : : Ptr downtime = kv . second ;
2013-11-09 22:16:53 +01:00
if ( downtime - > IsExpired ( ) )
2013-11-30 17:42:50 +01:00
expiredDowntimes . push_back ( kv . first ) ;
2013-03-04 15:52:42 +01:00
}
2013-01-30 14:28:13 +01:00
}
2013-09-18 10:30:20 +02:00
BOOST_FOREACH ( const String & id , expiredDowntimes ) {
RemoveDowntime ( id , false ) ;
2013-01-30 14:28:13 +01:00
}
}
2014-04-03 15:36:13 +02:00
void Checkable : : DowntimesExpireTimerHandler ( void )
2013-01-30 14:28:13 +01:00
{
2014-04-03 15:36:13 +02:00
BOOST_FOREACH ( const Host : : Ptr & host , DynamicType : : GetObjects < Host > ( ) ) {
host - > RemoveExpiredDowntimes ( ) ;
}
2013-08-20 11:06:04 +02:00
BOOST_FOREACH ( const Service : : Ptr & service , DynamicType : : GetObjects < Service > ( ) ) {
2013-02-09 01:16:43 +01:00
service - > RemoveExpiredDowntimes ( ) ;
2013-01-30 14:28:13 +01:00
}
2013-01-29 14:50:51 +01:00
}
2013-02-09 17:27:32 +01:00
2014-04-03 15:36:13 +02:00
bool Checkable : : IsInDowntime ( void ) const
2013-02-09 17:27:32 +01:00
{
Dictionary : : Ptr downtimes = GetDowntimes ( ) ;
2013-02-27 12:44:51 +01:00
ObjectLock olock ( downtimes ) ;
2013-11-30 17:42:50 +01:00
BOOST_FOREACH ( const Dictionary : : Pair & kv , downtimes ) {
Downtime : : Ptr downtime = kv . second ;
2013-11-09 22:16:53 +01:00
if ( downtime - > IsActive ( ) )
2013-02-09 17:27:32 +01:00
return true ;
}
return false ;
}
2013-07-05 09:35:49 +02:00
2014-04-03 15:36:13 +02:00
int Checkable : : GetDowntimeDepth ( void ) const
2013-07-05 09:35:49 +02:00
{
int downtime_depth = 0 ;
Dictionary : : Ptr downtimes = GetDowntimes ( ) ;
ObjectLock olock ( downtimes ) ;
2013-11-30 17:42:50 +01:00
BOOST_FOREACH ( const Dictionary : : Pair & kv , downtimes ) {
Downtime : : Ptr downtime = kv . second ;
2013-11-09 22:16:53 +01:00
if ( downtime - > IsActive ( ) )
2013-07-05 09:35:49 +02:00
downtime_depth + + ;
}
return downtime_depth ;
}
2013-11-13 14:56:31 +01:00