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/translator_option_data.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 using namespace sysrepo;
17
18 namespace isc {
19 namespace yang {
20
TranslatorOptionData(S_Session session,const string & model)21 TranslatorOptionData::TranslatorOptionData(S_Session session,
22 const string& model)
23 : TranslatorBasic(session, model) {
24 }
25
~TranslatorOptionData()26 TranslatorOptionData::~TranslatorOptionData() {
27 }
28
29 ElementPtr
getOptionData(const string & xpath)30 TranslatorOptionData::getOptionData(const string& xpath) {
31 try {
32 if ((model_ == KEA_DHCP4_SERVER) ||
33 (model_ == KEA_DHCP6_SERVER)) {
34 return (getOptionDataKea(xpath));
35 }
36 } catch (const sysrepo_exception& ex) {
37 isc_throw(SysrepoError,
38 "sysrepo error getting option data at '" << xpath
39 << "': " << ex.what());
40 }
41 isc_throw(NotImplemented,
42 "getOptionData not implemented for the model: " << model_);
43 }
44
45 ElementPtr
getOptionDataKea(const string & xpath)46 TranslatorOptionData::getOptionDataKea(const string& xpath) {
47 ConstElementPtr code = getItem(xpath + "/code");
48 ConstElementPtr space = getItem(xpath + "/space");
49 if (!code || !space) {
50 // Can't happen as code and space are the keys.
51 isc_throw(Unexpected, "getOptionDataKea requires code and space: "
52 << xpath);
53 }
54 ElementPtr result = Element::createMap();
55 result->set("code", code);
56 result->set("space", space);
57 ConstElementPtr name = getItem(xpath + "/name");
58 if (name) {
59 result->set("name", name);
60 }
61 ConstElementPtr data = getItem(xpath + "/data");
62 if (data) {
63 result->set("data", data);
64 }
65 ConstElementPtr format = getItem(xpath + "/csv-format");
66 if (format) {
67 result->set("csv-format", format);
68 }
69 ConstElementPtr send = getItem(xpath + "/always-send");
70 if (send) {
71 result->set("always-send", send);
72 }
73 ConstElementPtr context = getItem(xpath + "/user-context");
74 if (context) {
75 result->set("user-context", Element::fromJSON(context->stringValue()));
76 }
77 return (result);
78 }
79
80 void
setOptionData(const string & xpath,ConstElementPtr elem)81 TranslatorOptionData::setOptionData(const string& xpath,
82 ConstElementPtr elem) {
83 try {
84 if ((model_ == KEA_DHCP4_SERVER) ||
85 (model_ == KEA_DHCP6_SERVER)) {
86 setOptionDataKea(xpath, elem);
87 } else {
88 isc_throw(NotImplemented,
89 "setOptionData not implemented for the model: "
90 << model_);
91 }
92 } catch (const sysrepo_exception& ex) {
93 isc_throw(SysrepoError,
94 "sysrepo error setting option data '" << elem->str()
95 << "' at '" << xpath << "': " << ex.what());
96 }
97 }
98
99 void
setOptionDataKea(const string & xpath,ConstElementPtr elem)100 TranslatorOptionData::setOptionDataKea(const string& xpath,
101 ConstElementPtr elem) {
102 // Skip keys code and space.
103 ConstElementPtr name = elem->get("name");
104 if (name) {
105 setItem(xpath + "/name", name, SR_STRING_T);
106 }
107 ConstElementPtr data = elem->get("data");
108 if (data) {
109 setItem(xpath + "/data", data, SR_STRING_T);
110 }
111 ConstElementPtr format = elem->get("csv-format");
112 if (format) {
113 setItem(xpath + "/csv-format", format, SR_BOOL_T);
114 }
115 ConstElementPtr send = elem->get("always-send");
116 if (send) {
117 setItem(xpath + "/always-send", send, SR_BOOL_T);
118 }
119 ConstElementPtr context = Adaptor::getContext(elem);
120 if (context) {
121 setItem(xpath + "/user-context", Element::create(context->str()),
122 SR_STRING_T);
123 }
124 }
125
TranslatorOptionDataList(S_Session session,const string & model)126 TranslatorOptionDataList::TranslatorOptionDataList(S_Session session,
127 const string& model)
128 : TranslatorBasic(session, model),
129 TranslatorOptionData(session, model) {
130 }
131
~TranslatorOptionDataList()132 TranslatorOptionDataList::~TranslatorOptionDataList() {
133 }
134
135 ConstElementPtr
getOptionDataList(const string & xpath)136 TranslatorOptionDataList::getOptionDataList(const string& xpath) {
137 try {
138 if ((model_ == KEA_DHCP4_SERVER) ||
139 (model_ == KEA_DHCP6_SERVER)) {
140 return (getOptionDataListKea(xpath));
141 }
142 } catch (const sysrepo_exception& ex) {
143 isc_throw(SysrepoError,
144 "sysrepo error getting option data list at '" << xpath
145 << "': " << ex.what());
146 }
147 isc_throw(NotImplemented,
148 "getOptionDataList not implemented for the model: " << model_);
149 }
150
151 ConstElementPtr
getOptionDataListKea(const string & xpath)152 TranslatorOptionDataList::getOptionDataListKea(const string& xpath) {
153 return getList<TranslatorOptionData>(xpath + "/option-data", *this,
154 &TranslatorOptionData::getOptionData);
155 }
156
157 void
setOptionDataList(const string & xpath,ConstElementPtr elem)158 TranslatorOptionDataList::setOptionDataList(const string& xpath,
159 ConstElementPtr elem) {
160 try {
161 if ((model_ == KEA_DHCP4_SERVER) ||
162 (model_ == KEA_DHCP6_SERVER)) {
163 setOptionDataListKea(xpath, elem);
164 } else {
165 isc_throw(NotImplemented,
166 "setOptionDataList not implemented for the model: "
167 << model_);
168 }
169 } catch (const sysrepo_exception& ex) {
170 isc_throw(SysrepoError,
171 "sysrepo error setting option data list '" << elem->str()
172 << "' at '" << xpath << "': " << ex.what());
173 }
174 }
175
176 void
setOptionDataListKea(const string & xpath,ConstElementPtr elem)177 TranslatorOptionDataList::setOptionDataListKea(const string& xpath,
178 ConstElementPtr elem) {
179 for (size_t i = 0; i < elem->size(); ++i) {
180 ConstElementPtr option = elem->get(i);
181 if (!option->contains("code")) {
182 isc_throw(BadValue, "option data without code: " << option->str());
183 }
184 unsigned code = static_cast<unsigned>(option->get("code")->intValue());
185 if (!option->contains("space")) {
186 isc_throw(BadValue, "option data without space: " <<option->str());
187 }
188 string space = option->get("space")->stringValue();
189 ostringstream keys;
190 keys << xpath << "/option-data[code='" << code
191 << "'][space='" << space << "']";
192 setOptionData(keys.str(), option);
193 }
194 }
195
196 } // namespace yang
197 } // namespace isc
198