Commit 3bad9970 authored by Francis Dupont's avatar Francis Dupont
Browse files

[5351] Checkpoint: todo servers, doc, host DB -- adding control-socket

parent 15158895
......@@ -589,6 +589,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
case isc::dhcp::Parser4Context::OPTION_DATA:
case isc::dhcp::Parser4Context::RESERVATIONS:
case isc::dhcp::Parser4Context::CLIENT_CLASSES:
case isc::dhcp::Parser4Context::CONTROL_SOCKET:
case isc::dhcp::Parser4Context::LOGGERS:
case isc::dhcp::Parser4Context::DHCP_DDNS:
return isc::dhcp::Dhcp4Parser::make_USER_CONTEXT(driver.loc_);
......@@ -610,6 +611,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
case isc::dhcp::Parser4Context::OPTION_DATA:
case isc::dhcp::Parser4Context::RESERVATIONS:
case isc::dhcp::Parser4Context::CLIENT_CLASSES:
case isc::dhcp::Parser4Context::CONTROL_SOCKET:
case isc::dhcp::Parser4Context::LOGGERS:
case isc::dhcp::Parser4Context::DHCP_DDNS:
return isc::dhcp::Dhcp4Parser::make_COMMENT(driver.loc_);
......
......@@ -1633,6 +1633,9 @@ control_socket_params: control_socket_param
control_socket_param: control_socket_type
| control_socket_name
| user_context
| comment
| unknown_map_entry
;
control_socket_type: SOCKET_TYPE {
......
......@@ -253,7 +253,7 @@ void configureCommandChannel() {
// If the previous or new socket configuration doesn't exist or
// the new configuration differs from the old configuration we
// close the existing socket and open a new socket as appropriate.
// Note that closing an existing socket means the clien will not
// Note that closing an existing socket means the client will not
// receive the configuration result.
if (!sock_cfg || !current_sock_cfg || sock_changed) {
// Close the existing socket (if any).
......
......@@ -818,6 +818,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
case isc::dhcp::Parser6Context::OPTION_DATA:
case isc::dhcp::Parser6Context::CLIENT_CLASSES:
case isc::dhcp::Parser6Context::SERVER_ID:
case isc::dhcp::Parser6Context::CONTROL_SOCKET:
case isc::dhcp::Parser6Context::POOLS:
case isc::dhcp::Parser6Context::PD_POOLS:
case isc::dhcp::Parser6Context::RESERVATIONS:
......@@ -841,6 +842,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
case isc::dhcp::Parser6Context::OPTION_DATA:
case isc::dhcp::Parser6Context::CLIENT_CLASSES:
case isc::dhcp::Parser6Context::SERVER_ID:
case isc::dhcp::Parser6Context::CONTROL_SOCKET:
case isc::dhcp::Parser6Context::POOLS:
case isc::dhcp::Parser6Context::PD_POOLS:
case isc::dhcp::Parser6Context::RESERVATIONS:
......
......@@ -1716,6 +1716,9 @@ control_socket_params: control_socket_param
control_socket_param: socket_type
| socket_name
| user_context
| comment
| unknown_map_entry
;
socket_type: SOCKET_TYPE {
......
......@@ -350,7 +350,7 @@ void configureCommandChannel() {
// If the previous or new socket configuration doesn't exist or
// the new configuration differs from the old configuration we
// close the existing socket and open a new socket as appropriate.
// Note that closing an existing socket means the clien will not
// Note that closing an existing socket means the client will not
// receive the configuration result.
if (!sock_cfg || !current_sock_cfg || sock_changed) {
// Close the existing socket (if any).
......
......@@ -468,6 +468,8 @@ ElementPtr
Host::toElement6() const {
// Prepare the map
ElementPtr map = Element::createMap();
// Set the user context
contextToElement(map);
// Set the identifier
Host::IdentifierType id_type = getIdentifierType();
if (id_type == Host::IDENT_HWADDR) {
......
......@@ -54,6 +54,7 @@ getSupportedParams4(const bool identifiers_only = false) {
params_set.insert("server-hostname");
params_set.insert("boot-file-name");
params_set.insert("client-classes");
params_set.insert("user-context");
}
return (identifiers_only ? identifiers_set : params_set);
}
......@@ -87,6 +88,7 @@ getSupportedParams6(const bool identifiers_only = false) {
params_set.insert("prefixes");
params_set.insert("option-data");
params_set.insert("client-classes");
params_set.insert("user-context");
}
return (identifiers_only ? identifiers_set : params_set);
}
......@@ -108,6 +110,7 @@ HostReservationParser::parseInternal(const SubnetID&,
std::string identifier;
std::string identifier_name;
std::string hostname;
ConstElementPtr user_context;
HostPtr host;
try {
......@@ -131,7 +134,8 @@ HostReservationParser::parseInternal(const SubnetID&,
} else if (element.first == "hostname") {
hostname = element.second->stringValue();
} else if (element.first == "user-context") {
user_context = element.second;
}
}
......@@ -157,6 +161,10 @@ HostReservationParser::parseInternal(const SubnetID&,
host.reset(new Host(identifier, identifier_name, SubnetID(0),
SubnetID(0), IOAddress("0.0.0.0"), hostname));
// Add user context
if (user_context) {
host->setContext(user_context);
}
} catch (const std::exception& ex) {
// Append line number where the error occurred.
isc_throw(DhcpConfigError, ex.what() << " ("
......
......@@ -18,6 +18,7 @@
using namespace isc;
using namespace isc::dhcp;
using namespace isc::asiolink;
using namespace isc::data;
namespace {
......@@ -214,6 +215,7 @@ TEST_F(HostTest, createFromHWAddrString) {
EXPECT_EQ("192.0.0.2", host->getNextServer().toText());
EXPECT_EQ("server-hostname.example.org", host->getServerHostname());
EXPECT_EQ("bootfile.efi", host->getBootFileName());
EXPECT_FALSE(host->getContext());
// Use invalid identifier name
EXPECT_THROW(Host("01:02:03:04:05:06", "bogus", SubnetID(1), SubnetID(2),
......@@ -248,6 +250,7 @@ TEST_F(HostTest, createFromDUIDString) {
EXPECT_EQ(20, host->getIPv6SubnetID());
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
EXPECT_EQ("me.example.org", host->getHostname());
EXPECT_FALSE(host->getContext());
// Use invalid DUID.
EXPECT_THROW(Host("bogus", "duid", SubnetID(1), SubnetID(2),
......@@ -294,6 +297,7 @@ TEST_F(HostTest, createFromHWAddrBinary) {
EXPECT_EQ("192.0.0.2", host->getNextServer().toText());
EXPECT_EQ("server-hostname.example.org", host->getServerHostname());
EXPECT_EQ("bootfile.efi", host->getBootFileName());
EXPECT_FALSE(host->getContext());
}
// This test verifies that it is possible to create a Host object using
......@@ -322,6 +326,7 @@ TEST_F(HostTest, createFromDuidBinary) {
EXPECT_EQ(20, host->getIPv6SubnetID());
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
EXPECT_EQ("me.example.org", host->getHostname());
EXPECT_FALSE(host->getContext());
}
// This test verifies that it is possible create Host instance using all
......@@ -350,6 +355,7 @@ TEST_F(HostTest, createFromIdentifierBinary) {
EXPECT_EQ(20, host->getIPv6SubnetID());
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
EXPECT_EQ("me.example.org", host->getHostname());
EXPECT_FALSE(host->getContext());
}
}
......@@ -395,6 +401,7 @@ TEST_F(HostTest, createFromIdentifierHex) {
EXPECT_EQ(20, host->getIPv6SubnetID());
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
EXPECT_EQ("me.example.org", host->getHostname());
EXPECT_FALSE(host->getContext());
}
}
......@@ -439,6 +446,7 @@ TEST_F(HostTest, createFromIdentifierString) {
EXPECT_EQ(20, host->getIPv6SubnetID());
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
EXPECT_EQ("me.example.org", host->getHostname());
EXPECT_FALSE(host->getContext());
}
}
......@@ -493,6 +501,7 @@ TEST_F(HostTest, setIdentifierHex) {
EXPECT_EQ(20, host->getIPv6SubnetID());
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
EXPECT_EQ("me.example.org", host->getHostname());
EXPECT_FALSE(host->getContext());
// Now use another identifier.
type = static_cast<Host::IdentifierType>(i);
......@@ -525,6 +534,7 @@ TEST_F(HostTest, setIdentifierHex) {
EXPECT_EQ(20, host->getIPv6SubnetID());
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
EXPECT_EQ("me.example.org", host->getHostname());
EXPECT_FALSE(host->getContext());
}
}
......@@ -563,6 +573,7 @@ TEST_F(HostTest, setIdentifierBinary) {
EXPECT_EQ(20, host->getIPv6SubnetID());
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
EXPECT_EQ("me.example.org", host->getHostname());
EXPECT_FALSE(host->getContext());
type = static_cast<Host::IdentifierType>(i);
// Create identifier of variable length and fill with random values.
......@@ -582,6 +593,7 @@ TEST_F(HostTest, setIdentifierBinary) {
EXPECT_EQ(20, host->getIPv6SubnetID());
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
EXPECT_EQ("me.example.org", host->getHostname());
EXPECT_FALSE(host->getContext());
}
}
......@@ -656,6 +668,7 @@ TEST_F(HostTest, setValues) {
ASSERT_EQ(2, host->getIPv6SubnetID());
ASSERT_EQ("192.0.2.3", host->getIPv4Reservation().toText());
ASSERT_EQ("some-host.example.org", host->getHostname());
ASSERT_FALSE(host->getContext());
host->setIPv4SubnetID(SubnetID(123));
host->setIPv6SubnetID(SubnetID(234));
......@@ -664,6 +677,8 @@ TEST_F(HostTest, setValues) {
host->setNextServer(IOAddress("192.0.2.2"));
host->setServerHostname("server-hostname.example.org");
host->setBootFileName("bootfile.efi");
std::string user_context = "{ \"foo\": \"bar\" }";
host->setContext(Element::fromJSON(user_context));
EXPECT_EQ(123, host->getIPv4SubnetID());
EXPECT_EQ(234, host->getIPv6SubnetID());
......@@ -672,6 +687,8 @@ TEST_F(HostTest, setValues) {
EXPECT_EQ("192.0.2.2", host->getNextServer().toText());
EXPECT_EQ("server-hostname.example.org", host->getServerHostname());
EXPECT_EQ("bootfile.efi", host->getBootFileName());
ASSERT_TRUE(host->getContext());
EXPECT_EQ(user_context, host->getContext()->str());
// Remove IPv4 reservation.
host->removeIPv4Reservation();
......@@ -943,6 +960,10 @@ TEST_F(HostTest, toText) {
IOAddress("2001:db8:1::1")));
);
// Add invisble user context
std::string user_context = "{ \"foo\": \"bar\" }";
host->setContext(Element::fromJSON(user_context));
// Make sure that the output is correct,
EXPECT_EQ("hwaddr=010203040506 ipv4_subnet_id=1 ipv6_subnet_id=2"
" hostname=myhost.example.com"
......@@ -1010,6 +1031,165 @@ TEST_F(HostTest, toText) {
host->toText());
}
// This test checks that Host object is correctly unparsed,
TEST_F(HostTest, unparse) {
boost::scoped_ptr<Host> host;
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
SubnetID(1), SubnetID(2),
IOAddress("192.0.2.3"),
"myhost.example.com")));
// Add 4 reservations: 2 for NAs, 2 for PDs.
ASSERT_NO_THROW(
host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
IOAddress("2001:db8:1::cafe")));
host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
IOAddress("2001:db8:1:1::"), 64));
host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
IOAddress("2001:db8:1:2::"), 64));
host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
IOAddress("2001:db8:1::1")));
);
// Add user context
std::string user_context = "{ \"comment\": \"a host reservation\" }";
host->setContext(Element::fromJSON(user_context));
// Make sure that the output is correct,
EXPECT_EQ("{ "
"\"boot-file-name\": \"\", "
"\"client-classes\": [ ], "
"\"comment\": \"a host reservation\", "
"\"hostname\": \"myhost.example.com\", "
"\"hw-address\": \"01:02:03:04:05:06\", "
"\"ip-address\": \"192.0.2.3\", "
"\"next-server\": \"0.0.0.0\", "
"\"option-data\": [ ], "
"\"server-hostname\": \"\" "
"}",
host->toElement4()->str());
EXPECT_EQ("{ "
"\"client-classes\": [ ], "
"\"comment\": \"a host reservation\", "
"\"hostname\": \"myhost.example.com\", "
"\"hw-address\": \"01:02:03:04:05:06\", "
"\"ip-addresses\": [ \"2001:db8:1::cafe\", \"2001:db8:1::1\" ], "
"\"option-data\": [ ], "
"\"prefixes\": [ \"2001:db8:1:1::/64\", \"2001:db8:1:2::/64\" ] "
"}",
host->toElement6()->str());
// Reset some of the data and make sure that the output is affected.
host->setHostname("");
host->removeIPv4Reservation();
host->setIPv4SubnetID(0);
EXPECT_EQ("{ "
"\"boot-file-name\": \"\", "
"\"client-classes\": [ ], "
"\"comment\": \"a host reservation\", "
"\"hostname\": \"\", "
"\"hw-address\": \"01:02:03:04:05:06\", "
"\"ip-address\": \"0.0.0.0\", "
"\"next-server\": \"0.0.0.0\", "
"\"option-data\": [ ], "
"\"server-hostname\": \"\" "
"}",
host->toElement4()->str());
EXPECT_EQ("{ "
"\"client-classes\": [ ], "
"\"comment\": \"a host reservation\", "
"\"hostname\": \"\", "
"\"hw-address\": \"01:02:03:04:05:06\", "
"\"ip-addresses\": [ \"2001:db8:1::cafe\", \"2001:db8:1::1\" ], "
"\"option-data\": [ ], "
"\"prefixes\": [ \"2001:db8:1:1::/64\", \"2001:db8:1:2::/64\" ] "
"}",
host->toElement6()->str());
// Create host identified by DUID, instead of HWADDR, with a very
// basic configuration.
ASSERT_NO_THROW(host.reset(new Host("11:12:13:14:15", "duid",
SubnetID(0), SubnetID(0),
IOAddress::IPV4_ZERO_ADDRESS(),
"myhost")));
EXPECT_EQ("{ "
"\"boot-file-name\": \"\", "
"\"client-classes\": [ ], "
"\"duid\": \"11:12:13:14:15\", "
"\"hostname\": \"myhost\", "
"\"ip-address\": \"0.0.0.0\", "
"\"next-server\": \"0.0.0.0\", "
"\"option-data\": [ ], "
"\"server-hostname\": \"\" "
"}",
host->toElement4()->str());
EXPECT_EQ("{ "
"\"client-classes\": [ ], "
"\"duid\": \"11:12:13:14:15\", "
"\"hostname\": \"myhost\", "
"\"ip-addresses\": [ ], "
"\"option-data\": [ ], "
"\"prefixes\": [ ] "
"}",
host->toElement6()->str());
// Add some classes.
host->addClientClass4("modem");
host->addClientClass4("router");
EXPECT_EQ("{ "
"\"boot-file-name\": \"\", "
"\"client-classes\": [ \"modem\", \"router\" ], "
"\"duid\": \"11:12:13:14:15\", "
"\"hostname\": \"myhost\", "
"\"ip-address\": \"0.0.0.0\", "
"\"next-server\": \"0.0.0.0\", "
"\"option-data\": [ ], "
"\"server-hostname\": \"\" "
"}",
host->toElement4()->str());
EXPECT_EQ("{ "
"\"client-classes\": [ ], "
"\"duid\": \"11:12:13:14:15\", "
"\"hostname\": \"myhost\", "
"\"ip-addresses\": [ ], "
"\"option-data\": [ ], "
"\"prefixes\": [ ] "
"}",
host->toElement6()->str());
host->addClientClass6("hub");
host->addClientClass6("device");
EXPECT_EQ("{ "
"\"boot-file-name\": \"\", "
"\"client-classes\": [ \"modem\", \"router\" ], "
"\"duid\": \"11:12:13:14:15\", "
"\"hostname\": \"myhost\", "
"\"ip-address\": \"0.0.0.0\", "
"\"next-server\": \"0.0.0.0\", "
"\"option-data\": [ ], "
"\"server-hostname\": \"\" "
"}",
host->toElement4()->str());
EXPECT_EQ("{ "
"\"client-classes\": [ \"device\", \"hub\" ], "
"\"duid\": \"11:12:13:14:15\", "
"\"hostname\": \"myhost\", "
"\"ip-addresses\": [ ], "
"\"option-data\": [ ], "
"\"prefixes\": [ ] "
"}",
host->toElement6()->str());
}
// Test verifies if the host can store HostId properly.
TEST_F(HostTest, hostId) {
boost::scoped_ptr<Host> host;
......
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