]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1245] Checkpoint: flatten v4
authorFrancis Dupont <fdupont@isc.org>
Fri, 22 May 2020 08:34:36 +0000 (10:34 +0200)
committerFrancis Dupont <fdupont@isc.org>
Wed, 17 Jun 2020 09:27:52 +0000 (11:27 +0200)
src/bin/dhcp4/json_config_parser.cc

index 259f7ef289f076f1f783ea10d495311ce4801e6a..43f95cda0b40bdd9dcc6ce9d991ad3dae522f0de 100644 (file)
@@ -335,10 +335,8 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
     // Rollback informs whether error occurred and original data
     // have to be restored to global storages.
     bool rollback = false;
-    // config_pair holds the details of the current parser when iterating over
-    // the parsers.  It is declared outside the loops so in case of an error,
-    // the name of the failing parser can be retrieved in the "catch" clause.
-    ConfigPair config_pair;
+    // Global parameter name in case of an error.
+    string parameter_name;
     ElementPtr mutable_cfg;
     SrvConfigPtr srv_cfg;
     try {
@@ -362,188 +360,229 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
         // And now derive (inherit) global parameters to subnets, if not specified.
         SimpleParser4::deriveParameters(mutable_cfg);
 
+        // In principle we could have the following code structured as a series
+        // of long if else if clauses. That would give a marginal performance
+        // boost, but would make the code less readable. We had serious issues
+        // with the parser code debugability, so I decided to keep it as a
+        // series of independent ifs.
+
         // We need definitions first
         ConstElementPtr option_defs = mutable_cfg->get("option-def");
         if (option_defs) {
+            parameter_name = "option-def";
             OptionDefListParser parser(AF_INET);
             CfgOptionDefPtr cfg_option_def = srv_cfg->getCfgOptionDef();
             parser.parse(cfg_option_def, option_defs);
         }
 
-        // This parser is used in several places, so it should be available
-        // early.
-        Dhcp4ConfigParser global_parser;
-
-        // D2 client configuration.
-        D2ClientConfigPtr d2_client_cfg;
+        ConstElementPtr option_datas = mutable_cfg->get("option-data");
+        if (option_datas) {
+            parameter_name = "option-data";
+            OptionDataListParser parser(AF_INET);
+            CfgOptionPtr cfg_option = srv_cfg->getCfgOption();
+            parser.parse(cfg_option, option_datas);
+        }
 
-        // Make parsers grouping.
-        const std::map<std::string, ConstElementPtr>& values_map =
-                                                        mutable_cfg->mapValue();
-        BOOST_FOREACH(config_pair, values_map) {
-            // In principle we could have the following code structured as a series
-            // of long if else if clauses. That would give a marginal performance
-            // boost, but would make the code less readable. We had serious issues
-            // with the parser code debugability, so I decided to keep it as a
-            // series of independent ifs.
-            if (config_pair.first == "option-def") {
-                // This is converted to SimpleParser and is handled already above.
-                continue;
-            }
+        ConstElementPtr control_socket = mutable_cfg->get("control-socket");
+        if (control_socket) {
+            parameter_name = "control-socket";
+            ControlSocketParser parser;
+            parser.parse(*srv_cfg, control_socket);
+        }
 
-            if (config_pair.first == "option-data") {
-                OptionDataListParser parser(AF_INET);
-                CfgOptionPtr cfg_option = srv_cfg->getCfgOption();
-                parser.parse(cfg_option, config_pair.second);
-                continue;
-            }
+        ConstElementPtr multi_threading = mutable_cfg->get("multi-threading");
+        if (multi_threading) {
+            parameter_name = "multi-threading";
+            MultiThreadingConfigParser parser;
+            parser.parse(*srv_cfg, multi_threading);
+        }
 
-            if (config_pair.first == "control-socket") {
-                ControlSocketParser parser;
-                parser.parse(*srv_cfg, config_pair.second);
-                continue;
-            }
+        ConstElementPtr queue_control = mutable_cfg->get("dhcp-queue-control");
+        if (queue_control) {
+            parameter_name = "dhcp-queue-control";
+            DHCPQueueControlParser parser;
+            srv_cfg->setDHCPQueueControl(parser.parse(queue_control));
+        }
 
-            if (config_pair.first == "multi-threading") {
-                MultiThreadingConfigParser parser;
-                parser.parse(*srv_cfg, config_pair.second);
-                continue;
-            }
+        ConstElementPtr hr_identifiers =
+            mutable_cfg->get("host-reservation-identifiers");
+        if (hr_identifiers) {
+            parameter_name = "host-reservation-identifiers";
+            HostReservationIdsParser4 parser;
+            parser.parse(hr_identifiers);
+        }
 
-            if (config_pair.first == "dhcp-queue-control") {
-                DHCPQueueControlParser parser;
-                srv_cfg->setDHCPQueueControl(parser.parse(config_pair.second));
-                continue;
+        ConstElementPtr ifaces_config = mutable_cfg->get("interfaces-config");
+        if (ifaces_config) {
+            parameter_name = "interfaces-config";
+            ElementPtr mutable_cfg =
+                boost::const_pointer_cast<Element>(ifaces_config);
+            if (check_only) {
+                // No re-detection in check only mode
+                mutable_cfg->set("re-detect", Element::create(false));
             }
+            IfacesConfigParser parser(AF_INET);
+            CfgIfacePtr cfg_iface = srv_cfg->getCfgIface();
+            parser.parse(cfg_iface, ifaces_config);
+        }
 
-            if (config_pair.first == "host-reservation-identifiers") {
-                HostReservationIdsParser4 parser;
-                parser.parse(config_pair.second);
-                continue;
-            }
+        ConstElementPtr sanity_checks = mutable_cfg->get("sanity-checks");
+        if (sanity_checks) {
+            parameter_name = "sanity-checks";
+            SanityChecksParser parser;
+            parser.parse(*srv_cfg, sanity_checks);
+        }
 
-            if (config_pair.first == "interfaces-config") {
-                ElementPtr ifaces_cfg =
-                    boost::const_pointer_cast<Element>(config_pair.second);
-                if (check_only) {
-                    // No re-detection in check only mode
-                    ifaces_cfg->set("re-detect", Element::create(false));
-                }
-                IfacesConfigParser parser(AF_INET);
-                CfgIfacePtr cfg_iface = srv_cfg->getCfgIface();
-                parser.parse(cfg_iface, ifaces_cfg);
-                continue;
-            }
+        ConstElementPtr expiration_cfg =
+            mutable_cfg->get("expired-leases-processing");
+        if (expiration_cfg) {
+            parameter_name = "expired-leases-processing";
+            ExpirationConfigParser parser;
+            parser.parse(expiration_cfg);
+        }
 
-            if (config_pair.first == "sanity-checks") {
-                SanityChecksParser parser;
-                parser.parse(*srv_cfg, config_pair.second);
-                continue;
-            }
+        // The hooks-libraries configuration must be parsed after parsing
+        // multi-threading configuration so that libraries are checked
+        // for multi-threading compatibility.
+        ConstElementPtr hooks_libraries = mutable_cfg->get("hooks-libraries");
+        if (hooks_libraries) {
+            parameter_name = "hooks-libraries";
+            HooksLibrariesParser hooks_parser;
+            HooksConfig& libraries = srv_cfg->getHooksConfig();
+            hooks_parser.parse(libraries, hooks_libraries);
+            libraries.verifyLibraries(hooks_libraries->getPosition());
+        }
 
-            if (config_pair.first == "expired-leases-processing") {
-                ExpirationConfigParser parser;
-                parser.parse(config_pair.second);
-                continue;
-            }
+        // D2 client configuration.
+        D2ClientConfigPtr d2_client_cfg;
 
-            // The hooks-libraries configuration must be parsed after parsing
-            // multi-threading configuration so that libraries are checked
-            // for multi-threading compatibility.
-            if (config_pair.first == "hooks-libraries") {
-                HooksLibrariesParser hooks_parser;
-                HooksConfig& libraries = srv_cfg->getHooksConfig();
-                hooks_parser.parse(libraries, config_pair.second);
-                libraries.verifyLibraries(config_pair.second->getPosition());
-                continue;
-            }
+        // Legacy DhcpConfigParser stuff below.
+        ConstElementPtr dhcp_ddns = mutable_cfg->get("dhcp-ddns");
+        if (dhcp_ddns) {
+            parameter_name = "dhcp-ddns";
+            // Apply defaults
+            D2ClientConfigParser::setAllDefaults(dhcp_ddns);
+            D2ClientConfigParser parser;
+            d2_client_cfg = parser.parse(dhcp_ddns);
+        }
 
-            // Legacy DhcpConfigParser stuff below
-            if (config_pair.first == "dhcp-ddns") {
-                // Apply defaults
-                D2ClientConfigParser::setAllDefaults(config_pair.second);
-                D2ClientConfigParser parser;
-                d2_client_cfg = parser.parse(config_pair.second);
-                continue;
-            }
+        ConstElementPtr client_classes = mutable_cfg->get("client-classes");
+        if (client_classes) {
+            parameter_name = "client-classes";
+            ClientClassDefListParser parser;
+            ClientClassDictionaryPtr dictionary =
+                parser.parse(client_classes, AF_INET);
+            srv_cfg->setClientClassDictionary(dictionary);
+        }
 
-            if (config_pair.first == "client-classes") {
-                ClientClassDefListParser parser;
-                ClientClassDictionaryPtr dictionary =
-                    parser.parse(config_pair.second, AF_INET);
-                srv_cfg->setClientClassDictionary(dictionary);
-                continue;
-            }
+        // Please move at the end when migration will be finished.
+        ConstElementPtr lease_database = mutable_cfg->get("lease-database");
+        if (lease_database) {
+            parameter_name = "lease-database";
+            db::DbAccessParser parser;
+            std::string access_string;
+            parser.parse(access_string, lease_database);
+            CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
+            cfg_db_access->setLeaseDbAccessString(access_string);
+        }
 
-            // Please move at the end when migration will be finished.
-            if (config_pair.first == "lease-database") {
-                db::DbAccessParser parser;
-                std::string access_string;
-                parser.parse(access_string, config_pair.second);
-                CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
-                cfg_db_access->setLeaseDbAccessString(access_string);
-                continue;
-            }
+        ConstElementPtr hosts_database = mutable_cfg->get("hosts-database");
+        if (hosts_database) {
+            parameter_name = "hosts-database";
+            db::DbAccessParser parser;
+            std::string access_string;
+            parser.parse(access_string, hosts_database);
+            CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
+            cfg_db_access->setHostDbAccessString(access_string);
+        }
 
-            if (config_pair.first == "hosts-database") {
-                db::DbAccessParser parser;
+        ConstElementPtr hosts_databases = mutable_cfg->get("hosts-databases");
+        if (hosts_databases) {
+            parameter_name = "hosts-databases";
+            CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
+            db::DbAccessParser parser;
+            for (auto it : hosts_databases->listValue()) {
                 std::string access_string;
-                parser.parse(access_string, config_pair.second);
-                CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
+                parser.parse(access_string, it);
                 cfg_db_access->setHostDbAccessString(access_string);
-                continue;
             }
+        }
 
-            if (config_pair.first == "hosts-databases") {
-                CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
-                db::DbAccessParser parser;
-                auto list = config_pair.second->listValue();
-                for (auto it : list) {
-                    std::string access_string;
-                    parser.parse(access_string, it);
-                    cfg_db_access->setHostDbAccessString(access_string);
-                }
-                continue;
-            }
+        ConstElementPtr subnet4 = mutable_cfg->get("subnet4");
+        if (subnet4) {
+            parameter_name = "subnet4";
+            Subnets4ListConfigParser subnets_parser;
+            // parse() returns number of subnets parsed. We may log it one day.
+            subnets_parser.parse(srv_cfg, subnet4);
+        }
 
-            if (config_pair.first == "subnet4") {
-                Subnets4ListConfigParser subnets_parser;
-                // parse() returns number of subnets parsed. We may log it one day.
-                subnets_parser.parse(srv_cfg, config_pair.second);
-                continue;
-            }
+        // This parser is used in several places.
+        Dhcp4ConfigParser global_parser;
 
-            if (config_pair.first == "shared-networks") {
-                /// We need to create instance of SharedNetworks4ListParser
-                /// and parse the list of the shared networks into the
-                /// CfgSharedNetworks4 object. One additional step is then to
-                /// add subnets from the CfgSharedNetworks4 into CfgSubnets4
-                /// as well.
-                SharedNetworks4ListParser parser;
-                CfgSharedNetworks4Ptr cfg = srv_cfg->getCfgSharedNetworks4();
-                parser.parse(cfg, config_pair.second);
-
-                // We also need to put the subnets it contains into normal
-                // subnets list.
-                global_parser.copySubnets4(srv_cfg->getCfgSubnets4(), cfg);
-                continue;
+        ConstElementPtr shared_networks = mutable_cfg->get("shared-networks");
+        if (shared_networks) {
+            parameter_name = "shared-networks";
+            /// We need to create instance of SharedNetworks4ListParser
+            /// and parse the list of the shared networks into the
+            /// CfgSharedNetworks4 object. One additional step is then to
+            /// add subnets from the CfgSharedNetworks4 into CfgSubnets4
+            /// as well.
+            SharedNetworks4ListParser parser;
+            CfgSharedNetworks4Ptr cfg = srv_cfg->getCfgSharedNetworks4();
+            parser.parse(cfg, shared_networks);
+
+            // We also need to put the subnets it contains into normal
+            // subnets list.
+            global_parser.copySubnets4(srv_cfg->getCfgSubnets4(), cfg);
+        }
+
+        ConstElementPtr reservations = mutable_cfg->get("reservations");
+        if (reservations) {
+            parameter_name = "reservations";
+            HostCollection hosts;
+            HostReservationsListParser<HostReservationParser4> parser;
+            parser.parse(SUBNET_ID_GLOBAL, reservations, hosts);
+            for (auto h = hosts.begin(); h != hosts.end(); ++h) {
+                srv_cfg->getCfgHosts()->add(*h);
             }
+        }
 
-            if (config_pair.first == "reservations") {
-                HostCollection hosts;
-                HostReservationsListParser<HostReservationParser4> parser;
-                parser.parse(SUBNET_ID_GLOBAL, config_pair.second, hosts);
-                for (auto h = hosts.begin(); h != hosts.end(); ++h) {
-                    srv_cfg->getCfgHosts()->add(*h);
-                }
+        ConstElementPtr config_control = mutable_cfg->get("config-control");
+        if (config_control) {
+            parameter_name = "config-control";
+            ConfigControlParser parser;
+            ConfigControlInfoPtr config_ctl_info = parser.parse(config_control);
+            CfgMgr::instance().getStagingCfg()->setConfigControlInfo(config_ctl_info);
+        }
 
-                continue;
-            }
+        // Make parsers grouping.
+        ConfigPair config_pair;
+        const std::map<std::string, ConstElementPtr>& values_map =
+                                                        mutable_cfg->mapValue();
+        BOOST_FOREACH(config_pair, values_map) {
 
-            if (config_pair.first == "config-control") {
-                ConfigControlParser parser;
-                ConfigControlInfoPtr config_ctl_info = parser.parse(config_pair.second);
-                CfgMgr::instance().getStagingCfg()->setConfigControlInfo(config_ctl_info);
+            parameter_name = config_pair.first;
+
+            // These are converted to SimpleParser and are handled already above.
+            if ((config_pair.first == "option-def") ||
+                (config_pair.first == "option-data") ||
+                (config_pair.first == "control-socket") ||
+                (config_pair.first == "multi-threading") ||
+                (config_pair.first == "dhcp-queue-control") ||
+                (config_pair.first == "host-reservation-identifiers") ||
+                (config_pair.first == "interfaces-config") ||
+                (config_pair.first == "sanity-checks") ||
+                (config_pair.first == "expired-leases-processing") ||
+                (config_pair.first == "hooks-libraries") ||
+                (config_pair.first == "dhcp-ddns") ||
+                (config_pair.first == "client-classes") ||
+                (config_pair.first == "lease-database") ||
+                (config_pair.first == "hosts-database") ||
+                (config_pair.first == "hosts-databases") ||
+                (config_pair.first == "subnet4") ||
+                (config_pair.first == "shared-networks") ||
+                (config_pair.first == "reservations") ||
+                (config_pair.first == "config-control")) {
                 continue;
             }
 
@@ -603,6 +642,9 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
                       << " (" << config_pair.second->getPosition() << ")");
         }
 
+        // Reset parameter name.
+        parameter_name = "<post parsing>";
+
         // Apply global options in the staging config.
         global_parser.parse(srv_cfg, mutable_cfg);
 
@@ -620,7 +662,7 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
 
     } catch (const isc::Exception& ex) {
         LOG_ERROR(dhcp4_logger, DHCP4_PARSER_FAIL)
-                  .arg(config_pair.first).arg(ex.what());
+                  .arg(parameter_name).arg(ex.what());
         answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
 
         // An error occurred, so make sure that we restore original data.
@@ -628,7 +670,7 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
 
     } catch (...) {
         // For things like bad_cast in boost::lexical_cast
-        LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(config_pair.first);
+        LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(parameter_name);
         answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
                                            " processing error");