Kea 2.2.0
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
15using namespace std;
16using namespace isc::data;
17using namespace sysrepo;
18
19namespace isc {
20namespace yang {
21
22TranslatorPdPool::TranslatorPdPool(S_Session session, const string& model)
23 : TranslatorBasic(session, model),
24 TranslatorOptionData(session, model),
25 TranslatorOptionDataList(session, model) {
26}
27
29}
30
32TranslatorPdPool::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
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
102TranslatorPdPool::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
180void
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
198void
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
240void
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
287TranslatorPdPools::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
298TranslatorPdPools::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
319void
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
337void
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
347void
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
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 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:171
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
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.
TranslatorPdPool(sysrepo::S_Session session, const std::string &model)
Constructor.
void setPdPoolIetf6(const std::string &xpath, isc::data::ConstElementPtr elem)
setPdPool for ietf-dhcpv6-server.
virtual ~TranslatorPdPool()
Destructor.
isc::data::ElementPtr getPdPool(const std::string &xpath)
Get and translate a pd-pool from YANG to JSON.
isc::data::ElementPtr getPdPoolKea(const std::string &xpath)
getPdPool for kea-dhcp6-server.
void setPdPool(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set pd-pool from JSON to YANG.
void setPdPoolKea(const std::string &xpath, isc::data::ConstElementPtr elem)
setPdPool for kea-dhcp6-server.
isc::data::ElementPtr getPdPoolIetf6(const std::string &xpath)
getPdPool for ietf-dhcpv6-server.
void setPdPoolsId(const std::string &xpath, isc::data::ConstElementPtr elem)
setPdPools using pool-id.
void setPdPoolsPrefix(const std::string &xpath, isc::data::ConstElementPtr elem)
setPdPools using prefix.
void setPdPools(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set pd-pools from JSON to YANG.
isc::data::ElementPtr getPdPoolsCommon(const std::string &xpath)
getPdPools common part.
isc::data::ElementPtr getPdPools(const std::string &xpath)
Get and translate pd-pools from YANG to JSON.
virtual ~TranslatorPdPools()
Destructor.
TranslatorPdPools(sysrepo::S_Session session, const std::string &model)
Constructor.
#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.