public:
/// @brief Constructor
///
- /// @param ignored first parameter
/// stores global scope parameters, options, option definitions.
- Subnet4ConfigParser(const std::string&)
+ Subnet4ConfigParser()
:SubnetConfigParser("", globalContext(), IOAddress("0.0.0.0")) {
}
/// Configuration Manager.
///
/// @param subnet A new subnet being configured.
- void build(ConstElementPtr subnet) {
+ /// @return a pointer to created Subnet4 object
+ Subnet4Ptr parse(ConstElementPtr subnet) {
/// Parse Pools first.
ConstElementPtr pools = subnet->get("pools");
if (pools) {
parser.parse(pools_, pools);
}
- SubnetConfigParser::build(subnet);
+ SubnetPtr generic = SubnetConfigParser::build(subnet);
- if (subnet_) {
- Subnet4Ptr sub4ptr = boost::dynamic_pointer_cast<Subnet4>(subnet_);
- if (!sub4ptr) {
- // If we hit this, it is a programming error.
- isc_throw(Unexpected,
- "Invalid cast in Subnet4ConfigParser::commit");
- }
-
- // Set relay information if it was parsed
- if (relay_info_) {
- sub4ptr->setRelayInfo(*relay_info_);
- }
+ Subnet4Ptr sub4ptr = boost::dynamic_pointer_cast<Subnet4>(generic);
+ if (!sub4ptr) {
+ // If we hit this, it is a programming error.
+ isc_throw(Unexpected,
+ "Invalid Subnet4 cast in Subnet4ConfigParser::parse");
+ }
- // Adding a subnet to the Configuration Manager may fail if the
- // subnet id is invalid (duplicate). Thus, we catch exceptions
- // here to append a position in the configuration string.
- try {
- CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->add(sub4ptr);
- } catch (const std::exception& ex) {
- isc_throw(DhcpConfigError, ex.what() << " ("
- << subnet->getPosition() << ")");
- }
+ // Set relay information if it was parsed
+ if (relay_info_) {
+ sub4ptr->setRelayInfo(*relay_info_);
}
// Parse Host Reservations for this subnet if any.
HostReservationsListParser<HostReservationParser4> parser;
parser.parse(subnet_->getID(), reservations);
}
- }
- /// @brief Commits subnet configuration.
- ///
- /// This function is currently no-op because subnet should already
- /// be added into the Config Manager in the build().
- void commit() { }
+ return (sub4ptr);
+ }
protected:
/// This is a wrapper parser that handles the whole list of Subnet4
/// definitions. It iterates over all entries and creates Subnet4ConfigParser
/// for each entry.
-class Subnets4ListConfigParser : public DhcpConfigParser {
+class Subnets4ListConfigParser : public isc::data::SimpleParser {
public:
- /// @brief constructor
- ///
- /// @param dummy first argument, always ignored. All parsers accept a
- /// string parameter "name" as their first argument.
- Subnets4ListConfigParser(const std::string&) {
- }
-
/// @brief parses contents of the list
///
- /// Iterates over all entries on the list and creates Subnet4ConfigParser
- /// for each entry.
+ /// Iterates over all entries on the list, parses its content
+ /// (by instantiating Subnet6ConfigParser) and adds to specified
+ /// configuration.
///
/// @param subnets_list pointer to a list of IPv4 subnets
- void build(ConstElementPtr subnets_list) {
- BOOST_FOREACH(ConstElementPtr subnet, subnets_list->listValue()) {
- ParserPtr parser(new Subnet4ConfigParser("subnet"));
- parser->build(subnet);
+ /// @return number of subnets created
+ size_t parse(SrvConfigPtr cfg, ConstElementPtr subnets_list) {
+ size_t cnt = 0;
+ BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
+
+ Subnet4ConfigParser parser;
+ Subnet4Ptr subnet = parser.parse(subnet_json);
+ if (subnet) {
+
+ // Adding a subnet to the Configuration Manager may fail if the
+ // subnet id is invalid (duplicate). Thus, we catch exceptions
+ // here to append a position in the configuration string.
+ try {
+ cfg->getCfgSubnets4()->add(subnet);
+ cnt++;
+ } catch (const std::exception& ex) {
+ isc_throw(DhcpConfigError, ex.what() << " ("
+ << subnet_json->getPosition() << ")");
+ }
+ }
}
- }
-
- /// @brief commits subnets definitions.
- ///
- /// Does nothing.
- void commit() {
- }
-
- /// @brief Returns Subnet4ListConfigParser object
- /// @param param_name name of the parameter
- /// @return Subnets4ListConfigParser object
- static DhcpConfigParser* factory(const std::string& param_name) {
- return (new Subnets4ListConfigParser(param_name));
+ return (cnt);
}
};
(config_id.compare("dhcp4o6-port") == 0) ) {
parser = new Uint32Parser(config_id,
globalContext()->uint32_values_);
- } else if (config_id.compare("subnet4") == 0) {
- parser = new Subnets4ListConfigParser(config_id);
+ // subnet4 has been migrated to SimpleParser already.
// interface-config has been migrated to SimpleParser already.
// option-data and option-def have been converted to SimpleParser already.
} else if ((config_id.compare("next-server") == 0)) {
// then: option-data parser, subnet4 parser, lease-database parser.
// Please do not change this order!
ParserCollection independent_parsers;
- ParserPtr subnet_parser;
// Some of the parsers alter the state of the system in a way that can't
// easily be undone. (Or alter it in a way such that undoing the change has
// Set all default values if not specified by the user.
SimpleParser4::setAllDefaults(mutable_cfg);
+ // And now derive (inherit) global parameters to subnets, if not specified.
+ SimpleParser4::deriveParameters(mutable_cfg);
+
// We need definitions first
ConstElementPtr option_defs = mutable_cfg->get("option-def");
if (option_defs) {
hooks_parser.verifyLibraries();
continue;
}
-
+
// Legacy DhcpConfigParser stuff below
if (config_pair.first == "dhcp-ddns") {
// Apply defaults if not in short cut
continue;
}
+ if (config_pair.first == "subnet4") {
+ SrvConfigPtr srv_cfg = CfgMgr::instance().getStagingCfg();
+ Subnets4ListConfigParser subnets_parser;
+ // parse() returns number of subnets parsed. We may log it one day.
+ subnets_parser.parse(srv_cfg, config_pair.second);
+ continue;
+ }
+
ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first,
config_pair.second));
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PARSER_CREATED)
.arg(config_pair.first);
- if (config_pair.first == "subnet4") {
- subnet_parser = parser;
- } else {
- // Those parsers should be started before other
- // parsers so we can call build straight away.
- independent_parsers.push_back(parser);
- parser->build(config_pair.second);
- // The commit operation here may modify the global storage
- // but we need it so as the subnet6 parser can access the
- // parsed data.
- parser->commit();
- }
- }
- // The subnet parser is the next one to be run.
- std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
- values_map.find("subnet4");
- if (subnet_config != values_map.end()) {
- config_pair.first = "subnet4";
- subnet_parser->build(subnet_config->second);
+ // Those parsers should be started before other
+ // parsers so we can call build straight away.
+ independent_parsers.push_back(parser);
+ parser->build(config_pair.second);
+ // The commit operation here may modify the global storage
+ // but we need it so as the subnet6 parser can access the
+ // parsed data.
+ parser->commit();
}
// Setup the command channel.
cnt += SimpleParser::setDefaults(single_option, OPTION4_DEFAULTS);
}
}
+ return (cnt);
+}
+
+size_t SimpleParser4::deriveParameters(isc::data::ElementPtr global) {
+ size_t cnt = 0;
+
+ // Now derive global parameters into subnets.
+ ConstElementPtr subnets = global->get("subnet4");
+ if (subnets) {
+ BOOST_FOREACH(ElementPtr single_subnet, subnets->listValue()) {
+ cnt += SimpleParser::deriveParams(global, single_subnet,
+ INHERIT_GLOBAL_TO_SUBNET4);
+ }
+ }
return (cnt);
}
/// @return number of default values added
static size_t setAllDefaults(isc::data::ElementPtr global);
+ /// @brief Derives (inherits) all parameters from global to more specific scopes.
+ ///
+ /// This method currently does the following:
+ /// - derives global parameters to subnets (lifetimes for now)
+ /// @param global scope to be modified if needed (subnet4 will be extracted)
+ /// @return number of default values derived
+ static size_t deriveParameters(isc::data::ElementPtr global);
+
// see simple_parser4.cc for comments for those parameters
static const isc::data::SimpleDefaults OPTION4_DEF_DEFAULTS;
static const isc::data::SimpleDefaults OPTION4_DEFAULTS;
ElementPtr global = parseJSON("{ \"renew-timer\": 1,"
" \"rebind-timer\": 2,"
" \"preferred-lifetime\": 3,"
- " \"valid-lifetime\": 4"
+ " \"valid-lifetime\": 4,"
+ " \"subnet4\": [ { \"renew-timer\": 100 } ] "
"}");
- ElementPtr subnet = parseJSON("{ \"renew-timer\": 100 }");
+ ConstElementPtr subnets = global->find("subnet4");
+ ASSERT_TRUE(subnets);
+ ConstElementPtr subnet = subnets->get(0);
+ ASSERT_TRUE(subnet);
// we should inherit 3 parameters. Renew-timer should remain intact,
// as it was already defined in the subnet scope.
size_t num;
- EXPECT_NO_THROW(num = SimpleParser4::deriveParams(global, subnet,
- SimpleParser4::INHERIT_GLOBAL_TO_SUBNET4));
+ EXPECT_NO_THROW(num = SimpleParser4::deriveParameters(global));
EXPECT_EQ(2, num);
// Check the values. 2 of them are inherited, while the third one
checkIntegerValue(subnet, "valid-lifetime", 4);
}
+
};
};
};
/// @brief Constructor
///
- /// @param ignored first parameter
/// stores global scope parameters, options, option definitions.
- Subnet6ConfigParser(const std::string&)
+ Subnet6ConfigParser()
:SubnetConfigParser("", globalContext(), IOAddress("::")) {
}
/// Configuration Manager.
///
/// @param subnet A new subnet being configured.
- void build(ConstElementPtr subnet) {
+ /// @return a pointer to created Subnet6 object
+ Subnet6Ptr parse(ConstElementPtr subnet) {
/// Parse all pools first.
ConstElementPtr pools = subnet->get("pools");
if (pools) {
parser.parse(pools_, pd_pools);
}
- SubnetConfigParser::build(subnet);
+ SubnetPtr generic = SubnetConfigParser::build(subnet);
- if (subnet_) {
- Subnet6Ptr sub6ptr = boost::dynamic_pointer_cast<Subnet6>(subnet_);
- if (!sub6ptr) {
- // If we hit this, it is a programming error.
- isc_throw(Unexpected,
- "Invalid cast in Subnet6ConfigParser::commit");
- }
+ if (!generic) {
+ isc_throw(DhcpConfigError,
+ "Failed to create an IPv6 subnet (" <<
+ subnet->getPosition() << ")");
+ }
- // Set relay information if it was provided
- if (relay_info_) {
- sub6ptr->setRelayInfo(*relay_info_);
- }
+ Subnet6Ptr sub6ptr = boost::dynamic_pointer_cast<Subnet6>(subnet_);
+ if (!sub6ptr) {
+ // If we hit this, it is a programming error.
+ isc_throw(Unexpected,
+ "Invalid Subnet6 cast in Subnet6ConfigParser::parse");
+ }
- // Adding a subnet to the Configuration Manager may fail if the
- // subnet id is invalid (duplicate). Thus, we catch exceptions
- // here to append a position in the configuration string.
- try {
- CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(sub6ptr);
- } catch (const std::exception& ex) {
- isc_throw(DhcpConfigError, ex.what() << " ("
- << subnet->getPosition() << ")");
- }
+ // Set relay information if it was provided
+ if (relay_info_) {
+ sub6ptr->setRelayInfo(*relay_info_);
+ }
- // Parse Host Reservations for this subnet if any.
- ConstElementPtr reservations = subnet->get("reservations");
- if (reservations) {
- HostReservationsListParser<HostReservationParser6> parser;
- parser.parse(subnet_->getID(), reservations);
- }
+
+ // Parse Host Reservations for this subnet if any.
+ ConstElementPtr reservations = subnet->get("reservations");
+ if (reservations) {
+ HostReservationsListParser<HostReservationParser6> parser;
+ parser.parse(subnet_->getID(), reservations);
}
- }
- /// @brief Commits subnet configuration.
- ///
- /// This function is currently no-op because subnet should already
- /// be added into the Config Manager in the build().
- void commit() { }
+ return (sub6ptr);
+ }
protected:
/// This is a wrapper parser that handles the whole list of Subnet6
/// definitions. It iterates over all entries and creates Subnet6ConfigParser
/// for each entry.
-class Subnets6ListConfigParser : public DhcpConfigParser {
+class Subnets6ListConfigParser : public isc::data::SimpleParser {
public:
- /// @brief constructor
- ///
- /// @param dummy first argument, always ignored. All parsers accept a
- /// string parameter "name" as their first argument.
- Subnets6ListConfigParser(const std::string&) {
- }
-
/// @brief parses contents of the list
///
- /// Iterates over all entries on the list and creates a Subnet6ConfigParser
- /// for each entry.
+ /// Iterates over all entries on the list, parses its content
+ /// (by instantiating Subnet6ConfigParser) and adds to specified
+ /// configuration.
///
+ /// @param cfg configuration (parsed subnets will be stored here)
/// @param subnets_list pointer to a list of IPv6 subnets
- void build(ConstElementPtr subnets_list) {
- BOOST_FOREACH(ConstElementPtr subnet, subnets_list->listValue()) {
- ParserPtr parser(new Subnet6ConfigParser("subnet"));
- parser->build(subnet);
- subnets_.push_back(parser);
- }
+ /// @throw DhcpConfigError if CfgMgr rejects the subnet (e.g. subnet-id is a duplicate)
+ size_t parse(SrvConfigPtr cfg, ConstElementPtr subnets_list) {
+ size_t cnt = 0;
+ BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
- }
+ Subnet6ConfigParser parser;
+ Subnet6Ptr subnet = parser.parse(subnet_json);
- /// @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() {
- BOOST_FOREACH(ParserPtr subnet, subnets_) {
- subnet->commit();
+ // Adding a subnet to the Configuration Manager may fail if the
+ // subnet id is invalid (duplicate). Thus, we catch exceptions
+ // here to append a position in the configuration string.
+ try {
+ cfg->getCfgSubnets6()->add(subnet);
+ cnt++;
+ } catch (const std::exception& ex) {
+ isc_throw(DhcpConfigError, ex.what() << " ("
+ << subnet_json->getPosition() << ")");
+ }
}
-
- }
-
- /// @brief Returns Subnet6ListConfigParser object
- /// @param param_name name of the parameter
- /// @return Subnets6ListConfigParser object
- static DhcpConfigParser* factory(const std::string& param_name) {
- return (new Subnets6ListConfigParser(param_name));
+ return (cnt);
}
-
- /// @brief collection of subnet parsers.
- ParserCollection subnets_;
};
/// @brief Parser for list of RSOO options
(config_id.compare("dhcp4o6-port") == 0) ) {
parser = new Uint32Parser(config_id,
globalContext()->uint32_values_);
- } else if (config_id.compare("subnet6") == 0) {
- parser = new Subnets6ListConfigParser(config_id);
+ // subnet6 has been converted to SimpleParser.
// option-data and option-def are no longer needed here. They're now
// converted to SimpleParser and are handled in configureDhcp6Server.
// interfaces-config has been converted to SimpleParser.
// lease-database parser.
// Please do not change this order!
ParserCollection independent_parsers;
- ParserPtr subnet_parser;
// Some of the parsers alter state of the system that can't easily
// be undone. (Or alter it in a way such that undoing the change
// default values and will insert derived values as well.
ElementPtr mutable_cfg = boost::const_pointer_cast<Element>(config_set);
+ // Set all default values if not specified by the user.
SimpleParser6::setAllDefaults(mutable_cfg);
+ // And now derive (inherit) global parameters to subnets, if not specified.
+ SimpleParser6::deriveParameters(mutable_cfg);
+
// Make parsers grouping.
const std::map<std::string, ConstElementPtr>& values_map =
mutable_cfg->mapValue();
continue;
}
+ if (config_pair.first == "subnet6") {
+ SrvConfigPtr srv_cfg = CfgMgr::instance().getStagingCfg();
+ Subnets6ListConfigParser subnets_parser;
+ // parse() returns number of subnets parsed. We may log it one day.
+ subnets_parser.parse(srv_cfg, config_pair.second);
+ continue;
+ }
+
ParserPtr parser(createGlobal6DhcpConfigParser(config_pair.first,
config_pair.second));
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PARSER_CREATED)
.arg(config_pair.first);
- if (config_pair.first == "subnet6") {
- subnet_parser = parser;
- } else {
- // Those parsers should be started before other
- // parsers so we can call build straight away.
- independent_parsers.push_back(parser);
- parser->build(config_pair.second);
- // The commit operation here may modify the global storage
- // but we need it so as the subnet6 parser can access the
- // parsed data.
- parser->commit();
- }
- }
- // The subnet parser is the next one to be run.
- std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
- values_map.find("subnet6");
- if (subnet_config != values_map.end()) {
- config_pair.first = "subnet6";
- subnet_parser->build(subnet_config->second);
+ // Those parsers should be started before other
+ // parsers so we can call build straight away.
+ independent_parsers.push_back(parser);
+ parser->build(config_pair.second);
+ // The commit operation here may modify the global storage
+ // but we need it so as the subnet6 parser can access the
+ // parsed data.
+ parser->commit();
}
// Setup the command channel.
// This operation should be exception safe but let's make sure.
if (!rollback) {
try {
- if (subnet_parser) {
- subnet_parser->commit();
- }
// Apply global options in the staging config.
setGlobalParameters6();
return (cnt);
}
+size_t SimpleParser6::deriveParameters(isc::data::ElementPtr global) {
+ size_t cnt = 0;
+ // Now derive global parameters into subnets.
+ ConstElementPtr subnets = global->get("subnet6");
+ if (subnets) {
+ BOOST_FOREACH(ElementPtr single_subnet, subnets->listValue()) {
+ cnt += SimpleParser::deriveParams(global, single_subnet,
+ INHERIT_GLOBAL_TO_SUBNET6);
+ }
+ }
+
+ return (cnt);
+}
+
};
};
/// @return number of default values added
static size_t setAllDefaults(isc::data::ElementPtr global);
+ /// @brief Derives (inherits) all parameters from global to more specific scopes.
+ ///
+ /// This method currently does the following:
+ /// - derives global parameters to subnets (lifetimes for now)
+ /// @param global scope to be modified if needed (subnet4 will be extracted)
+ /// @return number of default values derived
+ static size_t deriveParameters(isc::data::ElementPtr global);
+
// see simple_parser6.cc for comments for those parameters
static const isc::data::SimpleDefaults OPTION6_DEF_DEFAULTS;
static const isc::data::SimpleDefaults OPTION6_DEFAULTS;
" \"rebind-timer\": 2,"
" \"preferred-lifetime\": 3,"
" \"valid-lifetime\": 4"
+ " \"subnet6\": [ { \"renew-timer\": 100 } ] "
"}");
- ElementPtr subnet = parseJSON("{ \"renew-timer\": 100 }");
+
+ ConstElementPtr subnets = global->find("subnet6");
+ ASSERT_TRUE(subnets);
+ ConstElementPtr subnet = subnets->get(0);
+ ASSERT_TRUE(subnet);
// we should inherit 3 parameters. Renew-timer should remain intact,
// as it was already defined in the subnet scope.
size_t num;
- EXPECT_NO_THROW(num = SimpleParser::deriveParams(global, subnet,
- SimpleParser6::INHERIT_GLOBAL_TO_SUBNET6));
+ EXPECT_NO_THROW(num = SimpleParser6::deriveParameters(global));
EXPECT_EQ(3, num);
// Check the values. 3 of them are inherited, while the fourth one
}
-void
+SubnetPtr
SubnetConfigParser::build(ConstElementPtr subnet) {
BOOST_FOREACH(ConfigPair param, subnet->mapValue()) {
// Pools has been converted to SimpleParser.
"subnet configuration failed (" << subnet->getPosition()
<< "): " << ex.what());
}
+
+ return (subnet_);
}
Subnet::HRMode
///
/// This class parses the whole subnet definition. It creates parsers
/// for received configuration parameters as needed.
-class SubnetConfigParser : public DhcpConfigParser {
+class SubnetConfigParser : public isc::data::SimpleParser {
public:
/// @brief constructor
SubnetConfigParser(const std::string&, ParserContextPtr global_context,
const isc::asiolink::IOAddress& default_addr);
- /// @brief parses parameter value
+ /// @brief virtual destuctor (does nothing)
+ virtual ~SubnetConfigParser() { }
+
+protected:
+ /// @brief parses a subnet description and returns Subnet{4,6} structure
+ ///
+ /// This method is called from specialized (Subnet4ConfigParser or
+ /// Subnet6ConfigParser) classes.
///
/// @param subnet pointer to the content of subnet definition
+ /// @return a pointer to newly created subnet
///
/// @throw isc::DhcpConfigError if subnet configuration parsing failed.
- virtual void build(isc::data::ConstElementPtr subnet);
+ virtual SubnetPtr build(isc::data::ConstElementPtr subnet);
- /// @brief Adds the created subnet to a server's configuration.
- virtual void commit() = 0;
-
-protected:
/// @brief creates parsers for entries in subnet definition
///
/// @param config_id name of the entry