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