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 
14 using namespace std;
15 using namespace isc::data;
16 #ifndef HAVE_PRE_0_7_6_SYSREPO
17 using namespace sysrepo;
18 #endif
19 
20 namespace isc {
21 namespace yang {
22 
23 TranslatorSubnet::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 
39 TranslatorSubnet::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 
57 TranslatorSubnet::getSubnetIetf6(const string& xpath) {
58  ElementPtr result = Element::createMap();
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) {
85  ElementPtr context = Element::createMap();
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 
95 TranslatorSubnet::getSubnetKea(const string& xpath) {
96  ElementPtr result = Element::createMap();
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 
218 void
219 TranslatorSubnet::setSubnet(const string& xpath, ConstElementPtr elem) {
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 
237 void
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 
265 void
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 
392 TranslatorSubnets::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 
409 TranslatorSubnets::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) {
430  ElementPtr result = Element::createList();
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 
446 void
447 TranslatorSubnets::setSubnets(const string& xpath, ConstElementPtr elem) {
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 
466 void
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 
481 void
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
isc::data::ElementPtr getItems(const std::string &xpath)
Get and translate a list of basic values from YANG to JSON.
Definition: translator.cc:119
virtual ~TranslatorSubnet()
Destructor.
isc::data::ElementPtr getHosts(const std::string &xpath)
Get and translate host reservations from YANG to JSON.
Subnet (aka network range) translation between YANG and JSON.
A generic exception that is thrown when a function is not implemented.
Between YANG and JSON translator class for basic values.
Definition: translator.h:27
isc::data::ElementPtr getSubnet(const std::string &xpath)
Get and translate a subnet from YANG to JSON.
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
void setSubnetKea(const std::string &xpath, isc::data::ConstElementPtr elem)
setSubnet for kea-dhcp[46]-server.
A translator class for converting a pd-pool list between YANG and JSON.
isc::data::ElementPtr getPdPools(const std::string &xpath)
Get and translate pd-pools from YANG to JSON.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
sysrepo::S_Iter_Value getIter(const std::string &xpath)
List iterator methods keeping the session private.
Definition: translator.cc:278
TranslatorSubnets(sysrepo::S_Session session, const std::string &model)
Constructor.
void setPools(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set (address) pools from JSON to YANG.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
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
Translation between YANG and JSON for a single host reservation.
isc::data::ElementPtr getSubnetsCommon(const std::string &xpath, const std::string &subsel)
getSubnets common part.
A translator class for converting an option data list between YANG and JSON.
A generic exception that is thrown when an unexpected error condition occurs.
isc::data::ElementPtr getSubnets(const std::string &xpath)
Get and translate subnets from YANG to JSON.
std::string model_
The model.
Definition: translator.h:132
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
std::string getNext(sysrepo::S_Iter_Value iter)
Get xpath of the next YANG list item.
Definition: translator.cc:283
void setPdPools(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set pd-pools from JSON to YANG.
static isc::data::ConstElementPtr getContext(isc::data::ConstElementPtr parent)
Get user context.
Definition: adaptor.cc:25
isc::data::ElementPtr getSubnetKea(const std::string &xpath)
getSubnet for kea-dhcp[46]-server.
Defines the logger used by the top-level component of kea-dhcp-ddns.
isc::data::ConstElementPtr getOptionDataList(const std::string &xpath)
Get and translate option data list from YANG to JSON.
isc::data::ElementPtr getItem(const std::string &xpath)
Get and translate basic value from YANG to JSON.
Definition: translator.cc:104
Prefix delegation pool translation between YANG and JSON.
A translator class for converting a pool between YANG and JSON.
void setSubnetsIetf6(const std::string &xpath, isc::data::ConstElementPtr elem)
setSubnets for ietf-dhcpv6-server.
void setSubnet(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set subnet from JSON to YANG.
virtual ~TranslatorSubnets()
Destructor.
A translator class for converting pools between YANG and JSON.
void setSubnets(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set subnets from JSON to YANG.
isc::data::ElementPtr getPools(const std::string &xpath)
Get and translate pools from YANG to JSON.
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
Option data translation between YANG and JSON.
void setOptionDataList(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set option data list from JSON to YANG.
void setSubnetIetf6(const std::string &xpath, isc::data::ConstElementPtr elem)
setSubnet for ietf-dhcpv6-server.
void setSubnetsKea(const std::string &xpath, isc::data::ConstElementPtr elem, const std::string &subsel)
setSubnets for kea-dhcp[46]-server.
A translator class for converting host reservations list between YANG and JSON.
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
isc::data::ElementPtr getSubnetIetf6(const std::string &xpath)
getSubnet for ietf-dhcpv6-server.
void setHosts(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set (address) host reservations from JSON to YANG.