From: Tomek Mrugalski Date: Wed, 21 May 2014 18:16:24 +0000 (+0200) Subject: [3399] Kea configuration backend for DHCPv4 X-Git-Tag: trac3434_base~15^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e6b9ed0da8a6e51c0fd9aba7754aadf3fa21b45c;p=thirdparty%2Fkea.git [3399] Kea configuration backend for DHCPv4 --- diff --git a/src/bin/dhcp4/kea_controller.cc b/src/bin/dhcp4/kea_controller.cc new file mode 100644 index 0000000000..53d601eb3d --- /dev/null +++ b/src/bin/dhcp4/kea_controller.cc @@ -0,0 +1,143 @@ +// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace isc::asiolink; +using namespace isc::cc; +using namespace isc::config; +using namespace isc::data; +using namespace isc::dhcp; +using namespace isc::log; +using namespace isc::util; +using namespace std; + +namespace isc { +namespace dhcp { + +void +ControlledDhcpv4Srv::init(const std::string& file_name) { + // This is a configuration backend implementation that reads the + // configuration from a JSON file. + + isc::data::ConstElementPtr json; + isc::data::ConstElementPtr dhcp4; + isc::data::ConstElementPtr result; + + // Basic sanity check: file name must not be empty. + try { + if (file_name.empty()) { + // Basic sanity check: file name must not be empty. + isc_throw(BadValue, "JSON configuration file not specified. Please " + "use -c command line option."); + } + + // Read contents of the file and parse it as JSON + json = Element::fromJSONFile(file_name, true); + + if (!json) { + LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL) + .arg("Config file " + file_name + " missing or empty."); + isc_throw(BadValue, "Unable to process JSON configuration file:" + + file_name); + } + + // Get Dhcp4 component from the config + dhcp4 = json->get("Dhcp4"); + + if (!dhcp4) { + LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL) + .arg("Config file " + file_name + " does not include 'Dhcp4' entry."); + isc_throw(BadValue, "Unable to process JSON configuration file:" + + file_name); + } + + // Use parsed JSON structures to configure the server + result = processCommand("config-reload", dhcp4); + + } catch (const std::exception& ex) { + LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL).arg(ex.what()); + isc_throw(BadValue, "Unable to process JSON configuration file:" + + file_name); + } + + if (!result) { + // Undetermined status of the configuration. This should never happen, + // but as the configureDhcp4Server returns a pointer, it is theoretically + // possible that it will return NULL. + LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL) + .arg("Configuration failed: Undefined result of configureDhcp4Server" + "() function after attempting to read " + file_name); + return; + } + + // Now check is the returned result is successful (rcode=0) or not + ConstElementPtr comment; /// see @ref isc::config::parseAnswer + int rcode; + comment = parseAnswer(rcode, result); + if (rcode != 0) { + string reason = ""; + if (comment) { + reason = string(" (") + comment->stringValue() + string(")"); + } + LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL).arg(reason); + isc_throw(BadValue, "Failed to apply configuration:" << reason); + } + + // We don't need to call openActiveSockets() or startD2() as these + // methods are called in processConfig() which is called by + // processCommand("reload-config", ...) +} + +void ControlledDhcpv4Srv::cleanup() { + // Nothing to do here. No need to disconnect from anything. +} + +/// This is a logger initialization for JSON file backend. +/// For now, it's just setting log messages to be printed on stdout. +/// @todo: Implement this properly (see #3427) +void Daemon::loggerInit(const char*, bool verbose, bool ) { + + setenv("B10_LOCKFILE_DIR_FROM_BUILD", "/tmp", 1); + setenv("B10_LOGGER_ROOT", "kea", 0); + setenv("B10_LOGGER_SEVERITY", (verbose ? "DEBUG":"INFO"), 0); + setenv("B10_LOGGER_DBGLEVEL", "99", 0); + setenv("B10_LOGGER_DESTINATION", "stdout", 0); + isc::log::initLogger(); +} + +}; +}; diff --git a/src/bin/dhcp4/tests/kea_controller_unittest.cc b/src/bin/dhcp4/tests/kea_controller_unittest.cc index aa5e5e8566..9475f9b842 100644 --- a/src/bin/dhcp4/tests/kea_controller_unittest.cc +++ b/src/bin/dhcp4/tests/kea_controller_unittest.cc @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include @@ -73,7 +73,7 @@ const char* JSONFileBackendTest::TEST_FILE = "test-config.json"; TEST_F(JSONFileBackendTest, jsonFile) { // Prepare configuration file. - string config = "{ \"interfaces\": [ \"*\" ]," + string config = "{ \"Dhcp4\": { \"interfaces\": [ \"*\" ]," "\"rebind-timer\": 2000, " "\"renew-timer\": 1000, " "\"subnet4\": [ { " @@ -89,7 +89,8 @@ TEST_F(JSONFileBackendTest, jsonFile) { " \"pool\": [ \"192.0.4.101 - 192.0.4.150\" ]," " \"subnet\": \"192.0.4.0/24\" " " } ]," - "\"valid-lifetime\": 4000 }"; + "\"valid-lifetime\": 4000 }" + "}"; writeFile(TEST_FILE, config); @@ -138,7 +139,7 @@ TEST_F(JSONFileBackendTest, jsonFile) { const PoolCollection& pools3 = subnets->at(2)->getPools(Lease::TYPE_V4); EXPECT_EQ("192.0.4.101", pools3.at(0)->getFirstAddress().toText()); EXPECT_EQ("192.0.4.150", pools3.at(0)->getLastAddress().toText()); - EXPECT_EQ(Lease::TYPE_NA, pools3.at(0)->getType()); + EXPECT_EQ(Lease::TYPE_V4, pools3.at(0)->getType()); } // This test checks if configuration can be read from a JSON file. @@ -181,11 +182,11 @@ TEST_F(JSONFileBackendTest, comments) { EXPECT_EQ(22, subnets->at(0)->get().second); // Check pools in the first subnet. - const PoolCollection& pools1 = subnets->at(0)->getPools(Lease::TYPE_NA); + const PoolCollection& pools1 = subnets->at(0)->getPools(Lease::TYPE_V4); ASSERT_EQ(1, pools1.size()); EXPECT_EQ("192.0.2.0", pools1.at(0)->getFirstAddress().toText()); EXPECT_EQ("192.0.2.255", pools1.at(0)->getLastAddress().toText()); - EXPECT_EQ(Lease::TYPE_NA, pools1.at(0)->getType()); + EXPECT_EQ(Lease::TYPE_V4, pools1.at(0)->getType()); } // This test checks if configuration detects failure when trying: