AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/cc -I$(top_builddir)/src/lib/cc
-AM_CPPFLAGS += -DTOP_BUILDDIR="\"$(top_builddir)\""
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS = $(B10_CXXFLAGS)
endif
if CONFIG_BACKEND_JSON
-b10_dhcp6_SOURCES += jsonfile_controller.cc
+b10_dhcp6_SOURCES += kea_controller.cc
endif
nodist_b10_dhcp6_SOURCES = dhcp6_messages.h dhcp6_messages.cc
/// *_backend.cc
///
/// @return true if initialization was successful, false if it failed
- bool init(const std::string& config_file);
+ void init(const std::string& config_file);
/// @brief Performs cleanup, immediately before termination
///
namespace isc {
namespace dhcp {
-bool
+void
ControlledDhcpv6Srv::init(const std::string& file_name) {
// This is a configuration backend implementation that reads the
// configuration from a JSON file.
isc::data::ConstElementPtr result;
// Basic sanity check: file name must not be empty.
- if (file_name.empty()) {
- isc_throw(BadValue, "JSON configuration file not specified");
- }
-
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);
LOG_ERROR(dhcp6_logger, DHCP6_CONFIG_LOAD_FAIL)
.arg("Configuration failed: Undefined result of configureDhcp6Server"
"() function after attempting to read " + file_name);
- return (false);
+ return;
}
// Now check is the returned result is successful (rcode=0) or not
reason = string(" (") + comment->stringValue() + string(")");
}
LOG_ERROR(dhcp6_logger, DHCP6_CONFIG_LOAD_FAIL).arg(reason);
- return (false);
+ 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", ...)
-
- return (true);
}
void ControlledDhcpv6Srv::cleanup() {
/// 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* log_name, bool verbose, bool ) {
- // This method configures logger. For now it is very simple.
- // We'll make it more robust once we add support for JSON-based logging
- // configuration.
-
- using namespace isc::log;
-
- Severity severity = b10LoggerSeverity(verbose ? isc::log::DEBUG : isc::log::INFO);
-
- // Set a directory for creating lockfiles when running tests
- // @todo: Find out why this is needed. Without this, the logger doesn't
- // work.
- setenv("B10_LOCKFILE_DIR_FROM_BUILD", TOP_BUILDDIR, 1);
-
- // Initialize logging
- initLogger(log_name, severity, isc::log::MAX_DEBUG_LEVEL, NULL);
-
- // Now configure logger output to stdout.
- /// @todo: Make this configurable as part of #3427.
- LoggerSpecification spec(log_name, severity,
- b10LoggerDbglevel(isc::log::MAX_DEBUG_LEVEL));
- OutputOption option;
- option.destination = OutputOption::DEST_CONSOLE;
- option.stream = OutputOption::STR_STDOUT;
-
- spec.addOutputOption(option);
- LoggerManager manager;
- manager.process(spec);
+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();
}
};
int ret = EXIT_SUCCESS;
- bool status = true;
try {
// Initialize logging. If verbose, we'll use maximum verbosity.
// If standalone is enabled, do not buffer initial log messages
try {
// Initialize the server, i.e. establish control session
// if BIND10 backend is used or read a configuration file
- //
- status = server.init(config_file);
+ server.init(config_file);
+
} catch (const std::exception& ex) {
LOG_ERROR(dhcp6_logger, DHCP6_INIT_FAIL).arg(ex.what());
} else {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_STANDALONE);
}
- if (!status) {
- isc_throw(isc::Unexpected, "Failed to initialize configuration backend.");
- }
server.run();
LOG_INFO(dhcp6_logger, DHCP6_SHUTDOWN);
endif
if CONFIG_BACKEND_JSON
-dhcp6_unittests_SOURCES += ../jsonfile_controller.cc
-dhcp6_unittests_SOURCES += jsonfile_controller_unittest.cc
+dhcp6_unittests_SOURCES += ../kea_controller.cc
+dhcp6_unittests_SOURCES += kea_controller_unittest.cc
endif
nodist_dhcp6_unittests_SOURCES = ../dhcp6_messages.h ../dhcp6_messages.cc
);
// And configure it using the config file.
- EXPECT_TRUE(srv->init(TEST_FILE));
+ EXPECT_NO_THROW(srv->init(TEST_FILE));
// Now check if the configuration has been applied correctly.
const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6();
);
// And configure it using config without
- EXPECT_TRUE(srv->init(TEST_FILE));
+ EXPECT_NO_THROW(srv->init(TEST_FILE));
// Now check if the configuration has been applied correctly.
const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6();
EXPECT_EQ(Lease::TYPE_NA, pools1.at(0)->getType());
}
+// This test checks if configuration detects failure when trying:
+// - empty file
+// - empty filename
+// - no Dhcp6 element
+// - Config file that contains Dhcp6 but has a content error
+TEST_F(JSONFileBackendTest, configBroken) {
+
+ // Empty config is not allowed, because Dhcp6 element is missing
+ string config_empty = "";
+
+ // This config does not have mandatory Dhcp6 element
+ string config_v4 = "{ \"Dhcp4\": { \"interfaces\": [ \"*\" ],"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet4\": [ { "
+ " \"pool\": [ \"192.0.2.0/24\" ],"
+ " \"subnet\": \"192.0.2.0/24\" "
+ " } ]}";
+
+ // This has Dhcp6 element, but it's utter nonsense
+ string config_nonsense = "{ \"Dhcp6\": { \"reviews\": \"are so much fun\" } }";
+
+ // Now initialize the server
+ boost::scoped_ptr<ControlledDhcpv6Srv> srv;
+ ASSERT_NO_THROW(
+ srv.reset(new ControlledDhcpv6Srv(0))
+ );
+
+ // Try to configure without filename. Should fail.
+ EXPECT_THROW(srv->init(""), BadValue);
+
+ // Try to configure it using empty file. Should fail.
+ writeFile(TEST_FILE, config_empty);
+ EXPECT_THROW(srv->init(TEST_FILE), BadValue);
+
+ // Now try to load a config that does not have Dhcp6 component.
+ writeFile(TEST_FILE, config_v4);
+ EXPECT_THROW(srv->init(TEST_FILE), BadValue);
+
+ // Now try to load a config with Dhcp6 full of nonsense.
+ writeFile(TEST_FILE, config_nonsense);
+ EXPECT_THROW(srv->init(TEST_FILE), BadValue);
+}
+
} // End of anonymous namespace
Daemon::Daemon() {
}
-bool Daemon::init(const std::string&) {
+void Daemon::init(const std::string&) {
return false;
}
/// likely that the D2 will be started, it will analyze its config file,
/// decide that it is not needed and will shut down.
///
- /// @return true if initialization was successful, false if it was not
- virtual bool init(const std::string& config_file);
+ /// @note this method may throw
+ virtual void init(const std::string& config_file);
/// @brief Performs final deconfiguration.
///