OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
controller/src/control-node/main.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 
6 #include <csignal>
7 #include <fstream>
8 #include <iostream>
9 
10 #include <boost/asio/ip/host_name.hpp>
11 #include <boost/bind.hpp>
12 #include <boost/date_time/posix_time/posix_time.hpp>
13 #include <boost/program_options.hpp>
14 
15 #include "nodeinfo_types.h"
16 #include "base/connection_info.h"
17 #include "base/logging.h"
18 #include "base/misc_utils.h"
19 #include "base/address_util.h"
20 #include "io/process_signal.h"
21 #include "bgp/bgp_config.h"
22 #include "bgp/bgp_config_ifmap.h"
23 #include "bgp/bgp_config_parser.h"
24 #include "bgp/bgp_ifmap_sandesh.h"
25 #include "bgp/bgp_peer.h"
26 #include "bgp/bgp_peer_types.h"
27 #include "bgp/bgp_sandesh.h"
28 #include "bgp/bgp_xmpp_sandesh.h"
29 #include "bgp/bgp_server.h"
31 #include "bgp/bgp_xmpp_channel.h"
35 #include "config_client_manager.h"
36 #include "control-node/buildinfo.h"
38 #include "control-node/options.h"
39 #include "db/db_graph.h"
41 #include "ifmap/ifmap_link_table.h"
43 #include "ifmap/ifmap_server.h"
44 #include "ifmap/ifmap_xmpp.h"
45 #include "io/event_manager.h"
46 #include "sandesh/common/vns_constants.h"
47 #include "sandesh/common/vns_types.h"
48 #include "sandesh/sandesh_http.h"
49 #include "sandesh/sandesh_trace.h"
50 #include "schema/bgp_schema_types.h"
51 #include "schema/vnc_cfg_types.h"
52 #include "xmpp/sandesh/xmpp_peer_info_types.h"
53 #include "xmpp/xmpp_init.h"
54 #include "xmpp/xmpp_sandesh.h"
55 #include "xmpp/xmpp_server.h"
56 
57 using namespace std;
58 using namespace boost::asio::ip;
59 using process::ConnectionInfo;
62 using process::ProcessState;
63 using process::ConnectionType;
65 using process::g_process_info_constants;
66 using process::Signal;
67 
70 
71 static string FileRead(const char *filename) {
72  ifstream file(filename);
73  string content((istreambuf_iterator<char>(file)),
74  istreambuf_iterator<char>());
75  return content;
76 }
77 
78 static void IFMap_Initialize(IFMapServer *server, ConfigJsonParser *json_parser) {
79  IFMapLinkTable_Init(server->database(), server->graph());
80  vnc_cfg_JsonParserInit(json_parser);
81  vnc_cfg_Server_ModuleInit(server->database(), server->graph());
82  bgp_schema_JsonParserInit(json_parser);
83  bgp_schema_Server_ModuleInit(server->database(), server->graph());
84  server->Initialize();
85 }
86 
88  XmppChannelConfig *xmpp_cfg) {
89 
90  // XmppChannel Configuration
91  xmpp_cfg->endpoint.port(options->xmpp_port());
93  xmpp_cfg->auth_enabled = options->xmpp_auth_enabled();
94  xmpp_cfg->tcp_hold_time = options->tcp_hold_time();
95  xmpp_cfg->gr_helper_disable = options->gr_helper_xmpp_disable();
96 
97  if (xmpp_cfg->auth_enabled) {
98  xmpp_cfg->path_to_server_cert = options->xmpp_server_cert();
99  xmpp_cfg->path_to_server_priv_key = options->xmpp_server_key();
100  xmpp_cfg->path_to_ca_cert = options->xmpp_ca_cert();
101  }
102 
103  // Create XmppServer
104  XmppServer *xmpp_server;
105  xmpp_server = new XmppServer(evm, options->hostname(), xmpp_cfg);
106  boost::system::error_code ec;
107  IpAddress xmpp_ip_address = AddressFromString(options->host_ip(), &ec);
108  if (ec) {
109  CONTROL_NODE_EXIT("Xmpp IP Address " << options->host_ip() <<
110  " conversion error:" << ec.message());
111  }
112  if (!xmpp_server->Initialize(options->xmpp_port(), true,
113  xmpp_ip_address)) {
114  return NULL;
115  } else {
116  return (xmpp_server);
117  }
118 }
119 
120 static void WaitForIdle() {
121  static const int kTimeout = 15;
123 
124  for (int i = 0; i < (kTimeout * 1000); i++) {
125  if (scheduler->IsEmpty()) {
126  break;
127  }
128  usleep(1000);
129  }
130 }
131 
132 // Shutdown various server objects used in the control-node.
133 static void ShutdownServers(
134  boost::scoped_ptr<BgpXmppChannelManager> *channel_manager) {
135 
136  // Bring down bgp server, xmpp server, etc. in the right order.
137  BgpServer *bgp_server = (*channel_manager)->bgp_server();
138  XmppServer *xmpp_server = (*channel_manager)->xmpp_server();
139 
140  // Shutdown Xmpp server first.
141  xmpp_server->Shutdown();
142  WaitForIdle();
143 
144  // Wait until all XMPP connections are cleaned up.
145  for (int cnt = 0; xmpp_server->ConnectionCount() != 0 && cnt < 15; cnt++) {
146  sleep(1);
147  }
148 
149  // Shutdown BGP server.
150  bgp_server->Shutdown();
151  WaitForIdle();
152 
153  // Wait until all routing-instances are cleaned up.
154  for (int cnt = 0;
155  bgp_server->routing_instance_mgr()->count() != 0 && cnt < 15;
156  cnt++) {
157  sleep(1);
158  }
159 
160  channel_manager->reset();
161  TcpServerManager::DeleteServer(xmpp_server);
163 
164  ConnectionStateManager::
165  GetInstance()->Shutdown();
166 
167  // Do sandesh cleanup.
168  Sandesh::Uninit();
169  WaitForIdle();
171  WaitForIdle();
172 }
173 
174 // Trigger graceful shutdown of control-node process.
175 //
176 // IO (evm) is shutdown first. Afterwards, main() resumes, shutting down rest
177 // of the objects, and eventually exit()s.
179  static bool shutdown_;
180 
181  if (shutdown_) return;
182  shutdown_ = true;
183 
184  // Shutdown event manager first to stop all IO activities.
185  evm.Shutdown();
186 }
187 
188 static void ControlNodeGetProcessStateCb(const BgpServer *bgp_server,
189  const ConfigClientManager *config_client_manager,
190  const std::vector<ConnectionInfo> &cinfos,
191  ProcessState::type &state, std::string &message,
192  std::vector<ConnectionTypeName> expected_connections) {
193  GetProcessStateCb(cinfos, state, message, expected_connections);
195  bgp_server->admin_down(), config_client_manager->GetEndOfRibComputed(),
196  &state, &message);
197 }
198 
199 // Docker restart takes long time as control node is not handling SIGTERM
200 // its better to exit gracefully.
201 void SigTermSignalHandler(const boost::system::error_code &error, int sig,
202  bool force_reinit) {
203  CONTROL_NODE_EXIT("Received terminating signal " << sig);
204 }
205 
206 void ReConfigSignalHandler(const boost::system::error_code &error, int sig,
207  bool force_reinit) {
208  if (error) {
209  LOG(ERROR, "SIGHUP handler ERROR: " << error);
210  return;
211  }
212  LOG(WARN, "Received signal " << sig << " inside ReConfigSignalHandler()");
213  options.ParseReConfig(force_reinit);
214 }
215 
216 int main(int argc, char *argv[]) {
217  // Process options from command-line and configuration file.
218  if (!options.Parse(evm, argc, argv)) {
219  CONTROL_NODE_EXIT("Invalid command line arguments");
220  }
221 
222  srand(unsigned(time(NULL)));
223  std::vector<Signal::SignalHandler> sighup_handlers = boost::assign::list_of
224  (boost::bind(&ReConfigSignalHandler, _1, _2, false));
225  std::vector<Signal::SignalHandler> sigusr1_handlers = boost::assign::list_of
226  (boost::bind(&ReConfigSignalHandler, _1, _2, true));
227  std::vector<Signal::SignalHandler> sigterm_handler = boost::assign::list_of
228  (boost::bind(&SigTermSignalHandler, _1, _2, true));
229  Signal::SignalCallbackMap smap = boost::assign::map_list_of
230  (SIGHUP, sighup_handlers)
231  (SIGUSR1, sigusr1_handlers)
232  (SIGTERM, sigterm_handler)
233  ;
234  Signal signal(&evm, smap);
235 
237  Module::type module = Module::CONTROL_NODE;
238  string module_name = g_vns_constants.ModuleNames.find(module)->second;
239  std::string log_property_file = options.log_property_file();
240  if (log_property_file.size()) {
241  LoggingInit(log_property_file);
242  } else {
245  options.syslog_facility(), module_name,
248  }
249 
250  int num_threads_to_tbb = TaskScheduler::GetDefaultThreadCount() +
252  TaskScheduler::Initialize(num_threads_to_tbb, &evm);
257 
258  BgpSandeshContext sandesh_context;
259  RegisterSandeshShowIfmapHandlers(&sandesh_context);
260  RegisterSandeshShowXmppExtensions(&sandesh_context);
262  options.log_level());
263 
264  // Disable logging -- for test purposes only.
265  if (options.log_disable()) {
266  SetLoggingDisabled(true);
267  }
268 
270 
272 
275  boost::scoped_ptr<BgpServer> bgp_server(new BgpServer(&evm));
276  sandesh_context.set_test_mode(ControlNode::GetTestMode());
277  sandesh_context.bgp_server = bgp_server.get();
279  bgp_server->set_mvpn_ipv4_enable(options.mvpn_ipv4_enable());
280 
281  ConnectionStateManager::GetInstance();
282 
283  DB config_db(TaskScheduler::GetInstance()->GetTaskId("db::IFMapTable"));
284  DBGraph config_graph;
285  IFMapServer ifmap_server(&config_db, &config_graph, evm.io_service());
286 
288  ConfigJsonParser>();
289 
290  boost::scoped_ptr<ConfigClientManager> config_client_manager_ptr(
292  ConfigStaticObjectFactory::Create<ConfigJsonParserBase>(),
293  options.hostname(),
294  module_name,
296  ConfigClientManager *config_client_manager = config_client_manager_ptr.get();
297  ConfigJsonParser *json_parser = static_cast<ConfigJsonParser *>(
298  config_client_manager->config_json_parser());
299  json_parser->ifmap_server_set(&ifmap_server);
300  IFMap_Initialize(&ifmap_server, json_parser);
301  ifmap_server.set_config_manager(config_client_manager);
302 
303  BgpIfmapConfigManager *config_manager =
304  static_cast<BgpIfmapConfigManager *>(bgp_server->config_manager());
305  config_manager->Initialize(&config_db, &config_graph, options.hostname());
307  BgpConfigParser parser(&config_db);
308  parser.Parse(FileRead(options.bgp_config_file().c_str()));
309 
310  boost::system::error_code ec;
311  IpAddress bgp_ip_address = AddressFromString(options.host_ip(), &ec);
312  if (ec) {
313  CONTROL_NODE_EXIT("BGP IP Address " << options.host_ip() <<
314  " conversion error: " << ec.message());
315  }
316  bgp_server->rtarget_group_mgr()->Initialize();
317  bgp_server->session_manager()->Initialize(options.bgp_port(),
318  bgp_ip_address);
319 
320  // Create Xmpp Server.
321  XmppChannelConfig xmpp_cfg(false);
322  xmpp_cfg.dscp_value = bgp_server->global_qos()->control_dscp();
323  XmppServer *xmpp_server = CreateXmppServer(&evm, &options, &xmpp_cfg);
324  if (xmpp_server == NULL) {
325  CONTROL_NODE_EXIT("XmppServer creation failed");
326  }
327 
328  // Create BGP and IFMap channel managers.
329  boost::scoped_ptr<BgpXmppChannelManager> bgp_peer_manager(
330  new BgpXmppChannelManager(xmpp_server, bgp_server.get()));
331  sandesh_context.xmpp_peer_manager = bgp_peer_manager.get();
332  IFMapChannelManager ifmap_channel_mgr(xmpp_server, &ifmap_server);
333  ifmap_server.set_ifmap_channel_manager(&ifmap_channel_mgr);
334 
335  XmppSandeshContext xmpp_sandesh_context;
336  xmpp_sandesh_context.xmpp_server = xmpp_server;
337  Sandesh::set_module_context("XMPP", &xmpp_sandesh_context);
338  IFMapSandeshContext ifmap_sandesh_context(&ifmap_server);
339  Sandesh::set_module_context("IFMap", &ifmap_sandesh_context);
340 
341  // Determine if the number of connections is as expected. At the moment,
342  // consider connections to collector, cassandra and rabbit servers
343  //
344  // 1. Collector client
345  // 2. Cassandra Server
346  // 3. AMQP Server
347  std::vector<ConnectionTypeName> expected_connections;
348  expected_connections = boost::assign::list_of
349  (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
350  ConnectionType::DATABASE)->second, "Cassandra"))
351  (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
352  ConnectionType::DATABASE)->second, "RabbitMQ"))
353  (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
354  ConnectionType::COLLECTOR)->second, ""))
355  .convert_to_container<vector<\
357 
359  LOG(INFO, "Collectors are not configured!");
360  expected_connections.pop_back();
361  }
362 
363  ConnectionStateManager::GetInstance()->Init(
365  module_name, g_vns_constants.INSTANCE_ID_DEFAULT,
366  boost::bind(&ControlNodeGetProcessStateCb,
367  bgp_server.get(), config_client_manager, _1, _2, _3,
368  expected_connections), "ObjectBgpRouter");
369 
370  NodeType::type node_type =
371  g_vns_constants.Module2NodeType.find(module)->second;
372  bool success;
374  success = Sandesh::InitGenerator(
375  module_name,
376  options.hostname(),
377  g_vns_constants.NodeTypeNames.find(node_type)->second,
378  g_vns_constants.INSTANCE_ID_DEFAULT,
379  &evm,
382  &sandesh_context,
385  } else {
386  success = Sandesh::InitGenerator(
387  g_vns_constants.ModuleNames.find(module)->second,
388  options.hostname(),
389  g_vns_constants.NodeTypeNames.find(node_type)->second,
390  g_vns_constants.INSTANCE_ID_DEFAULT,
391  &evm,
393  &sandesh_context,
396  }
397  if (!success) {
398  Sandesh::Uninit();
399  CONTROL_NODE_EXIT("Sandesh initialization failed");
400  }
401 
402  // Set BuildInfo.
403  string build_info;
404  MiscUtils::GetBuildInfo(MiscUtils::ControlNode, BuildInfo, build_info);
406  bgp_server.get(),
407  bgp_peer_manager.get(),
408  &ifmap_server, build_info);
409 
410  options.set_config_client_manager(config_client_manager);
411  config_client_manager->Initialize();
412 
413  // Event loop.
414  evm.Run();
415 
416  signal.Terminate();
417  ShutdownServers(&bgp_peer_manager);
419  return 0;
420 }
BgpXmppChannelManager * xmpp_peer_manager
Definition: bgp_sandesh.h:47
boost::asio::ip::tcp::endpoint endpoint
Definition: xmpp_config.h:24
ConfigJsonParserBase * config_json_parser()
log4cplus::LogLevel SandeshLevelTolog4Level(SandeshLevel::type slevel)
Definition: sandesh.cc:395
static void SetHostname(const std::string name)
Definition: control_node.h:29
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
std::string log_level() const
Definition: options.h:36
int log_files_count() const
Definition: options.h:34
#define CONTROL_NODE_EXIT(message)
Definition: control_node.h:20
static int GetDefaultThreadCount()
Definition: task.cc:429
static void Initialize(uint32_t thread_count=0, EventManager *evm=NULL)
Definition: task.cc:478
size_t count() const
static SandeshLevel::type StringToLevel(std::string level)
Definition: sandesh.cc:861
bool test_mode() const
Definition: options.h:77
void Initialize()
DBGraph * graph()
Definition: ifmap_server.h:83
const ConfigClientOptions & configdb_options() const
Definition: options.h:69
void ParseReConfig(bool force_reinit)
Definition: options.cc:327
BgpServer * bgp_server
Definition: bgp_sandesh.h:46
uint16_t http_server_port() const
Definition: options.h:29
static void SetLoggingParams(bool enable_local_log, std::string category, std::string level, bool enable_trace_print=false, bool enable_flow_log=false, bool enable_session_syslog=false)
Definition: sandesh.cc:369
virtual bool Initialize(short port)
Definition: xmpp_server.cc:300
static bool GetTestMode()
Definition: control_node.h:36
boost::asio::ip::address IpAddress
Definition: address.h:13
long log_file_size() const
Definition: options.h:35
void ifmap_server_set(IFMapServer *ifmap_server)
void RegisterSandeshShowIfmapHandlers(BgpSandeshContext *bsc)
boost::asio::io_context * io_service()
Definition: event_manager.h:42
static void Terminate()
Definition: bgp_server.cc:552
RoutingInstanceMgr * routing_instance_mgr()
Definition: bgp_server.h:102
static bool GetBuildInfo(BuildModule id, const std::string &build_info, std::string &result)
Definition: misc_utils.cc:99
void Shutdown()
Definition: bgp_server.cc:560
static void WaitForIdle()
bool mvpn_ipv4_enable() const
Definition: options.h:40
static void SetSelfIp(std::string ip)
Definition: control_node.h:34
std::map< std::string, std::map< std::string, std::string > > DerivedStats
Definition: p/sandesh.h:148
static void SetProgramName(const char *name)
Definition: control_node.h:32
std::string xmpp_server_cert() const
Definition: options.h:74
void Shutdown()
Definition: xmpp_server.cc:339
void Initialize(DB *db, DBGraph *db_graph, const std::string &localname)
bool log_disable() const
Definition: options.h:31
bool collectors_configured() const
Definition: options.h:78
std::string path_to_ca_cert
Definition: xmpp_config.h:30
static XmppServer * CreateXmppServer(EventManager *evm, Options *options, XmppChannelConfig *xmpp_cfg)
Definition: db.h:24
std::string host_ip() const
Definition: options.h:28
static string FileRead(const char *filename)
std::string FromAddr
Definition: xmpp_config.h:21
void SetTrackRunTime(bool value)
Definition: task.h:296
std::string log_property_file() const
Definition: options.h:33
void SigTermSignalHandler(const boost::system::error_code &error, int sig, bool force_reinit)
bool admin_down() const
Definition: bgp_server.h:202
void set_config_client_manager(ConfigClientManager *mgr)
Definition: options.h:92
uint8_t type
Definition: load_balance.h:109
std::vector< std::string > randomized_collector_server_list() const
Definition: options.h:23
DB * database()
Definition: ifmap_server.h:82
static TaskScheduler * GetInstance()
Definition: task.cc:547
static Options options
static void LinkImpl()
Definition: factory.h:68
bool xmpp_auth_enabled() const
Definition: options.h:73
static std::string GetProcessState(bool bgpHasSelfConfiguration, bool bgpIsAdminDown, bool configEndOfRibComputed, process::ProcessState::type *state, std::string *message)
void GetProcessStateCb(const vector< ConnectionInfo > &cinfos, ProcessState::type &state, string &message, const vector< ConnectionTypeName > &expected_connections)
bool log_local() const
Definition: options.h:37
static void ControlNodeGetProcessStateCb(const BgpServer *bgp_server, const ConfigClientManager *config_client_manager, const std::vector< ConnectionInfo > &cinfos, ProcessState::type &state, std::string &message, std::vector< ConnectionTypeName > expected_connections)
void LoggingInit()
Definition: logging.cc:51
std::string path_to_server_cert
Definition: xmpp_config.h:28
bool IsEmpty(bool running_only=false)
Returns true if there are no tasks running and/or enqueued If running_only is true, enqueued tasks are ignored i.e. return true if there are no running tasks. Ignore TaskGroup or TaskEntry if it is disabled.
Definition: task.cc:823
static void DeleteServer(TcpServer *server)
Definition: tcp_server.cc:656
const SandeshConfig & sandesh_config() const
Definition: options.h:88
void set_test_mode(bool test_mode)
Definition: bgp_sandesh.h:62
std::string bgp_config_file() const
Definition: options.h:18
static void Shutdown()
std::pair< std::string, std::string > ConnectionTypeName
std::string syslog_facility() const
Definition: options.h:39
static void set_module_context(const std::string &module_name, SandeshContext *context)
Definition: sandesh.cc:957
void set_gr_helper_disable(bool gr_helper_disable)
Definition: bgp_server.h:296
std::string log_file() const
Definition: options.h:32
bool HasSelfConfiguration() const
Definition: bgp_server.cc:568
std::string xmpp_server_key() const
Definition: options.h:75
std::string log_category() const
Definition: options.h:30
IpAddress AddressFromString(const std::string &ip_address_str, boost::system::error_code *ec)
static bool InitGenerator(const std::string &module, const std::string &source, const std::string &node_type, const std::string &instance_id, EventManager *evm, unsigned short http_port, const std::vector< std::string > &collectors, SandeshContext *client_context=NULL, DerivedStats ds=DerivedStats(), const SandeshConfig &config=SandeshConfig())
Definition: sandesh.cc:271
std::string hostname() const
Definition: options.h:27
XmppServer * xmpp_server
Definition: xmpp_sandesh.h:16
static void SetTestMode(const bool flag)
Definition: control_node.h:35
static void Initialize()
Definition: bgp_server.cc:548
static void SetDefaultSchedulingPolicy()
Definition: control_node.cc:19
#define LOG(_Level, _Msg)
Definition: logging.h:33
bool gr_helper_bgp_disable() const
Definition: options.h:81
void SetLoggingDisabled(bool flag)
Definition: logging.cc:28
void RegisterSandeshShowXmppExtensions(BgpSandeshContext *bsc)
static void Uninit()
Definition: sandesh.cc:341
int tcp_hold_time() const
Definition: options.h:79
static void StartControlNodeInfoLogger(EventManager &evm, uint64_t period_msecs, const BgpServer *server, const BgpXmppChannelManager *xmpp_channel_mgr, const IFMapServer *ifmap_server, const string &build_info)
size_t ConnectionCount() const
Definition: xmpp_server.cc:405
bool use_syslog() const
Definition: options.h:38
bool gr_helper_xmpp_disable() const
Definition: options.h:82
uint16_t xmpp_port() const
Definition: options.h:72
bool Parse(EventManager &evm, int argc, char **argv)
void ReConfigSignalHandler(const boost::system::error_code &error, int sig, bool force_reinit)
uint16_t bgp_port() const
Definition: options.h:19
std::string xmpp_ca_cert() const
Definition: options.h:76
static void IFMap_Initialize(IFMapServer *server, ConfigJsonParser *json_parser)
static void Uninit(void)
static const char * kControlNodeJID
Definition: xmpp_init.h:17
std::string path_to_server_priv_key
Definition: xmpp_config.h:29
bool task_track_run_time() const
Definition: options.h:41
static EventManager evm
static void ShutdownServers(boost::scoped_ptr< BgpXmppChannelManager > *channel_manager)