mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 05:27:55 +00:00
[#714,!409] Associate global options with the server tags.
This commit is contained in:
parent
711c1dca9d
commit
ed7befb616
@ -115,6 +115,7 @@ public:
|
|||||||
DELETE_OPTION_DEF4_CODE_NAME,
|
DELETE_OPTION_DEF4_CODE_NAME,
|
||||||
DELETE_ALL_OPTION_DEFS4,
|
DELETE_ALL_OPTION_DEFS4,
|
||||||
DELETE_OPTION4,
|
DELETE_OPTION4,
|
||||||
|
DELETE_ALL_OPTIONS4_UNASSIGNED,
|
||||||
DELETE_OPTION4_SUBNET_ID,
|
DELETE_OPTION4_SUBNET_ID,
|
||||||
DELETE_OPTION4_POOL_RANGE,
|
DELETE_OPTION4_POOL_RANGE,
|
||||||
DELETE_OPTION4_SHARED_NETWORK,
|
DELETE_OPTION4_SHARED_NETWORK,
|
||||||
@ -1441,7 +1442,10 @@ public:
|
|||||||
createInputContextBinding(option),
|
createInputContextBinding(option),
|
||||||
MySqlBinding::createNull(),
|
MySqlBinding::createNull(),
|
||||||
MySqlBinding::createNull(),
|
MySqlBinding::createNull(),
|
||||||
MySqlBinding::createTimestamp(option->getModificationTime())
|
MySqlBinding::createTimestamp(option->getModificationTime()),
|
||||||
|
MySqlBinding::createString(tag),
|
||||||
|
MySqlBinding::createInteger<uint8_t>(option->option_->getType()),
|
||||||
|
MySqlBinding::condCreateString(option->space_name_)
|
||||||
};
|
};
|
||||||
|
|
||||||
MySqlTransaction transaction(conn_);
|
MySqlTransaction transaction(conn_);
|
||||||
@ -1456,16 +1460,11 @@ public:
|
|||||||
MySqlConfigBackendDHCPv4Impl::CREATE_AUDIT_REVISION,
|
MySqlConfigBackendDHCPv4Impl::CREATE_AUDIT_REVISION,
|
||||||
server_selector, "global option set", false);
|
server_selector, "global option set", false);
|
||||||
|
|
||||||
if (existing_option) {
|
if (conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::UPDATE_OPTION4,
|
||||||
in_bindings.push_back(MySqlBinding::createString(tag));
|
in_bindings) == 0) {
|
||||||
in_bindings.push_back(MySqlBinding::createInteger<uint8_t>(option->option_->getType()));
|
// Remove the 3 bindings used only in case of update.
|
||||||
in_bindings.push_back(MySqlBinding::condCreateString(option->space_name_));
|
in_bindings.resize(in_bindings.size() - 3);
|
||||||
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::UPDATE_OPTION4,
|
|
||||||
in_bindings);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
insertOption4(server_selector, in_bindings);
|
insertOption4(server_selector, in_bindings);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
@ -1931,7 +1930,11 @@ public:
|
|||||||
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::
|
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::
|
||||||
DELETE_ALL_GLOBAL_PARAMETERS4_UNASSIGNED,
|
DELETE_ALL_GLOBAL_PARAMETERS4_UNASSIGNED,
|
||||||
MySqlBindingCollection());
|
MySqlBindingCollection());
|
||||||
/// @todo delete dangling options and option definitions.
|
|
||||||
|
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::
|
||||||
|
DELETE_ALL_OPTIONS4_UNASSIGNED,
|
||||||
|
MySqlBindingCollection());
|
||||||
|
/// @todo delete option definitions.
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
@ -1967,7 +1970,12 @@ public:
|
|||||||
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::
|
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::
|
||||||
DELETE_ALL_GLOBAL_PARAMETERS4_UNASSIGNED,
|
DELETE_ALL_GLOBAL_PARAMETERS4_UNASSIGNED,
|
||||||
MySqlBindingCollection());
|
MySqlBindingCollection());
|
||||||
/// @todo delete dangling options and option definitions.
|
|
||||||
|
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv4Impl::
|
||||||
|
DELETE_ALL_OPTIONS4_UNASSIGNED,
|
||||||
|
MySqlBindingCollection());
|
||||||
|
|
||||||
|
/// @todo delete dangling option definitions.
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
@ -2396,6 +2404,11 @@ TaggedStatementArray tagged_statements = { {
|
|||||||
MYSQL_DELETE_OPTION(dhcp4, AND o.scope_id = 0 AND o.code = ? AND o.space = ?)
|
MYSQL_DELETE_OPTION(dhcp4, AND o.scope_id = 0 AND o.code = ? AND o.space = ?)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Delete all options which are unassigned to any servers.
|
||||||
|
{ MySqlConfigBackendDHCPv4Impl::DELETE_ALL_OPTIONS4_UNASSIGNED,
|
||||||
|
MYSQL_DELETE_OPTION_UNASSIGNED(dhcp4)
|
||||||
|
},
|
||||||
|
|
||||||
// Delete single option from a subnet.
|
// Delete single option from a subnet.
|
||||||
{ MySqlConfigBackendDHCPv4Impl::DELETE_OPTION4_SUBNET_ID,
|
{ MySqlConfigBackendDHCPv4Impl::DELETE_OPTION4_SUBNET_ID,
|
||||||
MYSQL_DELETE_OPTION(dhcp4,
|
MYSQL_DELETE_OPTION(dhcp4,
|
||||||
|
@ -121,6 +121,7 @@ public:
|
|||||||
DELETE_OPTION_DEF6_CODE_NAME,
|
DELETE_OPTION_DEF6_CODE_NAME,
|
||||||
DELETE_ALL_OPTION_DEFS6,
|
DELETE_ALL_OPTION_DEFS6,
|
||||||
DELETE_OPTION6,
|
DELETE_OPTION6,
|
||||||
|
DELETE_ALL_OPTIONS6_UNASSIGNED,
|
||||||
DELETE_OPTION6_SUBNET_ID,
|
DELETE_OPTION6_SUBNET_ID,
|
||||||
DELETE_OPTION6_POOL_RANGE,
|
DELETE_OPTION6_POOL_RANGE,
|
||||||
DELETE_OPTION6_PD_POOL,
|
DELETE_OPTION6_PD_POOL,
|
||||||
@ -1653,7 +1654,10 @@ public:
|
|||||||
MySqlBinding::createNull(),
|
MySqlBinding::createNull(),
|
||||||
MySqlBinding::createNull(),
|
MySqlBinding::createNull(),
|
||||||
MySqlBinding::createTimestamp(option->getModificationTime()),
|
MySqlBinding::createTimestamp(option->getModificationTime()),
|
||||||
MySqlBinding::createNull()
|
MySqlBinding::createNull(),
|
||||||
|
MySqlBinding::createString(tag),
|
||||||
|
MySqlBinding::createInteger<uint8_t>(option->option_->getType()),
|
||||||
|
MySqlBinding::condCreateString(option->space_name_)
|
||||||
};
|
};
|
||||||
|
|
||||||
MySqlTransaction transaction(conn_);
|
MySqlTransaction transaction(conn_);
|
||||||
@ -1668,16 +1672,11 @@ public:
|
|||||||
MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
|
MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
|
||||||
server_selector, "global option set", false);
|
server_selector, "global option set", false);
|
||||||
|
|
||||||
if (existing_option) {
|
if (conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6,
|
||||||
in_bindings.push_back(MySqlBinding::createString(tag));
|
in_bindings) == 0) {
|
||||||
in_bindings.push_back(MySqlBinding::createInteger<uint16_t>(option->option_->getType()));
|
// Remove the 3 bindings used only in case of update.
|
||||||
in_bindings.push_back(MySqlBinding::condCreateString(option->space_name_));
|
in_bindings.resize(in_bindings.size() - 3);
|
||||||
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6,
|
|
||||||
in_bindings);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
insertOption6(server_selector, in_bindings);
|
insertOption6(server_selector, in_bindings);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
@ -2245,7 +2244,11 @@ public:
|
|||||||
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::
|
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::
|
||||||
DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED,
|
DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED,
|
||||||
MySqlBindingCollection());
|
MySqlBindingCollection());
|
||||||
/// @todo delete dangling options and option definitions.
|
|
||||||
|
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::
|
||||||
|
DELETE_ALL_OPTIONS6_UNASSIGNED,
|
||||||
|
MySqlBindingCollection());
|
||||||
|
/// @todo delete dangling option definitions.
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
@ -2281,7 +2284,11 @@ public:
|
|||||||
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::
|
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::
|
||||||
DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED,
|
DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED,
|
||||||
MySqlBindingCollection());
|
MySqlBindingCollection());
|
||||||
/// @todo delete dangling options and option definitions.
|
|
||||||
|
conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::
|
||||||
|
DELETE_ALL_OPTIONS6_UNASSIGNED,
|
||||||
|
MySqlBindingCollection());
|
||||||
|
/// @todo delete dangling option definitions.
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
@ -2753,6 +2760,11 @@ TaggedStatementArray tagged_statements = { {
|
|||||||
MYSQL_DELETE_OPTION(dhcp6, AND o.scope_id = 0 AND o.code = ? AND o.space = ?)
|
MYSQL_DELETE_OPTION(dhcp6, AND o.scope_id = 0 AND o.code = ? AND o.space = ?)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Delete all options which are unassigned to any servers.
|
||||||
|
{ MySqlConfigBackendDHCPv6Impl::DELETE_ALL_OPTIONS6_UNASSIGNED,
|
||||||
|
MYSQL_DELETE_OPTION_UNASSIGNED(dhcp6)
|
||||||
|
},
|
||||||
|
|
||||||
// Delete single option from a subnet.
|
// Delete single option from a subnet.
|
||||||
{ MySqlConfigBackendDHCPv6Impl::DELETE_OPTION6_SUBNET_ID,
|
{ MySqlConfigBackendDHCPv6Impl::DELETE_OPTION6_SUBNET_ID,
|
||||||
MYSQL_DELETE_OPTION(dhcp6,
|
MYSQL_DELETE_OPTION(dhcp6,
|
||||||
|
@ -762,8 +762,10 @@ MySqlConfigBackendImpl::getOptions(const int index,
|
|||||||
|
|
||||||
uint64_t last_option_id = 0;
|
uint64_t last_option_id = 0;
|
||||||
|
|
||||||
|
OptionContainer local_options;
|
||||||
|
|
||||||
conn_.selectQuery(index, in_bindings, out_bindings,
|
conn_.selectQuery(index, in_bindings, out_bindings,
|
||||||
[this, universe, &options, &last_option_id]
|
[this, universe, &local_options, &last_option_id]
|
||||||
(MySqlBindingCollection& out_bindings) {
|
(MySqlBindingCollection& out_bindings) {
|
||||||
// Parse option.
|
// Parse option.
|
||||||
if (!out_bindings[0]->amNull() &&
|
if (!out_bindings[0]->amNull() &&
|
||||||
@ -774,11 +776,46 @@ MySqlConfigBackendImpl::getOptions(const int index,
|
|||||||
OptionDescriptorPtr desc = processOptionRow(universe, out_bindings.begin());
|
OptionDescriptorPtr desc = processOptionRow(universe, out_bindings.begin());
|
||||||
if (desc) {
|
if (desc) {
|
||||||
// server_tag for the global option
|
// server_tag for the global option
|
||||||
desc->setServerTag(out_bindings[12]->getString());
|
ServerTag last_option_server_tag(out_bindings[12]->getString());
|
||||||
static_cast<void>(options.push_back(*desc));
|
desc->setServerTag(last_option_server_tag.get());
|
||||||
|
|
||||||
|
// If we're fetching options for a given server (explicit server
|
||||||
|
// tag is provided), it takes precedence over the same option
|
||||||
|
// specified for all servers. Therefore, we check if the given
|
||||||
|
// option already exists and belongs to 'all'.
|
||||||
|
auto& index = local_options.get<1>();
|
||||||
|
auto existing_it_pair = index.equal_range(desc->option_->getType());
|
||||||
|
auto existing_it = existing_it_pair.first;
|
||||||
|
bool found = false;
|
||||||
|
for ( ; existing_it != existing_it_pair.second; ++existing_it) {
|
||||||
|
if (existing_it->space_name_ == desc->space_name_) {
|
||||||
|
found = true;
|
||||||
|
// This option was already fetched. Let's check if we should
|
||||||
|
// replace it or not.
|
||||||
|
if (!last_option_server_tag.amAll() && existing_it->hasAllServerTag()) {
|
||||||
|
index.replace(existing_it, *desc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no such global option yet or the existing option
|
||||||
|
// belongs to a different server and the inserted option is not
|
||||||
|
// for all servers.
|
||||||
|
if (!found ||
|
||||||
|
(!existing_it->hasServerTag(last_option_server_tag) &&
|
||||||
|
!last_option_server_tag.amAll())) {
|
||||||
|
static_cast<void>(local_options.push_back(*desc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Append the options fetched by this function into the container supplied
|
||||||
|
// by the caller. The container supplied by the caller may already hold
|
||||||
|
// some options fetched for other server tags.
|
||||||
|
options.insert(options.end(), local_options.begin(), local_options.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionDescriptorPtr
|
OptionDescriptorPtr
|
||||||
|
@ -353,7 +353,7 @@ namespace {
|
|||||||
"INNER JOIN " #table_prefix "_server AS s" \
|
"INNER JOIN " #table_prefix "_server AS s" \
|
||||||
" ON a.server_id = s.id " \
|
" ON a.server_id = s.id " \
|
||||||
"WHERE (s.tag = ? OR s.id = 1) " #__VA_ARGS__ \
|
"WHERE (s.tag = ? OR s.id = 1) " #__VA_ARGS__ \
|
||||||
" ORDER BY o.option_id"
|
" ORDER BY o.option_id, s.id"
|
||||||
|
|
||||||
#define MYSQL_GET_OPTION4(...) \
|
#define MYSQL_GET_OPTION4(...) \
|
||||||
MYSQL_GET_OPTION_COMMON(dhcp4, "", __VA_ARGS__)
|
MYSQL_GET_OPTION_COMMON(dhcp4, "", __VA_ARGS__)
|
||||||
@ -667,6 +667,14 @@ namespace {
|
|||||||
"WHERE s.tag = ? " #__VA_ARGS__
|
"WHERE s.tag = ? " #__VA_ARGS__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MYSQL_DELETE_OPTION_UNASSIGNED
|
||||||
|
#define MYSQL_DELETE_OPTION_UNASSIGNED(table_prefix, ...) \
|
||||||
|
"DELETE o FROM " #table_prefix "_options AS o " \
|
||||||
|
"LEFT JOIN " #table_prefix "_options_server AS a " \
|
||||||
|
" ON o.option_id = a.option_id " \
|
||||||
|
"WHERE a.option_id IS NULL " #__VA_ARGS__
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MYSQL_DELETE_OPTION_POOL_RANGE
|
#ifndef MYSQL_DELETE_OPTION_POOL_RANGE
|
||||||
#define MYSQL_DELETE_OPTION_POOL_RANGE(table_prefix, ...) \
|
#define MYSQL_DELETE_OPTION_POOL_RANGE(table_prefix, ...) \
|
||||||
"DELETE o FROM " #table_prefix "_options AS o " \
|
"DELETE o FROM " #table_prefix "_options AS o " \
|
||||||
|
@ -302,6 +302,18 @@ public:
|
|||||||
desc.space_name_ = "isc";
|
desc.space_name_ = "isc";
|
||||||
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
|
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
|
||||||
|
|
||||||
|
desc = createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
|
||||||
|
true, false, "my-boot-file-2");
|
||||||
|
desc.space_name_ = DHCP4_OPTION_SPACE;
|
||||||
|
desc.setContext(user_context);
|
||||||
|
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
|
||||||
|
|
||||||
|
desc = createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
|
||||||
|
true, false, "my-boot-file-3");
|
||||||
|
desc.space_name_ = DHCP4_OPTION_SPACE;
|
||||||
|
desc.setContext(user_context);
|
||||||
|
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
|
||||||
|
|
||||||
// Add definitions for DHCPv4 non-standard options in case we need to
|
// Add definitions for DHCPv4 non-standard options in case we need to
|
||||||
// compare subnets, networks and pools in JSON format. In that case,
|
// compare subnets, networks and pools in JSON format. In that case,
|
||||||
// the @c toElement functions require option definitions to generate the
|
// the @c toElement functions require option definitions to generate the
|
||||||
@ -1931,8 +1943,9 @@ TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteOption4) {
|
|||||||
opt_boot_file_name);
|
opt_boot_file_name);
|
||||||
|
|
||||||
// Retrieve the option again and make sure that updates were
|
// Retrieve the option again and make sure that updates were
|
||||||
// properly propagated to the database.
|
// properly propagated to the database. Use explicit server selector
|
||||||
returned_opt_boot_file_name = cbptr_->getOption4(ServerSelector::ALL(),
|
// which should also return this option.
|
||||||
|
returned_opt_boot_file_name = cbptr_->getOption4(ServerSelector::ONE("server1"),
|
||||||
opt_boot_file_name->option_->getType(),
|
opt_boot_file_name->option_->getType(),
|
||||||
opt_boot_file_name->space_name_);
|
opt_boot_file_name->space_name_);
|
||||||
ASSERT_TRUE(returned_opt_boot_file_name);
|
ASSERT_TRUE(returned_opt_boot_file_name);
|
||||||
@ -1971,6 +1984,189 @@ TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteOption4) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies that it is possible to differentiate between the
|
||||||
|
// global options by server tag and that the option specified for the
|
||||||
|
// particular server overrides the value specified for all servers.
|
||||||
|
TEST_F(MySqlConfigBackendDHCPv4Test, globalOptions4WithServerTags) {
|
||||||
|
OptionDescriptorPtr opt_boot_file_name1 = test_options_[0];
|
||||||
|
OptionDescriptorPtr opt_boot_file_name2 = test_options_[6];
|
||||||
|
OptionDescriptorPtr opt_boot_file_name3 = test_options_[7];
|
||||||
|
|
||||||
|
EXPECT_THROW(cbptr_->createUpdateOption4(ServerSelector::ONE("server1"),
|
||||||
|
opt_boot_file_name1),
|
||||||
|
DbOperationError);
|
||||||
|
|
||||||
|
// Create two servers.
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[1]));
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("server1 is created");
|
||||||
|
testNewAuditEntry("dhcp4_server",
|
||||||
|
AuditEntry::ModificationType::CREATE,
|
||||||
|
"server set");
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("server2 is created");
|
||||||
|
testNewAuditEntry("dhcp4_server",
|
||||||
|
AuditEntry::ModificationType::CREATE,
|
||||||
|
"server set");
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateOption4(ServerSelector::ONE("server1"),
|
||||||
|
opt_boot_file_name1));
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("global option for server1 is set");
|
||||||
|
// The value of 3 means there should be 3 audit entries available for the
|
||||||
|
// server1, two that indicate creation of the servers and one that we
|
||||||
|
// validate, which sets the global option.
|
||||||
|
testNewAuditEntry("dhcp4_options",
|
||||||
|
AuditEntry::ModificationType::CREATE,
|
||||||
|
"global option set",
|
||||||
|
ServerSelector::ONE("server1"),
|
||||||
|
3, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateOption4(ServerSelector::ONE("server2"),
|
||||||
|
opt_boot_file_name2));
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("global option for server2 is set");
|
||||||
|
// Same as in case of the server1, there should be 3 audit entries and
|
||||||
|
// we validate one of them.
|
||||||
|
testNewAuditEntry("dhcp4_options",
|
||||||
|
AuditEntry::ModificationType::CREATE,
|
||||||
|
"global option set",
|
||||||
|
ServerSelector::ONE("server2"),
|
||||||
|
3, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateOption4(ServerSelector::ALL(),
|
||||||
|
opt_boot_file_name3));
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("global option for all servers is set");
|
||||||
|
// There should be one new audit entry for all servers. It logs
|
||||||
|
// the insertion of the global option.
|
||||||
|
testNewAuditEntry("dhcp4_options",
|
||||||
|
AuditEntry::ModificationType::CREATE,
|
||||||
|
"global option set",
|
||||||
|
ServerSelector::ALL(),
|
||||||
|
1, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionDescriptorPtr returned_option;
|
||||||
|
|
||||||
|
// Try to fetch the option specified for all servers. It should return
|
||||||
|
// the third option.
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_option = cbptr_->getOption4(ServerSelector::ALL(),
|
||||||
|
opt_boot_file_name3->option_->getType(),
|
||||||
|
opt_boot_file_name3->space_name_);
|
||||||
|
);
|
||||||
|
ASSERT_TRUE(returned_option);
|
||||||
|
testOptionsEquivalent(*opt_boot_file_name3, *returned_option);
|
||||||
|
|
||||||
|
// Try to fetch the option specified for the server1. It should override the
|
||||||
|
// option specified for all servers.
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_option = cbptr_->getOption4(ServerSelector::ONE("server1"),
|
||||||
|
opt_boot_file_name1->option_->getType(),
|
||||||
|
opt_boot_file_name1->space_name_);
|
||||||
|
);
|
||||||
|
ASSERT_TRUE(returned_option);
|
||||||
|
testOptionsEquivalent(*opt_boot_file_name1, *returned_option);
|
||||||
|
|
||||||
|
// The same in case of the server2.
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_option = cbptr_->getOption4(ServerSelector::ONE("server2"),
|
||||||
|
opt_boot_file_name2->option_->getType(),
|
||||||
|
opt_boot_file_name2->space_name_);
|
||||||
|
);
|
||||||
|
ASSERT_TRUE(returned_option);
|
||||||
|
testOptionsEquivalent(*opt_boot_file_name2, *returned_option);
|
||||||
|
|
||||||
|
OptionContainer returned_options;
|
||||||
|
|
||||||
|
// Try to fetch the collection of global options for the server1, server2
|
||||||
|
// and server3. The server3 does not have an explicit value so for this server
|
||||||
|
// we should get the option associated with "all" servers.
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_options = cbptr_->getAllOptions4(ServerSelector::
|
||||||
|
MULTIPLE({ "server1", "server2",
|
||||||
|
"server3" }));
|
||||||
|
);
|
||||||
|
ASSERT_EQ(3, returned_options.size());
|
||||||
|
|
||||||
|
// Check that expected options have been returned.
|
||||||
|
auto current_option = returned_options.begin();
|
||||||
|
testOptionsEquivalent(*opt_boot_file_name1, *current_option);
|
||||||
|
testOptionsEquivalent(*opt_boot_file_name2, *(++current_option));
|
||||||
|
testOptionsEquivalent(*opt_boot_file_name3, *(++current_option));
|
||||||
|
|
||||||
|
// Try to fetch the collection of options specified for all servers.
|
||||||
|
// This excludes the options specific to server1 and server2. It returns
|
||||||
|
// only the common ones.
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_options = cbptr_->getAllOptions4(ServerSelector::ALL());
|
||||||
|
);
|
||||||
|
ASSERT_EQ(1, returned_options.size());
|
||||||
|
testOptionsEquivalent(*opt_boot_file_name3, *returned_options.begin());
|
||||||
|
|
||||||
|
// Delete the server1. It should remove associations of this server with the
|
||||||
|
// option and the option itself.
|
||||||
|
EXPECT_NO_THROW(cbptr_->deleteServer4(ServerTag("server1")));
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_options = cbptr_->getAllOptions4(ServerSelector::ONE("server1"));
|
||||||
|
);
|
||||||
|
ASSERT_EQ(1, returned_options.size());
|
||||||
|
testOptionsEquivalent(*opt_boot_file_name3, *returned_options.begin());
|
||||||
|
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("DELETE audit entry for the global option after server deletion");
|
||||||
|
testNewAuditEntry("dhcp4_options",
|
||||||
|
AuditEntry::ModificationType::DELETE,
|
||||||
|
"deleting a server", ServerSelector::ONE("server1"),
|
||||||
|
2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to delete global option for server1.
|
||||||
|
uint64_t deleted_num = 0;
|
||||||
|
EXPECT_NO_THROW(deleted_num = cbptr_->deleteOption4(ServerSelector::ONE("server1"),
|
||||||
|
opt_boot_file_name1->option_->getType(),
|
||||||
|
opt_boot_file_name1->space_name_));
|
||||||
|
EXPECT_EQ(0, deleted_num);
|
||||||
|
|
||||||
|
// Deleting the existing option for server2 should succeed.
|
||||||
|
EXPECT_NO_THROW(deleted_num = cbptr_->deleteOption4(ServerSelector::ONE("server2"),
|
||||||
|
opt_boot_file_name2->option_->getType(),
|
||||||
|
opt_boot_file_name2->space_name_));
|
||||||
|
EXPECT_EQ(1, deleted_num);
|
||||||
|
|
||||||
|
// Create this option again to test that deletion of all servers removes it too.
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateOption4(ServerSelector::ONE("server2"),
|
||||||
|
opt_boot_file_name2));
|
||||||
|
|
||||||
|
// Delete all servers, except 'all'.
|
||||||
|
EXPECT_NO_THROW(deleted_num = cbptr_->deleteAllServers4());
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_options = cbptr_->getAllOptions4(ServerSelector::ALL());
|
||||||
|
);
|
||||||
|
EXPECT_EQ(1, deleted_num);
|
||||||
|
ASSERT_EQ(1, returned_options.size());
|
||||||
|
testOptionsEquivalent(*opt_boot_file_name3, *returned_options.begin());
|
||||||
|
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("DELETE audit entry for the global option after deletion of"
|
||||||
|
" all servers");
|
||||||
|
testNewAuditEntry("dhcp4_options",
|
||||||
|
AuditEntry::ModificationType::DELETE,
|
||||||
|
"deleting all servers", ServerSelector::ONE("server2"),
|
||||||
|
4, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This test verifies that all global options can be retrieved.
|
// This test verifies that all global options can be retrieved.
|
||||||
TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptions4) {
|
TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptions4) {
|
||||||
// Add three global options to the database.
|
// Add three global options to the database.
|
||||||
|
@ -343,6 +343,18 @@ public:
|
|||||||
desc.space_name_ = "isc";
|
desc.space_name_ = "isc";
|
||||||
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
|
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
|
||||||
|
|
||||||
|
desc = createOption<OptionString>(Option::V6, D6O_NEW_POSIX_TIMEZONE,
|
||||||
|
true, false, "my-timezone-2");
|
||||||
|
desc.space_name_ = DHCP6_OPTION_SPACE;
|
||||||
|
desc.setContext(user_context);
|
||||||
|
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
|
||||||
|
|
||||||
|
desc = createOption<OptionString>(Option::V6, D6O_NEW_POSIX_TIMEZONE,
|
||||||
|
true, false, "my-timezone-3");
|
||||||
|
desc.space_name_ = DHCP6_OPTION_SPACE;
|
||||||
|
desc.setContext(user_context);
|
||||||
|
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
|
||||||
|
|
||||||
// Add definitions for DHCPv6 non-standard options in case we need to
|
// Add definitions for DHCPv6 non-standard options in case we need to
|
||||||
// compare subnets, networks and pools in JSON format. In that case,
|
// compare subnets, networks and pools in JSON format. In that case,
|
||||||
// the @c toElement functions require option definitions to generate the
|
// the @c toElement functions require option definitions to generate the
|
||||||
@ -1953,8 +1965,9 @@ TEST_F(MySqlConfigBackendDHCPv6Test, createUpdateDeleteOption6) {
|
|||||||
opt_posix_timezone);
|
opt_posix_timezone);
|
||||||
|
|
||||||
// Retrieve the option again and make sure that updates were
|
// Retrieve the option again and make sure that updates were
|
||||||
// properly propagated to the database.
|
// properly propagated to the database. Use explicit server selector
|
||||||
returned_opt_posix_timezone = cbptr_->getOption6(ServerSelector::ALL(),
|
// which should also return this option.
|
||||||
|
returned_opt_posix_timezone = cbptr_->getOption6(ServerSelector::ONE("server1"),
|
||||||
opt_posix_timezone->option_->getType(),
|
opt_posix_timezone->option_->getType(),
|
||||||
opt_posix_timezone->space_name_);
|
opt_posix_timezone->space_name_);
|
||||||
ASSERT_TRUE(returned_opt_posix_timezone);
|
ASSERT_TRUE(returned_opt_posix_timezone);
|
||||||
@ -1994,6 +2007,189 @@ TEST_F(MySqlConfigBackendDHCPv6Test, createUpdateDeleteOption6) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies that it is possible to differentiate between the
|
||||||
|
// global options by server tag and that the option specified for the
|
||||||
|
// particular server overrides the value specified for all servers.
|
||||||
|
TEST_F(MySqlConfigBackendDHCPv6Test, globalOptions6WithServerTags) {
|
||||||
|
OptionDescriptorPtr opt_timezone1 = test_options_[0];
|
||||||
|
OptionDescriptorPtr opt_timezone2 = test_options_[6];
|
||||||
|
OptionDescriptorPtr opt_timezone3 = test_options_[7];
|
||||||
|
|
||||||
|
EXPECT_THROW(cbptr_->createUpdateOption6(ServerSelector::ONE("server1"),
|
||||||
|
opt_timezone1),
|
||||||
|
DbOperationError);
|
||||||
|
|
||||||
|
// Create two servers.
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[1]));
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("server1 is created");
|
||||||
|
testNewAuditEntry("dhcp6_server",
|
||||||
|
AuditEntry::ModificationType::CREATE,
|
||||||
|
"server set");
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2]));
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("server2 is created");
|
||||||
|
testNewAuditEntry("dhcp6_server",
|
||||||
|
AuditEntry::ModificationType::CREATE,
|
||||||
|
"server set");
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateOption6(ServerSelector::ONE("server1"),
|
||||||
|
opt_timezone1));
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("global option for server1 is set");
|
||||||
|
// The value of 3 means there should be 3 audit entries available for the
|
||||||
|
// server1, two that indicate creation of the servers and one that we
|
||||||
|
// validate, which sets the global option.
|
||||||
|
testNewAuditEntry("dhcp6_options",
|
||||||
|
AuditEntry::ModificationType::CREATE,
|
||||||
|
"global option set",
|
||||||
|
ServerSelector::ONE("server1"),
|
||||||
|
3, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateOption6(ServerSelector::ONE("server2"),
|
||||||
|
opt_timezone2));
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("global option for server2 is set");
|
||||||
|
// Same as in case of the server1, there should be 3 audit entries and
|
||||||
|
// we validate one of them.
|
||||||
|
testNewAuditEntry("dhcp6_options",
|
||||||
|
AuditEntry::ModificationType::CREATE,
|
||||||
|
"global option set",
|
||||||
|
ServerSelector::ONE("server2"),
|
||||||
|
3, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateOption6(ServerSelector::ALL(),
|
||||||
|
opt_timezone3));
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("global option for all servers is set");
|
||||||
|
// There should be one new audit entry for all servers. It logs
|
||||||
|
// the insertion of the global option.
|
||||||
|
testNewAuditEntry("dhcp6_options",
|
||||||
|
AuditEntry::ModificationType::CREATE,
|
||||||
|
"global option set",
|
||||||
|
ServerSelector::ALL(),
|
||||||
|
1, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionDescriptorPtr returned_option;
|
||||||
|
|
||||||
|
// Try to fetch the option specified for all servers. It should return
|
||||||
|
// the third option.
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_option = cbptr_->getOption6(ServerSelector::ALL(),
|
||||||
|
opt_timezone3->option_->getType(),
|
||||||
|
opt_timezone3->space_name_);
|
||||||
|
);
|
||||||
|
ASSERT_TRUE(returned_option);
|
||||||
|
testOptionsEquivalent(*opt_timezone3, *returned_option);
|
||||||
|
|
||||||
|
// Try to fetch the option specified for the server1. It should override the
|
||||||
|
// option specified for all servers.
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_option = cbptr_->getOption6(ServerSelector::ONE("server1"),
|
||||||
|
opt_timezone1->option_->getType(),
|
||||||
|
opt_timezone1->space_name_);
|
||||||
|
);
|
||||||
|
ASSERT_TRUE(returned_option);
|
||||||
|
testOptionsEquivalent(*opt_timezone1, *returned_option);
|
||||||
|
|
||||||
|
// The same in case of the server2.
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_option = cbptr_->getOption6(ServerSelector::ONE("server2"),
|
||||||
|
opt_timezone2->option_->getType(),
|
||||||
|
opt_timezone2->space_name_);
|
||||||
|
);
|
||||||
|
ASSERT_TRUE(returned_option);
|
||||||
|
testOptionsEquivalent(*opt_timezone2, *returned_option);
|
||||||
|
|
||||||
|
OptionContainer returned_options;
|
||||||
|
|
||||||
|
// Try to fetch the collection of global options for the server1, server2
|
||||||
|
// and server3. The server3 does not have an explicit value so for this server
|
||||||
|
// we should get the option associated with "all" servers.
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_options = cbptr_->getAllOptions6(ServerSelector::
|
||||||
|
MULTIPLE({ "server1", "server2",
|
||||||
|
"server3" }));
|
||||||
|
);
|
||||||
|
ASSERT_EQ(3, returned_options.size());
|
||||||
|
|
||||||
|
// Check that expected options have been returned.
|
||||||
|
auto current_option = returned_options.begin();
|
||||||
|
testOptionsEquivalent(*opt_timezone1, *current_option);
|
||||||
|
testOptionsEquivalent(*opt_timezone2, *(++current_option));
|
||||||
|
testOptionsEquivalent(*opt_timezone3, *(++current_option));
|
||||||
|
|
||||||
|
// Try to fetch the collection of options specified for all servers.
|
||||||
|
// This excludes the options specific to server1 and server2. It returns
|
||||||
|
// only the common ones.
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_options = cbptr_->getAllOptions6(ServerSelector::ALL());
|
||||||
|
);
|
||||||
|
ASSERT_EQ(1, returned_options.size());
|
||||||
|
testOptionsEquivalent(*opt_timezone3, *returned_options.begin());
|
||||||
|
|
||||||
|
// Delete the server1. It should remove associations of this server with the
|
||||||
|
// option and the option itself.
|
||||||
|
EXPECT_NO_THROW(cbptr_->deleteServer6(ServerTag("server1")));
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_options = cbptr_->getAllOptions6(ServerSelector::ONE("server1"));
|
||||||
|
);
|
||||||
|
ASSERT_EQ(1, returned_options.size());
|
||||||
|
testOptionsEquivalent(*opt_timezone3, *returned_options.begin());
|
||||||
|
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("DELETE audit entry for the global option after server deletion");
|
||||||
|
testNewAuditEntry("dhcp6_options",
|
||||||
|
AuditEntry::ModificationType::DELETE,
|
||||||
|
"deleting a server", ServerSelector::ONE("server1"),
|
||||||
|
2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to delete global option for server1.
|
||||||
|
uint64_t deleted_num = 0;
|
||||||
|
EXPECT_NO_THROW(deleted_num = cbptr_->deleteOption6(ServerSelector::ONE("server1"),
|
||||||
|
opt_timezone1->option_->getType(),
|
||||||
|
opt_timezone1->space_name_));
|
||||||
|
EXPECT_EQ(0, deleted_num);
|
||||||
|
|
||||||
|
// Deleting the existing option for server2 should succeed.
|
||||||
|
EXPECT_NO_THROW(deleted_num = cbptr_->deleteOption6(ServerSelector::ONE("server2"),
|
||||||
|
opt_timezone2->option_->getType(),
|
||||||
|
opt_timezone2->space_name_));
|
||||||
|
EXPECT_EQ(1, deleted_num);
|
||||||
|
|
||||||
|
// Create this option again to test that deletion of all servers removes it too.
|
||||||
|
EXPECT_NO_THROW(cbptr_->createUpdateOption6(ServerSelector::ONE("server2"),
|
||||||
|
opt_timezone2));
|
||||||
|
|
||||||
|
// Delete all servers, except 'all'.
|
||||||
|
EXPECT_NO_THROW(deleted_num = cbptr_->deleteAllServers6());
|
||||||
|
EXPECT_NO_THROW(
|
||||||
|
returned_options = cbptr_->getAllOptions6(ServerSelector::ALL());
|
||||||
|
);
|
||||||
|
EXPECT_EQ(1, deleted_num);
|
||||||
|
ASSERT_EQ(1, returned_options.size());
|
||||||
|
testOptionsEquivalent(*opt_timezone3, *returned_options.begin());
|
||||||
|
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("DELETE audit entry for the global option after deletion of"
|
||||||
|
" all servers");
|
||||||
|
testNewAuditEntry("dhcp6_options",
|
||||||
|
AuditEntry::ModificationType::DELETE,
|
||||||
|
"deleting all servers", ServerSelector::ONE("server2"),
|
||||||
|
4, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This test verifies that all global options can be retrieved.
|
// This test verifies that all global options can be retrieved.
|
||||||
TEST_F(MySqlConfigBackendDHCPv6Test, getAllOptions6) {
|
TEST_F(MySqlConfigBackendDHCPv6Test, getAllOptions6) {
|
||||||
// Add three global options to the database.
|
// Add three global options to the database.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user