GET_GLOBAL_PARAMETER4,
GET_ALL_GLOBAL_PARAMETERS4,
GET_MODIFIED_GLOBAL_PARAMETERS4,
- GET_SUBNET4_ID,
- GET_SUBNET4_PREFIX,
+ GET_SUBNET4_ID_NO_TAG,
+ GET_SUBNET4_ID_ANY,
+ GET_SUBNET4_ID_UNASSIGNED,
+ GET_SUBNET4_PREFIX_NO_TAG,
+ GET_SUBNET4_PREFIX_ANY,
+ GET_SUBNET4_PREFIX_UNASSIGNED,
GET_ALL_SUBNETS4,
+ GET_ALL_SUBNETS4_UNASSIGNED,
GET_MODIFIED_SUBNETS4,
+ GET_MODIFIED_SUBNETS4_UNASSIGNED,
GET_SHARED_NETWORK_SUBNETS4,
GET_POOL4_RANGE,
GET_SHARED_NETWORK4_NAME_NO_TAG,
DELETE_SUBNET4_PREFIX,
DELETE_ALL_SUBNETS4,
DELETE_ALL_SUBNETS4_SHARED_NETWORK_NAME,
+ DELETE_SUBNET4_SERVER,
DELETE_POOLS4_SUBNET_ID,
DELETE_SHARED_NETWORK4_NAME_WITH_TAG,
DELETE_SHARED_NETWORK4_NAME_ANY,
/// Query should order subnets by subnet_id.
///
/// @param index Index of the query to be used.
+ /// @param server_selector Server selector.
/// @param in_bindings Input bindings specifying selection criteria. The
/// size of the bindings collection must match the number of placeholders
/// in the prepared statement. The input bindings collection must be empty
/// @param [out] subnets Reference to the container where fetched subnets
/// will be inserted.
void getSubnets4(const StatementIndex& index,
+ const ServerSelector& server_selector,
const MySqlBindingCollection& in_bindings,
Subnet4Collection& subnets) {
// Create output bindings. The order must match that in the prepared
uint64_t last_pool_id = 0;
uint64_t last_pool_option_id = 0;
uint64_t last_option_id = 0;
-
Pool4Ptr last_pool;
+ std::string last_tag;
// Execute actual query.
conn_.selectQuery(index, in_bindings, out_bindings,
[this, &subnets, &last_pool, &last_pool_id,
- &last_pool_option_id, &last_option_id]
+ &last_pool_option_id, &last_option_id,
+ &last_tag]
(MySqlBindingCollection& out_bindings) {
// Get pointer to the last subnet in the collection.
Subnet4Ptr last_subnet;
// rows will contain pool information.
last_pool_id = 0;
+ // Reset last server tag as we're now starting to process new subnet.
+ last_tag.clear();
+
// subnet_id
SubnetID subnet_id(out_bindings[0]->getInteger<uint32_t>());
// subnet_prefix
// {min,max}_valid_lifetime
- // server_tag
- last_subnet->setServerTag(out_bindings[55]->getString());
-
// Subnet ready. Add it to the list.
auto ret = subnets.push_back(last_subnet);
}
}
+ // Check for new server tags.
+ if (!out_bindings[55]->amNull() &&
+ (last_tag != out_bindings[55]->getString())) {
+ last_tag = out_bindings[55]->getString();
+ if (!last_tag.empty() && !last_subnet->hasServerTag(ServerTag(last_tag))) {
+ last_subnet->setServerTag(last_tag);
+ }
+ }
+
// If the row contains information about the pool and it appears to be
// new pool entry (checked by comparing pool id), let's create the new
// pool and add it to the subnet.
last_subnet->getCfgOption()->add(*desc, desc->space_name_);
}
}
-
});
+
+ // Now that we're done fetching the whole subnet, we have to
+ // check if it has matching server tags and toss it if it
+ // doesn't. We skip matching the server tags if we're asking
+ // for ANY subnet.
+ auto& subnet_index = subnets.get<SubnetRandomAccessIndexTag>();
+ tossNonMatchingElements(server_selector, subnet_index);
}
/// @brief Sends query to retrieve single subnet by id.
/// doesn't exist.
Subnet4Ptr getSubnet4(const ServerSelector& server_selector,
const SubnetID& subnet_id) {
- Subnet4Collection subnets;
- auto tags = server_selector.getTags();
- for (auto tag : tags) {
- MySqlBindingCollection in_bindings = {
- MySqlBinding::createString(tag.get()),
- MySqlBinding::createInteger<uint32_t>(subnet_id)
- };
+ if (server_selector.hasMultipleTags()) {
+ isc_throw(InvalidOperation, "expected one server tag to be specified"
+ " while fetching a subnet. Got: "
+ << getServerTagsAsText(server_selector));
+ }
+
+ MySqlBindingCollection in_bindings = { MySqlBinding::createInteger<uint32_t>(subnet_id) };
+
+ auto index = GET_SUBNET4_ID_NO_TAG;
- getSubnets4(GET_SUBNET4_ID, in_bindings, subnets);
+ if (server_selector.amUnassigned()) {
+ index = GET_SUBNET4_ID_UNASSIGNED;
+
+ } else if (server_selector.amAny()) {
+ index = GET_SUBNET4_ID_ANY;
}
+ Subnet4Collection subnets;
+ getSubnets4(index, server_selector, in_bindings, subnets);
+
return (subnets.empty() ? Subnet4Ptr() : *subnets.begin());
}
/// doesn't exist.
Subnet4Ptr getSubnet4(const ServerSelector& server_selector,
const std::string& subnet_prefix) {
- Subnet4Collection subnets;
+ if (server_selector.hasMultipleTags()) {
+ isc_throw(InvalidOperation, "expected one server tag to be specified"
+ " while fetching a subnet. Got: "
+ << getServerTagsAsText(server_selector));
+ }
- auto tags = server_selector.getTags();
- for (auto tag : tags) {
- MySqlBindingCollection in_bindings = {
- MySqlBinding::createString(tag.get()),
- MySqlBinding::createString(subnet_prefix)
- };
+ MySqlBindingCollection in_bindings = { MySqlBinding::createString(subnet_prefix) };
- getSubnets4(GET_SUBNET4_PREFIX, in_bindings, subnets);
+ auto index = GET_SUBNET4_PREFIX_NO_TAG;
+
+ if (server_selector.amUnassigned()) {
+ index = GET_SUBNET4_PREFIX_UNASSIGNED;
+
+ } else if (server_selector.amAny()) {
+ index = GET_SUBNET4_PREFIX_ANY;
}
+ Subnet4Collection subnets;
+ getSubnets4(index, server_selector, in_bindings, subnets);
+
return (subnets.empty() ? Subnet4Ptr() : *subnets.begin());
}
/// subnets should be inserted.
void getAllSubnets4(const ServerSelector& server_selector,
Subnet4Collection& subnets) {
- auto tags = server_selector.getTags();
-
- for (auto tag : tags) {
- MySqlBindingCollection in_bindings = {
- MySqlBinding::createString(tag.get())
- };
-
- getSubnets4(GET_ALL_SUBNETS4, in_bindings, subnets);
- }
+ auto index = (server_selector.amUnassigned() ? GET_ALL_SUBNETS4_UNASSIGNED :
+ GET_ALL_SUBNETS4);
+ MySqlBindingCollection in_bindings;
+ getSubnets4(index, server_selector, in_bindings, subnets);
}
/// @brief Sends query to retrieve modified subnets.
void getModifiedSubnets4(const ServerSelector& server_selector,
const boost::posix_time::ptime& modification_ts,
Subnet4Collection& subnets) {
- auto tags = server_selector.getTags();
-
- for (auto tag : tags) {
- MySqlBindingCollection in_bindings = {
- MySqlBinding::createString(tag.get()),
- MySqlBinding::createTimestamp(modification_ts)
- };
+ MySqlBindingCollection in_bindings = {
+ MySqlBinding::createTimestamp(modification_ts)
+ };
- getSubnets4(GET_MODIFIED_SUBNETS4, in_bindings, subnets);
- }
+ auto index = (server_selector.amUnassigned() ? GET_MODIFIED_SUBNETS4_UNASSIGNED :
+ GET_MODIFIED_SUBNETS4);
+ getSubnets4(index, server_selector, in_bindings, subnets);
}
/// @brief Sends query to retrieve all subnets belonging to a shared network.
void getSharedNetworkSubnets4(const ServerSelector& server_selector,
const std::string& shared_network_name,
Subnet4Collection& subnets) {
- auto tags = server_selector.getTags();
-
- for (auto tag : tags) {
- MySqlBindingCollection in_bindings = {
- MySqlBinding::createString(tag.get()),
- MySqlBinding::createString(shared_network_name)
- };
-
- getSubnets4(GET_SHARED_NETWORK_SUBNETS4, in_bindings, subnets);
- }
+ MySqlBindingCollection in_bindings = { MySqlBinding::createString(shared_network_name) };
+ getSubnets4(GET_SHARED_NETWORK_SUBNETS4, server_selector, in_bindings, subnets);
}
/// @brief Sends query to retrieve multiple pools.
" (unassigned) is unsupported at the moment");
}
- auto tag = getServerTag(server_selector, "creating or updating subnet");
-
// Convert DHCPv4o6 interface id to text.
OptionPtr dhcp4o6_interface_id = subnet->get4o6().getInterfaceId();
MySqlBindingPtr dhcp4o6_interface_id_binding;
conn_.insertQuery(MySqlConfigBackendDHCPv4Impl::INSERT_SUBNET4,
in_bindings);
- // Insert associations with the servers.
- attachElementToServers(MySqlConfigBackendDHCPv4Impl::INSERT_SUBNET4_SERVER,
- server_selector,
- MySqlBinding::createInteger<uint32_t>(subnet->getID()),
- MySqlBinding::createTimestamp(subnet->getModificationTime()));
-
} catch (const DuplicateEntry&) {
deletePools4(subnet);
deleteOptions4(ServerSelector::ANY(), subnet);
in_bindings.push_back(MySqlBinding::createString(subnet->toText()));
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::UPDATE_SUBNET4,
in_bindings);
+
+ MySqlBindingCollection in_server_bindings = {
+ MySqlBinding::createInteger<uint32_t>(subnet->getID())
+ };
+ conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_SERVER,
+ in_server_bindings);
}
+
+ // Insert associations with the servers.
+ attachElementToServers(MySqlConfigBackendDHCPv4Impl::INSERT_SUBNET4_SERVER,
+ server_selector,
+ MySqlBinding::createInteger<uint32_t>(subnet->getID()),
+ MySqlBinding::createTimestamp(subnet->getModificationTime()));
+
// (Re)create pools.
for (auto pool : subnet->getPools(Lease::TYPE_V4)) {
createPool4(server_selector, boost::dynamic_pointer_cast<Pool4>(pool),
" (unassigned) is unsupported at the moment");
}
- auto tag = getServerTag(server_selector,
- "creating or updating subnet level option");
-
MySqlBindingCollection in_bindings = {
MySqlBinding::createInteger<uint8_t>(option->option_->getType()),
createOptionValueBinding(option),
MySqlBinding::createNull(),
MySqlBinding::createNull(),
MySqlBinding::createTimestamp(option->getModificationTime()),
- MySqlBinding::createString(tag),
MySqlBinding::createInteger<uint32_t>(static_cast<uint32_t>(subnet_id)),
MySqlBinding::createInteger<uint8_t>(option->option_->getType()),
MySqlBinding::condCreateString(option->space_name_)
if (conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::UPDATE_OPTION4_SUBNET_ID,
in_bindings) == 0) {
- // Remove the 4 bindings used only in case of update.
- in_bindings.resize(in_bindings.size() - 4);
+ // Remove the 3 bindings used only in case of update.
+ in_bindings.resize(in_bindings.size() - 3);
insertOption4(server_selector, in_bindings);
}
},
// Select subnet by id.
- { MySqlConfigBackendDHCPv4Impl::GET_SUBNET4_ID,
- MYSQL_GET_SUBNET4(AND s.subnet_id = ?)
+ { MySqlConfigBackendDHCPv4Impl::GET_SUBNET4_ID_NO_TAG,
+ MYSQL_GET_SUBNET4_NO_TAG(WHERE s.subnet_id = ?)
+ },
+
+ // Select subnet by id without specifying server tags.
+ { MySqlConfigBackendDHCPv4Impl::GET_SUBNET4_ID_ANY,
+ MYSQL_GET_SUBNET4_ANY(WHERE s.subnet_id = ?)
+ },
+
+ // Select unassigned subnet by id.
+ { MySqlConfigBackendDHCPv4Impl::GET_SUBNET4_ID_UNASSIGNED,
+ MYSQL_GET_SUBNET4_UNASSIGNED(AND s.subnet_id = ?)
},
// Select subnet by prefix.
- { MySqlConfigBackendDHCPv4Impl::GET_SUBNET4_PREFIX,
- MYSQL_GET_SUBNET4(AND s.subnet_prefix = ?)
+ { MySqlConfigBackendDHCPv4Impl::GET_SUBNET4_PREFIX_NO_TAG,
+ MYSQL_GET_SUBNET4_NO_TAG(WHERE s.subnet_prefix = ?)
+ },
+
+ // Select subnet by prefix without specifying server tags.
+ { MySqlConfigBackendDHCPv4Impl::GET_SUBNET4_PREFIX_ANY,
+ MYSQL_GET_SUBNET4_ANY(WHERE s.subnet_prefix = ?)
+ },
+
+ // Select unassigned subnet by prefix.
+ { MySqlConfigBackendDHCPv4Impl::GET_SUBNET4_PREFIX_UNASSIGNED,
+ MYSQL_GET_SUBNET4_UNASSIGNED(AND s.subnet_prefix = ?)
},
// Select all subnets.
{ MySqlConfigBackendDHCPv4Impl::GET_ALL_SUBNETS4,
- MYSQL_GET_SUBNET4()
+ MYSQL_GET_SUBNET4_NO_TAG()
+ },
+
+ // Select all unassigned subnets.
+ { MySqlConfigBackendDHCPv4Impl::GET_ALL_SUBNETS4_UNASSIGNED,
+ MYSQL_GET_SUBNET4_UNASSIGNED()
},
// Select subnets having modification time later than X.
{ MySqlConfigBackendDHCPv4Impl::GET_MODIFIED_SUBNETS4,
- MYSQL_GET_SUBNET4(AND s.modification_ts > ?)
+ MYSQL_GET_SUBNET4_NO_TAG(WHERE s.modification_ts > ?)
+ },
+
+ // Select modified and unassigned subnets.
+ { MySqlConfigBackendDHCPv4Impl::GET_MODIFIED_SUBNETS4_UNASSIGNED,
+ MYSQL_GET_SUBNET4_UNASSIGNED(AND s.modification_ts > ?)
},
// Select subnets belonging to a shared network.
{ MySqlConfigBackendDHCPv4Impl::GET_SHARED_NETWORK_SUBNETS4,
- MYSQL_GET_SUBNET4(AND s.shared_network_name = ?)
+ MYSQL_GET_SUBNET4_NO_TAG(WHERE s.shared_network_name = ?)
},
// Select pool by address range.
// Update existing subnet level option.
{ MySqlConfigBackendDHCPv4Impl::UPDATE_OPTION4_SUBNET_ID,
- MYSQL_UPDATE_OPTION4_WITH_TAG(AND o.scope_id = 1 AND o.dhcp4_subnet_id = ? AND o.code = ? AND o.space = ?)
+ MYSQL_UPDATE_OPTION4_NO_TAG(o.scope_id = 1 AND o.dhcp4_subnet_id = ? AND o.code = ? AND o.space = ?)
},
// Update existing pool level option.
MYSQL_DELETE_SUBNET(dhcp4, AND s.shared_network_name = ?)
},
+ // Delete associations of a subnet with server.
+ { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_SERVER,
+ MYSQL_DELETE_SUBNET_SERVER(dhcp4),
+ },
+
// Delete pools for a subnet.
{ MySqlConfigBackendDHCPv4Impl::DELETE_POOLS4_SUBNET_ID,
MYSQL_DELETE_POOLS(dhcp4)
GET_GLOBAL_PARAMETER6,
GET_ALL_GLOBAL_PARAMETERS6,
GET_MODIFIED_GLOBAL_PARAMETERS6,
- GET_SUBNET6_ID,
- GET_SUBNET6_PREFIX,
+ GET_SUBNET6_ID_NO_TAG,
+ GET_SUBNET6_ID_ANY,
+ GET_SUBNET6_ID_UNASSIGNED,
+ GET_SUBNET6_PREFIX_NO_TAG,
+ GET_SUBNET6_PREFIX_ANY,
+ GET_SUBNET6_PREFIX_UNASSIGNED,
GET_ALL_SUBNETS6,
+ GET_ALL_SUBNETS6_UNASSIGNED,
GET_MODIFIED_SUBNETS6,
+ GET_MODIFIED_SUBNETS6_UNASSIGNED,
GET_SHARED_NETWORK_SUBNETS6,
GET_POOL6_RANGE,
GET_PD_POOL,
DELETE_SUBNET6_PREFIX,
DELETE_ALL_SUBNETS6,
DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME,
+ DELETE_SUBNET6_SERVER,
DELETE_POOLS6_SUBNET_ID,
DELETE_PD_POOLS_SUBNET_ID,
DELETE_SHARED_NETWORK6_NAME_WITH_TAG,
/// Query should order subnets by subnet_id.
///
/// @param index Index of the query to be used.
+ /// @param server_selector Server selector.
/// @param in_bindings Input bindings specifying selection criteria. The
/// size of the bindings collection must match the number of placeholders
/// in the prepared statement. The input bindings collection must be empty
/// @param [out] subnets Reference to the container where fetched subnets
/// will be inserted.
void getSubnets6(const StatementIndex& index,
+ const ServerSelector& server_selector,
const MySqlBindingCollection& in_bindings,
Subnet6Collection& subnets) {
// Create output bindings. The order must match that in the prepared
uint64_t last_pool_option_id = 0;
uint64_t last_pd_pool_option_id = 0;
uint64_t last_option_id = 0;
-
Pool6Ptr last_pool;
Pool6Ptr last_pd_pool;
+ std::string last_tag;
// Execute actual query.
conn_.selectQuery(index, in_bindings, out_bindings,
[this, &subnets, &last_pool, &last_pd_pool,
&last_pool_id, &last_pd_pool_id,
&last_pool_option_id, &last_pd_pool_option_id,
- &last_option_id]
+ &last_option_id, &last_tag]
(MySqlBindingCollection& out_bindings) {
// Get pointer to the last subnet in the collection.
Subnet6Ptr last_subnet;
last_pool_id = 0;
last_pd_pool_id = 0;
+ // Reset last server tag as we're now starting to process new subnet.
+ last_tag.clear();
+
// subnet_id
SubnetID subnet_id(out_bindings[0]->getInteger<uint32_t>());
// 71 and 72 are {min,max}_valid_lifetime
- // server_tag
- last_subnet->setServerTag(out_bindings[73]->getString());
-
// Subnet ready. Add it to the list.
auto ret = subnets.push_back(last_subnet);
}
}
+ // Check for new server tags.
+ if (!out_bindings[73]->amNull() &&
+ (last_tag != out_bindings[73]->getString())) {
+ last_tag = out_bindings[73]->getString();
+ if (!last_tag.empty() && !last_subnet->hasServerTag(ServerTag(last_tag))) {
+ last_subnet->setServerTag(last_tag);
+ }
+ }
+
// Pool is between 15 and 19
// If the row contains information about the pool and it
last_subnet->getCfgOption()->add(*desc, desc->space_name_);
}
}
-
});
+
+ // Now that we're done fetching the whole subnet, we have to
+ // check if it has matching server tags and toss it if it
+ // doesn't. We skip matching the server tags if we're asking
+ // for ANY subnet.
+ auto& subnet_index = subnets.get<SubnetRandomAccessIndexTag>();
+ tossNonMatchingElements(server_selector, subnet_index);
}
/// @brief Sends query to retrieve single subnet by id.
/// doesn't exist.
Subnet6Ptr getSubnet6(const ServerSelector& server_selector,
const SubnetID& subnet_id) {
- Subnet6Collection subnets;
+ if (server_selector.hasMultipleTags()) {
+ isc_throw(InvalidOperation, "expected one server tag to be specified"
+ " while fetching a subnet. Got: "
+ << getServerTagsAsText(server_selector));
+ }
- auto tags = server_selector.getTags();
- for (auto tag : tags) {
- MySqlBindingCollection in_bindings = {
- MySqlBinding::createString(tag.get()),
- MySqlBinding::createInteger<uint32_t>(subnet_id)
- };
+ MySqlBindingCollection in_bindings = { MySqlBinding::createInteger<uint32_t>(subnet_id) };
- getSubnets6(GET_SUBNET6_ID, in_bindings, subnets);
+ auto index = GET_SUBNET6_ID_NO_TAG;
+
+ if (server_selector.amUnassigned()) {
+ index = GET_SUBNET6_ID_UNASSIGNED;
+
+ } else if (server_selector.amAny()) {
+ index = GET_SUBNET6_ID_ANY;
}
+ Subnet6Collection subnets;
+ getSubnets6(index, server_selector, in_bindings, subnets);
+
return (subnets.empty() ? Subnet6Ptr() : *subnets.begin());
}
/// doesn't exist.
Subnet6Ptr getSubnet6(const ServerSelector& server_selector,
const std::string& subnet_prefix) {
- Subnet6Collection subnets;
+ if (server_selector.hasMultipleTags()) {
+ isc_throw(InvalidOperation, "expected one server tag to be specified"
+ " while fetching a subnet. Got: "
+ << getServerTagsAsText(server_selector));
+ }
- auto tags = server_selector.getTags();
- for (auto tag : tags) {
- MySqlBindingCollection in_bindings = {
- MySqlBinding::createString(tag.get()),
- MySqlBinding::createString(subnet_prefix)
- };
+ MySqlBindingCollection in_bindings = { MySqlBinding::createString(subnet_prefix) };
+
+ auto index = GET_SUBNET6_PREFIX_NO_TAG;
+
+ if (server_selector.amUnassigned()) {
+ index = GET_SUBNET6_PREFIX_UNASSIGNED;
- getSubnets6(GET_SUBNET6_PREFIX, in_bindings, subnets);
+ } else if (server_selector.amAny()) {
+ index = GET_SUBNET6_PREFIX_ANY;
}
+ Subnet6Collection subnets;
+ getSubnets6(index, server_selector, in_bindings, subnets);
+
return (subnets.empty() ? Subnet6Ptr() : *subnets.begin());
}
/// subnets should be inserted.
void getAllSubnets6(const ServerSelector& server_selector,
Subnet6Collection& subnets) {
- auto tags = server_selector.getTags();
-
- for (auto tag : tags) {
- MySqlBindingCollection in_bindings = {
- MySqlBinding::createString(tag.get())
- };
-
- getSubnets6(GET_ALL_SUBNETS6, in_bindings, subnets);
- }
+ auto index = (server_selector.amUnassigned() ? GET_ALL_SUBNETS6_UNASSIGNED :
+ GET_ALL_SUBNETS6);
+ MySqlBindingCollection in_bindings;
+ getSubnets6(index, server_selector, in_bindings, subnets);
}
/// @brief Sends query to retrieve modified subnets.
void getModifiedSubnets6(const ServerSelector& server_selector,
const boost::posix_time::ptime& modification_ts,
Subnet6Collection& subnets) {
- auto tags = server_selector.getTags();
-
- for (auto tag : tags) {
- MySqlBindingCollection in_bindings = {
- MySqlBinding::createString(tag.get()),
- MySqlBinding::createTimestamp(modification_ts)
- };
+ MySqlBindingCollection in_bindings = {
+ MySqlBinding::createTimestamp(modification_ts)
+ };
- getSubnets6(GET_MODIFIED_SUBNETS6, in_bindings, subnets);
- }
+ auto index = (server_selector.amUnassigned() ? GET_MODIFIED_SUBNETS6_UNASSIGNED :
+ GET_MODIFIED_SUBNETS6);
+ getSubnets6(index, server_selector, in_bindings, subnets);
}
/// @brief Sends query to retrieve all subnets belonging to a shared network.
void getSharedNetworkSubnets6(const ServerSelector& server_selector,
const std::string& shared_network_name,
Subnet6Collection& subnets) {
- auto tags = server_selector.getTags();
-
- for (auto tag : tags) {
- MySqlBindingCollection in_bindings = {
- MySqlBinding::createString(tag.get()),
- MySqlBinding::createString(shared_network_name)
- };
-
- getSubnets6(GET_SHARED_NETWORK_SUBNETS6, in_bindings, subnets);
- }
+ MySqlBindingCollection in_bindings = { MySqlBinding::createString(shared_network_name) };
+ getSubnets6(GET_SHARED_NETWORK_SUBNETS6, server_selector, in_bindings, subnets);
}
/// @brief Sends query to retrieve multiple pools.
" (unassigned) is unsupported at the moment");
}
- auto tag = getServerTag(server_selector, "creating or updating subnet");
-
// Create JSON list of required classes.
ElementPtr required_classes_element = Element::createList();
const auto& required_classes = subnet->getRequiredClasses();
conn_.insertQuery(MySqlConfigBackendDHCPv6Impl::INSERT_SUBNET6,
in_bindings);
- // Insert associations with the servers.
- attachElementToServers(MySqlConfigBackendDHCPv6Impl::INSERT_SUBNET6_SERVER,
- server_selector,
- MySqlBinding::createInteger<uint32_t>(subnet->getID()),
- MySqlBinding::createTimestamp(subnet->getModificationTime()));
-
} catch (const DuplicateEntry&) {
deletePools6(subnet);
deletePdPools6(subnet);
in_bindings.push_back(MySqlBinding::createString(subnet->toText()));
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::UPDATE_SUBNET6,
in_bindings);
+
+ MySqlBindingCollection in_server_bindings = {
+ MySqlBinding::createInteger<uint32_t>(subnet->getID())
+ };
+ conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_SERVER,
+ in_server_bindings);
}
+ // Insert associations with the servers.
+ attachElementToServers(MySqlConfigBackendDHCPv6Impl::INSERT_SUBNET6_SERVER,
+ server_selector,
+ MySqlBinding::createInteger<uint32_t>(subnet->getID()),
+ MySqlBinding::createTimestamp(subnet->getModificationTime()));
+
// (Re)create pools.
for (auto pool : subnet->getPools(Lease::TYPE_NA)) {
createPool6(server_selector, boost::dynamic_pointer_cast<Pool6>(pool),
},
// Select subnet by id.
- { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_ID,
- MYSQL_GET_SUBNET6(AND s.subnet_id = ?)
+ { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_ID_NO_TAG,
+ MYSQL_GET_SUBNET6_NO_TAG(WHERE s.subnet_id = ?)
+ },
+
+ // Select subnet by id without specifying server tags.
+ { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_ID_ANY,
+ MYSQL_GET_SUBNET6_ANY(WHERE s.subnet_id = ?)
+ },
+
+ // Select unassigned subnet by id.
+ { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_ID_UNASSIGNED,
+ MYSQL_GET_SUBNET6_UNASSIGNED(AND s.subnet_id = ?)
},
// Select subnet by prefix.
- { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_PREFIX,
- MYSQL_GET_SUBNET6(AND s.subnet_prefix = ?)
+ { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_PREFIX_NO_TAG,
+ MYSQL_GET_SUBNET6_NO_TAG(WHERE s.subnet_prefix = ?)
+ },
+
+ // Select subnet by prefix without specifying server tags.
+ { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_PREFIX_ANY,
+ MYSQL_GET_SUBNET6_ANY(WHERE s.subnet_prefix = ?)
+ },
+
+ // Select unassigned subnet by prefix.
+ { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_PREFIX_UNASSIGNED,
+ MYSQL_GET_SUBNET6_UNASSIGNED(AND s.subnet_prefix = ?)
},
// Select all subnets.
{ MySqlConfigBackendDHCPv6Impl::GET_ALL_SUBNETS6,
- MYSQL_GET_SUBNET6()
+ MYSQL_GET_SUBNET6_NO_TAG()
+ },
+
+ // Select all unassigned subnets.
+ { MySqlConfigBackendDHCPv6Impl::GET_ALL_SUBNETS6_UNASSIGNED,
+ MYSQL_GET_SUBNET6_UNASSIGNED()
},
// Select subnets having modification time later than X.
{ MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_SUBNETS6,
- MYSQL_GET_SUBNET6(AND s.modification_ts > ?)
+ MYSQL_GET_SUBNET6_NO_TAG(WHERE s.modification_ts > ?)
+ },
+
+ // Select modified and unassigned subnets.
+ { MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_SUBNETS6_UNASSIGNED,
+ MYSQL_GET_SUBNET6_UNASSIGNED(AND s.modification_ts > ?)
},
// Select subnets belonging to a shared network.
{ MySqlConfigBackendDHCPv6Impl::GET_SHARED_NETWORK_SUBNETS6,
- MYSQL_GET_SUBNET6(AND s.shared_network_name = ?)
+ MYSQL_GET_SUBNET6_NO_TAG(WHERE s.shared_network_name = ?)
},
// Select pool by address range.
MYSQL_DELETE_SUBNET(dhcp6, AND s.shared_network_name = ?)
},
+ // Delete associations of a subnet with server.
+ { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_SERVER,
+ MYSQL_DELETE_SUBNET_SERVER(dhcp6),
+ },
+
// Delete pools for a subnet.
{ MySqlConfigBackendDHCPv6Impl::DELETE_POOLS6_SUBNET_ID,
MYSQL_DELETE_POOLS(dhcp6)
#endif
#ifndef MYSQL_GET_SUBNET4
-#define MYSQL_GET_SUBNET4(...) \
+#define MYSQL_GET_SUBNET4_COMMON(server_join, ...) \
"SELECT" \
" s.subnet_id," \
" s.subnet_prefix," \
" s.max_valid_lifetime," \
" srv.tag " \
"FROM dhcp4_subnet AS s " \
- "INNER JOIN dhcp4_subnet_server AS a " \
- " ON s.subnet_id = a.subnet_id " \
- "INNER JOIN dhcp4_server AS srv " \
- " ON (a.server_id = srv.id) OR (a.server_id = 1) " \
+ server_join \
"LEFT JOIN dhcp4_pool AS p ON s.subnet_id = p.subnet_id " \
"LEFT JOIN dhcp4_options AS x ON x.scope_id = 5 AND p.id = x.pool_id " \
"LEFT JOIN dhcp4_options AS o ON o.scope_id = 1 AND s.subnet_id = o.dhcp4_subnet_id " \
- "WHERE (srv.tag = ? OR srv.id = 1) " #__VA_ARGS__ \
+ #__VA_ARGS__ \
" ORDER BY s.subnet_id, p.id, x.option_id, o.option_id"
+
+#define MYSQL_GET_SUBNET4_NO_TAG(...) \
+ MYSQL_GET_SUBNET4_COMMON( \
+ "INNER JOIN dhcp4_subnet_server AS a " \
+ " ON s.subnet_id = a.subnet_id " \
+ "INNER JOIN dhcp4_server AS srv " \
+ " ON (a.server_id = srv.id) ", \
+ __VA_ARGS__)
+
+#define MYSQL_GET_SUBNET4_ANY(...) \
+ MYSQL_GET_SUBNET4_COMMON( \
+ "LEFT JOIN dhcp4_subnet_server AS a "\
+ " ON s.subnet_id = a.subnet_id " \
+ "LEFT JOIN dhcp4_server AS srv " \
+ " ON a.server_id = srv.id ", \
+ __VA_ARGS__)
+
+#define MYSQL_GET_SUBNET4_UNASSIGNED(...) \
+ MYSQL_GET_SUBNET4_COMMON( \
+ "LEFT JOIN dhcp4_subnet_server AS a "\
+ " ON s.subnet_id = a.subnet_id " \
+ "LEFT JOIN dhcp4_server AS srv " \
+ " ON a.server_id = srv.id ", \
+ WHERE a.subnet_id IS NULL __VA_ARGS__)
+
#endif
#ifndef MYSQL_GET_SUBNET6
-#define MYSQL_GET_SUBNET6(...) \
+#define MYSQL_GET_SUBNET6_COMMON(server_join, ...) \
"SELECT" \
" s.subnet_id," \
" s.subnet_prefix," \
" s.max_valid_lifetime," \
" srv.tag " \
"FROM dhcp6_subnet AS s " \
- "INNER JOIN dhcp6_subnet_server AS a " \
- " ON s.subnet_id = a.subnet_id " \
- "INNER JOIN dhcp6_server AS srv " \
- " ON (a.server_id = srv.id) OR (a.server_id = 1) " \
+ server_join \
"LEFT JOIN dhcp6_pool AS p ON s.subnet_id = p.subnet_id " \
"LEFT JOIN dhcp6_pd_pool AS d ON s.subnet_id = d.subnet_id " \
"LEFT JOIN dhcp6_options AS x ON x.scope_id = 5 AND p.id = x.pool_id " \
"LEFT JOIN dhcp6_options AS y ON y.scope_id = 6 AND d.id = y.pd_pool_id " \
"LEFT JOIN dhcp6_options AS o ON o.scope_id = 1 AND s.subnet_id = o.dhcp6_subnet_id " \
- "WHERE (srv.tag = ? OR srv.id = 1) " #__VA_ARGS__ \
+ #__VA_ARGS__ \
" ORDER BY s.subnet_id, p.id, d.id, x.option_id, o.option_id"
+
+#define MYSQL_GET_SUBNET6_NO_TAG(...) \
+ MYSQL_GET_SUBNET6_COMMON( \
+ "INNER JOIN dhcp6_subnet_server AS a " \
+ " ON s.subnet_id = a.subnet_id " \
+ "INNER JOIN dhcp6_server AS srv " \
+ " ON (a.server_id = srv.id) ", \
+ __VA_ARGS__)
+
+#define MYSQL_GET_SUBNET6_ANY(...) \
+ MYSQL_GET_SUBNET6_COMMON( \
+ "LEFT JOIN dhcp6_subnet_server AS a "\
+ " ON s.subnet_id = a.subnet_id " \
+ "LEFT JOIN dhcp6_server AS srv " \
+ " ON a.server_id = srv.id ", \
+ __VA_ARGS__)
+
+#define MYSQL_GET_SUBNET6_UNASSIGNED(...) \
+ MYSQL_GET_SUBNET6_COMMON( \
+ "LEFT JOIN dhcp6_subnet_server AS a "\
+ " ON s.subnet_id = a.subnet_id " \
+ "LEFT JOIN dhcp6_server AS srv " \
+ " ON a.server_id = srv.id ", \
+ WHERE a.subnet_id IS NULL __VA_ARGS__)
+
#endif
#ifndef MYSQL_GET_SHARED_NETWORK4
"WHERE srv.tag = ? " #__VA_ARGS__
#endif
+#ifndef MYSQL_DELETE_SUBNET_SERVER
+#define MYSQL_DELETE_SUBNET_SERVER(table_prefix) \
+ "DELETE FROM " #table_prefix "_subnet_server " \
+ "WHERE subnet_id = ?"
+#endif
+
#ifndef MYSQL_DELETE_POOLS
#define MYSQL_DELETE_POOLS(table_prefix) \
"DELETE FROM " #table_prefix "_pool " \
// Test that subnet can be inserted, fetched, updated and then fetched again.
TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4) {
- // Insert new subnet.
- Subnet4Ptr subnet = test_subnets_[0];
- cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet);
-
- // Fetch this subnet by subnet identifier.
- Subnet4Ptr returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
- test_subnets_[0]->getID());
- ASSERT_TRUE(returned_subnet);
- ASSERT_EQ(1, returned_subnet->getServerTags().size());
- EXPECT_EQ("all", returned_subnet->getServerTags().begin()->get());
+ // Insert the server2 into the database.
+ EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
+ {
+ SCOPED_TRACE("CREATE audit entry for server");
+ testNewAuditEntry("dhcp4_server",
+ AuditEntry::ModificationType::CREATE,
+ "server set");
+ }
- // The easiest way to verify whether the returned subnet matches the inserted
- // subnet is to convert both to text.
- EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
+ auto subnet = test_subnets_[0];
+ auto subnet2 = test_subnets_[2];
+ // Insert two subnets, one for all servers and one for server2.
+ EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet));
{
SCOPED_TRACE("CREATE audit entry for the subnet");
testNewAuditEntry("dhcp4_subnet",
"subnet set");
}
- // Update the subnet in the database (both use the same ID).
- Subnet4Ptr subnet2 = test_subnets_[1];
- cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet2);
- // Fetch updated subnet and see if it matches.
- returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
- SubnetID(1024));
- EXPECT_EQ(subnet2->toElement()->str(), returned_subnet->toElement()->str());
+ EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ONE("server2"), subnet2));
+ {
+ SCOPED_TRACE("CREATE audit entry for the subnet");
+ testNewAuditEntry("dhcp4_subnet",
+ AuditEntry::ModificationType::CREATE,
+ "subnet set", ServerSelector::ONE("subnet2"),
+ 2, 1);
+ }
- // Fetching the subnet for an explicitly specified server tag should
- // succeed too.
- returned_subnet = cbptr_->getSubnet4(ServerSelector::ONE("server1"),
- SubnetID(1024));
- EXPECT_EQ(subnet2->toElement()->str(), returned_subnet->toElement()->str());
+ // We are not going to support selection of a single entry for multiple servers.
+ EXPECT_THROW(cbptr_->getSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+ subnet->getID()),
+ isc::InvalidOperation);
+
+ EXPECT_THROW(cbptr_->getSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+ subnet->toText()),
+ isc::InvalidOperation);
+
+ // Test that this subnet will be fetched for various server selectors.
+ auto test_get_subnet = [this, &subnet] (const std::string& test_case_name,
+ const ServerSelector& server_selector,
+ const std::string& expected_tag = ServerTag::ALL) {
+ SCOPED_TRACE(test_case_name);
+
+ // Test fetching subnet by id.
+ Subnet4Ptr returned_subnet;
+ ASSERT_NO_THROW(returned_subnet = cbptr_->getSubnet4(server_selector, subnet->getID()));
+ ASSERT_TRUE(returned_subnet);
+
+ ASSERT_EQ(1, returned_subnet->getServerTags().size());
+ EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag(expected_tag)));
+
+ EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
+
+ // Test fetching subnet by prefix.
+ ASSERT_NO_THROW(returned_subnet = cbptr_->getSubnet4(server_selector,
+ subnet->toText()));
+ ASSERT_TRUE(returned_subnet);
+
+ ASSERT_EQ(1, returned_subnet->getServerTags().size());
+ EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag(expected_tag)));
+
+ EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
+ };
{
- SCOPED_TRACE("UPDATE audit entry for the subnet");
+ SCOPED_TRACE("testing various server selectors before update");
+ test_get_subnet("all servers", ServerSelector::ALL());
+ test_get_subnet("one server", ServerSelector::ONE("server1"));
+ test_get_subnet("any server", ServerSelector::ANY());
+ }
+
+ subnet = subnet2;
+ {
+ SCOPED_TRACE("testing server selectors for another server");
+ test_get_subnet("one server", ServerSelector::ONE("server2"), "server2");
+ test_get_subnet("any server", ServerSelector::ANY(), "server2");
+ }
+
+ // Update the subnet in the database (both use the same ID).
+ subnet = test_subnets_[1];
+ EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet));
+ {
+ SCOPED_TRACE("CREATE audit entry for the subnet");
testNewAuditEntry("dhcp4_subnet",
AuditEntry::ModificationType::UPDATE,
"subnet set");
}
- // Insert another subnet.
- cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[2]);
+ {
+ SCOPED_TRACE("testing various server selectors after update");
+ test_get_subnet("all servers", ServerSelector::ALL());
+ test_get_subnet("one server", ServerSelector::ONE("server1"));
+ test_get_subnet("any server", ServerSelector::ANY());
+ }
- // Fetch this subnet by prefix and verify it matches.
- returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
- test_subnets_[2]->toText());
- ASSERT_TRUE(returned_subnet);
- EXPECT_EQ(test_subnets_[2]->toElement()->str(), returned_subnet->toElement()->str());
+ // The server2 specific subnet should not be returned if the server selector
+ // is not matching.
+ EXPECT_FALSE(cbptr_->getSubnet4(ServerSelector::ALL(), subnet2->getID()));
+ EXPECT_FALSE(cbptr_->getSubnet4(ServerSelector::ALL(), subnet2->toText()));
+ EXPECT_FALSE(cbptr_->getSubnet4(ServerSelector::ONE("server1"), subnet2->getID()));
+ EXPECT_FALSE(cbptr_->getSubnet4(ServerSelector::ONE("server1"), subnet2->toText()));
// Update the subnet in the database (both use the same prefix).
subnet2.reset(new Subnet4(IOAddress("192.0.3.0"), 24, 30, 40, 60, 8192));
- cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet2);
+ EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ONE("server2"), subnet2));
// Fetch again and verify.
- returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
- test_subnets_[2]->toText());
+ auto returned_subnet = cbptr_->getSubnet4(ServerSelector::ONE("server2"),
+ subnet2->toText());
ASSERT_TRUE(returned_subnet);
EXPECT_EQ(subnet2->toElement()->str(), returned_subnet->toElement()->str());
// with different subnets. This should throw.
// Subnets are 10.0.0.0/8 id 1024 and 192.0.3.0/24 id 8192
subnet2.reset(new Subnet4(IOAddress("10.0.0.0"), 8, 30, 40, 60, 8192));
- EXPECT_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet2),
+ EXPECT_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ONE("server2"), subnet2),
DuplicateEntry);
}
// Test that subnet can be inserted, fetched, updated and then fetched again.
TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6) {
- // Insert new subnet.
- Subnet6Ptr subnet = test_subnets_[0];
- cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet);
-
- // Fetch this subnet by subnet identifier.
- Subnet6Ptr returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(),
- test_subnets_[0]->getID());
- ASSERT_TRUE(returned_subnet);
- ASSERT_EQ(1, returned_subnet->getServerTags().size());
- EXPECT_EQ("all", returned_subnet->getServerTags().begin()->get());
+ // Insert the server2 into the database.
+ EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2]));
+ {
+ SCOPED_TRACE("CREATE audit entry for server");
+ testNewAuditEntry("dhcp6_server",
+ AuditEntry::ModificationType::CREATE,
+ "server set");
+ }
- // The easiest way to verify whether the returned subnet matches the inserted
- // subnet is to convert both to text.
- EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
+ auto subnet = test_subnets_[0];
+ auto subnet2 = test_subnets_[2];
+ // Insert two subnets, one for all servers and one for server2.
+ EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet));
{
SCOPED_TRACE("CREATE audit entry for the subnet");
testNewAuditEntry("dhcp6_subnet",
"subnet set");
}
- // Update the subnet in the database (both use the same ID).
- Subnet6Ptr subnet2 = test_subnets_[1];
- cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet2);
- // Fetch updated subnet and see if it matches.
- returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(),
- SubnetID(1024));
- EXPECT_EQ(subnet2->toElement()->str(), returned_subnet->toElement()->str());
+ EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server2"), subnet2));
+ {
+ SCOPED_TRACE("CREATE audit entry for the subnet");
+ testNewAuditEntry("dhcp6_subnet",
+ AuditEntry::ModificationType::CREATE,
+ "subnet set", ServerSelector::ONE("subnet2"),
+ 2, 1);
+ }
- // Fetching the subnet for an explicitly specified server tag should
- // succeed too.
- returned_subnet = cbptr_->getSubnet6(ServerSelector::ONE("server1"),
- SubnetID(1024));
- EXPECT_EQ(subnet2->toElement()->str(), returned_subnet->toElement()->str());
+ // We are not going to support selection of a single entry for multiple servers.
+ EXPECT_THROW(cbptr_->getSubnet6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+ subnet->getID()),
+ isc::InvalidOperation);
+
+ EXPECT_THROW(cbptr_->getSubnet6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+ subnet->toText()),
+ isc::InvalidOperation);
+
+ // Test that this subnet will be fetched for various server selectors.
+ auto test_get_subnet = [this, &subnet] (const std::string& test_case_name,
+ const ServerSelector& server_selector,
+ const std::string& expected_tag = ServerTag::ALL) {
+ SCOPED_TRACE(test_case_name);
+
+ // Test fetching subnet by id.
+ Subnet6Ptr returned_subnet;
+ ASSERT_NO_THROW(returned_subnet = cbptr_->getSubnet6(server_selector, subnet->getID()));
+ ASSERT_TRUE(returned_subnet);
+
+ ASSERT_EQ(1, returned_subnet->getServerTags().size());
+ EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag(expected_tag)));
+
+ EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
+
+ // Test fetching subnet by prefix.
+ ASSERT_NO_THROW(returned_subnet = cbptr_->getSubnet6(server_selector,
+ subnet->toText()));
+ ASSERT_TRUE(returned_subnet);
+
+ ASSERT_EQ(1, returned_subnet->getServerTags().size());
+ EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag(expected_tag)));
+
+ EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
+ };
{
- SCOPED_TRACE("UPDATE audit entry for the subnet");
+ SCOPED_TRACE("testing various server selectors before update");
+ test_get_subnet("all servers", ServerSelector::ALL());
+ test_get_subnet("one server", ServerSelector::ONE("server1"));
+ test_get_subnet("any server", ServerSelector::ANY());
+ }
+
+ subnet = subnet2;
+ {
+ SCOPED_TRACE("testing server selectors for another server");
+ test_get_subnet("one server", ServerSelector::ONE("server2"), "server2");
+ test_get_subnet("any server", ServerSelector::ANY(), "server2");
+ }
+
+ // Update the subnet in the database (both use the same ID).
+ subnet = test_subnets_[1];
+ EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet));
+ {
+ SCOPED_TRACE("CREATE audit entry for the subnet");
testNewAuditEntry("dhcp6_subnet",
AuditEntry::ModificationType::UPDATE,
"subnet set");
}
- // Insert another subnet.
- cbptr_->createUpdateSubnet6(ServerSelector::ALL(), test_subnets_[2]);
+ {
+ SCOPED_TRACE("testing various server selectors after update");
+ test_get_subnet("all servers", ServerSelector::ALL());
+ test_get_subnet("one server", ServerSelector::ONE("server1"));
+ test_get_subnet("any server", ServerSelector::ANY());
+ }
- // Fetch this subnet by prefix and verify it matches.
- returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(),
- test_subnets_[2]->toText());
- ASSERT_TRUE(returned_subnet);
- EXPECT_EQ(test_subnets_[2]->toElement()->str(), returned_subnet->toElement()->str());
+ // The server2 specific subnet should not be returned if the server selector
+ // is not matching.
+ EXPECT_FALSE(cbptr_->getSubnet6(ServerSelector::ALL(), subnet2->getID()));
+ EXPECT_FALSE(cbptr_->getSubnet6(ServerSelector::ALL(), subnet2->toText()));
+ EXPECT_FALSE(cbptr_->getSubnet6(ServerSelector::ONE("server1"), subnet2->getID()));
+ EXPECT_FALSE(cbptr_->getSubnet6(ServerSelector::ONE("server1"), subnet2->toText()));
// Update the subnet in the database (both use the same prefix).
subnet2.reset(new Subnet6(IOAddress("2001:db8:3::"),
64, 30, 40, 50, 80, 8192));
- cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet2);
+ EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server2"), subnet2));
// Fetch again and verify.
- returned_subnet = cbptr_->getSubnet6(ServerSelector::ALL(),
- test_subnets_[2]->toText());
+ auto returned_subnet = cbptr_->getSubnet6(ServerSelector::ONE("server2"),
+ subnet2->toText());
ASSERT_TRUE(returned_subnet);
EXPECT_EQ(subnet2->toElement()->str(), returned_subnet->toElement()->str());
// Subnets are 2001:db8:1::/48 id 1024 and 2001:db8:3::/64 id 8192
subnet2.reset(new Subnet6(IOAddress("2001:db8:1::"),
48, 30, 40, 50, 80, 8192));
- EXPECT_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet2),
+ EXPECT_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server2"), subnet2),
DuplicateEntry);
}