Kea 1.5.0
netconf.cc
Go to the documentation of this file.
1// Copyright (C) 2018 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>
17#include <yang/yang_revisions.h>
18#include <boost/algorithm/string.hpp>
19#include <sstream>
20
21using namespace std;
22using namespace isc::config;
23using namespace isc::data;
24using namespace isc::netconf;
25using namespace isc::yang;
26#ifndef HAVE_PRE_0_7_6_SYSREPO
27using namespace sysrepo;
28#endif
29
30namespace {
31
33class NetconfAgentCallback : public Callback {
34public:
38 NetconfAgentCallback(const CfgServersMapPair& service_pair)
39 : service_pair_(service_pair) {
40 }
41
43 CfgServersMapPair service_pair_;
44
55 int module_change(S_Session sess,
56 const char* /*module_name*/,
57 sr_notif_event_t event,
58 void* /*private_ctx*/) {
60 return (SR_ERR_DISCONNECT);
61 }
62 ostringstream event_type;
63 switch (event) {
64 case SR_EV_VERIFY:
65 event_type << "VERIFY";
66 break;
67 case SR_EV_APPLY:
68 event_type << "APPLY";
69 break;
70 case SR_EV_ABORT:
71 event_type << "ABORT";
72 break;
73 case SR_EV_ENABLED:
74 event_type << "ENABLED";
75 break;
76 default:
77 event_type << "UNKNOWN (" << event << ")";
78 break;
79 }
80 LOG_INFO(netconf_logger, NETCONF_CONFIG_CHANGE_EVENT)
81 .arg(event_type.str());
82 string xpath = "/" + service_pair_.second->getModel() + ":";
83 NetconfAgent::logChanges(sess, xpath + "config");
85 return (SR_ERR_DISCONNECT);
86 }
87 switch (event) {
88 case SR_EV_VERIFY:
89 return (NetconfAgent::validate(sess, service_pair_));
90 case SR_EV_APPLY:
91 return (NetconfAgent::update(sess, service_pair_));
92 default:
93 return (SR_ERR_OK);
94 }
95 }
96};
97
99class NetconfAgentInstallCallback : public Callback {
100public:
109 void module_install(const char* module_name,
110 const char* revision,
111 sr_module_state_t /*state*/,
112 void* /*private_ctx*/) {
113 if (!module_name) {
114 // Not for us...
115 return;
116 }
117 LOG_WARN(netconf_logger, NETCONF_MODULE_INSTALL)
118 .arg(module_name)
119 .arg(revision ? revision : "unknown");
120 }
121};
122
123} // end of anonymous namespace
124
125namespace isc {
126namespace netconf {
127
129}
130
132 clear();
133}
134
135void
137 // If there is no configuration manager and/or we're shutting down.
138 if (!cfg_mgr || NetconfProcess::shut_down) {
139 return;
140 }
141 const CfgServersMapPtr& servers =
142 cfg_mgr->getNetconfConfig()->getCfgServersMap();
143 for (auto pair : *servers) {
145 return;
146 }
147
148 // Retrieve configuration from existing running DHCP daemons.
149 keaConfig(pair);
151 return;
152 }
153 }
155 return;
156 }
157
158 // Initialize sysrepo interface.
159 initSysrepo();
161 return;
162 }
163
164 // Check essential modules / revisions.
165 bool can_start = true;
166 for (auto pair : *servers) {
167 can_start = can_start && checkModule(pair.second->getModel());
169 return;
170 }
171 }
172 if (!can_start) {
173 cerr << "An essential YANG module / revision is missing."
174 << endl
175 << "The environment is not suitable for running kea-netconf."
176 << endl;
177 exit(EXIT_FAILURE);
178 }
180 return;
181 }
182
183 // Check modules / revisions.
184 checkModules();
186 return;
187 }
188
189 for (auto pair : *servers) {
191 return;
192 }
193 yangConfig(pair);
195 return;
196 }
197 subscribeConfig(pair);
199 return;
200 }
201 }
202}
203
204void
206 // Should be already set to true but in case...
208 for (auto subs : subscriptions_) {
209 subs.second.reset();
210 }
211 subscriptions_.clear();
212 running_sess_.reset();
213 startup_sess_.reset();
214 conn_.reset();
215}
216
217void
219 // If the boot-update flag is not set.
220 if (!service_pair.second->getBootUpdate()) {
221 return;
222 }
223 CfgControlSocketPtr ctrl_sock = service_pair.second->getCfgControlSocket();
224 if (!ctrl_sock) {
225 return;
226 }
228 try {
229 comm = createControlSocket(ctrl_sock);
230 } catch (const std::exception& ex) {
231 ostringstream msg;
232 msg << "createControlSocket failed with " << ex.what();
233 LOG_ERROR(netconf_logger, NETCONF_GET_CONFIG_FAILED)
234 .arg(service_pair.first)
235 .arg(msg.str());
236 return;
237 }
238 ConstElementPtr answer;
239 int rcode;
240 ConstElementPtr config;
241 LOG_INFO(netconf_logger, NETCONF_GET_CONFIG_STARTED)
242 .arg(service_pair.first);
243 try {
244 answer = comm->configGet(service_pair.first);
245 config = parseAnswer(rcode, answer);
246 } catch (const std::exception& ex) {
247 ostringstream msg;
248 msg << "config-get command failed with " << ex.what();
249 LOG_ERROR(netconf_logger, NETCONF_GET_CONFIG_FAILED)
250 .arg(service_pair.first)
251 .arg(msg.str());
252 return;
253 }
255 return;
256 }
257 if (rcode != CONTROL_RESULT_SUCCESS) {
258 ostringstream msg;
259 msg << "config-get command returned " << answerToText(answer);
260 LOG_ERROR(netconf_logger, NETCONF_GET_CONFIG_FAILED)
261 .arg(service_pair.first)
262 .arg(msg.str());
263 return;
264 }
265 if (!config) {
266 LOG_ERROR(netconf_logger, NETCONF_GET_CONFIG_FAILED)
267 .arg(service_pair.first)
268 .arg("config-get command returned an empty configuration");
269 return;
270 }
272 NETCONF_GET_CONFIG)
273 .arg(service_pair.first)
274 .arg(prettyPrint(config));
275}
276
277void
279 try {
280 conn_.reset(new Connection(NetconfController::netconf_app_name_,
281 SR_CONN_DAEMON_REQUIRED));
282 } catch (const std::exception& ex) {
283 isc_throw(Unexpected, "Can't connect to sysrepo: " << ex.what());
284 }
286 return;
287 }
288
289 try {
290 startup_sess_.reset(new Session(conn_, SR_DS_STARTUP));
292 return;
293 }
294 running_sess_.reset(new Session(conn_, SR_DS_RUNNING));
295 } catch (const std::exception& ex) {
296 isc_throw(Unexpected, "Can't establish a sysrepo session: "
297 << ex.what());
298 }
300 return;
301 }
302
303 try {
304 S_Yang_Schemas schemas = startup_sess_->list_schemas();
305 for (size_t i = 0; i < schemas->schema_cnt(); ++i) {
307 return;
308 }
309 if (!schemas->schema(i) ||
310 !schemas->schema(i)->module_name()) {
311 // Should not happen: skip it.
312 continue;
313 }
314 string module = schemas->schema(i)->module_name();
315 if (!schemas->schema(i)->revision() ||
316 !schemas->schema(i)->revision()->revision()) {
317 // Our modules have revisions: skip it.
318 continue;
319 }
320 string revision = schemas->schema(i)->revision()->revision();
321 modules_.insert(make_pair(module, revision));
322 }
323 } catch (const sysrepo_exception& ex) {
324 isc_throw(Unexpected, "Can't list schemas: " << ex.what());
325 }
327 return;
328 }
329
330 // Subscribe to the module (un)installation callback.
331 // When a module is (un)installed the callback is called.
332 // Note this requires a system test (vs. unit test).
333 try {
334 S_Subscribe subs(new Subscribe(startup_sess_));
335 S_Callback cb(new NetconfAgentInstallCallback());
336 subs->module_install_subscribe(cb);
337 subscriptions_.insert(make_pair("__install__", subs));
338 } catch (const sysrepo_exception& ex) {
339 isc_throw(Unexpected, "Can't subscribe module install: "
340 << ex.what());
341 }
342}
343
344bool
345NetconfAgent::checkModule(const string& module_name) const {
346 if (module_name.empty()) {
347 return (true);
348 }
349 auto module = modules_.find(module_name);
350 if (module == modules_.end()) {
351 LOG_ERROR(netconf_logger, NETCONF_MODULE_MISSING_ERR)
352 .arg(module_name);
353 return (false);
354 }
355 auto modrev = YANG_REVISIONS.find(module_name);
356 if (modrev == YANG_REVISIONS.end()) {
357 // Can't check revision?!
358 // It can happen only with a module which is not in
359 // YANG_REVISIONS but installed so likely on purpose.
360 return (true);
361 }
362 if (modrev->second != module->second) {
363 LOG_ERROR(netconf_logger, NETCONF_MODULE_REVISION_ERR)
364 .arg(module_name)
365 .arg(modrev->second)
366 .arg(module->second);
367 return (false);
368 }
369 return (true);
370}
371
372void
374 for (auto modrev : YANG_REVISIONS) {
376 return;
377 }
378 auto module = modules_.find(modrev.first);
379 if (module == modules_.end()) {
380 LOG_WARN(netconf_logger, NETCONF_MODULE_MISSING_WARN)
381 .arg(modrev.first);
382 continue;
383 }
384 if (modrev.second != module->second) {
385 LOG_WARN(netconf_logger, NETCONF_MODULE_REVISION_WARN)
386 .arg(modrev.first)
387 .arg(modrev.second)
388 .arg(module->second);
389 }
390 }
391}
392
393void
395 // If we're shutting down, or the boot-update flag is not set or the model
396 // associated with it is not specified.
398 !service_pair.second->getBootUpdate() ||
399 service_pair.second->getModel().empty()) {
400 return;
401 }
402
403 // First we need a way to reach the actual servers.
404 CfgControlSocketPtr ctrl_sock = service_pair.second->getCfgControlSocket();
405 if (!ctrl_sock) {
406 return;
407 }
408
409 LOG_INFO(netconf_logger, NETCONF_SET_CONFIG_STARTED)
410 .arg(service_pair.first);
411 ConstElementPtr config;
412 try {
413 // Retrieve configuration from Sysrepo.
414 TranslatorConfig tc(startup_sess_, service_pair.second->getModel());
415 config = tc.getConfig();
416 if (!config) {
417 ostringstream msg;
418 msg << "YANG configuration for "
419 << service_pair.second->getModel()
420 << " is empty";
421 LOG_ERROR(netconf_logger, NETCONF_SET_CONFIG_FAILED)
422 .arg(service_pair.first)
423 .arg(msg.str());
424 return;
425 } else {
427 NETCONF_SET_CONFIG)
428 .arg(service_pair.first)
429 .arg(prettyPrint(config));
430 }
431 } catch (const std::exception& ex) {
432 ostringstream msg;
433 msg << "get YANG configuration for " << service_pair.first
434 << " failed with " << ex.what();
435 LOG_ERROR(netconf_logger, NETCONF_SET_CONFIG_FAILED)
436 .arg(service_pair.first)
437 .arg(msg.str());
438 return;
439 }
441 return;
442 }
444 try {
445 comm = createControlSocket(ctrl_sock);
446 } catch (const std::exception& ex) {
447 ostringstream msg;
448 msg << "control socket creation failed with " << ex.what();
449 LOG_ERROR(netconf_logger, NETCONF_SET_CONFIG_FAILED)
450 .arg(service_pair.first)
451 .arg(msg.str());
452 return;
453 }
455 return;
456 }
457 ConstElementPtr answer;
458 int rcode;
459 try {
460 answer = comm->configSet(config, service_pair.first);
461 parseAnswer(rcode, answer);
462 } catch (const std::exception& ex) {
463 ostringstream msg;
464 msg << "config-set command failed with " << ex.what();
465 LOG_ERROR(netconf_logger, NETCONF_SET_CONFIG_FAILED)
466 .arg(service_pair.first)
467 .arg(msg.str());
468 return;
469 }
470 if (rcode != CONTROL_RESULT_SUCCESS) {
471 ostringstream msg;
472 msg << "config-set command returned " << answerToText(answer);
473 LOG_ERROR(netconf_logger, NETCONF_SET_CONFIG_FAILED)
474 .arg(service_pair.first)
475 .arg(msg.str());
476 return;
477 }
478 LOG_INFO(netconf_logger, NETCONF_BOOT_UPDATE_COMPLETED)
479 .arg(service_pair.first);
480}
481
482void
484 // If we're shutting down, or the subscribe-changes flag is not set or
485 // the model associated with it is not specified.
487 !service_pair.second->getSubscribeChanges() ||
488 service_pair.second->getModel().empty()) {
489 return;
490 }
491 LOG_INFO(netconf_logger, NETCONF_SUBSCRIBE_CONFIG)
492 .arg(service_pair.first)
493 .arg(service_pair.second->getModel());
494 S_Subscribe subs(new Subscribe(running_sess_));
495 S_Callback cb(new NetconfAgentCallback(service_pair));
496 try {
497 sr_subscr_options_t options = SR_SUBSCR_DEFAULT;
498 if (!service_pair.second->getValidateChanges()) {
499 options |= SR_SUBSCR_APPLY_ONLY;
500 }
501 // Note the API stores the module name so do not put it
502 // in a short lifetime variable!
503 subs->module_change_subscribe(service_pair.second->getModel().c_str(),
504 cb, 0, 0, options);
505 } catch (const std::exception& ex) {
506 ostringstream msg;
507 msg << "module change subscribe failed with " << ex.what();
508 LOG_ERROR(netconf_logger, NETCONF_SUBSCRIBE_CONFIG_FAILED)
509 .arg(service_pair.first)
510 .arg(service_pair.second->getModel())
511 .arg(msg.str());
512 subs.reset();
513 return;
514 }
515 subscriptions_.insert(make_pair(service_pair.first, subs));
516}
517
518int
519NetconfAgent::validate(S_Session sess, const CfgServersMapPair& service_pair) {
520 // If we're shutting down, or the subscribe-changes or the
521 // validate-changes flag is not set or the model associated with
522 // it is not specified.
524 !service_pair.second->getSubscribeChanges() ||
525 !service_pair.second->getValidateChanges() ||
526 service_pair.second->getModel().empty()) {
527 return (SR_ERR_OK);
528 }
529 CfgControlSocketPtr ctrl_sock = service_pair.second->getCfgControlSocket();
530 if (!ctrl_sock) {
531 return (SR_ERR_OK);
532 }
533 LOG_INFO(netconf_logger, NETCONF_VALIDATE_CONFIG_STARTED)
534 .arg(service_pair.first);
535 ConstElementPtr config;
536 try {
537 TranslatorConfig tc(sess, service_pair.second->getModel());
538 config = tc.getConfig();
539 if (!config) {
540 ostringstream msg;
541 msg << "YANG configuration for "
542 << service_pair.second->getModel()
543 << " is empty";
544 LOG_ERROR(netconf_logger, NETCONF_VALIDATE_CONFIG_FAILED)
545 .arg(service_pair.first)
546 .arg(msg.str());
547 return (SR_ERR_DISCONNECT);
548 } else {
550 NETCONF_VALIDATE_CONFIG)
551 .arg(service_pair.first)
552 .arg(prettyPrint(config));
553 }
554 } catch (const std::exception& ex) {
555 ostringstream msg;
556 msg << "get YANG configuration for " << service_pair.first
557 << " failed with " << ex.what();
558 LOG_ERROR(netconf_logger, NETCONF_VALIDATE_CONFIG_FAILED)
559 .arg(service_pair.first)
560 .arg(msg.str());
561 return (SR_ERR_VALIDATION_FAILED);;
562 }
564 return (SR_ERR_DISCONNECT);
565 }
567 try {
568 comm = createControlSocket(ctrl_sock);
569 } catch (const std::exception& ex) {
570 ostringstream msg;
571 msg << "createControlSocket failed with " << ex.what();
572 LOG_ERROR(netconf_logger, NETCONF_VALIDATE_CONFIG_FAILED)
573 .arg(service_pair.first)
574 .arg(msg.str());
575 return (SR_ERR_OK);
576 }
577 ConstElementPtr answer;
578 int rcode;
579 try {
580 answer = comm->configTest(config, service_pair.first);
581 parseAnswer(rcode, answer);
582 } catch (const std::exception& ex) {
583 stringstream msg;
584 msg << "configTest failed with " << ex.what();
585 LOG_ERROR(netconf_logger, NETCONF_VALIDATE_CONFIG_FAILED)
586 .arg(service_pair.first)
587 .arg(msg.str());
588 return (SR_ERR_VALIDATION_FAILED);
589 }
590 if (rcode != CONTROL_RESULT_SUCCESS) {
591 stringstream msg;
592 msg << "configTest returned " << answerToText(answer);
593 LOG_ERROR(netconf_logger, NETCONF_VALIDATE_CONFIG_REJECTED)
594 .arg(service_pair.first)
595 .arg(msg.str());
596 return (SR_ERR_VALIDATION_FAILED);
597 }
598 LOG_INFO(netconf_logger, NETCONF_VALIDATE_CONFIG_COMPLETED)
599 .arg(service_pair.first);
600 return (SR_ERR_OK);
601}
602
603int
604NetconfAgent::update(S_Session sess, const CfgServersMapPair& service_pair) {
605 // Check if we should and can process this update.
607 !service_pair.second->getSubscribeChanges() ||
608 service_pair.second->getModel().empty()) {
609 return (SR_ERR_OK);
610 }
611 CfgControlSocketPtr ctrl_sock = service_pair.second->getCfgControlSocket();
612 if (!ctrl_sock) {
613 return (SR_ERR_OK);
614 }
615
616 // All looks good, let's get started. Print an info that we're about
617 // to update the configuration.
618 LOG_INFO(netconf_logger, NETCONF_UPDATE_CONFIG_STARTED)
619 .arg(service_pair.first);
620
621 // Retrieve the configuration from SYSREPO first.
622 ConstElementPtr config;
623 try {
624 TranslatorConfig tc(sess, service_pair.second->getModel());
625 config = tc.getConfig();
626 if (!config) {
627 ostringstream msg;
628 msg << "YANG configuration for "
629 << service_pair.second->getModel()
630 << " is empty";
631 LOG_ERROR(netconf_logger, NETCONF_UPDATE_CONFIG_FAILED)
632 .arg(service_pair.first)
633 .arg(msg.str());
634 return (SR_ERR_VALIDATION_FAILED);
635 } else {
637 NETCONF_UPDATE_CONFIG)
638 .arg(service_pair.first)
639 .arg(prettyPrint(config));
640 }
641 } catch (const std::exception& ex) {
642 ostringstream msg;
643 msg << "get YANG configuration for " << service_pair.first
644 << " failed with " << ex.what();
645 LOG_ERROR(netconf_logger, NETCONF_UPDATE_CONFIG_FAILED)
646 .arg(service_pair.first)
647 .arg(msg.str());
648 return (SR_ERR_VALIDATION_FAILED);
649 }
651 return (SR_ERR_OK);
652 }
653
654 // Ok, now open the control socket. We need this to send the config to
655 // the server.
657 try {
658 comm = createControlSocket(ctrl_sock);
659 } catch (const std::exception& ex) {
660 ostringstream msg;
661 msg << "createControlSocket failed with " << ex.what();
662 LOG_ERROR(netconf_logger, NETCONF_UPDATE_CONFIG_FAILED)
663 .arg(service_pair.first)
664 .arg(msg.str());
665 return (SR_ERR_OK);
666 }
667
668 // Now apply the config using config-set command.
669 ConstElementPtr answer;
670 int rcode;
671 try {
672 answer = comm->configSet(config, service_pair.first);
673 parseAnswer(rcode, answer);
674 } catch (const std::exception& ex) {
675 stringstream msg;
676 msg << "configSet failed with " << ex.what();
677 LOG_ERROR(netconf_logger, NETCONF_UPDATE_CONFIG_FAILED)
678 .arg(service_pair.first)
679 .arg(msg.str());
680 return (SR_ERR_VALIDATION_FAILED);
681 }
682
683 // rcode == CONTROL_RESULT_SUCCESS, unless the docs say otherwise :).
684 if (rcode != CONTROL_RESULT_SUCCESS) {
685 stringstream msg;
686 msg << "configSet returned " << answerToText(answer);
687 LOG_ERROR(netconf_logger, NETCONF_UPDATE_CONFIG_FAILED)
688 .arg(service_pair.first)
689 .arg(msg.str());
690 return (SR_ERR_VALIDATION_FAILED);
691 }
692 LOG_INFO(netconf_logger, NETCONF_UPDATE_CONFIG_COMPLETED)
693 .arg(service_pair.first);
694 return (SR_ERR_OK);
695}
696
697void
698NetconfAgent::logChanges(S_Session sess, const string& model) {
700 return;
701 }
702 S_Iter_Change iter = sess->get_changes_iter(model.c_str());
703 if (!iter) {
704 LOG_WARN(netconf_logger, NETCONF_LOG_CHANGE_FAIL)
705 .arg("no iterator");
706 return;
707 }
708 for (;;) {
710 return;
711 }
712 S_Change change;
713 ostringstream msg;
714 try {
715 change = sess->get_change_next(iter);
716 } catch (const sysrepo_exception& ex) {
717 msg << "get change iterator next failed: " << ex.what();
718 LOG_WARN(netconf_logger, NETCONF_LOG_CHANGE_FAIL)
719 .arg(msg.str());
720 return;
721 }
722 if (!change) {
723 // End of changes, not an error.
724 return;
725 }
727 return;
728 }
729 S_Val new_val = change->new_val();
730 S_Val old_val = change->old_val();
731 string report;
732 switch (change->oper()) {
733 case SR_OP_CREATED:
734 if (!new_val) {
735 LOG_WARN(netconf_logger, NETCONF_LOG_CHANGE_FAIL)
736 .arg("created but without a new value");
737 break;
738 }
739 msg << "created: " << new_val->to_string();
740 report = msg.str();
741 boost::erase_all(report, "\n");
743 NETCONF_CONFIG_CHANGED_DETAIL)
744 .arg(report);
745 break;
746 case SR_OP_MODIFIED:
747 if (!old_val || !new_val) {
748 LOG_WARN(netconf_logger, NETCONF_LOG_CHANGE_FAIL)
749 .arg("modified but without an old or new value");
750 break;
751 }
752 msg << "modified: " << old_val->to_string()
753 << " => " << new_val->to_string();
754 report = msg.str();
755 boost::erase_all(report, "\n");
757 NETCONF_CONFIG_CHANGED_DETAIL)
758 .arg(report);
759 break;
760 case SR_OP_DELETED:
761 if (!old_val) {
762 LOG_WARN(netconf_logger, NETCONF_LOG_CHANGE_FAIL)
763 .arg("deleted but without an old value");
764 break;
765 }
766 msg << "deleted: " << old_val->to_string();
767 report = msg.str();
768 boost::erase_all(report, "\n");
770 NETCONF_CONFIG_CHANGED_DETAIL)
771 .arg(report);
772 break;
773 case SR_OP_MOVED:
774 if (!new_val) {
775 LOG_WARN(netconf_logger, NETCONF_LOG_CHANGE_FAIL)
776 .arg("moved but without a new value");
777 break;
778 }
779 msg << "moved: " << new_val->xpath();
780 if (!old_val) {
781 msg << " first";
782 } else {
783 msg << " after " << old_val->xpath();
784 }
785 report = msg.str();
786 boost::erase_all(report, "\n");
788 NETCONF_CONFIG_CHANGED_DETAIL)
789 .arg(report);
790 break;
791 default:
792 msg << "unknown operation (" << change->oper() << ")";
793 LOG_WARN(netconf_logger, NETCONF_LOG_CHANGE_FAIL)
794 .arg(msg.str());
795 }
796 }
797}
798
799} // namespace netconf
800} // namespace isc
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown when an unexpected error condition occurs.
sysrepo::S_Session running_sess_
Sysrepo running datastore session.
Definition: netconf.h:182
sysrepo::S_Session startup_sess_
Sysrepo startup datastore session.
Definition: netconf.h:175
void yangConfig(const CfgServersMapPair &service_pair)
Retrieve Kea server configuration from the YANG startup datastore and applies it to servers.
Definition: netconf.cc:394
virtual ~NetconfAgent()
Destructor (call clear).
Definition: netconf.cc:131
void subscribeConfig(const CfgServersMapPair &service_pair)
Subscribe changes for a module in YANG datastore.
Definition: netconf.cc:483
static int validate(sysrepo::S_Session sess, const CfgServersMapPair &service_pair)
Validate.
Definition: netconf.cc:519
NetconfAgent()
Constructor.
Definition: netconf.cc:128
void checkModules() const
Check module availability.
Definition: netconf.cc:373
void initSysrepo()
Initialize sysrepo sessions.
Definition: netconf.cc:278
std::map< const std::string, sysrepo::S_Subscribe > subscriptions_
Subscription map.
Definition: netconf.h:192
void keaConfig(const CfgServersMapPair &service_pair)
Get and display Kea server configuration.
Definition: netconf.cc:218
sysrepo::S_Connection conn_
Sysrepo connection.
Definition: netconf.h:168
static void logChanges(sysrepo::S_Session sess, const std::string &model)
Log changes.
Definition: netconf.cc:698
static int update(sysrepo::S_Session sess, const CfgServersMapPair &service_pair)
Update.
Definition: netconf.cc:604
void init(NetconfCfgMgrPtr cfg_mgr)
Initialization.
Definition: netconf.cc:136
bool checkModule(const std::string &module_name) const
Check essential module availability.
Definition: netconf.cc:345
std::map< const std::string, const std::string > modules_
Available modules and revisions in Sysrepo.
Definition: netconf.h:188
static const char * netconf_app_name_
Defines the application name, this is passed into base class and appears in log statements.
static bool shut_down
Global (globally visible) shutdown flag.
DHCP configuration translation between YANG and JSON.
isc::data::ElementPtr getConfig()
Get and translate the whole DHCP server configuration from YANG to JSON.
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
ConstElementPtr parseAnswer(int &rcode, const ConstElementPtr &msg)
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
std::string answerToText(const ConstElementPtr &msg)
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
Definition: data.cc:1256
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
const int NETCONF_DBG_TRACE_DETAIL_DATA
Additional information.
Definition: netconf_log.h:41
isc::log::Logger netconf_logger(NETCONF_LOGGER_NAME)
Base logger for the netconf agent.
Definition: netconf_log.h:49
boost::shared_ptr< ControlSocketBase > ControlSocketBasePtr
Type definition for the pointer to the ControlSocketBase.
ControlSocketBasePtr createControlSocket(CfgControlSocketPtr ctrl_sock)
Factory function for control sockets.
boost::shared_ptr< CfgControlSocket > CfgControlSocketPtr
Defines a pointer for CfgControlSocket instances.
boost::shared_ptr< NetconfCfgMgr > NetconfCfgMgrPtr
Defines a shared pointer to NetconfCfgMgr.
boost::shared_ptr< CfgServersMap > CfgServersMapPtr
Defines a pointer to map of CfgServers.
std::pair< std::string, CfgServerPtr > CfgServersMapPair
Defines a iterator pairing of name and CfgServer.
Defines the logger used by the top-level component of kea-dhcp-ddns.
Contains declarations for loggers used by the Kea netconf agent.