Line data Source code
1 : /*
2 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <fstream>
7 : #include <iostream>
8 : #include <boost/foreach.hpp>
9 : #include <boost/functional/hash.hpp>
10 :
11 : #include "base/contrail_ports.h"
12 : #include "base/logging.h"
13 : #include "base/misc_utils.h"
14 : #include "base/address_util.h"
15 : #include "base/util.h"
16 : #include <base/options_util.h>
17 : #include <query_engine/buildinfo.h>
18 : #include "viz_constants.h"
19 :
20 : #include "options.h"
21 :
22 : using namespace std;
23 : using namespace boost::asio::ip;
24 : namespace opt = boost::program_options;
25 : using namespace options::util;
26 :
27 : // Process command line options for query-engine .
28 51 : Options::Options() {
29 51 : }
30 :
31 51 : bool Options::Parse(EventManager &evm, int argc, char *argv[]) {
32 102 : opt::options_description cmdline_options("Allowed options");
33 51 : Initialize(evm, cmdline_options);
34 :
35 51 : Process(argc, argv, cmdline_options);
36 51 : return true;
37 51 : }
38 :
39 51 : uint32_t Options::GenerateHash(std::vector<std::string> &list) {
40 51 : std::string concat_servers;
41 51 : std::vector<std::string>::iterator iter;
42 110 : for (iter = list.begin(); iter != list.end(); iter++) {
43 59 : concat_servers += *iter;
44 : }
45 : boost::hash<std::string> string_hash;
46 102 : return(string_hash(concat_servers));
47 51 : }
48 :
49 : // Initialize query-engine's command line option tags with appropriate default
50 : // values. Options can from a config file as well. By default, we read
51 : // options from /etc/contrail/contrail-query-engine.conf
52 51 : void Options::Initialize(EventManager &evm,
53 : opt::options_description &cmdline_options) {
54 51 : boost::system::error_code error;
55 51 : string hostname = ResolveCanonicalName();
56 51 : string host_ip = GetHostIp(evm.io_service(), hostname);
57 51 : if (host_ip.empty()) {
58 : cout << "Error! Cannot resolve host " << hostname <<
59 0 : " to a valid IP address";
60 0 : exit(-1);
61 : }
62 :
63 : map<string, vector<string> >::const_iterator it =
64 51 : g_vns_constants.ServicesDefaultConfigurationFiles.find(
65 : g_vns_constants.SERVICE_QUERY_ENGINE);
66 51 : assert(it != g_vns_constants.ServicesDefaultConfigurationFiles.end());
67 51 : const vector<string> &conf_files(it->second);
68 :
69 102 : opt::options_description generic("Generic options");
70 :
71 : // Command line only options.
72 51 : ostringstream conf_files_oss;
73 51 : bool first = true;
74 255 : BOOST_FOREACH(const string &cfile, conf_files) {
75 102 : if (first) {
76 51 : conf_files_oss << cfile;
77 51 : first = false;
78 : } else {
79 51 : conf_files_oss << ", " << cfile;
80 : }
81 : }
82 51 : generic.add_options()
83 102 : ("conf_file", opt::value<vector<string> >()->default_value(
84 102 : conf_files, conf_files_oss.str()),
85 : "Configuration file")
86 51 : ("help", "help message")
87 51 : ("version", "Display version information")
88 : ;
89 :
90 51 : uint16_t default_redis_port = ContrailPorts::RedisQueryPort();
91 51 : uint16_t default_http_server_port = ContrailPorts::HttpPortQueryEngine();
92 :
93 51 : vector<string> default_cassandra_server_list;
94 51 : default_cassandra_server_list.push_back("127.0.0.1:9160");
95 51 : default_collector_server_list_.push_back("127.0.0.1:8086");
96 : // Command line and config file options.
97 102 : opt::options_description cassandra_config("Configuration options");
98 51 : cassandra_config.add_options()
99 102 : ("CASSANDRA.cassandra_user", opt::value<string>()->default_value(""),
100 : "name for cassandra")
101 102 : ("CASSANDRA.cassandra_password", opt::value<string>()->default_value(""),
102 : "password for cassandra")
103 51 : ("CASSANDRA.cassandra_use_ssl", opt::bool_switch(&cassandra_use_ssl_),
104 : "SSL on/off for cassandra")
105 51 : ("CASSANDRA.cassandra_ca_certs", opt::value<string>()->default_value(""),
106 : "Path to CA certs file for cassandra's SSL");
107 :
108 : // Command line and config file options.
109 102 : opt::options_description config("Configuration options");
110 51 : config.add_options()
111 102 : ("DEFAULT.analytics_data_ttl",
112 51 : opt::value<int>()->default_value(0),
113 : "global TTL(hours) for analytics data")
114 102 : ("DEFAULT.collectors",
115 51 : opt::value<vector<string> >(),
116 : "Collector server list")
117 102 : ("DEFAULT.cassandra_server_list",
118 102 : opt::value<vector<string> >()->default_value(
119 : default_cassandra_server_list, "127.0.0.1:9160"),
120 : "Cassandra server list")
121 51 : ("DEFAULT.hostip", opt::value<string>()->default_value(host_ip),
122 : "IP address of query-engine")
123 51 : ("DEFAULT.hostname", opt::value<string>()->default_value(hostname),
124 : "Hostname of query-engine")
125 102 : ("DEFAULT.http_server_port",
126 51 : opt::value<uint16_t>()->default_value(default_http_server_port),
127 : "Sandesh HTTP listener port")
128 :
129 51 : ("DEFAULT.log_category", opt::value<string>(),
130 : "Category filter for local logging of sandesh messages")
131 51 : ("DEFAULT.log_disable", opt::bool_switch(&log_disable_),
132 : "Disable sandesh logging")
133 102 : ("DEFAULT.log_file", opt::value<string>()->default_value("<stdout>"),
134 : "Filename for the logs to be written to")
135 102 : ("DEFAULT.log_property_file", opt::value<string>()->default_value(""),
136 : "log4cplus property file name")
137 102 : ("DEFAULT.log_files_count",
138 51 : opt::value<int>()->default_value(10),
139 : "Maximum log file roll over index")
140 102 : ("DEFAULT.log_file_size",
141 51 : opt::value<long>()->default_value(1024*1024),
142 : "Maximum size of the log file")
143 102 : ("DEFAULT.log_level", opt::value<string>()->default_value("SYS_NOTICE"),
144 : "Severity level for local logging of sandesh messages")
145 51 : ("DEFAULT.log_local", opt::bool_switch(&log_local_),
146 : "Enable local logging of sandesh messages")
147 51 : ("DEFAULT.use_syslog", opt::bool_switch(&use_syslog_),
148 : "Enable logging to syslog")
149 102 : ("DEFAULT.syslog_facility", opt::value<string>()->default_value("LOG_LOCAL0"),
150 : "Syslog facility to receive log lines")
151 51 : ("DEFAULT.max_slice", opt::value<int>()->default_value(100),
152 : "Max number of rows in chunk slice")
153 51 : ("DEFAULT.max_tasks", opt::value<int>()->default_value(0),
154 : "Max number of tasks used for a query")
155 102 : ("DEFAULT.start_time", opt::value<uint64_t>()->default_value(0),
156 : "Lowest start time for queries")
157 :
158 51 : ("DEFAULT.test_mode", opt::bool_switch(&test_mode_),
159 : "Enable query-engine to run in test-mode")
160 : ;
161 :
162 : // Command line and config file options.
163 102 : opt::options_description redis_config("Redis Configuration options");
164 51 : vector<string> default_redis_server_list;
165 51 : default_redis_server_list.push_back("127.0.0.1:6379");
166 51 : redis_config.add_options()
167 102 : ("REDIS.port",
168 51 : opt::value<uint16_t>()->default_value(default_redis_port),
169 : "Port of Redis-uve server")
170 102 : ("REDIS.server_list",
171 102 : opt::value<vector<string> >()->default_value(
172 : default_redis_server_list, "127.0.0.1:6379"),
173 : "IP address:port of Redis Servers")
174 102 : ("REDIS.server", opt::value<string>()->default_value("127.0.0.1"),
175 : "IP address of Redis Server")
176 102 : ("REDIS.password", opt::value<string>()->default_value(""),
177 : "password for Redis Server")
178 102 : ("REDIS.redis_ssl_enable",
179 51 : opt::value<bool>()->default_value(false),
180 : "Enable SSL Encryptions for Redis connection")
181 102 : ("REDIS.redis_keyfile", opt::value<std::string>()->default_value(
182 : "/etc/contrail/ssl/private/server-privkey.pem"),
183 : "Redis SSL private key")
184 102 : ("REDIS.redis_certfile", opt::value<std::string>()->default_value(
185 : "/etc/contrail/ssl/certs/server.pem"),
186 : "Redis SSL certificate")
187 51 : ("REDIS.redis_ca_cert", opt::value<std::string>()->default_value(
188 : "/etc/contrail/ssl/certs/ca-cert.pem"),
189 : "Redis CA SSL certificate")
190 : ;
191 :
192 : // Command line and config file options.
193 102 : opt::options_description sandesh_config("Sandesh Configuration options");
194 51 : sandesh::options::AddOptions(&sandesh_config, &sandesh_config_);
195 :
196 : // Command line and config file options.
197 102 : opt::options_description database_config("Database Configuration options");
198 51 : database_config.add_options()
199 51 : ("DATABASE.cluster_id", opt::value<string>()->default_value(""),
200 : "Analytics Cluster Id")
201 : ;
202 :
203 51 : config_file_options_.add(config).add(cassandra_config)
204 51 : .add(redis_config).add(sandesh_config).add(database_config);
205 51 : cmdline_options.add(generic).add(config).add(cassandra_config)
206 51 : .add(redis_config).add(sandesh_config).add(database_config);
207 51 : }
208 :
209 : // Process command line options. They can come from a conf file as well. Options
210 : // from command line always overrides those that come from the config file.
211 51 : void Options::Process(int argc, char *argv[],
212 : opt::options_description &cmdline_options) {
213 : // Process options off command line first.
214 51 : opt::variables_map var_map;
215 51 : opt::store(opt::parse_command_line(argc, argv, cmdline_options), var_map);
216 :
217 : // Process options off configuration file.
218 51 : GetOptValue<vector<string> >(var_map, config_file_, "conf_file");
219 51 : ifstream config_file_in;
220 151 : for(std::vector<int>::size_type i = 0; i != config_file_.size(); i++) {
221 100 : config_file_in.open(config_file_[i].c_str());
222 100 : if (config_file_in.good()) {
223 8 : opt::store(opt::parse_config_file(config_file_in, config_file_options_),
224 : var_map);
225 : }
226 100 : config_file_in.close();
227 : }
228 :
229 51 : opt::notify(var_map);
230 :
231 51 : if (var_map.count("help")) {
232 0 : cout << cmdline_options << endl;
233 0 : exit(0);
234 : }
235 :
236 51 : if (var_map.count("version")) {
237 0 : cout << BuildInfo << endl;
238 0 : exit(0);
239 : }
240 :
241 : // Retrieve the options.
242 51 : GetOptValue<int>(var_map, analytics_data_ttl_,
243 : "DEFAULT.analytics_data_ttl");
244 :
245 51 : GetOptValue< vector<string> >(var_map, cassandra_server_list_,
246 : "DEFAULT.cassandra_server_list");
247 51 : GetOptValue< vector<string> >(var_map, collector_server_list_,
248 : "DEFAULT.collectors");
249 : // Randomize Collector List
250 51 : collector_chksum_ = GenerateHash(collector_server_list_);
251 51 : randomized_collector_server_list_ = collector_server_list_;
252 51 : std::random_shuffle(randomized_collector_server_list_.begin(),
253 : randomized_collector_server_list_.end());
254 :
255 51 : GetOptValue<string>(var_map, host_ip_, "DEFAULT.hostip");
256 51 : GetOptValue<string>(var_map, hostname_, "DEFAULT.hostname");
257 51 : GetOptValue<uint16_t>(var_map, http_server_port_,
258 : "DEFAULT.http_server_port");
259 :
260 51 : GetOptValue<string>(var_map, log_category_, "DEFAULT.log_category");
261 51 : GetOptValue<string>(var_map, log_file_, "DEFAULT.log_file");
262 51 : GetOptValue<string>(var_map, log_property_file_, "DEFAULT.log_property_file");
263 51 : GetOptValue<int>(var_map, log_files_count_, "DEFAULT.log_files_count");
264 51 : GetOptValue<long>(var_map, log_file_size_, "DEFAULT.log_file_size");
265 51 : GetOptValue<string>(var_map, log_level_, "DEFAULT.log_level");
266 51 : GetOptValue<bool>(var_map, use_syslog_, "DEFAULT.use_syslog");
267 51 : GetOptValue<string>(var_map, syslog_facility_, "DEFAULT.syslog_facility");
268 51 : GetOptValue<uint64_t>(var_map, start_time_, "DEFAULT.start_time");
269 51 : GetOptValue<int>(var_map, max_tasks_, "DEFAULT.max_tasks");
270 51 : GetOptValue<int>(var_map, max_slice_, "DEFAULT.max_slice");
271 :
272 51 : GetOptValue< vector<string> >(var_map, redis_server_list_,
273 : "REDIS.server_list");
274 51 : GetOptValue<string>(var_map, redis_server_, "REDIS.server");
275 51 : GetOptValue<uint16_t>(var_map, redis_port_, "REDIS.port");
276 51 : GetOptValue<string>(var_map, redis_password_, "REDIS.password");
277 51 : GetOptValue<bool>(var_map, redis_ssl_enable_, "REDIS.redis_ssl_enable");
278 51 : GetOptValue<string>(var_map, redis_keyfile_, "REDIS.redis_keyfile");
279 51 : GetOptValue<string>(var_map, redis_certfile_, "REDIS.redis_certfile");
280 51 : GetOptValue<string>(var_map, redis_ca_cert_, "REDIS.redis_ca_cert");
281 51 : GetOptValue<string>(var_map, cluster_id_, "DATABASE.cluster_id");
282 51 : GetOptValue<string>(var_map, cassandra_user_, "CASSANDRA.cassandra_user");
283 51 : GetOptValue<string>(var_map, cassandra_password_, "CASSANDRA.cassandra_password");
284 51 : GetOptValue<bool>(var_map, cassandra_use_ssl_, "CASSANDRA.cassandra_use_ssl");
285 51 : GetOptValue<string>(var_map, cassandra_ca_certs_, "CASSANDRA.cassandra_ca_certs");
286 :
287 51 : sandesh::options::ProcessOptions(var_map, &sandesh_config_);
288 51 : }
289 :
290 0 : void Options::ParseReConfig() {
291 : // ReParse the filtered config params
292 0 : opt::variables_map var_map;
293 0 : ifstream config_file_in;
294 0 : for(std::vector<int>::size_type i = 0; i != config_file_.size(); i++) {
295 0 : config_file_in.open(config_file_[i].c_str());
296 0 : if (config_file_in.good()) {
297 0 : opt::store(opt::parse_config_file(config_file_in, config_file_options_),
298 : var_map);
299 : }
300 0 : config_file_in.close();
301 : }
302 :
303 0 : collector_server_list_.clear();
304 0 : GetOptValue< vector<string> >(var_map, collector_server_list_,
305 : "DEFAULT.collectors");
306 0 : uint32_t new_chksum = GenerateHash(collector_server_list_);
307 0 : if (collector_chksum_ != new_chksum) {
308 0 : collector_chksum_ = new_chksum;
309 0 : randomized_collector_server_list_.clear();
310 0 : randomized_collector_server_list_ = collector_server_list_;
311 0 : std::random_shuffle(randomized_collector_server_list_.begin(),
312 : randomized_collector_server_list_.end());
313 : }
314 : // ReConnect Collectors irrespective of change list to achieve
315 : // rebalance when older collector nodes are up again.
316 0 : Sandesh::ReConfigCollectors(randomized_collector_server_list_);
317 0 : }
|