Browse Source

[2317] Created common function to get configured parameter from a storage.

Marcin Siodelski 12 years ago
parent
commit
e39b610889

+ 103 - 77
src/bin/dhcp4/config_parser.cc

@@ -37,6 +37,17 @@ using namespace isc::asiolink;
 
 namespace {
 
+// Forward declarations of some of the parser classes.
+// They are used to define pointer types for these classes.
+class BooleanParser;
+class StringParser;
+class Uint32Parser;
+
+// Pointers to various parser objects.
+typedef boost::shared_ptr<BooleanParser> BooleanParserPtr;
+typedef boost::shared_ptr<StringParser> StringParserPtr;
+typedef boost::shared_ptr<Uint32Parser> Uint32ParserPtr;
+
 /// @brief auxiliary type used for storing element name and its parser
 typedef pair<string, ConstElementPtr> ConfigPair;
 
@@ -149,7 +160,7 @@ public:
           value_(false) {
         // Empty parameter name is invalid.
         if (param_name_.empty()) {
-            isc_throw(isc::dhcp::Dhcp4ConfigError, "parser logic error:"
+            isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
     }
@@ -160,7 +171,7 @@ public:
     ///
     /// @throw isc::InvalidOperation if a storage has not been set
     ///        prior to calling this function
-    /// @throw isc::dhcp::Dhcp4ConfigError if a provided parameter's
+    /// @throw isc::dhcp::DhcpConfigError if a provided parameter's
     ///        name is empty.
     virtual void build(ConstElementPtr value) {
         if (storage_ == NULL) {
@@ -168,7 +179,7 @@ public:
                       << " storage for the " << param_name_
                       << " value has not been set");
         } else if (param_name_.empty()) {
-            isc_throw(isc::dhcp::Dhcp4ConfigError, "parser logic error:"
+            isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
         // The Config Manager checks if user specified a
@@ -233,7 +244,7 @@ public:
           param_name_(param_name) {
         // Empty parameter name is invalid.
         if (param_name_.empty()) {
-            isc_throw(Dhcp4ConfigError, "parser logic error:"
+            isc_throw(DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
     }
@@ -245,7 +256,7 @@ public:
     ///        or the parameter name is empty.
     virtual void build(ConstElementPtr value) {
         if (param_name_.empty()) {
-            isc_throw(Dhcp4ConfigError, "parser logic error:"
+            isc_throw(DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
 
@@ -326,7 +337,7 @@ public:
         :storage_(&string_defaults), param_name_(param_name) {
         // Empty parameter name is invalid.
         if (param_name_.empty()) {
-            isc_throw(Dhcp4ConfigError, "parser logic error:"
+            isc_throw(DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
     }
@@ -460,7 +471,7 @@ public:
     /// interface name.
     /// @param pools_list list of pools defined for a subnet
     /// @throw InvalidOperation if storage was not specified (setStorage() not called)
-    /// @throw Dhcp4ConfigError when pool parsing fails
+    /// @throw DhcpConfigError when pool parsing fails
     void build(ConstElementPtr pools_list) {
         // setStorage() should have been called before build
         if (!pools_) {
@@ -500,7 +511,7 @@ public:
                     // be checked in Pool4 constructor.
                     len = boost::lexical_cast<int>(prefix_len);
                 } catch (...)  {
-                    isc_throw(Dhcp4ConfigError, "Failed to parse pool "
+                    isc_throw(DhcpConfigError, "Failed to parse pool "
                               "definition: " << text_pool->stringValue());
                 }
 
@@ -522,7 +533,7 @@ public:
                 continue;
             }
 
-            isc_throw(Dhcp4ConfigError, "Failed to parse pool definition:"
+            isc_throw(DhcpConfigError, "Failed to parse pool definition:"
                       << text_pool->stringValue() <<
                       ". Does not contain - (for min-max) nor / (prefix/len)");
         }
@@ -603,7 +614,7 @@ public:
     ///
     /// @param option_data_entries collection of entries that define value
     /// for a particular option.
-    /// @throw Dhcp4ConfigError if invalid parameter specified in
+    /// @throw DhcpConfigError if invalid parameter specified in
     /// the configuration.
     /// @throw isc::InvalidOperation if failed to set storage prior to
     /// calling build.
@@ -644,7 +655,7 @@ public:
                     parser = value_parser;
                 }
             } else {
-                isc_throw(Dhcp4ConfigError,
+                isc_throw(DhcpConfigError,
                           "Parser error: option-data parameter not supported: "
                           << param.first);
             }
@@ -718,36 +729,36 @@ private:
     /// is intitialized but this check is not needed here because it is done
     /// in the \ref build function.
     ///
-    /// @throw Dhcp4ConfigError if parameters provided in the configuration
+    /// @throw DhcpConfigError if parameters provided in the configuration
     /// are invalid.
     void createOption() {
         // Option code is held in the uint32_t storage but is supposed to
         // be uint16_t value. We need to check that value in the configuration
         // does not exceed range of uint16_t and is not zero.
-        uint32_t option_code = getUint32Param("code");
+        uint32_t option_code = getParam<uint32_t>("code", uint32_values_);
         if (option_code == 0) {
-            isc_throw(Dhcp4ConfigError, "Parser error: value of 'code' must not"
+            isc_throw(DhcpConfigError, "Parser error: value of 'code' must not"
                       << " be equal to zero. Option code '0' is reserved in"
                       << " DHCPv4.");
         } else if (option_code > std::numeric_limits<uint16_t>::max()) {
-            isc_throw(Dhcp4ConfigError, "Parser error: value of 'code' must not"
+            isc_throw(DhcpConfigError, "Parser error: value of 'code' must not"
                       << " exceed " << std::numeric_limits<uint16_t>::max());
         }
         // Check that the option name has been specified, is non-empty and does not
         // contain spaces.
         // @todo possibly some more restrictions apply here?
-        std::string option_name = getStringParam("name");
+        std::string option_name = getParam<std::string>("name", string_values_);
         if (option_name.empty()) {
-            isc_throw(Dhcp4ConfigError, "Parser error: option name must not be"
+            isc_throw(DhcpConfigError, "Parser error: option name must not be"
                       << " empty");
         } else if (option_name.find(" ") != std::string::npos) {
-            isc_throw(Dhcp4ConfigError, "Parser error: option name must not contain"
+            isc_throw(DhcpConfigError, "Parser error: option name must not contain"
                       << " spaces");
         }
 
         // Get option data from the configuration database ('data' field).
-        const std::string option_data = getStringParam("data");
-        const bool csv_format = getBooleanParam("csv-format");
+        const std::string option_data = getParam<std::string>("data", string_values_);
+        const bool csv_format = getParam<bool>("csv-format", boolean_values_);
         // Transform string of hexadecimal digits into binary format.
         std::vector<uint8_t> binary;
         std::vector<std::string> data_tokens;
@@ -764,7 +775,7 @@ private:
             try {
                 util::encode::decodeHex(option_data, binary);
             } catch (...) {
-                isc_throw(Dhcp4ConfigError, "Parser error: option data is not a valid"
+                isc_throw(DhcpConfigError, "Parser error: option data is not a valid"
                           << " string of hexadecimal digits: " << option_data);
             }
         }
@@ -781,13 +792,13 @@ private:
         // Currently we do not allow duplicated definitions and if there are
         // any duplicates we issue internal server error.
         if (num_defs > 1) {
-            isc_throw(Dhcp4ConfigError, "Internal error: currently it is not"
+            isc_throw(DhcpConfigError, "Internal error: currently it is not"
                       << " supported to initialize multiple option definitions"
                       << " for the same option code. This will be supported once"
                       << " there option spaces are implemented.");
         } else if (num_defs == 0) {
             if (csv_format) {
-                isc_throw(Dhcp4ConfigError, "the CSV option data format can be"
+                isc_throw(DhcpConfigError, "the CSV option data format can be"
                           " used to specify values for an option that has a"
                           " definition. The option with code " << option_code
                           << " does not have a definition.");
@@ -817,54 +828,13 @@ private:
                 option_descriptor_.option = option;
                 option_descriptor_.persistent = false;
             } catch (const isc::Exception& ex) {
-                isc_throw(Dhcp4ConfigError, "Parser error: option data does not match"
+                isc_throw(DhcpConfigError, "Parser error: option data does not match"
                           << " option definition (code " << option_code << "): "
                           << ex.what());
             }
         }
     }
 
-    /// @brief Get a parameter from the strings storage.
-    ///
-    /// @param param_id parameter identifier.
-    /// @throw Dhcp4ConfigError if parameter has not been found.
-    std::string getStringParam(const std::string& param_id) const {
-        StringStorage::const_iterator param = string_values_.find(param_id);
-        if (param == string_values_.end()) {
-            isc_throw(Dhcp4ConfigError, "Parser error: option-data parameter"
-                      << " '" << param_id << "' not specified");
-        }
-        return (param->second);
-    }
-
-    /// @brief Get a parameter from the uint32 values storage.
-    ///
-    /// @param param_id parameter identifier.
-    /// @throw Dhcp4ConfigError if parameter has not been found.
-    uint32_t getUint32Param(const std::string& param_id) const {
-        Uint32Storage::const_iterator param = uint32_values_.find(param_id);
-        if (param == uint32_values_.end()) {
-            isc_throw(Dhcp4ConfigError, "Parser error: option-data parameter"
-                      << " '" << param_id << "' not specified");
-        }
-        return (param->second);
-    }
-
-    /// @brief Get a parameter from the boolean values storage.
-    ///
-    /// @param param_id parameter identifier.
-    ///
-    /// @throw isc::dhcp::Dhcp6ConfigError if a parameter has not been found.
-    /// @return a value of the boolean parameter.
-    bool getBooleanParam(const std::string& param_id) const {
-        BooleanStorage::const_iterator param = boolean_values_.find(param_id);
-        if (param == boolean_values_.end()) {
-            isc_throw(isc::dhcp::Dhcp4ConfigError, "parser error: option-data parameter"
-                      << " '" << param_id << "' not specified");
-        }
-        return (param->second);
-    }
-
     /// Storage for uint32 values (e.g. option code).
     Uint32Storage uint32_values_;
     /// Storage for string values (e.g. option name or data).
@@ -901,7 +871,7 @@ public:
     /// for options within a single subnet and creates options' instances.
     ///
     /// @param option_data_list pointer to a list of options' data sets.
-    /// @throw Dhcp4ConfigError if option parsing failed.
+    /// @throw DhcpConfigError if option parsing failed.
     void build(ConstElementPtr option_data_list) {
         BOOST_FOREACH(ConstElementPtr option_value, option_data_list->listValue()) {
             boost::shared_ptr<OptionDataParser> parser(new OptionDataParser("option-data"));
@@ -975,12 +945,53 @@ public:
     ///
     /// @param option_def a configuration entry to be parsed.
     ///
-    /// @throw Dhcp4ConfigError if parsing was unsuccessful.
+    /// @throw DhcpConfigError if parsing was unsuccessful.
     void build(ConstElementPtr option_def) {
+        if (storage_ == NULL) {
+            isc_throw(DhcpConfigError, "parser logic error: storage must be set"
+                      " before parsing option definition data");
+        }
+        // Parse the elements that make up the option definition.
+        BOOST_FOREACH(ConfigPair param, option_def->mapValue()) {
+            std::string entry(param.first);
+            ParserPtr parser;
+            if (entry == "name" || entry == "type" || entry == "space") {
+                StringParserPtr
+                    str_parser(dynamic_cast<StringParser*>(StringParser::factory(entry)));
+                if (str_parser) {
+                    str_parser->setStorage(&string_values_);
+                    parser = str_parser;
+                }
+            } else if (entry == "code") {
+                Uint32ParserPtr
+                    code_parser(dynamic_cast<Uint32Parser*>(Uint32Parser::factory(entry)));
+                if (code_parser) {
+                    code_parser->setStorage(&uint32_values_);
+                    parser = code_parser;
+                }
+            } else if (entry == "array") {
+                BooleanParserPtr
+                    array_parser(dynamic_cast<BooleanParser*>(BooleanParser::factory(entry)));
+                if (array_parser) {
+                    array_parser->setStorage(&boolean_values_);
+                    parser = array_parser;
+                }
+            } else if (entry == "record_types") {
+                // do nothing yet
+            } else {
+                isc_throw(DhcpConfigError, "invalid parameter: " << entry);
+            }
+            
+            parser->build(param.second);
+            parser->commit();
+        }
+
+        createOptionDef();
     }
 
     /// @brief Stores the parsed option definition in a storage.
     void commit() {
+        
     }
 
     /// @brief Sets a pointer to a storage.
@@ -996,12 +1007,27 @@ public:
 
 private:
 
+    void createOptionDef() {
+        std::string name = getParam<std::string>("name", string_values_);
+        uint32_t code = getParam<uint32_t>("code", uint32_values_);
+        std::string type = getParam<std::string>("type", string_values_);
+        bool array_type = getParam<bool>("array", boolean_values_);
+        std::string space = getParam<std::string>("space", string_values_);
+    }
+
     /// Instance of option definition being created by this parser.
     OptionDefinitionPtr option_definition_;
 
     /// Pointer to a storage where the option definition will be
     /// added when \ref commit is called.
     OptionDefContainer* storage_;
+
+    /// Storage for boolean values.
+    BooleanStorage boolean_values_;
+    /// Storage for string values.
+    StringStorage string_values_;
+    /// Storage for uint32 values.
+    Uint32Storage uint32_values_;
 };
 
 /// @brief Parser for a list of option definitions.
@@ -1029,13 +1055,13 @@ public:
     ///
     /// @param option_def_list pointer to an element that holds entries
     /// that define option definitions.
-    /// @throw Dhcp4ConfigError if configuration parsing fails.
+    /// @throw DhcpConfigError if configuration parsing fails.
     void build(ConstElementPtr option_def_list) {
         if (!option_def_list) {
-            isc_throw(Dhcp4ConfigError, "parser error: a pointer to a list of"
+            isc_throw(DhcpConfigError, "parser error: a pointer to a list of"
                       << " option definitions is NULL");
         } else if (option_defs_ == NULL) {
-            isc_throw(Dhcp4ConfigError, "parser error: the storage for option"
+            isc_throw(DhcpConfigError, "parser error: the storage for option"
                       << " definitions must be set before parsing option"
                       << " definitions");
         }
@@ -1121,7 +1147,7 @@ public:
                 // Appropriate parsers are created in the createSubnet6ConfigParser
                 // and they should be limited to those that we check here for. Thus,
                 // if we fail to find a matching parser here it is a programming error.
-                isc_throw(Dhcp4ConfigError, "failed to find suitable parser");
+                isc_throw(DhcpConfigError, "failed to find suitable parser");
             }
         }
         // In order to create new subnet we need to get the data out
@@ -1146,7 +1172,7 @@ public:
     /// storing the values that are actually consumed here. Pool definitions
     /// created in other parsers are used here and added to newly created Subnet4
     /// objects. Subnet4 are then added to DHCP CfgMgr.
-    /// @throw Dhcp4ConfigError if there are any issues encountered during commit
+    /// @throw DhcpConfigError if there are any issues encountered during commit
     void commit() {
         if (subnet_) {
             CfgMgr::instance().addSubnet4(subnet_);
@@ -1191,11 +1217,11 @@ private:
 
     /// @brief Create a new subnet using a data from child parsers.
     ///
-    /// @throw isc::dhcp::Dhcp4ConfigError if subnet configuration parsing failed.
+    /// @throw isc::dhcp::DhcpConfigError if subnet configuration parsing failed.
     void createSubnet() {
         StringStorage::const_iterator it = string_values_.find("subnet");
         if (it == string_values_.end()) {
-            isc_throw(Dhcp4ConfigError,
+            isc_throw(DhcpConfigError,
                       "Mandatory subnet definition in subnet missing");
         }
         // Remove any spaces or tabs.
@@ -1210,7 +1236,7 @@ private:
         // need to get all characters preceding "/".
         size_t pos = subnet_txt.find("/");
         if (pos == string::npos) {
-            isc_throw(Dhcp4ConfigError,
+            isc_throw(DhcpConfigError,
                       "Invalid subnet syntax (prefix/len expected):" << it->second);
         }
 
@@ -1315,7 +1341,7 @@ private:
     ///
     /// @param name name of the parameter
     /// @return triplet with the parameter name
-    /// @throw Dhcp4ConfigError when requested parameter is not present
+    /// @throw DhcpConfigError when requested parameter is not present
     Triplet<uint32_t> getParam(const std::string& name) {
         uint32_t value = 0;
         bool found = false;
@@ -1334,7 +1360,7 @@ private:
         if (found) {
             return (Triplet<uint32_t>(value));
         } else {
-            isc_throw(Dhcp4ConfigError, "Mandatory parameter " << name
+            isc_throw(DhcpConfigError, "Mandatory parameter " << name
                       << " missing (no global default and no subnet-"
                       << "specific value)");
         }

+ 0 - 14
src/bin/dhcp4/config_parser.h

@@ -28,20 +28,6 @@ namespace dhcp {
 
 class Dhcpv4Srv;
 
-/// An exception that is thrown if an error occurs while configuring an
-/// @c Dhcpv4Srv object.
-class Dhcp4ConfigError : public isc::Exception {
-public:
-
-    /// @brief constructor
-    ///
-    /// @param file name of the file, where exception occurred
-    /// @param line line of the file, where exception occurred
-    /// @param what text description of the issue that caused exception
-    Dhcp4ConfigError(const char* file, size_t line, const char* what)
-        : isc::Exception(file, line, what) {}
-};
-
 /// @brief Configure DHCPv4 server (@c Dhcpv4Srv) with a set of configuration values.
 ///
 /// This function parses configuration information stored in @c config_set

+ 2 - 1
src/bin/dhcp4/ctrl_dhcp4_srv.cc

@@ -19,6 +19,7 @@
 #include <cc/session.h>
 #include <config/ccsession.h>
 #include <dhcp/iface_mgr.h>
+#include <dhcpsrv/dhcp_config_parser.h>
 #include <dhcp4/ctrl_dhcp4_srv.h>
 #include <dhcp4/dhcp4_log.h>
 #include <dhcp4/spec_config.h>
@@ -121,7 +122,7 @@ void ControlledDhcpv4Srv::establishSession() {
 
     try {
         configureDhcp4Server(*this, config_session_->getFullConfig());
-    } catch (const Dhcp4ConfigError& ex) {
+    } catch (const DhcpConfigError& ex) {
         LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL).arg(ex.what());
     }
 

+ 37 - 82
src/bin/dhcp6/config_parser.cc

@@ -161,7 +161,7 @@ public:
           value_(false) {
         // Empty parameter name is invalid.
         if (param_name_.empty()) {
-            isc_throw(isc::dhcp::Dhcp6ConfigError, "parser logic error:"
+            isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
     }
@@ -172,7 +172,7 @@ public:
     ///
     /// @throw isc::InvalidOperation if a storage has not been set
     ///        prior to calling this function
-    /// @throw isc::dhcp::Dhcp6ConfigError if a provided parameter's
+    /// @throw isc::dhcp::DhcpConfigError if a provided parameter's
     ///        name is empty.
     virtual void build(ConstElementPtr value) {
         if (storage_ == NULL) {
@@ -180,7 +180,7 @@ public:
                       << " storage for the " << param_name_
                       << " value has not been set");
         } else if (param_name_.empty()) {
-            isc_throw(isc::dhcp::Dhcp6ConfigError, "parser logic error:"
+            isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
         // The Config Manager checks if user specified a
@@ -249,7 +249,7 @@ public:
           param_name_(param_name) {
         // Empty parameter name is invalid.
         if (param_name_.empty()) {
-            isc_throw(Dhcp6ConfigError, "parser logic error:"
+            isc_throw(DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
     }
@@ -257,11 +257,11 @@ public:
     /// @brief Parses configuration configuration parameter as uint32_t.
     ///
     /// @param value pointer to the content of parsed values
-    /// @throw isc::dhcp::Dhcp6ConfigError if failed to parse
+    /// @throw isc::dhcp::DhcpConfigError if failed to parse
     ///        the configuration parameter as uint32_t value.
     virtual void build(ConstElementPtr value) {
         if (param_name_.empty()) {
-            isc_throw(isc::dhcp::Dhcp6ConfigError, "parser logic error:"
+            isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
 
@@ -291,7 +291,7 @@ public:
         }
         // Invalid value provided.
         if (parse_error) {
-            isc_throw(isc::dhcp::Dhcp6ConfigError, "Failed to parse value " << value->str()
+            isc_throw(isc::dhcp::DhcpConfigError, "Failed to parse value " << value->str()
                       << " as unsigned 32-bit integer.");
         }
     }
@@ -352,7 +352,7 @@ public:
           param_name_(param_name) {
         // Empty parameter name is invalid.
         if (param_name_.empty()) {
-            isc_throw(Dhcp6ConfigError, "parser logic error:"
+            isc_throw(DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
     }
@@ -362,10 +362,10 @@ public:
     /// Parses configuration parameter's value as string.
     ///
     /// @param value pointer to the content of parsed values
-    /// @throws Dhcp6ConfigError if the parsed parameter's name is empty.
+    /// @throws DhcpConfigError if the parsed parameter's name is empty.
     virtual void build(ConstElementPtr value) {
         if (param_name_.empty()) {
-            isc_throw(isc::dhcp::Dhcp6ConfigError, "parser logic error:"
+            isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
                       << "empty parameter name provided");
         }
         value_ = value->str();
@@ -528,7 +528,7 @@ public:
                     // be checked in Pool6 constructor.
                     len = boost::lexical_cast<int>(prefix_len);
                 } catch (...)  {
-                    isc_throw(Dhcp6ConfigError, "failed to parse pool "
+                    isc_throw(DhcpConfigError, "failed to parse pool "
                               "definition: " << text_pool->stringValue());
                 }
 
@@ -550,7 +550,7 @@ public:
                 continue;
             }
 
-            isc_throw(Dhcp6ConfigError, "failed to parse pool definition:"
+            isc_throw(DhcpConfigError, "failed to parse pool definition:"
                       << text_pool->stringValue() <<
                       ". Does not contain - (for min-max) nor / (prefix/len)");
         }
@@ -632,7 +632,7 @@ public:
     ///
     /// @param option_data_entries collection of entries that define value
     /// for a particular option.
-    /// @throw Dhcp6ConfigError if invalid parameter specified in
+    /// @throw DhcpConfigError if invalid parameter specified in
     /// the configuration.
     /// @throw isc::InvalidOperation if failed to set storage prior to
     /// calling build.
@@ -674,7 +674,7 @@ public:
                     parser = value_parser;
                 }
             } else {
-                isc_throw(Dhcp6ConfigError,
+                isc_throw(DhcpConfigError,
                           "parser error: option-data parameter not supported: "
                           << param.first);
             }
@@ -748,37 +748,37 @@ private:
     /// is intitialized but this check is not needed here because it is done
     /// in the \ref build function.
     ///
-    /// @throw Dhcp6ConfigError if parameters provided in the configuration
+    /// @throw DhcpConfigError if parameters provided in the configuration
     /// are invalid.
     void createOption() {
 
         // Option code is held in the uint32_t storage but is supposed to
         // be uint16_t value. We need to check that value in the configuration
         // does not exceed range of uint16_t and is not zero.
-        uint32_t option_code = getUint32Param("code");
+        uint32_t option_code = getParam<uint32_t>("code", uint32_values_);
         if (option_code == 0) {
-            isc_throw(Dhcp6ConfigError, "Parser error: value of 'code' must not"
+            isc_throw(DhcpConfigError, "Parser error: value of 'code' must not"
                       << " be equal to zero. Option code '0' is reserved in"
                       << " DHCPv6.");
         } else if (option_code > std::numeric_limits<uint16_t>::max()) {
-            isc_throw(Dhcp6ConfigError, "Parser error: value of 'code' must not"
+            isc_throw(DhcpConfigError, "Parser error: value of 'code' must not"
                       << " exceed " << std::numeric_limits<uint16_t>::max());
         }
         // Check that the option name has been specified, is non-empty and does not
         // contain spaces.
         // @todo possibly some more restrictions apply here?
-        std::string option_name = getStringParam("name");
+        std::string option_name = getParam<std::string>("name", string_values_);
         if (option_name.empty()) {
-            isc_throw(Dhcp6ConfigError, "Parser error: option name must not be"
+            isc_throw(DhcpConfigError, "Parser error: option name must not be"
                       << " empty");
         } else if (option_name.find(" ") != std::string::npos) {
-            isc_throw(Dhcp6ConfigError, "Parser error: option name must not contain"
+            isc_throw(DhcpConfigError, "Parser error: option name must not contain"
                       << " spaces");
         }
 
         // Get option data from the configuration database ('data' field).
-        const std::string option_data = getStringParam("data");
-        const bool csv_format = getBooleanParam("csv-format");
+        const std::string option_data = getParam<std::string>("data", string_values_);
+        const bool csv_format = getParam<bool>("csv-format", boolean_values_);
         std::vector<uint8_t> binary;
         std::vector<std::string> data_tokens;
         if (csv_format) {
@@ -793,7 +793,7 @@ private:
             try {
                 isc::util::encode::decodeHex(option_data, binary);
             } catch (...) {
-                isc_throw(Dhcp6ConfigError, "Parser error: option data is not a valid"
+                isc_throw(DhcpConfigError, "Parser error: option data is not a valid"
                           << " string of hexadecimal digits: " << option_data);
             }
         }
@@ -810,13 +810,13 @@ private:
         // Currently we do not allow duplicated definitions and if there are
         // any duplicates we issue internal server error.
         if (num_defs > 1) {
-            isc_throw(Dhcp6ConfigError, "Internal error: currently it is not"
+            isc_throw(DhcpConfigError, "Internal error: currently it is not"
                       << " supported to initialize multiple option definitions"
                       << " for the same option code. This will be supported once"
                       << " there option spaces are implemented.");
         } else if (num_defs == 0) {
             if (csv_format) {
-                isc_throw(Dhcp6ConfigError, "the CSV option data format can be"
+                isc_throw(DhcpConfigError, "the CSV option data format can be"
                           " used to specify values for an option that has a"
                           " definition. The option with code " << option_code
                           << " does not have a definition.");
@@ -845,58 +845,13 @@ private:
                 option_descriptor_.option = option;
                 option_descriptor_.persistent = false;
             } catch (const isc::Exception& ex) {
-                isc_throw(Dhcp6ConfigError, "Parser error: option data does not match"
+                isc_throw(DhcpConfigError, "Parser error: option data does not match"
                           << " option definition (code " << option_code << "): "
                           << ex.what());
             }
         }
     }
 
-    /// @brief Get a parameter from the strings storage.
-    ///
-    /// @param param_id parameter identifier.
-    ///
-    /// @throw Dhcp6ConfigError if a parameter has not been found.
-    /// @return a value of the string parameter.
-    std::string getStringParam(const std::string& param_id) const {
-        StringStorage::const_iterator param = string_values_.find(param_id);
-        if (param == string_values_.end()) {
-            isc_throw(isc::dhcp::Dhcp6ConfigError, "parser error: option-data parameter"
-                      << " '" << param_id << "' not specified");
-        }
-        return (param->second);
-    }
-
-    /// @brief Get a parameter from the uint32 values storage.
-    ///
-    /// @param param_id parameter identifier.
-    ///
-    /// @throw Dhcp6ConfigError if a parameter has not been found.
-    /// @return a value of the uint32_t parameter.
-    uint32_t getUint32Param(const std::string& param_id) const {
-        Uint32Storage::const_iterator param = uint32_values_.find(param_id);
-        if (param == uint32_values_.end()) {
-            isc_throw(isc::dhcp::Dhcp6ConfigError, "parser error: option-data parameter"
-                      << " '" << param_id << "' not specified");
-        }
-        return (param->second);
-    }
-
-    /// @brief Get a parameter from the boolean values storage.
-    ///
-    /// @param param_id parameter identifier.
-    ///
-    /// @throw isc::dhcp::Dhcp6ConfigError if a parameter has not been found.
-    /// @return a value of the boolean parameter.
-    bool getBooleanParam(const std::string& param_id) const {
-        BooleanStorage::const_iterator param = boolean_values_.find(param_id);
-        if (param == boolean_values_.end()) {
-            isc_throw(isc::dhcp::Dhcp6ConfigError, "parser error: option-data parameter"
-                      << " '" << param_id << "' not specified");
-        }
-        return (param->second);
-    }
-
     /// Storage for uint32 values (e.g. option code).
     Uint32Storage uint32_values_;
     /// Storage for string values (e.g. option name or data).
@@ -933,7 +888,7 @@ public:
     /// for options within a single subnet and creates options' instances.
     ///
     /// @param option_data_list pointer to a list of options' data sets.
-    /// @throw Dhcp6ConfigError if option parsing failed.
+    /// @throw DhcpConfigError if option parsing failed.
     void build(ConstElementPtr option_data_list) {
         BOOST_FOREACH(ConstElementPtr option_value, option_data_list->listValue()) {
             boost::shared_ptr<OptionDataParser> parser(new OptionDataParser("option-data"));
@@ -1005,7 +960,7 @@ public:
     ///
     /// @param subnet pointer to the content of subnet definition
     ///
-    /// @throw isc::Dhcp6ConfigError if subnet configuration parsing failed.
+    /// @throw isc::DhcpConfigError if subnet configuration parsing failed.
     void build(ConstElementPtr subnet) {
 
         BOOST_FOREACH(ConfigPair param, subnet->mapValue()) {
@@ -1031,7 +986,7 @@ public:
                 // Appropriate parsers are created in the createSubnet6ConfigParser
                 // and they should be limited to those that we check here for. Thus,
                 // if we fail to find a matching parser here it is a programming error.
-                isc_throw(Dhcp6ConfigError, "failed to find suitable parser");
+                isc_throw(DhcpConfigError, "failed to find suitable parser");
             }
         }
 
@@ -1096,13 +1051,13 @@ private:
 
     /// @brief Create a new subnet using a data from child parsers.
     ///
-    /// @throw isc::dhcp::Dhcp6ConfigError if subnet configuration parsing failed.
+    /// @throw isc::dhcp::DhcpConfigError if subnet configuration parsing failed.
     void createSubnet() {
         
         // Find a subnet string.
         StringStorage::const_iterator it = string_values_.find("subnet");
         if (it == string_values_.end()) {
-            isc_throw(Dhcp6ConfigError,
+            isc_throw(DhcpConfigError,
                       "Mandatory subnet definition in subnet missing");
         }
         // Remove any spaces or tabs.
@@ -1116,7 +1071,7 @@ private:
         // need to get all characters preceding "/".
         size_t pos = subnet_txt.find("/");
         if (pos == string::npos) {
-            isc_throw(Dhcp6ConfigError,
+            isc_throw(DhcpConfigError,
                       "Invalid subnet syntax (prefix/len expected):" << it->second);
         }
 
@@ -1193,7 +1148,7 @@ private:
     /// @param config_id name od the entry
     ///
     /// @return parser object for specified entry name
-    /// @throw isc::dhcp::Dhcp6ConfigError if trying to create a parser
+    /// @throw isc::dhcp::DhcpConfigError if trying to create a parser
     ///        for unknown config element
     DhcpConfigParser* createSubnet6ConfigParser(const std::string& config_id) {
         FactoryMap factories;
@@ -1211,7 +1166,7 @@ private:
             // Used for debugging only.
             // return new DebugParser(config_id);
 
-            isc_throw(isc::dhcp::Dhcp6ConfigError,
+            isc_throw(isc::dhcp::DhcpConfigError,
                       "parser error: subnet6 parameter not supported: "
                       << config_id);
         }
@@ -1226,7 +1181,7 @@ private:
     ///
     /// @param name name of the parameter
     /// @return triplet with the parameter name
-    /// @throw Dhcp6ConfigError when requested parameter is not present
+    /// @throw DhcpConfigError when requested parameter is not present
     isc::dhcp::Triplet<uint32_t> getParam(const std::string& name) {
         uint32_t value = 0;
         bool found = false;
@@ -1245,7 +1200,7 @@ private:
         if (found) {
             return (isc::dhcp::Triplet<uint32_t>(value));
         } else {
-            isc_throw(isc::dhcp::Dhcp6ConfigError, "Mandatory parameter " << name
+            isc_throw(isc::dhcp::DhcpConfigError, "Mandatory parameter " << name
                       << " missing (no global default and no subnet-"
                       << "specific value)");
         }

+ 0 - 14
src/bin/dhcp6/config_parser.h

@@ -27,20 +27,6 @@ namespace dhcp {
 
 class Dhcpv6Srv;
 
-/// An exception that is thrown if an error occurs while configuring an
-/// @c Dhcpv6Srv object.
-class Dhcp6ConfigError : public isc::Exception {
-public:
-
-    /// @brief constructor
-    ///
-    /// @param file name of the file, where exception occurred
-    /// @param line line of the file, where exception occurred
-    /// @param what text description of the issue that caused exception
-    Dhcp6ConfigError(const char* file, size_t line, const char* what)
-        : isc::Exception(file, line, what) {}
-};
-
 /// @brief Configures DHCPv6 server
 ///
 /// This function is called every time a new configuration is received. The extra

+ 2 - 1
src/bin/dhcp6/ctrl_dhcp6_srv.cc

@@ -19,6 +19,7 @@
 #include <cc/session.h>
 #include <config/ccsession.h>
 #include <dhcp/iface_mgr.h>
+#include <dhcpsrv/dhcp_config_parser.h>
 #include <dhcp6/config_parser.h>
 #include <dhcp6/ctrl_dhcp6_srv.h>
 #include <dhcp6/dhcp6_log.h>
@@ -121,7 +122,7 @@ void ControlledDhcpv6Srv::establishSession() {
 
     try {
         configureDhcp6Server(*this, config_session_->getFullConfig());
-    } catch (const Dhcp6ConfigError& ex) {
+    } catch (const DhcpConfigError& ex) {
         LOG_ERROR(dhcp6_logger, DHCP6_CONFIG_LOAD_FAIL).arg(ex.what());
     }
 

+ 42 - 0
src/lib/dhcpsrv/dhcp_config_parser.h

@@ -18,6 +18,20 @@
 namespace isc {
 namespace dhcp {
 
+/// An exception that is thrown if an error occurs while configuring
+/// DHCP server.
+class DhcpConfigError : public isc::Exception {
+public:
+
+    /// @brief constructor
+    ///
+    /// @param file name of the file, where exception occurred
+    /// @param line line of the file, where exception occurred
+    /// @param what text description of the issue that caused exception
+    DhcpConfigError(const char* file, size_t line, const char* what)
+        : isc::Exception(file, line, what) {}
+};
+
 /// @brief Forward declaration to DhcpConfigParser class.
 ///
 /// It is only needed here to define types that are
@@ -105,6 +119,34 @@ public:
     /// This method is expected to be called after @c build(), and only once.
     /// The result is undefined otherwise.
     virtual void commit() = 0;
+
+protected:
+
+    /// @brief Return the parsed entry from the provided storage.
+    ///
+    /// This method returns the parsed entry from the provided
+    /// storage. If the entry is not found, then exception is
+    /// thrown.
+    ///
+    /// @param param_id name of the configuration entry.
+    /// @param storage storage where the entry should be searched.
+    /// @tparam ReturnType type of the returned value.
+    /// @tparam StorageType type of the storage.
+    ///
+    /// @throw DhcpConfigError if the entry has not been found
+    /// in the storage.
+    template<typename ReturnType, typename StorageType>
+    ReturnType getParam(const std::string param_id,
+                        const StorageType& storage) const {
+        typename StorageType::const_iterator param = storage.find(param_id);
+        if (param == storage.end()) {
+            isc_throw(DhcpConfigError, "missing parameter '"
+                      << param_id << "'");
+        }
+        ReturnType value = param->second;
+        return (value);
+    }
+
 };