Commit 24213920 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[4765] Client classes in HR can be specified in configuration file.

parent 37a2fed8
......@@ -580,7 +580,9 @@ CfgHosts::add4(const HostPtr& host) {
host->getServerHostname().empty() &&
host->getBootFileName().empty() &&
host->getCfgOption4()->empty() &&
host->getCfgOption6()->empty()) {
host->getCfgOption6()->empty() &&
host->getClientClasses4().empty() &&
host->getClientClasses6().empty()) {
std::ostringstream s;
if (hwaddr) {
s << "for DUID: " << hwaddr->toText();
......
......@@ -347,6 +347,7 @@ Host::addClientClass4(const std::string& class_name) {
addClientClassInternal(dhcp4_client_classes_, class_name);
}
void
Host::addClientClass6(const std::string& class_name) {
addClientClassInternal(dhcp6_client_classes_, class_name);
......
......@@ -52,6 +52,7 @@ getSupportedParams4(const bool identifiers_only = false) {
params_set.insert("next-server");
params_set.insert("server-hostname");
params_set.insert("boot-file-name");
params_set.insert("client-classes");
}
return (identifiers_only ? identifiers_set : params_set);
}
......@@ -83,6 +84,7 @@ getSupportedParams6(const bool identifiers_only = false) {
params_set.insert("ip-addresses");
params_set.insert("prefixes");
params_set.insert("option-data");
params_set.insert("client-classes");
}
return (identifiers_only ? identifiers_set : params_set);
}
......@@ -102,10 +104,10 @@ HostReservationParser::build(isc::data::ConstElementPtr reservation_data) {
std::string identifier_name;
std::string hostname;
// Gather those parameters that are common for both IPv4 and IPv6
// reservations.
BOOST_FOREACH(ConfigPair element, reservation_data->mapValue()) {
try {
try {
// Gather those parameters that are common for both IPv4 and IPv6
// reservations.
BOOST_FOREACH(ConfigPair element, reservation_data->mapValue()) {
// Check if we support this parameter.
if (!isSupportedParameter(element.first)) {
isc_throw(DhcpConfigError, "unsupported configuration"
......@@ -123,15 +125,10 @@ HostReservationParser::build(isc::data::ConstElementPtr reservation_data) {
} else if (element.first == "hostname") {
hostname = element.second->stringValue();
}
} catch (const std::exception& ex) {
// Append line number where the error occurred.
isc_throw(DhcpConfigError, ex.what() << " ("
<< element.second->getPosition() << ")");
}
}
try {
// Host identifier is a must.
if (identifier_name.empty()) {
// If there is no identifier specified, we have to display an
......@@ -210,19 +207,25 @@ HostReservationParser4::build(isc::data::ConstElementPtr reservation_data) {
host_->setIPv4Reservation(IOAddress(element.second->
stringValue()));
} else if (element.first == "next-server") {
host_->setNextServer(IOAddress(element.second->stringValue()));
host_->setNextServer(IOAddress(element.second->stringValue()));
} else if (element.first == "server-hostname") {
host_->setServerHostname(element.second->stringValue());
} else if (element.first == "boot-file-name") {
host_->setBootFileName(element.second->stringValue());
} else if (element.first == "client-classes") {
BOOST_FOREACH(ConstElementPtr class_element,
element.second->listValue()) {
host_->addClientClass4(class_element->stringValue());
}
}
} catch (const std::exception& ex) {
// Append line number where the error occurred.
isc_throw(DhcpConfigError, ex.what() << " ("
<< reservation_data->getPosition() << ")");
<< element.second->getPosition() << ")");
}
}
}
......@@ -318,6 +321,19 @@ HostReservationParser6::build(isc::data::ConstElementPtr reservation_data) {
<< prefix_element->getPosition() << ")");
}
}
} else if (element.first == "client-classes") {
try {
BOOST_FOREACH(ConstElementPtr class_element,
element.second->listValue()) {
host_->addClientClass6(class_element->stringValue());
}
} catch (const std::exception& ex) {
// Append line number where the error occurred.
isc_throw(DhcpConfigError, ex.what() << " ("
<< element.second->getPosition() << ")");
}
}
}
......
......@@ -300,6 +300,29 @@ TEST_F(HostReservationParserTest, dhcp4NoHostname) {
EXPECT_TRUE(hosts[0]->getHostname().empty());
}
// This test verifies that it is possible to specify DHCPv4 client classes
// within the host reservation.
TEST_F(HostReservationParserTest, dhcp4ClientClasses) {
std::string config = "{ \"hw-address\": \"01:02:03:04:05:06\","
"\"client-classes\": [ \"foo\", \"bar\" ] }";
ElementPtr config_element = Element::fromJSON(config);
HostReservationParser4 parser(SubnetID(10));
ASSERT_NO_THROW(parser.build(config_element));
CfgHostsPtr cfg_hosts = CfgMgr::instance().getStagingCfg()->getCfgHosts();
HostCollection hosts;
ASSERT_NO_THROW(hosts = cfg_hosts->getAll(hwaddr_));
ASSERT_EQ(1, hosts.size());
const ClientClasses& classes = hosts[0]->getClientClasses4();
ASSERT_EQ(2, classes.size());
EXPECT_EQ(1, classes.count("foo"));
EXPECT_EQ(1, classes.count("bar"));
}
// This test verifies that the parser can parse reservation entry
// containing next-server, server-hostname and boot-file-name values for
// DHCPv4 message fields.
......@@ -627,6 +650,29 @@ TEST_F(HostReservationParserTest, dhcp6NoHostname) {
ASSERT_EQ(0, std::distance(prefixes.first, prefixes.second));
}
// This test verifies that it is possible to specify DHCPv4 client classes
// within the host reservation.
TEST_F(HostReservationParserTest, dhcp6ClientClasses) {
std::string config = "{ \"duid\": \"01:02:03:04:05:06:07:08:09:0A\","
"\"client-classes\": [ \"foo\", \"bar\" ] }";
ElementPtr config_element = Element::fromJSON(config);
HostReservationParser6 parser(SubnetID(10));
ASSERT_NO_THROW(parser.build(config_element));
CfgHostsPtr cfg_hosts = CfgMgr::instance().getStagingCfg()->getCfgHosts();
HostCollection hosts;
ASSERT_NO_THROW(hosts = cfg_hosts->getAll(Host::IDENT_DUID,
&duid_->getDuid()[0],
duid_->getDuid().size()));
ASSERT_EQ(1, hosts.size());
const ClientClasses& classes = hosts[0]->getClientClasses6();
ASSERT_EQ(2, classes.size());
EXPECT_EQ(1, classes.count("foo"));
EXPECT_EQ(1, classes.count("bar"));
}
// This test verifies that the configuration parser throws an exception
// when IPv4 address is specified for IPv6 reservation.
......
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