mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 14:05:33 +00:00
[#1245] Checkpoint: flatten v4
This commit is contained in:
@@ -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;
|
||||
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);
|
||||
}
|
||||
|
||||
ConstElementPtr control_socket = mutable_cfg->get("control-socket");
|
||||
if (control_socket) {
|
||||
parameter_name = "control-socket";
|
||||
ControlSocketParser parser;
|
||||
parser.parse(*srv_cfg, control_socket);
|
||||
}
|
||||
|
||||
ConstElementPtr multi_threading = mutable_cfg->get("multi-threading");
|
||||
if (multi_threading) {
|
||||
parameter_name = "multi-threading";
|
||||
MultiThreadingConfigParser parser;
|
||||
parser.parse(*srv_cfg, multi_threading);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
ConstElementPtr hr_identifiers =
|
||||
mutable_cfg->get("host-reservation-identifiers");
|
||||
if (hr_identifiers) {
|
||||
parameter_name = "host-reservation-identifiers";
|
||||
HostReservationIdsParser4 parser;
|
||||
parser.parse(hr_identifiers);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ConstElementPtr sanity_checks = mutable_cfg->get("sanity-checks");
|
||||
if (sanity_checks) {
|
||||
parameter_name = "sanity-checks";
|
||||
SanityChecksParser parser;
|
||||
parser.parse(*srv_cfg, sanity_checks);
|
||||
}
|
||||
|
||||
ConstElementPtr expiration_cfg =
|
||||
mutable_cfg->get("expired-leases-processing");
|
||||
if (expiration_cfg) {
|
||||
parameter_name = "expired-leases-processing";
|
||||
ExpirationConfigParser parser;
|
||||
parser.parse(expiration_cfg);
|
||||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
// D2 client configuration.
|
||||
D2ClientConfigPtr d2_client_cfg;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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, it);
|
||||
cfg_db_access->setHostDbAccessString(access_string);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// This parser is used in several places.
|
||||
Dhcp4ConfigParser global_parser;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Make parsers grouping.
|
||||
ConfigPair config_pair;
|
||||
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;
|
||||
}
|
||||
|
||||
if (config_pair.first == "option-data") {
|
||||
OptionDataListParser parser(AF_INET);
|
||||
CfgOptionPtr cfg_option = srv_cfg->getCfgOption();
|
||||
parser.parse(cfg_option, config_pair.second);
|
||||
continue;
|
||||
}
|
||||
parameter_name = config_pair.first;
|
||||
|
||||
if (config_pair.first == "control-socket") {
|
||||
ControlSocketParser parser;
|
||||
parser.parse(*srv_cfg, config_pair.second);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_pair.first == "multi-threading") {
|
||||
MultiThreadingConfigParser parser;
|
||||
parser.parse(*srv_cfg, config_pair.second);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_pair.first == "dhcp-queue-control") {
|
||||
DHCPQueueControlParser parser;
|
||||
srv_cfg->setDHCPQueueControl(parser.parse(config_pair.second));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_pair.first == "host-reservation-identifiers") {
|
||||
HostReservationIdsParser4 parser;
|
||||
parser.parse(config_pair.second);
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (config_pair.first == "sanity-checks") {
|
||||
SanityChecksParser parser;
|
||||
parser.parse(*srv_cfg, config_pair.second);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_pair.first == "expired-leases-processing") {
|
||||
ExpirationConfigParser parser;
|
||||
parser.parse(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.
|
||||
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
|
||||
if (config_pair.first == "dhcp-ddns") {
|
||||
// Apply defaults
|
||||
D2ClientConfigParser::setAllDefaults(config_pair.second);
|
||||
D2ClientConfigParser parser;
|
||||
d2_client_cfg = parser.parse(config_pair.second);
|
||||
continue;
|
||||
}
|
||||
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
||||
if (config_pair.first == "hosts-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->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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config_pair.first == "config-control") {
|
||||
ConfigControlParser parser;
|
||||
ConfigControlInfoPtr config_ctl_info = parser.parse(config_pair.second);
|
||||
CfgMgr::instance().getStagingCfg()->setConfigControlInfo(config_ctl_info);
|
||||
// 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");
|
||||
|
||||
|
Reference in New Issue
Block a user