isc::data::ConstElementPtr
CtrlAgentProcess::shutdown(isc::data::ConstElementPtr /*args*/) {
setShutdownFlag(true);
- return (isc::config::createAnswer(0, "Control Agent is shutting down"));
+ return (isc::config::createAnswer(CONTROL_RESULT_SUCCESS,
+ "Control Agent is shutting down"));
}
isc::data::ConstElementPtr
#include <hooks/hooks.h>
#include <hooks/hooks_manager.h>
+using namespace isc::config;
using namespace isc::hooks;
using namespace isc::process;
shutdown_type_ = SD_NOW;
} else {
setShutdownFlag(false);
- return (isc::config::createAnswer(1, "Invalid Shutdown type: "
- + type_str));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR,
+ "Invalid Shutdown type: " +
+ type_str));
}
}
}
// Set the base class's shutdown flag.
setShutdownFlag(true);
- return (isc::config::createAnswer(0, "Shutdown initiated, type is: "
- + type_str));
+ return (isc::config::createAnswer(CONTROL_RESULT_SUCCESS,
+ "Shutdown initiated, type is: " +\
+ type_str));
}
isc::data::ConstElementPtr
LOG_ERROR(d2_logger, DHCP_DDNS_CONFIGURED_CALLOUT_DROP)
.arg(error);
reconf_queue_flag_ = false;
- answer = isc::config::createAnswer(1, error);
+ answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, error);
return (answer);
}
}
// both structures are built using the same order.
EXPECT_EQ(Element::fromJSON(expected_command)->str(),
entire_command->str());
- return (createAnswer(0, "long command received ok"));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, "long command received ok"));
}
/// @brief Command handler which generates long response.
s << std::setw(5) << i;
arguments->add(Element::create(s.str()));
}
- return (createAnswer(0, arguments));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, arguments));
}
};
}
} catch (const std::exception& ex) {
LOG_ERROR(dhcp4_logger, DHCP4_HOOKS_LIBS_RELOAD_FAIL);
- ConstElementPtr answer = isc::config::createAnswer(1, ex.what());
+ ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
return (answer);
}
- ConstElementPtr answer = isc::config::createAnswer(0,
- "Hooks libraries successfully reloaded"
- " (WARNING: libreload is deprecated).");
+ ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS,
+ "Hooks libraries successfully reloaded "
+ "(WARNING: libreload is deprecated).");
return (answer);
}
ConstElementPtr /*args*/) {
ConstElementPtr config = CfgMgr::instance().getCurrentCfg()->toElement();
- return (createAnswer(0, config));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, config));
}
ConstElementPtr
// configuration attempts.
CfgMgr::instance().rollback();
- // Let's first check the config
- ConstElementPtr result = checkConfig(dhcp4);
-
- int rcode = 0;
- isc::config::parseAnswer(rcode, result);
- if (rcode != CONTROL_RESULT_SUCCESS) {
- return (result);
- }
-
- // disable multi-threading (it will be applied by new configuration)
- // this must be done in order to properly handle MT to ST transition
- // when 'multi-threading' structure is missing from new config
- MultiThreadingMgr::instance().apply(false, 0, 0);
-
- // We are starting the configuration process so we should remove any
- // staging configuration that has been created during previous
- // configuration attempts.
- CfgMgr::instance().rollback();
-
// 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
CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
// Now we configure the server proper.
- result = processConfig(dhcp4);
+ ConstElementPtr result = processConfig(dhcp4);
// If the configuration parsed successfully, apply the new logger
// configuration and the commit the new configuration. We apply
// the logging first in case there's a configuration failure.
+ int rcode = 0;
isc::config::parseAnswer(rcode, result);
if (rcode == CONTROL_RESULT_SUCCESS) {
CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
ElementPtr extended = Element::create(Dhcpv4Srv::getVersion(true));
ElementPtr arguments = Element::createMap();
arguments->set("extended", extended);
- ConstElementPtr answer = isc::config::createAnswer(0,
+ ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS,
Dhcpv4Srv::getVersion(false),
arguments);
return (answer);
ControlledDhcpv4Srv::commandBuildReportHandler(const string&,
ConstElementPtr) {
ConstElementPtr answer =
- isc::config::createAnswer(0, isc::detail::getConfigReport());
+ isc::config::createAnswer(CONTROL_RESULT_SUCCESS, isc::detail::getConfigReport());
return (answer);
}
}
status->set("sockets", sockets);
- return (createAnswer(0, status));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, status));
}
ConstElementPtr
ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance();
if (!srv) {
- ConstElementPtr no_srv = isc::config::createAnswer(1,
+ ConstElementPtr no_srv = isc::config::createAnswer(CONTROL_RESULT_ERROR,
"Server object not initialized, so can't process command '" +
command + "', arguments: '" + txt + "'.");
return (no_srv);
return (srv->commandStatusGetHandler(command, args));
}
- return (isc::config::createAnswer(1, "Unrecognized command:"
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, "Unrecognized command:"
+ command));
} catch (const isc::Exception& ex) {
- return (isc::config::createAnswer(1, "Error while processing command '"
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, "Error while processing command '"
+ command + "': " + ex.what() +
", params: '" + txt + "'"));
}
if (!srv) {
err << "Server object not initialized, can't process config.";
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_CONFIG_RECEIVED)
}
} catch (const std::exception& ex) {
err << "Failed to process configuration:" << ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Re-open lease and host database with new parameters.
srv->getNetworkState()->reset(NetworkState::Origin::DB_CONNECTION);
} catch (const std::exception& ex) {
err << "Unable to open database: " << ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Server will start DDNS communications if its enabled.
} catch (const std::exception& ex) {
err << "Error starting DHCP_DDNS client after server reconfiguration: "
<< ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Setup DHCPv4-over-DHCPv6 IPC
} catch (const std::exception& ex) {
err << "error starting DHCPv4-over-DHCPv6 IPC "
" after server reconfiguration: " << ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Configure DHCP packet queueing
} catch (const std::exception& ex) {
err << "Error setting packet queue controls after server reconfiguration: "
<< ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Configure a callback to shut down the server when the bind socket
err << "unable to setup timers for periodically running the"
" reclamation of the expired leases: "
<< ex.what() << ".";
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Setup config backend polling, if configured for it.
ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance();
- // Single stream instance used in all error clauses
- std::ostringstream err;
-
if (!srv) {
- err << "Server object not initialized, can't process config.";
- return (isc::config::createAnswer(1, err.str()));
+ ConstElementPtr no_srv = isc::config::createAnswer(CONTROL_RESULT_ERROR,
+ "Server object not initialized, can't process config.");
+ return (no_srv);
}
return (configureDhcp4Server(*srv, config, true));
}
isc::data::ConstElementPtr
-configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
- bool check_only) {
- if (!config_set) {
- ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
- string("Can't parse NULL config"));
- return (answer);
- }
-
- LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_CONFIG_START)
- .arg(server.redactConfig(config_set)->str());
-
+processDhcp4Config(isc::data::ConstElementPtr config_set) {
// Before starting any subnet operations, let's reset the subnet-id counter,
// so newly recreated configuration starts with first subnet-id equal 1.
Subnet::resetSubnetID();
- // Close DHCP sockets and remove any existing timers.
- if (!check_only) {
- IfaceMgr::instance().closeSockets();
- TimerMgr::instance()->unregisterTimers();
- server.discardPackets();
- server.getCBControl()->reset();
- }
-
// Revert any runtime option definitions configured so far and not committed.
LibDHCP::revertRuntimeOptionDefs();
// Let's set empty container in case a user hasn't specified any configuration
// Answer will hold the result.
ConstElementPtr answer;
- // Rollback informs whether error occurred and original data
- // have to be restored to global storages.
- bool rollback = false;
+
// Global parameter name in case of an error.
string parameter_name;
ElementPtr mutable_cfg;
ConstElementPtr ifaces_config = mutable_cfg->get("interfaces-config");
if (ifaces_config) {
parameter_name = "interfaces-config";
- IfacesConfigParser parser(AF_INET, check_only);
+ IfacesConfigParser parser(AF_INET, true);
CfgIfacePtr cfg_iface = srv_config->getCfgIface();
parser.parse(cfg_iface, ifaces_config);
}
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_FAIL)
.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.
- rollback = true;
} catch (...) {
// For things like bad_cast in boost::lexical_cast
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(parameter_name);
- answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
- " processing error");
+ answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration "
+ "processing error");
+ }
- // An error occurred, so make sure that we restore original data.
- rollback = true;
+ if (!answer) {
+ answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration seems sane. "
+ "Control-socket, hook-libraries, and D2 configuration "
+ "were sanity checked, but not applied.");
}
- if (check_only) {
+ return (answer);
+}
+
+isc::data::ConstElementPtr
+configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
+ bool check_only) {
+ if (!config_set) {
+ ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
+ "Can't parse NULL config");
+ return (answer);
+ }
+
+ LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_CONFIG_START)
+ .arg(server.redactConfig(config_set)->str());
+
+ // Rollback informs whether error occurred and original data
+ // have to be restored to global storages.
+ bool rollback = false;
+
+ auto answer = processDhcp4Config(config_set);
+
+ int status_code = 0;
+ isc::config::parseAnswer(status_code, answer);
+ if (status_code != CONTROL_RESULT_SUCCESS) {
rollback = true;
- if (!answer) {
- answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS,
- "Configuration seems sane. Control-socket, hook-libraries, and D2 "
- "configuration were sanity checked, but not applied.");
+ }
+
+ SrvConfigPtr srv_config;
+
+ if (!rollback) {
+ if (!check_only) {
+ string parameter_name;
+ ElementPtr mutable_cfg;
+
+ // Close DHCP sockets and remove any existing timers.
+ IfaceMgr::instance().closeSockets();
+ TimerMgr::instance()->unregisterTimers();
+ server.discardPackets();
+ server.getCBControl()->reset();
+
+ try {
+
+ // Get the staging configuration.
+ srv_config = CfgMgr::instance().getStagingCfg();
+
+ // This is a way to convert ConstElementPtr to ElementPtr.
+ // We need a config that can be edited, because we will insert
+ // default values and will insert derived values as well.
+ mutable_cfg = boost::const_pointer_cast<Element>(config_set);
+
+ ConstElementPtr ifaces_config = mutable_cfg->get("interfaces-config");
+ if (ifaces_config) {
+ parameter_name = "interfaces-config";
+ IfacesConfigParser parser(AF_INET, false);
+ CfgIfacePtr cfg_iface = srv_config->getCfgIface();
+ cfg_iface->reset();
+ parser.parse(cfg_iface, ifaces_config);
+ }
+ } catch (const isc::Exception& ex) {
+ LOG_ERROR(dhcp4_logger, DHCP4_PARSER_FAIL)
+ .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.
+ rollback = true;
+ } catch (...) {
+ // For things like bad_cast in boost::lexical_cast
+ LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(parameter_name);
+ answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
+ " processing error");
+
+ // An error occurred, so make sure that we restore original data.
+ rollback = true;
+ }
+ } else {
+ rollback = true;
}
}
// both structures are built using the same order.
EXPECT_EQ(Element::fromJSON(expected_command)->str(),
entire_command->str());
- return (createAnswer(0, "long command received ok"));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, "long command received ok"));
}
/// @brief Command handler which generates long response
s << std::setw(5) << i;
arguments->add(Element::create(s.str()));
}
- return (createAnswer(0, arguments));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, arguments));
}
};
}
} catch (const std::exception& ex) {
LOG_ERROR(dhcp6_logger, DHCP6_HOOKS_LIBS_RELOAD_FAIL);
- ConstElementPtr answer = isc::config::createAnswer(1, ex.what());
+ ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
return (answer);
}
- ConstElementPtr answer = isc::config::createAnswer(0,
+ ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS,
"Hooks libraries successfully reloaded "
"(WARNING: libreload is deprecated).");
return (answer);
ConstElementPtr /*args*/) {
ConstElementPtr config = CfgMgr::instance().getCurrentCfg()->toElement();
- return (createAnswer(0, config));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, config));
}
ConstElementPtr
// configuration attempts.
CfgMgr::instance().rollback();
- // Let's first check the config
- ConstElementPtr result = checkConfig(dhcp6);
-
- int rcode = 0;
- isc::config::parseAnswer(rcode, result);
- if (rcode != CONTROL_RESULT_SUCCESS) {
- return (result);
- }
-
- // disable multi-threading (it will be applied by new configuration)
- // this must be done in order to properly handle MT to ST transition
- // when 'multi-threading' structure is missing from new config
- MultiThreadingMgr::instance().apply(false, 0, 0);
-
- // We are starting the configuration process so we should remove any
- // staging configuration that has been created during previous
- // configuration attempts.
- CfgMgr::instance().rollback();
-
// 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
CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
// Now we configure the server proper.
- result = processConfig(dhcp6);
+ ConstElementPtr result = processConfig(dhcp6);
// If the configuration parsed successfully, apply the new logger
// configuration and the commit the new configuration. We apply
// the logging first in case there's a configuration failure.
+ int rcode = 0;
isc::config::parseAnswer(rcode, result);
if (rcode == CONTROL_RESULT_SUCCESS) {
CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
ElementPtr extended = Element::create(Dhcpv6Srv::getVersion(true));
ElementPtr arguments = Element::createMap();
arguments->set("extended", extended);
- ConstElementPtr answer = isc::config::createAnswer(0,
+ ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS,
Dhcpv6Srv::getVersion(false),
arguments);
return (answer);
ControlledDhcpv6Srv::commandBuildReportHandler(const string&,
ConstElementPtr) {
ConstElementPtr answer =
- isc::config::createAnswer(0, isc::detail::getConfigReport());
+ isc::config::createAnswer(CONTROL_RESULT_SUCCESS, isc::detail::getConfigReport());
return (answer);
}
}
status->set("sockets", sockets);
- return (createAnswer(0, status));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, status));
}
ConstElementPtr
ControlledDhcpv6Srv* srv = ControlledDhcpv6Srv::getInstance();
if (!srv) {
- ConstElementPtr no_srv = isc::config::createAnswer(1,
+ ConstElementPtr no_srv = isc::config::createAnswer(CONTROL_RESULT_ERROR,
"Server object not initialized, so can't process command '" +
command + "', arguments: '" + txt + "'.");
return (no_srv);
return (srv->commandStatusGetHandler(command, args));
}
- return (isc::config::createAnswer(1, "Unrecognized command:"
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, "Unrecognized command:"
+ command));
} catch (const isc::Exception& ex) {
- return (isc::config::createAnswer(1, "Error while processing command '"
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, "Error while processing command '"
+ command + "': " + ex.what() +
", params: '" + txt + "'"));
}
if (!srv) {
err << "Server object not initialized, can't process config.";
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_CONFIG_RECEIVED)
}
} catch (const std::exception& ex) {
err << "Failed to process configuration:" << ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Re-open lease and host database with new parameters.
srv->getNetworkState()->reset(NetworkState::Origin::DB_CONNECTION);
} catch (const std::exception& ex) {
err << "Unable to open database: " << ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Regenerate server identifier if needed.
} catch (const std::exception& ex) {
err << "unable to configure server identifier: " << ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Server will start DDNS communications if its enabled.
} catch (const std::exception& ex) {
err << "Error starting DHCP_DDNS client after server reconfiguration: "
<< ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Setup DHCPv4-over-DHCPv6 IPC
} catch (const std::exception& ex) {
err << "error starting DHCPv4-over-DHCPv6 IPC "
" after server reconfiguration: " << ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Configure DHCP packet queueing
} catch (const std::exception& ex) {
err << "Error setting packet queue controls after server reconfiguration: "
<< ex.what();
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Configure a callback to shut down the server when the bind socket
err << "unable to setup timers for periodically running the"
" reclamation of the expired leases: "
<< ex.what() << ".";
- return (isc::config::createAnswer(1, err.str()));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
}
// Setup config backend polling, if configured for it.
ControlledDhcpv6Srv* srv = ControlledDhcpv6Srv::getInstance();
if (!srv) {
- ConstElementPtr no_srv = isc::config::createAnswer(1,
+ ConstElementPtr no_srv = isc::config::createAnswer(CONTROL_RESULT_ERROR,
"Server object not initialized, can't process config.");
return (no_srv);
}
}
isc::data::ConstElementPtr
-configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
- bool check_only) {
- if (!config_set) {
- ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
- string("Can't parse NULL config"));
- return (answer);
- }
-
- LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_CONFIG_START)
- .arg(server.redactConfig(config_set)->str());
-
+processDhcp6Config(isc::data::ConstElementPtr config_set) {
// Before starting any subnet operations, let's reset the subnet-id counter,
// so newly recreated configuration starts with first subnet-id equal 1.
Subnet::resetSubnetID();
- // Close DHCP sockets and remove any existing timers.
- if (!check_only) {
- IfaceMgr::instance().closeSockets();
- TimerMgr::instance()->unregisterTimers();
- server.discardPackets();
- server.getCBControl()->reset();
- }
-
// Revert any runtime option definitions configured so far and not committed.
LibDHCP::revertRuntimeOptionDefs();
// Let's set empty container in case a user hasn't specified any configuration
// Answer will hold the result.
ConstElementPtr answer;
- // Rollback informs whether error occurred and original data
- // have to be restored to global storages.
- bool rollback = false;
+
// Global parameter name in case of an error.
string parameter_name;
ElementPtr mutable_cfg;
ConstElementPtr ifaces_config = mutable_cfg->get("interfaces-config");
if (ifaces_config) {
parameter_name = "interfaces-config";
- IfacesConfigParser parser(AF_INET6, check_only);
+ IfacesConfigParser parser(AF_INET6, true);
CfgIfacePtr cfg_iface = srv_config->getCfgIface();
parser.parse(cfg_iface, ifaces_config);
}
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_FAIL)
.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.
- rollback = true;
} catch (...) {
// For things like bad_cast in boost::lexical_cast
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_EXCEPTION).arg(parameter_name);
- answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
- " processing error");
+ answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration "
+ "processing error");
+ }
- // An error occurred, so make sure that we restore original data.
- rollback = true;
+ if (!answer) {
+ answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration seems sane. "
+ "Control-socket, hook-libraries, and D2 configuration "
+ "were sanity checked, but not applied.");
}
- if (check_only) {
+ return (answer);
+}
+
+isc::data::ConstElementPtr
+configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
+ bool check_only) {
+ if (!config_set) {
+ ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
+ "Can't parse NULL config");
+ return (answer);
+ }
+
+ LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_CONFIG_START)
+ .arg(server.redactConfig(config_set)->str());
+
+ // Rollback informs whether error occurred and original data
+ // have to be restored to global storages.
+ bool rollback = false;
+
+ auto answer = processDhcp6Config(config_set);
+
+ int status_code = 0;
+ isc::config::parseAnswer(status_code, answer);
+ if (status_code != CONTROL_RESULT_SUCCESS) {
rollback = true;
- if (!answer) {
- answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS,
- "Configuration seems sane. Control-socket, hook-libraries, and D2 "
- "configuration were sanity checked, but not applied.");
+ }
+
+ SrvConfigPtr srv_config;
+
+ if (!rollback) {
+ if (!check_only) {
+ string parameter_name;
+ ElementPtr mutable_cfg;
+
+ // Close DHCP sockets and remove any existing timers.
+ IfaceMgr::instance().closeSockets();
+ TimerMgr::instance()->unregisterTimers();
+ server.discardPackets();
+ server.getCBControl()->reset();
+
+ try {
+
+ // Get the staging configuration.
+ srv_config = CfgMgr::instance().getStagingCfg();
+
+ // This is a way to convert ConstElementPtr to ElementPtr.
+ // We need a config that can be edited, because we will insert
+ // default values and will insert derived values as well.
+ mutable_cfg = boost::const_pointer_cast<Element>(config_set);
+
+ ConstElementPtr ifaces_config = mutable_cfg->get("interfaces-config");
+ if (ifaces_config) {
+ parameter_name = "interfaces-config";
+ IfacesConfigParser parser(AF_INET6, false);
+ CfgIfacePtr cfg_iface = srv_config->getCfgIface();
+ cfg_iface->reset();
+ parser.parse(cfg_iface, ifaces_config);
+ }
+ } catch (const isc::Exception& ex) {
+ LOG_ERROR(dhcp6_logger, DHCP6_PARSER_FAIL)
+ .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.
+ rollback = true;
+ } catch (...) {
+ // For things like bad_cast in boost::lexical_cast
+ LOG_ERROR(dhcp6_logger, DHCP6_PARSER_EXCEPTION).arg(parameter_name);
+ answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
+ " processing error");
+
+ // An error occurred, so make sure that we restore original data.
+ rollback = true;
+ }
+ } else {
+ rollback = true;
}
}
// both structures are built using the same order.
EXPECT_EQ(Element::fromJSON(expected_command)->str(),
entire_command->str());
- return (createAnswer(0, "long command received ok"));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, "long command received ok"));
}
/// @brief Command handler which generates long response
s << std::setw(5) << i;
arguments->add(Element::create(s.str()));
}
- return (createAnswer(0, arguments));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, arguments));
}
};
isc::data::ConstElementPtr
NetconfProcess::shutdown(isc::data::ConstElementPtr /*args*/) {
setShutdownFlag(true);
- return (isc::config::createAnswer(0, "Netconf is shutting down"));
+ return (isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Netconf is shutting down"));
}
isc::data::ConstElementPtr
ConstElementPtr
createAnswer() {
- return (createAnswer(0, string(""), ConstElementPtr()));
+ return (createAnswer(CONTROL_RESULT_SUCCESS, string(""), ConstElementPtr()));
}
ConstElementPtr
EXPECT_EQ("{ \"result\": 0 }", answer->str());
// Let's check if we can generate an error.
- answer = createAnswer(1, "error");
+ answer = createAnswer(CONTROL_RESULT_ERROR, "error");
EXPECT_EQ("{ \"result\": 1, \"text\": \"error\" }", answer->str());
// This is expected to throw. When status code is non-zero (indicating error),
// textual explanation is mandatory.
- EXPECT_THROW(createAnswer(1, ElementPtr()), CtrlChannelError);
- EXPECT_THROW(createAnswer(1, Element::create(1)), CtrlChannelError);
+ EXPECT_THROW(createAnswer(CONTROL_RESULT_ERROR, ElementPtr()), CtrlChannelError);
+ EXPECT_THROW(createAnswer(CONTROL_RESULT_ERROR, Element::create(1)), CtrlChannelError);
// Let's check if answer can be generate with some data in it.
ConstElementPtr arg = el("[ \"just\", \"some\", \"data\" ]");
- answer = createAnswer(0, arg);
+ answer = createAnswer(CONTROL_RESULT_SUCCESS, arg);
EXPECT_EQ("{ \"arguments\": [ \"just\", \"some\", \"data\" ], \"result\": 0 }",
answer->str());
}
// registered
// for it, combine the lists of commands.
if (!hooks_commands->empty()) {
- response = combineCommandsLists(response, createAnswer(0, hooks_commands));
+ response = combineCommandsLists(response, createAnswer(CONTROL_RESULT_SUCCESS, hooks_commands));
}
}
}
// Answer will hold the result.
ConstElementPtr answer;
if (!config_set) {
- answer = isc::config::createAnswer(1,
+ answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
string("Can't parse NULL config"));
return (answer);
}
}
// Everything was fine. Configuration is successful.
- answer = isc::config::createAnswer(0, "Configuration committed.");
+ answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration committed.");
} catch (const isc::Exception& ex) {
- answer = isc::config::createAnswer(1,
+ answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
string("Configuration parsing failed: ") + ex.what());
} catch (...) {
- answer = isc::config::createAnswer(1,
+ answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
string("Configuration parsing failed"));
}
using namespace std;
using namespace isc;
+using namespace isc::config;
using namespace isc::dhcp;
using namespace isc::data;
using namespace isc::asiolink;
bool check_only,
const std::function<void()>& post_config_cb) {
if (!config_set) {
- return (isc::config::createAnswer(1,
- std::string("Can't parse NULL config")));
+ return (isc::config::createAnswer(CONTROL_RESULT_ERROR,
+ std::string("Can't parse NULL config")));
}
LOG_DEBUG(dctl_logger, isc::log::DBGLVL_COMMAND, DCTL_CONFIG_START)
.arg(redactConfig(config_set)->str());
}
// Use the answer provided.
- //answer = isc::config::createAnswer(0, "Configuration committed.");
+ //answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration committed.");
} else {
LOG_INFO(dctl_logger, DCTL_CONFIG_CHECK_COMPLETE)
.arg(getConfigSummary(0))
} catch (const std::exception& ex) {
LOG_ERROR(dctl_logger, DCTL_PARSER_FAIL).arg(ex.what());
- answer = isc::config::createAnswer(1, ex.what());
+ answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
rollback = true;
}
setShutdownFlag(true);
stopIOService();
- return (isc::config::createAnswer(0, "Shutdown initiated."));
+ return (isc::config::createAnswer(isc::config::CONTROL_RESULT_SUCCESS,
+ "Shutdown initiated."));
}
isc::data::ConstElementPtr
DStubProcess::configure(isc::data::ConstElementPtr config_set, bool check_only) {
if (SimFailure::shouldFailOn(SimFailure::ftProcessConfigure)) {
// Simulates a process configure failure.
- return (isc::config::createAnswer(1,
- "Simulated process configuration error."));
+ return (isc::config::createAnswer(isc::config::CONTROL_RESULT_ERROR,
+ "Simulated process configuration error."));
}
return (getCfgMgr()->simpleParseConfig(config_set, check_only));
isc::data::ConstElementPtr
DStubCfgMgr::parse(isc::data::ConstElementPtr /*config*/, bool /*check_only*/) {
- return (isc::config::createAnswer(0, "It all went fine. I promise"));
+ return (isc::config::createAnswer(isc::config::CONTROL_RESULT_SUCCESS,
+ "It all went fine. I promise"));
}
} // namespace isc::process