Commit 5e4ab450 authored by Marcin Siodelski's avatar Marcin Siodelski

[3974] Implemented configuration parser for lease expiration config.

parent 878bae10
...@@ -132,6 +132,8 @@ libkea_dhcpsrv_la_SOURCES += parsers/dbaccess_parser.cc ...@@ -132,6 +132,8 @@ libkea_dhcpsrv_la_SOURCES += parsers/dbaccess_parser.cc
libkea_dhcpsrv_la_SOURCES += parsers/dbaccess_parser.h libkea_dhcpsrv_la_SOURCES += parsers/dbaccess_parser.h
libkea_dhcpsrv_la_SOURCES += parsers/dhcp_parsers.cc libkea_dhcpsrv_la_SOURCES += parsers/dhcp_parsers.cc
libkea_dhcpsrv_la_SOURCES += parsers/dhcp_parsers.h libkea_dhcpsrv_la_SOURCES += parsers/dhcp_parsers.h
libkea_dhcpsrv_la_SOURCES += parsers/expiration_config_parser.cc
libkea_dhcpsrv_la_SOURCES += parsers/expiration_config_parser.h
libkea_dhcpsrv_la_SOURCES += parsers/host_reservation_parser.cc libkea_dhcpsrv_la_SOURCES += parsers/host_reservation_parser.cc
libkea_dhcpsrv_la_SOURCES += parsers/host_reservation_parser.h libkea_dhcpsrv_la_SOURCES += parsers/host_reservation_parser.h
libkea_dhcpsrv_la_SOURCES += parsers/host_reservations_list_parser.h libkea_dhcpsrv_la_SOURCES += parsers/host_reservations_list_parser.h
......
// Copyright (C) 2015 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 <cc/data.h>
#include <dhcpsrv/cfg_expiration.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/parsers/expiration_config_parser.h>
#include <boost/foreach.hpp>
using namespace isc::data;
namespace isc {
namespace dhcp {
ExpirationConfigParser::ExpirationConfigParser()
: DhcpConfigParser() {
}
void
ExpirationConfigParser::build(ConstElementPtr expiration_config) {
CfgExpirationPtr cfg = CfgMgr::instance().getStagingCfg()->getCfgExpiration();
BOOST_FOREACH(ConfigPair config_element, expiration_config->mapValue()) {
// Get parameter name and value.
std::string param_name = config_element.first;
ConstElementPtr param_value = config_element.second;
try {
// Set configuration parameters.
if (param_name == "reclaim-timer-wait-time") {
cfg->setReclaimTimerWaitTime(param_value->intValue());
} else if (param_name == "flush-reclaimed-timer-wait-time") {
cfg->setFlushReclaimedTimerWaitTime(param_value->intValue());
} else if (param_name == "hold-reclaimed-time") {
cfg->setHoldReclaimedTime(param_value->intValue());
} else if (param_name == "max-reclaim-leases") {
cfg->setMaxReclaimLeases(param_value->intValue());
} else if (param_name == "max-reclaim-time") {
cfg->setMaxReclaimTime(param_value->intValue());
} else if (param_name == "unwarned-reclaim-cycles") {
cfg->setUnwarnedReclaimCycles(param_value->intValue());
} else {
isc_throw(DhcpConfigError, "unsupported parameter '"
<< param_name << "'");
}
} catch (const std::exception& ex) {
// Append position of the configuration parameter to the error
// message.
isc_throw(DhcpConfigError, ex.what() << " ("
<< param_value->getPosition() << ")");
}
}
}
void
ExpirationConfigParser::commit() {
// Nothing to do.
}
} // end of namespace isc::dhcp
} // end of namespace isc
// Copyright (C) 2015 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.
#ifndef EXPIRATION_CONFIG_PARSER_H
#define EXPIRATION_CONFIG_PARSER_H
#include <dhcpsrv/parsers/dhcp_config_parser.h>
namespace isc {
namespace dhcp {
/// @brief Parser for the configuration parameters pertaining to the
/// processing of expired leases.
///
/// This parser iterates over parameters stored in the map and tries to
/// set the appropriate values in the @c CfgExpiration object of the
/// Configuration Manager.
///
/// Currently supported parameters are:
/// - reclaim-timer-wait-time,
/// - flush-reclaimed-timer-wait-time,
/// - hold-reclaimed-time,
/// - max-reclaim-leases,
/// - max-reclaim-time,
/// - unwarned-reclaim-cycles.
///
/// These parameters are optional and the default values are used for
/// those that aren't specified.
///
/// The parser checks if the values of the specified parameters are within
/// the allowed ranges and throws exception if they are. Each parameter
/// has a corresponding maximum value defined in the @c CfgExpiration class.
/// None of them may be negative.
class ExpirationConfigParser : public DhcpConfigParser {
public:
/// @brief Constructor
ExpirationConfigParser();
/// @brief Parses parameters in the JSON map, pertaining to the processing
/// of the expired leases.
///
/// @param value pointer to the content of parsed values
///
/// @throw DhcpConfigError if unknown parameter specified or the
/// parameter contains invalid value..
virtual void build(isc::data::ConstElementPtr value);
/// @brief Does nothing.
virtual void commit();
};
} // end of namespace isc::dhcp
} // end of namespace isc
#endif // EXPIRATION_CONFIG_PARSER_H
...@@ -81,6 +81,7 @@ libdhcpsrv_unittests_SOURCES += d2_client_unittest.cc ...@@ -81,6 +81,7 @@ libdhcpsrv_unittests_SOURCES += d2_client_unittest.cc
libdhcpsrv_unittests_SOURCES += d2_udp_unittest.cc libdhcpsrv_unittests_SOURCES += d2_udp_unittest.cc
libdhcpsrv_unittests_SOURCES += daemon_unittest.cc libdhcpsrv_unittests_SOURCES += daemon_unittest.cc
libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc
libdhcpsrv_unittests_SOURCES += expiration_config_parser_unittest.cc
libdhcpsrv_unittests_SOURCES += host_mgr_unittest.cc libdhcpsrv_unittests_SOURCES += host_mgr_unittest.cc
libdhcpsrv_unittests_SOURCES += host_unittest.cc libdhcpsrv_unittests_SOURCES += host_unittest.cc
libdhcpsrv_unittests_SOURCES += host_reservation_parser_unittest.cc libdhcpsrv_unittests_SOURCES += host_reservation_parser_unittest.cc
......
// Copyright (C) 2015 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 <config.h>
#include <cc/data.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/cfg_expiration.h>
#include <dhcpsrv/parsers/expiration_config_parser.h>
#include <gtest/gtest.h>
#include <sstream>
#include <stdint.h>
#include <string>
using namespace isc::data;
using namespace isc::dhcp;
namespace {
/// @brief Test fixture class for @c ExpirationConfigParser.
class ExpirationConfigParserTest : public ::testing::Test {
protected:
/// @brief Setup for each test.
///
/// Clears the configuration in the @c CfgMgr.
virtual void SetUp();
/// @brief Cleans up after each test.
///
/// Clears the configuration in the @c CfgMgr.
virtual void TearDown();
/// @brief Include a specified parameter in the configuration.
///
/// If the specified parameter already exists, its value is replaced.
///
/// @param param_name Parameter name.
/// @param value Parameter value.
void addParam(const std::string& param_name, const int64_t value);
/// @brief Creates configuration and parses it with the parser under test.
///
/// This method creates the JSON configuration form the parameters
/// specified using the @c ExpirationConfigParserTest::addParam method.
/// It then uses the parser to parse this configuration. Any exceptions
/// emitted by the parser are propagated to the caller (they aren't
/// caught by this method).
///
/// @return Pointer to the parsed configuration.
CfgExpirationPtr renderConfig() const;
/// @brief Tests that the out of range parameter value is not accepted.
///
/// This test checks that the negative value and the value which is
/// greater than the maximum for the given parameter is not accepted.
///
/// @param param Parameter name.
/// @param max_value Maximum value allowed for the parameter.
void testOutOfRange(const std::string& param, const uint64_t max_value);
private:
/// @brief Holds configuration parameters specified for a test.
std::map<std::string, int64_t> config_params_;
};
void
ExpirationConfigParserTest::SetUp() {
CfgMgr::instance().clear();
}
void
ExpirationConfigParserTest::TearDown() {
CfgMgr::instance().clear();
}
void
ExpirationConfigParserTest::addParam(const std::string& param_name,
const int64_t value) {
config_params_[param_name] = value;
}
CfgExpirationPtr
ExpirationConfigParserTest::renderConfig() const {
std::ostringstream s;
// Create JSON configuration from the parameters in the map.
s << "{";
for (std::map<std::string, int64_t>::const_iterator param =
config_params_.begin(); param != config_params_.end();
++param) {
// Include comma sign if we're at the subsequent parameter.
if (std::distance(config_params_.begin(), param) > 0) {
s << ",";
}
s << "\"" << param->first << "\": " << param->second;
}
s << "}";
ElementPtr config_element = Element::fromJSON(s.str());
// Parse the configuration. This may emit exceptions.
ExpirationConfigParser parser;
parser.build(config_element);
// No exception so return configuration.
return (CfgMgr::instance().getStagingCfg()->getCfgExpiration());
}
void
ExpirationConfigParserTest::testOutOfRange(const std::string& param,
const uint64_t max_value) {
// Remove any existing parameters which would influence the
// behavior of the test.
config_params_.clear();
// Negative value is not allowed.
addParam(param, -3);
EXPECT_THROW(renderConfig(), DhcpConfigError)
<< "test for negative value of '" << param << "' failed";
// Value greater than maximum is not allowed.
addParam(param, max_value + 1);
EXPECT_THROW(renderConfig(), DhcpConfigError)
<< "test for out of range value of '" << param << "' failed";
// Value in range should be accepted.
addParam(param, max_value);
EXPECT_NO_THROW(renderConfig())
<< "test for in range value of '" << param << "' failed";
}
// This test verifies that all parameters for the expiration may be configured.
TEST_F(ExpirationConfigParserTest, allParameters) {
// Create configuration which overrides default values of all parameters.
addParam("reclaim-timer-wait-time", 20);
addParam("flush-reclaimed-timer-wait-time", 35);
addParam("hold-reclaimed-time", 1800);
addParam("max-reclaim-leases", 50);
addParam("max-reclaim-time", 100);
addParam("unwarned-reclaim-cycles", 10);
CfgExpirationPtr cfg;
ASSERT_NO_THROW(cfg = renderConfig());
EXPECT_EQ(20, cfg->getReclaimTimerWaitTime());
EXPECT_EQ(35, cfg->getFlushReclaimedTimerWaitTime());
EXPECT_EQ(1800, cfg->getHoldReclaimedTime());
EXPECT_EQ(50, cfg->getMaxReclaimLeases());
EXPECT_EQ(100, cfg->getMaxReclaimTime());
EXPECT_EQ(10, cfg->getUnwarnedReclaimCycles());
}
// This test verifies that default values are used if no parameter is
// specified.
TEST_F(ExpirationConfigParserTest, noParameters) {
CfgExpirationPtr cfg;
ASSERT_NO_THROW(cfg = renderConfig());
EXPECT_EQ(CfgExpiration::DEFAULT_RECLAIM_TIMER_WAIT_TIME,
cfg->getReclaimTimerWaitTime());
EXPECT_EQ(CfgExpiration::DEFAULT_FLUSH_RECLAIMED_TIMER_WAIT_TIME,
cfg->getFlushReclaimedTimerWaitTime());
EXPECT_EQ(CfgExpiration::DEFAULT_HOLD_RECLAIMED_TIME,
cfg->getHoldReclaimedTime());
EXPECT_EQ(CfgExpiration::DEFAULT_MAX_RECLAIM_LEASES,
cfg->getMaxReclaimLeases());
EXPECT_EQ(CfgExpiration::DEFAULT_MAX_RECLAIM_TIME,
cfg->getMaxReclaimTime());
EXPECT_EQ(CfgExpiration::DEFAULT_UNWARNED_RECLAIM_CYCLES,
cfg->getUnwarnedReclaimCycles());
}
// This test verifies that a subset of parameters may be specified and
// that default values are used for those that aren't specified.
TEST_F(ExpirationConfigParserTest, someParameters) {
addParam("reclaim-timer-wait-time", 15);
addParam("hold-reclaimed-time", 2000);
addParam("max-reclaim-time", 200);
CfgExpirationPtr cfg;
ASSERT_NO_THROW(cfg = renderConfig());
EXPECT_EQ(15, cfg->getReclaimTimerWaitTime());
EXPECT_EQ(CfgExpiration::DEFAULT_FLUSH_RECLAIMED_TIMER_WAIT_TIME,
cfg->getFlushReclaimedTimerWaitTime());
EXPECT_EQ(2000, cfg->getHoldReclaimedTime());
EXPECT_EQ(CfgExpiration::DEFAULT_MAX_RECLAIM_LEASES,
cfg->getMaxReclaimLeases());
EXPECT_EQ(200, cfg->getMaxReclaimTime());
EXPECT_EQ(CfgExpiration::DEFAULT_UNWARNED_RECLAIM_CYCLES,
cfg->getUnwarnedReclaimCycles());
}
// This test verifies that another subset of parameters may be specified
// and that default values are used for those that aren't specified.
TEST_F(ExpirationConfigParserTest, otherParameters) {
addParam("flush-reclaimed-timer-wait-time", 50);
addParam("max-reclaim-leases", 60);
addParam("unwarned-reclaim-cycles", 20);
CfgExpirationPtr cfg;
ASSERT_NO_THROW(cfg = renderConfig());
EXPECT_EQ(CfgExpiration::DEFAULT_RECLAIM_TIMER_WAIT_TIME,
cfg->getReclaimTimerWaitTime());
EXPECT_EQ(50, cfg->getFlushReclaimedTimerWaitTime());
EXPECT_EQ(CfgExpiration::DEFAULT_HOLD_RECLAIMED_TIME,
cfg->getHoldReclaimedTime());
EXPECT_EQ(60, cfg->getMaxReclaimLeases());
EXPECT_EQ(CfgExpiration::DEFAULT_MAX_RECLAIM_TIME,
cfg->getMaxReclaimTime());
EXPECT_EQ(20, cfg->getUnwarnedReclaimCycles());
}
// This test verifies that the exception is thrown if unsupported
// parameter is specified.
TEST_F(ExpirationConfigParserTest, invalidParameter) {
addParam("reclaim-timer-wait-time", 20);
addParam("invalid-parameter", 20);
EXPECT_THROW(renderConfig(), DhcpConfigError);
}
// This test verifies that negative parameter values are not allowed.
TEST_F(ExpirationConfigParserTest, outOfRangeValues) {
testOutOfRange("reclaim-timer-wait-time",
CfgExpiration::LIMIT_RECLAIM_TIMER_WAIT_TIME);
testOutOfRange("flush-reclaimed-timer-wait-time",
CfgExpiration::LIMIT_FLUSH_RECLAIMED_TIMER_WAIT_TIME);
testOutOfRange("hold-reclaimed-time",
CfgExpiration::LIMIT_HOLD_RECLAIMED_TIME);
testOutOfRange("max-reclaim-leases",
CfgExpiration::LIMIT_MAX_RECLAIM_LEASES);
testOutOfRange("max-reclaim-time",
CfgExpiration::LIMIT_MAX_RECLAIM_TIME);
testOutOfRange("unwarned-reclaim-cycles",
CfgExpiration::LIMIT_UNWARNED_RECLAIM_CYCLES);
}
// This test verifies that it is not allowed to specify a value as
// a text.
TEST_F(ExpirationConfigParserTest, notNumberValue) {
// The value should not be in quotes.
std::string config = "{ \"reclaim-timer-wait-time\": \"10\" }";
ElementPtr config_element = Element::fromJSON(config);
// Parse the configuration. It should throw exception.
ExpirationConfigParser parser;
EXPECT_THROW(parser.build(config_element), DhcpConfigError);
}
} // end of anonymous namespace
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment