]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#916] Checkpoint before regen
authorFrancis Dupont <fdupont@isc.org>
Fri, 29 May 2020 15:47:16 +0000 (17:47 +0200)
committerFrancis Dupont <fdupont@isc.org>
Wed, 8 Jul 2020 12:32:45 +0000 (14:32 +0200)
28 files changed:
doc/sphinx/arm/config.rst
doc/sphinx/arm/dhcp4-srv.rst
doc/sphinx/arm/dhcp6-srv.rst
doc/sphinx/arm/logging.rst
src/bin/dhcp4/ctrl_dhcp4_srv.cc
src/bin/dhcp4/dhcp4_lexer.ll
src/bin/dhcp4/dhcp4_parser.yy
src/bin/dhcp4/parser_context.cc
src/bin/dhcp4/parser_context.h
src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dhcp4_process_tests.sh.in
src/bin/dhcp4/tests/kea_controller_unittest.cc
src/bin/dhcp4/tests/parser_unittest.cc
src/bin/dhcp6/ctrl_dhcp6_srv.cc
src/bin/dhcp6/dhcp6_lexer.ll
src/bin/dhcp6/dhcp6_parser.yy
src/bin/dhcp6/parser_context.cc
src/bin/dhcp6/parser_context.h
src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
src/bin/dhcp6/tests/dhcp6_process_tests.sh.in
src/bin/dhcp6/tests/kea_controller_unittest.cc
src/bin/dhcp6/tests/parser_unittest.cc
src/lib/process/d_controller.cc
src/lib/process/d_controller.h
src/lib/process/daemon.cc
src/lib/process/daemon.h
src/lib/process/process_messages.mes
src/lib/process/tests/daemon_unittest.cc

index 892e7b67c38f85423736d5264ba4e4e1090bc1e9..785bb9fffc3d781d5124048402a8b69d8ac2004e 100644 (file)
@@ -91,11 +91,11 @@ directory.
    "loggers" object) moved inside the configuration objects (maps) for the
    respective Kea modules. For example: the "Dhcp4" map contains the
    "loggers" object specifying logging configuration for the DHCPv4
-   server. Backward compatibility is maintained until at least Kea 1.7.0
+   server. Backward compatibility is maintained until Kea 1.7.8
    release; it will be possible to specify the "Logging" object at the top
    configuration level and "loggers" objects at the module configuration
-   level. Ultimately, support for the top-level "Logging" object will be
-   removed.
+   level. Finally, support for the top-level "Logging" object was
+   removed in Kea 1.7.0.
 
    The specification of several supported elements (e.g. "Dhcp4",
    "Dhcp6") in a single configuration file can be confusing and works
index 99950c67f5a5789d9a70b5a600d455bda24295d7..e58679a48803a76f42144740e300f122865d1420 100644 (file)
@@ -148,12 +148,9 @@ above this object is called ``Dhcp4``.
 
    In the current Kea release it is possible to specify configurations
    of multiple modules within a single configuration file, but this is
-   not recommended and support for it will be removed in a future
-   release. The only object, besides the one specifying module
-   configuration, which can be (and usually was) included in the same file
-   is ``Logging``. However, we don't include this object in the example
-   above for clarity; its content, the list of loggers, should now be
-   inside the ``Dhcp4`` object instead of the deprecated object.
+   not recommended and support for it was removed in 1.7.9 release,
+   including the ``Logging`` object: its previous content, the list
+   of loggers, must now inside be the ``Dhcp4`` object.
 
 The Dhcp4 configuration starts with the ``"Dhcp4": {`` line and ends
 with the corresponding closing brace (in the above example, the brace
index b2be666198d7efebe11e308cec41e2f8c881e78d..5ea4df359f9375e18b18cfbf55508ca5bda32d82 100644 (file)
@@ -149,12 +149,9 @@ above this object is called ``Dhcp6``.
 
    In the current Kea release it is possible to specify configurations
    of multiple modules within a single configuration file, but this is
-   not recommended and support for it will be removed in a future
-   release. The only object, besides the one specifying module
-   configuration, which can be (and usually was) included in the same file
-   is ``Logging``. However, we don't include this object in the example
-   above for clarity; its content, the list of loggers, should now be
-   inside the ``Dhcp6`` object instead of this deprecated object.
+   not recommended and support for it was removed in 1.7.9 release,
+   including the ``Logging`` object: its previous content, the list
+   of loggers, must now inside be the ``Dhcp6`` object.
 
 The Dhcp6 configuration starts with the ``"Dhcp6": {`` line and ends
 with the corresponding closing brace (in the above example, the brace
index 03017874aa17aa9fa5a82ec0aac7e49c61f8c386..70593239098d58bb248a24aef411e6ea924fc498 100644 (file)
@@ -17,8 +17,8 @@ useful when debugging a problem.
 
 The logging system in Kea is configured through the loggers entry in the
 server section of your configuration file. In previous Kea releases this
-entry was in an independent Logging section; this is still supported for
-backward compatibility.
+entry was in an independent Logging section; this was still supported
+for backward compatibility until Kea 1.7.8 included.
 
 Loggers
 -------
index fa4096f00f5d6b036f76e5f78157dbbf7fd0d646..30a5a0fd59d351ba80e22890dbee354b5e9a0aff 100644 (file)
@@ -343,7 +343,6 @@ ControlledDhcpv4Srv::commandConfigSetHandler(const string&,
 
     // Command arguments are expected to be:
     // { "Dhcp4": { ... } }
-    // The Logging component is supported by backward compatiblity.
     if (!args) {
         message = "Missing mandatory 'arguments' parameter.";
     } else {
@@ -355,6 +354,25 @@ ControlledDhcpv4Srv::commandConfigSetHandler(const string&,
         }
     }
 
+    // Check unsupported objects.
+    if (message.empty()) {
+        for (auto obj : args->mapValue()) {
+            const string& obj_name = obj.first;
+            if (obj_name != "Dhcp4") {
+                LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_UNSUPPORTED_OBJECT)
+                    .arg(obj_name);
+                if (message.empty()) {
+                    message = "Unsupported '" + obj_name + "' parameter";
+                } else {
+                    message += " (and '" + obj_name + "')";
+                }
+            }
+        }
+        if (!message.empty()) {
+            message += ".";
+        }
+    }
+
     if (!message.empty()) {
         // Something is amiss with arguments, return a failure response.
         ConstElementPtr result = isc::config::createAnswer(status_code,
@@ -375,20 +393,6 @@ ControlledDhcpv4Srv::commandConfigSetHandler(const string&,
     // configuration attempts.
     CfgMgr::instance().rollback();
 
-    // Check deprecated, obsolete or unknown (aka unsupported) objects.
-    list<string> unsupported;
-    for (auto obj : args->mapValue()) {
-        const string& obj_name = obj.first;
-        if ((obj_name == "Dhcp4") || (obj_name == "Logging")) {
-            continue;
-        }
-        unsupported.push_back(obj_name);
-    }
-
-    // Relocate Logging: if there is a global Logging object takes its
-    // loggers entry, move the entry to Dhcp4 and remove now empty Logging.
-    Daemon::relocateLogging(args, "Dhcp4");
-
     // Parse the logger configuration explicitly into the staging config.
     // Note this does not alter the current loggers, they remain in
     // effect until we apply the logging config below.  If no logging
@@ -399,15 +403,6 @@ ControlledDhcpv4Srv::commandConfigSetHandler(const string&,
     // out what exactly is wrong with the new config in case of problems.
     CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
 
-    // Log unsupported objects.
-    if (!unsupported.empty()) {
-        for (auto name : unsupported) {
-            LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_UNSUPPORTED_OBJECT).arg(name);
-        }
-
-        // Will return an error in a future version.
-    }
-
     // Now we configure the server proper.
     ConstElementPtr result = processConfig(dhcp4);
 
@@ -452,6 +447,25 @@ ControlledDhcpv4Srv::commandConfigTestHandler(const string&,
         }
     }
 
+    // Check unsupported objects.
+    if (message.empty()) {
+        for (auto obj : args->mapValue()) {
+            const string& obj_name = obj.first;
+            if (obj_name != "Dhcp4") {
+                LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_UNSUPPORTED_OBJECT)
+                    .arg(obj_name);
+                if (message.empty()) {
+                    message = "Unsupported '" + obj_name + "' parameter";
+                } else {
+                    message += " (and '" + obj_name + "')";
+                }
+            }
+        }
+        if (!message.empty()) {
+            message += ".";
+        }
+    }
+
     if (!message.empty()) {
         // Something is amiss with arguments, return a failure response.
         ConstElementPtr result = isc::config::createAnswer(status_code,
@@ -459,13 +473,6 @@ ControlledDhcpv4Srv::commandConfigTestHandler(const string&,
         return (result);
     }
 
-    // Check obsolete objects.
-
-    // Relocate Logging. Note this allows to check the loggers configuration.
-    Daemon::relocateLogging(args, "Dhcp4");
-
-    // Log obsolete objects and return an error.
-
     // stop thread pool (if running)
     MultiThreadingCriticalSection cs;
 
index de71b4f34350e7a843d02b5d97ace2a160c23597..d4a753c241dbf0844d080ce3c0d33a5a2323864a 100644 (file)
@@ -137,8 +137,6 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
             return isc::dhcp::Dhcp4Parser::make_SUB_DHCP_DDNS(driver.loc_);
         case Parser4Context::PARSER_CONFIG_CONTROL:
             return isc::dhcp::Dhcp4Parser::make_SUB_CONFIG_CONTROL(driver.loc_);
-        case Parser4Context::PARSER_LOGGING:
-            return isc::dhcp::Dhcp4Parser::make_SUB_LOGGING(driver.loc_);
         }
     }
 %}
@@ -1036,19 +1034,9 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 }
 
 
-\"Logging\" {
-    switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONFIG:
-        return isc::dhcp::Dhcp4Parser::make_LOGGING(driver.loc_);
-    default:
-        return isc::dhcp::Dhcp4Parser::make_STRING("Logging", driver.loc_);
-    }
-}
-
 \"loggers\" {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::DHCP4:
-    case isc::dhcp::Parser4Context::LOGGING:
         return isc::dhcp::Dhcp4Parser::make_LOGGERS(driver.loc_);
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("loggers", driver.loc_);
@@ -1761,33 +1749,6 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     return isc::dhcp::Dhcp4Parser::make_STRING(tmp, driver.loc_);
 }
 
