Commit 381371a7 authored by Francis Dupont's avatar Francis Dupont

[430-configure-location-of-datadir] Moved datadir to server config and use it for v6

parent 15f8d821
......@@ -645,6 +645,7 @@
// Queue type was mandatory.
"queue-type": "kea-ring6"
}
// missing data-directory
},
// Logging configuration begins here.
......
......@@ -4444,6 +4444,22 @@ autogenerated IDs are not stable across configuration changes.
identifier is explicitly specified in the configuration.</para>
</section>
<section xml:id="data-directory">
<title>DHCPv6 data directory</title>
<para>The Kea DHCPv6 server puts the server identifier file and the
default memory lease file into its data directory. By default
this directory is <filename><userinput>prefix</userinput>/var/kea</filename>
but this location can be changed using the
<command>data-directory</command> global parameter as in:
<screen>
"Dhcp6": {
"data-directory": <userinput>/var/tmp/kea-server6</userinput>,
...
}
</screen>
</para>
</section>
<section xml:id="stateless-dhcp6">
<title>Stateless DHCPv6 (Information-Request Message)</title>
<para>Typically DHCPv6 is used to assign both addresses and options. These
......
// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2019 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
......@@ -36,18 +36,19 @@ namespace dhcp {
namespace test {
BaseServerTest::BaseServerTest()
: original_datadir_(CfgMgr::instance().getDataDir()) {
CfgMgr::instance().setDataDir(TEST_DATA_BUILDDIR);
: original_datadir_(CfgMgr::instance().getCurrentCfg()->getDataDir()) {
CfgMgr::instance().getStagingCfg()->setDataDir(TEST_DATA_BUILDDIR);
}
BaseServerTest::~BaseServerTest() {
// Remove default lease file.
std::ostringstream s2;
s2 << CfgMgr::instance().getDataDir() << "/" << "kea-leases4.csv";
s2 << CfgMgr::instance().getStagingCfg()->getDataDir()
<< "/" << "kea-leases4.csv";
static_cast<void>(::remove(s2.str().c_str()));
// Revert to original data directory.
CfgMgr::instance().setDataDir(original_datadir_);
CfgMgr::instance().getStagingCfg()->setDataDir(original_datadir_);
// Revert to unit test logging, in case the test reconfigured it.
isc::log::initLogger();
......
// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2019 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
......@@ -617,7 +617,8 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
// Regenerate server identifier if needed.
try {
const std::string duid_file = CfgMgr::instance().getDataDir() + "/" +
const std::string duid_file =
CfgMgr::instance().getStagingCfg()->getDataDir() + "/" +
std::string(SERVER_DUID_FILE);
DuidPtr duid = CfgMgr::instance().getStagingCfg()->getCfgDUID()->create(duid_file);
server_->serverid_.reset(new Option(Option::V6, D6O_SERVERID, duid->getDuid()));
......
......@@ -65,6 +65,21 @@ using namespace isc::hooks;
namespace {
/// @brief Checks if specified directory exists.
///
/// @param dir_path Path to a directory.
/// @throw BadValue If the directory does not exist or is not a directory.
void dirExists(const string& dir_path) {
struct stat statbuf;
if (stat(dir_path.c_str(), &statbuf) < 0) {
isc_throw(BadValue, "Bad directory '" << dir_path
<< "': " << strerror(errno));
}
if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
isc_throw(BadValue, "'" << dir_path << "' is not a directory");
}
}
/// @brief Parser for list of RSOO options
///
/// This parser handles a Dhcp6/relay-supplied-options entry. It contains a
......@@ -148,6 +163,7 @@ public:
///
/// Currently this method sets the following global parameters:
///
/// - data-directory
/// - decline-probation-period
/// - dhcp4o6-port
/// - user-context
......@@ -156,6 +172,11 @@ public:
/// or having incorrect values.
void parse(const SrvConfigPtr& srv_config, const ConstElementPtr& global) {
// Set the data directory for server id file.
if (global->contains("data-directory")) {
srv_config->setDataDir(getString(global, "data-directory"));
}
// Set the probation period for decline handling.
uint32_t probation_period =
getUint32(global, "decline-probation-period");
......@@ -458,6 +479,12 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
// with the parser code debugability, so I decided to keep it as a
// series of independent ifs.
if (config_pair.first == "data-directory") {
// Specific check for this global parameter.
dirExists(config_pair.second->stringValue());
continue;
}
if (config_pair.first == "option-def") {
// This is converted to SimpleParser and is handled already above.
continue;
......
......@@ -5451,6 +5451,71 @@ TEST_F(Dhcp6ParserTest, rsooBogusName) {
EXPECT_TRUE(errorContainsPosition(status, "<string>"));
}
/// Check that not existent data directory returns an error.
TEST_F(Dhcp6ParserTest, notExistDataDir) {
string config_txt = "{\n"
"\"data-directory\": \"/does-not-exist--\"\n"
"}";
ConstElementPtr config;
ASSERT_NO_THROW(config = parseDHCP6(config_txt));
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, config));
// returned value should be 1 (error)
int rcode;
ConstElementPtr comment = parseAnswer(rcode, status);
EXPECT_EQ(1, rcode);
string text;
ASSERT_NO_THROW(text = comment->stringValue());
EXPECT_EQ("Bad directory '/does-not-exist--': No such file or directory",
text);
}
/// Check that not a directory data directory returns an error.
TEST_F(Dhcp6ParserTest, notDirDataDir) {
string config_txt = "{\n"
"\"data-directory\": \"/dev/null\"\n"
"}";
ConstElementPtr config;
ASSERT_NO_THROW(config = parseDHCP6(config_txt));
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, config));
// returned value should be 1 (error)
int rcode;
ConstElementPtr comment = parseAnswer(rcode, status);
EXPECT_EQ(1, rcode);
string text;
ASSERT_NO_THROW(text = comment->stringValue());
EXPECT_EQ("'/dev/null' is not a directory", text);
}
/// Check that a valid data directory is accepted.
TEST_F(Dhcp6ParserTest, testDataDir) {
string datadir(TEST_DATA_BUILDDIR);
string config_txt = "{\n"
"\"data-directory\": \"" + datadir + "\"\n"
"}";
ConstElementPtr config;
ASSERT_NO_THROW(config = parseDHCP6(config_txt));
extractConfig(config_txt);
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, config));
// returned value should be 0 (success);
checkResult(status, 0);
// The value of data-directory was updated.
EXPECT_EQ(datadir, CfgMgr::instance().getStagingCfg()->getDataDir());
EXPECT_NE(datadir, CfgMgr::instance().getCurrentCfg()->getDataDir());
}
/// Check that the decline-probation-period value has a default value if not
/// specified explicitly.
TEST_F(Dhcp6ParserTest, declineTimerDefault) {
......
// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2019 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
......@@ -30,23 +30,25 @@ namespace test {
const char* BaseServerTest::DUID_FILE = "kea-dhcp6-serverid";
BaseServerTest::BaseServerTest()
: original_datadir_(CfgMgr::instance().getDataDir()) {
CfgMgr::instance().setDataDir(TEST_DATA_BUILDDIR);
: original_datadir_(CfgMgr::instance().getCurrentCfg()->getDataDir()) {
CfgMgr::instance().getStagingCfg()->setDataDir(TEST_DATA_BUILDDIR);
}
BaseServerTest::~BaseServerTest() {
// Remove test DUID file.
std::ostringstream s;
s << CfgMgr::instance().getDataDir() << "/" << DUID_FILE;
s << CfgMgr::instance().getStagingCfg()->getDataDir()
<< "/" << DUID_FILE;
static_cast<void>(::remove(s.str().c_str()));
// Remove default lease file.
std::ostringstream s2;
s2 << CfgMgr::instance().getDataDir() << "/" << "kea-leases6.csv";
s2 << CfgMgr::instance().getStagingCfg()->getDataDir()
<< "/" << "kea-leases6.csv";
static_cast<void>(::remove(s2.str().c_str()));
// Revert to original data directory.
CfgMgr::instance().setDataDir(original_datadir_);
CfgMgr::instance().getStagingCfg()->setDataDir(original_datadir_);
// Revert to unit test logging in case the test reconfigured logging.
isc::log::initLogger();
......
......@@ -1399,13 +1399,17 @@ const char* EXTRACTED_CONFIGS[] = {
" }\n",
// CONFIGURATION 43
"{\n"
" \"data-directory\": \"/tmp/k430/src/bin/dhcp6/tests\"\n"
" }\n",
// CONFIGURATION 44
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"re-detect\": false\n"
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
// CONFIGURATION 44
// CONFIGURATION 45
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
......@@ -1413,7 +1417,7 @@ const char* EXTRACTED_CONFIGS[] = {
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
// CONFIGURATION 45
// CONFIGURATION 46
"{\n"
" \"decline-probation-period\": 12345,\n"
" \"interfaces-config\": {\n"
......@@ -1422,7 +1426,7 @@ const char* EXTRACTED_CONFIGS[] = {
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
// CONFIGURATION 46
// CONFIGURATION 47
"{\n"
" \"expired-leases-processing\": {\n"
" \"flush-reclaimed-timer-wait-time\": 35,\n"
......@@ -1438,7 +1442,7 @@ const char* EXTRACTED_CONFIGS[] = {
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
// CONFIGURATION 47
// CONFIGURATION 48
"{\n"
" \"client-classes\": [\n"
" {\n"
......@@ -1470,7 +1474,7 @@ const char* EXTRACTED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 48
// CONFIGURATION 49
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
......@@ -1491,7 +1495,7 @@ const char* EXTRACTED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 49
// CONFIGURATION 50
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
......@@ -1513,7 +1517,7 @@ const char* EXTRACTED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 50
// CONFIGURATION 51
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
......@@ -1540,7 +1544,7 @@ const char* EXTRACTED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 51
// CONFIGURATION 52
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
......@@ -1567,7 +1571,7 @@ const char* EXTRACTED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 52
// CONFIGURATION 53
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
......@@ -1590,7 +1594,7 @@ const char* EXTRACTED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 53
// CONFIGURATION 54
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
......@@ -1614,7 +1618,7 @@ const char* EXTRACTED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 54
// CONFIGURATION 55
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
......@@ -1643,7 +1647,7 @@ const char* EXTRACTED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 55
// CONFIGURATION 56
"{\n"
" \"hosts-databases\": [\n"
" {\n"
......@@ -1668,7 +1672,7 @@ const char* EXTRACTED_CONFIGS[] = {
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 56
// CONFIGURATION 57
"{\n"
" \"comment\": \"A DHCPv6 server\",\n"
" \"client-classes\": [\n"
......@@ -1765,7 +1769,7 @@ const char* EXTRACTED_CONFIGS[] = {
" }\n"
" ]\n"
" }\n",
// CONFIGURATION 57
// CONFIGURATION 58
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
......@@ -1830,7 +1834,7 @@ const char* EXTRACTED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 58
// CONFIGURATION 59
"{\n"
" \"config-control\": {\n"
" \"config-databases\": [\n"
......@@ -6299,6 +6303,7 @@ const char* UNPARSED_CONFIGS[] = {
" }\n",
// CONFIGURATION 43
"{\n"
" \"data-directory\": \"/tmp/k430/src/bin/dhcp6/tests\",\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
" \"enable-updates\": false,\n"
......@@ -6334,7 +6339,7 @@ const char* UNPARSED_CONFIGS[] = {
" \"hooks-libraries\": [ ],\n"
" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"interfaces\": [ ],\n"
" \"re-detect\": false\n"
" },\n"
" \"lease-database\": {\n"
......@@ -6421,7 +6426,7 @@ const char* UNPARSED_CONFIGS[] = {
" }\n",
// CONFIGURATION 45
"{\n"
" \"decline-probation-period\": 12345,\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
" \"enable-updates\": false,\n"
" \"generated-prefix\": \"myhost\",\n"
......@@ -6482,6 +6487,67 @@ const char* UNPARSED_CONFIGS[] = {
" }\n",
// CONFIGURATION 46
"{\n"
" \"decline-probation-period\": 12345,\n"
" \"dhcp-ddns\": {\n"
" \"enable-updates\": false,\n"
" \"generated-prefix\": \"myhost\",\n"
" \"hostname-char-replacement\": \"\",\n"
" \"hostname-char-set\": \"\",\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"
" \"dhcp-queue-control\": {\n"
" \"capacity\": 500,\n"
" \"enable-queue\": false,\n"
" \"queue-type\": \"kea-ring6\"\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"
" \"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"
" \"sanity-checks\": {\n"
" \"lease-checks\": \"warn\"\n"
" },\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 47
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
" \"enable-updates\": false,\n"
......@@ -6541,7 +6607,7 @@ const char* UNPARSED_CONFIGS[] = {
" \"shared-networks\": [ ],\n"
" \"subnet6\": [ ]\n"
" }\n",
// CONFIGURATION 47
// CONFIGURATION 48
"{\n"
" \"client-classes\": [\n"
" {\n"
......@@ -6643,7 +6709,7 @@ const char* UNPARSED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 48
// CONFIGURATION 49
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
......@@ -6731,7 +6797,7 @@ const char* UNPARSED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 49
// CONFIGURATION 50
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
......@@ -6820,7 +6886,7 @@ const char* UNPARSED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 50
// CONFIGURATION 51
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
......@@ -6914,7 +6980,7 @@ const char* UNPARSED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 51
// CONFIGURATION 52
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
......@@ -7008,7 +7074,7 @@ const char* UNPARSED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 52
// CONFIGURATION 53
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
......@@ -7098,7 +7164,7 @@ const char* UNPARSED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 53
// CONFIGURATION 54
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
......@@ -7189,7 +7255,7 @@ const char* UNPARSED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 54
// CONFIGURATION 55
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
......@@ -7285,7 +7351,7 @@ const char* UNPARSED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 55
// CONFIGURATION 56
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
......@@ -7364,7 +7430,7 @@ const char* UNPARSED_CONFIGS[] = {
" \"subnet6\": [ ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 56
// CONFIGURATION 57
"{\n"
" \"comment\": \"A DHCPv6 server\",\n"
" \"client-classes\": [\n"
......@@ -7544,7 +7610,7 @@ const char* UNPARSED_CONFIGS[] = {
" ],\n"
" \"subnet6\": [ ]\n"
" }\n",
// CONFIGURATION 57
// CONFIGURATION 58
"{\n"
" \"decline-probation-period\": 86400,\n"
" \"dhcp-ddns\": {\n"
......@@ -7718,7 +7784,7 @@ const char* UNPARSED_CONFIGS[] = {
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
// CONFIGURATION 58
// CONFIGURATION 59
"{\n"
" \"config-control\": {\n"
" \"config-databases\": [\n"
......
......@@ -27,15 +27,6 @@ CfgMgr::instance() {
return (cfg_mgr);
}
std::string CfgMgr::getDataDir() const {
return (datadir_);
}
void
CfgMgr::setDataDir(const std::string& datadir) {
datadir_ = datadir;
}
void
CfgMgr::setD2ClientConfig(D2ClientConfigPtr& new_config) {
ensureCurrentAllocated();
......@@ -203,11 +194,7 @@ CfgMgr::mergeIntoCfg(const SrvConfigPtr& target_config, const uint32_t seq) {
}
}
CfgMgr::CfgMgr()
: datadir_(DHCP_DATA_DIR), d2_client_mgr_(), family_(AF_INET) {
// DHCP_DATA_DIR must be set set with -DDHCP_DATA_DIR="..." in Makefile.am
// Note: the definition of DHCP_DATA_DIR needs to include quotation marks
// See AM_CPPFLAGS definition in Makefile.am
CfgMgr::CfgMgr() : d2_client_mgr_(), family_(AF_INET) {
}
CfgMgr::~CfgMgr() {
......
......@@ -80,18 +80,6 @@ public:
/// accessing it.
static CfgMgr& instance();