2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
21 #include "config/configurationoptions.h"
25 #include <boost/foreach.hpp>
27 #include <logfunc.hpp>
29 #include "boost_assert_handler.h"
30 #include "config/option/configfileoption.h"
31 #include "config/option/daemonoption.h"
32 #include "config/option/hostsdownlimitoption.h"
33 #include "config/option/hostnameoption.h"
34 #include "config/option/hostportoption.h"
35 #include "config/option/hostpingprotocoloption.h"
36 #include "config/option/hostpingintervaloption.h"
37 #include "config/option/hostsourcenetworkinterfaceoption.h"
38 #include "config/option/linkdownintervaloption.h"
39 #include "config/option/linkupintervaloption.h"
40 #include "config/option/logleveloption.h"
41 #include "config/option/logoutputoption.h"
42 #include "config/option/nameserveroption.h"
43 #include "config/option/pingfaillimitoption.h"
44 #include "config/option/sourcenetworkinterfaceoption.h"
45 #include "config/option/statusnotifiercmdoption.h"
46 #include "config/option/versionoption.h"
47 #include "config/option/ratiorandomhostsoption.h"
48 #include "config/option/pingreplytimeoutoption.h"
49 #include "config/option/maxaddressresolutionattemptsoption.h"
50 #include "config/option/resolvedipttlthresholdoption.h"
51 #include "config/option/dnscachefileoption.h"
54 using boost::program_options::option_description;
55 using boost::program_options::options_description;
56 using boost::program_options::value;
57 using boost::program_options::variables_map;
58 using boost::shared_ptr;
59 using I2n::Logger::GlobalLogger;
61 //-----------------------------------------------------------------------------
62 // ConfigurationOptions
63 //-----------------------------------------------------------------------------
66 * @brief Default constructor.
68 ConfigurationOptions::ConfigurationOptions() :
73 HelpCmdDesc( "Print this help and exit." )
75 ConfigurationOptionItem config_file( new ConfigFileOption );
76 GenericOptions.push_back( config_file );
78 ConfigurationOptionItem daemon( new DaemonOption );
79 GenericOptions.push_back( daemon );
81 ConfigurationOptionItem version( new VersionOption );
82 GenericOptions.push_back( version );
84 ConfigurationOptionItem log_level( new LogLevelOption );
85 GenericOptions.push_back( log_level );
87 ConfigurationOptionItem log_output( new LogOutputOption );
88 GenericOptions.push_back( log_output );
90 ConfigurationOptionItem hosts_down_limit( new HostsDownLimitOption );
91 ConfigOptions.push_back( hosts_down_limit );
93 ConfigurationOptionItem link_down_interval( new LinkDownIntervalOption );
94 ConfigOptions.push_back( link_down_interval );
96 ConfigurationOptionItem link_up_interval( new LinkUpIntervalOption );
97 ConfigOptions.push_back( link_up_interval );
99 ConfigurationOptionItem nameserver( new NameserverOption );
100 ConfigOptions.push_back( nameserver );
102 ConfigurationOptionItem ping_fail_limit( new PingFailLimitOption );
103 ConfigOptions.push_back( ping_fail_limit );
105 ConfigurationOptionItem source_network_interface( new SourceNetworkInterfaceOption );
106 ConfigOptions.push_back( source_network_interface );
108 ConfigurationOptionItem status_notifier_cmd( new StatusNotifierCmdOption );
109 ConfigOptions.push_back( status_notifier_cmd );
111 ConfigurationOptionItem ping_reply_timeout( new PingReplyTimeoutOption );
112 ConfigOptions.push_back( ping_reply_timeout );
114 ConfigurationOptionItem max_address_resolution_attempts( new MaxAddressResolutionAttemptsOption );
115 ConfigOptions.push_back( max_address_resolution_attempts );
117 ConfigurationOptionItem resolved_ip_ttl_threshold( new ResolvedIpTtlThresholdOption );
118 ConfigOptions.push_back( resolved_ip_ttl_threshold );
120 ConfigurationOptionItem ratio_random_hosts( new RatioRandomHostsOption );
121 ConfigOptions.push_back( ratio_random_hosts );
123 ConfigurationOptionItem dns_cache_file( new DnsCacheFileOption );
124 ConfigOptions.push_back( dns_cache_file );
126 HostConfigurationOptionItem host_name( new HostNameOption );
127 HostOptions.push_back( host_name );
129 HostConfigurationOptionItem host_port( new HostPortOption );
130 HostOptions.push_back( host_port );
132 HostConfigurationOptionItem host_source_network_interface( new HostSourceNetworkInterfaceOption );
133 HostOptions.push_back( host_source_network_interface );
135 HostConfigurationOptionItem host_protocol( new HostPingProtocolOption );
136 HostOptions.push_back( host_protocol );
138 HostConfigurationOptionItem host_interval( new HostPingIntervalOption );
139 HostOptions.push_back( host_interval );
145 ConfigurationOptions::~ConfigurationOptions()
150 * @return The options which are common to all kinds of applications.
152 options_description ConfigurationOptions::get_generic_options() const
154 options_description options( "Generic options" );
156 options.add_options()
157 ( HelpCmdStr.c_str(), HelpCmdDesc.c_str() )
160 BOOST_FOREACH( ConfigurationOptionItem generic_option, GenericOptions )
162 // Do not pass the the underlying boost::program_options::option_description
163 // object from ConfigurationOption to the
164 // boost::program_options::options_description::add() method, because it
165 // deletes the boost::program_options::option_description, causing
166 // multiple freed when ConfigurationOption try to delete it.
167 option_description option = generic_option->get_option_description();
168 shared_ptr< option_description > ptr( new option_description( option ) );
176 * @return The options which are specific to this application.
178 options_description ConfigurationOptions::get_configuration_options() const
180 options_description options( "Configuration" );
182 BOOST_FOREACH( ConfigurationOptionItem configuration_option, ConfigOptions )
184 option_description option = configuration_option->get_option_description();
185 shared_ptr< option_description > ptr( new option_description( option ) );
189 BOOST_FOREACH( ConfigurationOptionItem host_option, HostOptions )
191 option_description option = host_option->get_option_description();
192 shared_ptr< option_description > ptr( new option_description( option ) );
200 * @brief Parse the options common to all kinds of applications.
202 * @param vm The input @c boost::program_options::variables_map.
203 * @param configuration The output @c Configuration filled with the parsed
206 * @return @c true if it was parsed at least one option, or @c false if there
207 * were no options available in this category.
209 bool ConfigurationOptions::parse_generic_options(
210 const variables_map& vm,
211 Configuration *configuration
214 BOOST_ASSERT(configuration != NULL);
217 if ( vm.count( HelpCmdStr ) > 0 )
219 options_description generic = get_generic_options();
220 options_description config = get_configuration_options();
222 options_description visible_options( "Allowed options" );
223 visible_options.add( generic ).add( config );
225 // TODO GlobalOutput::print( help )
226 cout << visible_options << endl;
230 BOOST_FOREACH( ConfigurationOptionItem generic_option, GenericOptions )
232 generic_option->parse( vm, configuration );
239 * @brief Parse the options specific to this application.
241 * @param vm The input @c boost::program_options::variables_map.
242 * @param configuration The output @c Configuration filled with the parsed
243 * configuration options.
245 * @return @c true if it was parsed at least one option, or @c false if there
246 * were no options available in this category.
248 bool ConfigurationOptions::parse_configuration_options(
249 const variables_map &vm,
250 Configuration *configuration
253 BOOST_ASSERT(configuration != NULL);
255 BOOST_FOREACH( ConfigurationOptionItem configuration_option, ConfigOptions )
257 configuration_option->parse( vm, configuration );
260 bool hosts_parsed = parse_hosts_options(vm, configuration);
266 * @brief Parse the hosts section options.
268 * @param vm The input @c boost::program_options::variables_map.
269 * @param configuration The output @c Configuration filled with the parsed
272 * @return @c true if the hosts were parsed correctly, or @c false otherwise.
274 bool ConfigurationOptions::parse_hosts_options(
275 const variables_map &vm,
276 Configuration *configuration
279 BOOST_ASSERT(configuration != NULL);
281 size_t host_down_limit_count = static_cast<size_t>( configuration->get_hosts_down_limit() );
283 BOOST_FOREACH( HostConfigurationOptionItem host_option, HostOptions )
285 bool parsed = host_option->parse( vm, configuration );
288 // The set_hosts_count() method is called in parse() method, that is
289 // why we must parse before check the number of host options
290 size_t hosts_parsed_count = host_option->get_hosts_count();
291 bool have_minimum_hosts = ( host_down_limit_count <= hosts_parsed_count );
292 // Ensure we have all options for each host
293 if ( !have_minimum_hosts ) {
294 // TODO GlobalOutput::print()
295 GlobalLogger.error() << "Could not parse configuration file." <<
296 " Missing an entry for one of the hosts." << endl;
297 // TODO Assume default value for a missing option
301 BOOST_ASSERT( hosts_parsed_count >= static_cast<size_t>( host_down_limit_count ) );
309 * @return which options must abort the application. Like the --version.
311 bool ConfigurationOptions::halt_on_generic_options( const variables_map &vm ) const
315 bool is_help = ( vm.count( HelpCmdStr ) > 0 );
316 bool is_version = ( vm.count( v.get_command_string() ) > 0 );
317 bool terminate_app = is_help || is_version;
319 return terminate_app;