-\"Dhcp6\"  {
-    switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONFIG:
-        return isc::dhcp::Dhcp4Parser::make_DHCP6(driver.loc_);
-    default:
-        return isc::dhcp::Dhcp4Parser::make_STRING("Dhcp6", driver.loc_);
-    }
-}
-
-\"DhcpDdns\" {
-    switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONFIG:
-        return isc::dhcp::Dhcp4Parser::make_DHCPDDNS(driver.loc_);
-    default:
-        return isc::dhcp::Dhcp4Parser::make_STRING("DhcpDdns", driver.loc_);
-    }
-}
-
-\"Control-agent\" {
-    switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONFIG:
-        return isc::dhcp::Dhcp4Parser::make_CONTROL_AGENT(driver.loc_);
-    default:
-        return isc::dhcp::Dhcp4Parser::make_STRING("Control-agent", driver.loc_);
-    }
-}
-
 \"4o6-interface\" {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::SUBNET4:
index 8ad58216c0f95c48f54e0a850d7c74f7b23c3b5d..963deb9fc4f57d751523f0f88ec81d1ba0620086 100644 (file)
@@ -224,7 +224,6 @@ using namespace std;
   HOSTNAME_CHAR_SET "hostname-char-set"
   HOSTNAME_CHAR_REPLACEMENT "hostname-char-replacement"
 
-  LOGGING "Logging"
   LOGGERS "loggers"
   OUTPUT_OPTIONS "output_options"
   OUTPUT "output"
@@ -235,10 +234,6 @@ using namespace std;
   MAXVER "maxver"
   PATTERN "pattern"
 
-  DHCP6 "Dhcp6"
-  DHCPDDNS "DhcpDdns"
-  CONTROL_AGENT "Control-agent"
-
  // Not real tokens, just a way to signal what the parser is expected to
  // parse.
   TOPLEVEL_JSON
@@ -253,7 +248,6 @@ using namespace std;
   SUB_OPTION_DATA
   SUB_HOOKS_LIBRARY
   SUB_DHCP_DDNS
-  SUB_LOGGING
   SUB_CONFIG_CONTROL
 ;
 
@@ -292,7 +286,6 @@ start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json
      | SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data
      | SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
      | SUB_DHCP_DDNS { ctx.ctx_ = ctx.DHCP_DDNS; } sub_dhcp_ddns
-     | SUB_LOGGING { ctx.ctx_ = ctx.LOGGING; } sub_logging
      | SUB_CONFIG_CONTROL { ctx.ctx_ = ctx.CONFIG_CONTROL; } sub_config_control
      ;
 
@@ -400,8 +393,7 @@ unknown_map_entry: STRING COLON {
 };
 
 
