Kea  1.9.9-git
translator_host.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/translator_host.h>
10 #include <yang/adaptor.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 TranslatorHost::TranslatorHost(S_Session session, const string& model)
24  : TranslatorBasic(session, model),
25  TranslatorOptionData(session, model),
26  TranslatorOptionDataList(session, model) {
27 }
28 
30 }
31 
33  TranslatorHost::getHost(const string& xpath) {
34  try {
35  if ((model_ == KEA_DHCP4_SERVER) ||
36  (model_ == KEA_DHCP6_SERVER)) {
37  return (getHostKea(xpath));
38  }
39  } catch (const sysrepo_exception& ex) {
41  "sysrepo error getting host reservation at '" << xpath
42  << "': " << ex.what());
43  }
45  "getHost not implemented for the model: " << model_);
46 }
47 
49 TranslatorHost::getHostKea(const string& xpath) {
50  ConstElementPtr id_type = getItem(xpath + "/identifier-type");
51  ConstElementPtr id = getItem(xpath + "/identifier");
52  if (!id_type || !id) {
53  isc_throw(Unexpected, "getHostKea requires both identifier and "
54  "identifier-type");
55  }
56  ElementPtr result = Element::createMap();
57  result->set(id_type->stringValue(), id);
58  ConstElementPtr hostname = getItem(xpath + "/hostname");
59  if (hostname) {
60  result->set("hostname", hostname);
61  }
62  if (model_ == KEA_DHCP4_SERVER) {
63  ConstElementPtr address = getItem(xpath + "/ip-address");
64  if (address) {
65  result->set("ip-address", address);
66  }
67  } else {
68  ConstElementPtr addresses = getItems(xpath + "/ip-addresses");
69  if (addresses && (addresses->size() > 0)) {
70  result->set("ip-addresses", addresses);
71  }
72  ConstElementPtr prefixes = getItems(xpath + "/prefixes");
73  if (prefixes && (prefixes->size() > 0)) {
74  result->set("prefixes", prefixes);
75  }
76  }
77  ConstElementPtr options = getOptionDataList(xpath);
78  if (options && (options->size() > 0)) {
79  result->set("option-data", options);
80  }
81  ConstElementPtr classes = getItems(xpath + "/client-classes");
82  if (classes) {
83  result->set("client-classes", classes);
84  }
85  if (model_ == KEA_DHCP4_SERVER) {
86  ConstElementPtr next = getItem(xpath + "/next-server");
87  if (next) {
88  result->set("next-server", next);
89  }
90  ConstElementPtr hostname = getItem(xpath + "/server-hostname");
91  if (hostname) {
92  result->set("server-hostname", hostname);
93  }
94  ConstElementPtr boot = getItem(xpath + "/boot-file-name");
95  if (boot) {
96  result->set("boot-file-name", boot);
97  }
98  }
99  ConstElementPtr context = getItem(xpath + "/user-context");
100  if (context) {
101  result->set("user-context", Element::fromJSON(context->stringValue()));
102  }
103  return (result);
104 }
105 
106 void
107 TranslatorHost::setHost(const string& xpath, ConstElementPtr elem) {
108  try {
109  if ((model_ == KEA_DHCP4_SERVER) ||
110  (model_ == KEA_DHCP6_SERVER)) {
111  setHostKea(xpath, elem);
112  } else {
114  "setHost not implemented for the model: " << model_);
115  }
116  } catch (const sysrepo_exception& ex) {
118  "sysrepo error setting host reservation '" << elem->str()
119  << "' at '" << xpath << "': " << ex.what());
120  }
121 }
122 
123 void
124 TranslatorHost::setHostKea(const string& xpath, ConstElementPtr elem) {
125  ConstElementPtr hostname = elem->get("hostname");
126  // Skip identifier and identifier type as they are keys.
127  if (hostname) {
128  setItem(xpath + "/hostname", hostname, SR_STRING_T);
129  }
130  if (model_ == KEA_DHCP4_SERVER) {
131  ConstElementPtr address = elem->get("ip-address");
132  if (address) {
133  setItem(xpath + "/ip-address", address, SR_STRING_T);
134  }
135  } else {
136  ConstElementPtr addresses = elem->get("ip-addresses");
137  if (addresses && (addresses->size() > 0)) {
138  for (ConstElementPtr address : addresses->listValue()) {
139  setItem(xpath + "/ip-addresses", address, SR_STRING_T);
140  }
141  }
142  ConstElementPtr prefixes = elem->get("prefixes");
143  if (prefixes && (prefixes->size() > 0)) {
144  for (ConstElementPtr prefix : prefixes->listValue()) {
145  setItem(xpath + "/prefixes", prefix, SR_STRING_T);
146  }
147  }
148  }
149  ConstElementPtr options = elem->get("option-data");
150  if (options && (options->size() > 0)) {
151  setOptionDataList(xpath, options);
152  }
153  ConstElementPtr classes = elem->get("client-classes");
154  if (classes && (classes->size() > 0)) {
155  for (ConstElementPtr cclass : classes->listValue()) {
156  setItem(xpath + "/client-classes", cclass, SR_STRING_T);
157  }
158  }
159 
160  // These are DHCPv4-specific parameters.
161  if (model_ == KEA_DHCP4_SERVER) {
162  ConstElementPtr next = elem->get("next-server");
163  if (next) {
164  setItem(xpath + "/next-server", next, SR_STRING_T);
165  }
166  ConstElementPtr hostname = elem->get("server-hostname");
167  if (hostname) {
168  setItem(xpath + "/server-hostname", hostname, SR_STRING_T);
169  }
170  ConstElementPtr boot = elem->get("boot-file-name");
171  if (boot) {
172  setItem(xpath + "/boot-file-name", boot, SR_STRING_T);
173  }
174  }
175 
176  // User context is supported in both kea-dhcp4-server and kea-dhcp6-server.
177  ConstElementPtr context = Adaptor::getContext(elem);
178  if (context) {
179  setItem(xpath + "/user-context", Element::create(context->str()),
180  SR_STRING_T);
181  }
182 }
183 
184 TranslatorHosts::TranslatorHosts(S_Session session, const string& model)
185  : TranslatorBasic(session, model),
186  TranslatorOptionData(session, model),
187  TranslatorOptionDataList(session, model),
188  TranslatorHost(session, model) {
189 }
190 
192 }
193 
195 TranslatorHosts::getHosts(const string& xpath) {
196  try {
197  ElementPtr result = Element::createList();
198  S_Iter_Value iter = getIter(xpath + "/host");
199  if (!iter) {
200  // Can't happen.
201  isc_throw(Unexpected, "getHosts can't get iterator: " << xpath);
202  }
203  for (;;) {
204  const string& host = getNext(iter);
205  if (host.empty()) {
206  break;
207  }
208  result->add(getHost(host));
209  }
210  return (result);
211  } catch (const sysrepo_exception& ex) {
213  "sysrepo error getting host reservations at '" << xpath
214  << "': " << ex.what());
215  }
216 }
217 
218 void
219 TranslatorHosts::setHosts(const string& xpath, ConstElementPtr elem) {
220  try {
221  if ((model_ == KEA_DHCP4_SERVER) ||
222  (model_ == KEA_DHCP6_SERVER)) {
223  setHostsKea(xpath, elem);
224  } else {
226  "setHosts not implemented for the model: " << model_);
227  }
228  } catch (const sysrepo_exception& ex) {
230  "sysrepo error setting host reservations '" << elem->str()
231  << "' at '" << xpath << "': " << ex.what());
232  }
233 }
234 
235 void
236 TranslatorHosts::setHostsKea(const string& xpath, ConstElementPtr elem) {
237  for (size_t i = 0; i < elem->size(); ++i) {
238  string id_type = "unknown";
239  ConstElementPtr host = elem->get(i);
240  ConstElementPtr id = host->get("hw-address");
241  if (id) {
242  id_type = "hw-address";
243  goto found;
244  }
245  id = host->get("duid");
246  if (id) {
247  id_type = "duid";
248  goto found;
249  }
250  if (model_ == KEA_DHCP4_SERVER) {
251  id = host->get("circuit-id");
252  if (id) {
253  id_type = "circuit-id";
254  goto found;
255  }
256  id = host->get("client-id");
257  if (id) {
258  id_type = "client-id";
259  goto found;
260  }
261  }
262  id = host->get("flex-id");
263  if (id) {
264  id_type = "flex-id";
265  goto found;
266  }
267 
268  found:
269  if (id_type == "unknown") {
270  isc_throw(BadValue, "getHosts: can't find the identifier type in "
271  << host->str());
272  }
273  ostringstream key;
274  key << xpath << "/host[identifier-type='" << id_type
275  << "'][identifier='" << id->stringValue() << "']";
276  setHost(key.str(), host);
277  }
278 }
279 
280 }; // end of namespace isc::yang
281 }; // 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:126
isc::data::ElementPtr getHostKea(const std::string &xpath)
getHost for kea-dhcp[46]-server models.
isc::data::ElementPtr getHosts(const std::string &xpath)
Get and translate host reservations from YANG to JSON.
void setHostsKea(const std::string &xpath, isc::data::ConstElementPtr elem)
setHosts for kea-dhcp[46].
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
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
STL namespace.
virtual ~TranslatorHost()
Destructor.
sysrepo::S_Iter_Value getIter(const std::string &xpath)
List iterator methods keeping the session private.
Definition: translator.cc:316
isc::data::ElementPtr getHost(const std::string &xpath)
Get and translate a host reservation from YANG to JSON.
#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:288
Translation between YANG and JSON for a single host reservation.
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.
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:321
static isc::data::ConstElementPtr getContext(isc::data::ConstElementPtr parent)
Get user context.
Definition: adaptor.cc:27
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
void setHostKea(const std::string &xpath, isc::data::ConstElementPtr elem)
setHost for kea-dhcp[46]-server models.
TranslatorHosts(sysrepo::S_Session session, const std::string &model)
Constructor.
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:111
virtual ~TranslatorHosts()
Destructor.
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 setHost(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set host reservation from JSON to YANG.
void setHosts(const std::string &xpath, isc::data::ConstElementPtr elem)
Translate and set (address) host reservations from JSON to YANG.