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