-// This defines the top-level { } that holds Control-agent, Dhcp6, Dhcp4,
-// DhcpDdns or Logging objects.
+// This defines the top-level { } that holds Dhcp4 only object.
 syntax_map: LCURLY_BRACKET {
     // This code is executed when we're about to start parsing
     // the content of the map
@@ -416,24 +408,20 @@ syntax_map: LCURLY_BRACKET {
     ctx.require("Dhcp4", ctx.loc2pos(@1), ctx.loc2pos(@4));
 };
 
-// This represents top-level entries: Control-agent, Dhcp6, Dhcp4,
-// DhcpDdns, Logging
+// This represents top-level entries: Dhcp4
 global_objects: global_object
               | global_objects COMMA global_object
               ;
 
-// This represents a single top level entry, e.g. Dhcp4 or DhcpDdns.
+// This represents a single top level entry, e.g. Dhcp4.
 global_object: dhcp4_object
-             | logging_object
-             | dhcp6_json_object
-             | dhcpddns_json_object
-             | control_agent_json_object
-             | unknown_map_entry
              ;
 
 dhcp4_object: DHCP4 {
     // This code is executed when we're about to start parsing
     // the content of the map
+    // Prevent against duplicate.
+    ctx.unique("Dhcp4", ctx.loc2pos(@1));
     ElementPtr m(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->set("Dhcp4", m);
     ctx.stack_.push_back(m);
@@ -2299,29 +2287,6 @@ dep_hostname_char_replacement: HOSTNAME_CHAR_REPLACEMENT {
 };
 
 
-// JSON entries for Dhcp4 and DhcpDdns
-
-dhcp6_json_object: DHCP6 {
-    ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
-    ctx.stack_.back()->set("Dhcp6", $4);
-    ctx.leave();
-};
-
-dhcpddns_json_object: DHCPDDNS {
-    ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
-    ctx.stack_.back()->set("DhcpDdns", $4);
-    ctx.leave();
-};
-
-control_agent_json_object: CONTROL_AGENT {
-    ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
-    ctx.stack_.back()->set("Control-agent", $4);
-    ctx.leave();
-};
-
 // Config control information element
 
 config_control: CONFIG_CONTROL {
@@ -2369,41 +2334,8 @@ config_fetch_wait_time: CONFIG_FETCH_WAIT_TIME COLON INTEGER {
     ctx.stack_.back()->set("config-fetch-wait-time", value);
 };
 
-// --- logging entry -----------------------------------------
-
-// This defines the top level "Logging" object. It parses
-// the following "Logging": { ... }. The ... is defined
-// by logging_params
-logging_object: LOGGING {
-    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
-    ctx.stack_.back()->set("Logging", m);
-    ctx.stack_.push_back(m);
-    ctx.enter(ctx.LOGGING);
-} COLON LCURLY_BRACKET logging_params RCURLY_BRACKET {
-    ctx.stack_.pop_back();
-    ctx.leave();
-};
-
-sub_logging: LCURLY_BRACKET {
-    // Parse the Logging map
-    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
-    ctx.stack_.push_back(m);
-} logging_params RCURLY_BRACKET {
-    // parsing completed
-};
-
-// This defines the list of allowed parameters that may appear
-// in the top-level Logging object. It can either be a single
-// parameter or several parameters separated by commas.
-logging_params: logging_param
-              | logging_params COMMA logging_param
-              ;
-
-// There's currently only one parameter defined, which is "loggers".
-logging_param: loggers;
+// --- loggers entry -----------------------------------------
 
-// "loggers", the only parameter currently defined in "Logging" object,
-// is "loggers": [ ... ].
 loggers: LOGGERS {
     ElementPtr l(new ListElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->set("loggers", l);
@@ -2420,7 +2352,7 @@ loggers_entries: logger_entry
                | loggers_entries COMMA logger_entry
                ;
 
-// This defines a single entry defined in loggers in Logging.
+// This defines a single entry defined in loggers.
 logger_entry: LCURLY_BRACKET {
     ElementPtr l(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->add(l);
index 5c03e944fc7207cf66b86c9574c425a0bff02441..6a9f21aa013f81903872131a95d90ea281bc2259 100644 (file)
@@ -111,6 +111,18 @@ Parser4Context::require(const std::string& name,
     }
 }
 
+void
+Parser4Context::unique(const std::string& name,
+                       isc::data::Element::Position loc)
+{
+    ConstElementPtr value = stack_.back()->get(name);
+    if (value) {
+        isc_throw(Dhcp4ParseError, loc << ": duplicate " << name
+                  << " entries in " << contextName()
+                  << " map (previous at " << value->getPosition() << ")");
+    }
+}
+
 void
 Parser4Context::enter(const ParserContext& ctx)
 {
@@ -140,8 +152,6 @@ Parser4Context::contextName()
         return ("toplevel");
     case DHCP4:
         return ("Dhcp4");
-    case LOGGING:
-        return ("Logging");
     case INTERFACES_CONFIG:
         return ("interfaces-config");
     case DHCP_SOCKET_TYPE:
index ccbcd59d65eff217575906534d2067db534af0b3..61ae67f772b729be39b092ed29c9e7213c2bfedc 100644 (file)
@@ -90,9 +90,6 @@ public:
 
         /// This will parse the input as config-control.
         PARSER_CONFIG_CONTROL,
-
-        /// This will parse the content of Logging.
-        PARSER_LOGGING
     } ParserType;
 
     /// @brief Default constructor.
@@ -192,28 +189,34 @@ public:
     ///
     /// @param name name of the parameter to check
     /// @param open_loc location of the opening curly bracket
-    /// @param close_loc ocation of the closing curly bracket
+    /// @param close_loc location of the closing curly bracket
     /// @throw Dhcp4ParseError
     void require(const std::string& name,
                  isc::data::Element::Position open_loc,
                  isc::data::Element::Position close_loc);
 
+    /// @brief Check if a parameter is already present
+    ///
+    /// Check if a parameter is already present in the map at the top
+    /// of the stack and raise an error when it is.
+    ///
+    /// @param name name of the parameter to check
+    /// @param loc location of the current parameter
+    /// @throw Dhcp4ParseError
+    void unique(const std::string& name,
+                isc::data::Element::Position loc);
+
     /// @brief Defines syntactic contexts for lexical tie-ins
     typedef enum {
         ///< This one is used in pure JSON mode.
         NO_KEYWORD,
 
-        ///< Used while parsing top level (that contains Dhcp4, Logging and others)
+        ///< Used while parsing top level (that contains Dhcp4)
         CONFIG,
 
         ///< Used while parsing content of Dhcp4.
         DHCP4,
 
-        // not yet Dhcp6, DhcpDdns,
-
-        ///< Used while parsing content of Logging
-        LOGGING,
-
         /// Used while parsing Dhcp4/interfaces structures.
         INTERFACES_CONFIG,
 
index 0f194833ceed48dcc9af09a70d1d0fa07f81fb84..107caea4b1380bb4c194be70e4ebdf162f7db790 100644 (file)
@@ -768,15 +768,13 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configSet) {
     string control_socket_footer =
         "\"   \n} \n";
     string logger_txt =
-        "    \"Logging\": { \n"
-        "        \"loggers\": [ { \n"
+        "       ,\"loggers\": [ { \n"
         "            \"name\": \"kea\", \n"
         "            \"severity\": \"FATAL\", \n"
         "            \"output_options\": [{ \n"
         "                \"output\": \"/dev/null\" \n"
         "            }] \n"
-        "        }] \n"
-        "    } \n";
+        "        }] \n";
 
     std::ostringstream os;
 
@@ -791,9 +789,8 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configSet) {
         << control_socket_header
         << socket_path_
         << control_socket_footer
-        << "}\n"                      // close dhcp4
-        << ","
         << logger_txt
+        << "}\n"                      // close dhcp4
         << "}}";
 
     // Send the config-set command
@@ -823,7 +820,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configSet) {
         << socket_path_
         << control_socket_footer
         << "}\n"                      // close dhcp4
-        "}}";
+        << "}}";
 
     // Send the config-set command
     sendUnixCommand(os.str(), response);
@@ -945,15 +942,13 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configTest) {
     string control_socket_footer =
         "\"   \n} \n";
     string logger_txt =
-        "    \"Logging\": { \n"
-        "        \"loggers\": [ { \n"
+        "       ,\"loggers\": [ { \n"
         "            \"name\": \"kea\", \n"
         "            \"severity\": \"FATAL\", \n"
         "            \"output_options\": [{ \n"
         "                \"output\": \"/dev/null\" \n"
         "            }] \n"
-        "        }] \n"
-        "    } \n";
+        "        }] \n";
 
     std::ostringstream os;
 
@@ -966,9 +961,8 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configTest) {
         << control_socket_header
         << socket_path_
         << control_socket_footer
-        << "}\n"                      // close dhcp4
-        << ","
         << logger_txt
+        << "}\n"                      // close dhcp4
         << "}}";
 
     // Send the config-set command
@@ -995,7 +989,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configTest) {
         << socket_path_
         << control_socket_footer
         << "}\n"                      // close dhcp4
-        "}}";
+        << "}}";
 
     // Send the config-test command
     sendUnixCommand(os.str(), response);
index b85f520dc20fb4def5ce84cf19fff2d3023c6915..1a996b0f396b5f53a6649c574416f399fdc24d22 100644 (file)
@@ -39,11 +39,7 @@ CONFIG="{
        \"dhcp-ddns\": {
             \"enable-updates\": true,
             \"qualifying-suffix\": \"\"
-        }
-    },
-
-    \"Logging\":
-    {
+        },
         \"loggers\": [
         {
             \"name\": \"kea-dhcp4\",
@@ -77,11 +73,7 @@ CONFIG_BAD_SYNTAX="{
         {
             \"subnet\": \"10.0.0.0/8\",
             \"pool\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]
-        } ]
-    },
-
-    \"Logging\":
-    {
+        } ],
         \"loggers\": [
         {
             \"name\": \"kea-dhcp4\",
@@ -116,11 +108,7 @@ CONFIG_BAD_VALUES="{
         {
             \"subnet\": \"10.0.0.0/8\",
             \"pools\": [ { \"pool\": \"192.168.0.10-192.168.0.100\" } ]
-        } ]
-    },
-
-    \"Logging\":
-    {
+        } ],
         \"loggers\": [
         {
             \"name\": \"kea-dhcp4\",
@@ -155,11 +143,7 @@ CONFIG_INVALID="{
         {
             \"subnet\": \"10.0.0.0/8\",
             \"pool\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]
-        } ]
-    },
-
-    \"Logging\":
-    {
+        } ],
         \"loggers\": [
         {
             \"name\": \"kea-dhcp4\",
index f006611b2138735e95fca0ca48d7d9f4f1441bbe..c8b43945abca9bb627f974272f8244a9a119ee5a 100644 (file)
@@ -465,31 +465,6 @@ TEST_F(JSONFileBackendTest, jsonFile) {
     EXPECT_EQ(Lease::TYPE_V4, pools3.at(0)->getType());
 }
 
-// This test verifies that the configurations for various servers
-// can coexist and that the DHCPv4 configuration parsers will simply
-// ignore them.
-TEST_F(JSONFileBackendTest, serverConfigurationsCoexistence) {
-    std::string config = "{ \"Dhcp4\": {"
-        "\"rebind-timer\": 2000, "
-        "\"renew-timer\": 1000, \n"
-        "\"valid-lifetime\": 4000 }, "
-        "\"Dhcp6\": { },"
-        "\"DhcpDdns\": { },"
-        "\"Control-agent\": { }"
-        "}";
-
-    writeFile(TEST_FILE, config);
-
-    // Now initialize the server
-    boost::scoped_ptr<ControlledDhcpv4Srv> srv;
-    ASSERT_NO_THROW(
-        srv.reset(new ControlledDhcpv4Srv(0))
-    );
-
-    // And configure it using the config file.
-    EXPECT_NO_THROW(srv->init(TEST_FILE));
-}
-
 // This test checks if configuration can be read from a JSON file
 // using hash (#) line comments
 TEST_F(JSONFileBackendTest, hashComments) {
index 8e6867bf0cb89a04f700aeded10cdc6a58ae851a..ae03c8ba96df5264f98e54138040fe2377d143d9 100644 (file)
@@ -508,26 +508,28 @@ TEST(ParserTest, errors) {
               "expecting }");
     testError("{ 123 }\n",
               Parser4Context::PARSER_DHCP4,
-              "<string>:1.3-5: syntax error, unexpected integer");
+              "<string>:1.3-5: syntax error, unexpected integer, "
+              "expecting Dhcp4");
     testError("{ \"foo\" }\n",
               Parser4Context::PARSER_JSON,
               "<string>:1.9: syntax error, unexpected }, "
               "expecting :");
     testError("{ \"foo\" }\n",
               Parser4Context::PARSER_DHCP4,
-              "<string>:1.9: syntax error, unexpected }, expecting :");
+              "<string>:1.3-7: syntax error, unexpected constant string, "
+              "expecting Dhcp4");
     testError("{ \"foo\":null }\n",
               Parser4Context::PARSER_DHCP4,
-              "<string>:1.3-7: got unexpected keyword "
-              "\"foo\" in toplevel map.");
+              "<string>:1.3-7: syntax error, unexpected constant string, "
+              "expecting Dhcp4");
+    testError("{ \"Logging\":null }\n",
+              Parser4Context::PARSER_DHCP4,
+              "<string>:1.3-11: syntax error, unexpected constant string, "
+              "expecting Dhcp4");
     testError("{ \"Dhcp4\" }\n",
               Parser4Context::PARSER_DHCP4,
               "<string>:1.11: syntax error, unexpected }, "
               "expecting :");
-    testError("{ \"Dhcp6\":[]\n",
-              Parser4Context::PARSER_DHCP4,
-              "<string>:2.1: syntax error, unexpected end of file, "
-              "expecting \",\" or }");
     testError("{}{}\n",
               Parser4Context::PARSER_JSON,
               "<string>:1.3: syntax error, unexpected {, "
@@ -606,6 +608,15 @@ TEST(ParserTest, errors) {
               Parser4Context::PARSER_DHCP4,
               "<string>:3.3-11: duplicate user-context/comment entries "
               "(previous at <string>:2:19)");
+
+    // duplicate Dhcp4 entries
+    testError("{ \"Dhcp4\":{\n"
+              "  \"comment\": \"first\" },\n"
+              "  \"Dhcp4\":{\n"
+              "  \"comment\": \"second\" }}\n",
+              Parser4Context::PARSER_DHCP4,
+              "<string>:3:3: duplicate Dhcp4 entries in toplevel map "
+              "(previous at <string>:1:3)");
 }
 
 // Check unicode escapes
@@ -649,6 +660,6 @@ TEST(ParserTest, unicodeSlash) {
     EXPECT_EQ("////", result->stringValue());
 }
 
-};
-};
-};
+}
+}
+}
index 282cc9e4b16d1ade348491f6a972bacdd04b0ba2..3ecd2880727063bb33553d001547ea6399c00422 100644 (file)
@@ -358,6 +358,25 @@ ControlledDhcpv6Srv::commandConfigSetHandler(const string&,
         }
     }
 
