Kea  2.1.7-git
netconf.cc
Go to the documentation of this file.
1 // Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
9 
10 #include <config.h>
11 
12 #include <netconf/netconf.h>
14 #include <netconf/netconf_log.h>
15 #include <cc/command_interpreter.h>
16 #include <yang/translator_config.h>
17 #include <yang/yang_revisions.h>
18 
19 #include <boost/algorithm/string.hpp>
20 
21 #include <sstream>
22 
23 using namespace std;
24 using namespace isc::config;
25 using namespace isc::data;
26 using namespace isc::netconf;
27 using namespace isc::yang;
28 using namespace sysrepo;
29 
30 using libyang::S_Context;
31 using libyang::S_Module;
32 
33 namespace {
34 
36 class NetconfAgentCallback {
37 public:
41  NetconfAgentCallback(const CfgServersMapPair& service_pair)
42  : service_pair_(service_pair) {
43  }
44 
46  CfgServersMapPair const service_pair_;
47 
58  sr_error_t module_change(S_Session sess,
59  const char* module_name,
60  const char* /* xpath */,
61  sr_event_t event,
62  void* /* private_ctx */) {
63  ostringstream event_type;
64  switch (event) {
65  case SR_EV_UPDATE:
66  // This could potentially be a hook point for mid-flight
67  // configuration changes.
68  event_type << "SR_EV_UPDATE";
69  break;
70  case SR_EV_CHANGE:
71  event_type << "SR_EV_CHANGE";
72  break;
73  case SR_EV_DONE:
74  event_type << "SR_EV_DONE";
75  break;
76  case SR_EV_ABORT:
77  event_type << "SR_EV_ABORT";
78  break;
79  case SR_EV_ENABLED:
80  event_type << "SR_EV_ENABLED";
81  break;
82  case SR_EV_RPC:
83  event_type << "SR_EV_RPC";
84  break;
85  default:
86  event_type << "UNKNOWN (" << event << ")";
87  break;
88  }
90  .arg(event_type.str());
91  NetconfAgent::logChanges(sess, module_name);
92  switch (event) {
93  case SR_EV_CHANGE:
94  return (NetconfAgent::change(sess, service_pair_));
95  case SR_EV_DONE:
96  return (NetconfAgent::done(sess, service_pair_));
97  default:
98  return (SR_ERR_OK);
99  }
100  }
101 
102  void event_notif(sysrepo::S_Session /* session */,
103  sr_ev_notif_type_t const notification_type,
104  char const* /* path */,
105  sysrepo::S_Vals const vals,
106  time_t /* timestamp */,
107  void* /* private_data */) {
108  string n;
109  switch (notification_type) {
110  case SR_EV_NOTIF_REALTIME:
111  n = "SR_EV_NOTIF_REALTIME";
112  break;
113  case SR_EV_NOTIF_REPLAY:
114  n = "SR_EV_NOTIF_REPLAY";
115  break;
116  case SR_EV_NOTIF_REPLAY_COMPLETE:
117  n = "SR_EV_NOTIF_REPLAY_COMPLETE";
118  break;
119  case SR_EV_NOTIF_STOP:
120  n = "SR_EV_NOTIF_STOP";
121  break;
122  case SR_EV_NOTIF_SUSPENDED:
123  n = "SR_EV_NOTIF_SUSPENDED";
124  break;
125  case SR_EV_NOTIF_RESUMED:
126  n = "SR_EV_NOTIF_RESUMED";
127  break;
128  }
129 
130  stringstream s;
131  for (size_t i(0); i < vals->val_cnt(); ++i) {
132  if (i != 0) {
133  s << ", ";
134  }
135  s << vals->val(i)->to_string();
136  }
137 
139  .arg(n)
140  .arg(service_pair_.first)
141  .arg(s.str());
142  }
143 };
144 
145 } // end of anonymous namespace
146 
147 namespace isc {
148 namespace netconf {
149 
150 NetconfAgent::~NetconfAgent() {
151  clear();
152 }
153 
154 void
155 NetconfAgent::init(NetconfCfgMgrPtr cfg_mgr) {
156  // Check for a configuration manager.
157  if (!cfg_mgr) {
158  isc_throw(Unexpected, "missing configuration manager");
159  return;
160  }
161 
162  // Retrieve configuration from existing running DHCP daemons.
163  const CfgServersMapPtr& servers =
164  cfg_mgr->getNetconfConfig()->getCfgServersMap();
165  for (auto const& pair : *servers) {
166  keaConfig(pair);
167  }
168 
169  // Initialize sysrepo.
170  initSysrepo();
171 
172  // Check modules / revisions.
173  checkModules(servers);
174 
175  for (auto const& pair : *servers) {
176  yangConfig(pair);
177  subscribeConfig(pair);
178  subscribeToNotifications(pair);
179  }
180 }
181 
182 void
183 NetconfAgent::clear() {
184  for (auto subs : subscriptions_) {
185  subs.second.reset();
186  }
187  subscriptions_.clear();
188  running_sess_.reset();
189  startup_sess_.reset();
190  conn_.reset();
191 }
192 
193 void
194 NetconfAgent::keaConfig(const CfgServersMapPair& service_pair) {
195  // If the boot-update flag is not set.
196  if (!service_pair.second->getBootUpdate()) {
197  return;
198  }
199  CfgControlSocketPtr ctrl_sock = service_pair.second->getCfgControlSocket();
200  if (!ctrl_sock) {
201  return;
202  }
204  try {
205  comm = createControlSocket(ctrl_sock);
206  } catch (const std::exception& ex) {
207  ostringstream msg;
208  msg << "createControlSocket failed with " << ex.what();
210  .arg(service_pair.first)
211  .arg(msg.str());
212  return;
213  }
214  ConstElementPtr answer;
215  int rcode;
216  ConstElementPtr config;
218  .arg(service_pair.first);
219  try {
220  answer = comm->configGet(service_pair.first);
221  config = parseAnswer(rcode, answer);
222  } catch (const std::exception& ex) {
223  ostringstream msg;
224  msg << "config-get command failed with " << ex.what();
226  .arg(service_pair.first)
227  .arg(msg.str());
228  return;
229  }
230  if (rcode != CONTROL_RESULT_SUCCESS) {
231  ostringstream msg;
232  msg << "config-get command returned " << answerToText(answer);
234  .arg(service_pair.first)
235  .arg(msg.str());
236  return;
237  }
238  if (!config) {
240  .arg(service_pair.first)
241  .arg("config-get command returned an empty configuration");
242  return;
243  }
246  .arg(service_pair.first)
247  .arg(prettyPrint(config));
248 }
249 
250 void
251 NetconfAgent::initSysrepo() {
252  try {
253  conn_ = make_shared<Connection>();
254  } catch (const std::exception& ex) {
255  isc_throw(Unexpected, "Can't connect to sysrepo: " << ex.what());
256  }
257 
258  try {
259  startup_sess_.reset(new Session(conn_, SR_DS_STARTUP));
260  running_sess_.reset(new Session(conn_, SR_DS_RUNNING));
261  } catch (const std::exception& ex) {
262  isc_throw(Unexpected, "Can't establish a sysrepo session: "
263  << ex.what());
264  }
265 
266  // Retrieve names and revisions of installed modules from sysrepo.
267  getModules();
268 }
269 
270 void NetconfAgent::getModules() {
271  vector<S_Module> modules;
272  try {
273  S_Context context(running_sess_->get_context());
274  modules = context->get_module_iter();
275  } catch (const sysrepo_exception& ex) {
276  isc_throw(Unexpected, "can't retrieve available modules: " << ex.what());
277  }
278 
279  for (S_Module const& module : modules) {
280  if (!module->name()) {
281  isc_throw(Unexpected, "could not retrieve module name");
282  }
283  string const name(module->name());
284  if (!module->rev() || !module->rev()->date()) {
286  "could not retrieve module revision for module " << name);
287  }
288  string const revision(module->rev()->date());
289  modules_.emplace(name, revision);
290  }
291 }
292 
293 bool
294 NetconfAgent::checkModule(const string& module_name) const {
295  auto module = modules_.find(module_name);
296  if (module == modules_.end()) {
298  .arg(module_name);
299  return (false);
300  }
301  auto modrev = YANG_REVISIONS.find(module_name);
302  if (modrev == YANG_REVISIONS.end()) {
303  // Can't check revision?!
304  // It can happen only with a module which is not in
305  // YANG_REVISIONS but installed so likely on purpose.
306  return (true);
307  }
308  if (modrev->second != module->second) {
310  .arg(module_name)
311  .arg(modrev->second)
312  .arg(module->second);
313  return (false);
314  }
315  return (true);
316 }
317 
318 void
319 NetconfAgent::checkModules(CfgServersMapPtr const& servers /* = {} */) const {
320  bool faulty_model(false);
321  if (servers) {
322  for (auto pair : *servers) {
323  if (!checkModule(pair.second->getModel())) {
324  faulty_model = true;
325  }
326  }
327  }
328 
329  if (faulty_model) {
330  isc_throw(Unexpected, "YANG module is missing or its revision is not "
331  "supported. Check logs for details.");
332  }
333 
334  for (auto modrev : YANG_REVISIONS) {
335  auto module = modules_.find(modrev.first);
336  if (module == modules_.end()) {
338  .arg(modrev.first);
339  continue;
340  }
341  if (modrev.second != module->second) {
343  .arg(modrev.first)
344  .arg(modrev.second)
345  .arg(module->second);
346  }
347  }
348 }
349 
350 void
351 NetconfAgent::yangConfig(const CfgServersMapPair& service_pair) {
352  // If we're shutting down, or the boot-update flag is not set or the model
353  // associated with it is not specified.
354  if (!service_pair.second->getBootUpdate() ||
355  service_pair.second->getModel().empty()) {
356  return;
357  }
358 
359  // First we need a way to reach the actual servers.
360  CfgControlSocketPtr ctrl_sock = service_pair.second->getCfgControlSocket();
361  if (!ctrl_sock) {
362  return;
363  }
364 
366  .arg(service_pair.first);
367  ConstElementPtr config;
368  try {
369  // Retrieve configuration from Sysrepo.
370  TranslatorConfig tc(startup_sess_, service_pair.second->getModel());
371  config = tc.getConfig();
372  if (!config) {
373  ostringstream msg;
374  msg << "YANG configuration for "
375  << service_pair.second->getModel()
376  << " is empty";
378  .arg(service_pair.first)
379  .arg(msg.str());
380  return;
381  } else {
384  .arg(service_pair.first)
385  .arg(prettyPrint(config));
386  }
387  } catch (const std::exception& ex) {
388  ostringstream msg;
389  msg << "get YANG configuration for " << service_pair.first
390  << " failed with " << ex.what();
392  .arg(service_pair.first)
393  .arg(msg.str());
394  return;
395  }
397  try {
398  comm = createControlSocket(ctrl_sock);
399  } catch (const std::exception& ex) {
400  ostringstream msg;
401  msg << "control socket creation failed with " << ex.what();
403  .arg(service_pair.first)
404  .arg(msg.str());
405  return;
406  }
407  ConstElementPtr answer;
408  int rcode;
409  try {
410  answer = comm->configSet(config, service_pair.first);
411  parseAnswer(rcode, answer);
412  } catch (const std::exception& ex) {
413  ostringstream msg;
414  msg << "config-set command failed with " << ex.what();
416  .arg(service_pair.first)
417  .arg(msg.str());
418  return;
419  }
420  if (rcode != CONTROL_RESULT_SUCCESS) {
421  ostringstream msg;
422  msg << "config-set command returned " << answerToText(answer);
424  .arg(service_pair.first)
425  .arg(msg.str());
426  return;
427  }
429  .arg(service_pair.first);
430 }
431 
432 void
433 NetconfAgent::subscribeConfig(const CfgServersMapPair& service_pair) {
434  std::string const& model(service_pair.second->getModel());
435 
436  // If we're shutting down, or the subscribe-changes flag is not set or
437  // the model associated with it is not specified.
438  if (!service_pair.second->getSubscribeChanges() ||
439  model.empty()) {
440  return;
441  }
443  .arg(service_pair.first)
444  .arg(model);
445  S_Subscribe subs(new Subscribe(running_sess_));
446  auto callback = [=](sysrepo::S_Session sess, const char* module_name,
447  const char* xpath, sr_event_t event,
448  uint32_t /* request_id */) {
449  NetconfAgentCallback agent(service_pair);
450  return agent.module_change(sess, module_name, xpath, event, nullptr);
451  };
452  try {
453  sr_subscr_options_t options = SR_SUBSCR_DEFAULT;
454  if (!service_pair.second->getValidateChanges()) {
455  options |= SR_SUBSCR_DONE_ONLY;
456  }
457  // Note the API stores the module name so do not put it
458  // in a short lifetime variable!
459  subs->module_change_subscribe(model.c_str(), callback, nullptr, 0,
460  options);
461  } catch (const std::exception& ex) {
462  ostringstream msg;
463  msg << "module change subscribe failed with " << ex.what();
464  msg << "change subscription for model " << model <<
465  " failed with: " << ex.what();
467  .arg(service_pair.first)
468  .arg(service_pair.second->getModel())
469  .arg(msg.str());
470  return;
471  }
472  subscriptions_.insert(make_pair(service_pair.first, subs));
473 }
474 
475 
476 void
477 NetconfAgent::subscribeToNotifications(const CfgServersMapPair& service_pair) {
478  std::string const& model(service_pair.second->getModel());
479  // If we're shutting down, or the subscribe-changes flag is not set or
480  // the model associated with it is not specified.
481  if (!service_pair.second->getSubscribeNotifications() ||
482  model.empty()) {
483  return;
484  }
486  .arg(service_pair.first)
487  .arg(model);
488 
489  S_Subscribe subscription(std::make_shared<Subscribe>(running_sess_));
490  auto callback = [=](sysrepo::S_Session session,
491  sr_ev_notif_type_t const notification_type,
492  char const* path,
493  sysrepo::S_Vals const vals,
494  time_t timestamp) {
495  NetconfAgentCallback agent(service_pair);
496  return agent.event_notif(session, notification_type, path, vals, timestamp, nullptr);
497  };
498  try {
499  subscription->event_notif_subscribe(model.c_str(), callback);
500  } catch (const std::exception& ex) {
501  ostringstream msg;
502  msg << "event notification subscription for model " << model <<
503  " failed with: " << ex.what();
505  .arg(service_pair.first)
506  .arg(service_pair.second->getModel())
507  .arg(msg.str());
508  return;
509  }
510  subscriptions_.emplace(service_pair.first, subscription);
511 }
512 
513 sr_error_t
514 NetconfAgent::change(S_Session sess, const CfgServersMapPair& service_pair) {
515  // If we're shutting down, or the subscribe-changes or the
516  // validate-changes flag is not set or the model associated with
517  // it is not specified.
518  if (!service_pair.second->getSubscribeChanges() ||
519  !service_pair.second->getValidateChanges() ||
520  service_pair.second->getModel().empty()) {
521  return (SR_ERR_OK);
522  }
523  CfgControlSocketPtr ctrl_sock = service_pair.second->getCfgControlSocket();
524  if (!ctrl_sock) {
525  return (SR_ERR_OK);
526  }
528  .arg(service_pair.first);
529  ConstElementPtr config;
530  try {
531  TranslatorConfig tc(sess, service_pair.second->getModel());
532  config = tc.getConfig();
533  if (!config) {
534  ostringstream msg;
535  msg << "YANG configuration for "
536  << service_pair.second->getModel()
537  << " is empty";
539  .arg(service_pair.first)
540  .arg(msg.str());
541  return (SR_ERR_OPERATION_FAILED);
542  } else {
545  .arg(service_pair.first)
546  .arg(prettyPrint(config));
547  }
548  } catch (const std::exception& ex) {
549  ostringstream msg;
550  msg << "get YANG configuration for " << service_pair.first
551  << " failed with " << ex.what();
553  .arg(service_pair.first)
554  .arg(msg.str());
555  return (SR_ERR_VALIDATION_FAILED);;
556  }
558  try {
559  comm = createControlSocket(ctrl_sock);
560  } catch (const std::exception& ex) {
561  ostringstream msg;
562  msg << "createControlSocket failed with " << ex.what();
564  .arg(service_pair.first)
565  .arg(msg.str());
566  return (SR_ERR_OK);
567  }
568  ConstElementPtr answer;
569  int rcode;
570  try {
571  answer = comm->configTest(config, service_pair.first);
572  parseAnswer(rcode, answer);
573  } catch (const std::exception& ex) {
574  stringstream msg;
575  msg << "configTest failed with " << ex.what();
577  .arg(service_pair.first)
578  .arg(msg.str());
579  return (SR_ERR_VALIDATION_FAILED);
580  }
581  if (rcode != CONTROL_RESULT_SUCCESS) {
582  stringstream msg;
583  msg << "configTest returned " << answerToText(answer);
585  .arg(service_pair.first)
586  .arg(msg.str());
587  return (SR_ERR_VALIDATION_FAILED);
588  }
590  .arg(service_pair.first);
591  return (SR_ERR_OK);
592 }
593 
594 sr_error_t
595 NetconfAgent::done(S_Session sess, const CfgServersMapPair& service_pair) {
596  // Check if we should and can process this update.
597  if (!service_pair.second->getSubscribeChanges() ||
598  service_pair.second->getModel().empty()) {
599  return (SR_ERR_OK);
600  }
601  CfgControlSocketPtr ctrl_sock = service_pair.second->getCfgControlSocket();
602  if (!ctrl_sock) {
603  return (SR_ERR_OK);
604  }
605 
606  // All looks good, let's get started. Print an info that we're about
607  // to update the configuration.
609  .arg(service_pair.first);
610 
611  // Retrieve the configuration from SYSREPO first.
612  ConstElementPtr config;
613  try {
614  TranslatorConfig tc(sess, service_pair.second->getModel());
615  config = tc.getConfig();
616  if (!config) {
617  ostringstream msg;
618  msg << "YANG configuration for "
619  << service_pair.second->getModel()
620  << " is empty";
622  .arg(service_pair.first)
623  .arg(msg.str());
624  return (SR_ERR_VALIDATION_FAILED);
625  } else {
628  .arg(service_pair.first)
629  .arg(prettyPrint(config));
630  }
631  } catch (const std::exception& ex) {
632  ostringstream msg;
633  msg << "get YANG configuration for " << service_pair.first
634  << " failed with " << ex.what();
636  .arg(service_pair.first)
637  .arg(msg.str());
638  return (SR_ERR_VALIDATION_FAILED);
639  }
640 
641  // Ok, now open the control socket. We need this to send the config to
642  // the server.
644  try {
645  comm = createControlSocket(ctrl_sock);
646  } catch (const std::exception& ex) {
647  ostringstream msg;
648  msg << "createControlSocket failed with " << ex.what();
650  .arg(service_pair.first)
651  .arg(msg.str());
652  return (SR_ERR_OK);
653  }
654 
655  // Now apply the config using config-set command.
656  ConstElementPtr answer;
657  int rcode;
658  try {
659  answer = comm->configSet(config, service_pair.first);
660  parseAnswer(rcode, answer);
661  } catch (const std::exception& ex) {
662  stringstream msg;
663  msg << "configSet failed with " << ex.what();
665  .arg(service_pair.first)
666  .arg(msg.str());
667  return (SR_ERR_VALIDATION_FAILED);
668  }
669 
670  // rcode == CONTROL_RESULT_SUCCESS, unless the docs say otherwise :).
671  if (rcode != CONTROL_RESULT_SUCCESS) {
672  stringstream msg;
673  msg << "configSet returned " << answerToText(answer);
675  .arg(service_pair.first)
676  .arg(msg.str());
677  return (SR_ERR_VALIDATION_FAILED);
678  }
680  .arg(service_pair.first);
681  return (SR_ERR_OK);
682 }
683 
684 void
685 NetconfAgent::logChanges(S_Session sess, const string& model) {
686  ostringstream stream;
687  stream << "/" << model << ":*//.";
688  std::string const xpath(stream.str());
689  S_Iter_Change iter = sess->get_changes_iter(xpath.c_str());
690  if (!iter) {
692  .arg("no iterator");
693  return;
694  }
695  for (;;) {
696  S_Change change;
697  ostringstream msg;
698  try {
699  change = sess->get_change_next(iter);
700  } catch (const sysrepo_exception& ex) {
701  msg << "get change iterator next failed: " << ex.what();
703  .arg(msg.str());
704  return;
705  }
706  if (!change) {
707  // End of changes, not an error.
708  return;
709  }
710  S_Val new_val = change->new_val();
711  S_Val old_val = change->old_val();
712  string report;
713  switch (change->oper()) {
714  case SR_OP_CREATED:
715  if (!new_val) {
717  .arg("created but without a new value");
718  break;
719  }
720  msg << "created: " << new_val->to_string();
721  report = msg.str();
722  boost::erase_all(report, "\n");
725  .arg(report);
726  break;
727  case SR_OP_MODIFIED:
728  if (!old_val || !new_val) {
730  .arg("modified but without an old or new value");
731  break;
732  }
733  msg << "modified: " << old_val->to_string()
734  << " => " << new_val->to_string();
735  report = msg.str();
736  boost::erase_all(report, "\n");
739  .arg(report);
740  break;
741  case SR_OP_DELETED:
742  if (!old_val) {
744  .arg("deleted but without an old value");
745  break;
746  }
747  msg << "deleted: " << old_val->to_string();
748  report = msg.str();
749  boost::erase_all(report, "\n");
752  .arg(report);
753  break;
754  case SR_OP_MOVED:
755  if (!new_val) {
757  .arg("moved but without a new value");
758  break;
759  }
760  msg << "moved: " << new_val->xpath();
761  if (!old_val) {
762  msg << " first";
763  } else {
764  msg << " after " << old_val->xpath();
765  }
766  report = msg.str();
767  boost::erase_all(report, "\n");
770  .arg(report);
771  break;
772  default:
773  msg << "unknown operation (" << change->oper() << ")";
775  .arg(msg.str());
776  }
777  }
778 }
779 
780 void
781 NetconfAgent::announceShutdown() const {
782  isc::process::DControllerBasePtr& controller(NetconfController::instance());
783  if (controller) {
784  boost::dynamic_pointer_cast<NetconfController>(controller)
785  ->getNetconfProcess()
786  ->setShutdownFlag(true);
787  }
788 }
789 
790 bool NetconfAgent::shouldShutdown() const {
791  return boost::dynamic_pointer_cast<NetconfController>(NetconfController::instance())
792  ->getNetconfProcess()
793  ->shouldShutdown();
794 }
795 
796 } // namespace netconf
797 } // namespace isc
const isc::log::MessageID NETCONF_SUBSCRIBE_CONFIG
boost::shared_ptr< DControllerBase > DControllerBasePtr
Definition: d_controller.h:78
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
const isc::log::MessageID NETCONF_GET_CONFIG
const isc::log::MessageID NETCONF_SET_CONFIG_FAILED
const isc::log::MessageID NETCONF_GET_CONFIG_FAILED
DHCP configuration translation between YANG and JSON.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< ControlSocketBase > ControlSocketBasePtr
Type definition for the pointer to the ControlSocketBase.
const isc::log::MessageID NETCONF_BOOT_UPDATE_COMPLETED
const int NETCONF_DBG_TRACE_DETAIL_DATA
Additional information.
Definition: netconf_log.h:41
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
Definition: data.cc:1279
std::pair< std::string, CfgServerPtr > CfgServersMapPair
Defines a iterator pairing of name and CfgServer.
const isc::log::MessageID NETCONF_VALIDATE_CONFIG_COMPLETED
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
STL namespace.
const isc::log::MessageID NETCONF_UPDATE_CONFIG
const isc::log::MessageID NETCONF_SET_CONFIG_STARTED
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
const isc::log::MessageID NETCONF_LOG_CHANGE_FAIL
const isc::log::MessageID NETCONF_NOTIFICATION_RECEIVED
const isc::log::MessageID NETCONF_SET_CONFIG
const isc::log::MessageID NETCONF_VALIDATE_CONFIG_STARTED
isc::data::ElementPtr getConfig()
Get and translate the whole DHCP server configuration from YANG to JSON.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
std::string answerToText(const ConstElementPtr &msg)
const isc::log::MessageID NETCONF_VALIDATE_CONFIG
A generic exception that is thrown when an unexpected error condition occurs.
const isc::log::MessageID NETCONF_CONFIG_CHANGE_EVENT
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
const isc::log::MessageID NETCONF_MODULE_REVISION_ERR
isc::log::Logger netconf_logger(NETCONF_LOGGER_NAME)
Base logger for the netconf agent.
Definition: netconf_log.h:49
const isc::log::MessageID NETCONF_SUBSCRIBE_CONFIG_FAILED
ConstElementPtr parseAnswer(int &rcode, const ConstElementPtr &msg)
Process Controller for Netconf Process.
Defines the logger used by the top-level component of kea-lfc.
const isc::log::MessageID NETCONF_UPDATE_CONFIG_STARTED
const isc::log::MessageID NETCONF_MODULE_REVISION_WARN
boost::shared_ptr< NetconfCfgMgr > NetconfCfgMgrPtr
Defines a shared pointer to NetconfCfgMgr.
const isc::log::MessageID NETCONF_UPDATE_CONFIG_FAILED
const isc::log::MessageID NETCONF_MODULE_MISSING_ERR
This file contains several functions and constants that are used for handling commands and responses ...
ControlSocketBasePtr createControlSocket(CfgControlSocketPtr ctrl_sock)
Factory template for control sockets.
const isc::log::MessageID NETCONF_SUBSCRIBE_NOTIFICATIONS
const isc::log::MessageID NETCONF_GET_CONFIG_STARTED
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
Contains declarations for loggers used by the Kea netconf agent.
const isc::log::MessageID NETCONF_CONFIG_CHANGED_DETAIL
const isc::log::MessageID NETCONF_SUBSCRIBE_NOTIFICATIONS_FAILED
const isc::log::MessageID NETCONF_VALIDATE_CONFIG_FAILED
const isc::log::MessageID NETCONF_UPDATE_CONFIG_COMPLETED
const isc::log::MessageID NETCONF_MODULE_MISSING_WARN
const isc::log::MessageID NETCONF_VALIDATE_CONFIG_REJECTED
boost::shared_ptr< CfgControlSocket > CfgControlSocketPtr
Defines a pointer for CfgControlSocket instances.
boost::shared_ptr< CfgServersMap > CfgServersMapPtr
Defines a pointer to map of CfgServers.