Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
ed7befb6
Commit
ed7befb6
authored
Jul 03, 2019
by
Marcin Siodelski
Browse files
[
#714
,
!409
] Associate global options with the server tags.
parent
711c1dca
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
View file @
ed7befb6
...
...
@@ -115,6 +115,7 @@ public:
DELETE_OPTION_DEF4_CODE_NAME
,
DELETE_ALL_OPTION_DEFS4
,
DELETE_OPTION4
,
DELETE_ALL_OPTIONS4_UNASSIGNED
,
DELETE_OPTION4_SUBNET_ID
,
DELETE_OPTION4_POOL_RANGE
,
DELETE_OPTION4_SHARED_NETWORK
,
...
...
@@ -1441,7 +1442,10 @@ public:
createInputContextBinding
(
option
),
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_
);
...
...
@@ -1456,16 +1460,11 @@ public:
MySqlConfigBackendDHCPv4Impl
::
CREATE_AUDIT_REVISION
,
server_selector
,
"global option set"
,
false
);
if
(
existing_option
)
{
in_bindings
.
push_back
(
MySqlBinding
::
createString
(
tag
));
in_bindings
.
push_back
(
MySqlBinding
::
createInteger
<
uint8_t
>
(
option
->
option_
->
getType
()));
in_bindings
.
push_back
(
MySqlBinding
::
condCreateString
(
option
->
space_name_
));
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv4Impl
::
UPDATE_OPTION4
,
in_bindings
);
}
else
{
if
(
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv4Impl
::
UPDATE_OPTION4
,
in_bindings
)
==
0
)
{
// Remove the 3 bindings used only in case of update.
in_bindings
.
resize
(
in_bindings
.
size
()
-
3
);
insertOption4
(
server_selector
,
in_bindings
);
}
transaction
.
commit
();
...
...
@@ -1931,7 +1930,11 @@ public:
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv4Impl
::
DELETE_ALL_GLOBAL_PARAMETERS4_UNASSIGNED
,
MySqlBindingCollection
());
/// @todo delete dangling options and option definitions.
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv4Impl
::
DELETE_ALL_OPTIONS4_UNASSIGNED
,
MySqlBindingCollection
());
/// @todo delete option definitions.
}
transaction
.
commit
();
...
...
@@ -1967,7 +1970,12 @@ public:
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv4Impl
::
DELETE_ALL_GLOBAL_PARAMETERS4_UNASSIGNED
,
MySqlBindingCollection
());
/// @todo delete dangling options and option definitions.
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv4Impl
::
DELETE_ALL_OPTIONS4_UNASSIGNED
,
MySqlBindingCollection
());
/// @todo delete dangling option definitions.
}
transaction
.
commit
();
...
...
@@ -2396,6 +2404,11 @@ TaggedStatementArray tagged_statements = { {
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.
{
MySqlConfigBackendDHCPv4Impl
::
DELETE_OPTION4_SUBNET_ID
,
MYSQL_DELETE_OPTION
(
dhcp4
,
...
...
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc
View file @
ed7befb6
...
...
@@ -121,6 +121,7 @@ public:
DELETE_OPTION_DEF6_CODE_NAME
,
DELETE_ALL_OPTION_DEFS6
,
DELETE_OPTION6
,
DELETE_ALL_OPTIONS6_UNASSIGNED
,
DELETE_OPTION6_SUBNET_ID
,
DELETE_OPTION6_POOL_RANGE
,
DELETE_OPTION6_PD_POOL
,
...
...
@@ -1653,7 +1654,10 @@ public:
MySqlBinding
::
createNull
(),
MySqlBinding
::
createNull
(),
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_
);
...
...
@@ -1668,16 +1672,11 @@ public:
MySqlConfigBackendDHCPv6Impl
::
CREATE_AUDIT_REVISION
,
server_selector
,
"global option set"
,
false
);
if
(
existing_option
)
{
in_bindings
.
push_back
(
MySqlBinding
::
createString
(
tag
));
in_bindings
.
push_back
(
MySqlBinding
::
createInteger
<
uint16_t
>
(
option
->
option_
->
getType
()));
in_bindings
.
push_back
(
MySqlBinding
::
condCreateString
(
option
->
space_name_
));
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv6Impl
::
UPDATE_OPTION6
,
in_bindings
);
}
else
{
if
(
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv6Impl
::
UPDATE_OPTION6
,
in_bindings
)
==
0
)
{
// Remove the 3 bindings used only in case of update.
in_bindings
.
resize
(
in_bindings
.
size
()
-
3
);
insertOption6
(
server_selector
,
in_bindings
);
}
transaction
.
commit
();
...
...
@@ -2245,7 +2244,11 @@ public:
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv6Impl
::
DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED
,
MySqlBindingCollection
());
/// @todo delete dangling options and option definitions.
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv6Impl
::
DELETE_ALL_OPTIONS6_UNASSIGNED
,
MySqlBindingCollection
());
/// @todo delete dangling option definitions.
}
transaction
.
commit
();
...
...
@@ -2281,7 +2284,11 @@ public:
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv6Impl
::
DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED
,
MySqlBindingCollection
());
/// @todo delete dangling options and option definitions.
conn_
.
updateDeleteQuery
(
MySqlConfigBackendDHCPv6Impl
::
DELETE_ALL_OPTIONS6_UNASSIGNED
,
MySqlBindingCollection
());
/// @todo delete dangling option definitions.
}
transaction
.
commit
();
...
...
@@ -2753,6 +2760,11 @@ TaggedStatementArray tagged_statements = { {
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.
{
MySqlConfigBackendDHCPv6Impl
::
DELETE_OPTION6_SUBNET_ID
,
MYSQL_DELETE_OPTION
(
dhcp6
,
...
...
src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc
View file @
ed7befb6
...
...
@@ -762,8 +762,10 @@ MySqlConfigBackendImpl::getOptions(const int index,
uint64_t
last_option_id
=
0
;
OptionContainer
local_options
;
conn_
.
selectQuery
(
index
,
in_bindings
,
out_bindings
,
[
this
,
universe
,
&
options
,
&
last_option_id
]
[
this
,
universe
,
&
local_
options
,
&
last_option_id
]
(
MySqlBindingCollection
&
out_bindings
)
{
// Parse option.
if
(
!
out_bindings
[
0
]
->
amNull
()
&&
...
...
@@ -774,11 +776,46 @@ MySqlConfigBackendImpl::getOptions(const int index,
OptionDescriptorPtr
desc
=
processOptionRow
(
universe
,
out_bindings
.
begin
());
if
(
desc
)
{
// server_tag for the global option
desc
->
setServerTag
(
out_bindings
[
12
]
->
getString
());
static_cast
<
void
>
(
options
.
push_back
(
*
desc
));
ServerTag
last_option_server_tag
(
out_bindings
[
12
]
->
getString
());
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
...
...
src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h
View file @
ed7befb6
...
...
@@ -353,7 +353,7 @@ namespace {
"INNER JOIN " #table_prefix "_server AS s" \
" ON a.server_id = s.id " \
"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(...) \
MYSQL_GET_OPTION_COMMON(dhcp4, "", __VA_ARGS__)
...
...
@@ -667,6 +667,14 @@ namespace {
"WHERE s.tag = ? " #__VA_ARGS__
#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
#define MYSQL_DELETE_OPTION_POOL_RANGE(table_prefix, ...) \
"DELETE o FROM " #table_prefix "_options AS o " \
...
...
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc
View file @
ed7befb6
...
...
@@ -302,6 +302,18 @@ public:
desc
.
space_name_
=
"isc"
;
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
// compare subnets, networks and pools in JSON format. In that case,
// the @c toElement functions require option definitions to generate the
...
...
@@ -1931,8 +1943,9 @@ TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteOption4) {
opt_boot_file_name
);
// Retrieve the option again and make sure that updates were
// properly propagated to the database.
returned_opt_boot_file_name
=
cbptr_
->
getOption4
(
ServerSelector
::
ALL
(),
// properly propagated to the database. Use explicit server selector
// 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
->
space_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.
TEST_F
(
MySqlConfigBackendDHCPv4Test
,
getAllOptions4
)
{
// Add three global options to the database.
...
...
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc
View file @
ed7befb6
...
...
@@ -343,6 +343,18 @@ public:
desc
.
space_name_
=
"isc"
;
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
// compare subnets, networks and pools in JSON format. In that case,
// the @c toElement functions require option definitions to generate the
...
...
@@ -1953,8 +1965,9 @@ TEST_F(MySqlConfigBackendDHCPv6Test, createUpdateDeleteOption6) {
opt_posix_timezone
);
// Retrieve the option again and make sure that updates were
// properly propagated to the database.
returned_opt_posix_timezone
=
cbptr_
->
getOption6
(
ServerSelector
::
ALL
(),
// properly propagated to the database. Use explicit server selector
// which should also return this option.
returned_opt_posix_timezone
=
cbptr_
->
getOption6
(
ServerSelector
::
ONE
(
"server1"
),
opt_posix_timezone
->
option_
->
getType
(),
opt_posix_timezone
->
space_name_
);
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_
);
);