*/
#include "config/configurationreader.h"
-#include <fstream>
-#include <iostream>
-#include <limits>
-
#include <boost/assert.hpp>
-#include <boost/foreach.hpp>
#include <logfunc.hpp>
+#include "config/configurationcommandline.h"
+#include "config/configurationfile.h"
+
using namespace std;
using boost::program_options::command_line_parser;
using boost::program_options::options_description;
// ConfigurationReader
//-----------------------------------------------------------------------------
+/**
+ * @brief Default constructor.
+ */
ConfigurationReader::ConfigurationReader() :
- Config(),
- HelpCmdStr( "help" ),
- HelpCmdDesc( "Print this help and exit." ),
- VersionCmdStr( "version" ),
- VersionCmdDesc( "Print the version string and exit." ),
- DaemonCmdStr( "daemon" ),
- DaemonCmdDesc( "Run the evil in background." ),
- DefaultConfigFileName( "/etc/pingcheck.conf" ),
- ConfigFileCmdStr( "config-file" ),
- ConfigFileCmdDesc( "Name of the configuration file." ),
- SourceNetworkInterfaceCmdStr( "source-network-interface" ),
- SourceNetworkInterfaceCmdDesc( "The network interface from where the packets will be received and originated" ),
- DefaultNameServer( "127.0.0.1" ),
- NameServerCmdStr( "nameserver" ),
- NameServerCmdDesc( "The local address from where the DNS query will be made." ),
- PingProtocolCmdStr( "ping-protocol" ),
- PingProtocolCmdDesc( "Defines which protocol will be used to ping the destination." ),
- DefaultHostsDownLimit( 0 ), // no host down
- HostsDownLimitCmdStr( "hosts-down-limit" ),
- HostsDownLimitCmdDesc( "Limit of host that have to be down in order to notify." ),
- DefaultPingFailLimit( 50 ), // 50 pings can fail at most
- PingFailLimitCmdStr( "ping-fail-limit" ),
- PingFailLimitCmdDesc( "Maximum percentage of pings that can fail for a given host." ),
- StatusNotifierCmdCmdStr( "status-notifier-cmd" ),
- StatusNotifierCmdCmdDesc( "The command to execute to alert about host status." ),
- DefaultLinkUpIntervalInMin( 5 ), // 5 minutes
- LinkUpIntervalCmdStr( "link-up-interval" ),
- LinkUpIntervalCmdDesc( "How long the link must be responsive in order to consider it stable." ),
- DefaultLinkDownIntervalInMin( 2 ), // 2 minutes
- LinkDownIntervalCmdStr( "link-down-interval" ),
- LinkDownIntervalCmdDesc( "How long the link must be offline in order to consider it down." ),
- HostNameCmdStr( "host.name" ),
- HostNameCmdDesc( "Host address" ),
- DefaultHostPort( 80 ), // HTTP port
- HostPortCmdStr( "host.port" ),
- HostPortCmdDesc( "Host port number" ),
- DefaultHostIntervalInSec( 60 ), // 60 seconds
- HostIntervalCmdStr( "host.interval" ),
- HostIntervalCmdDesc( "Interval between each ping to the host" )
+ Config()
{
}
+/**
+ * @brief Destructor.
+ */
ConfigurationReader::~ConfigurationReader()
{
}
* @param argc the number of arguments in command line.
* @param argv a vector containing the command line elements.
*
- * @return true if the parsing was successful, otherwise returns false.
+ * @return @c true if the parsing was successful, otherwise returns @c false.
*/
bool ConfigurationReader::parse(
const int argc,
BOOST_ASSERT( argv != NULL );
variables_map vm;
-
- bool command_line_processed = process_command_line( argc, argv, vm );
+ ConfigurationCommandLine command_line( argc, argv );
+ bool command_line_processed = command_line.process( &vm );
if ( command_line_processed )
{
- parse_generic_options( vm );
-
- bool terminate_app = halt_on_generic_options( vm );
+ bool terminate_app = command_line.parse( vm, &Config );
if ( terminate_app )
{
return false;
}
}
- bool configuration_file_processed = process_configuration_file( vm );
+ string file_name = Config.get_config_file_name();
+ ConfigurationFile file( file_name );
+ bool configuration_file_processed = file.process( &vm );
+ file.parse( vm, &Config );
bool input_processed = command_line_processed && configuration_file_processed;
- if ( input_processed )
- {
- return parse_configuration_options( vm );
- }
- else
- {
- return false;
- }
+
+ return input_processed;
}
/**
{
return Config;
}
-
-/**
- * @return which options must abort the application. Like the --version.
- */
-bool ConfigurationReader::halt_on_generic_options( const variables_map &vm ) const
-{
- bool is_help = ( vm.count( HelpCmdStr ) > 0 );
- bool is_version = ( vm.count( VersionCmdStr ) > 0 );
- bool terminate_app = is_help || is_version;
-
- return terminate_app;
-}
-
-options_description ConfigurationReader::get_generic_options() const
-{
- options_description options( "Generic options" );
- options.add_options()
- ( HelpCmdStr.c_str(), HelpCmdDesc.c_str() )
- ( VersionCmdStr.c_str(), VersionCmdDesc.c_str() )
- ( DaemonCmdStr.c_str(), DaemonCmdDesc.c_str() )
- ( ConfigFileCmdStr.c_str(), value<string>()->default_value( DefaultConfigFileName ), ConfigFileCmdDesc.c_str() )
- ;
-
- return options;
-}
-
-bool ConfigurationReader::parse_generic_options(
- const variables_map& vm
-)
-{
- // help
- if ( vm.count( HelpCmdStr ) > 0)
- {
- options_description generic = get_generic_options();
- options_description config = get_configuration_options();
-
- options_description visible_options( "Allowed options" );
- visible_options.add( generic ).add( config );
-
- cout << visible_options << endl;
- return true;
- }
-
- // version
- if ( vm.count( VersionCmdStr ) > 0 )
- {
- cout << PROJECT_NAME << " version " << VERSION_STRING << endl;
- return true;
- }
-
- // daemon
- bool have_daemon = ( vm.count( DaemonCmdStr ) > 0 );
- Config.set_daemon( have_daemon );
- GlobalLogger.info() << DaemonCmdStr << "="
- << have_daemon << endl;
-
- // config-file
- if ( vm.count( ConfigFileCmdStr ) > 0 )
- {
- string config_file_name = vm[ ConfigFileCmdStr ].as<string> ();
- Config.set_config_file_name( config_file_name );
-
- GlobalLogger.info() << ConfigFileCmdStr << "="
- << config_file_name << endl;
- }
-
- return false;
-}
-
-options_description ConfigurationReader::get_configuration_options() const
-{
- options_description options( "Configuration" );
- options.add_options()
- ( SourceNetworkInterfaceCmdStr.c_str(), value<string>(), SourceNetworkInterfaceCmdDesc.c_str() )
- ( NameServerCmdStr.c_str(), value<string>()->default_value( DefaultNameServer ), NameServerCmdDesc.c_str() )
- ( PingProtocolCmdStr.c_str(), value<string>(), PingProtocolCmdDesc.c_str() )
- ( HostsDownLimitCmdStr.c_str(), value<int>()->default_value( DefaultHostsDownLimit ), HostsDownLimitCmdDesc.c_str() )
- ( PingFailLimitCmdStr.c_str(), value<int>()->default_value( DefaultPingFailLimit ), PingFailLimitCmdDesc.c_str() )
- ( StatusNotifierCmdCmdStr.c_str(), value<string>(), StatusNotifierCmdCmdDesc.c_str() )
- ( LinkUpIntervalCmdStr.c_str(), value<int>()->default_value( DefaultLinkUpIntervalInMin ), LinkUpIntervalCmdDesc.c_str() )
- ( LinkDownIntervalCmdStr.c_str(), value<int>()->default_value( DefaultLinkDownIntervalInMin ), LinkDownIntervalCmdDesc.c_str() )
- ( HostNameCmdStr.c_str(), value< vector<string> >(), HostNameCmdDesc.c_str() )
- ( HostPortCmdStr.c_str(), value< vector<int> >(), HostPortCmdDesc.c_str() )
- ( HostIntervalCmdStr.c_str(), value< vector<int> >(), HostIntervalCmdDesc.c_str() )
- ;
-
- return options;
-}
-
-bool ConfigurationReader::parse_configuration_options( const variables_map &vm )
-{
- // source-network-interface
- if ( vm.count( SourceNetworkInterfaceCmdStr ) > 0 )
- {
- string source_network_interface =
- vm[ SourceNetworkInterfaceCmdStr ].as<string> ();
- Config.set_source_network_interface( source_network_interface );
-
- GlobalLogger.info() << SourceNetworkInterfaceCmdStr << "="
- << source_network_interface << endl;
- }
-
- // nameserver
- if ( vm.count( NameServerCmdStr ) > 0 )
- {
- string nameserver = vm[ NameServerCmdStr ].as<string> ();
- Config.set_nameserver( nameserver );
-
- GlobalLogger.info() << NameServerCmdStr << "="
- << nameserver << endl;
- }
-
- // ping-protocol
- if ( vm.count( PingProtocolCmdStr ) > 0 )
- {
- string protocol_string = vm[ PingProtocolCmdStr ].as<string> ();
- PingProtocol protocol = get_ping_protocol_from_string( protocol_string );
- Config.set_ping_protocol( protocol );
-
- GlobalLogger.info() << PingProtocolCmdStr << "="
- << protocol_string << endl;
- }
-
- // hosts-down-limit
- int host_down_limit = 0;
- if ( vm.count( HostsDownLimitCmdStr ) > 0 )
- {
- host_down_limit = vm[ HostsDownLimitCmdStr ].as<int> ();
- Config.set_hosts_down_limit( host_down_limit );
-
- GlobalLogger.info() << HostsDownLimitCmdStr << "="
- << host_down_limit << endl;
- }
-
- // ping-fail-limit
- if ( vm.count( PingFailLimitCmdStr ) > 0 )
- {
- int ping_fail_limit = vm[ PingFailLimitCmdStr ].as<int> ();
- Config.set_ping_fail_limit( ping_fail_limit );
-
- GlobalLogger.info() << PingFailLimitCmdStr << "="
- << ping_fail_limit << endl;
- }
-
- // status-notifier-cmd
- if ( vm.count( StatusNotifierCmdCmdStr ) > 0 )
- {
- string status_notifier_cmd = vm[ StatusNotifierCmdCmdStr ].as<string>();
- Config.set_status_notifier_cmd( status_notifier_cmd );
-
- GlobalLogger.info() << StatusNotifierCmdCmdStr << "="
- << status_notifier_cmd << endl;
- }
-
- // link-up-interval
- if ( vm.count( LinkUpIntervalCmdStr ) > 0 )
- {
- int link_up_interval_in_min = vm[ LinkUpIntervalCmdStr ].as<int>();
- Config.set_link_up_interval_in_min( link_up_interval_in_min );
-
- GlobalLogger.info() << LinkUpIntervalCmdStr << "="
- << link_up_interval_in_min << endl;
- }
-
- // link-down-interval
- if ( vm.count( LinkDownIntervalCmdStr ) > 0 )
- {
- int link_down_interval_in_min = vm[ LinkDownIntervalCmdStr ].as<int>();
- Config.set_link_down_interval_in_min( link_down_interval_in_min );
-
- GlobalLogger.info() << LinkDownIntervalCmdStr << "="
- << link_down_interval_in_min << endl;
- }
-
- // [host] name
- size_t hosts_names_count = 0;
- if ( vm.count( HostNameCmdStr ) > 0 )
- {
- HostList hosts_list;
-
- vector<string> hosts_names = vm[ HostNameCmdStr ].as< vector<string> > ();
- BOOST_FOREACH( string host_name, hosts_names )
- {
- BOOST_ASSERT( !host_name.empty() );
-
- HostItem host_item( new Host( host_name ) );
- hosts_list.push_back( host_item );
-
- GlobalLogger.info() << HostNameCmdStr << "="
- << host_name << endl;
- }
-
- Config.set_hosts( hosts_list );
-
- hosts_names_count = hosts_names.size();
-
- BOOST_ASSERT( hosts_names_count >= static_cast<size_t>( host_down_limit ) );
- }
-
- // [host] port
- size_t host_port_count = 0;
- if ( vm.count( HostPortCmdStr ) > 0 )
- {
- HostList hosts_list = Config.get_hosts();
- HostList::iterator hosts_it = hosts_list.begin();
-
- vector<int> hosts_ports = vm[ HostPortCmdStr ].as< vector<int> >();
- BOOST_FOREACH( int host_port, hosts_ports )
- {
- BOOST_ASSERT( ( 0 <= host_port ) && ( host_port <= numeric_limits<uint16_t>::max() ) );
-
- HostItem host_item = *hosts_it;
- host_item->set_port( static_cast<uint16_t>(host_port) );
- ++hosts_it;
-
- GlobalLogger.info() << HostPortCmdStr << "=" << host_port << endl;
- }
-
- host_port_count = hosts_ports.size();
- }
-
- // [host] interval
- size_t hosts_interval_count = 0;
- if ( vm.count( HostIntervalCmdStr ) > 0 )
- {
- HostList hosts_list = Config.get_hosts();
- HostList::iterator hosts_it = hosts_list.begin();
-
- vector<int> hosts_intervals = vm[ HostIntervalCmdStr ].as< vector<int> >();
- BOOST_FOREACH( int host_interval_in_sec, hosts_intervals )
- {
- BOOST_ASSERT( 0 < host_interval_in_sec );
-
- HostItem host_item = *hosts_it;
- host_item->set_interval_in_sec( host_interval_in_sec );
- ++hosts_it;
-
- GlobalLogger.info() << HostIntervalCmdStr << "="
- << host_interval_in_sec << endl;
- }
-
- hosts_interval_count = hosts_intervals.size();
- }
-
- // make sure there is always an interval for each host
- if ( hosts_names_count != hosts_interval_count )
- {
- GlobalLogger.error() << "Could not parse configuration file." <<
- " Missing an interval entry for one of the hosts." << endl;
- return false;
- }
-
- BOOST_ASSERT( hosts_names_count == host_port_count );
- BOOST_ASSERT( hosts_names_count == hosts_interval_count );
-
- return true;
-}
-
-/**
- * @brief Reads and parses the command line, storing the parsed tokens in the
- * variables_map.
- *
- * @param argc the number of arguments in command line.
- * @param argv a vector containing the command line elements.
- * @param vm the variables_map object to store configuration tokens.
- */
-bool ConfigurationReader::process_command_line(
- const int argc,
- char *argv[],
- variables_map &vm
-)
-{
- try
- {
- options_description generic = get_generic_options();
- options_description config = get_configuration_options();
-
- options_description cmdline_options;
- cmdline_options.add( generic ).add( config );
-
- positional_options_description p;
- (void) p.add( HostNameCmdStr.c_str(), -1 );
-
- parsed_options parsed_opt = command_line_parser( argc, argv ).
- options( cmdline_options ).
- positional( p ).
- allow_unregistered().
- run();
- store( parsed_opt, vm );
- notify( vm );
- }
- catch ( const std::exception &ex )
- {
- GlobalLogger.error() << ex.what() << endl;
- return false;
- }
-
- return true;
-}
-
-/**
- * @brief Reads and parses the configuration file. The file name is retrieved
- * from the variables_map object.
- *
- * @param vm the variables_map object to store configuration tokens.
- */
-bool ConfigurationReader::process_configuration_file( variables_map &vm )
-{
- string config_file_name = "";
- // parse the command line options to retrieve the config file name, if the
- // config-file option was not specified in the command line, it will return
- // the default file
- if ( parse_configuration_options( vm ) )
- {
- config_file_name = Config.get_config_file_name();
- }
-
- return process_configuration_file( config_file_name, vm );
-}
-
-/**
- * @brief Reads and parses the configuration file.
- *
- * @param config_file_name the configuration file name to be parsed.
- * @param vm the variables_map object to store configuration tokens.
- */
-bool ConfigurationReader::process_configuration_file(
- const string &config_file_name,
- variables_map &vm
-) const
-{
- BOOST_ASSERT( !config_file_name.empty() );
-
- ifstream ifs( config_file_name.c_str() );
- if ( !ifs )
- {
- GlobalLogger.error() << "Error: could not open "
- << config_file_name << " file." << endl;
- return false;
- }
- else
- {
- options_description config = get_configuration_options();
- options_description config_file_options;
- config_file_options.add( config );
-
- parsed_options parsed_opt = parse_config_file( ifs, config_file_options );
- store( parsed_opt, vm );
- notify( vm );
- }
-
- return true;
-}
#ifndef CONFIGURATIONREADER_H
#define CONFIGURATIONREADER_H
-#include <string>
-
#include <boost/program_options.hpp>
#include "config/configuration.h"
Configuration get_configuration() const;
private:
- bool halt_on_generic_options(
- const boost::program_options::variables_map &vm
- ) const;
- boost::program_options::options_description get_generic_options() const;
- bool parse_generic_options(
- const boost::program_options::variables_map &vm
- );
-
- boost::program_options::options_description get_configuration_options() const;
- bool parse_configuration_options(
- const boost::program_options::variables_map &vm
- );
-
- bool process_command_line(
- const int argc,
- char *argv[],
- boost::program_options::variables_map &vm
- );
- bool process_configuration_file(
- boost::program_options::variables_map &vm
- );
- bool process_configuration_file(
- const std::string &config_file_name,
- boost::program_options::variables_map &vm
- ) const;
-
-private:
Configuration Config;
- const std::string HelpCmdStr;
- const std::string HelpCmdDesc;
- const std::string VersionCmdStr;
- const std::string VersionCmdDesc;
- const std::string DaemonCmdStr;
- const std::string DaemonCmdDesc;
- const std::string DefaultConfigFileName;
- const std::string ConfigFileCmdStr;
- const std::string ConfigFileCmdDesc;
- const std::string SourceNetworkInterfaceCmdStr;
- const std::string SourceNetworkInterfaceCmdDesc;
- const std::string DefaultNameServer;
- const std::string NameServerCmdStr;
- const std::string NameServerCmdDesc;
- const std::string PingProtocolCmdStr;
- const std::string PingProtocolCmdDesc;
- const int DefaultHostsDownLimit;
- const std::string HostsDownLimitCmdStr;
- const std::string HostsDownLimitCmdDesc;
- const int DefaultPingFailLimit;
- const std::string PingFailLimitCmdStr;
- const std::string PingFailLimitCmdDesc;
- const std::string StatusNotifierCmdCmdStr;
- const std::string StatusNotifierCmdCmdDesc;
- const int DefaultLinkUpIntervalInMin;
- const std::string LinkUpIntervalCmdStr;
- const std::string LinkUpIntervalCmdDesc;
- const int DefaultLinkDownIntervalInMin;
- const std::string LinkDownIntervalCmdStr;
- const std::string LinkDownIntervalCmdDesc;
- const std::string HostNameCmdStr;
- const std::string HostNameCmdDesc;
- const int DefaultHostPort;
- const std::string HostPortCmdStr;
- const std::string HostPortCmdDesc;
- const int DefaultHostIntervalInSec;
- const std::string HostIntervalCmdStr;
- const std::string HostIntervalCmdDesc;
-
};
-#endif /* CONFIGURATIONREADER_H */
+#endif // CONFIGURATIONREADER_H