From: Marcin Siodelski Date: Mon, 15 Oct 2012 11:39:37 +0000 (+0200) Subject: [2318] Basic configuration parsers for option data added. X-Git-Tag: trac2487_base~28^2~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=41fa47c50d302aa71e9aee629c28ed9cb4fcd065;p=thirdparty%2Fkea.git [2318] Basic configuration parsers for option data added. --- diff --git a/src/bin/dhcp6/config_parser.cc b/src/bin/dhcp6/config_parser.cc index dbffc40863..b4c8ababd2 100644 --- a/src/bin/dhcp6/config_parser.cc +++ b/src/bin/dhcp6/config_parser.cc @@ -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 + name_parser(dynamic_cast(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 + code_parser(dynamic_cast(Uint32Parser::Factory(param.first))); + if (code_parser) { + code_parser->setStorage(&uint32_values_); + parser = code_parser; + } + } else if (param.first == "data") { + boost::shared_ptr + value_parser(dynamic_cast(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(parser); if (poolParser) { poolParser->setStorage(&pools_); + } else { + boost::shared_ptr option_data_parser = + boost::dynamic_pointer_cast(parser); } } } @@ -569,6 +682,10 @@ protected: factories.insert(pair( "pool", PoolParser::Factory)); + factories.insert(pair( + "option-data", OptionDataListParser::Factory)); + + FactoryMap::iterator f = factories.find(config_id); if (f == factories.end()) { // Used for debugging only. diff --git a/src/bin/dhcp6/dhcp6.spec b/src/bin/dhcp6/dhcp6.spec index f35f606213..818ea4b176 100644 --- a/src/bin/dhcp6/dhcp6.spec +++ b/src/bin/dhcp6/dhcp6.spec @@ -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": [ { diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc index 22592e8c2d..f2caff1052 100644 --- a/src/bin/dhcp6/tests/config_parser_unittest.cc +++ b/src/bin/dhcp6/tests/config_parser_unittest.cc @@ -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); +} + };