#include <ha_service_states.h>
#include <cc/dhcp_config_error.h>
#include <util/file_utilities.h>
+#include <boost/make_shared.hpp>
#include <limits>
#include <set>
namespace isc {
namespace ha {
-void
-HAConfigParser::parse(const HAConfigMapperPtr& config_storage,
- const ConstElementPtr& config) {
+HAConfigMapperPtr
+HAConfigParser::parse(const ConstElementPtr& config) {
try {
+ auto config_storage = boost::make_shared<HAConfigMapper>();
+
// This may cause different types of exceptions. We catch them here
// and throw unified exception type.
parseAllInternal(config_storage, config);
+ validateRelationships(config_storage);
logConfigStatus(config_storage);
+ return (config_storage);
} catch (const ConfigError& ex) {
throw;
auto peer_configs = rel_config->getAllServersConfig();
for (auto peer_config : peer_configs) {
- config_storage->map(peer_config.first, rel_config);
+ try {
+ config_storage->map(peer_config.first, rel_config);
+
+ } catch (...) {
+ isc_throw(HAConfigValidationError, "server names must be unique for different relationships");
+ }
}
}
template<typename T>
T HAConfigParser::getAndValidateInteger(const ConstElementPtr& config,
- const std::string& parameter_name) const {
+ const std::string& parameter_name) {
int64_t value = getInteger(config, parameter_name);
if (value < 0) {
isc_throw(ConfigError, "'" << parameter_name << "' must not be negative");
}
void
-HAConfigParser::logConfigStatus(const HAConfigMapperPtr& config_storage) const {
+HAConfigParser::logConfigStatus(const HAConfigMapperPtr& config_storage) {
LOG_INFO(ha_logger, HA_CONFIGURATION_SUCCESSFUL);
for (auto config : config_storage->getAll()) {
}
}
+void
+HAConfigParser::validateRelationships(const HAConfigMapperPtr& config_storage) {
+ auto configs = config_storage->getAll();
+ if (configs.size() <= 1) {
+ return;
+ }
+ std::unordered_set<std::string> server_names;
+ for (auto config : configs) {
+ // Only the hot-standby mode is supported for multiple relationships.
+ if (config->getHAMode() != HAConfig::HOT_STANDBY) {
+ isc_throw(HAConfigValidationError, "multiple HA relationships are only supported for 'hot-standby' mode");
+ }
+ }
+}
+
} // namespace ha
} // namespace isc
/// @brief Parses HA configuration.
///
- /// @param [out] config_storage Pointer to the object where parsed configuration
- /// is going to be stored.
- ///
/// @param config specified configuration.
- /// @throw ConfigError when parsing fails or configuration is invalid.
- void parse(const HAConfigMapperPtr& config_storage,
- const data::ConstElementPtr& config);
+ /// @return Pointer to the object where parsed configuration is stored.
+ /// @throw HAConfigValidationError when parsing fails or configuration is invalid.
+ static HAConfigMapperPtr parse(const data::ConstElementPtr& config);
private:
/// is going to be stored.
///
/// @param config Specified configuration.
- void parseAllInternal(const HAConfigMapperPtr& config_storage,
- const data::ConstElementPtr& config);
+ static void parseAllInternal(const HAConfigMapperPtr& config_storage,
+ const data::ConstElementPtr& config);
/// @brief Parses HA configuration for a single relationship.
///
///
/// @param config specified configuration for a relationship.
/// @throw ConfigError when parsing fails or configuration is invalid.
- void parseOneInternal(const HAConfigMapperPtr& config_storage,
- const data::ElementPtr& config);
+ static void parseOneInternal(const HAConfigMapperPtr& config_storage,
+ const data::ElementPtr& config);
/// @brief Validates and returns a value of the parameter.
///
/// @param parameter_name parameter name to be fetched from the configuration.
/// @tparam T parameter type, e.g. @c uint16_t, @c uint32_t etc.
template<typename T>
- T getAndValidateInteger(const data::ConstElementPtr& config,
- const std::string& parameter_name) const;
+ static T getAndValidateInteger(const data::ConstElementPtr& config,
+ const std::string& parameter_name);
/// @brief Logs various information related to the successfully parsed
/// configuration.
///
/// One example of such information is a warning message indicating that
/// sending lease updates is disabled.
- void logConfigStatus(const HAConfigMapperPtr& config_storage) const;
+ static void logConfigStatus(const HAConfigMapperPtr& config_storage);
+
+ /// @brief Validates dependencies between the relationships.
+ ///
+ /// @throw HAConfigValidationError when there are configuration errors
+ /// between the relationships.
+ static void validateRelationships(const HAConfigMapperPtr& config_storage);
};
} // end of namespace isc::ha
namespace ha {
HAImpl::HAImpl()
- : config_(new HAConfigMapper()) {
+ : config_() {
}
void
HAImpl::configure(const ConstElementPtr& input_config) {
- HAConfigParser parser;
- parser.parse(config_, input_config);
+ config_ = HAConfigParser::parse(input_config);
}
void
" ]"
" }"
"]",
- "'this-server-name' must be unique for different relationships");
+ "server names must be unique for different relationships");
}
setDHCPMultiThreadingConfig(true, 3);
// Create the HA configuration
- HAConfigMapperPtr ha_config(new HAConfigMapper());
- HAConfigParser parser;
- ASSERT_NO_THROW_LOG(parser.parse(ha_config, config_json));
+ HAConfigMapperPtr ha_config;
+ ASSERT_NO_THROW_LOG(ha_config = HAConfigParser::parse(config_json));
// Instantiate the service.
TestHAServicePtr service;
setDHCPMultiThreadingConfig(true, 3);
// Create the HA configuration
- HAConfigMapperPtr ha_config(new HAConfigMapper());
- HAConfigParser parser;
- ASSERT_NO_THROW_LOG(parser.parse(ha_config, config_json));
+ HAConfigMapperPtr ha_config;
+ ASSERT_NO_THROW_LOG(ha_config = HAConfigParser::parse(config_json));
// Instantiate the service.
TestHAServicePtr service;
MultiThreadingMgr::instance().setMode(scenario.dhcp_mt_enabled_);
// Create the HA configuration
- HAConfigMapperPtr ha_config(new HAConfigMapper());
- HAConfigParser parser;
- ASSERT_NO_THROW_LOG(parser.parse(ha_config, config_json));
+ HAConfigMapperPtr ha_config;
+ ASSERT_NO_THROW_LOG(ha_config = HAConfigParser::parse(config_json));
// Instantiate the service.
TestHAServicePtr service;
"]";
// Parse the HA configuration.
- HAConfigMapperPtr config_storage(new HAConfigMapper());
- HAConfigParser parser;
- ASSERT_NO_THROW(parser.parse(config_storage, Element::fromJSON(config_text)));
+ HAConfigMapperPtr config_storage;
+ ASSERT_NO_THROW(config_storage = HAConfigParser::parse(Element::fromJSON(config_text)));
TestHAService service(io_service_, network_state_, config_storage->get());
service.query_filter_.serveDefaultScopes();
HAConfigPtr
HATest::createValidConfiguration(const HAConfig::HAMode& ha_mode) const {
- HAConfigMapperPtr config_storage(new HAConfigMapper());
- HAConfigParser parser;
-
- parser.parse(config_storage, createValidJsonConfiguration(ha_mode));
+ auto config_storage = HAConfigParser::parse(createValidJsonConfiguration(ha_mode));
return (config_storage->get());
}
HAConfigPtr
HATest::createValidPassiveBackupConfiguration() const {
- HAConfigMapperPtr config_storage(new HAConfigMapper());
- HAConfigParser parser;
-
- parser.parse(config_storage, createValidPassiveBackupJsonConfiguration());
+ auto config_storage = HAConfigParser::parse(createValidPassiveBackupJsonConfiguration());
return (config_storage->get());
}