Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include "dns_config_parser.h"
7 :
8 : #include <sstream>
9 : #include <boost/algorithm/string/trim.hpp>
10 : #include <boost/asio/ip/address.hpp>
11 : #include <boost/uuid/name_generator.hpp>
12 : #include <boost/uuid/nil_generator.hpp>
13 : #include <boost/uuid/uuid.hpp>
14 : #include <boost/uuid/uuid_io.hpp>
15 : #include <pugixml/pugixml.hpp>
16 : #include "base/logging.h"
17 : #include "bind/bind_util.h"
18 : #include "cfg/dns_config.h"
19 : #include "ifmap/ifmap_server_table.h"
20 :
21 : using namespace std;
22 : using namespace pugi;
23 :
24 : namespace {
25 :
26 92 : static void MapObjectLink(const string <ype, const string &lname,
27 : const string &rtype, const string &rname,
28 : const string &linkname,
29 : DnsConfigParser::RequestList *requests,
30 : DBRequest::DBOperation oper) {
31 92 : DBRequest *request = new DBRequest;
32 92 : request->oper = oper;
33 92 : IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
34 92 : request->key.reset(key);
35 92 : key->id_type = ltype;
36 92 : key->id_name = lname;
37 92 : IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
38 92 : request->data.reset(data);
39 92 : data->metadata = linkname;
40 92 : data->id_type = rtype;
41 92 : data->id_name = rname;
42 92 : data->origin.set_origin(IFMapOrigin::MAP_SERVER);
43 92 : requests->push_back(request);
44 92 : }
45 :
46 48 : static void MapObjectLinkAttr(const string <ype, const string &lname,
47 : const string &rtype, const string &rname,
48 : const string &linkname, AutogenProperty *attr,
49 : DnsConfigParser::RequestList *requests,
50 : DBRequest::DBOperation oper) {
51 48 : DBRequest *request = new DBRequest;
52 48 : request->oper = oper;
53 48 : IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
54 48 : request->key.reset(key);
55 48 : key->id_type = ltype;
56 48 : key->id_name = lname;
57 48 : IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
58 48 : request->data.reset(data);
59 48 : data->metadata = linkname;
60 48 : data->id_type = rtype;
61 48 : data->id_name = rname;
62 48 : data->content.reset(attr);
63 48 : data->origin.set_origin(IFMapOrigin::MAP_SERVER);
64 48 : requests->push_back(request);
65 48 : }
66 :
67 75 : static void SetData(const string &identifier, const string &id_type,
68 : const string &metadata, AutogenProperty *params,
69 : DnsConfigParser::RequestList *requests) {
70 75 : DBRequest *request = new DBRequest;
71 75 : request->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
72 75 : IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
73 75 : request->key.reset(key);
74 75 : key->id_type = id_type;
75 75 : key->id_name = identifier;
76 75 : IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
77 75 : request->data.reset(data);
78 75 : data->metadata = metadata;
79 75 : data->content.reset(params);
80 75 : data->origin.set_origin(IFMapOrigin::MAP_SERVER);
81 75 : requests->push_back(request);
82 75 : }
83 :
84 45 : static void ClearData(const string &identifier, const string &id_type,
85 : const string &metadata,
86 : DnsConfigParser::RequestList *requests) {
87 45 : DBRequest *request = new DBRequest;
88 45 : request->oper = DBRequest::DB_ENTRY_DELETE;
89 45 : IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
90 45 : request->key.reset(key);
91 45 : key->id_type = id_type;
92 45 : key->id_name = identifier;
93 45 : IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
94 45 : request->data.reset(data);
95 45 : data->metadata = metadata;
96 45 : data->origin.set_origin(IFMapOrigin::MAP_SERVER);
97 45 : requests->push_back(request);
98 45 : }
99 :
100 48 : static bool ParseVnNetworkIpam(const xml_node &node, bool add_change,
101 : DnsConfigParser::RequestList *requests) {
102 48 : xml_attribute name_attr = node.attribute("name");
103 48 : xml_attribute ipam_attr = node.attribute("ipam");
104 48 : xml_attribute vn_attr = node.attribute("vn");
105 48 : string name;
106 48 : string ipam;
107 48 : string vn;
108 :
109 48 : if (name_attr)
110 4 : name = name_attr.value();
111 48 : if (ipam_attr)
112 48 : ipam = ipam_attr.value();
113 48 : if (vn_attr)
114 48 : vn = vn_attr.value();
115 :
116 48 : unique_ptr<autogen::VnSubnetsType> params(new autogen::VnSubnetsType());
117 48 : if (!params->XmlParse(node)) {
118 0 : assert(0);
119 : }
120 :
121 48 : if (add_change) {
122 30 : MapObjectLinkAttr("virtual-network", vn, "network-ipam", ipam,
123 30 : "virtual-network-network-ipam", params.release(), requests,
124 : DBRequest::DB_ENTRY_ADD_CHANGE);
125 : } else {
126 18 : MapObjectLinkAttr("virtual-network", vn, "network-ipam", ipam,
127 18 : "virtual-network-network-ipam", params.release(), requests,
128 : DBRequest::DB_ENTRY_DELETE);
129 : }
130 :
131 48 : return true;
132 48 : }
133 :
134 28 : static bool ParseNetworkIpam(const xml_node &node, bool add_change,
135 : DnsConfigParser::RequestList *requests) {
136 28 : xml_attribute name = node.attribute("name");
137 28 : string identifier;
138 28 : if (name)
139 28 : identifier = name.value();
140 :
141 28 : unique_ptr<autogen::IpamType> params(new autogen::IpamType());
142 28 : if (!params->XmlParse(node)) {
143 0 : assert(0);
144 : }
145 :
146 28 : if (add_change) {
147 17 : SetData(identifier, "network-ipam", "network-ipam-mgmt",
148 17 : params.release(), requests);
149 : } else {
150 11 : ClearData(identifier, "network-ipam", "network-ipam-mgmt", requests);
151 : }
152 :
153 28 : return true;
154 28 : }
155 :
156 30 : static bool ParseVirtualDNS(const xml_node &node, bool add_change,
157 : DnsConfigParser::RequestList *requests) {
158 30 : xml_attribute name = node.attribute("name");
159 30 : xml_attribute domain = node.attribute("domain");
160 30 : string identifier;
161 30 : string view;
162 :
163 30 : if (name)
164 30 : identifier = name.value();
165 30 : if (domain)
166 30 : view = domain.value();
167 :
168 30 : unique_ptr<autogen::VirtualDnsType> params(new autogen::VirtualDnsType());
169 30 : if (!params->XmlParse(node)) {
170 0 : assert(0);
171 : }
172 :
173 30 : if (add_change) {
174 19 : SetData(identifier, "virtual-DNS", "virtual-DNS-data",
175 19 : params.release(), requests);
176 19 : MapObjectLink("domain", view, "virtual-DNS", identifier,
177 : "domain-virtual-DNS", requests,
178 : DBRequest::DB_ENTRY_ADD_CHANGE);
179 : } else {
180 11 : ClearData(identifier, "virtual-DNS", "virtual-DNS-data", requests);
181 11 : MapObjectLink("domain", view, "virtual-DNS", identifier,
182 : "domain-virtual-DNS", requests,
183 : DBRequest::DB_ENTRY_DELETE);
184 : }
185 :
186 30 : return true;
187 30 : }
188 :
189 62 : static bool ParseVirtualDNSRecord(const xml_node &node, bool add_change,
190 : DnsConfigParser::RequestList *requests) {
191 62 : xml_attribute name = node.attribute("name");
192 62 : xml_attribute dns = node.attribute("dns");
193 62 : string identifier;
194 62 : string virtual_dns;
195 :
196 62 : if (name)
197 62 : identifier = name.value();
198 62 : if (dns)
199 62 : virtual_dns = dns.value();
200 :
201 62 : unique_ptr<autogen::VirtualDnsRecordType> params(new autogen::VirtualDnsRecordType());
202 62 : if (!params->XmlParse(node)) {
203 0 : assert(0);
204 : }
205 :
206 62 : if (add_change) {
207 39 : SetData(identifier, "virtual-DNS-record", "virtual-DNS-record-data",
208 39 : params.release(), requests);
209 39 : MapObjectLink("virtual-DNS", virtual_dns,
210 : "virtual-DNS-record", identifier,
211 : "virtual-DNS-virtual-DNS-record", requests,
212 : DBRequest::DB_ENTRY_ADD_CHANGE);
213 : } else {
214 23 : ClearData(identifier, "virtual-DNS-record",
215 : "virtual-DNS-record-data", requests);
216 23 : MapObjectLink("virtual-DNS", virtual_dns,
217 : "virtual-DNS-record", identifier,
218 : "virtual-DNS-virtual-DNS-record", requests,
219 : DBRequest::DB_ENTRY_DELETE);
220 : }
221 :
222 62 : return true;
223 62 : }
224 :
225 0 : static bool ParseGlobalQosConfig(const xml_node &node, bool add_change,
226 : DnsConfigParser::RequestList *requests) {
227 0 : xml_attribute name = node.attribute("name");
228 0 : string identifier;
229 0 : if (name)
230 0 : identifier = name.value();
231 :
232 0 : for (xml_node child = node.first_child(); child;
233 0 : child = child.next_sibling()) {
234 0 : if (strcmp(child.name(), "control-traffic-dscp") == 0) {
235 : unique_ptr<autogen::ControlTrafficDscpType> cfg(
236 0 : new autogen::ControlTrafficDscpType());
237 0 : assert(cfg->XmlParse(child));
238 :
239 0 : if (add_change) {
240 0 : SetData(identifier, "global-qos-config",
241 0 : "control-traffic-dscp", cfg.release(), requests);
242 : } else {
243 0 : ClearData(identifier, "global-qos-config",
244 : "control-traffic-dscp", requests);
245 : }
246 0 : }
247 : }
248 0 : return true;
249 0 : }
250 :
251 : } // namespace
252 :
253 15 : DnsConfigParser::DnsConfigParser(DB *db) : db_(db) {
254 15 : }
255 :
256 26 : bool DnsConfigParser::ParseConfig(const xml_node &root, bool add_change,
257 : RequestList *requests) const {
258 :
259 194 : for (xml_node node = root.first_child(); node; node = node.next_sibling()) {
260 168 : if (strcmp(node.name(), "network-ipam") == 0) {
261 28 : ParseNetworkIpam(node, add_change, requests);
262 : }
263 140 : else if (strcmp(node.name(), "virtual-network-network-ipam") == 0) {
264 48 : ParseVnNetworkIpam(node, add_change, requests);
265 : }
266 92 : else if (strcmp(node.name(), "virtual-DNS") == 0) {
267 30 : ParseVirtualDNS(node, add_change, requests);
268 : }
269 62 : else if (strcmp(node.name(), "virtual-DNS-record") == 0) {
270 62 : ParseVirtualDNSRecord(node, add_change, requests);
271 : }
272 0 : else if (strcmp(node.name(), "global-qos-config") == 0) {
273 0 : ParseGlobalQosConfig(node, add_change, requests);
274 : }
275 : }
276 :
277 26 : return true;
278 : }
279 :
280 26 : bool DnsConfigParser::Parse(const std::string &content) {
281 26 : istringstream sstream(content);
282 26 : xml_document xdoc;
283 26 : xml_parse_result result = xdoc.load(sstream);
284 26 : if (!result) {
285 0 : std::stringstream str;
286 0 : str << "Unable to load XML document. (status="
287 0 : << result.status << ", offset=" << result.offset << ")";
288 0 : DNS_TRACE(DnsError, str.str());
289 0 : return false;
290 0 : }
291 :
292 26 : RequestList requests;
293 52 : for (xml_node node = xdoc.first_child(); node; node = node.next_sibling()) {
294 : bool add_change;
295 26 : if (strcmp(node.name(), "config") == 0) {
296 15 : add_change = true;
297 11 : } else if (strcmp(node.name(), "delete") == 0) {
298 11 : add_change = false;
299 : } else {
300 0 : continue;
301 : }
302 26 : if (!ParseConfig(node, add_change, &requests)) {
303 0 : STLDeleteValues(&requests);
304 0 : return false;
305 : }
306 : }
307 :
308 286 : while (!requests.empty()) {
309 260 : unique_ptr<DBRequest> req(requests.front());
310 260 : requests.pop_front();
311 :
312 : IFMapTable::RequestKey *key =
313 260 : static_cast<IFMapTable::RequestKey *>(req->key.get());
314 :
315 260 : IFMapTable *table = IFMapTable::FindTable(db_, key->id_type);
316 260 : if (table == NULL) {
317 0 : continue;
318 : }
319 260 : table->Enqueue(req.get());
320 260 : }
321 :
322 26 : return true;
323 26 : }
|