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 <database/database_connection.h>
10 #include <test_config_backend_dhcp4.h>
11 #include <list>
12 
13 using namespace isc::data;
14 using namespace isc::db;
15 
16 namespace isc {
17 namespace dhcp {
18 namespace test {
19 
20 bool
registerBackendType(ConfigBackendDHCPv4Mgr & mgr,const std::string & db_type)21 TestConfigBackendDHCPv4::registerBackendType(ConfigBackendDHCPv4Mgr& mgr,
22                                              const std::string& db_type) {
23     return(mgr.registerBackendFactory(db_type,
24                 [](const db::DatabaseConnection::ParameterMap& params)
25                 -> dhcp::ConfigBackendDHCPv4Ptr {
26                 return (TestConfigBackendDHCPv4Ptr(new TestConfigBackendDHCPv4(params)));
27             })
28     );
29 }
30 
31 void
unregisterBackendType(ConfigBackendDHCPv4Mgr & mgr,const std::string & db_type)32 TestConfigBackendDHCPv4::unregisterBackendType(ConfigBackendDHCPv4Mgr& mgr,
33                                                const std::string& db_type) {
34     mgr.unregisterBackendFactory(db_type);
35 }
36 
37 Subnet4Ptr
getSubnet4(const db::ServerSelector & server_selector,const std::string & subnet_prefix) const38 TestConfigBackendDHCPv4::getSubnet4(const db::ServerSelector& server_selector,
39                                     const std::string& subnet_prefix) const{
40     const auto& index = subnets_.get<SubnetPrefixIndexTag>();
41     auto subnet_it = index.find(subnet_prefix);
42     if (subnet_it == index.cend()) {
43         return (Subnet4Ptr());
44     }
45     Subnet4Ptr subnet = *subnet_it;
46     if (server_selector.amAny()) {
47         return (subnet);
48     }
49     if (server_selector.amUnassigned()) {
50         return (subnet->getServerTags().empty() ? subnet : Subnet4Ptr());
51     }
52     auto tags = server_selector.getTags();
53     for (auto tag : tags) {
54         if (subnet->hasServerTag(ServerTag(tag))) {
55             return (subnet);
56         }
57     }
58     return (subnet->hasAllServerTag() ? subnet : Subnet4Ptr());
59 }
60 
61 Subnet4Ptr
getSubnet4(const db::ServerSelector & server_selector,const SubnetID & subnet_id) const62 TestConfigBackendDHCPv4::getSubnet4(const db::ServerSelector& server_selector,
63                                     const SubnetID& subnet_id) const {
64     const auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
65     auto subnet_it = index.find(subnet_id);
66     if (subnet_it == index.cend()) {
67         return (Subnet4Ptr());
68     }
69     Subnet4Ptr subnet = *subnet_it;
70     if (server_selector.amAny()) {
71         return (subnet);
72     }
73     if (server_selector.amUnassigned()) {
74         return (subnet->getServerTags().empty() ? subnet : Subnet4Ptr());
75     }
76     auto tags = server_selector.getTags();
77     for (auto tag : tags) {
78         if (subnet->hasServerTag(ServerTag(tag))) {
79             return (subnet);
80         }
81     }
82     return (subnet->hasAllServerTag() ? subnet : Subnet4Ptr());
83 }
84 
85 Subnet4Collection
getAllSubnets4(const db::ServerSelector & server_selector) const86 TestConfigBackendDHCPv4::getAllSubnets4(const db::ServerSelector& server_selector) const {
87     Subnet4Collection subnets;
88     for (auto subnet : subnets_) {
89         if (server_selector.amAny()) {
90             subnets.insert(subnet);
91             continue;
92         }
93         if (server_selector.amUnassigned()) {
94             if (subnet->getServerTags().empty()) {
95                 subnets.insert(subnet);
96             }
97             continue;
98         }
99         bool got = false;
100         auto tags = server_selector.getTags();
101         for (auto tag : tags) {
102             if (subnet->hasServerTag(ServerTag(tag))) {
103                 subnets.insert(subnet);
104                 got = true;
105                 break;
106             }
107         }
108         if (got) {
109             continue;
110         }
111         if (subnet->hasAllServerTag()) {
112             subnets.insert(subnet);
113         }
114     }
115     return (subnets);
116 }
117 
118 Subnet4Collection
getModifiedSubnets4(const db::ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const119 TestConfigBackendDHCPv4::getModifiedSubnets4(const db::ServerSelector& server_selector,
120                                              const boost::posix_time::ptime& modification_time) const {
121     const auto& index = subnets_.get<SubnetModificationTimeIndexTag>();
122     Subnet4Collection subnets;
123     auto lb = index.lower_bound(modification_time);
124     for (auto subnet = lb; subnet != index.end(); ++subnet) {
125         if (server_selector.amAny()) {
126             subnets.insert(*subnet);
127             continue;
128         }
129         if (server_selector.amUnassigned()) {
130             if ((*subnet)->getServerTags().empty()) {
131                 subnets.insert(*subnet);
132             }
133             continue;
134         }
135         bool got = false;
136         auto tags = server_selector.getTags();
137         for (auto tag : tags) {
138             if ((*subnet)->hasServerTag(ServerTag(tag))) {
139                 subnets.insert(*subnet);
140                 got = true;
141                 break;
142             }
143         }
144         if (got) {
145             continue;
146         }
147         if ((*subnet)->hasAllServerTag()) {
148             subnets.insert(*subnet);
149         }
150     }
151     return (subnets);
152 }
153 
154 Subnet4Collection
getSharedNetworkSubnets4(const db::ServerSelector & server_selector,const std::string & shared_network_name) const155 TestConfigBackendDHCPv4::getSharedNetworkSubnets4(const db::ServerSelector& server_selector,
156                                                   const std::string& shared_network_name) const {
157     Subnet4Collection subnets;
158 
159     // Subnet collection does not include the index by shared network name.
160     // We need to iterate over the subnets and pick those that are associated
161     // with a shared network.
162     for (auto subnet : subnets_) {
163         // Skip subnets which do not match the server selector.
164         if (server_selector.amUnassigned() &&
165             !subnet->getServerTags().empty()) {
166             continue;
167         }
168         if (!server_selector.amAny()) {
169             bool got = false;
170             auto tags = server_selector.getTags();
171             for (auto tag : tags) {
172                 if (subnet->hasServerTag(ServerTag(tag))) {
173                     got = true;
174                     break;
175                 }
176             }
177             if (!got && !subnet->hasAllServerTag()) {
178                 continue;
179             }
180         }
181 
182         // The subnet can be associated with a shared network instance or
183         // it may just point to the shared network name. The former is
184         // the case when the subnet belongs to the server configuration.
185         // The latter is the case when the subnet is fetched from the
186         // database.
187         SharedNetwork4Ptr network;
188         subnet->getSharedNetwork(network);
189         if (((network && (network->getName() == shared_network_name)) ||
190              (subnet->getSharedNetworkName() == shared_network_name))) {
191             subnets.insert(subnet);
192         }
193     }
194     return (subnets);
195 }
196 
197 SharedNetwork4Ptr
getSharedNetwork4(const db::ServerSelector & server_selector,const std::string & name) const198 TestConfigBackendDHCPv4::getSharedNetwork4(const db::ServerSelector& server_selector,
199                                            const std::string& name) const {
200     const auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
201     auto network_it = index.find(name);
202     if (network_it == index.cend()) {
203         return (SharedNetwork4Ptr());
204     }
205     SharedNetwork4Ptr network = *network_it;
206     if (server_selector.amAny()) {
207         return (network);
208     }
209     if (server_selector.amUnassigned()) {
210         return (network->getServerTags().empty() ? network : SharedNetwork4Ptr());
211     }
212     auto tags = server_selector.getTags();
213     for (auto tag : tags) {
214         if (network->hasServerTag(ServerTag(tag))) {
215             return (network);
216         }
217     }
218     return (network->hasAllServerTag() ? network : SharedNetwork4Ptr());
219 }
220 
221 SharedNetwork4Collection
getAllSharedNetworks4(const db::ServerSelector & server_selector) const222 TestConfigBackendDHCPv4::getAllSharedNetworks4(const db::ServerSelector& server_selector) const{
223     SharedNetwork4Collection shared_networks;
224     for (auto shared_network : shared_networks_) {
225         if (server_selector.amAny()) {
226             shared_networks.push_back(shared_network);
227             continue;
228         }
229         if (server_selector.amUnassigned()) {
230             if (shared_network->getServerTags().empty()) {
231                 shared_networks.push_back(shared_network);
232             }
233             continue;
234         }
235         bool got = false;
236         auto tags = server_selector.getTags();
237         for (auto tag : tags) {
238             if (shared_network->hasServerTag(ServerTag(tag))) {
239                 shared_networks.push_back(shared_network);
240                 got = true;
241                 break;
242             }
243         }
244         if (got) {
245             continue;
246         }
247         if (shared_network->hasAllServerTag()) {
248             shared_networks.push_back(shared_network);
249         }
250     }
251     return (shared_networks);
252 }
253 
254 SharedNetwork4Collection
getModifiedSharedNetworks4(const db::ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const255 TestConfigBackendDHCPv4::getModifiedSharedNetworks4(const db::ServerSelector& server_selector,
256                                                     const boost::posix_time::ptime& modification_time) const {
257     const auto& index = shared_networks_.get<SharedNetworkModificationTimeIndexTag>();
258     SharedNetwork4Collection shared_networks;
259     auto lb = index.lower_bound(modification_time);
260     for (auto shared_network = lb; shared_network != index.end(); ++shared_network) {
261         if (server_selector.amAny()) {
262             shared_networks.push_back(*shared_network);
263             continue;
264         }
265         if (server_selector.amUnassigned()) {
266             if ((*shared_network)->getServerTags().empty()) {
267                 shared_networks.push_back(*shared_network);
268             }
269             continue;
270         }
271         bool got = false;
272         auto tags = server_selector.getTags();
273         for (auto tag : tags) {
274             if ((*shared_network)->hasServerTag(ServerTag(tag))) {
275                 shared_networks.push_back(*shared_network);
276                 got = true;
277                 break;
278             }
279         }
280         if (got) {
281             continue;
282         }
283         if ((*shared_network)->hasAllServerTag()) {
284             shared_networks.push_back(*shared_network);
285         }
286     }
287     return (shared_networks);
288 }
289 
290 OptionDefinitionPtr
getOptionDef4(const db::ServerSelector & server_selector,const uint16_t code,const std::string & space) const291 TestConfigBackendDHCPv4::getOptionDef4(const db::ServerSelector& server_selector,
292                                        const uint16_t code,
293                                        const std::string& space) const {
294     auto tags = server_selector.getTags();
295     auto candidate = OptionDefinitionPtr();
296     const auto& index = option_defs_.get<1>();
297     auto option_def_it_pair = index.equal_range(code);
298 
299     for (auto option_def_it = option_def_it_pair.first;
300          option_def_it != option_def_it_pair.second;
301          ++option_def_it) {
302         if ((*option_def_it)->getOptionSpaceName() == space) {
303             for (auto tag : tags) {
304                 if ((*option_def_it)->hasServerTag(ServerTag(tag))) {
305                     return (*option_def_it);
306                 }
307             }
308             if ((*option_def_it)->hasAllServerTag()) {
309                 candidate = *option_def_it;
310             }
311         }
312     }
313     return (candidate);
314 }
315 
316 OptionDefContainer
getAllOptionDefs4(const db::ServerSelector & server_selector) const317 TestConfigBackendDHCPv4::getAllOptionDefs4(const db::ServerSelector& server_selector) const {
318     auto tags = server_selector.getTags();
319     OptionDefContainer option_defs;
320     for (auto option_def : option_defs_) {
321         bool got = false;
322         if (server_selector.amUnassigned()) {
323             if (option_def->getServerTags().empty()) {
324                 option_defs.push_back(option_def);
325                 got = true;
326             }
327         } else {
328             for (auto tag : tags) {
329                 if (option_def->hasServerTag(ServerTag(tag))) {
330                     option_defs.push_back(option_def);
331                     got = true;
332                     break;
333                 }
334             }
335         }
336         if (got) {
337             continue;
338         }
339         if (option_def->hasAllServerTag() && !server_selector.amUnassigned()) {
340             option_defs.push_back(option_def);
341         }
342     }
343     return (option_defs);
344 }
345 
346 OptionDefContainer
getModifiedOptionDefs4(const db::ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const347 TestConfigBackendDHCPv4::getModifiedOptionDefs4(const db::ServerSelector& server_selector,
348                                                 const boost::posix_time::ptime& modification_time) const {
349     auto tags = server_selector.getTags();
350     OptionDefContainer option_defs;
351     const auto& index = option_defs_.get<3>();
352     auto lb = index.lower_bound(modification_time);
353     for (auto option_def = lb; option_def != index.end(); ++option_def) {
354         bool got = false;
355         for (auto tag : tags) {
356             if ((*option_def)->hasServerTag(ServerTag(tag))) {
357                 option_defs.push_back(*option_def);
358                 got = true;
359                 break;
360             }
361         }
362         if (got) {
363             continue;
364         }
365         if ((*option_def)->hasAllServerTag()) {
366             option_defs.push_back(*option_def);
367         }
368     }
369     return (option_defs);
370 }
371 
372 OptionDescriptorPtr
getOption4(const db::ServerSelector & server_selector,const uint16_t code,const std::string & space) const373 TestConfigBackendDHCPv4::getOption4(const db::ServerSelector& server_selector,
374                                     const uint16_t code,
375                                     const std::string& space) const {
376     auto tags = server_selector.getTags();
377     auto candidate = OptionDescriptorPtr();
378     const auto& index = options_.get<1>();
379     auto option_it_pair = index.equal_range(code);
380 
381     for (auto option_it = option_it_pair.first; option_it != option_it_pair.second;
382          ++option_it) {
383         if (option_it->space_name_ == space) {
384             for (auto tag : tags) {
385                 if (option_it->hasServerTag(ServerTag(tag))) {
386                     return (OptionDescriptorPtr(new OptionDescriptor(*option_it)));
387                 }
388             }
389             if (option_it->hasAllServerTag()) {
390                 candidate = OptionDescriptorPtr(new OptionDescriptor(*option_it));
391             }
392         }
393     }
394 
395     return (candidate);
396 }
397 
398 OptionContainer
getAllOptions4(const db::ServerSelector & server_selector) const399 TestConfigBackendDHCPv4::getAllOptions4(const db::ServerSelector& server_selector) const {
400     auto tags = server_selector.getTags();
401     OptionContainer options;
402     for (auto option : options_) {
403         bool got = false;
404         for (auto tag : tags) {
405             if (option.hasServerTag(ServerTag(tag))) {
406                 options.push_back(option);
407                 got = true;
408                 break;
409             }
410         }
411         if (got) {
412             continue;
413         }
414         if (option.hasAllServerTag()) {
415             options.push_back(option);
416         }
417     }
418     return (options);
419 }
420 
421 OptionContainer
getModifiedOptions4(const db::ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const422 TestConfigBackendDHCPv4::getModifiedOptions4(const db::ServerSelector& server_selector,
423                                              const boost::posix_time::ptime& modification_time) const {
424     auto tags = server_selector.getTags();
425     OptionContainer options;
426     const auto& index = options_.get<3>();
427     auto lb = index.lower_bound(modification_time);
428     for (auto option = lb; option != index.end(); ++option) {
429         bool got = false;
430         for (auto tag : tags) {
431             if (option->hasServerTag(ServerTag(tag))) {
432                 options.push_back(*option);
433                 got = true;
434                 break;
435             }
436         }
437         if (got) {
438             continue;
439         }
440         if (option->hasAllServerTag()) {
441             options.push_back(*option);
442         }
443     }
444     return (options);
445 }
446 
447 StampedValuePtr
getGlobalParameter4(const db::ServerSelector & server_selector,const std::string & name) const448 TestConfigBackendDHCPv4::getGlobalParameter4(const db::ServerSelector& server_selector,
449                                              const std::string& name) const {
450     auto tags = server_selector.getTags();
451     auto candidate = StampedValuePtr();
452     const auto& index = globals_.get<StampedValueNameIndexTag>();
453     auto global_range = index.equal_range(name);
454     for (auto global_it = global_range.first; global_it != global_range.second;
455          ++global_it) {
456         for (auto tag : tags) {
457             if ((*global_it)->hasServerTag(ServerTag(tag))) {
458                 return (*global_it);
459             }
460         }
461         if ((*global_it)->hasAllServerTag()) {
462             candidate = *global_it;
463         }
464     }
465 
466     return (candidate);
467 }
468 
469 
470 StampedValueCollection
getAllGlobalParameters4(const db::ServerSelector & server_selector) const471 TestConfigBackendDHCPv4::getAllGlobalParameters4(const db::ServerSelector& server_selector) const {
472     auto tags = server_selector.getTags();
473     StampedValueCollection globals;
474     for (auto global : globals_) {
475         bool got = false;
476         for (auto tag : tags) {
477             if (global->hasServerTag(ServerTag(tag))) {
478                 globals.insert(global);
479                 got = true;
480                 break;
481             }
482         }
483         if (got) {
484             continue;
485         }
486         if (global->hasAllServerTag()) {
487             globals.insert(global);
488         }
489     }
490     return (globals);
491 }
492 
493 StampedValueCollection
getModifiedGlobalParameters4(const db::ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const494 TestConfigBackendDHCPv4::getModifiedGlobalParameters4(const db::ServerSelector& server_selector,
495                                                       const boost::posix_time::ptime& modification_time) const {
496     auto tags = server_selector.getTags();
497     StampedValueCollection globals;
498     const auto& index = globals_.get<StampedValueModificationTimeIndexTag>();
499     auto lb = index.lower_bound(modification_time);
500     for (auto global = lb; global != index.end(); ++global) {
501         bool got = false;
502         for (auto tag : tags) {
503             if ((*global)->hasServerTag(ServerTag(tag))) {
504                 globals.insert(*global);
505                 got = true;
506                 break;
507             }
508         }
509         if (got) {
510             continue;
511         }
512         if ((*global)->hasAllServerTag()) {
513             globals.insert(*global);
514         }
515     }
516     return (globals);
517 }
518 
519 ClientClassDefPtr
getClientClass4(const db::ServerSelector & server_selector,const std::string & name) const520 TestConfigBackendDHCPv4::getClientClass4(const db::ServerSelector& server_selector,
521                                          const std::string& name) const {
522     ClientClassDefPtr client_class;
523     for (auto c : classes_) {
524         if (c->getName() == name) {
525             client_class = c;
526             break;
527         }
528     }
529     if (!client_class || server_selector.amAny()) {
530         return (client_class);
531     }
532     if (server_selector.amUnassigned()) {
533         return (client_class->getServerTags().empty() ? client_class : ClientClassDefPtr());
534     }
535     auto tags = server_selector.getTags();
536     for (auto tag : tags) {
537         if (client_class->hasServerTag(ServerTag(tag))) {
538             return (client_class);
539         }
540     }
541     return (client_class->hasAllServerTag() ? client_class : ClientClassDefPtr());
542 }
543 
544 ClientClassDictionary
getAllClientClasses4(const db::ServerSelector & server_selector) const545 TestConfigBackendDHCPv4::getAllClientClasses4(const db::ServerSelector& server_selector) const {
546     auto tags = server_selector.getTags();
547     ClientClassDictionary all_classes;
548     for (auto client_class : classes_) {
549         if (server_selector.amAny()) {
550             all_classes.addClass(client_class);
551             continue;
552         }
553         if (server_selector.amUnassigned()) {
554             if (client_class->getServerTags().empty()) {
555                 all_classes.addClass(client_class);
556             }
557             continue;
558         }
559         bool got = false;
560         for (auto tag : tags) {
561             if (client_class->hasServerTag(ServerTag(tag))) {
562                 all_classes.addClass(client_class);
563                 got = true;
564                 break;
565             }
566         }
567         if (got) {
568             continue;
569         }
570         if (client_class->hasAllServerTag()) {
571             all_classes.addClass(client_class);
572         }
573     }
574     return (all_classes);
575 }
576 
577 ClientClassDictionary
getModifiedClientClasses4(const db::ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const578 TestConfigBackendDHCPv4::getModifiedClientClasses4(const db::ServerSelector& server_selector,
579                                                    const boost::posix_time::ptime& modification_time) const {
580     auto tags = server_selector.getTags();
581     ClientClassDictionary modified_classes;
582     for (auto client_class : classes_) {
583         if (client_class->getModificationTime() >= modification_time) {
584             bool got = false;
585             for (auto tag : tags) {
586                 if (client_class->hasServerTag(ServerTag(tag))) {
587                     modified_classes.addClass(client_class);
588                     got = true;
589                     break;
590                 }
591             }
592             if (got) {
593                 continue;
594             }
595             if (client_class->hasAllServerTag()) {
596                 modified_classes.addClass(client_class);
597             }
598         }
599     }
600     return (modified_classes);
601 }
602 
603 void
createUpdateClientClass4(const db::ServerSelector & server_selector,const ClientClassDefPtr & client_class,const std::string & follow_class_name)604 TestConfigBackendDHCPv4::createUpdateClientClass4(const db::ServerSelector& server_selector,
605                                                   const ClientClassDefPtr& client_class,
606                                                   const std::string& follow_class_name) {
607     int follow_class_index = -1;
608     if (!follow_class_name.empty()) {
609         for (auto i = 0; i < classes_.size(); ++i) {
610             if (classes_[i]->getName() == follow_class_name) {
611                 follow_class_index = i;
612                 break;
613             }
614         }
615         if (follow_class_index < 0) {
616             isc_throw(BadValue, "class " << follow_class_name << " does not exist");
617 
618         }
619     }
620 
621     mergeServerTags(client_class, server_selector);
622 
623     int existing_class_index = -1;
624     for (auto i = 0; i < classes_.size(); ++i) {
625         if (classes_[i]->getName() == client_class->getName()) {
626             existing_class_index = i;
627             break;
628         }
629     }
630 
631     if (follow_class_index < 0) {
632         if (existing_class_index >= 0) {
633             classes_[existing_class_index] = client_class;
634         } else {
635             classes_.push_back(client_class);
636         }
637     } else {
638         if (existing_class_index < 0) {
639             classes_.insert(classes_.begin() + follow_class_index + 1, client_class);
640         } else {
641             classes_.erase(classes_.begin() + existing_class_index);
642             classes_.insert(classes_.begin() + follow_class_index + 1, client_class);
643         }
644     }
645 }
646 
647 AuditEntryCollection
getRecentAuditEntries(const db::ServerSelector &,const boost::posix_time::ptime &,const uint64_t &) const648 TestConfigBackendDHCPv4::getRecentAuditEntries(const db::ServerSelector&,
649                                                const boost::posix_time::ptime&,
650                                                const uint64_t&) const {
651     return (AuditEntryCollection());
652 }
653 
654 ServerCollection
getAllServers4() const655 TestConfigBackendDHCPv4::getAllServers4() const {
656     return (servers_);
657 }
658 
659 ServerPtr
getServer4(const ServerTag & server_tag) const660 TestConfigBackendDHCPv4::getServer4(const ServerTag& server_tag) const {
661     const auto& index = servers_.get<ServerTagIndexTag>();
662     auto server_it = index.find(server_tag.get());
663     return ((server_it != index.cend()) ? (*server_it) : ServerPtr());
664 }
665 
666 void
createUpdateSubnet4(const db::ServerSelector & server_selector,const Subnet4Ptr & subnet)667 TestConfigBackendDHCPv4::createUpdateSubnet4(const db::ServerSelector& server_selector,
668                                              const Subnet4Ptr& subnet) {
669     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
670     auto subnet_it = index.find(subnet->getID());
671 
672     mergeServerTags(subnet, server_selector);
673 
674     if (subnet_it != index.cend()) {
675         index.replace(subnet_it, subnet);
676     } else {
677         index.insert(subnet);
678     }
679 }
680 
681 void
createUpdateSharedNetwork4(const db::ServerSelector & server_selector,const SharedNetwork4Ptr & shared_network)682 TestConfigBackendDHCPv4::createUpdateSharedNetwork4(const db::ServerSelector& server_selector,
683                                                     const SharedNetwork4Ptr& shared_network) {
684     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
685     auto network_it = index.find(shared_network->getName());
686 
687     mergeServerTags(shared_network, server_selector);
688 
689     if (network_it != index.cend()) {
690         index.replace(network_it, shared_network);
691     } else {
692         index.insert(shared_network);
693     }
694 }
695 
696 void
createUpdateOptionDef4(const db::ServerSelector & server_selector,const OptionDefinitionPtr & option_def)697 TestConfigBackendDHCPv4::createUpdateOptionDef4(const db::ServerSelector& server_selector,
698                                                 const OptionDefinitionPtr& option_def) {
699     auto tag = getServerTag(server_selector);
700     option_def->setServerTag(tag);
701 
702     // Index #1 is by option code.
703     auto& index1 = option_defs_.get<1>();
704     auto option_def_it_pair1 = index1.equal_range(option_def->getCode());
705 
706     for (auto option_def_it = option_def_it_pair1.first;
707          option_def_it != option_def_it_pair1.second;
708          option_def_it++) {
709         auto existing_option_def = *option_def_it;
710         if ((existing_option_def->getOptionSpaceName() == option_def->getOptionSpaceName()) &&
711             (existing_option_def->hasServerTag(ServerTag(tag)))) {
712             index1.replace(option_def_it, option_def);
713             return;
714         }
715     }
716 
717     // Index #2 is by option name.
718     auto& index2 = option_defs_.get<2>();
719     auto option_def_it_pair2 = index2.equal_range(option_def->getName());
720 
721     for (auto option_def_it = option_def_it_pair2.first;
722          option_def_it != option_def_it_pair2.second;
723          option_def_it++) {
724         auto existing_option_def = *option_def_it;
725         if ((existing_option_def->getOptionSpaceName() == option_def->getOptionSpaceName()) &&
726             (existing_option_def->hasServerTag(ServerTag(tag)))) {
727             index2.replace(option_def_it, option_def);
728             return;
729         }
730     }
731 
732     option_defs_.push_back(option_def);
733 }
734 
735 void
createUpdateOption4(const db::ServerSelector & server_selector,const OptionDescriptorPtr & option)736 TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_selector,
737                                              const OptionDescriptorPtr& option) {
738     auto tag = getServerTag(server_selector);
739     option->setServerTag(tag);
740 
741     auto& index = options_.get<1>();
742     auto option_it_pair = index.equal_range(option->option_->getType());
743 
744     for (auto option_it = option_it_pair.first;
745          option_it != option_it_pair.second;
746          ++option_it) {
747         if ((option_it->space_name_ == option->space_name_) &&
748             (option_it->hasServerTag(ServerTag(tag)))) {
749             index.replace(option_it, *option);
750             return;
751         }
752     }
753 
754     options_.push_back(*option);
755 }
756 
757 void
createUpdateOption4(const db::ServerSelector & server_selector,const std::string & shared_network_name,const OptionDescriptorPtr & option)758 TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_selector,
759                                              const std::string& shared_network_name,
760                                              const OptionDescriptorPtr& option) {
761     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
762     auto network_it = index.find(shared_network_name);
763 
764     if (network_it == index.end()) {
765         isc_throw(BadValue, "attempted to create or update option in a non existing "
766                   "shared network " << shared_network_name);
767     }
768 
769     auto shared_network = *network_it;
770     bool found = false;
771     if (server_selector.amUnassigned()) {
772         if (shared_network->getServerTags().empty()) {
773             found = true;
774         }
775     } else if (server_selector.amAny()) {
776         found = true;
777     } else if (shared_network->hasAllServerTag()) {
778         found = true;
779     } else {
780         auto tags = server_selector.getTags();
781         for (auto tag : tags) {
782             if (shared_network->hasServerTag(ServerTag(tag))) {
783                 found = true;
784                 break;
785             }
786         }
787     }
788     if (!found) {
789         isc_throw(BadValue, "attempted to create or update option in a "
790                   "shared network " << shared_network_name
791                   << " not present in a selected server");
792     }
793 
794     shared_network->getCfgOption()->del(option->space_name_, option->option_->getType());
795     shared_network->getCfgOption()->add(*option, option->space_name_);
796 }
797 
798 void
createUpdateOption4(const db::ServerSelector & server_selector,const SubnetID & subnet_id,const OptionDescriptorPtr & option)799 TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_selector,
800                                              const SubnetID& subnet_id,
801                                              const OptionDescriptorPtr& option) {
802     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
803     auto subnet_it = index.find(subnet_id);
804 
805     if (subnet_it == index.cend()) {
806         isc_throw(BadValue, "attempted to create or update option in a non existing "
807                   "subnet ID " << subnet_id);
808     }
809 
810     auto subnet = *subnet_it;
811     bool found = false;
812     if (server_selector.amUnassigned()) {
813         if (subnet->getServerTags().empty()) {
814             found = true;
815         }
816     } else if (server_selector.amAny()) {
817         found = true;
818     } else if (subnet->hasAllServerTag()) {
819         found = true;
820     } else {
821         auto tags = server_selector.getTags();
822         for (auto tag : tags) {
823             if (subnet->hasServerTag(ServerTag(tag))) {
824                 found = true;
825                 break;
826             }
827         }
828     }
829     if (!found) {
830         isc_throw(BadValue, "attempted to create or update option in a "
831                   "subnet ID " << subnet_id
832                   << " not present in a selected server");
833     }
834 
835     subnet->getCfgOption()->del(option->space_name_, option->option_->getType());
836     subnet->getCfgOption()->add(*option, option->space_name_);
837 }
838 
839 void
createUpdateOption4(const db::ServerSelector & server_selector,const asiolink::IOAddress & pool_start_address,const asiolink::IOAddress & pool_end_address,const OptionDescriptorPtr & option)840 TestConfigBackendDHCPv4::createUpdateOption4(const db::ServerSelector& server_selector,
841                                              const asiolink::IOAddress& pool_start_address,
842                                              const asiolink::IOAddress& pool_end_address,
843                                              const OptionDescriptorPtr& option) {
844     auto not_in_selected_servers = false;
845     for (auto subnet : subnets_) {
846         // Get the pool: if it is not here we can directly go to the next subnet.
847         auto pool = subnet->getPool(Lease::TYPE_V4, pool_start_address);
848         if (!pool) {
849             continue;
850         }
851 
852         // Verify the subnet is in a selected server.
853         if (server_selector.amUnassigned()) {
854             if (!subnet->getServerTags().empty()) {
855                 not_in_selected_servers = true;
856                 continue;
857             }
858         } else if (!server_selector.amAny() && !subnet->hasAllServerTag()) {
859             auto in_tags = false;
860             auto tags = server_selector.getTags();
861             for (auto tag : tags) {
862                 if (subnet->hasServerTag(ServerTag(tag))) {
863                     in_tags = true;
864                     break;
865                 }
866             }
867             if (!in_tags) {
868                 // Records the fact a subnet was found but not in a server.
869                 not_in_selected_servers = true;
870                 continue;
871             }
872         }
873 
874         // Update the option.
875         pool->getCfgOption()->del(option->space_name_, option->option_->getType());
876         pool->getCfgOption()->add(*option, option->space_name_);
877 
878         return;
879     }
880 
881     if (not_in_selected_servers) {
882         isc_throw(BadValue, "attempted to create or update option in "
883                   "a pool " << pool_start_address
884                   << " - " << pool_end_address
885                   << " not present in a selected server");
886     } else {
887         isc_throw(BadValue, "attempted to create or update option in "
888                   "a non existing pool " << pool_start_address
889                   << " - " << pool_end_address);
890     }
891 }
892 
893 void
createUpdateGlobalParameter4(const db::ServerSelector & server_selector,const data::StampedValuePtr & value)894 TestConfigBackendDHCPv4::createUpdateGlobalParameter4(const db::ServerSelector& server_selector,
895                                                       const data::StampedValuePtr& value) {
896     auto tag = getServerTag(server_selector);
897     value->setServerTag(tag);
898 
899     auto& index = globals_.get<StampedValueNameIndexTag>();
900     auto global_it_pair = index.equal_range(value->getName());
901 
902     for (auto global_it = global_it_pair.first; global_it != global_it_pair.second;
903          ++global_it) {
904         auto existing_value = *global_it;
905         if (existing_value->hasServerTag(ServerTag(tag))) {
906             index.replace(global_it, value);
907             return;
908         }
909     }
910 
911     index.insert(value);
912 }
913 
914 void
createUpdateServer4(const db::ServerPtr & server)915 TestConfigBackendDHCPv4::createUpdateServer4(const db::ServerPtr& server) {
916     auto& index = servers_.get<ServerTagIndexTag>();
917     auto server_it = index.find(server->getServerTagAsText());
918 
919     if (server_it != index.end()) {
920         index.replace(server_it, server);
921 
922     } else {
923         index.insert(server);
924     }
925 }
926 
927 uint64_t
deleteSubnet4(const db::ServerSelector & server_selector,const std::string & subnet_prefix)928 TestConfigBackendDHCPv4::deleteSubnet4(const db::ServerSelector& server_selector,
929                                        const std::string& subnet_prefix) {
930     auto& index = subnets_.get<SubnetPrefixIndexTag>();
931     auto subnet_it = index.find(subnet_prefix);
932     if (subnet_it == index.end()) {
933         return (0);
934     }
935     if ((server_selector.amUnassigned()) &&
936         !(*subnet_it)->getServerTags().empty()) {
937         return (0);
938     }
939     if (!server_selector.amAny()) {
940         bool got = false;
941         auto tags = server_selector.getTags();
942         for (auto tag : tags) {
943             if ((*subnet_it)->hasServerTag(ServerTag(tag))) {
944                 got = true;
945                 break;
946             }
947         }
948         if (!got && !(*subnet_it)->hasAllServerTag()) {
949             return (0);
950         }
951     }
952     return (index.erase(subnet_prefix));
953 }
954 
955 uint64_t
deleteSubnet4(const db::ServerSelector & server_selector,const SubnetID & subnet_id)956 TestConfigBackendDHCPv4::deleteSubnet4(const db::ServerSelector& server_selector,
957                                        const SubnetID& subnet_id) {
958     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
959     auto subnet_it = index.find(subnet_id);
960     if (subnet_it == index.end()) {
961         return (0);
962     }
963     if ((server_selector.amUnassigned()) &&
964         !(*subnet_it)->getServerTags().empty()) {
965         return (0);
966     }
967     if (!server_selector.amAny()) {
968         bool got = false;
969         auto tags = server_selector.getTags();
970         for (auto tag : tags) {
971             if ((*subnet_it)->hasServerTag(ServerTag(tag))) {
972                 got = true;
973                 break;
974             }
975         }
976         if (!got && !(*subnet_it)->hasAllServerTag()) {
977             return (0);
978         }
979     }
980     return (index.erase(subnet_id));
981 }
982 
983 uint64_t
deleteAllSubnets4(const db::ServerSelector & server_selector)984 TestConfigBackendDHCPv4::deleteAllSubnets4(const db::ServerSelector& server_selector) {
985     // Collect subnet to remove by ID.
986     std::list<SubnetID> ids;
987     for (auto subnet : subnets_) {
988         if (server_selector.amAny()) {
989             ids.push_back(subnet->getID());
990             continue;
991         }
992         if (server_selector.amUnassigned()) {
993             if (subnet->getServerTags().empty()) {
994                 ids.push_back(subnet->getID());
995             }
996             continue;
997         }
998         bool got = false;
999         auto tags = server_selector.getTags();
1000         for (auto tag : tags) {
1001             if (subnet->hasServerTag(ServerTag(tag))) {
1002                 ids.push_back(subnet->getID());
1003                 got = true;
1004                 break;
1005             }
1006         }
1007         if (got) {
1008             continue;
1009         }
1010         if (subnet->hasAllServerTag()) {
1011             ids.push_back(subnet->getID());
1012         }
1013     }
1014 
1015     // Erase subnets.
1016     uint64_t erased = 0;
1017     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
1018     for (auto subnet_id : ids) {
1019         erased += index.erase(subnet_id);
1020     }
1021     return (erased);
1022 }
1023 
1024 uint64_t
deleteSharedNetworkSubnets4(const db::ServerSelector & server_selector,const std::string & shared_network_name)1025 TestConfigBackendDHCPv4::deleteSharedNetworkSubnets4(const db::ServerSelector& server_selector,
1026                                                      const std::string& shared_network_name) {
1027     uint64_t cnt = 0;
1028     for (auto subnet = subnets_.begin(); subnet != subnets_.end(); ) {
1029         // Skip subnets which do not match the server selector.
1030         if (server_selector.amUnassigned() &&
1031            !(*subnet)->getServerTags().empty()) {
1032             ++subnet;
1033             continue;
1034         }
1035         if (!server_selector.amAny()) {
1036             bool got = false;
1037             auto tags = server_selector.getTags();
1038             for (auto tag : tags) {
1039                 if ((*subnet)->hasServerTag(ServerTag(tag))) {
1040                     got = true;
1041                     break;
1042                 }
1043             }
1044             if (!got && !(*subnet)->hasAllServerTag()) {
1045                 ++subnet;
1046                 continue;
1047             }
1048         }
1049 
1050         SharedNetwork4Ptr network;
1051         (*subnet)->getSharedNetwork(network);
1052         if (network && (network->getName() == shared_network_name)) {
1053             network->del((*subnet)->getID());
1054         }
1055 
1056         if ((network && (network->getName() == shared_network_name)) ||
1057             ((*subnet)->getSharedNetworkName() == shared_network_name)) {
1058             subnet = subnets_.erase(subnet);
1059             ++cnt;
1060         } else {
1061             ++subnet;
1062         }
1063     }
1064     return (cnt);
1065 }
1066 
1067 uint64_t
deleteSharedNetwork4(const db::ServerSelector & server_selector,const std::string & name)1068 TestConfigBackendDHCPv4::deleteSharedNetwork4(const db::ServerSelector& server_selector,
1069                                               const std::string& name) {
1070     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
1071     auto network_it = index.find(name);
1072     if (network_it == index.end()) {
1073         return (0);
1074     }
1075     if ((server_selector.amUnassigned()) &&
1076         !(*network_it)->getServerTags().empty()) {
1077         return (0);
1078     }
1079     if (!server_selector.amAny()) {
1080         bool got = false;
1081         auto tags = server_selector.getTags();
1082         for (auto tag : tags) {
1083             if ((*network_it)->hasServerTag(ServerTag(tag))) {
1084                 got = true;
1085                 break;
1086             }
1087         }
1088         if (!got && !(*network_it)->hasAllServerTag()) {
1089             return (0);
1090         }
1091     }
1092 
1093     // Remove this shared network.
1094     for (auto subnet = subnets_.begin(); subnet != subnets_.end(); ++subnet) {
1095         if ((*subnet)->getSharedNetworkName() == name) {
1096             (*subnet)->setSharedNetworkName("");
1097         }
1098     }
1099     (*network_it)->delAll();
1100     return (index.erase(name));
1101 }
1102 
1103 uint64_t
deleteAllSharedNetworks4(const db::ServerSelector & server_selector)1104 TestConfigBackendDHCPv4::deleteAllSharedNetworks4(const db::ServerSelector& server_selector) {
1105     // Collect shared network to remove.
1106     std::list<std::string> names;
1107     for (auto shared_network : shared_networks_) {
1108         if (server_selector.amAny()) {
1109             names.push_back(shared_network->getName());
1110             continue;
1111         }
1112         if (server_selector.amUnassigned()) {
1113             if (shared_network->getServerTags().empty()) {
1114                 names.push_back(shared_network->getName());
1115             }
1116             continue;
1117         }
1118         bool got = false;
1119         auto tags = server_selector.getTags();
1120         for (auto tag : tags) {
1121             if (shared_network->hasServerTag(ServerTag(tag))) {
1122                 names.push_back(shared_network->getName());
1123                 got = true;
1124                 break;
1125             }
1126         }
1127         if (got) {
1128             continue;
1129         }
1130         if (shared_network->hasAllServerTag()) {
1131             names.push_back(shared_network->getName());
1132         }
1133     }
1134 
1135     // Erase shared networks.
1136     uint64_t erased = 0;
1137     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
1138     for (auto name : names) {
1139         erased += index.erase(name);
1140     }
1141     return (erased);
1142 }
1143 
1144 uint64_t
deleteOptionDef4(const db::ServerSelector & server_selector,const uint16_t code,const std::string & space)1145 TestConfigBackendDHCPv4::deleteOptionDef4(const db::ServerSelector& server_selector,
1146                                           const uint16_t code,
1147                                           const std::string& space) {
1148     auto tag = getServerTag(server_selector);
1149     uint64_t erased = 0;
1150     for (auto option_def_it = option_defs_.begin(); option_def_it != option_defs_.end(); ) {
1151         if (((*option_def_it)->getCode() == code) &&
1152             ((*option_def_it)->getOptionSpaceName() == space) &&
1153             ((*option_def_it)->hasServerTag(ServerTag(tag)))) {
1154             option_def_it = option_defs_.erase(option_def_it);
1155             ++erased;
1156         } else {
1157             ++option_def_it;
1158         }
1159     }
1160     return (erased);
1161 }
1162 
1163 uint64_t
deleteAllOptionDefs4(const db::ServerSelector & server_selector)1164 TestConfigBackendDHCPv4::deleteAllOptionDefs4(const db::ServerSelector& server_selector) {
1165     auto tag = getServerTag(server_selector);
1166     uint64_t erased = 0;
1167     for (auto option_def_it = option_defs_.begin(); option_def_it != option_defs_.end(); ) {
1168         if ((*option_def_it)->hasServerTag(ServerTag(tag))) {
1169             option_def_it = option_defs_.erase(option_def_it);
1170             ++erased;
1171         } else {
1172             ++option_def_it;
1173         }
1174     }
1175     return (erased);
1176 }
1177 
1178 uint64_t
deleteOption4(const db::ServerSelector & server_selector,const uint16_t code,const std::string & space)1179 TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& server_selector,
1180                                        const uint16_t code,
1181                                        const std::string& space) {
1182     auto tag = getServerTag(server_selector);
1183     uint64_t erased = 0;
1184     for (auto option_it = options_.begin(); option_it != options_.end(); ) {
1185         if ((option_it->option_->getType() == code) &&
1186             (option_it->space_name_ == space) &&
1187             (option_it->hasServerTag(ServerTag(tag)))) {
1188             option_it = options_.erase(option_it);
1189             ++erased;
1190         } else {
1191             ++option_it;
1192         }
1193     }
1194     return (erased);
1195 }
1196 
1197 uint64_t
deleteOption4(const db::ServerSelector & server_selector,const std::string & shared_network_name,const uint16_t code,const std::string & space)1198 TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& server_selector,
1199                                        const std::string& shared_network_name,
1200                                        const uint16_t code,
1201                                        const std::string& space) {
1202     auto& index = shared_networks_.get<SharedNetworkNameIndexTag>();
1203     auto network_it = index.find(shared_network_name);
1204 
1205     if (network_it == index.end()) {
1206         isc_throw(BadValue, "attempted to delete an option in a non existing "
1207                   "shared network " << shared_network_name);
1208     }
1209 
1210     auto shared_network = *network_it;
1211     bool found = false;
1212     if (server_selector.amUnassigned()) {
1213         if (shared_network->getServerTags().empty()) {
1214             found = true;
1215         }
1216     } else if (server_selector.amAny()) {
1217         found = true;
1218     } else if (shared_network->hasAllServerTag()) {
1219         found = true;
1220     } else {
1221         auto tags = server_selector.getTags();
1222         for (auto tag : tags) {
1223             if (shared_network->hasServerTag(ServerTag(tag))) {
1224                 found = true;
1225                 break;
1226             }
1227         }
1228     }
1229     if (!found) {
1230         isc_throw(BadValue, "attempted to delete option in a "
1231                   "shared network " << shared_network_name
1232                   << " not present in a selected server");
1233     }
1234 
1235     return (shared_network->getCfgOption()->del(space, code));
1236 }
1237 
1238 uint64_t
deleteOption4(const db::ServerSelector & server_selector,const SubnetID & subnet_id,const uint16_t code,const std::string & space)1239 TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& server_selector,
1240                                        const SubnetID& subnet_id,
1241                                        const uint16_t code,
1242                                        const std::string& space) {
1243     auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
1244     auto subnet_it = index.find(subnet_id);
1245 
1246     if (subnet_it == index.cend()) {
1247         isc_throw(BadValue, "attempted to delete an option in a non existing "
1248                   "subnet ID " << subnet_id);
1249     }
1250 
1251     auto subnet = *subnet_it;
1252     bool found = false;
1253     if (server_selector.amUnassigned()) {
1254         if (subnet->getServerTags().empty()) {
1255             found = true;
1256         }
1257     } else if (server_selector.amAny()) {
1258         found = true;
1259     } else if (subnet->hasAllServerTag()) {
1260         found = true;
1261     } else {
1262         auto tags = server_selector.getTags();
1263         for (auto tag : tags) {
1264             if (subnet->hasServerTag(ServerTag(tag))) {
1265                 found = true;
1266                 break;
1267             }
1268         }
1269     }
1270     if (!found) {
1271         isc_throw(BadValue, "attempted to delete option in a "
1272                   "subnet ID " << subnet_id
1273                   << " not present in a selected server");
1274     }
1275 
1276     return (subnet->getCfgOption()->del(space, code));
1277 }
1278 
1279 uint64_t
deleteOption4(const db::ServerSelector & server_selector,const asiolink::IOAddress & pool_start_address,const asiolink::IOAddress & pool_end_address,const uint16_t code,const std::string & space)1280 TestConfigBackendDHCPv4::deleteOption4(const db::ServerSelector& server_selector,
1281                                        const asiolink::IOAddress& pool_start_address,
1282                                        const asiolink::IOAddress& pool_end_address,
1283                                        const uint16_t code,
1284                                        const std::string& space) {
1285     auto not_in_selected_servers = false;
1286     for (auto subnet : subnets_) {
1287         // Get the pool: if it is not here we can directly go to the next subnet.
1288 
1289         auto pool = subnet->getPool(Lease::TYPE_V4, pool_start_address);
1290         if (!pool) {
1291             continue;
1292         }
1293 
1294         // Verify the subnet is in a selected server.
1295         if (server_selector.amUnassigned()) {
1296             if (!subnet->getServerTags().empty()) {
1297                 not_in_selected_servers = true;
1298                 continue;
1299             }
1300         } else if (!server_selector.amAny() && !subnet->hasAllServerTag()) {
1301             auto in_tags = false;
1302             auto tags = server_selector.getTags();
1303             for (auto tag : tags) {
1304                 if (subnet->hasServerTag(ServerTag(tag))) {
1305                     in_tags = true;
1306                     break;
1307                 }
1308             }
1309             if (!in_tags) {
1310                 // Records the fact a subnet was found but not in a server.
1311                 not_in_selected_servers = true;
1312                 continue;
1313             }
1314         }
1315 
1316         return (pool->getCfgOption()->del(space, code));
1317     }
1318 
1319     if (not_in_selected_servers) {
1320         isc_throw(BadValue, "attempted to delete an option in a pool "
1321                   << pool_start_address << " - " << pool_end_address
1322                   << " not present in a selected server");
1323     } else {
1324         isc_throw(BadValue, "attempted to delete an option in a non existing "
1325                   "pool " << pool_start_address << " - " << pool_end_address);
1326     }
1327 }
1328 
1329 uint64_t
deleteGlobalParameter4(const db::ServerSelector & server_selector,const std::string & name)1330 TestConfigBackendDHCPv4::deleteGlobalParameter4(const db::ServerSelector& server_selector,
1331                                                 const std::string& name) {
1332     auto tag = getServerTag(server_selector);
1333     auto& index = globals_.get<StampedValueNameIndexTag>();
1334     auto global_it_pair = index.equal_range(name);
1335 
1336     for (auto global_it = global_it_pair.first; global_it != global_it_pair.second;
1337          ++global_it) {
1338         auto value = *global_it;
1339         if (value->hasServerTag(ServerTag(tag))) {
1340             index.erase(global_it);
1341             return (1);
1342         }
1343     }
1344     return (0);
1345 }
1346 
1347 uint64_t
deleteAllGlobalParameters4(const db::ServerSelector & server_selector)1348 TestConfigBackendDHCPv4::deleteAllGlobalParameters4(const db::ServerSelector& server_selector) {
1349     auto tag = getServerTag(server_selector);
1350     uint64_t cnt = 0;
1351     for (auto global_it = globals_.begin(); global_it != globals_.end(); ) {
1352         auto value = *global_it;
1353         if (value->hasServerTag(ServerTag(tag))) {
1354             global_it = globals_.erase(global_it);
1355             cnt++;
1356         } else {
1357             ++global_it;
1358         }
1359     }
1360     return (cnt);
1361 }
1362 
1363 uint64_t
deleteClientClass4(const db::ServerSelector & server_selector,const std::string & name)1364 TestConfigBackendDHCPv4::deleteClientClass4(const db::ServerSelector& server_selector,
1365                                             const std::string& name) {
1366     ClientClassDefPtr existing_class;
1367     auto c = classes_.begin();
1368     for (; c != classes_.end(); ++c) {
1369         if ((*c)->getName() == name) {
1370             existing_class = (*c);
1371             break;
1372         }
1373     }
1374     if (!existing_class) {
1375         return (0);
1376     }
1377     if ((server_selector.amUnassigned()) &&
1378         !existing_class->getServerTags().empty()) {
1379         return (0);
1380     }
1381     if (!server_selector.amAny()) {
1382         bool got = false;
1383         auto tags = server_selector.getTags();
1384         for (auto tag : tags) {
1385             if (existing_class->hasServerTag(ServerTag(tag))) {
1386                 got = true;
1387                 break;
1388             }
1389         }
1390         if (!got && !existing_class->hasAllServerTag()) {
1391             return (0);
1392         }
1393     }
1394     classes_.erase(c);
1395     return (1);
1396 }
1397 
1398 uint64_t
deleteAllClientClasses4(const db::ServerSelector & server_selector)1399 TestConfigBackendDHCPv4::deleteAllClientClasses4(const db::ServerSelector& server_selector) {
1400     uint64_t count = 0;
1401     for (auto c = classes_.begin(); c != classes_.end(); ++c) {
1402         auto client_class = *c;
1403         if (server_selector.amAny()) {
1404             c = classes_.erase(c);
1405             ++count;
1406             continue;
1407         }
1408         if (server_selector.amUnassigned()) {
1409             if (client_class->getServerTags().empty()) {
1410                 c = classes_.erase(c);
1411                 ++count;
1412             }
1413             continue;
1414         }
1415         bool got = false;
1416         auto tags = server_selector.getTags();
1417         for (auto tag : tags) {
1418             if (client_class->hasServerTag(ServerTag(tag))) {
1419                 c = classes_.erase(c);
1420                 ++count;
1421                 got = true;
1422                 break;
1423             }
1424         }
1425         if (got) {
1426             continue;
1427         }
1428         if (client_class->hasAllServerTag()) {
1429             c = classes_.erase(c);
1430             ++count;
1431         }
1432     }
1433 
1434     return (count);
1435 }
1436 
1437 uint64_t
deleteServer4(const ServerTag & server_tag)1438 TestConfigBackendDHCPv4::deleteServer4(const ServerTag& server_tag) {
1439     auto& index = servers_.get<ServerTagIndexTag>();
1440     return (index.erase(server_tag.get()));
1441 }
1442 
1443 uint64_t
deleteAllServers4()1444 TestConfigBackendDHCPv4::deleteAllServers4() {
1445     auto servers_size = servers_.size();
1446     servers_.clear();
1447     return (servers_size);
1448 }
1449 
1450 } // namespace test
1451 } // namespace dhcp
1452 } // namespace isc
1453