Kea  2.1.7-git
translator_pd_pool.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.h>
11 #include <yang/yang_models.h>
12 #include <boost/lexical_cast.hpp>
13 #include <sstream>
14 
15 using namespace std;
16 using namespace isc::data;
17 using namespace sysrepo;
18 
19 namespace isc {
20 namespace yang {
21 
22 TranslatorPdPool::TranslatorPdPool(S_Session session, const string& model)
23  : TranslatorBasic(session, model),
24  TranslatorOptionData(session, model),
25  TranslatorOptionDataList(session, model) {
26 }
27 
29 }
30 
32 TranslatorPdPool::getPdPool(const string& xpath) {
33  try {
34  if (model_ == IETF_DHCPV6_SERVER) {
35  return (getPdPoolIetf6(xpath));
36  } else if (model_ == KEA_DHCP6_SERVER) {
37  return (getPdPoolKea(xpath));
38  }
39  } catch (const sysrepo_exception& ex) {
41  "sysrepo error getting pd-pool at '" << xpath
42  << "': " << ex.what());
43  }
45  "getPdPool not implemented for the model: " << model_);
46 }
47 
49 TranslatorPdPool::getPdPoolIetf6(const string& xpath) {
50  ElementPtr result = Element::createMap();
51  ConstElementPtr pref = getItem(xpath + "/prefix");
52  if (!pref) {
53  isc_throw(BadValue, "getPdPoolIetf6: prefix is required");
54  }
55  const string& prefix = pref->stringValue();
56  size_t slash = prefix.find("/");
57  if (slash == string::npos) {
59  "getPdPoolIetf6: no '/' in prefix '" << prefix << "'");
60  }
61  const string& address = prefix.substr(0, slash);
62  if (address.empty()) {
64  "getPdPoolIetf6: malformed prefix '" << prefix << "'");
65  }
66  result->set("prefix", Element::create(address));
67  // Silly: the prefix length is specified twice...
68  ConstElementPtr preflen = getItem(xpath + "/prefix-length");
69  if (!preflen) {
70  isc_throw(BadValue, "getPdPoolIetf6: prefix length is required");
71  }
72  result->set("prefix-len", preflen);
73  ConstElementPtr valid_lifetime = getItem(xpath + "/valid-lifetime");
74  if (valid_lifetime) {
75  result->set("valid-lifetime", valid_lifetime);
76  }
77  ConstElementPtr preferred_lifetime =
78  getItem(xpath + "/preferred-lifetime");
79  if (preferred_lifetime) {
80  result->set("preferred-lifetime", preferred_lifetime);
81  }
82  ConstElementPtr renew_time = getItem(xpath + "/renew-time");
83  if (renew_time) {
84  result->set("renew-timer", renew_time);
85  }
86  ConstElementPtr rebind_time = getItem(xpath + "/rebind-time");
87  if (rebind_time) {
88  result->set("rebind-timer", rebind_time);
89  }
90  // Skip rapid-commit.
91  ConstElementPtr guard = getItem(xpath + "/client-class");
92  if (guard) {
93  result->set("client-class", guard);
94  }
95  // no require-client-classes nor user-context.
96  // Skip max-pd-space-utilization.
97  // @todo option-data.
98  return (result);
99 }
100 
102 TranslatorPdPool::getPdPoolKea(const string& xpath) {
103  ElementPtr result = Element::createMap();
104  ConstElementPtr pref = getItem(xpath + "/prefix");
105  if (!pref) {
106  isc_throw(BadValue, "getPdPoolKea: no prefix defined at " << xpath);
107  }
108  const string& prefix = pref->stringValue();
109  size_t slash = prefix.find("/");
110  if (slash == string::npos) {
112  "getPdPoolKea: no '/' in prefix '" << prefix << "'");
113  }
114  const string& address = prefix.substr(0, slash);
115  const string& length = prefix.substr(slash + 1, string::npos);
116  if (address.empty() || length.empty()) {
118  "getPdPoolKea: malformed prefix '" << prefix << "'");
119  }
120  result->set("prefix", Element::create(address));
121  try {
122  unsigned len = boost::lexical_cast<unsigned>(length);
123  result->set("prefix-len", Element::create(static_cast<int>(len)));
124  } catch (const boost::bad_lexical_cast&) {
126  "getPdPoolKea: bad prefix length in '" << prefix << "'");
127  }
128 
129  ConstElementPtr xpref = getItem(xpath + "/excluded-prefix");
130  if (xpref) {
131  const string& xprefix = xpref->stringValue();
132  size_t xslash = xprefix.find("/");
133  if (xslash == string::npos) {
135  "getPdPoolKea: no '/' in excluded prefix '"
136  << xprefix << "'");
137  }
138  const string& xaddress = xprefix.substr(0, xslash);
139  const string& xlength = xprefix.substr(xslash + 1, string::npos);
140  if (xaddress.empty() || xlength.empty()) {
142  "getPdPoolKea: malformed excluded prefix '"
143  << xprefix << "'");
144  }
145  result->set("excluded-prefix", Element::create(xaddress));
146  try {
147  unsigned xlen = boost::lexical_cast<unsigned>(xlength);
148  result->set("excluded-prefix-len",
149  Element::create(static_cast<int>(xlen)));
150  } catch (const boost::bad_lexical_cast&) {
152  "getPdPoolKea: bad excluded prefix length in '"
153  << xprefix << "'");
154  }
155  }
156 
157  ConstElementPtr delegated = getItem(xpath + "/delegated-len");
158  if (delegated) {
159  result->set("delegated-len", delegated);
160  }
161  ConstElementPtr options = getOptionDataList(xpath);
162  if (options && (options->size() > 0)) {
163  result->set("option-data", options);
164  }
165  ConstElementPtr guard = getItem(xpath + "/client-class");
166  if (guard) {
167  result->set("client-class", guard);
168  }
169  ConstElementPtr required = getItems(xpath + "/require-client-classes");
170  if (required && (required->size() > 0)) {
171  result->set("require-client-classes", required);
172  }
173  ConstElementPtr context = getItem(xpath + "/user-context");
174  if (context) {
175  result->set("user-context", Element::fromJSON(context->stringValue()));
176  }
177  return (result);
178 }
179 
180 void
181 TranslatorPdPool::setPdPool(const string& xpath, ConstElementPtr elem) {
182  try {
183  if (model_ == IETF_DHCPV6_SERVER) {
184  setPdPoolIetf6(xpath, elem);
185  } else if (model_ == KEA_DHCP6_SERVER) {
186  setPdPoolKea(xpath, elem);
187  } else {
189  "setPdPool not implemented for the model: " << model_);
190  }
191  } catch (const sysrepo_exception& ex) {
193  "sysrepo error setting pd-pool '" << elem->str()
194  << "' at '" << xpath << "': " << ex.what());
195  }
196 }
197 
198 void
200  ConstElementPtr base = elem->get("prefix");
201  ConstElementPtr length = elem->get("prefix-len");
202  if (!base || !length) {
204  "setPdPoolIetf6 requires prefix and prefix length: "
205  << elem->str());
206  }
207  ostringstream prefix;
208  prefix << base->stringValue() << "/" << length->intValue();
209  setItem(xpath + "/prefix", Element::create(prefix.str()), SR_STRING_T);
210  setItem(xpath + "/prefix-length", length, SR_UINT8_T);
211  ConstElementPtr valid_lifetime = elem->get("valid-lifetime");
212  if (valid_lifetime) {
213  setItem(xpath + "/valid-lifetime", valid_lifetime, SR_UINT32_T);
214  }
215  ConstElementPtr preferred_lifetime = elem->get("preferred-lifetime");
216  if (preferred_lifetime) {
217  setItem(xpath + "/preferred-lifetime",
218  preferred_lifetime, SR_UINT32_T);
219  }
220  ConstElementPtr renew_timer = elem->get("renew-timer");
221  if (renew_timer) {
222  setItem(xpath + "/renew-time", renew_timer, SR_UINT32_T);
223  }
224  ConstElementPtr rebind_timer = elem->get("rebind-timer");
225  if (rebind_timer) {
226  setItem(xpath + "/rebind-time", rebind_timer, SR_UINT32_T);
227  }
228  // Skip rapid-commit.
229  ConstElementPtr guard = elem->get("client-class");
230  if (guard) {
231  setItem(xpath + "/client-class", guard, SR_STRING_T);
232  }
233  // Set max pd space utilization to disabled.
234  setItem(xpath + "/max-pd-space-utilization",
235  Element::create(string("disabled")),
236  SR_ENUM_T);
237  // @todo option-data.
238 }
239 
240 void
242  // Skip prefix as it is the key.
243  bool created = false;
244  ConstElementPtr delegated = elem->get("delegated-len");
245  if (delegated) {
246  setItem(xpath + "/delegated-len", delegated, SR_UINT8_T);
247  }
248  ConstElementPtr xprefix = elem->get("excluded-prefix");
249  ConstElementPtr xlen = elem->get("excluded-prefix-len");
250  if (xprefix && xlen) {
251  ostringstream xpref;
252  xpref << xprefix->stringValue() << "/" << xlen->intValue();
253  setItem(xpath + "/excluded-prefix", Element::create(xpref.str()),
254  SR_STRING_T);
255  created = true;
256  }
257  ConstElementPtr options = elem->get("option-data");
258  if (options && (options->size() > 0)) {
259  setOptionDataList(xpath, options);
260  created = true;
261  }
262  ConstElementPtr guard = elem->get("client-class");
263  if (guard) {
264  setItem(xpath + "/client-class", guard, SR_STRING_T);
265  created = true;
266  }
267  ConstElementPtr required = elem->get("require-client-classes");
268  if (required && (required->size() > 0)) {
269  for (ConstElementPtr rclass : required->listValue()) {
270  setItem(xpath + "/require-client-classes", rclass, SR_STRING_T);
271  created = true;
272  }
273  }
274  ConstElementPtr context = Adaptor::getContext(elem);
275  if (context) {
276  setItem(xpath + "/user-context", Element::create(context->str()),
277  SR_STRING_T);
278  created = true;
279  }
280  // There is no mandatory fields outside the keys so force creation.
281  if (!created) {
282  ConstElementPtr list = Element::createList();
283  setItem(xpath, list, SR_LIST_T);
284  }
285 }
286 
287 TranslatorPdPools::TranslatorPdPools(S_Session session, const string& model)
288  : TranslatorBasic(session, model),
289  TranslatorOptionData(session, model),
290  TranslatorOptionDataList(session, model),
291  TranslatorPdPool(session, model) {
292 }
293 
295 }
296 
298 TranslatorPdPools::getPdPools(const string& xpath) {
299  try {
300  if ((model_ == IETF_DHCPV6_SERVER) ||
301  (model_ == KEA_DHCP6_SERVER)) {
302  return (getPdPoolsCommon(xpath));
303  }
304  } catch (const sysrepo_exception& ex) {
306  "sysrepo error getting pd-pools at '" << xpath
307  << "': " << ex.what());
308  }
310  "getPdPools not implemented for the model: " << model_);
311 }
312 
315  return getList<TranslatorPdPool>(xpath + "/pd-pool", *this,
317 }
318 
319 void
320 TranslatorPdPools::setPdPools(const string& xpath, ConstElementPtr elem) {
321  try {
322  if (model_ == IETF_DHCPV6_SERVER) {
323  setPdPoolsId(xpath, elem);
324  } else if (model_ == KEA_DHCP6_SERVER) {
325  setPdPoolsPrefix(xpath, elem);
326  } else {
328  "setPdPools not implemented for the model: " << model_);
329  }
330  } catch (const sysrepo_exception& ex) {
332  "sysrepo error setting pools '" << elem->str()
333  << "' at '" << xpath << "': " << ex.what());
334  }
335 }
336 
337 void
339  for (size_t i = 0; i < elem->size(); ++i) {
340  ConstElementPtr pool = elem->get(i);
341  ostringstream prefix;
342  prefix << xpath << "/pd-pool[pool-id='" << i << "']";
343  setPdPool(prefix.str(), pool);
344  }
345 }
346 
347 void
349  ConstElementPtr elem) {
350  for (size_t i = 0; i < elem->size(); ++i) {
351  ConstElementPtr pool = elem->get(i);
352  if (!pool->contains("prefix") || !pool->contains("prefix-len")) {
353  isc_throw(BadValue, "pd-pool requires prefix and prefix length: "
354  << pool->str());
355  }
356  ostringstream prefix;
357  prefix << xpath << "/pd-pool[prefix='"
358  << pool->get("prefix")->stringValue() << "/"
359  << pool->get("prefix-len")->intValue() << "']";
360  setPdPool(prefix.str(), pool);
361  }
362 }
363 
364 } // namespace yang
365 } // 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:124
A generic exception that is thrown when a function is not implemented.
isc::data::ElementPtr getPdPoolsCommon(const std::string &xpath)
getPdPools common part.
Between YANG and JSON translator class for basic values.
Definition: translator.h:19
void setPdPool(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set pd-pool from JSON to YANG.
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
STL namespace.
TranslatorPdPools(sysrepo::S_Session session, const std::string &model)
Constructor.
virtual ~TranslatorPdPool()
Destructor.
virtual ~TranslatorPdPools()
Destructor.
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.
#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:260
isc::data::ElementPtr getPdPoolIetf6(const std::string &xpath)
getPdPool for ietf-dhcpv6-server.
A translator class for converting an option data list between YANG and JSON.
std::string model_
The model.
Definition: translator.h:171
isc::data::ElementPtr getPdPool(const std::string &xpath)
Get and translate a pd-pool from YANG to JSON.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
void setPdPoolsId(const std::string &xpath, isc::data::ConstElementPtr elem)
setPdPools using pool-id.
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:27
Defines the logger used by the top-level component of kea-lfc.
isc::data::ConstElementPtr getOptionDataList(const std::string &xpath)
Get and translate option data list from YANG to JSON.
void setPdPoolIetf6(const std::string &xpath, isc::data::ConstElementPtr elem)
setPdPool for ietf-dhcpv6-server.
isc::data::ElementPtr getItem(const std::string &xpath)
Get and translate basic value from YANG to JSON.
Definition: translator.cc:105
Prefix delegation pool translation between YANG and JSON.
isc::data::ElementPtr getPdPoolKea(const std::string &xpath)
getPdPool for kea-dhcp6-server.
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 setPdPoolsPrefix(const std::string &xpath, isc::data::ConstElementPtr elem)
setPdPools using prefix.
void setPdPoolKea(const std::string &xpath, isc::data::ConstElementPtr elem)
setPdPool for kea-dhcp6-server.