From f1bf324961ac4694dad50acbd2444931e49153e9 Mon Sep 17 00:00:00 2001 From: Guilherme Maciel Ferreira Date: Wed, 30 Mar 2011 12:12:21 +0200 Subject: [PATCH] Implemented the requirement "If we notified an external system that a link is down, also notify it if the link is back up (=stable for a configurable period of time)" - the status of the link is reported only once, when it changes from down to up, or vice versa - allows to configure the minimum amount of time the link must stays stable in order to report its status --- src/main.cpp | 7 +++- src/notify/linkstatusanalyzer.cpp | 90 ++++++++++++++++++++++++++++++++----- src/notify/linkstatusanalyzer.h | 37 +++++++++++++++- 3 files changed, 120 insertions(+), 14 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e9de4bc..0ff8247 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,12 +25,17 @@ int main( int argc, char* argv[] ) Configuration config = config_reader.get_configuration(); int ping_fail_limit = config.get_ping_fail_limit(); + int link_up_interval = config.get_link_up_interval(); // TODO init_notifier and get_notifier int hosts_down_limit = config.get_hosts_down_limit(); string status_notifier_cmd = config.get_status_notifier_cmd(); shared_ptr link_analyzer( - new LinkStatusAnalyzer( hosts_down_limit, status_notifier_cmd ) + new LinkStatusAnalyzer( + hosts_down_limit, + link_up_interval, + status_notifier_cmd + ) ); // TODO init_pingers() diff --git a/src/notify/linkstatusanalyzer.cpp b/src/notify/linkstatusanalyzer.cpp index 93f9023..ecc1f8f 100644 --- a/src/notify/linkstatusanalyzer.cpp +++ b/src/notify/linkstatusanalyzer.cpp @@ -5,6 +5,7 @@ #include using namespace std; +using namespace boost::posix_time; //----------------------------------------------------------------------------- // LinkStatusAnalyzer @@ -12,13 +13,19 @@ using namespace std; LinkStatusAnalyzer::LinkStatusAnalyzer( const int hosts_down_limit, + const int link_up_interval_in_min, const string &status_notifier_cmd ) : HostsDownLimit( hosts_down_limit ), - StatusNotifierCmd( status_notifier_cmd ), - HostsDownList() + HostsDownList(), + LinkUpIntervalInMin( link_up_interval_in_min ), + CurrentLinkStatus( LinkStatus_Down ), + CurrentNotificationStatus( NotificationStatus_NotReported ), + TimeLinkStatusChanged( microsec_clock::universal_time() ), + StatusNotifierCmd( status_notifier_cmd ) { BOOST_ASSERT( 0 <= hosts_down_limit ); + BOOST_ASSERT( 0 <= link_up_interval_in_min ); BOOST_ASSERT( !status_notifier_cmd.empty() ); } @@ -81,20 +88,79 @@ bool LinkStatusAnalyzer::exceeded_host_down_limit() const void LinkStatusAnalyzer::notify_link_up() { - StatusNotifierCmd.set_token_value( - StatusNotifierCommand::StatusToken, - "up" - ); + set_link_status( LinkStatus_Up ); - StatusNotifierCmd.execute(); + // report the link status only if it is up longer than a configured amount + // of time and if we haven't reported the new status yet + if ( is_link_up_enough_time() && can_report_link_status() ) + { + BOOST_ASSERT( CurrentLinkStatus == LinkStatus_Up ); + BOOST_ASSERT( CurrentNotificationStatus == NotificationStatus_NotReported ); + + StatusNotifierCmd.set_token_value( + StatusNotifierCommand::StatusToken, + "up" + ); + + StatusNotifierCmd.execute(); + + CurrentNotificationStatus = NotificationStatus_Reported; + } } void LinkStatusAnalyzer::notify_link_down() { - StatusNotifierCmd.set_token_value( - StatusNotifierCommand::StatusToken, - "down" - ); + set_link_status( LinkStatus_Down ); + + if ( can_report_link_status() ) + { + BOOST_ASSERT( CurrentLinkStatus == LinkStatus_Down ); + BOOST_ASSERT( CurrentNotificationStatus == NotificationStatus_NotReported ); - StatusNotifierCmd.execute(); + StatusNotifierCmd.set_token_value( + StatusNotifierCommand::StatusToken, + "down" + ); + + StatusNotifierCmd.execute(); + + CurrentNotificationStatus = NotificationStatus_Reported; + } +} + +bool LinkStatusAnalyzer::is_link_up_enough_time() const +{ + if ( CurrentLinkStatus == LinkStatus_Up ) + { + ptime now = microsec_clock::universal_time(); + long amount_time_link_is_up = (now - TimeLinkStatusChanged).total_seconds(); + long link_up_interval_in_sec = LinkUpIntervalInMin * 60; + + if ( amount_time_link_is_up >= link_up_interval_in_sec ) + { + return true; + } + } + + return false; +} + +bool LinkStatusAnalyzer::can_report_link_status() const +{ + return ( CurrentNotificationStatus == NotificationStatus_NotReported ); +} + +void LinkStatusAnalyzer::set_link_status( + const LinkStatusAnalyzer::LinkStatus new_link_status +) +{ + // only reset the control flags if the link status has changed + if ( new_link_status != CurrentLinkStatus ) + { + CurrentLinkStatus = new_link_status; + TimeLinkStatusChanged = microsec_clock::universal_time(); + + // have to report the link status change + CurrentNotificationStatus = NotificationStatus_NotReported; + } } diff --git a/src/notify/linkstatusanalyzer.h b/src/notify/linkstatusanalyzer.h index dddc81a..5dedceb 100644 --- a/src/notify/linkstatusanalyzer.h +++ b/src/notify/linkstatusanalyzer.h @@ -4,6 +4,8 @@ #include #include +#include + #include "notify/statusnotifiercommand.h" //----------------------------------------------------------------------------- @@ -20,6 +22,7 @@ class LinkStatusAnalyzer public: LinkStatusAnalyzer( const int hosts_down_limit, + const int link_up_interval_in_min, const std::string &status_notifier_cmd ); virtual ~LinkStatusAnalyzer(); @@ -28,6 +31,19 @@ public: void notify_host_down( const std::string &host_address ); private: + enum LinkStatus + { + LinkStatus_Up, + LinkStatus_Down + }; + + enum NotificationStatus + { + NotificationStatus_NotReported, + NotificationStatus_Reported + }; + +private: void add_host_up( const std::string &host_address ); void add_host_down( const std::string &host_address ); @@ -36,10 +52,29 @@ private: void notify_link_up(); void notify_link_down(); + bool is_link_up_enough_time() const; + + bool can_report_link_status() const; + void set_link_status( + const LinkStatusAnalyzer::LinkStatus new_link_status + ); + private: + /// the maximum amount of hosts which can be down before sound the alarm const int HostsDownLimit; - StatusNotifierCommand StatusNotifierCmd; + /// list of host down (obvious isn't it?) std::set HostsDownList; + /// interval the link have to be stable in order to consider it is functional + const int LinkUpIntervalInMin; + /// keep track of the actual link status + LinkStatusAnalyzer::LinkStatus CurrentLinkStatus; + /// indicates if was notified the last link status change + LinkStatusAnalyzer::NotificationStatus CurrentNotificationStatus; + /// when was the last time the status changed + boost::posix_time::ptime TimeLinkStatusChanged; + /// + StatusNotifierCommand StatusNotifierCmd; + }; -- 1.7.1