Browse Source

[3259] Added capability to interpret old and new hooks library syntax

Stephen Morris 9 years ago
parent
commit
c98ef91cb1
2 changed files with 99 additions and 5 deletions
  1. 10 0
      src/lib/dhcpsrv/dhcpsrv_messages.mes
  2. 89 5
      src/lib/dhcpsrv/parsers/dhcp_parsers.cc

+ 10 - 0
src/lib/dhcpsrv/dhcpsrv_messages.mes

@@ -176,6 +176,16 @@ have been experienced.  Any such errors should have preceding entries in the
 log with details.  No further attempts to communicate with kea-dhcp-ddns will
 be made without intervention.
 
+% DHCPSRV_HOOK_DEPRECATED_SYNTAX hook libraries specified using deprecated syntax, please update your configuration
+This warning message is issued when a configuration file is loaded and Kea notices
+that the hooks libraries have been specified as a simple list of libraries (the
+syntax used in Kea 0.9.2 and earlier).  In Kea 1.0 the syntax was changed to allow the
+specification of library-specific parameters.
+
+To ease the transition, the old syntax is accepted for now, but a future version of
+Kea will no longer accept it.  Please update your configuration files to use the new
+syntax (described in the Kea Administrator Reference Manual).
+
 % DHCPSRV_HOOK_LEASE4_RENEW_SKIP DHCPv4 lease was not renewed because a callout set the skip flag.
 This debug message is printed when a callout installed on lease4_renew
 hook point set the skip flag. For this particular hook point, the setting

+ 89 - 5
src/lib/dhcpsrv/parsers/dhcp_parsers.cc

@@ -18,6 +18,7 @@
 #include <dhcp/libdhcp++.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/cfg_option.h>
+#include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/parsers/dhcp_parsers.h>
 #include <dhcpsrv/cfg_mac_source.h>
 #include <hooks/hooks_manager.h>
@@ -248,17 +249,100 @@ HooksLibrariesParser::HooksLibrariesParser(const std::string& param_name)
     }
 }
 
+// The pre-Kea-1.0 syntax for the hooks libraries was a simple list, e.g.
+//
+//      ["hook-lib-1.so", "hook-lib-2.so", ... ]
+//
+// With Kea 1.0,. the sytntax was altered to allow for parameters to be
+// specified: instead of a list of strings, it is a list of maps, with
+// each map holding an element "library" giving the name of the library and
+// an element "parameters" listing the library's parameters, e.g.
+//
+//      [
+//          {
+//              "library": "hook-lib-1.so",
+//              "parameters": {
+//                  "alpha": "a string",
+//                  "beta": 42
+//              }
+//          },
+//          {
+//              "library": "hook-lib-2.so",
+//                  :
+//          }
+//      ]
+//
+// Kea 1.0 has not yet implemented parameters, so additional elements in the
+// map are ignored.
+//
+// The following code eases the transition between the two syntaxes as both
+// are allowed, although the old syntax gives a warning message.
 void
 HooksLibrariesParser::build(ConstElementPtr value) {
     // Initialize.
     libraries_.clear();
     changed_ = false;
 
-    // Extract the list of libraries.
-    BOOST_FOREACH(ConstElementPtr iface, value->listValue()) {
-        string libname = iface->str();
-        boost::erase_all(libname, "\"");
-        libraries_.push_back(libname);
+    // Iterate through the list of values to see what is there.  This list
+    // should be all strings (old syntax) or all maps (new syntax).
+    bool all_string = true;
+    bool all_map = true;
+    BOOST_FOREACH(ConstElementPtr library_entry, value->listValue()) {
+        if (library_entry->getType() == Element::string) {
+            all_map = false;
+        } else if  (library_entry->getType() == Element::map) {
+            all_string = false;
+        } else {
+            all_map = false;
+            all_string = false;
+        }
+    }
+
+    if (all_string && all_map) {
+        // The list must be empty.  This is valid in both syntaxes: do nothing
+        // as this is taken care of below.
+
+    } else if (all_string) {
+        // This is the old (pre Kea-1.0 syntax).  Warn about it, but
+        // otherwise accept it.
+        LOG_WARN(dhcpsrv_logger, DHCPSRV_HOOK_DEPRECATED_SYNTAX);
+
+        // Iterate through each entry in the list - this is just the library
+        // name.  Just remove quotes and add to the library list.
+        BOOST_FOREACH(ConstElementPtr library_entry, value->listValue()) {
+            string libname = library_entry->stringValue();
+            boost::erase_all(libname, "\"");
+            libraries_.push_back(libname);
+        }
+
+    } else if (all_map) {
+        // This is the new syntax.  Iterate through it and get each map.
+        BOOST_FOREACH(ConstElementPtr library_entry, value->listValue()) {
+            // Iterate iterate through each element in the map.  We check
+            // whether we have found a library element.
+            bool lib_found = false;
+            BOOST_FOREACH(ConfigPair entry_item, library_entry->mapValue()) {
+                if (entry_item.first == "library") {
+                    // Name of the library. Add it to the list after trimming
+                    // quotes.
+                    string libname = (entry_item.second)->stringValue();
+                    boost::erase_all(libname, "\"");
+                    libraries_.push_back(libname);
+
+                    // ... and we have found the library name.
+                    lib_found = true;
+                }
+            }
+            if (! lib_found) {
+                isc_throw(DhcpConfigError, "hooks library configuration error:"
+                    " one or more hooks-libraries elements are missing the "
+                    " name of the library");
+            }
+        }
+    } else {
+        isc_throw(DhcpConfigError, "hooks library configuration error:"
+            " list of hooks libraries is not a list of maps, each map"
+            " containing a 'library' element");
     }
 
     // Check if the list of libraries has changed.  If not, nothing is done