Commit | Line | Data |
---|---|---|
aab6eaa1 GMF |
1 | /* |
2 | The software in this package is distributed under the GNU General | |
3 | Public License version 2 (with a special exception described below). | |
4 | ||
5 | A copy of GNU General Public License (GPL) is included in this distribution, | |
6 | in the file COPYING.GPL. | |
7 | ||
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. | |
13 | ||
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. | |
16 | ||
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. | |
19 | */ | |
20 | ||
21 | #include "config/configurationoptions.h" | |
22 | ||
23 | #include <iostream> | |
24 | ||
aab6eaa1 GMF |
25 | #include <boost/foreach.hpp> |
26 | ||
27 | #include <logfunc.hpp> | |
28 | ||
780b0bca | 29 | #include "boost_assert_handler.h" |
6c5bdffd GMF |
30 | #include "config/option/configfileoption.h" |
31 | #include "config/option/daemonoption.h" | |
5596767b | 32 | #include "config/option/hostsdownlimitoption.h" |
6c5bdffd GMF |
33 | #include "config/option/hostnameoption.h" |
34 | #include "config/option/hostportoption.h" | |
35 | #include "config/option/hostpingprotocoloption.h" | |
36 | #include "config/option/hostpingintervaloption.h" | |
74dd30e1 | 37 | #include "config/option/hostsourcenetworkinterfaceoption.h" |
6c5bdffd GMF |
38 | #include "config/option/linkdownintervaloption.h" |
39 | #include "config/option/linkupintervaloption.h" | |
2c40f493 | 40 | #include "config/option/logleveloption.h" |
5ba17410 | 41 | #include "config/option/logoutputoption.h" |
fda777ea | 42 | #include "config/option/logfileoption.h" |
6c5bdffd GMF |
43 | #include "config/option/nameserveroption.h" |
44 | #include "config/option/pingfaillimitoption.h" | |
45 | #include "config/option/sourcenetworkinterfaceoption.h" | |
46 | #include "config/option/statusnotifiercmdoption.h" | |
47 | #include "config/option/versionoption.h" | |
096b06ef | 48 | #include "config/option/ratiorandomhostsoption.h" |
079d19ab CH |
49 | #include "config/option/pingreplytimeoutoption.h" |
50 | #include "config/option/maxaddressresolutionattemptsoption.h" | |
51 | #include "config/option/resolvedipttlthresholdoption.h" | |
a901aed6 | 52 | #include "config/option/dnscachefileoption.h" |
6c5bdffd | 53 | |
aab6eaa1 | 54 | using namespace std; |
6c5bdffd | 55 | using boost::program_options::option_description; |
aab6eaa1 GMF |
56 | using boost::program_options::options_description; |
57 | using boost::program_options::value; | |
58 | using boost::program_options::variables_map; | |
6c5bdffd | 59 | using boost::shared_ptr; |
aab6eaa1 GMF |
60 | using I2n::Logger::GlobalLogger; |
61 | ||
62 | //----------------------------------------------------------------------------- | |
63 | // ConfigurationOptions | |
64 | //----------------------------------------------------------------------------- | |
65 | ||
66 | /** | |
67 | * @brief Default constructor. | |
68 | */ | |
69 | ConfigurationOptions::ConfigurationOptions() : | |
6c5bdffd GMF |
70 | GenericOptions(), |
71 | ConfigOptions(), | |
72 | HostOptions(), | |
aab6eaa1 | 73 | HelpCmdStr( "help" ), |
6c5bdffd | 74 | HelpCmdDesc( "Print this help and exit." ) |
aab6eaa1 | 75 | { |
6c5bdffd GMF |
76 | ConfigurationOptionItem config_file( new ConfigFileOption ); |
77 | GenericOptions.push_back( config_file ); | |
78 | ||
79 | ConfigurationOptionItem daemon( new DaemonOption ); | |
80 | GenericOptions.push_back( daemon ); | |
81 | ||
82 | ConfigurationOptionItem version( new VersionOption ); | |
83 | GenericOptions.push_back( version ); | |
84 | ||
2c40f493 GMF |
85 | ConfigurationOptionItem log_level( new LogLevelOption ); |
86 | GenericOptions.push_back( log_level ); | |
87 | ||
5ba17410 GMF |
88 | ConfigurationOptionItem log_output( new LogOutputOption ); |
89 | GenericOptions.push_back( log_output ); | |
90 | ||
fda777ea CH |
91 | ConfigurationOptionItem log_file( new LogFileOption ); |
92 | GenericOptions.push_back( log_file ); | |
93 | ||
5596767b GMF |
94 | ConfigurationOptionItem hosts_down_limit( new HostsDownLimitOption ); |
95 | ConfigOptions.push_back( hosts_down_limit ); | |
6c5bdffd GMF |
96 | |
97 | ConfigurationOptionItem link_down_interval( new LinkDownIntervalOption ); | |
98 | ConfigOptions.push_back( link_down_interval ); | |
99 | ||
100 | ConfigurationOptionItem link_up_interval( new LinkUpIntervalOption ); | |
101 | ConfigOptions.push_back( link_up_interval ); | |
102 | ||
103 | ConfigurationOptionItem nameserver( new NameserverOption ); | |
104 | ConfigOptions.push_back( nameserver ); | |
105 | ||
106 | ConfigurationOptionItem ping_fail_limit( new PingFailLimitOption ); | |
107 | ConfigOptions.push_back( ping_fail_limit ); | |
108 | ||
109 | ConfigurationOptionItem source_network_interface( new SourceNetworkInterfaceOption ); | |
110 | ConfigOptions.push_back( source_network_interface ); | |
111 | ||
112 | ConfigurationOptionItem status_notifier_cmd( new StatusNotifierCmdOption ); | |
113 | ConfigOptions.push_back( status_notifier_cmd ); | |
114 | ||
079d19ab CH |
115 | ConfigurationOptionItem ping_reply_timeout( new PingReplyTimeoutOption ); |
116 | ConfigOptions.push_back( ping_reply_timeout ); | |
117 | ||
118 | ConfigurationOptionItem max_address_resolution_attempts( new MaxAddressResolutionAttemptsOption ); | |
119 | ConfigOptions.push_back( max_address_resolution_attempts ); | |
120 | ||
121 | ConfigurationOptionItem resolved_ip_ttl_threshold( new ResolvedIpTtlThresholdOption ); | |
122 | ConfigOptions.push_back( resolved_ip_ttl_threshold ); | |
123 | ||
096b06ef CH |
124 | ConfigurationOptionItem ratio_random_hosts( new RatioRandomHostsOption ); |
125 | ConfigOptions.push_back( ratio_random_hosts ); | |
126 | ||
a901aed6 CH |
127 | ConfigurationOptionItem dns_cache_file( new DnsCacheFileOption ); |
128 | ConfigOptions.push_back( dns_cache_file ); | |
129 | ||
6c5bdffd GMF |
130 | HostConfigurationOptionItem host_name( new HostNameOption ); |
131 | HostOptions.push_back( host_name ); | |
132 | ||
133 | HostConfigurationOptionItem host_port( new HostPortOption ); | |
134 | HostOptions.push_back( host_port ); | |
135 | ||
74dd30e1 GMF |
136 | HostConfigurationOptionItem host_source_network_interface( new HostSourceNetworkInterfaceOption ); |
137 | HostOptions.push_back( host_source_network_interface ); | |
138 | ||
6c5bdffd GMF |
139 | HostConfigurationOptionItem host_protocol( new HostPingProtocolOption ); |
140 | HostOptions.push_back( host_protocol ); | |
141 | ||
142 | HostConfigurationOptionItem host_interval( new HostPingIntervalOption ); | |
143 | HostOptions.push_back( host_interval ); | |
aab6eaa1 GMF |
144 | } |
145 | ||
146 | /** | |
147 | * @brief Destructor. | |
148 | */ | |
149 | ConfigurationOptions::~ConfigurationOptions() | |
150 | { | |
151 | } | |
152 | ||
153 | /** | |
6c5bdffd | 154 | * @return The options which are common to all kinds of applications. |
aab6eaa1 GMF |
155 | */ |
156 | options_description ConfigurationOptions::get_generic_options() const | |
157 | { | |
158 | options_description options( "Generic options" ); | |
6c5bdffd | 159 | |
aab6eaa1 GMF |
160 | options.add_options() |
161 | ( HelpCmdStr.c_str(), HelpCmdDesc.c_str() ) | |
aab6eaa1 GMF |
162 | ; |
163 | ||
6c5bdffd GMF |
164 | BOOST_FOREACH( ConfigurationOptionItem generic_option, GenericOptions ) |
165 | { | |
166 | // Do not pass the the underlying boost::program_options::option_description | |
167 | // object from ConfigurationOption to the | |
168 | // boost::program_options::options_description::add() method, because it | |
169 | // deletes the boost::program_options::option_description, causing | |
170 | // multiple freed when ConfigurationOption try to delete it. | |
171 | option_description option = generic_option->get_option_description(); | |
172 | shared_ptr< option_description > ptr( new option_description( option ) ); | |
173 | options.add( ptr ); | |
174 | } | |
175 | ||
aab6eaa1 GMF |
176 | return options; |
177 | } | |
178 | ||
179 | /** | |
6c5bdffd | 180 | * @return The options which are specific to this application. |
aab6eaa1 GMF |
181 | */ |
182 | options_description ConfigurationOptions::get_configuration_options() const | |
183 | { | |
184 | options_description options( "Configuration" ); | |
6c5bdffd GMF |
185 | |
186 | BOOST_FOREACH( ConfigurationOptionItem configuration_option, ConfigOptions ) | |
187 | { | |
188 | option_description option = configuration_option->get_option_description(); | |
189 | shared_ptr< option_description > ptr( new option_description( option ) ); | |
190 | options.add( ptr ); | |
191 | } | |
192 | ||
193 | BOOST_FOREACH( ConfigurationOptionItem host_option, HostOptions ) | |
194 | { | |
195 | option_description option = host_option->get_option_description(); | |
196 | shared_ptr< option_description > ptr( new option_description( option ) ); | |
197 | options.add( ptr ); | |
198 | } | |
aab6eaa1 GMF |
199 | |
200 | return options; | |
201 | } | |
202 | ||
203 | /** | |
6c5bdffd | 204 | * @brief Parse the options common to all kinds of applications. |
aab6eaa1 | 205 | * |
6c5bdffd GMF |
206 | * @param vm The input @c boost::program_options::variables_map. |
207 | * @param configuration The output @c Configuration filled with the parsed | |
208 | * generic options. | |
aab6eaa1 | 209 | * |
6c5bdffd GMF |
210 | * @return @c true if it was parsed at least one option, or @c false if there |
211 | * were no options available in this category. | |
aab6eaa1 GMF |
212 | */ |
213 | bool ConfigurationOptions::parse_generic_options( | |
214 | const variables_map& vm, | |
215 | Configuration *configuration | |
216 | ) | |
217 | { | |
10af47fc GMF |
218 | BOOST_ASSERT(configuration != NULL); |
219 | ||
aab6eaa1 | 220 | // help |
6c5bdffd | 221 | if ( vm.count( HelpCmdStr ) > 0 ) |
aab6eaa1 GMF |
222 | { |
223 | options_description generic = get_generic_options(); | |
224 | options_description config = get_configuration_options(); | |
225 | ||
226 | options_description visible_options( "Allowed options" ); | |
227 | visible_options.add( generic ).add( config ); | |
228 | ||
6c5bdffd | 229 | // TODO GlobalOutput::print( help ) |
aab6eaa1 GMF |
230 | cout << visible_options << endl; |
231 | return true; | |
232 | } | |
233 | ||
6c5bdffd | 234 | BOOST_FOREACH( ConfigurationOptionItem generic_option, GenericOptions ) |
aab6eaa1 | 235 | { |
d3384e36 | 236 | generic_option->parse( vm, configuration ); |
aab6eaa1 GMF |
237 | } |
238 | ||
aab6eaa1 GMF |
239 | return false; |
240 | } | |
241 | ||
242 | /** | |
6c5bdffd | 243 | * @brief Parse the options specific to this application. |
aab6eaa1 | 244 | * |
6c5bdffd GMF |
245 | * @param vm The input @c boost::program_options::variables_map. |
246 | * @param configuration The output @c Configuration filled with the parsed | |
247 | * configuration options. | |
aab6eaa1 | 248 | * |
6c5bdffd GMF |
249 | * @return @c true if it was parsed at least one option, or @c false if there |
250 | * were no options available in this category. | |
aab6eaa1 GMF |
251 | */ |
252 | bool ConfigurationOptions::parse_configuration_options( | |
253 | const variables_map &vm, | |
254 | Configuration *configuration | |
255 | ) | |
256 | { | |
10af47fc GMF |
257 | BOOST_ASSERT(configuration != NULL); |
258 | ||
6c5bdffd | 259 | BOOST_FOREACH( ConfigurationOptionItem configuration_option, ConfigOptions ) |
aab6eaa1 | 260 | { |
d3384e36 | 261 | configuration_option->parse( vm, configuration ); |
aab6eaa1 GMF |
262 | } |
263 | ||
10af47fc GMF |
264 | bool hosts_parsed = parse_hosts_options(vm, configuration); |
265 | ||
266 | return hosts_parsed; | |
267 | } | |
268 | ||
269 | /** | |
270 | * @brief Parse the hosts section options. | |
271 | * | |
272 | * @param vm The input @c boost::program_options::variables_map. | |
273 | * @param configuration The output @c Configuration filled with the parsed | |
274 | * hosts options. | |
275 | * | |
276 | * @return @c true if the hosts were parsed correctly, or @c false otherwise. | |
277 | */ | |
278 | bool ConfigurationOptions::parse_hosts_options( | |
279 | const variables_map &vm, | |
280 | Configuration *configuration | |
281 | ) | |
282 | { | |
283 | BOOST_ASSERT(configuration != NULL); | |
284 | ||
6c5bdffd | 285 | size_t host_down_limit_count = static_cast<size_t>( configuration->get_hosts_down_limit() ); |
aab6eaa1 | 286 | |
6c5bdffd | 287 | BOOST_FOREACH( HostConfigurationOptionItem host_option, HostOptions ) |
c9e981f6 | 288 | { |
6c5bdffd | 289 | bool parsed = host_option->parse( vm, configuration ); |
d3384e36 | 290 | if ( parsed ) |
c9e981f6 | 291 | { |
6c5bdffd GMF |
292 | // The set_hosts_count() method is called in parse() method, that is |
293 | // why we must parse before check the number of host options | |
294 | size_t hosts_parsed_count = host_option->get_hosts_count(); | |
295 | bool have_minimum_hosts = ( host_down_limit_count <= hosts_parsed_count ); | |
296 | // Ensure we have all options for each host | |
297 | if ( !have_minimum_hosts ) { | |
298 | // TODO GlobalOutput::print() | |
299 | GlobalLogger.error() << "Could not parse configuration file." << | |
300 | " Missing an entry for one of the hosts." << endl; | |
301 | // TODO Assume default value for a missing option | |
302 | return false; | |
303 | } | |
304 | ||
305 | BOOST_ASSERT( hosts_parsed_count >= static_cast<size_t>( host_down_limit_count ) ); | |
c9e981f6 | 306 | } |
c9e981f6 GMF |
307 | } |
308 | ||
aab6eaa1 GMF |
309 | return true; |
310 | } | |
311 | ||
312 | /** | |
313 | * @return which options must abort the application. Like the --version. | |
aab6eaa1 GMF |
314 | */ |
315 | bool ConfigurationOptions::halt_on_generic_options( const variables_map &vm ) const | |
316 | { | |
6c5bdffd GMF |
317 | VersionOption v; |
318 | ||
aab6eaa1 | 319 | bool is_help = ( vm.count( HelpCmdStr ) > 0 ); |
6c5bdffd | 320 | bool is_version = ( vm.count( v.get_command_string() ) > 0 ); |
aab6eaa1 GMF |
321 | bool terminate_app = is_help || is_version; |
322 | ||
323 | return terminate_app; | |
324 | } |