Kea 1.5.0
translator_pd_pool.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
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;
17#ifndef HAVE_PRE_0_7_6_SYSREPO
18using namespace sysrepo;
19#endif
20
21namespace isc {
22namespace yang {
23
24TranslatorPdPool::TranslatorPdPool(S_Session session, const string& model)
25 : TranslatorBasic(session, model),
26 TranslatorOptionData(session, model),
27 TranslatorOptionDataList(session, model) {
28}
29
31}
32
34TranslatorPdPool::getPdPool(const string& xpath) {
35 try {
36 if (model_ == IETF_DHCPV6_SERVER) {
37 return (getPdPoolIetf6(xpath));
38 } else if (model_ == KEA_DHCP6_SERVER) {
39 return (getPdPoolKea(xpath));
40 }
41 } catch (const sysrepo_exception& ex) {
43 "sysrepo error getting pd-pool at '" << xpath
44 << "': " << ex.what());
45 }
47 "getPdPool not implemented for the model: " << model_);
48}
49
53 ConstElementPtr pref = getItem(xpath + "/prefix");
54 if (!pref) {
55 isc_throw(BadValue, "getPdPoolIetf6: prefix is required");
56 }
57 const string& prefix = pref->stringValue();
58 size_t slash = prefix.find("/");
59 if (slash == string::npos) {
61 "getPdPoolIetf6: no '/' in prefix '" << prefix << "'");
62 }
63 const string& address = prefix.substr(0, slash);
64 if (address.empty()) {
66 "getPdPoolIetf6: malformed prefix '" << prefix << "'");
67 }
68 result->set("prefix", Element::create(address));
69 // Silly: the prefix length is specified twice...
70 ConstElementPtr preflen = getItem(xpath + "/prefix-length");
71 if (!preflen) {
72 isc_throw(BadValue, "getPdPoolIetf6: prefix length is required");
73 }
74 result->set("prefix-len", preflen);
75 ConstElementPtr valid_lifetime = getItem(xpath + "/valid-lifetime");
76 if (valid_lifetime) {
77 result->set("valid-lifetime", valid_lifetime);
78 }
79 ConstElementPtr preferred_lifetime =
80 getItem(xpath + "/preferred-lifetime");
81 if (preferred_lifetime) {
82 result->set("preferred-lifetime", preferred_lifetime);
83 }
84 ConstElementPtr renew_time = getItem(xpath + "/renew-time");
85 if (renew_time) {
86 result->set("renew-timer", renew_time);
87 }
88 ConstElementPtr rebind_time = getItem(xpath + "/rebind-time");
89 if (rebind_time) {
90 result->set("rebind-timer", rebind_time);
91 }
92 // Skip rapid-commit.
93 ConstElementPtr guard = getItem(xpath + "/client-class");
94 if (guard) {
95 result->set("client-class", guard);
96 }
97 // no require-client-classes nor user-context.
98 // Skip max-pd-space-utilization.
99 // @todo option-data.
100 return (result);
101}
102
104TranslatorPdPool::getPdPoolKea(const string& xpath) {
106 ConstElementPtr pref = getItem(xpath + "/prefix");
107 if (!pref) {
108 isc_throw(BadValue, "getPdPoolKea: no prefix defined at " << xpath);
109 }
110 const string& prefix = pref->stringValue();
111 size_t slash = prefix.find("/");
112 if (slash == string::npos) {
114 "getPdPoolKea: no '/' in prefix '" << prefix << "'");
115 }
116 const string& address = prefix.substr(0, slash);
117 const string& length = prefix.substr(slash + 1, string::npos);
118 if (address.empty() || length.empty()) {
120 "getPdPoolKea: malformed prefix '" << prefix << "'");
121 }
122 result->set("prefix", Element::create(address));
123 try {
124 unsigned len = boost::lexical_cast<unsigned>(length);
125 result->set("prefix-len", Element::create(static_cast<int>(len)));
126 } catch (const boost::bad_lexical_cast&) {
128 "getPdPoolKea: bad prefix length in '" << prefix << "'");
129 }
130
131 ConstElementPtr xpref = getItem(xpath + "/excluded-prefix");
132 if (xpref) {
133 const string& xprefix = xpref->stringValue();
134 size_t xslash = xprefix.find("/");
135 if (xslash == string::npos) {
137 "getPdPoolKea: no '/' in excluded prefix '"
138 << xprefix << "'");
139 }
140 const string& xaddress = xprefix.substr(0, xslash);
141 const string& xlength = xprefix.substr(xslash + 1, string::npos);
142 if (xaddress.empty() || xlength.empty()) {
144 "getPdPoolKea: malformed excluded prefix '"
145 << xprefix << "'");
146 }
147 result->set("excluded-prefix", Element::create(xaddress));
148 try {
149 unsigned xlen = boost::lexical_cast<unsigned>(xlength);
150 result->set("excluded-prefix-len",
151 Element::create(static_cast<int>(xlen)));
152 } catch (const boost::bad_lexical_cast&) {
154 "getPdPoolKea: bad excluded prefix length in '"
155 << xprefix << "'");
156 }
157 }
158
159 ConstElementPtr delegated = getItem(xpath + "/delegated-len");
160 if (delegated) {
161 result->set("delegated-len", delegated);
162 }
163 ConstElementPtr options = getOptionDataList(xpath);
164 if (options && (options->size() > 0)) {
165 result->set("option-data", options);
166 }
167 ConstElementPtr guard = getItem(xpath + "/client-class");
168 if (guard) {
169 result->set("client-class", guard);
170 }
171 ConstElementPtr required = getItems(xpath + "/require-client-classes");
172 if (required && (required->size() > 0)) {
173 result->set("require-client-classes", required);
174 }
175 ConstElementPtr context = getItem(xpath + "/user-context");
176 if (context) {
177 result->set("user-context", Element::fromJSON(context->stringValue()));
178 }
179 return (result);
180}
181
182void
184 try {
185 if (model_ == IETF_DHCPV6_SERVER) {
186 setPdPoolIetf6(xpath, elem);
187 } else if (model_ == KEA_DHCP6_SERVER) {
188 setPdPoolKea(xpath, elem);
189 } else {
191 "setPdPool not implemented for the model: " << model_);
192 }
193 } catch (const sysrepo_exception& ex) {
195 "sysrepo error setting pd-pool '" << elem->str()
196 << "' at '" << xpath << "': " << ex.what());
197 }
198}
199
200void
202 ConstElementPtr base = elem->get("prefix");
203 ConstElementPtr length = elem->get("prefix-len");
204 if (!base || !length) {
206 "setPdPoolIetf6 requires prefix and prefix length: "
207 << elem->str());
208 }
209 ostringstream prefix;
210 prefix << base->stringValue() << "/" << length->intValue();
211 setItem(xpath + "/prefix", Element::create(prefix.str()), SR_STRING_T);
212 setItem(xpath + "/prefix-length", length, SR_UINT8_T);
213 ConstElementPtr valid_lifetime = elem->get("valid-lifetime");
214 if (valid_lifetime) {
215 setItem(xpath + "/valid-lifetime", valid_lifetime, SR_UINT32_T);
216 }
217 ConstElementPtr preferred_lifetime = elem->get("preferred-lifetime");
218 if (preferred_lifetime) {
219 setItem(xpath + "/preferred-lifetime",
220 preferred_lifetime, SR_UINT32_T);
221 }
222 ConstElementPtr renew_timer = elem->get("renew-timer");
223 if (renew_timer) {
224 setItem(xpath + "/renew-time", renew_timer, SR_UINT32_T);
225 }
226 ConstElementPtr rebind_timer = elem->get("rebind-timer");
227 if (rebind_timer) {
228 setItem(xpath + "/rebind-time", rebind_timer, SR_UINT32_T);
229 }
230 // Skip rapid-commit.
231 ConstElementPtr guard = elem->get("client-class");
232 if (guard) {
233 setItem(xpath + "/client-class", guard, SR_STRING_T);
234 }
235 // Set max pd space utilization to disabled.
236 setItem(xpath + "/max-pd-space-utilization",
237 Element::create(string("disabled")),
238 SR_ENUM_T);
239 // @todo option-data.
240}
241
242void
244 // Skip prefix as it is the key.
245 bool created = false;
246 ConstElementPtr delegated = elem->get("delegated-len");
247 if (delegated) {
248 setItem(xpath + "/delegated-len", delegated, SR_UINT8_T);
249 }
250 ConstElementPtr xprefix = elem->get("excluded-prefix");
251 ConstElementPtr xlen = elem->get("excluded-prefix-len");
252 if (xprefix && xlen) {
253 ostringstream xpref;
254 xpref << xprefix->stringValue() << "/" << xlen->intValue();
255 setItem(xpath + "/excluded-prefix", Element::create(xpref.str()),
256 SR_STRING_T);
257 created = true;
258 }
259 ConstElementPtr options = elem->get("option-data");
260 if (options && (options->size() > 0)) {
261 setOptionDataList(xpath, options);
262 created = true;
263 }
264 ConstElementPtr guard = elem->get("client-class");
265 if (guard) {
266 setItem(xpath + "/client-class", guard, SR_STRING_T);
267 created = true;
268 }
269 ConstElementPtr required = elem->get("require-client-classes");
270 if (required && (required->size() > 0)) {
271 for (ConstElementPtr rclass : required->listValue()) {
272 setItem(xpath + "/require-client-classes", rclass, SR_STRING_T);
273 created = true;
274 }
275 }
276 ConstElementPtr context = Adaptor::getContext(elem);
277 if (context) {
278 setItem(xpath + "/user-context", Element::create(context->str()),
279 SR_STRING_T);
280 created = true;
281 }
282 // There is no mandatory fields outside the keys so force creation.
283 if (!created) {
285 setItem(xpath, list, SR_LIST_T);
286 }
287}
288
289TranslatorPdPools::TranslatorPdPools(S_Session session, const string& model)
290 : TranslatorBasic(session, model),
291 TranslatorOptionData(session, model),
292 TranslatorOptionDataList(session, model),
293 TranslatorPdPool(session, model) {
294}
295
297}
298
300TranslatorPdPools::getPdPools(const string& xpath) {
301 try {
302 if ((model_ == IETF_DHCPV6_SERVER) ||
303 (model_ == KEA_DHCP6_SERVER)) {
304 return (getPdPoolsCommon(xpath));
305 }
306 } catch (const sysrepo_exception& ex) {
308 "sysrepo error getting pd-pools at '" << xpath
309 << "': " << ex.what());
310 }
312 "getPdPools not implemented for the model: " << model_);
313}
314
318 S_Iter_Value iter = getIter(xpath + "/pd-pool");
319 if (!iter) {
320 // Can't happen.
321 isc_throw(Unexpected, "getPdPools: can't get iterator: " << xpath);
322 }
323 for (;;) {
324 const string& pool = getNext(iter);
325 if (pool.empty()) {
326 break;
327 }
328 result->add(getPdPool(pool));
329 }
330 return (result);
331}
332
333void
335 try {
336 if (model_ == IETF_DHCPV6_SERVER) {
337 setPdPoolsId(xpath, elem);
338 } else if (model_ == KEA_DHCP6_SERVER) {
339 setPdPoolsPrefix(xpath, elem);
340 } else {
342 "setPdPools not implemented for the model: " << model_);
343 }
344 } catch (const sysrepo_exception& ex) {
346 "sysrepo error setting pools '" << elem->str()
347 << "' at '" << xpath << "': " << ex.what());
348 }
349}
350
351void
353 for (size_t i = 0; i < elem->size(); ++i) {
354 ConstElementPtr pool = elem->get(i);
355 ostringstream prefix;
356 prefix << xpath << "/pd-pool[pool-id='" << i << "']";
357 setPdPool(prefix.str(), pool);
358 }
359}
360
361void
363 ConstElementPtr elem) {
364 for (size_t i = 0; i < elem->size(); ++i) {
365 ConstElementPtr pool = elem->get(i);
366 if (!pool->contains("prefix") || !pool->contains("prefix-len")) {
367 isc_throw(BadValue, "pd-pool requires prefix and prefix length: "
368 << pool->str());
369 }
370 ostringstream prefix;
371 prefix << xpath << "/pd-pool[prefix='"
372 << pool->get("prefix")->stringValue() << "/"
373 << pool->get("prefix-len")->intValue() << "']";
374 setPdPool(prefix.str(), pool);
375 }
376}
377
378}; // end of namespace isc::yang
379}; // 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 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
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:23
boost::shared_ptr< Element > ElementPtr
Definition: data.h:22
Defines the logger used by the top-level component of kea-dhcp-ddns.