Commit 0b223d03 authored by Francis Dupont's avatar Francis Dupont
Browse files

[5531] Done

parent 68fbae07
......@@ -54,13 +54,17 @@
// reservations list, within the subnet (configuration file). If there are
// no reservations there, the server will try to retrieve reservations
// from this database.
"hosts-database": {
"type": "postgresql",
"name": "kea",
"user": "kea",
"password": "kea",
"host": "localhost"
},
// The database specification can go into one hosts-database entry for
// backward compatibility or be listed in hosts-databases list.
"hosts-databases": [
{
"type": "postgresql",
"name": "kea",
"user": "kea",
"password": "kea",
"host": "localhost"
}
],
// Define a subnet with a single pool of dynamic addresses. Addresses from
// this pool will be assigned to clients which don't have reservations in the
......
......@@ -41,13 +41,17 @@
// reservations list, within the subnet (configuration file). If there are
// no reservations there, the server will try to retrieve reservations
// from this database.
"hosts-database": {
"type": "postgresql",
"name": "kea",
"user": "kea",
"password": "kea",
"host": "localhost"
},
// The database specification can go into one hosts-database entry for
// backward compatibility or be listed in hosts-databases list.
"hosts-databases": [
{
"type": "postgresql",
"name": "kea",
"user": "kea",
"password": "kea",
"host": "localhost"
}
],
// Define a subnet with a pool of dynamic addresses and a pool of dynamic
// prefixes. Addresses and prefixes from those pools will be assigned to
......
......@@ -529,7 +529,13 @@ If a timeout is given though, it should be an integer greater than zero.
from the configuration file are checked first and external storage is checked
later, if necessary.</para>
<section xml:id="hosts-database-configuration4">
<para>Version 1.4 extends the host storage to multiple storages. Operations
are performed on host storages in the configuration order with a special
case for addition: read-only storages must be configured after a
required read-write storage, or host reservation addition will
always fail.</para>
<section xml:id="hosts-databases-configuration4">
<title>DHCPv4 Hosts Database Configuration</title>
<para>Hosts database configuration is controlled through the Dhcp4/hosts-database
......@@ -572,6 +578,16 @@ If a timeout is given though, it should be an integer greater than zero.
</screen>
If there is no password to the account, set the password to the empty string
"". (This is also the default.)</para>
<para>The multiple storage extension uses a similar syntax: a configuration
is placed into a "hosts-databases" list instead of into a "hosts-database"
entry as in:
<screen>
"Dhcp4": { "hosts-databases": [ { <userinput>"type": "mysql"</userinput>, ... }, ... ], ... }
</screen>
</para>
</section>
<section xml:id="read-only-database-configuration4">
......
......@@ -525,7 +525,13 @@ If a timeout is given though, it should be an integer greater than zero.
from the configuration file are checked first and external storage is checked
later, if necessary.</para>
<section xml:id="hosts-database-configuration6">
<para>Version 1.4 extends the host storage to multiple storages. Operations
are performed on host storages in the configuration order with a special
case for addition: read-only storages must be configured after a
required read-write storage, or host reservation addition will
always fail.</para>
<section xml:id="hosts-databases-configuration6">
<title>DHCPv6 Hosts Database Configuration</title>
<para>Hosts database configuration is controlled through the Dhcp6/hosts-database
......@@ -565,6 +571,16 @@ If a timeout is given though, it should be an integer greater than zero.
</screen>
If there is no password to the account, set the password to the empty string
"". (This is also the default.)</para>
<para>The multiple storage extension uses a similar syntax: a configuration
is placed into a "hosts-databases" list instead of into a "hosts-database"
entry as in:
<screen>
"Dhcp6": { "hosts-databases": [ { <userinput>"type": "mysql"</userinput>, ... }, ... ], ... }
</screen>
</para>
</section>
<section xml:id="read-only-database-configuration6">
......
......@@ -1025,9 +1025,9 @@ Administrator deleted a lease for a device identified by: duid of 1a:1b:1c:1d:1e
criteria). To use commands that change the reservation information
(currently these are reservation-add and reservation-del, but this
rule applies to other commands that may be implemented in the future),
hosts database must be specified (see hosts-database description in
<xref linkend="hosts-database-configuration4"/> and <xref linkend="hosts-database-configuration6"/>) and it must not operate in
read-only mode. If the hosts-database is not specified or is running
hosts database must be specified (see hosts-databases description in
<xref linkend="hosts-databases-configuration4"/> and <xref linkend="hosts-databases-configuration6"/>) and it must not operate in
read-only mode. If the hosts-databases are not specified or are running
in read-only mode, the host_cmds library will load, but any attempts
to use reservation-add or reservation-del will fail.
</para>
......@@ -1146,8 +1146,8 @@ Here is an example of complex IPv6 reservation:
<para>
As <command>reservation-add</command> is expected to store the host,
hosts-database parameter must be specified in your configuration and
the database must not run in read-only mode. In the future versions
hosts-databases parameter must be specified in your configuration and
databases must not run in read-only mode. In the future versions
it will be possible to modify the reservations read from a
configuration file. Please contact ISC if you are interested in this
functionality.
......
......@@ -412,27 +412,25 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set,
// Please move at the end when migration will be finished.
if (config_pair.first == "lease-database") {
DbAccessParser parser(DbAccessParser::LEASE_DB);
DbAccessParser parser(CfgDbAccess::LEASE_DB);
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
parser.parse(cfg_db_access, config_pair.second);
continue;
}
if (config_pair.first == "hosts-database") {
DbAccessParser parser(DbAccessParser::HOSTS_DB);
DbAccessParser parser(CfgDbAccess::HOSTS_DB);
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
parser.parse(cfg_db_access, config_pair.second);
continue;
}
// For now only support empty or singleton, ignoring extra entries.
if (config_pair.first == "hosts-databases") {
if (config_pair.second->size() == 0) {
continue;
}
DbAccessParser parser(DbAccessParser::HOSTS_DB);
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
parser.parse(cfg_db_access, config_pair.second->get(0));
for (size_t i = 0; i < config_pair.second->size(); ++i) {
DbAccessParser parser(CfgDbAccess::HOSTS_DB + i);
parser.parse(cfg_db_access, config_pair.second->get(i));
}
continue;
}
......
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -131,6 +131,28 @@ const char* PARSER_CONFIGS[] = {
" } ]"
"}",
// Configuration 4: two host databases
"{"
" \"interfaces-config\": {"
" \"interfaces\": [\"*\" ]"
" },"
" \"valid-lifetime\": 4000,"
" \"rebind-timer\": 2000,"
" \"renew-timer\": 1000,"
" \"hosts-databases\": [ {"
" \"type\": \"mysql\","
" \"name\": \"keatest1\","
" \"user\": \"keatest\","
" \"password\": \"keatest\""
" },{"
" \"type\": \"mysql\","
" \"name\": \"keatest2\","
" \"user\": \"keatest\","
" \"password\": \"keatest\""
" }"
" ]"
"}",
// Last Configuration for comments
"{"
" \"comment\": \"A DHCPv4 server\","
......@@ -5757,10 +5779,28 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDeriveClientClass) {
EXPECT_TRUE(classes.empty());
}
// This test checks multiple host data sources.
TEST_F(Dhcp4ParserTest, hostsDatabases) {
string config = PARSER_CONFIGS[4];
extractConfig(config);
configure(config, CONTROL_RESULT_SUCCESS, "");
// Check database config
ConstCfgDbAccessPtr cfgdb =
CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
ASSERT_TRUE(cfgdb);
const std::vector<std::string>& hal = cfgdb->getHostDbAccessStringList();
ASSERT_EQ(2, hal.size());
// Keywords are in alphabetical order
EXPECT_EQ("name=keatest1 password=keatest type=mysql user=keatest", hal[0]);
EXPECT_EQ("name=keatest2 password=keatest type=mysql user=keatest", hal[1]);
}
// This test checks comments. Please keep it last.
TEST_F(Dhcp4ParserTest, comments) {
string config = PARSER_CONFIGS[4];
string config = PARSER_CONFIGS[5];
extractConfig(config);
configure(config, CONTROL_RESULT_SUCCESS, "");
......
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -1719,6 +1719,30 @@ const char* EXTRACTED_CONFIGS[] = {
" }\n",
// CONFIGURATION 60
"{\n"
" \"hosts-databases\": [\n"
" {\n"
" \"name\": \"keatest1\",\n"
" \"password\": \"keatest\",\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" },\n"
" {\n"
" \"name\": \"keatest2\",\n"
" \"password\": \"keatest\",\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" }\n"
" ],\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 61
"{\n"
" \"comment\": \"A DHCPv4 server\",\n"
" \"client-classes\": [\n"
" {\n"
......@@ -6683,6 +6707,63 @@ const char* UNPARSED_CONFIGS[] = {
" }\n",
// CONFIGURATION 60
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
" \"always-include-fqdn\": false,\n"
" \"enable-updates\": false,\n"
" \"generated-prefix\": \"myhost\",\n"
" \"max-queue-size\": 1024,\n"
" \"ncr-format\": \"JSON\",\n"
" \"ncr-protocol\": \"UDP\",\n"
" \"override-client-update\": false,\n"
" \"override-no-update\": false,\n"
" \"qualifying-suffix\": \"\",\n"
" \"replace-client-name\": \"never\",\n"
" \"sender-ip\": \"0.0.0.0\",\n"
" \"sender-port\": 0,\n"
" \"server-ip\": \"127.0.0.1\",\n"
" \"server-port\": 53001\n"
" },\n"
" \"dhcp4o6-port\": 0,\n"
" \"echo-client-id\": true,\n"
" \"expired-leases-processing\": {\n"
" \"flush-reclaimed-timer-wait-time\": 25,\n"
" \"hold-reclaimed-time\": 3600,\n"
" \"max-reclaim-leases\": 100,\n"
" \"max-reclaim-time\": 250,\n"
" \"reclaim-timer-wait-time\": 10,\n"
" \"unwarned-reclaim-cycles\": 5\n"
" },\n"
" \"hooks-libraries\": [ ],\n"
" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n"
" \"hosts-databases\": [\n"
" {\n"
" \"name\": \"keatest1\",\n"
" \"password\": \"keatest\",\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" },\n"
" {\n"
" \"name\": \"keatest2\",\n"
" \"password\": \"keatest\",\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" }\n"
" ],\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"re-detect\": false\n"
" },\n"
" \"lease-database\": {\n"
" \"type\": \"memfile\"\n"
" },\n"
" \"option-data\": [ ],\n"
" \"option-def\": [ ],\n"
" \"shared-networks\": [ ],\n"
" \"subnet4\": [ ]\n"
" }\n",
// CONFIGURATION 61
"{\n"
" \"comment\": \"A DHCPv4 server\",\n"
" \"client-classes\": [\n"
" {\n"
......
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -124,7 +124,7 @@ outputFormatted(const std::string& config) {
}
}
};
} // namespace
namespace isc {
namespace dhcp {
......@@ -155,9 +155,9 @@ extractConfig(const std::string& config) {
++extract_count;
}
};
};
};
} // namespace test
} // namespace dhcp
} // namespace isc
namespace {
......
......@@ -525,14 +525,14 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set,
// Please move at the end when migration will be finished.
if (config_pair.first == "lease-database") {
DbAccessParser parser(DbAccessParser::LEASE_DB);
DbAccessParser parser(CfgDbAccess::LEASE_DB);
CfgDbAccessPtr cfg_db_access = srv_config->getCfgDbAccess();
parser.parse(cfg_db_access, config_pair.second);
continue;
}
if (config_pair.first == "hosts-database") {
DbAccessParser parser(DbAccessParser::HOSTS_DB);
DbAccessParser parser(CfgDbAccess::HOSTS_DB);
CfgDbAccessPtr cfg_db_access = srv_config->getCfgDbAccess();
parser.parse(cfg_db_access, config_pair.second);
continue;
......@@ -540,12 +540,11 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set,
// For now only support empty or singleton, ignoring extra entries.
if (config_pair.first == "hosts-databases") {
if (config_pair.second->size() == 0) {
continue;
}
DbAccessParser parser(DbAccessParser::HOSTS_DB);
CfgDbAccessPtr cfg_db_access = srv_config->getCfgDbAccess();
parser.parse(cfg_db_access, config_pair.second->get(0));
for (size_t i = 0; i < config_pair.second->size(); ++i) {
DbAccessParser parser(CfgDbAccess::HOSTS_DB + i);
parser.parse(cfg_db_access, config_pair.second->get(i));
}
continue;
}
......
......@@ -208,6 +208,29 @@ const char* PARSER_CONFIGS[] = {
" } ]"
"}",
// Configuration 7: two host databases
"{"
" \"interfaces-config\": {"
" \"interfaces\": [\"*\" ]"
" },"
" \"valid-lifetime\": 4000,"
" \"preferred-lifetime\": 3000,"
" \"rebind-timer\": 2000,"
" \"renew-timer\": 1000,"
" \"hosts-databases\": [ {"
" \"type\": \"mysql\","
" \"name\": \"keatest1\","
" \"user\": \"keatest\","
" \"password\": \"keatest\""
" },{"
" \"type\": \"mysql\","
" \"name\": \"keatest2\","
" \"user\": \"keatest\","
" \"password\": \"keatest\""
" }"
" ]"
"}",
// Last configuration for comments
"{"
" \"comment\": \"A DHCPv6 server\","
......@@ -6314,10 +6337,28 @@ TEST_F(Dhcp6ParserTest, sharedNetworksRapidCommitMix) {
"shared-network or the shared-network itself used rapid-commit true");
}
// This test checks multiple host data sources.
TEST_F(Dhcp6ParserTest, hostsDatabases) {
string config = PARSER_CONFIGS[7];
extractConfig(config);
configure(config, CONTROL_RESULT_SUCCESS, "");
// Check database config
ConstCfgDbAccessPtr cfgdb =
CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
ASSERT_TRUE(cfgdb);
const std::vector<std::string>& hal = cfgdb->getHostDbAccessStringList();
ASSERT_EQ(2, hal.size());
// Keywords are in alphabetical order
EXPECT_EQ("name=keatest1 password=keatest type=mysql user=keatest", hal[0]);
EXPECT_EQ("name=keatest2 password=keatest type=mysql user=keatest", hal[1]);
}
// This test checks comments. Please keep it last.
TEST_F(Dhcp6ParserTest, comments) {
string config = PARSER_CONFIGS[7];
string config = PARSER_CONFIGS[8];
extractConfig(config);
configure(config, CONTROL_RESULT_SUCCESS, "");
......
......@@ -1584,6 +1584,31 @@ const char* EXTRACTED_CONFIGS[] = {
" }\n",
// CONFIGURATION 53
"{\n"
" \"hosts-databases\": [\n"
" {\n"
" \"name\": \"keatest1\",\n"
" \"password\": \"keatest\",\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" },\n"
" {\n"
" \"name\": \"keatest2\",\n"
" \"password\": \"keatest\",\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" }\n"
" ],\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 54
"{\n"
" \"comment\": \"A DHCPv6 server\",\n"
" \"client-classes\": [\n"
" {\n"
......@@ -6240,6 +6265,72 @@ const char* UNPARSED_CONFIGS[] = {
" }\n",
// CONFIGURATION 53
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
" \"always-include-fqdn\": false,\n"
" \"enable-updates\": false,\n"
" \"generated-prefix\": \"myhost\",\n"
" \"max-queue-size\": 1024,\n"
" \"ncr-format\": \"JSON\",\n"
" \"ncr-protocol\": \"UDP\",\n"
" \"override-client-update\": false,\n"
" \"override-no-update\": false,\n"
" \"qualifying-suffix\": \"\",\n"
" \"replace-client-name\": \"never\",\n"
" \"sender-ip\": \"0.0.0.0\",\n"
" \"sender-port\": 0,\n"
" \"server-ip\": \"127.0.0.1\",\n"
" \"server-port\": 53001\n"
" },\n"
" \"dhcp4o6-port\": 0,\n"
" \"expired-leases-processing\": {\n"
" \"flush-reclaimed-timer-wait-time\": 25,\n"
" \"hold-reclaimed-time\": 3600,\n"
" \"max-reclaim-leases\": 100,\n"
" \"max-reclaim-time\": 250,\n"
" \"reclaim-timer-wait-time\": 10,\n"
" \"unwarned-reclaim-cycles\": 5\n"
" },\n"
" \"hooks-libraries\": [ ],\n"
" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
" \"hosts-databases\": [\n"
" {\n"
" \"name\": \"keatest1\",\n"
" \"password\": \"keatest\",\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" },\n"
" {\n"
" \"name\": \"keatest2\",\n"
" \"password\": \"keatest\",\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" }\n"
" ],\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"re-detect\": false\n"
" },\n"
" \"lease-database\": {\n"
" \"type\": \"memfile\"\n"
" },\n"
" \"mac-sources\": [ \"any\" ],\n"
" \"option-data\": [ ],\n"
" \"option-def\": [ ],\n"
" \"relay-supplied-options\": [ \"65\" ],\n"
" \"server-id\": {\n"
" \"enterprise-id\": 0,\n"
" \"htype\": 0,\n"
" \"identifier\": \"\",\n"
" \"persist\": true,\n"
" \"time\": 0,\n"
" \"type\": \"LLT\"\n"
" },\n"
" \"shared-networks\": [ ],\n"
" \"subnet6\": [ ]\n"
" }\n",
// CONFIGURATION 54
"{\n"
" \"comment\": \"A DHCPv6 server\",\n"
" \"client-classes\": [\n"
" {\n"
......@@ -6459,7 +6550,7 @@ outputFormatted(const std::string& config) {
}
}
}
} // namespace
namespace isc {
namespace dhcp {
......
......@@ -125,7 +125,7 @@ outputFormatted(const std::string& config) {
}
}
};
} // namespace
namespace isc {
namespace dhcp {
......@@ -156,9 +156,9 @@ extractConfig(const std::string& config) {
++extract_count;
}
};
};
};