LCOV - code coverage report
Current view: top level - control-node - options.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 205 238 86.1 %
Date: 2026-05-18 11:54:02 Functions: 7 8 87.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14