From c5e4bfa1c1aabb5c67c045f699aad54b0a7adf13 Mon Sep 17 00:00:00 2001 From: Guilherme Maciel Ferreira Date: Mon, 21 Mar 2011 15:58:20 +0100 Subject: [PATCH] The limit-ping-fail option is available (and read) from the configuration file - this option sets the threshold of pings to a host that must fail in order to mark the host as down. --- Readme | 19 +++++++++++++-- conf/pingcheck.conf | 1 + src/config/configuration.cpp | 17 ++++++++++++- src/config/configuration.h | 9 ++++++- src/config/configurationreader.cpp | 20 ++++++++++++++++- src/config/configurationreader.h | 3 ++ src/main.cpp | 12 +++++++-- src/ping/boostpinger.h | 3 ++ src/ping/pinganalyzer.cpp | 42 +++++++++++++++++++++++++---------- src/ping/pinganalyzer.h | 14 ++++++++++- src/ping/pingscheduler.cpp | 8 ++++-- src/ping/pingscheduler.h | 10 ++++++- 12 files changed, 128 insertions(+), 30 deletions(-) diff --git a/Readme b/Readme index 70a0101..c197b94 100644 --- a/Readme +++ b/Readme @@ -106,6 +106,16 @@ of error detection and handling: - Handle Exceptions for exceptional errors. +2.5. Assertions +--------------------------------------- +Also, it is good to use ASSERTS to document assumptions about: +- method's argument values. If you expect that a parameter have certain values, + assert it (preconditions) +- and if you expect the method deliver a certain value, assert in the end of + the method (postcondition). +This is known by programming by contract. + + 3. Source Code ======================================= @@ -157,9 +167,12 @@ configuration block. 4.1. General --------------------------------------- This configurations are shared among and affect all the hosts. -- limit-hosts-down: ranges from 0 to the number of hosts available. This value - represents the minimum number of hosts that have to fail (i.e. do not reply - the ping) in order to alert any external system. +- limit-hosts-down: an absolute number, which ranges from 0 to the number of + hosts available. This value represents the minimum number of hosts that have + to fail (i.e. do not reply to the ping) in order to alert any external system. +- limit-ping-fail: percentage of pings to a host that can fail. If the + percentage of failed pings to a host exceed this number, then the host is + considered down. 4.2. Host diff --git a/conf/pingcheck.conf b/conf/pingcheck.conf index 5e5548b..799a7c8 100644 --- a/conf/pingcheck.conf +++ b/conf/pingcheck.conf @@ -1,4 +1,5 @@ limit-hosts-down=5 +limit-ping-fail=40 [host] name=www.intra2net.com diff --git a/src/config/configuration.cpp b/src/config/configuration.cpp index ea6bce0..468993f 100644 --- a/src/config/configuration.cpp +++ b/src/config/configuration.cpp @@ -11,9 +11,12 @@ using namespace std; Configuration::Configuration() : ConfigFileName( "" ), LimitHostsDown( 0 ), - Hosts(), MinLimitHostsDown( 0 ), - MaxLimitHostsDown( 50 ) + MaxLimitHostsDown( 50 ), + LimitPingFail( 0 ), + MinLimitPingFail( 0 ), + MaxLimitPingFail( 100 ), + Hosts() { } @@ -45,6 +48,16 @@ void Configuration::set_limit_hosts_down( const int limit_hosts_down ) this->LimitHostsDown = limit_hosts_down; } +int Configuration::get_limit_ping_fail() const +{ + return LimitPingFail; +} + +void Configuration::set_limit_ping_fail( const int limit_ping_fail ) +{ + LimitPingFail = limit_ping_fail; +} + vector< HostItem > Configuration::get_hosts() const { return Hosts; diff --git a/src/config/configuration.h b/src/config/configuration.h index b86335e..fa8d0a7 100644 --- a/src/config/configuration.h +++ b/src/config/configuration.h @@ -24,16 +24,21 @@ public: int get_limit_hosts_down() const; void set_limit_hosts_down( const int limit_hosts_down ); + int get_limit_ping_fail() const; + void set_limit_ping_fail( const int limit_ping_fail ); + std::vector get_hosts() const; void set_hosts( const std::vector &hosts_list ); private: std::string ConfigFileName; int LimitHostsDown; - std::vector Hosts; - const int MinLimitHostsDown; const int MaxLimitHostsDown; + int LimitPingFail; + const int MinLimitPingFail; + const int MaxLimitPingFail; + std::vector Hosts; }; diff --git a/src/config/configurationreader.cpp b/src/config/configurationreader.cpp index 2df1a63..06c2d0f 100644 --- a/src/config/configurationreader.cpp +++ b/src/config/configurationreader.cpp @@ -26,6 +26,9 @@ ConfigurationReader::ConfigurationReader() : DefaultLimitHostsDown( 1 ), LimitHostsDownCmdStr( "limit-hosts-down" ), LimitHostsDownCmdDesc( "Limit of host that have to be down in order to notify." ), + DefaultLimitPingFail( 50 ), + LimitPingFailCmdStr( "limit-ping-fail" ), + LimitPingFailCmdDesc( "Maximum percentage of pings that can fail for a given host." ), HostNameCmdStr( "host.name" ), HostNameCmdDesc( "Host address" ), DefaultHostInterval( 1 ), @@ -110,6 +113,7 @@ options_description ConfigurationReader::get_configuration_options() const options_description options( "Configuration" ); options.add_options() ( LimitHostsDownCmdStr.c_str(), value()->default_value( DefaultLimitHostsDown ), LimitHostsDownCmdDesc.c_str() ) + ( LimitPingFailCmdStr.c_str(), value()->default_value( DefaultLimitPingFail ), LimitPingFailCmdDesc.c_str() ) ( HostNameCmdStr.c_str(), value< vector >(), HostNameCmdDesc.c_str() ) ( HostIntervalCmdStr.c_str(), value< vector >(), HostIntervalCmdDesc.c_str() ) ; @@ -119,6 +123,7 @@ options_description ConfigurationReader::get_configuration_options() const bool ConfigurationReader::parse_configuration_options( const variables_map &vm ) { + // config-file if ( vm.count( ConfigFileCmdStr ) ) { string config_file_name = vm[ ConfigFileCmdStr ].as (); @@ -127,6 +132,7 @@ bool ConfigurationReader::parse_configuration_options( const variables_map &vm ) cout << ConfigFileCmdStr << "=" << config_file_name << endl; } + // limit-hosts-down if ( vm.count( LimitHostsDownCmdStr ) ) { int limit_host_down = vm[ LimitHostsDownCmdStr ].as (); @@ -135,6 +141,16 @@ bool ConfigurationReader::parse_configuration_options( const variables_map &vm ) cout << LimitHostsDownCmdStr << "=" << limit_host_down << endl; } + // limit-ping-fail + if ( vm.count( LimitPingFailCmdStr ) ) + { + int limit_ping_fail = vm[ LimitPingFailCmdStr ].as (); + Config.set_limit_ping_fail( limit_ping_fail ); + + cout << LimitPingFailCmdStr << "=" << limit_ping_fail << endl; + } + + // [host] name int hosts_names_total = 0; if ( vm.count( HostNameCmdStr ) ) { @@ -154,6 +170,7 @@ bool ConfigurationReader::parse_configuration_options( const variables_map &vm ) hosts_names_total = hosts_names.size(); } + // [host] interval int hosts_interval_total = 0; if ( vm.count( HostIntervalCmdStr ) ) { @@ -174,7 +191,8 @@ bool ConfigurationReader::parse_configuration_options( const variables_map &vm ) } // TODO deal when interval for a given host was not set. use DefaultHostInterval - BOOST_ASSERT(hosts_names_total == hosts_interval_total); + + BOOST_ASSERT( hosts_names_total == hosts_interval_total ); return true; } diff --git a/src/config/configurationreader.h b/src/config/configurationreader.h index a6dded0..f586892 100644 --- a/src/config/configurationreader.h +++ b/src/config/configurationreader.h @@ -64,6 +64,9 @@ private: const int DefaultLimitHostsDown; const std::string LimitHostsDownCmdStr; const std::string LimitHostsDownCmdDesc; + const int DefaultLimitPingFail; + const std::string LimitPingFailCmdStr; + const std::string LimitPingFailCmdDesc; const std::string HostNameCmdStr; const std::string HostNameCmdDesc; const int DefaultHostInterval; diff --git a/src/main.cpp b/src/main.cpp index ae4d889..1608ffd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,12 +1,14 @@ +#include + #include #include -#include #include "config/configurationreader.h" #include "config/host.h" #include "ping/pingscheduler.h" using namespace std; +using namespace boost; using namespace boost::asio; int main( int argc, char* argv[] ) @@ -18,8 +20,11 @@ int main( int argc, char* argv[] ) { io_service io_service; - // TODO init_pingers() Configuration config = config_reader.get_configuration(); + + int limit_ping_fail = config.get_limit_ping_fail(); + + // TODO init_pingers() vector< HostItem > hosts = config.get_hosts(); vector< PingSchedulerItem > scheduler_list; BOOST_FOREACH( HostItem host, hosts ) @@ -28,7 +33,8 @@ int main( int argc, char* argv[] ) int ping_interval = (*host).get_interval(); PingSchedulerItem scheduler( new PingScheduler( - io_service, ping_address, ping_interval + io_service, ping_address, ping_interval, + limit_ping_fail ) ); scheduler_list.push_back( scheduler ); diff --git a/src/ping/boostpinger.h b/src/ping/boostpinger.h index b8b840b..a1bbf12 100644 --- a/src/ping/boostpinger.h +++ b/src/ping/boostpinger.h @@ -11,6 +11,9 @@ class IcmpPacket; // BoostPinger //----------------------------------------------------------------------------- +/** + * @brief This class performs ping to host using Boost Asio. + */ class BoostPinger : public Pinger { public: diff --git a/src/ping/pinganalyzer.cpp b/src/ping/pinganalyzer.cpp index 72692ca..b7f4acd 100644 --- a/src/ping/pinganalyzer.cpp +++ b/src/ping/pinganalyzer.cpp @@ -5,6 +5,7 @@ #include using namespace std; +using namespace boost; //----------------------------------------------------------------------------- // PingAnalyzer @@ -12,16 +13,16 @@ using namespace std; PingAnalyzer::PingAnalyzer( const string &host_address, - const int ping_fail_threshold_percentage + const int limit_ping_fail_percentage ) : Notifier( host_address ), - PingFailThresholdPercentage( ping_fail_threshold_percentage ), + LimitPingFailPercentage( limit_ping_fail_percentage ), ResolvedIpCount( 0 ), PingsPerformedCount( 0 ), PingsFailedCount( 0 ) { BOOST_ASSERT( !host_address.empty() ); - BOOST_ASSERT( ( 0 <= ping_fail_threshold_percentage ) && ( ping_fail_threshold_percentage <= 100 ) ); + BOOST_ASSERT( ( 0 <= limit_ping_fail_percentage ) && ( limit_ping_fail_percentage <= 100 ) ); } PingAnalyzer::~PingAnalyzer() @@ -41,18 +42,20 @@ void PingAnalyzer::update_ping_statistics( bool ping_success ) BOOST_ASSERT( 0 <= PingsPerformedCount ); BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount ); - ++PingsPerformedCount; + increase_ping_performed_count(); if ( !ping_success ) { - ++PingsFailedCount; + increase_ping_failed_count(); } - if ( PingsPerformedCount >= ResolvedIpCount ) + // after we tried all IPs resolved for this host, we can analyze how many + // failed + if ( tried_all_resolved_ip() ) { analyze(); - reset_ping_counter(); + reset_ping_counters(); } BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount ); @@ -60,13 +63,13 @@ void PingAnalyzer::update_ping_statistics( bool ping_success ) void PingAnalyzer::analyze() { - BOOST_ASSERT( ( 0 <= PingFailThresholdPercentage ) && ( PingFailThresholdPercentage <= 100 ) ); - BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) ); BOOST_ASSERT( PingsPerformedCount == ResolvedIpCount ); + BOOST_ASSERT( ( 0 <= LimitPingFailPercentage ) && ( LimitPingFailPercentage <= 100 ) ); + BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) ); - int ping_fail_threshold_absolute = PingFailThresholdPercentage / 100; // TODO possible number loss, check with care + int limit_ping_fail_absolute = LimitPingFailPercentage / 100; // TODO possible precision loss, check with care - if ( PingsFailedCount > ping_fail_threshold_absolute ) + if ( PingsFailedCount > limit_ping_fail_absolute ) { Notifier.alert_host_down(); } @@ -77,8 +80,23 @@ void PingAnalyzer::analyze() } -void PingAnalyzer::reset_ping_counter() +void PingAnalyzer::increase_ping_performed_count() +{ + ++PingsPerformedCount; +} + +void PingAnalyzer::increase_ping_failed_count() +{ + ++PingsFailedCount; +} + +void PingAnalyzer::reset_ping_counters() { PingsPerformedCount = 0; PingsFailedCount = 0; } + +bool PingAnalyzer::tried_all_resolved_ip() const +{ + return ( PingsPerformedCount >= ResolvedIpCount ); +} diff --git a/src/ping/pinganalyzer.h b/src/ping/pinganalyzer.h index b97adc4..e7033cc 100644 --- a/src/ping/pinganalyzer.h +++ b/src/ping/pinganalyzer.h @@ -3,12 +3,19 @@ #include +#include + #include "ping/pingstatusnotifier.h" //----------------------------------------------------------------------------- // PingAnalyzer //----------------------------------------------------------------------------- +/** + * @brief This class analyze the ping status (success or failure) and decides + * what to do. + * Scope: one object per host. + */ class PingAnalyzer { public: @@ -23,11 +30,14 @@ public: private: void analyze(); - void reset_ping_counter(); + void increase_ping_performed_count(); + void increase_ping_failed_count(); + void reset_ping_counters(); + bool tried_all_resolved_ip() const; private: PingStatusNotifier Notifier; - int PingFailThresholdPercentage; + int LimitPingFailPercentage; int ResolvedIpCount; int PingsPerformedCount; int PingsFailedCount; diff --git a/src/ping/pingscheduler.cpp b/src/ping/pingscheduler.cpp index 499751d..38a7ee3 100644 --- a/src/ping/pingscheduler.cpp +++ b/src/ping/pingscheduler.cpp @@ -19,14 +19,16 @@ using namespace boost::posix_time; PingScheduler::PingScheduler( boost::asio::io_service &io_service, const string &ping_address, - const int ping_interval_in_sec + const int ping_interval_in_sec, + const int limit_ping_fail_percentage + ) : IoService( io_service ), Timer( io_service ), TimeSentLastPing( microsec_clock::universal_time() ), - IpList( ping_address ), PingIntervalInSec( ping_interval_in_sec ), - Analyzer( ping_address, 50 ) // 50% max acceptable failure + IpList( ping_address ), + Analyzer( ping_address, limit_ping_fail_percentage ) { } diff --git a/src/ping/pingscheduler.h b/src/ping/pingscheduler.h index 1060477..d9b9d5a 100644 --- a/src/ping/pingscheduler.h +++ b/src/ping/pingscheduler.h @@ -13,13 +13,19 @@ // PingScheduler //----------------------------------------------------------------------------- +/** + * @brief This class is responsible to control whether to ping a host. It + * schedules periodic pings to a host. + * Scope: one object per host. + */ class PingScheduler { public: PingScheduler( boost::asio::io_service &io_service, const std::string &ping_address, - const int ping_interval_in_sec + const int ping_interval_in_sec, + const int limit_ping_fail_percentage ); virtual ~PingScheduler(); @@ -38,8 +44,8 @@ private: boost::asio::io_service &IoService; boost::asio::deadline_timer Timer; boost::posix_time::ptime TimeSentLastPing; - DnsResolver IpList; const int PingIntervalInSec; + DnsResolver IpList; PingAnalyzer Analyzer; }; -- 1.7.1