Kea 1.5.0
translator_subnet.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
7#include <config.h>
8
10#include <yang/adaptor_pool.h>
11#include <yang/yang_models.h>
12#include <sstream>
13
14using namespace std;
15using namespace isc::data;
16#ifndef HAVE_PRE_0_7_6_SYSREPO
17using namespace sysrepo;
18#endif
19
20namespace isc {
21namespace yang {
22
23TranslatorSubnet::TranslatorSubnet(S_Session session, const string& model)
24 : TranslatorBasic(session, model),
25 TranslatorOptionData(session, model),
26 TranslatorOptionDataList(session, model),
27 TranslatorPool(session, model),
28 TranslatorPools(session, model),
29 TranslatorPdPool(session, model),
30 TranslatorPdPools(session, model),
31 TranslatorHost(session, model),
32 TranslatorHosts(session, model) {
33}
34
36}
37
39TranslatorSubnet::getSubnet(const string& xpath) {
40 try {
41 if (model_ == IETF_DHCPV6_SERVER) {
42 return (getSubnetIetf6(xpath));
43 } else if ((model_ == KEA_DHCP4_SERVER) ||
44 (model_ == KEA_DHCP6_SERVER)) {
45 return (getSubnetKea(xpath));
46 }
47 } catch (const sysrepo_exception& ex) {
49 "sysrepo error getting subnet at '" << xpath
50 << "': " << ex.what());
51 }
53 "getSubnet not implemented for the model: " << model_);
54}
55
61 ConstElementPtr pools = getPools(xpath + "/address-pools");
62 if (pools) {
64 result->set("pools", pools);
65 }
66 pools = getPdPools(xpath + "/pd-pools");
67 if (pools && (pools->size() > 0)) {
68 result->set("pd-pools", pools);
69 }
70 ConstElementPtr subnet = getItem(xpath + "/network-prefix");
71 if (!subnet) {
72 isc_throw(BadValue, "getSubnetIetf6 requires network prefix");
73 }
74 result->set("subnet", subnet);
75 ConstElementPtr id = getItem(xpath + "/network-range-id");
76 if (!id) {
77 isc_throw(BadValue, "getSubnetIetf6 requires network range id");
78 }
79 result->set("id", id);
82 ConstElementPtr description = getItem(xpath + "/network-description");
84 if (description) {
86 context->set("description", description);
87 result->set("user-context", context);
88 }
90 AdaptorPool::toSubnet(model_, result, result->get("pools"));
91 return (result);
92}
93
95TranslatorSubnet::getSubnetKea(const string& xpath) {
97 if (model_ == KEA_DHCP6_SERVER) {
98 ConstElementPtr preferred = getItem(xpath + "/preferred-lifetime");
99 if (preferred) {
100 result->set("preferred-lifetime", preferred);
101 }
102 }
103 ConstElementPtr valid = getItem(xpath + "/valid-lifetime");
104 if (valid) {
105 result->set("valid-lifetime", valid);
106 }
107 ConstElementPtr renew = getItem(xpath + "/renew-timer");
108 if (renew) {
109 result->set("renew-timer", renew);
110 }
111 ConstElementPtr rebind = getItem(xpath + "/rebind-timer");
112 if (rebind) {
113 result->set("rebind-timer", rebind);
114 }
115 ConstElementPtr options = getOptionDataList(xpath);
116 if (options && (options->size() > 0)) {
117 result->set("option-data", options);
118 }
119 ConstElementPtr pools = getPools(xpath);
120 if (pools && (pools->size() > 0)) {
121 result->set("pools", pools);
122 }
123 if (model_ == KEA_DHCP6_SERVER) {
124 pools = getPdPools(xpath);
125 if (pools && (pools->size() > 0)) {
126 result->set("pd-pools", pools);
127 }
128 }
129 ConstElementPtr subnet = getItem(xpath + "/subnet");
130 if (!subnet) {
131 isc_throw(BadValue, "getSubnetKea requires subnet");
132 }
133 result->set("subnet", subnet);
134 ConstElementPtr interface = getItem(xpath + "/interface");
135 if (interface) {
136 result->set("interface", interface);
137 }
138 if (model_ == KEA_DHCP6_SERVER) {
139 ConstElementPtr interface_id = getItem(xpath + "/interface-id");
140 if (interface_id) {
141 result->set("interface-id", interface_id);
142 }
143 }
144 ConstElementPtr id = getItem(xpath + "/id");
145 if (!id) {
146 isc_throw(BadValue, "getSubnetKea requires id");
147 }
148 result->set("id", id);
149 if (model_ == KEA_DHCP6_SERVER) {
150 ConstElementPtr rapid_commit = getItem(xpath + "/rapid-commit");
151 if (rapid_commit) {
152 result->set("rapid-commit", rapid_commit);
153 }
154 }
155 ConstElementPtr guard = getItem(xpath + "/client-class");
156 if (guard) {
157 result->set("client-class", guard);
158 }
159 ConstElementPtr required = getItems(xpath + "/require-client-classes");
160 if (required && (required->size() > 0)) {
161 result->set("require-client-classes", required);
162 }
163 ConstElementPtr hosts = getHosts(xpath);
164 if (hosts && (hosts->size() > 0)) {
165 result->set("reservations", hosts);
166 }
167 ConstElementPtr mode = getItem(xpath + "/reservation-mode");
168 if (mode) {
169 result->set("reservation-mode", mode);
170 }
171 ConstElementPtr relay = getItems(xpath + "/relay/ip-addresses");
172 if (relay && (relay->size() > 0)) {
173 ElementPtr relay_map = Element::createMap();
174 relay_map->set("ip-addresses", relay);
175 result->set("relay", relay_map);
176 }
177 if (model_ == KEA_DHCP4_SERVER) {
178 ConstElementPtr match = getItem(xpath + "/match-client-id");
179 if (match) {
180 result->set("match-client-id", match);
181 }
182 ConstElementPtr auth = getItem(xpath + "/authoritative");
183 if (auth) {
184 result->set("authoritative", auth);
185 }
186 ConstElementPtr next = getItem(xpath + "/next-server");
187 if (next) {
188 result->set("next-server", next);
189 }
190 ConstElementPtr hostname = getItem(xpath + "/server-hostname");
191 if (hostname) {
192 result->set("server-hostname", hostname);
193 }
194 ConstElementPtr boot = getItem(xpath + "/boot-file-name");
195 if (boot) {
196 result->set("boot-file-name", boot);
197 }
198 ConstElementPtr s4o6_if = getItem(xpath + "/subnet-4o6-interface");
199 if (s4o6_if) {
200 result->set("4o6-interface", s4o6_if);
201 }
202 ConstElementPtr s4o6_id = getItem(xpath + "/subnet-4o6-interface-id");
203 if (s4o6_id) {
204 result->set("4o6-interface-id", s4o6_id);
205 }
206 ConstElementPtr s4o6_sub = getItem(xpath + "/subnet-4o6-subnet");
207 if (s4o6_sub) {
208 result->set("4o6-subnet", s4o6_sub);
209 }
210 }
211 ConstElementPtr context = getItem(xpath + "/user-context");
212 if (context) {
213 result->set("user-context", Element::fromJSON(context->stringValue()));
214 }
215 return (result);
216}
217
218void
220 try {
221 if (model_ == IETF_DHCPV6_SERVER) {
222 setSubnetIetf6(xpath, elem);
223 } else if ((model_ == KEA_DHCP4_SERVER) ||
224 (model_ == KEA_DHCP6_SERVER)) {
225 setSubnetKea(xpath, elem);
226 } else {
228 "setSubnet not implemented for the model: " << model_);
229 }
230 } catch (const sysrepo_exception& ex) {
232 "sysrepo error setting subnet '" << elem->str()
233 << "' at '" << xpath << "': " << ex.what());
234 }
235}
236
237void
240 AdaptorPool::fromSubnet(model_, elem, elem->get("pools"));
241 ConstElementPtr context = elem->get("user-context");
242 if (context && context->contains("description")) {
243 ConstElementPtr description = context->get("description");
244 if (description->getType() == Element::string) {
245 setItem(xpath + "/network-description", description, SR_STRING_T);
246 }
247 }
248 ConstElementPtr subnet = elem->get("subnet");
249 if (!subnet) {
250 isc_throw(BadValue, "setSubnetIetf6 requires subnet: " << elem->str());
251 }
252 setItem(xpath + "/network-prefix", subnet, SR_STRING_T);
254 ConstElementPtr pools = elem->get("pools");
255 if (pools && (pools->size() > 0)) {
256 setPools(xpath + "/address-pools", pools);
257 }
258 pools = elem->get("pd-pools");
259 if (pools && (pools->size() > 0)) {
260 setPdPools(xpath + "/pd-pools", pools);
261 }
263}
264
265void
268 if (model_ == KEA_DHCP6_SERVER) {
269 ConstElementPtr preferred = elem->get("preferred-lifetime");
270 if (preferred) {
271 setItem(xpath + "/preferred-lifetime", preferred, SR_UINT32_T);
272 }
273 }
274 ConstElementPtr valid = elem->get("valid-lifetime");
275 if (valid) {
276 setItem(xpath + "/valid-lifetime", valid, SR_UINT32_T);
277 }
278 ConstElementPtr renew = elem->get("renew-timer");
279 if (renew) {
280 setItem(xpath + "/renew-timer", renew, SR_UINT32_T);
281 }
282 ConstElementPtr rebind = elem->get("rebind-timer");
283 if (rebind) {
284 setItem(xpath + "/rebind-timer", rebind, SR_UINT32_T);
285 }
286 ConstElementPtr options = elem->get("option-data");
287 if (options && (options->size() > 0)) {
288 setOptionDataList(xpath, options);
289 }
290 ConstElementPtr pools = elem->get("pools");
291 if (pools && (pools->size() > 0)) {
292 setPools(xpath, pools);
293 }
294 if (model_ == KEA_DHCP6_SERVER) {
295 pools = elem->get("pd-pools");
296 if (pools && (pools->size() > 0)) {
297 setPdPools(xpath, pools);
298 }
299 }
300 ConstElementPtr subnet = elem->get("subnet");
301 if (!subnet) {
302 isc_throw(BadValue, "setSubnetKea requires subnet: " << elem->str());
303 }
304 setItem(xpath + "/subnet", subnet, SR_STRING_T);
305 ConstElementPtr interface = elem->get("interface");
306 if (interface) {
307 setItem(xpath + "/interface", interface, SR_STRING_T);
308 }
309 if (model_ == KEA_DHCP6_SERVER) {
310 ConstElementPtr interface_id = elem->get("interface-id");
311 if (interface_id) {
312 setItem(xpath + "/interface-id", interface_id, SR_STRING_T);
313 }
314 }
315 if (model_ == KEA_DHCP6_SERVER) {
316 ConstElementPtr rapid_commit = elem->get("rapid-commit");
317 if (rapid_commit) {
318 setItem(xpath + "/rapid-commit", rapid_commit, SR_BOOL_T);
319 }
320 }
321 ConstElementPtr guard = elem->get("client-class");
322 if (guard) {
323 setItem(xpath + "/client-class", guard, SR_STRING_T);
324 }
325 ConstElementPtr required = elem->get("require-client-classes");
326 if (required && (required->size() > 0)) {
327 for (ConstElementPtr rclass : required->listValue()) {
328 setItem(xpath + "/require-client-classes", rclass, SR_STRING_T);
329 }
330 }
331 ConstElementPtr hosts = elem->get("reservations");
332 if (hosts && (hosts->size() > 0)) {
333 setHosts(xpath, hosts);
334 }
335 ConstElementPtr mode = elem->get("reservation-mode");
336 if (mode) {
337 setItem(xpath + "/reservation-mode", mode, SR_ENUM_T);
338 }
339 ConstElementPtr relay = elem->get("relay");
340 if (relay) {
341 ConstElementPtr address = relay->get("ip-address");
342 ConstElementPtr addresses = relay->get("ip-addresses");
343 if (address) {
344 setItem(xpath + "/relay/ip-addresses", address, SR_STRING_T);
345 } else if (addresses && (addresses->size() > 0)) {
346 for (ConstElementPtr addr : addresses->listValue()) {
347 setItem(xpath + "/relay/ip-addresses", addr, SR_STRING_T);
348 }
349 }
350 }
351 if (model_ == KEA_DHCP4_SERVER) {
352 ConstElementPtr match = elem->get("match-client-id");
353 if (match) {
354 setItem(xpath + "/match-client-id", match, SR_BOOL_T);
355 }
356 ConstElementPtr auth = elem->get("authoritative");
357 if (auth) {
358 setItem(xpath + "/authoritative", auth, SR_BOOL_T);
359 }
360 ConstElementPtr next = elem->get("next-server");
361 if (next) {
362 setItem(xpath + "/next-server", next, SR_STRING_T);
363 }
364 ConstElementPtr hostname = elem->get("server-hostname");
365 if (hostname) {
366 setItem(xpath + "/server-hostname", hostname, SR_STRING_T);
367 }
368 ConstElementPtr boot = elem->get("boot-file-name");
369 if (boot) {
370 setItem(xpath + "/boot-file-name", boot, SR_STRING_T);
371 }
372 ConstElementPtr s4o6_if = elem->get("4o6-interface");
373 if (s4o6_if) {
374 setItem(xpath + "/subnet-4o6-interface", s4o6_if, SR_STRING_T);
375 }
376 ConstElementPtr s4o6_id = elem->get("4o6-interface-id");
377 if (s4o6_id) {
378 setItem(xpath + "/subnet-4o6-interface-id", s4o6_id, SR_STRING_T);
379 }
380 ConstElementPtr s4o6_subnet = elem->get("4o6-subnet");
381 if (s4o6_subnet) {
382 setItem(xpath + "/subnet-4o6-subnet", s4o6_subnet, SR_STRING_T);
383 }
384 }
385 ConstElementPtr context = Adaptor::getContext(elem);
386 if (context) {
387 ConstElementPtr repr = Element::create(context->str());
388 setItem(xpath + "/user-context", repr, SR_STRING_T);
389 }
390}
391
392TranslatorSubnets::TranslatorSubnets(S_Session session, const string& model)
393 : TranslatorBasic(session, model),
394 TranslatorOptionData(session, model),
395 TranslatorOptionDataList(session, model),
396 TranslatorPool(session, model),
397 TranslatorPools(session, model),
398 TranslatorPdPool(session, model),
399 TranslatorPdPools(session, model),
400 TranslatorHost(session, model),
401 TranslatorHosts(session, model),
402 TranslatorSubnet(session, model) {
403}
404
406}
407
409TranslatorSubnets::getSubnets(const string& xpath) {
410 try {
411 if (model_ == IETF_DHCPV6_SERVER) {
412 return (getSubnetsCommon(xpath, "network-range"));
413 } else if (model_ == KEA_DHCP4_SERVER) {
414 return (getSubnetsCommon(xpath, "subnet4"));
415 } else if (model_ == KEA_DHCP6_SERVER) {
416 return (getSubnetsCommon(xpath, "subnet6"));
417 }
418 } catch (const sysrepo_exception& ex) {
420 "sysrepo error getting subnets at '" << xpath
421 << "': " << ex.what());
422 }
424 "getSubnets not implemented for the model: " << model_);
425}
426
429 const std::string& subsel) {
431 S_Iter_Value iter = getIter(xpath + "/" + subsel);
432 if (!iter) {
434 isc_throw(Unexpected, "getSubnets: can't get iterator: " << xpath);
435 }
436 for (;;) {
437 const string& subnet = getNext(iter);
438 if (subnet.empty()) {
439 break;
440 }
441 result->add(getSubnet(subnet));
442 }
443 return (result);
444}
445
446void
448 try {
449 if (model_ == IETF_DHCPV6_SERVER) {
450 setSubnetsIetf6(xpath, elem);
451 } else if (model_ == KEA_DHCP4_SERVER) {
452 setSubnetsKea(xpath, elem, "subnet4");
453 } else if (model_ == KEA_DHCP6_SERVER) {
454 setSubnetsKea(xpath, elem, "subnet6");
455 } else {
457 "setSubnets not implemented for the model: " << model_);
458 }
459 } catch (const sysrepo_exception& ex) {
461 "sysrepo error setting subnets '" << elem->str()
462 << "' at '" << xpath << "': " << ex.what());
463 }
464}
465
466void
468 for (size_t i = 0; i < elem->size(); ++i) {
469 ConstElementPtr subnet = elem->get(i);
470 ostringstream range;
471 range << xpath << "/network-range[network-range-id='";
472 ConstElementPtr id = subnet->get("id");
473 if (!id) {
474 isc_throw(BadValue, "subnet without id: " << elem->str());
475 }
476 range << id->intValue() << "']";
477 setSubnet(range.str().c_str(), subnet);
478 }
479}
480
481void
483 const std::string& subsel) {
484 for (size_t i = 0; i < elem->size(); ++i) {
485 ConstElementPtr subnet = elem->get(i);
486 if (!subnet->contains("id")) {
487 isc_throw(BadValue, "subnet without id: " << subnet->str());
488 }
489 ostringstream prefix;
490 prefix << xpath << "/" << subsel << "[id='"
491 << subnet->get("id")->intValue() << "']";
492 setSubnet(prefix.str(), subnet);
493 }
494}
495
496}; // end of namespace isc::yang
497}; // end of 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.
A generic exception that is thrown when an unexpected error condition occurs.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:223
static ElementPtr fromJSON(const std::string &in, bool preproc=false)
These functions will parse the given string (JSON) representation of a compound element.
Definition: data.cc:750
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:268
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:263
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:65
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:45
static isc::data::ConstElementPtr getContext(isc::data::ConstElementPtr parent)
Get user context.
Definition: adaptor.cc:25
Between YANG and JSON translator class for basic values.
Definition: translator.h:27
std::string getNext(sysrepo::S_Iter_Value iter)
Get xpath of the next YANG list item.
Definition: translator.cc:283
isc::data::ElementPtr getItem(const std::string &xpath)
Get and translate basic value from YANG to JSON.
Definition: translator.cc:104
sysrepo::S_Iter_Value getIter(const std::string &xpath)
List iterator methods keeping the session private.
Definition: translator.cc:278
std::string model_
The model.
Definition: translator.h:132
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:250
isc::data::ElementPtr getItems(const std::string &xpath)
Get and translate a list of basic values from YANG to JSON.
Definition: translator.cc:119
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:23
boost::shared_ptr< Element > ElementPtr
Definition: data.h:22
Defines the logger used by the top-level component of kea-dhcp-ddns.