Commit 41fa47c5 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[2318] Basic configuration parsers for option data added.

parent c4690c43
......@@ -445,6 +445,116 @@ protected:
PoolStorage* pools_;
};
class OptionDataParser : public DhcpConfigParser {
public:
OptionDataParser(const std::string&) {
}
void build(ConstElementPtr option_value) {
BOOST_FOREACH(ConfigPair param, option_value->mapValue()) {
ParserPtr parser;
if (param.first == "name") {
boost::shared_ptr<StringParser>
name_parser(dynamic_cast<StringParser*>(StringParser::Factory(param.first)));
if (name_parser) {
name_parser->setStorage(&string_values_);
parser = name_parser;
}
// @todo: what if this is NULL pointer. Shouldn't we throw exception?
} else if (param.first == "code") {
boost::shared_ptr<Uint32Parser>
code_parser(dynamic_cast<Uint32Parser*>(Uint32Parser::Factory(param.first)));
if (code_parser) {
code_parser->setStorage(&uint32_values_);
parser = code_parser;
}
} else if (param.first == "data") {
boost::shared_ptr<StringParser>
value_parser(dynamic_cast<StringParser*>(StringParser::Factory(param.first)));
if (value_parser) {
value_parser->setStorage(&string_values_);
parser = value_parser;
}
} else {
isc_throw(NotImplemented,
"Parser error: option-data parameter not supported: "
<< param.first);
}
parser->build(param.second);
parsers_.push_back(parser);
}
}
void commit() {
}
private:
Uint32Storage uint32_values_;
StringStorage string_values_;
ParserCollection parsers_;
};
class OptionDataListParser : public DhcpConfigParser {
public:
/// @brief parses contents of the list
///
/// Iterates over all entries on the list and creates Subnet6ConfigParser
/// for each entry.
///
/// @param subnets_list pointer to a list of IPv6 subnets
OptionDataListParser(const std::string&) {
}
/// @brief parses contents of the list
///
/// Iterates over all entries on the list and creates Subnet6ConfigParser
/// for each entry.
///
/// @param subnets_list pointer to a list of IPv6 subnets
void build(ConstElementPtr option_value_list) {
// No need to define FactoryMap here. There's only one type
// used: Subnet6ConfigParser
BOOST_FOREACH(ConstElementPtr option_value, option_value_list->listValue()) {
ParserPtr parser(new OptionDataParser("option-data"));
parser->build(option_value);
option_values_.push_back(parser);
}
}
/// @brief commits subnets definitions.
///
/// Iterates over all Subnet6 parsers. Each parser contains definitions
/// of a single subnet and its parameters and commits each subnet separately.
void commit() {
// @todo: Implement more subtle reconfiguration than toss
// the old one and replace with the new one.
// remove old subnets
// CfgMgr::instance().deleteSubnets6();
BOOST_FOREACH(ParserPtr option_value, option_values_) {
option_value->commit();
}
}
/// @brief Returns Subnet6ListConfigParser object
/// @param param_name name of the parameter
/// @return Subnets6ListConfigParser object
static DhcpConfigParser* Factory(const std::string& param_name) {
return (new OptionDataListParser(param_name));
}
ParserCollection option_values_;
};
/// @brief this class parses a single subnet
///
/// This class parses the whole subnet definition. It creates parsers
......@@ -485,6 +595,9 @@ public:
boost::dynamic_pointer_cast<PoolParser>(parser);
if (poolParser) {
poolParser->setStorage(&pools_);
} else {
boost::shared_ptr<OptionDataParser> option_data_parser =
boost::dynamic_pointer_cast<OptionDataParser>(parser);
}
}
}
......@@ -569,6 +682,10 @@ protected:
factories.insert(pair<string, ParserFactory*>(
"pool", PoolParser::Factory));
factories.insert(pair<string, ParserFactory*>(
"option-data", OptionDataListParser::Factory));
FactoryMap::iterator f = factories.find(config_id);
if (f == factories.end()) {
// Used for debugging only.
......
......@@ -92,10 +92,37 @@
"item_optional": false,
"item_default": ""
}
}
]
}
}
},
{ "item_name": "option-data",
"item_type": "list",
"item_optional": false,
"item_default": [],
"list_item_spec":
{
"item_name": "single-option-data",
"item_type": "map",
"item_optional": false,
"item_default": {},
"map_item_spec": [
{ "item_name": "name",
"item_type": "string",
"item_optional": false,
"item_default": ""
},
{ "item_name": "code",
"item_type": "integer",
"item_optional": false,
"item_default": 0
},
{ "item_name": "data",
"item_type": "string",
"item_optional": false,
"item_default": ""
} ]
},
} ]
}
}
],
"commands": [
{
......
......@@ -240,4 +240,28 @@ TEST_F(Dhcp6ParserTest, pool_prefix_len) {
EXPECT_EQ(4000, subnet->getValid());
}
TEST_F(Dhcp6ParserTest, globalOptionValues) {
ConstElementPtr x;
string config = "{ \"interface\": [ \"all\" ],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
" \"pool\": [ \"2001:db8:1::/80\" ],"
" \"subnet\": \"2001:db8:1::/64\", "
" \"option-value\": [ { "
" \"name\": \"option_foo\","
" \"code\": 100,"
" \"data\": \"XYZ, 1, 5\" } ]"
" } ],"
"\"valid-lifetime\": 4000 }";
cout << config << endl;
ElementPtr json = Element::fromJSON(config);
EXPECT_NO_THROW(x = configureDhcp6Server(*srv_, json));
ASSERT_TRUE(x);
}
};
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