// This test verifies that externally configured globals are
// merged correctly into staging configuration.
-TEST_F(Dhcp6CBTest, DISABLED_mergeGlobals) {
+TEST_F(Dhcp6CBTest, mergeGlobals) {
string base_config =
"{ \n"
" \"interfaces-config\": { \n"
if (CfgMgr::instance().getFamily() == AF_INET) {
merge4(other_srv_config);
} else {
- /// @todo merge6();
+ merge6(other_srv_config);
}
} catch (const std::bad_cast&) {
isc_throw(InvalidOperation, "internal server error: must use derivation"
// We merge objects in order of dependency (real or theoretical).
// Merge globals.
- mergeGlobals4(other);
+ mergeGlobals(other);
// Merge option defs. We need to do this next so we
// pass these into subsequent merges so option instances
// definitions.
cfg_option_def_->merge((*other.getCfgOptionDef()));
- // Merge options.
+ // Merge options.
cfg_option_->merge(cfg_option_def_, (*other.getCfgOption()));
// Merge shared networks.
cfg_shared_networks4_->merge(cfg_option_def_, *(other.getCfgSharedNetworks4()));
// Merge subnets.
- cfg_subnets4_->merge(cfg_option_def_, getCfgSharedNetworks4(),
+ cfg_subnets4_->merge(cfg_option_def_, getCfgSharedNetworks4(),
*(other.getCfgSubnets4()));
/// @todo merge other parts of the configuration here.
}
void
-SrvConfig::mergeGlobals4(SrvConfig& other) {
+SrvConfig::merge6(SrvConfig& other) {
+ // We merge objects in order of dependency (real or theoretical).
+
+ // Merge globals.
+ mergeGlobals(other);
+
+#if 0
+ // Merge option defs. We need to do this next so we
+ // pass these into subsequent merges so option instances
+ // at each level can be created based on the merged
+ // definitions.
+ cfg_option_def_->merge((*other.getCfgOptionDef()));
+
+ // Merge options.
+ cfg_option_->merge(cfg_option_def_, (*other.getCfgOption()));
+
+ // Merge shared networks.
+ cfg_shared_networks6_->merge(cfg_option_def_, *(other.getCfgSharedNetworks6()));
+
+ // Merge subnets.
+ cfg_subnets6_->merge(cfg_option_def_, getCfgSharedNetworks4(),
+ *(other.getCfgSubnets6()));
+#endif
+
+ /// @todo merge other parts of the configuration here.
+}
+
+void
+SrvConfig::mergeGlobals(SrvConfig& other) {
// Iterate over the "other" globals, adding/overwriting them into
// this config's list of globals.
for (auto other_global : other.getConfiguredGlobals()->mapValue()) {
addConfiguredGlobal(other_global.first, other_global.second);
}
- // A handful of values are stored as members in SrvConfig. So we'll
+ // A handful of values are stored as members in SrvConfig. So we'll
// iterate over the merged globals, setting approprate members.
for (auto merged_global : getConfiguredGlobals()->mapValue()) {
std::string name = merged_global.first;
setDeclinePeriod(element->intValue());
}
else if (name == "echo-client-id") {
+ // echo-client-id is v4 only, but we'll let upstream
+ // worry about that.
setEchoClientId(element->boolValue());
}
else if (name == "dhcp4o6port") {
}
}
+
void
SrvConfig::removeStatistics() {
/// into this configuration.
void merge4(SrvConfig& other);
+ /// @brief Merges the DHCPv6 configuration specified as a parameter into
+ /// this configuration.
+ ///
+ /// The general rule is that the configuration data from the @c other
+ /// object replaces configuration data held in this object instance.
+ /// The data that do not overlap between the two objects is simply
+ /// inserted into this configuration.
+ ///
+ /// @warning The call to @c merge may modify the data in the @c other
+ /// object. Therefore, the caller must not rely on the data held
+ /// in the @c other object after the call to @c merge. Also, the
+ /// data held in @c other must not be modified after the call to
+ /// @c merge because it may affect the merged configuration.
+ ///
+ /// The @c other parameter must be a @c SrvConfig or its derivation.
+ ///
+ /// Currently, the following parts of the v6 configuration are merged:
+ /// - globals
+ /// - shared-networks
+ /// - subnets
+ ///
+ /// @todo Add support for merging other configuration elements.
+ ///
+ /// @param other An object holding the configuration to be merged
+ /// into this configuration.
+ void merge6(SrvConfig& other);
- /// @brief Merges the DHCPv4 globals specified in the given configuration
+ /// @brief Merges the globals specified in the given configuration
/// into this configuration.
///
/// Configurable global values may be specified either via JSON
///
/// @param other An object holding the configuration to be merged
/// into this configuration.
- void mergeGlobals4(SrvConfig& other);
+ void mergeGlobals(SrvConfig& other);
/// @brief Sequence number identifying the configuration.
uint32_t sequence_;
// Let's create the "existing" config we will merge into.
SrvConfig cfg_to;
- // Set some explicit values.
+ // Set some explicit values.
cfg_to.setDeclinePeriod(100);
cfg_to.setEchoClientId(false);
cfg_to.setDhcp4o6Port(777);
// server-tag port should be the "from" configured value.
EXPECT_EQ("use_this_server", cfg_to.getServerTag().get());
- // Next we check the explicitly "configured" globals.
+ // Next we check the explicitly "configured" globals.
+ // The list should be all of the "to" + "from", with the
+ // latter overwriting the former.
+ std::string exp_globals =
+ "{ \n"
+ " \"decline-probation-period\": 300, \n"
+ " \"dhcp4o6port\": 999, \n"
+ " \"server-tag\": \"use_this_server\" \n"
+ "} \n";
+
+ ConstElementPtr expected_globals;
+ ASSERT_NO_THROW(expected_globals = Element::fromJSON(exp_globals))
+ << "exp_globals didn't parse, test is broken";
+
+ EXPECT_TRUE(isEquivalent(expected_globals, cfg_to.getConfiguredGlobals()));
+
+}
+
+// This test verifies that globals from one SrvConfig
+// can be merged into another. It verifies that values
+// in the from-config override those in to-config which
+// override those in GLOBAL4_DEFAULTS.
+TEST_F(SrvConfigTest, mergeGlobals6) {
+ // Set the family we're working with.
+ CfgMgr::instance().setFamily(AF_INET6);
+
+ // Let's create the "existing" config we will merge into.
+ SrvConfig cfg_to;
+
+ // Set some explicit values.
+ cfg_to.setDeclinePeriod(100);
+ cfg_to.setEchoClientId(false);
+ cfg_to.setDhcp4o6Port(777);
+ cfg_to.setServerTag("not_this_server");
+
+ // Add some configured globals
+ cfg_to.addConfiguredGlobal("decline-probation-period", Element::create(300));
+ cfg_to.addConfiguredGlobal("dhcp4o6port", Element::create(888));
+
+ // Now we'll create the config we'll merge from.
+ SrvConfig cfg_from;
+
+ // Set some explicit values. None of these should be preserved.
+ cfg_from.setDeclinePeriod(200);
+ cfg_from.setEchoClientId(true);
+ cfg_from.setDhcp4o6Port(888);
+ cfg_from.setServerTag("nor_this_server");
+
+ // Add some configured globals:
+ cfg_to.addConfiguredGlobal("dhcp4o6port", Element::create(999));
+ cfg_to.addConfiguredGlobal("server-tag", Element::create("use_this_server"));
+
+ // Now let's merge.
+ ASSERT_NO_THROW(cfg_to.merge(cfg_from));
+
+ // Make sure the explicit values are set correctly.
+
+ // decline-probation-period should be the "to" configured value.
+ EXPECT_EQ(300, cfg_to.getDeclinePeriod());
+
+ // dhcp4o6port should be the "from" configured value.
+ EXPECT_EQ(999, cfg_to.getDhcp4o6Port());
+
+ // server-tag port should be the "from" configured value.
+ EXPECT_EQ("use_this_server", cfg_to.getServerTag().get());
+
+ // Next we check the explicitly "configured" globals.
// The list should be all of the "to" + "from", with the
// latter overwriting the former.
std::string exp_globals =