+    // Check unsupported objects.
+    if (message.empty()) {
+        for (auto obj : args->mapValue()) {
+            const string& obj_name = obj.first;
+            if (obj_name != "Dhcp6") {
+                LOG_ERROR(dhcp6_logger, DHCP6_CONFIG_UNSUPPORTED_OBJECT)
+                    .arg(obj_name);
+                if (message.empty()) {
+                    message = "Unsupported '" + obj_name + "' parameter";
+                } else {
+                    message += " (and '" + obj_name + "')";
+                }
+            }
+        }
+        if (!message.empty()) {
+            message += ".";
+        }
+    }
+
     if (!message.empty()) {
         // Something is amiss with arguments, return a failure response.
         ConstElementPtr result = isc::config::createAnswer(status_code,
@@ -378,20 +397,6 @@ ControlledDhcpv6Srv::commandConfigSetHandler(const string&,
     // configuration attempts.
     CfgMgr::instance().rollback();
 
-    // Check deprecated, obsolete or unknown (aka unsupported) objects.
-    list<string> unsupported;
-    for (auto obj : args->mapValue()) {
-        const string& obj_name = obj.first;
-        if ((obj_name == "Dhcp6") || (obj_name == "Logging")) {
-            continue;
-        }
-        unsupported.push_back(obj_name);
-    }
-
-    // Relocate Logging: if there is a global Logging object takes its
-    // loggers entry, move the entry to Dhcp6 and remove now empty Logging.
-    Daemon::relocateLogging(args, "Dhcp6");
-
     // Parse the logger configuration explicitly into the staging config.
     // Note this does not alter the current loggers, they remain in
     // effect until we apply the logging config below.  If no logging
@@ -402,15 +407,6 @@ ControlledDhcpv6Srv::commandConfigSetHandler(const string&,
     // out what exactly is wrong with the new config in case of problems.
     CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
 
-    // Log unsupported objects.
-    if (!unsupported.empty()) {
-        for (auto name : unsupported) {
-            LOG_ERROR(dhcp6_logger, DHCP6_CONFIG_UNSUPPORTED_OBJECT).arg(name);
-        }
-
-        // Will return an error in a future version.
-    }
-
     // Now we configure the server proper.
     ConstElementPtr result = processConfig(dhcp6);
 
@@ -455,6 +451,25 @@ ControlledDhcpv6Srv::commandConfigTestHandler(const string&,
         }
     }
 
+    // Check unsupported objects.
+    if (message.empty()) {
+        for (auto obj : args->mapValue()) {
+            const string& obj_name = obj.first;
+            if (obj_name != "Dhcp6") {
+                LOG_ERROR(dhcp6_logger, DHCP6_CONFIG_UNSUPPORTED_OBJECT)
+                    .arg(obj_name);
+                if (message.empty()) {
+                    message = "Unsupported '" + obj_name + "' parameter";
+                } else {
+                    message += " (and '" + obj_name + "')";
+                }
+            }
+        }
+        if (!message.empty()) {
+            message += ".";
+        }
+    }
+
     if (!message.empty()) {
         // Something is amiss with arguments, return a failure response.
         ConstElementPtr result = isc::config::createAnswer(status_code,
@@ -462,13 +477,6 @@ ControlledDhcpv6Srv::commandConfigTestHandler(const string&,
         return (result);
     }
 
-    // Check obsolete objects.
-
-    // Relocate Logging. Note this allows to check the loggers configuration.
-    Daemon::relocateLogging(args, "Dhcp6");
-
-    // Log obsolete objects and return an error.
-
     // stop thread pool (if running)
     MultiThreadingCriticalSection cs;
 
index 36d8c32f1bb207ee4e23e2bfbbda155fc0684ab1..0475a286cbca091fa64f5952db8af4db8ac9185f 100644 (file)
@@ -139,8 +139,6 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
             return isc::dhcp::Dhcp6Parser::make_SUB_DHCP_DDNS(driver.loc_);
         case Parser6Context::PARSER_CONFIG_CONTROL:
             return isc::dhcp::Dhcp6Parser::make_SUB_CONFIG_CONTROL(driver.loc_);
-        case Parser6Context::PARSER_LOGGING:
-            return isc::dhcp::Dhcp6Parser::make_SUB_LOGGING(driver.loc_);
         }
     }
 %}
@@ -1362,19 +1360,9 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
-\"Logging\" {
-    switch(driver.ctx_) {
-    case isc::dhcp::Parser6Context::CONFIG:
-        return isc::dhcp::Dhcp6Parser::make_LOGGING(driver.loc_);
-    default:
-        return isc::dhcp::Dhcp6Parser::make_STRING("Logging", driver.loc_);
-    }
-}
-
 \"loggers\" {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::DHCP6:
-    case isc::dhcp::Parser6Context::LOGGING:
         return isc::dhcp::Dhcp6Parser::make_LOGGERS(driver.loc_);
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("loggers", driver.loc_);
@@ -1919,33 +1907,6 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
-\"Dhcp4\" {
-    switch(driver.ctx_) {
-    case isc::dhcp::Parser6Context::CONFIG:
-        return isc::dhcp::Dhcp6Parser::make_DHCP4(driver.loc_);
-    default:
-        return isc::dhcp::Dhcp6Parser::make_STRING("Dhcp4", driver.loc_);
-    }
-}
-
-\"DhcpDdns\" {
-    switch(driver.ctx_) {
-    case isc::dhcp::Parser6Context::CONFIG:
-        return isc::dhcp::Dhcp6Parser::make_DHCPDDNS(driver.loc_);
-    default:
-        return isc::dhcp::Dhcp6Parser::make_STRING("DhcpDdns", driver.loc_);
-    }
-}
-
-\"Control-agent\" {
-    switch(driver.ctx_) {
-    case isc::dhcp::Parser6Context::CONFIG:
-        return isc::dhcp::Dhcp6Parser::make_CONTROL_AGENT(driver.loc_);
-    default:
-        return isc::dhcp::Dhcp6Parser::make_STRING("Control-agent", driver.loc_);
-    }
-}
-
 {JSONString} {
     /* A string has been matched. It contains the actual string and single quotes.
        We need to get those quotes out of the way and just use its content, e.g.
index 554a4b4e3ad243a8a1639a5447f7f0fcd55cd1f5..88f0ca9d814d8de7d07f38c27591d2c47c714c48 100644 (file)
@@ -230,7 +230,6 @@ using namespace std;
   HOSTNAME_CHAR_SET "hostname-char-set"
   HOSTNAME_CHAR_REPLACEMENT "hostname-char-replacement"
 
-  LOGGING "Logging"
   LOGGERS "loggers"
   OUTPUT_OPTIONS "output_options"
   OUTPUT "output"
@@ -241,10 +240,6 @@ using namespace std;
   MAXVER "maxver"
   PATTERN "pattern"
 
-  DHCP4 "Dhcp4"
-  DHCPDDNS "DhcpDdns"
-  CONTROL_AGENT "Control-agent"
-
  // Not real tokens, just a way to signal what the parser is expected to
  // parse.
   TOPLEVEL_JSON
@@ -260,7 +255,6 @@ using namespace std;
   SUB_OPTION_DATA
   SUB_HOOKS_LIBRARY
   SUB_DHCP_DDNS
-  SUB_LOGGING
   SUB_CONFIG_CONTROL
 ;
 
@@ -299,7 +293,6 @@ start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json
      | SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data
      | SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
      | SUB_DHCP_DDNS { ctx.ctx_ = ctx.DHCP_DDNS; } sub_dhcp_ddns
-     | SUB_LOGGING { ctx.ctx_ = ctx.LOGGING; } sub_logging
      | SUB_CONFIG_CONTROL { ctx.ctx_ = ctx.CONFIG_CONTROL; } sub_config_control
      ;
 
@@ -407,8 +400,7 @@ unknown_map_entry: STRING COLON {
 };
 
 
-// This defines the top-level { } that holds Control-agent, Dhcp6, Dhcp4,
-// DhcpDdns or Logging objects.
+// This defines the top-level { } that holds Dhcp6 only object.
 syntax_map: LCURLY_BRACKET {
     // This code is executed when we're about to start parsing
     // the content of the map
@@ -423,24 +415,20 @@ syntax_map: LCURLY_BRACKET {
     ctx.require("Dhcp6", ctx.loc2pos(@1), ctx.loc2pos(@4));
 };
 
-// This represents top-level entries: Control-agent, Dhcp6, Dhcp4,
-// DhcpDdns, Logging
+// This represents top-level entries: Dhcp6
 global_objects: global_object
               | global_objects COMMA global_object
               ;
 
-// This represents a single top level entry, e.g. Dhcp6 or DhcpDdns.
+// This represents a single top level entry, e.g. Dhcp6.
 global_object: dhcp6_object
-             | logging_object
-             | dhcp4_json_object
-             | dhcpddns_json_object
-             | control_agent_json_object
-             | unknown_map_entry
              ;
 
 dhcp6_object: DHCP6 {
     // This code is executed when we're about to start parsing
     // the content of the map
+    // Prevent against duplicate.
+    ctx.unique("Dhcp6", ctx.loc2pos(@1));
     ElementPtr m(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->set("Dhcp6", m);
     ctx.stack_.push_back(m);
@@ -2418,29 +2406,6 @@ dep_hostname_char_replacement: HOSTNAME_CHAR_REPLACEMENT {
 };
 
 
-// JSON entries for Dhcp4 and DhcpDdns
-
-dhcp4_json_object: DHCP4 {
-    ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
-    ctx.stack_.back()->set("Dhcp4", $4);
-    ctx.leave();
-};
-
-dhcpddns_json_object: DHCPDDNS {
-    ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
-    ctx.stack_.back()->set("DhcpDdns", $4);
-    ctx.leave();
-};
-
-control_agent_json_object: CONTROL_AGENT {
-    ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
-    ctx.stack_.back()->set("Control-agent", $4);
-    ctx.leave();
-};
-
 // Config control information element
 
 config_control: CONFIG_CONTROL {
@@ -2488,41 +2453,8 @@ config_fetch_wait_time: CONFIG_FETCH_WAIT_TIME COLON INTEGER {
     ctx.stack_.back()->set("config-fetch-wait-time", value);
 };
 
-// --- logging entry -----------------------------------------
-
-// This defines the top level "Logging" object. It parses
-// the following "Logging": { ... }. The ... is defined
-// by logging_params
-logging_object: LOGGING {
-    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
-    ctx.stack_.back()->set("Logging", m);
-    ctx.stack_.push_back(m);
-    ctx.enter(ctx.LOGGING);
-} COLON LCURLY_BRACKET logging_params RCURLY_BRACKET {
-    ctx.stack_.pop_back();
-    ctx.leave();
-};
-
-sub_logging: LCURLY_BRACKET {
-    // Parse the Logging map
-    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
-    ctx.stack_.push_back(m);
-} logging_params RCURLY_BRACKET {
-    // parsing completed
-};
-
-// This defines the list of allowed parameters that may appear
-// in the top-level Logging object. It can either be a single
-// parameter or several parameters separated by commas.
-logging_params: logging_param
-              | logging_params COMMA logging_param
-              ;
-
-// There's currently only one parameter defined, which is "loggers".
-logging_param: loggers;
+// --- loggers entry -----------------------------------------
 
-// "loggers", the only parameter currently defined in "Logging" object,
-// is "loggers": [ ... ].
 loggers: LOGGERS {
     ElementPtr l(new ListElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->set("loggers", l);
@@ -2539,7 +2471,7 @@ loggers_entries: logger_entry
                | loggers_entries COMMA logger_entry
                ;
 
-// This defines a single entry defined in loggers in Logging.
+// This defines a single entry defined in loggers.
 logger_entry: LCURLY_BRACKET {
     ElementPtr l(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->add(l);
index 3aaf5d84674c6b95444d32957ab9ff90e5170de6..ab0785fa3eb66e8a023af086d48a0e6065eed861 100644 (file)
@@ -111,6 +111,18 @@ Parser6Context::require(const std::string& name,
     }
 }
 
+void
+Parser6Context::unique(const std::string& name,
+                       isc::data::Element::Position loc)
+{
+    ConstElementPtr value = stack_.back()->get(name);
+    if (value) {
+        isc_throw(Dhcp6ParseError, loc << ": duplicate " << name
+                  << " entries in " << contextName()
+                  << " map (previous at " << value->getPosition() << ")");
+    }
+}
+
 void
 Parser6Context::enter(const ParserContext& ctx)
 {
@@ -140,8 +152,6 @@ Parser6Context::contextName()
         return ("toplevel");
     case DHCP6:
         return ("Dhcp6");
-    case LOGGING:
-        return ("Logging");
     case INTERFACES_CONFIG:
         return ("interfaces-config");
     case LEASE_DATABASE:
index 1e5a1260e97740f66be53aa8044f46ba485b5646..6175648966409dcae29ea2d87c5d91f9bfad245d 100644 (file)
@@ -93,10 +93,6 @@ public:
 
         /// This will parse the input as config-control.
         PARSER_CONFIG_CONTROL,
-
-        /// This will parse the content of Logging.
-        PARSER_LOGGING
-
     } ParserType;
 
     /// @brief Default constructor.
@@ -202,22 +198,28 @@ public:
                  isc::data::Element::Position open_loc,
                  isc::data::Element::Position close_loc);
 
+    /// @brief Check if a parameter is already present
+    ///
+    /// Check if a parameter is already present in the map at the top
+    /// of the stack and raise an error when it is.
+    ///
+    /// @param name name of the parameter to check
+    /// @param loc location of the current parameter
+    /// @throw Dhcp6ParseError
+    void unique(const std::string& name,
+                isc::data::Element::Position loc);
+
     /// @brief Defines syntactic contexts for lexical tie-ins
     typedef enum {
         ///< This one is used in pure JSON mode.
         NO_KEYWORD,
 
-        ///< Used while parsing top level (that contains Dhcp6, Logging and others)
+        ///< Used while parsing top level (that contains Dhcp6)
         CONFIG,
 
         ///< Used while parsing content of Dhcp6.
         DHCP6,
 
-        // not yet Dhcp4, DhcpDdns,
-
-        ///< Used while parsing content of Logging
-        LOGGING,
-
         /// Used while parsing Dhcp6/interfaces structures.
         INTERFACES_CONFIG,
 
index 081b78f494c9121d28684fc907715e06b995fa60..010e00a121d05ca34c822eec478f6799249771b1 100644 (file)
@@ -677,8 +677,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configSet) {
     string control_socket_footer =
         "\"   \n} \n";
     string logger_txt =
-        "    \"Logging\": { \n"
-        "        \"loggers\": [ { \n"
+        "       ,\"loggers\": [ { \n"
         "            \"name\": \"kea\", \n"
         "            \"severity\": \"FATAL\", \n"
         "            \"output_options\": [{ \n"
@@ -700,9 +699,8 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configSet) {
         << control_socket_header
         << socket_path_
         << control_socket_footer
-        << "}\n"                      // close dhcp6
-        << ","
         << logger_txt
+        << "}\n"                      // close dhcp6
         << "}}";
 
     // Send the config-set command
@@ -855,8 +853,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configTest) {
     string control_socket_footer =
         "\"   \n} \n";
     string logger_txt =
-        "    \"Logging\": { \n"
-        "        \"loggers\": [ { \n"
+        "       ,\"loggers\": [ { \n"
         "            \"name\": \"kea\", \n"
         "            \"severity\": \"FATAL\", \n"
         "            \"output_options\": [{ \n"
@@ -876,9 +873,8 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configTest) {
         << control_socket_header
         << socket_path_
         << control_socket_footer
-        << "}\n"                      // close dhcp6
-        << ","
         << logger_txt
+        << "}\n"                      // close dhcp6
         << "}}";
 
     // Send the config-set command
index fdf7ab1793b243d65d0a1260240c2b5279c567ef..df835c8be8e2351228d88934a3ed92bb6c579d39 100644 (file)
@@ -41,11 +41,7 @@ CONFIG="{
         \"dhcp-ddns\": {
             \"enable-updates\": true,
             \"qualifying-suffix\": \"\"
-        }
-    },
-
-    \"Logging\":
-    {
+        },
         \"loggers\": [
         {
             \"name\": \"kea-dhcp6\",
@@ -80,11 +76,7 @@ CONFIG_BAD_SYNTAX="{
         {
             \"subnet\": \"2001:db8:1::/64\",
             \"pool\": [ { \"pool\": \"2001:db8:1::10-2001:db8:1::100\" } ]
-        } ]
-    },
-
-    \"Logging\":
-    {
+        } ],
         \"loggers\": [
         {
             \"name\": \"kea-dhcp6\",
@@ -119,11 +111,7 @@ CONFIG_INVALID="{
         {
             \"subnet\": \"2001:db8:1::/64\",
             \"pool\": [ { \"pool\": \"2001:db8:1::10-2001:db8:1::100\" } ]
-        } ]
-    },
-
-    \"Logging\":
-    {
+        } ],
         \"loggers\": [
         {
             \"name\": \"kea-dhcp6\",
index 351455baaf083e70e3cf4134523998f9fd7ab9ed..4290f74da3858bac563bf07383f8920466e817ee 100644 (file)
@@ -450,32 +450,6 @@ TEST_F(JSONFileBackendTest, jsonFile) {
     EXPECT_EQ(Lease::TYPE_NA, pools3.at(0)->getType());
 }
 
-// This test verifies that the configurations for various servers
-// can coexist and that the DHCPv6 configuration parsers will simply
-// ignore them.
-TEST_F(JSONFileBackendTest, serverConfigurationsCoexistence) {
-    std::string config = "{ \"Dhcp6\": {"
-        "\"rebind-timer\": 2000, "
-        "\"renew-timer\": 1000, \n"
-        "\"preferred-lifetime\": 1000, \n"
-        "\"valid-lifetime\": 4000 }, "
-        "\"Dhcp4\": { },"
-        "\"DhcpDdns\": { },"
-        "\"Control-agent\": { }"
-        "}";
-
-    writeFile(TEST_FILE, config);
-
-    // Now initialize the server
-    boost::scoped_ptr<ControlledDhcpv6Srv> srv;
-    ASSERT_NO_THROW(
-        srv.reset(new ControlledDhcpv6Srv(0))
-    );
-
-    // And configure it using the config file.
-    EXPECT_NO_THROW(srv->init(TEST_FILE));
-}
-
 // This test checks if configuration can be read from a JSON file
 // using hash (#) line comments
 TEST_F(JSONFileBackendTest, hashComments) {
index 84ab706ec466beec8d2e5ec2c6e04aafef1fa744..07a3c3fa57de7f4f53dede4e8f51feb756b3ce4e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -498,26 +498,28 @@ TEST(ParserTest, errors) {
               "expecting }");
     testError("{ 123 }\n",
               Parser6Context::PARSER_DHCP6,
-              "<string>:1.3-5: syntax error, unexpected integer");
+              "<string>:1.3-5: syntax error, unexpected integer, "
+              "expecting Dhcp6");
     testError("{ \"foo\" }\n",
               Parser6Context::PARSER_JSON,
               "<string>:1.9: syntax error, unexpected }, "
               "expecting :");
     testError("{ \"foo\" }\n",
               Parser6Context::PARSER_DHCP6,
-              "<string>:1.9: syntax error, unexpected }, expecting :");
+              "<string>:1.3-7: syntax error, unexpected constant string, "
+              "expecting Dhcp6");
     testError("{ \"foo\":null }\n",
               Parser6Context::PARSER_DHCP6,
-              "<string>:1.3-7: got unexpected keyword "
-              "\"foo\" in toplevel map.");
+              "<string>:1.3-7: syntax error, unexpected constant string, "
+              "expecting Dhcp6");
+    testError("{ \"Logging\":null }\n",
+              Parser6Context::PARSER_DHCP6,
+              "<string>:1.3-11: syntax error, unexpected constant string, "
+              "expecting Dhcp6");
     testError("{ \"Dhcp6\" }\n",
               Parser6Context::PARSER_DHCP6,
               "<string>:1.11: syntax error, unexpected }, "
               "expecting :");
-    testError("{ \"Dhcp4\":[]\n",
-              Parser6Context::PARSER_DHCP6,
-              "<string>:2.1: syntax error, unexpected end of file, "
-              "expecting \",\" or }");
     testError("{}{}\n",
               Parser6Context::PARSER_JSON,
               "<string>:1.3: syntax error, unexpected {, "
@@ -596,6 +598,15 @@ TEST(ParserTest, errors) {
               Parser6Context::PARSER_DHCP6,
               "<string>:3.3-11: duplicate user-context/comment entries "
               "(previous at <string>:2:19)");
+
+    // duplicate Dhcp6 entries
+    testError("{ \"Dhcp6\":{\n"
+              "  \"comment\": \"first\" },\n"
+              "  \"Dhcp6\":{\n"
+              "  \"comment\": \"second\" }}\n",
+              Parser6Context::PARSER_DHCP6,
+              "<string>:3:3: duplicate Dhcp6 entries in toplevel map "
+              "(previous at <string>:1:3)");
 }
 
 // Check unicode escapes
@@ -639,6 +650,6 @@ TEST(ParserTest, unicodeSlash) {
     EXPECT_EQ("////", result->stringValue());
 }
 
-};
-};
-};
+}
+}
+}
index 128c6452781f401a3f64d82e6370fae22fe5e905..d6343bb243f32be425c30904e31066a1a2c60bb5 100644 (file)
@@ -203,7 +203,7 @@ DControllerBase::checkConfigOnly() {
                       " include not map '" << getAppName() << "' entry");
         }
 
-        // Handle other (i.e. not application name) objects (e.g. Logging).
+        // Handle other (i.e. not application name) objects.
         handleOtherObjects(whole_config);
 
         // Get an application process object.
@@ -376,7 +376,7 @@ DControllerBase::configFromFile() {
                       " include not map '" << getAppName() << "' entry");
         }
 
-        // Handle other (i.e. not application name) objects (e.g. Logging).
+        // Handle other (i.e. not application name) objects.
         handleOtherObjects(whole_config);
 
         // Let's configure logging before applying the configuration,
@@ -509,22 +509,10 @@ DControllerBase::handleOtherObjects(ConstElementPtr args) {
         if (obj_name == app_name) {
             continue;
         }
-        if (obj_name == "Logging") {
-            LOG_WARN(dctl_logger, DCTL_CONFIG_DEPRECATED)
-                .arg("The top level element, 'Logging', has been deprecated."
-                     "  Loggers should be defined with the 'loggers[]'"
-                     " element within the '" +  app_name + "' scope.");
-            continue;
-        }
-        LOG_WARN(dctl_logger, DCTL_CONFIG_DEPRECATED)
+        LOG_ERROR(dctl_logger, DCTL_CONFIG_DEPRECATED)
             .arg("'" + obj_name + "', defining anything in global level besides '"
                  + app_name + "' is no longer supported.");
     }
-
-    // Relocate Logging: if there is a global Logging object takes its
-    // loggers entry, move the entry to AppName object and remove
-    // now empty Logging.
-    Daemon::relocateLogging(args, app_name);
 }
 
 ConstElementPtr
@@ -554,7 +542,7 @@ DControllerBase::configTestHandler(const std::string&, ConstElementPtr args) {
         return (result);
     }
 
-    // Handle other (i.e. not application name) objects (e.g. Logging).
+    // Handle other (i.e. not application name) objects.
     handleOtherObjects(args);
 
     // We are starting the configuration process so we should remove any
@@ -602,7 +590,7 @@ DControllerBase::configSetHandler(const std::string&, ConstElementPtr args) {
 
     try {
 
-        // Handle other (i.e. not application name) objects (e.g. Logging).
+        // Handle other (i.e. not application name) objects.
         handleOtherObjects(args);
 
         // We are starting the configuration process so we should remove any
index 16db298b5d60f203df58031b10723d11768d95c9..025f0a332242ac873c1c4ba02c4650836f4a6f35 100644 (file)
@@ -605,7 +605,6 @@ protected:
     ///
     /// Code shared between configuration handlers:
     ///  - check obsolete or unknown (aka unsupported) objects.
-    ///  - relocate Logging.
     ///
     /// @param args Command arguments.
     void handleOtherObjects(isc::data::ConstElementPtr args);
index dce6ee80868b9c9bcee533ca348a1c3b8fa0e10a..0b562a764c0e8672fbe593fc3d533cf4e26a3383 100644 (file)
@@ -67,31 +67,6 @@ void Daemon::handleSignal() {
     }
 }
 
-void Daemon::relocateLogging(ConstElementPtr config,
-                             const std::string server_name) {
-    ConstElementPtr logging = config->get("Logging");
-    ConstElementPtr loggers;
-    if (logging) {
-        loggers = logging->get("loggers");
-        ElementPtr mutable_cfg = boost::const_pointer_cast<Element>(config);
-        mutable_cfg->remove("Logging");
-    }
-    if (loggers) {
-        ConstElementPtr server = config->get(server_name);
-        ElementPtr mutable_srv = boost::const_pointer_cast<Element>(server);
-        mutable_srv->set("loggers", loggers);
-    }
-    while (config->size() > 1) {
-        ElementPtr mutable_cfg = boost::const_pointer_cast<Element>(config);
-        for (auto object : config->mapValue()) {
-            if (object.first != server_name) {
-                mutable_cfg->remove(object.first);
-                break;
-            }
-        }
-    }
-}
-
 void Daemon::configureLogger(const ConstElementPtr& log_config,
                              const ConfigPtr& storage) {
 
index 9cb8e56265bbd201d9ddf3c8ac14f5a838c15716..7ace9aafb4f4cef25726089200fdb0322d256394 100644 (file)
@@ -86,18 +86,6 @@ public:
     /// @param verbose verbose mode (true usually enables DEBUG messages)
     static void loggerInit(const char* log_name, bool verbose);
 
-    /// @brief Relocate Logging configuration
-    ///
-    /// Moves the loggers entry from Logging to the server top element.
-    /// This method assumes the configuration is sane, e.g. the server
-    /// top element exists and is a map.
-    /// Top elements other than the server one are removed.
-    ///
-    /// @param config JSON top level configuration
-    /// @param server_name name of the server top element
-    static void relocateLogging(isc::data::ConstElementPtr config,
-                                const std::string server_name);
-
     /// @brief Configures logger
     ///
     /// Applies configuration stored in a top-level structure in the
index 6d8e7169099e2c4145249d977f629c0bf0726495..00800b1772dfde1dd2dcb6bf7aa78cec8fc21566 100644 (file)
@@ -46,7 +46,7 @@ configuration is committed by the administrator.  Additional information
 may be provided.
 
 % DCTL_CONFIG_DEPRECATED server configuration includes a deprecated object: %1
-This warning message is issued when the configuration includes a deprecated
+This error message is issued when the configuration includes a deprecated
 object (i.e. a top level element) which will be ignored.
 
 % DCTL_CONFIG_FETCH Fetching configuration data from config backends.
index 57e381cdba2f33159484e8c376d0b0d18af98526..bd80e25a656fad7a7eef0d3e2b6d3515c6bccfc6 100644 (file)
@@ -270,58 +270,6 @@ TEST_F(DaemonTest, PIDFileCleanup) {
     EXPECT_EQ(errno, ENOENT);
 }
 
-// Check that relocateLogging method is behaving properly with no Logging.
-TEST_F(DaemonTest, relocateLoggingNoLogging) {
-    std::string config_txt = "{ \"myServer\": { } }";
-    ConstElementPtr config = Element::fromJSON(config_txt);
-    ConstElementPtr expected = Element::fromJSON(config_txt);
-    Daemon x;
-    EXPECT_NO_THROW(x.relocateLogging(config, "myServer"));
-    EXPECT_TRUE(expected->equals(*config));
-}
-
-// Check that relocateLogging method is behaving properly with empty Logging.
-TEST_F(DaemonTest, relocateLoggingEmptyLogging) {
-    std::string config_txt =
-        "{ \"myServer\": { },\n"
-        "  \"Logging\": { } }";
-    ConstElementPtr config = Element::fromJSON(config_txt);
-    std::string expected_txt = "{ \"myServer\": { } }";
-    ConstElementPtr expected = Element::fromJSON(expected_txt);
-    Daemon x;
-    EXPECT_NO_THROW(x.relocateLogging(config, "myServer"));
-    EXPECT_TRUE(expected->equals(*config));
-}
-
-// Check that relocateLogging method is behaving properly.
-TEST_F(DaemonTest, relocateLogging) {
-    std::string config_txt =
-        "{ \"myServer\": { },\n"
-        "  \"Logging\": {\n"
-        "    \"loggers\": [ ] } }";
-    ConstElementPtr config = Element::fromJSON(config_txt);
-    std::string expected_txt =
-        "{ \"myServer\": {\n"
-        "  \"loggers\": [ ] } }";
-    ConstElementPtr expected = Element::fromJSON(expected_txt);
-    Daemon x;
-    EXPECT_NO_THROW(x.relocateLogging(config, "myServer"));
-    EXPECT_TRUE(expected->equals(*config));
-}
-
-// Check that relocateLogging method is behaving properly with extra objects.
-TEST_F(DaemonTest, relocateLoggingExtraObjects) {
-    std::string config_txt =
-        "{ \"myServer\": { },\n"
-        "  \"Foobar\": { } }";
-    ConstElementPtr config = Element::fromJSON(config_txt);
-    std::string expected_txt = "{ \"myServer\": { } }";
-    ConstElementPtr expected = Element::fromJSON(expected_txt);
-    Daemon x;
-    EXPECT_NO_THROW(x.relocateLogging(config, "myServer"));
-    EXPECT_TRUE(expected->equals(*config));
-}
-
 // Checks that configureLogger method is behaving properly.
 // More dedicated tests are available for LogConfigParser class.
 // See logger_unittest.cc