Kea 2.0.2
translator_subnet.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
7#include <config.h>
8
9#include <yang/adaptor_pool.h>
11#include <yang/yang_models.h>
12
13#include <sstream>
14
15using namespace std;
16using namespace isc::data;
17using namespace sysrepo;
18
19namespace isc {
20namespace yang {
21
22TranslatorSubnet::TranslatorSubnet(S_Session session, const string& model)
23 : TranslatorBasic(session, model),
24 TranslatorOptionData(session, model),
25 TranslatorOptionDataList(session, model),
26 TranslatorPool(session, model),
27 TranslatorPools(session, model),
28 TranslatorPdPool(session, model),
29 TranslatorPdPools(session, model),
30 TranslatorHost(session, model),
31 TranslatorHosts(session, model) {
32}
33
35}
36
38TranslatorSubnet::getSubnet(const string& xpath) {
39 try {
40 if (model_ == IETF_DHCPV6_SERVER) {
41 return (getSubnetIetf6(xpath));
42 } else if ((model_ == KEA_DHCP4_SERVER) ||
43 (model_ == KEA_DHCP6_SERVER)) {
44 return (getSubnetKea(xpath));
45 }
46 } catch (const sysrepo_exception& ex) {
48 "sysrepo error getting subnet at '" << xpath
49 << "': " << ex.what());
50 }
52 "getSubnet not implemented for the model: " << model_);
53}
54
57 ElementPtr result = Element::createMap();
60 ConstElementPtr pools = getPools(xpath + "/address-pools");
61 if (pools) {
63 result->set("pools", pools);
64 }
65 pools = getPdPools(xpath + "/pd-pools");
66 if (pools && (pools->size() > 0)) {
67 result->set("pd-pools", pools);
68 }
69 ConstElementPtr subnet = getItem(xpath + "/network-prefix");
70 if (!subnet) {
71 isc_throw(BadValue, "getSubnetIetf6 requires network prefix");
72 }
73 result->set("subnet", subnet);
74 ConstElementPtr id = getItem(xpath + "/network-range-id");
75 if (!id) {
76 isc_throw(BadValue, "getSubnetIetf6 requires network range id");
77 }
78 result->set("id", id);
81 ConstElementPtr description = getItem(xpath + "/network-description");
83 if (description) {
84 ElementPtr context = Element::createMap();
85 context->set("description", description);
86 result->set("user-context", context);
87 }
89 if (result->get("pools")) {
90 AdaptorPool::toSubnet(model_, result, result->get("pools"));
91 }
92 return (result);
93}
94
96TranslatorSubnet::getSubnetKea(const string& xpath) {
97 ElementPtr result = Element::createMap();
98 if (model_ == KEA_DHCP6_SERVER) {
99 ConstElementPtr preferred = getItem(xpath + "/preferred-lifetime");
100 if (preferred) {
101 result->set("preferred-lifetime", preferred);
102 }
103 ConstElementPtr min_pref = getItem(xpath + "/min-preferred-lifetime");
104 if (min_pref) {
105 result->set("min-preferred-lifetime", min_pref);
106 }
107 ConstElementPtr max_pref = getItem(xpath + "/max-preferred-lifetime");
108 if (max_pref) {
109 result->set("max-preferred-lifetime", max_pref);
110 }
111 }
112 ConstElementPtr valid = getItem(xpath + "/valid-lifetime");
113 if (valid) {
114 result->set("valid-lifetime", valid);
115 }
116 ConstElementPtr min_valid = getItem(xpath + "/min-valid-lifetime");
117 if (min_valid) {
118 result->set("min-valid-lifetime", min_valid);
119 }
120 ConstElementPtr max_valid = getItem(xpath + "/max-valid-lifetime");
121 if (max_valid) {
122 result->set("max-valid-lifetime", max_valid);
123 }
124 ConstElementPtr renew = getItem(xpath + "/renew-timer");
125
126 if (renew) {
127 result->set("renew-timer", renew);
128 }
129 ConstElementPtr rebind = getItem(xpath + "/rebind-timer");
130 if (rebind) {
131 result->set("rebind-timer", rebind);
132 }
133 ConstElementPtr calculate = getItem(xpath + "/calculate-tee-times");
134 if (calculate) {
135 result->set("calculate-tee-times", calculate);
136 }
137 ConstElementPtr t1_percent = getItem(xpath + "/t1-percent");
138 if (t1_percent) {
139 result->set("t1-percent", t1_percent);
140 }
141 ConstElementPtr t2_percent = getItem(xpath + "/t2-percent");
142 if (t2_percent) {
143 result->set("t2-percent", t2_percent);
144 }
145 ConstElementPtr options = getOptionDataList(xpath);
146 if (options && (options->size() > 0)) {
147 result->set("option-data", options);
148 }
149 ConstElementPtr pools = getPools(xpath);
150 if (pools && (pools->size() > 0)) {
151 result->set("pools", pools);
152 }
153 if (model_ == KEA_DHCP6_SERVER) {
154 pools = getPdPools(xpath);
155 if (pools && (pools->size() > 0)) {
156 result->set("pd-pools", pools);
157 }
158 }
159 ConstElementPtr subnet = getItem(xpath + "/subnet");
160 if (!subnet) {
161 isc_throw(BadValue, "getSubnetKea requires subnet");
162 }
163 result->set("subnet", subnet);
164 ConstElementPtr interface = getItem(xpath + "/interface");
165 if (interface) {
166 result->set("interface", interface);
167 }
168 if (model_ == KEA_DHCP6_SERVER) {
169 ConstElementPtr interface_id = getItem(xpath + "/interface-id");
170 if (interface_id) {
171 result->set("interface-id", interface_id);
172 }
173 }
174 ConstElementPtr id = getItem(xpath + "/id");
175 if (!id) {
176 isc_throw(BadValue, "getSubnetKea requires id");
177 }
178 result->set("id", id);
179 if (model_ == KEA_DHCP6_SERVER) {
180 ConstElementPtr rapid_commit = getItem(xpath + "/rapid-commit");
181 if (rapid_commit) {
182 result->set("rapid-commit", rapid_commit);
183 }
184 }
185 ConstElementPtr guard = getItem(xpath + "/client-class");
186 if (guard) {
187 result->set("client-class", guard);
188 }
189 ConstElementPtr required = getItems(xpath + "/require-client-classes");
190 if (required && (required->size() > 0)) {
191 result->set("require-client-classes", required);
192 }
193 ConstElementPtr hosts = getHosts(xpath);
194 if (hosts && (hosts->size() > 0)) {
195 result->set("reservations", hosts);
196 }
197 ConstElementPtr mode = getItem(xpath + "/reservation-mode");
198 if (mode) {
199 result->set("reservation-mode", mode);
200 }
201 ConstElementPtr relay = getItems(xpath + "/relay/ip-addresses");
202 if (relay && (relay->size() > 0)) {
203 ElementPtr relay_map = Element::createMap();
204 relay_map->set("ip-addresses", relay);
205 result->set("relay", relay_map);
206 }
207 if (model_ == KEA_DHCP4_SERVER) {
208 ConstElementPtr match = getItem(xpath + "/match-client-id");
209 if (match) {
210 result->set("match-client-id", match);
211 }
212 ConstElementPtr auth = getItem(xpath + "/authoritative");
213 if (auth) {
214 result->set("authoritative", auth);
215 }
216 ConstElementPtr next = getItem(xpath + "/next-server");
217 if (next) {
218 result->set("next-server", next);
219 }
220 ConstElementPtr hostname = getItem(xpath + "/server-hostname");
221 if (hostname) {
222 result->set("server-hostname", hostname);
223 }
224 ConstElementPtr boot = getItem(xpath + "/boot-file-name");
225 if (boot) {
226 result->set("boot-file-name", boot);
227 }
228 ConstElementPtr s4o6_if = getItem(xpath + "/subnet-4o6-interface");
229 if (s4o6_if) {
230 result->set("4o6-interface", s4o6_if);
231 }
232 ConstElementPtr s4o6_id = getItem(xpath + "/subnet-4o6-interface-id");
233 if (s4o6_id) {
234 result->set("4o6-interface-id", s4o6_id);
235 }
236 ConstElementPtr s4o6_sub = getItem(xpath + "/subnet-4o6-subnet");
237 if (s4o6_sub) {
238 result->set("4o6-subnet", s4o6_sub);
239 }
240 }
241 ConstElementPtr context = getItem(xpath + "/user-context");
242 if (context) {
243 result->set("user-context", Element::fromJSON(context->stringValue()));
244 }
245 return (result);
246}
247
248void
250 try {
251 if (model_ == IETF_DHCPV6_SERVER) {
252 setSubnetIetf6(xpath, elem);
253 } else if ((model_ == KEA_DHCP4_SERVER) ||
254 (model_ == KEA_DHCP6_SERVER)) {
255 setSubnetKea(xpath, elem);
256 } else {
258 "setSubnet not implemented for the model: " << model_);
259 }
260 } catch (const sysrepo_exception& ex) {
262 "sysrepo error setting subnet '" << elem->str()
263 << "' at '" << xpath << "': " << ex.what());
264 }
265}
266
267void
270 AdaptorPool::fromSubnet(model_, elem, elem->get("pools"));
271 ConstElementPtr context = elem->get("user-context");
272 if (context && context->contains("description")) {
273 ConstElementPtr description = context->get("description");
274 if (description->getType() == Element::string) {
275 setItem(xpath + "/network-description", description, SR_STRING_T);
276 }
277 }
278 ConstElementPtr subnet = elem->get("subnet");
279 if (!subnet) {
280 isc_throw(BadValue, "setSubnetIetf6 requires subnet: " << elem->str());
281 }
282 setItem(xpath + "/network-prefix", subnet, SR_STRING_T);
284 ConstElementPtr pools = elem->get("pools");
285 if (pools && (pools->size() > 0)) {
286 setPools(xpath + "/address-pools", pools);
287 }
288 pools = elem->get("pd-pools");
289 if (pools && (pools->size() > 0)) {
290 setPdPools(xpath + "/pd-pools", pools);
291 }
293}
294
295void
298 if (model_ == KEA_DHCP6_SERVER) {
299 ConstElementPtr preferred = elem->get("preferred-lifetime");
300 if (preferred) {
301 setItem(xpath + "/preferred-lifetime", preferred, SR_UINT32_T);
302 }
303 ConstElementPtr min_pref = elem->get("min-preferred-lifetime");
304 if (min_pref) {
305 setItem(xpath + "/min-preferred-lifetime", min_pref, SR_UINT32_T);
306 }
307 ConstElementPtr max_pref = elem->get("max-preferred-lifetime");
308 if (max_pref) {
309 setItem(xpath + "/max-preferred-lifetime", max_pref, SR_UINT32_T);
310 }
311 }
312 ConstElementPtr valid = elem->get("valid-lifetime");
313 if (valid) {
314 setItem(xpath + "/valid-lifetime", valid, SR_UINT32_T);
315 }
316 ConstElementPtr min_valid = elem->get("min-valid-lifetime");
317 if (min_valid) {
318 setItem(xpath + "/min-valid-lifetime", min_valid, SR_UINT32_T);
319 }
320 ConstElementPtr max_valid = elem->get("max-valid-lifetime");
321 if (max_valid) {
322 setItem(xpath + "/max-valid-lifetime", max_valid, SR_UINT32_T);
323 }
324 ConstElementPtr renew = elem->get("renew-timer");
325 if (renew) {
326 setItem(xpath + "/renew-timer", renew, SR_UINT32_T);
327 }
328 ConstElementPtr rebind = elem->get("rebind-timer");
329 if (rebind) {
330 setItem(xpath + "/rebind-timer", rebind, SR_UINT32_T);
331 }
332 ConstElementPtr calculate = elem->get("calculate-tee-times");
333 if (calculate) {
334 setItem(xpath + "/calculate-tee-times", calculate, SR_BOOL_T);
335 }
336 ConstElementPtr t1_percent = elem->get("t1-percent");
337 if (t1_percent) {
338 setItem(xpath + "/t1-percent", t1_percent, SR_DECIMAL64_T);
339 }
340 ConstElementPtr t2_percent = elem->get("t2-percent");
341 if (t2_percent) {
342 setItem(xpath + "/t2-percent", t2_percent, SR_DECIMAL64_T);
343 }
344 ConstElementPtr options = elem->get("option-data");
345 if (options && (options->size() > 0)) {
346 setOptionDataList(xpath, options);
347 }
348 ConstElementPtr pools = elem->get("pools");
349 if (pools && (pools->size() > 0)) {
350 setPools(xpath, pools);
351 }
352 if (model_ == KEA_DHCP6_SERVER) {
353 pools = elem->get("pd-pools");
354 if (pools && (pools->size() > 0)) {
355 setPdPools(xpath, pools);
356 }
357 }
358 ConstElementPtr subnet = elem->get("subnet");
359 if (!subnet) {
360 isc_throw(BadValue, "setSubnetKea requires subnet: " << elem->str());
361 }
362 setItem(xpath + "/subnet", subnet, SR_STRING_T);
363 ConstElementPtr interface = elem->get("interface");
364 if (interface) {
365 setItem(xpath + "/interface", interface, SR_STRING_T);
366 }
367 if (model_ == KEA_DHCP6_SERVER) {
368 ConstElementPtr interface_id = elem->get("interface-id");
369 if (interface_id) {
370 setItem(xpath + "/interface-id", interface_id, SR_STRING_T);
371 }
372 }
373 if (model_ == KEA_DHCP6_SERVER) {
374 ConstElementPtr rapid_commit = elem->get("rapid-commit");
375 if (rapid_commit) {
376 setItem(xpath + "/rapid-commit", rapid_commit, SR_BOOL_T);
377 }
378 }
379 ConstElementPtr guard = elem->get("client-class");
380 if (guard) {
381 setItem(xpath + "/client-class", guard, SR_STRING_T);
382 }
383 ConstElementPtr required = elem->get("require-client-classes");
384 if (required && (required->size() > 0)) {
385 for (ConstElementPtr rclass : required->listValue()) {
386 setItem(xpath + "/require-client-classes", rclass, SR_STRING_T);
387 }
388 }
389 ConstElementPtr hosts = elem->get("reservations");
390 if (hosts && (hosts->size() > 0)) {
391 setHosts(xpath, hosts);
392 }
393 ConstElementPtr mode = elem->get("reservation-mode");
394 if (mode) {
395 setItem(xpath + "/reservation-mode", mode, SR_ENUM_T);
396 }
397 ConstElementPtr relay = elem->get("relay");
398 if (relay) {
399 ConstElementPtr address = relay->get("ip-address");
400 ConstElementPtr addresses = relay->get("ip-addresses");
401 if (address) {
402 setItem(xpath + "/relay/ip-addresses", address, SR_STRING_T);
403 } else if (addresses && (addresses->size() > 0)) {
404 for (ConstElementPtr addr : addresses->listValue()) {
405 setItem(xpath + "/relay/ip-addresses", addr, SR_STRING_T);
406 }
407 }
408 }
409 checkAndSetLeaf(elem, xpath, "store-extended-info", SR_BOOL_T);
410 if (model_ == KEA_DHCP4_SERVER) {
411 ConstElementPtr match = elem->get("match-client-id");
412 if (match) {
413 setItem(xpath + "/match-client-id", match, SR_BOOL_T);
414 }
415 ConstElementPtr auth = elem->get("authoritative");
416 if (auth) {
417 setItem(xpath + "/authoritative", auth, SR_BOOL_T);
418 }
419 ConstElementPtr next = elem->get("next-server");
420 if (next) {
421 setItem(xpath + "/next-server", next, SR_STRING_T);
422 }
423 ConstElementPtr hostname = elem->get("server-hostname");
424 if (hostname) {
425 setItem(xpath + "/server-hostname", hostname, SR_STRING_T);
426 }
427 ConstElementPtr boot = elem->get("boot-file-name");
428 if (boot) {
429 setItem(xpath + "/boot-file-name", boot, SR_STRING_T);
430 }
431 ConstElementPtr s4o6_if = elem->get("4o6-interface");
432 if (s4o6_if) {
433 setItem(xpath + "/subnet-4o6-interface", s4o6_if, SR_STRING_T);
434 }
435 ConstElementPtr s4o6_id = elem->get("4o6-interface-id");
436 if (s4o6_id) {
437 setItem(xpath + "/subnet-4o6-interface-id", s4o6_id, SR_STRING_T);
438 }
439 ConstElementPtr s4o6_subnet = elem->get("4o6-subnet");
440 if (s4o6_subnet) {
441 setItem(xpath + "/subnet-4o6-subnet", s4o6_subnet, SR_STRING_T);
442 }
443 }
444 ConstElementPtr context = Adaptor::getContext(elem);
445 if (context) {
446 ConstElementPtr repr = Element::create(context->str());
447 setItem(xpath + "/user-context", repr, SR_STRING_T);
448 }
449}
450
451TranslatorSubnets::TranslatorSubnets(S_Session session, const string& model)
452 : TranslatorBasic(session, model),
453 TranslatorOptionData(session, model),
454 TranslatorOptionDataList(session, model),
455 TranslatorPool(session, model),
456 TranslatorPools(session, model),
457 TranslatorPdPool(session, model),
458 TranslatorPdPools(session, model),
459 TranslatorHost(session, model),
460 TranslatorHosts(session, model),
461 TranslatorSubnet(session, model) {
462}
463
465}
466
468TranslatorSubnets::getSubnets(const string& xpath) {
469 try {
470 if (model_ == IETF_DHCPV6_SERVER) {
471 return (getSubnetsCommon(xpath, "network-range"));
472 } else if (model_ == KEA_DHCP4_SERVER) {
473 return (getSubnetsCommon(xpath, "subnet4"));
474 } else if (model_ == KEA_DHCP6_SERVER) {
475 return (getSubnetsCommon(xpath, "subnet6"));
476 }
477 } catch (const sysrepo_exception& ex) {
479 "sysrepo error getting subnets at '" << xpath
480 << "': " << ex.what());
481 }
483 "getSubnets not implemented for the model: " << model_);
484}
485
488 const std::string& subsel) {
489 return getList<TranslatorSubnet>(xpath + "/" + subsel, *this,
491}
492
493void
495 try {
496 if (model_ == IETF_DHCPV6_SERVER) {
497 setSubnetsIetf6(xpath, elem);
498 } else if (model_ == KEA_DHCP4_SERVER) {
499 setSubnetsKea(xpath, elem, "subnet4");
500 } else if (model_ == KEA_DHCP6_SERVER) {
501 setSubnetsKea(xpath, elem, "subnet6");
502 } else {
504 "setSubnets not implemented for the model: " << model_);
505 }
506 } catch (const sysrepo_exception& ex) {
508 "sysrepo error setting subnets '" << elem->str()
509 << "' at '" << xpath << "': " << ex.what());
510 }
511}
512
513void
515 for (size_t i = 0; i < elem->size(); ++i) {
516 ConstElementPtr subnet = elem->get(i);
517 ostringstream range;
518 range << xpath << "/network-range[network-range-id='";
519 ConstElementPtr id = subnet->get("id");
520 if (!id) {
521 isc_throw(BadValue, "subnet without id: " << elem->str());
522 }
523 range << id->intValue() << "']";
524 setSubnet(range.str().c_str(), subnet);
525 }
526}
527
528void
530 const std::string& subsel) {
531 for (size_t i = 0; i < elem->size(); ++i) {
532 ConstElementPtr subnet = elem->get(i);
533 if (!subnet->contains("id")) {
534 isc_throw(BadValue, "subnet without id: " << subnet->str());
535 }
536 ostringstream prefix;
537 prefix << xpath << "/" << subsel << "[id='"
538 << subnet->get("id")->intValue() << "']";
539 setSubnet(prefix.str(), subnet);
540 }
541}
542
543} // namespace yang
544} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown when a function is not implemented.
static void toSubnet(const std::string &model, isc::data::ElementPtr subnet, isc::data::ConstElementPtr pools)
Move parameters from pools to the subnet.
Definition: adaptor_pool.cc:67
static void fromSubnet(const std::string &model, isc::data::ConstElementPtr subnet, isc::data::ConstElementPtr pools)
Moves parameters from subnets to pools.
Definition: adaptor_pool.cc:47
static isc::data::ConstElementPtr getContext(isc::data::ConstElementPtr parent)
Get user context.
Definition: adaptor.cc:27
Between YANG and JSON translator class for basic values.
Definition: translator.h:19
isc::data::ElementPtr getItem(const std::string &xpath)
Get and translate basic value from YANG to JSON.
Definition: translator.cc:105
std::string model_
The model.
Definition: translator.h:159
void setItem(const std::string &xpath, isc::data::ConstElementPtr elem, sr_type_t type)
Translate and set basic value from JSON to YANG.
Definition: translator.cc:260
isc::data::ElementPtr getItems(const std::string &xpath)
Get and translate a list of basic values from YANG to JSON.
Definition: translator.cc:124
void checkAndSetLeaf(isc::data::ConstElementPtr const &from, std::string const &xpath, std::string const &name, sr_type_t const type)
Get an element from given ElementPtr node and set it in sysrepo at given xpath.
Definition: translator.cc:273
Translation between YANG and JSON for a single host reservation.
A translator class for converting host reservations list between YANG and JSON.
isc::data::ElementPtr getHosts(const std::string &xpath)
Get and translate host reservations from YANG to JSON.
void setHosts(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set (address) host reservations from JSON to YANG.
A translator class for converting an option data list between YANG and JSON.
isc::data::ConstElementPtr getOptionDataList(const std::string &xpath)
Get and translate option data list from YANG to JSON.
void setOptionDataList(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set option data list from JSON to YANG.
Option data translation between YANG and JSON.
Prefix delegation pool translation between YANG and JSON.
A translator class for converting a pd-pool list between YANG and JSON.
void setPdPools(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set pd-pools from JSON to YANG.
isc::data::ElementPtr getPdPools(const std::string &xpath)
Get and translate pd-pools from YANG to JSON.
A translator class for converting a pool between YANG and JSON.
A translator class for converting pools between YANG and JSON.
isc::data::ElementPtr getPools(const std::string &xpath)
Get and translate pools from YANG to JSON.
void setPools(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set (address) pools from JSON to YANG.
Subnet (aka network range) translation between YANG and JSON.
virtual ~TranslatorSubnet()
Destructor.
void setSubnetIetf6(const std::string &xpath, isc::data::ConstElementPtr elem)
setSubnet for ietf-dhcpv6-server.
TranslatorSubnet(sysrepo::S_Session session, const std::string &model)
Constructor.
isc::data::ElementPtr getSubnet(const std::string &xpath)
Get and translate a subnet from YANG to JSON.
void setSubnet(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set subnet from JSON to YANG.
isc::data::ElementPtr getSubnetIetf6(const std::string &xpath)
getSubnet for ietf-dhcpv6-server.
void setSubnetKea(const std::string &xpath, isc::data::ConstElementPtr elem)
setSubnet for kea-dhcp[46]-server.
isc::data::ElementPtr getSubnetKea(const std::string &xpath)
getSubnet for kea-dhcp[46]-server.
void setSubnets(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set subnets from JSON to YANG.
void setSubnetsKea(const std::string &xpath, isc::data::ConstElementPtr elem, const std::string &subsel)
setSubnets for kea-dhcp[46]-server.
isc::data::ElementPtr getSubnets(const std::string &xpath)
Get and translate subnets from YANG to JSON.
void setSubnetsIetf6(const std::string &xpath, isc::data::ConstElementPtr elem)
setSubnets for ietf-dhcpv6-server.
TranslatorSubnets(sysrepo::S_Session session, const std::string &model)
Constructor.
virtual ~TranslatorSubnets()
Destructor.
isc::data::ElementPtr getSubnetsCommon(const std::string &xpath, const std::string &subsel)
getSubnets common part.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
Defines the logger used by the top-level component of kea-lfc.