OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
controller/src/dns/main.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <csignal>
6 #include <fstream>
7 
8 #include <pthread.h>
9 #include <boost/program_options.hpp>
10 #include "nodeinfo_types.h"
11 #include "base/connection_info.h"
12 #include <base/logging.h>
13 #include <base/misc_utils.h>
14 #include <base/contrail_ports.h>
15 #include <base/task.h>
16 #include <io/process_signal.h>
17 #include <config_client_manager.h>
18 #include <db/db_graph.h>
20 #include <ifmap/ifmap_link_table.h>
22 #include <ifmap/ifmap_server.h>
23 #include <ifmap/ifmap_xmpp.h>
24 #include <io/event_manager.h>
25 #include <vnc_cfg_types.h>
26 #include <cmn/dns.h>
27 #include <bind/bind_util.h>
28 #include <mgr/dns_mgr.h>
29 #include <mgr/dns_oper.h>
30 #include <bind/named_config.h>
31 #include <cfg/dns_config.h>
32 #include <cfg/dns_config_parser.h>
33 #include <agent/agent_xmpp_init.h>
34 #include "cmn/dns_options.h"
35 #include <sandesh/common/vns_types.h>
36 #include <sandesh/common/vns_constants.h>
37 #include <uve/uve.h>
38 #include "xmpp/xmpp_sandesh.h"
40 
41 namespace opt = boost::program_options;
42 using namespace boost::asio::ip;
43 using namespace std;
44 using process::ConnectionInfo;
47 using process::ProcessState;
48 using process::ConnectionType;
50 using process::g_process_info_constants;
51 using process::Signal;
52 
53 uint64_t start_time;
57 
58 static void WaitForIdle(long wait_seconds = 1200, bool running_only = false);
59 static void WaitForIdle(long wait_seconds, bool running_only) {
60  static const long kTimeoutUsecs = 1000;
61  static long envWaitTime;
62 
63  if (!envWaitTime) {
64  if (getenv("WAIT_FOR_IDLE")) {
65  envWaitTime = atoi(getenv("WAIT_FOR_IDLE"));
66  } else {
67  envWaitTime = wait_seconds;
68  }
69  }
70 
71  if (envWaitTime > wait_seconds) wait_seconds = envWaitTime;
72 
74  for (long i = 0; i < ((wait_seconds * 1000000)/kTimeoutUsecs); i++) {
75  if (scheduler->IsEmpty(running_only)) {
76  return;
77  }
78  usleep(kTimeoutUsecs);
79  }
80 }
81 
82 static void PrintBulkSyncStats(DB *database) {
83  DNS_OPERATIONAL_LOG(
84  g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
85  SandeshLevel::SYS_NOTICE, "EndOfRib point was reached, "
86  "IF-MAP objects have been created");
87  uint32_t ntypes = DnsConfigManager::config_types_size / sizeof(const char *);
88  for (uint32_t i=0; i<ntypes; i++) {
89  const char *type_name = DnsConfigManager::config_types[i];
90  IFMapTable *table = IFMapTable::FindTable(database, type_name);
91  std::stringstream msg_str;
92  msg_str << "The IF-MAP database table has been updated: "
93  << table->name()
94  << ", counting " << table->Size() << " elements";
95 
96  DNS_OPERATIONAL_LOG(
97  g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
98  SandeshLevel::SYS_NOTICE, msg_str.str().c_str());
99  }
100 
101  {
102  std::stringstream msg_str;
103  msg_str << "VnniConfig has been updated after"
104  << " the bulk sync, the number of elements: "
105  << VnniConfig::vnni_config_.size();
106  DNS_OPERATIONAL_LOG(
107  g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
108  SandeshLevel::SYS_NOTICE,
109  msg_str.str().c_str());
110  }
111 
112  {
113  std::stringstream msg_str;
114  msg_str << "IpamConfig has been updated after"
115  << " the bulk sync, the number of elements: "
116  << IpamConfig::ipam_config_.size();
117  DNS_OPERATIONAL_LOG(
118  g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
119  SandeshLevel::SYS_NOTICE,
120  msg_str.str().c_str());
121  }
122 
123  {
124  std::stringstream msg_str;
125  msg_str << "VirtualDnsConfig has been updated after"
126  << " the bulk sync, the number of elements: "
128  DNS_OPERATIONAL_LOG(
129  g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
130  SandeshLevel::SYS_NOTICE,
131  msg_str.str().c_str());
132  }
133 
134  {
135  std::stringstream msg_str;
136  msg_str << "VirtualDnsRecordConfig has been updated after"
137  << " the bulk sync, the number of elements: "
139  DNS_OPERATIONAL_LOG(
140  g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
141  SandeshLevel::SYS_NOTICE,
142  msg_str.str().c_str());
143  }
144 
145  {
146  std::stringstream msg_str;
147  msg_str << "GlobalQosConfig has been updated after"
148  << " the bulk sync";
149  DNS_OPERATIONAL_LOG(
150  g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
151  SandeshLevel::SYS_NOTICE,
152  msg_str.str().c_str());
153  }
154 }
155 
158  return false;
159 }
160 
163 
165  dns_info_log_timer->Start(60*1000, boost::bind(&DnsInfoLogTimer),NULL);
166  return true;
167 }
168 
170  const ConfigClientManager *config_client_manager,
171  const std::vector<ConnectionInfo> &cinfos,
172  ProcessState::type &state, std::string &message,
173  std::vector<ConnectionTypeName> expected_connections) {
174  GetProcessStateCb(cinfos, state, message, expected_connections);
175  if (state == ProcessState::NON_FUNCTIONAL)
176  return;
177  if (!config_client_manager->GetEndOfRibComputed()) {
178  state = ProcessState::NON_FUNCTIONAL;
179  message = "IFMap Server End-Of-RIB not computed";
180  }
181 }
182 
183 static string FileRead(const string &filename) {
184  ifstream file(filename.c_str());
185  string content((istreambuf_iterator<char>(file)),
186  istreambuf_iterator<char>());
187  return content;
188 }
189 
190 static void IFMap_Initialize(IFMapServer *server, ConfigJsonParser *json_parser) {
191  IFMapLinkTable_Init(server->database(), server->graph());
192  vnc_cfg_JsonParserInit(json_parser);
193  vnc_cfg_Server_ModuleInit(server->database(), server->graph());
194  server->Initialize();
195 }
196 
197 static bool OptionsParse(Options &options, int argc, char *argv[]) {
198  try {
199  options.Parse(*Dns::GetEventManager(), argc, argv);
200  return true;
201  } catch (boost::program_options::error &e) {
202  cout << "Error " << e.what() << endl;
203  } catch (...) {
204  cout << "Options Parser: Caught fatal unknown exception" << endl;
205  }
206 
207  return false;
208 }
209 
210 void ReConfigSignalHandler(const boost::system::error_code &error, int sig) {
211  if (error) {
212  LOG(ERROR, "SIGHUP handler ERROR: " << error);
213  return;
214  }
216 }
217 
218 int main(int argc, char *argv[]) {
219  // Initialize the task scheduler
220  int num_threads_to_tbb = TaskScheduler::GetDefaultThreadCount() +
222  TaskScheduler::Initialize(num_threads_to_tbb);
223 
224  // Create DB table and event manager
225  Dns::Init();
226 
227  // Process options from command-line and configuration file.
228  if (!OptionsParse(options, argc, argv)) {
229  exit(-1);
230  }
231 
232  srand(unsigned(time(NULL)));
233  std::vector<Signal::SignalHandler> sighup_handlers = boost::assign::list_of
234  (boost::bind(&ReConfigSignalHandler, _1, _2));
235  Signal::SignalCallbackMap smap = boost::assign::map_list_of
236  (SIGHUP, sighup_handlers);
237  Signal signal(Dns::GetEventManager(), smap);
238 
239  Dns::SetProgramName(argv[0]);
240  Module::type module = Module::DNS;
241  string module_name = g_vns_constants.ModuleNames.find(module)->second;
242 
243  std::string log_property_file = options.log_property_file();
244  if (log_property_file.size()) {
245  LoggingInit(log_property_file);
246  }
247  else {
250  options.syslog_facility(), module_name,
253  }
254 
255  string build_info_str;
256  Dns::GetVersion(build_info_str);
257  MiscUtils::LogVersionInfo(build_info_str, Category::DNSAGENT);
258 
261  }
264 
265  string hostname = options.hostname();
266  Dns::SetHostName(hostname);
267 
268  ConnectionStateManager::GetInstance();
269  NodeType::type node_type =
270  g_vns_constants.Module2NodeType.find(module)->second;
271  bool success;
273  success = Sandesh::InitGenerator(
274  module_name,
275  options.hostname(),
276  g_vns_constants.NodeTypeNames.find(node_type)->second,
277  g_vns_constants.INSTANCE_ID_DEFAULT,
281  NULL,
284  } else {
285  success = Sandesh::InitGenerator(
286  g_vns_constants.ModuleNames.find(module)->second,
287  options.hostname(),
288  g_vns_constants.NodeTypeNames.find(node_type)->second,
289  g_vns_constants.INSTANCE_ID_DEFAULT,
292  NULL,
295  }
296  if (!success) {
297  LOG(ERROR, "SANDESH: Initialization FAILED ... exiting");
298  Sandesh::Uninit();
299  exit(1);
300  }
302  options.log_level());
303 
304  // XXX Disable logging -- for test purposes only
305  if (options.log_disable()) {
306  SetLoggingDisabled(true);
307  }
308 
309  // DNS::SetTestMode(options.test_mode());
310 
311  DB config_db(TaskScheduler::GetInstance()->GetTaskId("db::IFMapTable"));
312  DBGraph config_graph;
313  IFMapServer ifmap_server(&config_db, &config_graph,
314  Dns::GetEventManager()->io_service());
315 
317  ConfigJsonParser>();
318  boost::scoped_ptr<ConfigClientManager> config_client_manager_ptr(
320  ConfigStaticObjectFactory::Create<ConfigJsonParserBase>(),
321  options.hostname(),
322  module_name,
324  ConfigClientManager *config_client_manager = config_client_manager_ptr.get();
325  ConfigJsonParser *json_parser = static_cast<ConfigJsonParser *>(
326  config_client_manager->config_json_parser());
327  json_parser->ifmap_server_set(&ifmap_server);
328  IFMap_Initialize(&ifmap_server, json_parser);
329 
330 
331  DnsManager dns_manager;
332  Dns::SetDnsManager(&dns_manager);
333  dns_manager.Initialize(&config_db, &config_graph,
342  DnsConfigParser parser(&config_db);
343  parser.Parse(FileRead(options.config_file()));
344 
349  options.xmpp_ca_cert())) {
350  LOG(ERROR, "Address already in use " << ContrailPorts::DnsXmpp());
351  exit(1);
352  }
353 
354  XmppSandeshContext xmpp_sandesh_context;
355  xmpp_sandesh_context.xmpp_server = Dns::GetXmppServer();
356  Sandesh::set_module_context("XMPP", &xmpp_sandesh_context);
357  IFMapSandeshContext ifmap_sandesh_context(&ifmap_server);
358  Sandesh::set_module_context("IFMap", &ifmap_sandesh_context);
359 
362  new TaskTrigger(boost::bind(&DnsInfoLogger),
363  TaskScheduler::GetInstance()->GetTaskId("dns::Config"), 0);
364 
367  "Dns Info log timer");
368  dns_info_log_timer->Start(60*1000, boost::bind(&DnsInfoLogTimer), NULL);
370  ifmap_server.set_config_manager(config_client_manager);
371 
372  //
373  // Determine if the number of connections is as expected.
374  // 1. Cassandra Server
375  // 2. AMQP Server
376  //
377  std::vector<ConnectionTypeName> expected_connections;
378  expected_connections = boost::assign::list_of
379  (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
380  ConnectionType::DATABASE)->second, "Cassandra"))
381  (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
382  ConnectionType::DATABASE)->second, "RabbitMQ"))
383  (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
384  ConnectionType::COLLECTOR)->second, ""))
385  .convert_to_container\
386  <vector<ConnectionTypeName> >();
387 
389  LOG(INFO, "DNS: Collectors are not configured!");
390  expected_connections.pop_back();
391  }
392 
393  ConnectionStateManager::GetInstance()->Init(
394  *(Dns::GetEventManager()->io_service()), options.hostname(),
395  module_name, g_vns_constants.INSTANCE_ID_DEFAULT,
396  boost::bind(&DnsServerGetProcessStateCb, config_client_manager, _1, _2, _3,
397  expected_connections), "ObjectDns");
398 
399  dns_manager.set_config_manager(config_client_manager);
400  options.set_config_client_manager(config_client_manager);
401  DNS_OPERATIONAL_LOG(
402  g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
403  SandeshLevel::SYS_NOTICE, "Bulk sync has been started");
404  config_client_manager->Initialize();
405  config_client_manager->config_amqp_client()->set_terminate(true);
406  WaitForIdle(); // 20 mins
407  PrintBulkSyncStats(&config_db);
408  config_client_manager->config_amqp_client()->set_terminate(false);
409  config_client_manager->config_amqp_client()->StartRabbitMQReader();
410  dns_manager.StartEndofConfigTimer();
412  signal.Terminate();
413  return 0;
414 }
ConfigJsonParserBase * config_json_parser()
log4cplus::LogLevel SandeshLevelTolog4Level(SandeshLevel::type slevel)
Definition: sandesh.cc:395
static DataMap virt_dns_rec_config_
Definition: dns_oper.h:201
static const char * config_types[]
Definition: dns_config.h:83
void set_config_manager(ConfigClientManager *config_manager)
Definition: dns_mgr.h:89
static void SetDnsPort(uint32_t port)
Definition: dns.h:62
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
static int GetDefaultThreadCount()
Definition: task.cc:429
static void Initialize(uint32_t thread_count=0, EventManager *evm=NULL)
Definition: task.cc:478
static SandeshLevel::type StringToLevel(std::string level)
Definition: sandesh.cc:861
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
static void DnsServerGetProcessStateCb(const ConfigClientManager *config_client_manager, const std::vector< ConnectionInfo > &cinfos, ProcessState::type &state, std::string &message, std::vector< ConnectionTypeName > expected_connections)
uint16_t http_server_port() const
Definition: options.h:29
const uint16_t named_max_retransmissions()
Definition: dns_options.h:35
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
long log_file_size() const
Definition: options.h:35
std::string config_file() const
Definition: options.h:26
void ifmap_server_set(IFMapServer *ifmap_server)
static void SetProgramName(const char *name)
Definition: dns.h:56
static void SetSelfIp(std::string ip)
Definition: dns.h:64
const std::string & rndc_secret() const
Definition: dns_options.h:31
static Options options
ConfigAmqpClient * config_amqp_client() const
void Initialize(DB *config_db, DBGraph *config_graph, const std::string &named_config_dir, const std::string &named_config_file, const std::string &named_log_file, const std::string &rndc_config_file, const std::string &rndc_secret, const std::string &named_max_cache_size, const uint16_t named_max_retransmissions, const uint16_t named_retransmission_interval)
Definition: dns_mgr.cc:66
static void LogVersionInfo(const std::string str, Category::type categ)
Definition: misc_utils.cc:38
bool DnsInfoLogger()
void StartEndofConfigTimer()
Definition: dns_mgr.cc:759
static void SetHostName(const std::string name)
Definition: dns.h:54
std::map< std::string, std::map< std::string, std::string > > DerivedStats
Definition: p/sandesh.h:148
static DataMap vnni_config_
Definition: dns_oper.h:79
uint16_t dns_server_port() const
Definition: dns_options.h:42
static string FileRead(const string &filename)
static void SetDnsManager(DnsManager *mgr)
Definition: dns.h:35
const std::string & named_config_file() const
Definition: dns_options.h:27
std::string xmpp_server_cert() const
Definition: options.h:74
static void SetHttpPort(uint32_t port)
Definition: dns.h:60
bool log_disable() const
Definition: options.h:31
bool collectors_configured() const
Definition: options.h:78
Definition: db.h:24
std::vector< std::string > collector_server_list() const
Definition: options.h:20
std::string host_ip() const
Definition: options.h:28
static DataMap virt_dns_config_
Definition: dns_oper.h:146
virtual size_t Size() const
Definition: db_table.cc:507
std::string log_property_file() const
Definition: options.h:33
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
TaskTrigger * dns_info_trigger
static void SetCollector(std::string name)
Definition: dns.h:58
Timer * dns_info_log_timer
static DataMap ipam_config_
Definition: dns_oper.h:108
static TaskScheduler * GetInstance()
Definition: task.cc:547
const std::string & named_config_dir() const
Definition: dns_options.h:28
const uint16_t named_retransmission_interval()
Definition: dns_options.h:36
uint64_t start_time
static void Init()
Definition: dns.h:67
static void LinkImpl()
Definition: factory.h:68
bool xmpp_auth_enabled() const
Definition: options.h:73
void GetProcessStateCb(const vector< ConnectionInfo > &cinfos, ProcessState::type &state, string &message, const vector< ConnectionTypeName > &expected_connections)
bool log_local() const
Definition: options.h:37
void LoggingInit()
Definition: logging.cc:51
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
const std::string & name() const
Definition: db_table.h:110
const SandeshConfig & sandesh_config() const
Definition: options.h:88
static Timer * CreateTimer(boost::asio::io_context &service, const std::string &name, int task_id=Timer::GetTimerTaskId(), int task_instance=Timer::GetTimerInstanceId(), bool delete_on_completion=false)
Definition: timer.cc:201
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
bool Cancel()
Definition: timer.cc:150
std::string log_file() const
Definition: options.h:32
static void SendDnsUve(uint64_t start_time)
Definition: uve.cc:14
std::string xmpp_server_key() const
Definition: options.h:75
std::string log_category() const
Definition: options.h:30
const std::string & named_max_cache_size() const
Definition: dns_options.h:32
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 PrintBulkSyncStats(DB *database)
static uint64_t UTCTimestampUsec()
Definition: time_util.h:13
static IFMapTable * FindTable(DB *db, const std::string &element_type)
Definition: ifmap_table.cc:39
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
Definition: timer.cc:108
static uint32_t config_types_size
Definition: dns_config.h:84
void set_terminate(bool terminate)
#define LOG(_Level, _Msg)
Definition: logging.h:33
void SetLoggingDisabled(bool flag)
Definition: logging.cc:28
static void Uninit()
Definition: sandesh.cc:341
static XmppServer * GetXmppServer()
Definition: dns.h:40
bool use_syslog() const
Definition: options.h:38
static EventManager * GetEventManager()
Definition: dns.h:31
Definition: timer.h:54
bool Parse(EventManager &evm, int argc, char **argv)
static bool GetVersion(std::string &build_info_str)
Definition: dns.cc:32
const std::string & rndc_config_file() const
Definition: dns_options.h:30
static bool OptionsParse(Options &options, int argc, char *argv[])
void ReConfigSignalHandler(const boost::system::error_code &error, int sig, bool force_reinit)
static void WaitForIdle(long wait_seconds=1200, bool running_only=false)
static const uint16_t DnsXmpp()
std::string xmpp_ca_cert() const
Definition: options.h:76
bool DnsInfoLogTimer()
static void IFMap_Initialize(IFMapServer *server, ConfigJsonParser *json_parser)
const std::string & named_log_file() const
Definition: dns_options.h:29
static bool Init(bool xmpp_auth_enabled, const std::string &xmpp_server_cert, const std::string &xmpp_server_key, const std::string &xmpp_ca_cert)