OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
options.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "options.h"
6 
7 #include <fstream>
8 #include <iostream>
9 #include <boost/asio/ip/host_name.hpp>
10 #include <boost/functional/hash.hpp>
11 
12 #include "control-node/buildinfo.h"
13 #include "base/contrail_ports.h"
14 #include "base/logging.h"
15 #include "base/misc_utils.h"
16 #include "base/util.h"
17 #include "config_client_manager.h"
18 #include <base/address_util.h>
19 #include <base/options_util.h>
20 
21 using namespace std;
22 using namespace boost::asio::ip;
23 namespace opt = boost::program_options;
24 using namespace options::util;
25 
26 // Process command line options for control-node.
28 }
29 
30 bool Options::Parse(EventManager &evm, int argc, char *argv[]) {
31  opt::options_description cmdline_options("Allowed options");
32  Initialize(evm, cmdline_options);
33 
34  try {
35  return Process(argc, argv, cmdline_options);
36  } catch (boost::program_options::error &e) {
37  cout << "Error " << e.what() << endl;
38  } catch (...) {
39  cout << "Options Parser: Caught fatal unknown exception" << endl;
40  }
41 
42  return false;
43 }
44 
45 // Initialize control-node's command line option tags with appropriate default
46 // values. Options can from a config file as well. By default, we read
47 // options from /etc/contrail/contrail-control.conf
49  opt::options_description &cmdline_options) {
50  boost::system::error_code error;
51  string hostname = host_name(error);
52  string host_ip = GetHostIp(evm.io_service(), hostname);
53 
54  if (host_ip.empty())
55  host_ip = "127.0.0.1";
56 
57  opt::options_description generic("Generic options");
58 
59  // Command line only options.
60  generic.add_options()
61  ("conf_file", opt::value<string>()->default_value(
62  "/etc/contrail/contrail-control.conf"),
63  "Configuration file")
64  ("help", "help message")
65  ("version", "Display version information")
66  ;
67 
68  uint16_t default_bgp_port = ContrailPorts::ControlBgp();
69  uint16_t default_http_server_port = ContrailPorts::HttpPortControl();
70  uint16_t default_xmpp_port = ContrailPorts::ControlXmpp();
71 
72  default_collector_server_list_.push_back("127.0.0.1:8086");
73 
74  vector<string> default_config_db_server_list;
75  string default_config_db_server(host_ip + ":9042");
76  default_config_db_server_list.push_back(default_config_db_server);
77 
78  vector<string> default_rabbitmq_server_list;
79  string default_rabbitmq_server(host_ip + ":5672");
80  default_rabbitmq_server_list.push_back(default_rabbitmq_server);
81 
82  // Command line and config file options.
83  opt::options_description config("Configuration options");
84  config.add_options()
85  ("DEFAULT.bgp_config_file",
86  opt::value<string>()->default_value("bgp_config.xml"),
87  "BGP Configuration file")
88  ("DEFAULT.bgp_port",
89  opt::value<uint16_t>()->default_value(default_bgp_port),
90  "BGP listener port")
91  ("DEFAULT.collectors",
92  opt::value<vector<string> >()->default_value(
93  default_collector_server_list_, "127.0.0.1:8086"),
94  "Collector server list")
95 
96  ("DEFAULT.gr_helper_bgp_disable",
97  opt::bool_switch(&gr_helper_bgp_disable_),
98  "Disable Graceful Restart Helper functionality for BGP peers")
99  ("DEFAULT.gr_helper_xmpp_disable",
100  opt::bool_switch(&gr_helper_xmpp_disable_),
101  "Disable Graceful Restart Helper functionality for XMPP agents")
102 
103  ("DEFAULT.hostip", opt::value<string>()->default_value(host_ip),
104  "IP address of control-node")
105  ("DEFAULT.hostname", opt::value<string>()->default_value(hostname),
106  "Hostname of control-node")
107  ("DEFAULT.http_server_port",
108  opt::value<uint16_t>()->default_value(default_http_server_port),
109  "Sandesh HTTP listener port")
110 
111  ("DEFAULT.log_category",
112  opt::value<string>()->default_value(log_category_),
113  "Category filter for local logging of sandesh messages")
114  ("DEFAULT.log_disable", opt::bool_switch(&log_disable_),
115  "Disable sandesh logging")
116  ("DEFAULT.log_file", opt::value<string>()->default_value(
117  "/var/log/contrail/contrail-control.log"),
118  "Filename for the logs to be written to")
119  ("DEFAULT.log_property_file", opt::value<string>()->default_value(""),
120  "log4cplus property file name")
121  ("DEFAULT.log_files_count",
122  opt::value<int>()->default_value(10),
123  "Maximum log file roll over index")
124  ("DEFAULT.log_file_size",
125  opt::value<long>()->default_value(10*1024*1024),
126  "Maximum size of the log file")
127  ("DEFAULT.log_level", opt::value<string>()->default_value("SYS_NOTICE"),
128  "Severity level for local logging of sandesh messages")
129  ("DEFAULT.log_local",
130  opt::bool_switch(&log_local_)->default_value(true),
131  "Enable local logging of sandesh messages")
132  ("DEFAULT.mvpn_ipv4_enable", opt::bool_switch(&mvpn_ipv4_enable_),
133  "Enable NGEN Multicast VPN support for IPv4 routes")
134  ("DEFAULT.use_syslog", opt::bool_switch(&use_syslog_),
135  "Enable logging to syslog")
136  ("DEFAULT.syslog_facility",
137  opt::value<string>()->default_value("LOG_LOCAL0"),
138  "Syslog facility to receive log lines")
139  ("DEFAULT.task_track_run_time", opt::bool_switch(&task_track_run_time_),
140  "Enable tracking of run time per task id")
141  ("DEFAULT.test_mode", opt::bool_switch(&test_mode_),
142  "Enable control-node to run in test-mode")
143  ("DEFAULT.tcp_hold_time", opt::value<int>()->default_value(30),
144  "Configurable TCP hold time")
145  ("DEFAULT.optimize_snat", opt::bool_switch(&optimize_snat_),
146  "Enable control-node optimizations for SNAT (deprecated)")
147  ("DEFAULT.xmpp_server_port",
148  opt::value<uint16_t>()->default_value(default_xmpp_port),
149  "XMPP listener port")
150  ("DEFAULT.xmpp_auth_enable", opt::bool_switch(&xmpp_auth_enable_),
151  "Enable authentication over Xmpp")
152  ("DEFAULT.xmpp_server_cert",
153  opt::value<string>()->default_value(
154  "/etc/contrail/ssl/certs/server.pem"),
155  "XMPP Server ssl certificate")
156  ("DEFAULT.xmpp_server_key",
157  opt::value<string>()->default_value(
158  "/etc/contrail/ssl/private/server-privkey.pem"),
159  "XMPP Server ssl private key")
160  ("DEFAULT.xmpp_ca_cert",
161  opt::value<string>()->default_value(
162  "/etc/contrail/ssl/certs/ca-cert.pem"),
163  "XMPP CA ssl certificate")
164 
165  ("CONFIGDB.config_db_server_list",
166  opt::value<vector<string> >()->default_value(
167  default_config_db_server_list, default_config_db_server),
168  "Config database server list")
169  ("CONFIGDB.config_db_username",
170  opt::value<string>()->default_value(""),
171  "ConfigDB user")
172  ("CONFIGDB.config_db_password",
173  opt::value<string>()->default_value(""),
174  "ConfigDB password")
175  ("CONFIGDB.config_db_use_ssl",
176  opt::value<bool>()->default_value(false),
177  "Use SSL for Cassandra connection")
178  ("CONFIGDB.config_db_ca_certs",
179  opt::value<string>()->default_value(""),
180  "CA Certificate file for SSL Cassandra connection")
181  ("CONFIGDB.rabbitmq_server_list",
182  opt::value<vector<string> >()->default_value(
183  default_rabbitmq_server_list, default_rabbitmq_server),
184  "RabbitMQ server list")
185  ("CONFIGDB.rabbitmq_user",
186  opt::value<string>()->default_value("guest"),
187  "RabbitMQ user")
188  ("CONFIGDB.rabbitmq_password",
189  opt::value<string>()->default_value("guest"),
190  "RabbitMQ password")
191  ("CONFIGDB.rabbitmq_vhost",
192  opt::value<string>()->default_value(""),
193  "RabbitMQ vhost")
194  ("CONFIGDB.rabbitmq_use_ssl",
195  opt::value<bool>()->default_value(false),
196  "Use SSL for RabbitMQ connection")
197  ("CONFIGDB.rabbitmq_ssl_version",
198  opt::value<string>()->default_value(""),
199  "SSL version for RabbitMQ connection")
200  ("CONFIGDB.rabbitmq_ssl_keyfile",
201  opt::value<string>()->default_value(""),
202  "Keyfile for SSL RabbitMQ connection")
203  ("CONFIGDB.rabbitmq_ssl_certfile",
204  opt::value<string>()->default_value(""),
205  "Certificate file for SSL RabbitMQ connection")
206  ("CONFIGDB.rabbitmq_ssl_ca_certs",
207  opt::value<string>()->default_value(""),
208  "CA Certificate file for SSL RabbitMQ connection")
209 
210  ("CONFIGDB.config_db_use_etcd",
211  opt::value<bool>()->default_value(false),
212  "Use etcd as the contrail DB client")
213  ;
214 
215  sandesh::options::AddOptions(&config, &sandesh_config_);
216 
217  config_file_options_.add(config);
218  cmdline_options.add(generic).add(config);
219 }
220 
221 uint32_t Options::GenerateHash(const std::vector<std::string> &list) {
222  std::string concat_servers;
223  std::vector<std::string>::const_iterator iter;
224  for (iter = list.begin(); iter != list.end(); iter++) {
225  concat_servers += *iter;
226  }
227  boost::hash<std::string> string_hash;
228  return(string_hash(concat_servers));
229 }
230 
232  uint32_t chk_sum = GenerateHash(config.config_db_server_list);
233  chk_sum += GenerateHash(config.rabbitmq_server_list);
234  boost::hash<std::string> string_hash;
235  chk_sum += string_hash(config.rabbitmq_user);
236  chk_sum += string_hash(config.rabbitmq_password);
237  chk_sum += string_hash(config.config_db_username);
238  chk_sum += string_hash(config.config_db_password);
239  return chk_sum;
240 }
241 
242 // Process command line options. They can come from a conf file as well. Options
243 // from command line always overrides those that come from the config file.
244 bool Options::Process(int argc, char *argv[],
245  opt::options_description &cmdline_options) {
246  // Process options off command line first.
247  opt::variables_map var_map;
248  opt::store(opt::parse_command_line(argc, argv, cmdline_options), var_map);
249 
250  // Process options off configuration file.
251  GetOptValue<string>(var_map, config_file_, "conf_file");
252  ifstream config_file_in;
253  config_file_in.open(config_file_.c_str());
254  if (config_file_in.good()) {
255  opt::store(opt::parse_config_file(config_file_in, config_file_options_),
256  var_map);
257  }
258  config_file_in.close();
259 
260  opt::notify(var_map);
261 
262  if (var_map.count("help")) {
263  cout << cmdline_options << endl;
264  return false;
265  }
266 
267  if (var_map.count("version")) {
268  string build_info;
270  build_info) << endl;
271  return false;
272  }
273 
274  // Retrieve the options.
275  GetOptValue<string>(var_map, bgp_config_file_, "DEFAULT.bgp_config_file");
276  GetOptValue<uint16_t>(var_map, bgp_port_, "DEFAULT.bgp_port");
277  GetOptValue< vector<string> >(var_map, collector_server_list_,
278  "DEFAULT.collectors");
279  string error_msg;
280  if (!ValidateServerEndpoints(collector_server_list_, &error_msg)) {
281  cout << "Invalid endpoint : " << error_msg;
282  return false;
283  }
284 
285  collectors_configured_ = collector_server_list_.size();
286  if (collector_server_list_.size() == 1 &&
287  !collector_server_list_[0].compare(default_collector_server_list_[0])) {
288  collectors_configured_ = false;
289  }
290 
291  // Randomize Collector List
292  collector_chksum_ = GenerateHash(collector_server_list_);
293  randomized_collector_server_list_ = collector_server_list_;
294  std::random_shuffle(randomized_collector_server_list_.begin(),
295  randomized_collector_server_list_.end());
296 
297  GetOptValue<string>(var_map, host_ip_, "DEFAULT.hostip");
298  if (!ValidateIPAddressString(host_ip_, &error_msg)) {
299  cout << "Invalid IP address: " << host_ip_ << error_msg;
300  return false;
301  }
302 
303  GetOptValue<string>(var_map, hostname_, "DEFAULT.hostname");
304 
305  GetOptValue<uint16_t>(var_map, http_server_port_,
306  "DEFAULT.http_server_port");
307 
308  GetOptValue<string>(var_map, log_category_, "DEFAULT.log_category");
309  GetOptValue<string>(var_map, log_file_, "DEFAULT.log_file");
310  GetOptValue<string>(var_map, log_property_file_, "DEFAULT.log_property_file");
311  GetOptValue<int>(var_map, log_files_count_, "DEFAULT.log_files_count");
312  GetOptValue<long>(var_map, log_file_size_, "DEFAULT.log_file_size");
313  GetOptValue<string>(var_map, log_level_, "DEFAULT.log_level");
314  GetOptValue<string>(var_map, syslog_facility_, "DEFAULT.syslog_facility");
315  GetOptValue<int>(var_map, tcp_hold_time_, "DEFAULT.tcp_hold_time");
316  GetOptValue<uint16_t>(var_map, xmpp_port_, "DEFAULT.xmpp_server_port");
317  GetOptValue<string>(var_map, xmpp_server_cert_, "DEFAULT.xmpp_server_cert");
318  GetOptValue<string>(var_map, xmpp_server_key_, "DEFAULT.xmpp_server_key");
319  GetOptValue<string>(var_map, xmpp_ca_cert_, "DEFAULT.xmpp_ca_cert");
320 
321  ParseConfigOptions(var_map);
322 
323  sandesh::options::ProcessOptions(var_map, &sandesh_config_);
324  return true;
325 }
326 
327 void Options::ParseReConfig(bool force_reinit) {
328  // ReParse the filtered config params
329  opt::variables_map var_map;
330  ifstream config_file_in;
331  config_file_in.open(config_file_.c_str());
332  if (config_file_in.good()) {
333  opt::store(opt::parse_config_file(config_file_in, config_file_options_),
334  var_map);
335  }
336  config_file_in.close();
337 
338  collector_server_list_.clear();
339  GetOptValue< vector<string> >(var_map, collector_server_list_,
340  "DEFAULT.collectors");
341 
342  uint32_t new_chksum = GenerateHash(collector_server_list_);
343  if (collector_chksum_ != new_chksum) {
344  collector_chksum_ = new_chksum;
345  randomized_collector_server_list_.clear();
346  randomized_collector_server_list_ = collector_server_list_;
347  std::random_shuffle(randomized_collector_server_list_.begin(),
348  randomized_collector_server_list_.end());
349  }
350  // ReConnect Collectors irrespective of change list to achieve
351  // rebalance when older collector node/s are up again.
352  Sandesh::ReConfigCollectors(randomized_collector_server_list_);
353 
354  uint32_t old_config_chksum = configdb_chksum_;
355  ParseConfigOptions(var_map);
356  if ((force_reinit || old_config_chksum != configdb_chksum_) &&
357  config_client_manager_) {
358  config_client_manager_->ReinitConfigClient(configdb_options());
359  }
360 }
361 
362 void Options::ParseConfigOptions(const boost::program_options::variables_map
363  &var_map) {
364  configdb_options_.config_db_server_list.clear();
365  GetOptValue< vector<string> >(var_map,
366  configdb_options_.config_db_server_list,
367  "CONFIGDB.config_db_server_list");
368  GetOptValue<string>(var_map,
369  configdb_options_.config_db_username,
370  "CONFIGDB.config_db_username");
371  GetOptValue<string>(var_map,
372  configdb_options_.config_db_password,
373  "CONFIGDB.config_db_password");
374  GetOptValue<bool>(var_map,
375  configdb_options_.config_db_use_ssl,
376  "CONFIGDB.config_db_use_ssl");
377  GetOptValue<string>(var_map,
378  configdb_options_.config_db_ca_certs,
379  "CONFIGDB.config_db_ca_certs");
380  configdb_options_.rabbitmq_server_list.clear();
381  GetOptValue< vector<string> >(var_map,
382  configdb_options_.rabbitmq_server_list,
383  "CONFIGDB.rabbitmq_server_list");
384  GetOptValue<string>(var_map,
385  configdb_options_.rabbitmq_user,
386  "CONFIGDB.rabbitmq_user");
387  GetOptValue<string>(var_map,
388  configdb_options_.rabbitmq_password,
389  "CONFIGDB.rabbitmq_password");
390  GetOptValue<string>(var_map,
391  configdb_options_.rabbitmq_vhost,
392  "CONFIGDB.rabbitmq_vhost");
393  GetOptValue<bool>(var_map,
394  configdb_options_.rabbitmq_use_ssl,
395  "CONFIGDB.rabbitmq_use_ssl");
396  GetOptValue<string>(var_map,
397  configdb_options_.rabbitmq_ssl_version,
398  "CONFIGDB.rabbitmq_ssl_version");
399  GetOptValue<string>(var_map,
400  configdb_options_.rabbitmq_ssl_keyfile,
401  "CONFIGDB.rabbitmq_ssl_keyfile");
402  GetOptValue<string>(var_map,
403  configdb_options_.rabbitmq_ssl_certfile,
404  "CONFIGDB.rabbitmq_ssl_certfile");
405  GetOptValue<string>(var_map,
406  configdb_options_.rabbitmq_ssl_ca_certs,
407  "CONFIGDB.rabbitmq_ssl_ca_certs");
408  GetOptValue<bool>(var_map,
409  configdb_options_.config_db_use_etcd,
410  "CONFIGDB.config_db_use_etcd");
411  configdb_chksum_ = GenerateHash(configdb_options_);
412 }
bool Process(int argc, char *argv[], boost::program_options::options_description &cmdline_options)
uint32_t GenerateHash(const std::vector< std::string > &list)
Definition: options.cc:221
void ParseConfigOptions(const boost::program_options::variables_map &var_map)
Definition: options.cc:362
static void ReConfigCollectors(const std::vector< std::string > &collector_list)
Definition: sandesh.cc:230
boost::asio::io_context * io_service()
Definition: event_manager.h:42
static const uint16_t ControlBgp()
static bool GetBuildInfo(BuildModule id, const std::string &build_info, std::string &result)
Definition: misc_utils.cc:99
static const uint16_t HttpPortControl()
bool ValidateServerEndpoints(std::vector< std::string > list, std::string *error_msg)
void Initialize(EventManager &evm, boost::program_options::options_description &options)
void ParseReConfig()
Definition: dns_options.cc:369
Options()
Definition: options.cc:27
static bool use_syslog_
Definition: logging.cc:20
static const uint16_t ControlXmpp()
void ProcessOptions(const opt::variables_map &var_map, SandeshConfig *sandesh_config)
bool ValidateIPAddressString(std::string ip_address_str, std::string *error_msg)
std::vector< std::string > config_db_server_list
std::string GetHostIp(boost::asio::io_context *io_service, const std::string &hostname)
std::vector< std::string > rabbitmq_server_list
void AddOptions(opt::options_description *sandesh_options, SandeshConfig *sandesh_config)
bool Parse(EventManager &evm, int argc, char **argv)
static EventManager evm