summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/multiVersion/initiate_shard_server_with_secondaryDelaySecs.js126
-rw-r--r--src/mongo/db/repl/repl_set_config_checks.cpp44
2 files changed, 153 insertions, 17 deletions
diff --git a/jstests/multiVersion/initiate_shard_server_with_secondaryDelaySecs.js b/jstests/multiVersion/initiate_shard_server_with_secondaryDelaySecs.js
new file mode 100644
index 00000000000..7b46a84ea7b
--- /dev/null
+++ b/jstests/multiVersion/initiate_shard_server_with_secondaryDelaySecs.js
@@ -0,0 +1,126 @@
+/**
+ * Tests that new shard servers using the 'latest' binary in 'lastLTSFCV' are able to use the
+ * 'secondaryDelaySecs' field. Once the shard is added to a sharded cluster, it must abide by
+ * the FCV restrictions of that cluster.
+ */
+
+(function() {
+"use strict";
+
+function checkForSecondaryDelaySecs(primaryDB) {
+ let config = primaryDB.runCommand({replSetGetConfig: 1}).config;
+ assert.eq(config.members[0].secondaryDelaySecs, 0, config);
+ assert(!config.members[0].hasOwnProperty('slaveDelay'), config);
+}
+
+function checkForSlaveDelaySecs(primaryDB) {
+ let config = primaryDB.runCommand({replSetGetConfig: 1}).config;
+ assert.eq(config.members[0].slaveDelay, 0, config);
+ assert(!config.members[0].hasOwnProperty('secondaryDelaySecs'), config);
+}
+
+// A 'latest' binary cluster started with clean data files will initialize shard servers
+// with 'lastLTSFCV' and then use addShard to get them to 'latestFCV'.
+const st = new ShardingTest({
+ shards: {rs0: {nodes: [{binVersion: "latest"}]}},
+});
+const mongosAdminDB = st.s.getDB("admin");
+const configPrimaryAdminDB = st.configRS.getPrimary().getDB("admin");
+const shardPrimaryAdminDB = st.rs0.getPrimary().getDB("admin");
+
+checkFCV(configPrimaryAdminDB, latestFCV);
+checkFCV(shardPrimaryAdminDB, latestFCV);
+
+jsTestLog("Test adding a shard server to cluster running 'latest' binaries and 'latestFCV'");
+// A 'latest' binary replica set started as a shard server defaults to 'lastLTSFCV'. Allow
+// the use of 'secondaryDelaySecs' before the shard server is added to a cluster.
+let shard2 = new ReplSetTest({
+ name: "shard2",
+ nodes: [{binVersion: "latest", rsConfig: {secondaryDelaySecs: 0}}],
+ nodeOptions: {shardsvr: ""},
+ useHostName: true
+});
+
+shard2.startSet();
+shard2.initiate();
+let latestShardPrimaryAdminDB = shard2.getPrimary().getDB("admin");
+checkFCV(latestShardPrimaryAdminDB, lastLTSFCV);
+// Even though shard2 is in the 'lastLTSFCV', its config should still have the
+// 'secondaryDelaySecs' field.
+let config = checkForSecondaryDelaySecs(latestShardPrimaryAdminDB);
+
+// The cluster is in the 'latestFCV', so adding shard2 to the cluster should update shard2's
+// FCV.
+assert.commandWorked(mongosAdminDB.runCommand({addShard: shard2.getURL()}));
+checkFCV(latestShardPrimaryAdminDB, latestFCV);
+
+// FCV can be set to 'lastLTSFCV' on mongos.
+assert.commandWorked(mongosAdminDB.runCommand({setFeatureCompatibilityVersion: lastLTSFCV}));
+
+// featureCompatibilityVersion propagates to the config, existing shard, and newly added shard.
+checkFCV(configPrimaryAdminDB, lastLTSFCV);
+checkFCV(shardPrimaryAdminDB, lastLTSFCV);
+checkFCV(latestShardPrimaryAdminDB, lastLTSFCV);
+
+// The FCV was downgraded to 'lastLTSFCV', which is 4.4 in this case. During FCV downgrade, the
+// 'secondaryDelaySecs' will automatically be changed to 'slaveDelay'.
+checkForSlaveDelaySecs(latestShardPrimaryAdminDB);
+checkForSlaveDelaySecs(configPrimaryAdminDB);
+checkForSlaveDelaySecs(shardPrimaryAdminDB);
+
+jsTestLog("Test adding a shard server to cluster running 'latest' binaries and 'lastLTSFCV'");
+// A 'latest' binary replica set started as a shard server defaults to 'lastLTSFCV'. Allow
+// the use of 'secondaryDelaySecs' before the shard server is added to a cluster.
+let shard3 = new ReplSetTest({
+ name: "shard3",
+ nodes: [{binVersion: "latest", rsConfig: {secondaryDelaySecs: 0}}],
+ nodeOptions: {shardsvr: ""},
+ useHostName: true
+});
+
+shard3.startSet();
+shard3.initiate();
+latestShardPrimaryAdminDB = shard3.getPrimary().getDB("admin");
+checkFCV(latestShardPrimaryAdminDB, lastLTSFCV);
+// Even though shard3 is in the 'lastLTSFCV', its config should still have the
+// 'secondaryDelaySecs' field.
+checkForSecondaryDelaySecs(latestShardPrimaryAdminDB);
+
+// The cluster is also in the 'lastLTSFCV', so adding shard3 to a downgraded cluster will not
+// update shard3's FCV.
+assert.commandWorked(mongosAdminDB.runCommand({addShard: shard3.getURL()}));
+checkFCV(latestShardPrimaryAdminDB, lastLTSFCV);
+// Since the FCV was not updated, secondaryDelaySecs is still present in the config.
+checkForSecondaryDelaySecs(latestShardPrimaryAdminDB);
+
+// The cluster wide FCV is 'lastLTSFCV', which is 4.4 in this case. Despite replSetGetConfig
+// returning 'secondaryDelaySecs' for shard3, future reconfigs on shard3 must use 'slaveDelay'.
+config = latestShardPrimaryAdminDB.runCommand({replSetGetConfig: 1}).config;
+config.version++;
+assert.commandFailedWithCode(latestShardPrimaryAdminDB.runCommand({replSetReconfig: config}),
+ ErrorCodes.NewReplicaSetConfigurationIncompatible);
+
+delete config.members[0].secondaryDelaySecs;
+config.members[0].slaveDelay = 0;
+config.version++;
+
+// Test that a reconfig with 'slaveDelay' succeeds.
+assert.commandWorked(latestShardPrimaryAdminDB.runCommand({replSetReconfig: config}));
+checkForSlaveDelaySecs(latestShardPrimaryAdminDB);
+
+// FCV can be set to 'latestFCV' on mongos.
+assert.commandWorked(mongosAdminDB.runCommand({setFeatureCompatibilityVersion: latestFCV}));
+checkFCV(st.configRS.getPrimary().getDB("admin"), latestFCV);
+checkFCV(shardPrimaryAdminDB, latestFCV);
+checkFCV(latestShardPrimaryAdminDB, latestFCV);
+
+checkForSecondaryDelaySecs(latestShardPrimaryAdminDB);
+checkForSecondaryDelaySecs(configPrimaryAdminDB);
+checkForSecondaryDelaySecs(shardPrimaryAdminDB);
+
+// Call ShardingTest.stop before shutting down shard2 and shard3, so that the UUID check in
+// ShardingTest.stop can talk to them.
+st.stop();
+shard2.stopSet();
+shard3.stopSet();
+})();
diff --git a/src/mongo/db/repl/repl_set_config_checks.cpp b/src/mongo/db/repl/repl_set_config_checks.cpp
index 20ad4106e2f..e4da3276793 100644
--- a/src/mongo/db/repl/repl_set_config_checks.cpp
+++ b/src/mongo/db/repl/repl_set_config_checks.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/repl/repl_server_parameters_gen.h"
#include "mongo/db/repl/repl_set_config.h"
#include "mongo/db/repl/replication_coordinator_external_state.h"
+#include "mongo/db/s/sharding_state.h"
#include "mongo/db/service_context.h"
#include "mongo/util/str.h"
@@ -105,6 +106,11 @@ Status ensureNoNewlyAddedMembers(const ReplSetConfig& config) {
*/
Status isFCVCompatible(const ReplSetConfig& config) {
auto version = serverGlobalParams.featureCompatibility.getVersion();
+ // New shard servers using 'latest' binaries will default to the 'lastLTS' FCV prior to being
+ // added to the cluster. If they have not yet been added to a sharded cluster via addShard,
+ // allow them to use 'secondaryDelaySecs'.
+ bool isNewShardServer = (serverGlobalParams.clusterRole == ClusterRole::ShardServer &&
+ !ShardingState::get(getGlobalServiceContext())->enabled());
// TODO (SERVER-53354) If we are currently upgrading, we check if the feature flag is enabled
// for the target version. We use the generic FCV references here to avoid having to update the
// FCV constants used after each continuous release. After release, we should make sure to
@@ -121,24 +127,28 @@ Status isFCVCompatible(const ReplSetConfig& config) {
bool isEnabled = feature_flags::gUseSecondaryDelaySecs.isEnabled(targetFCV);
// We must check that every member config has a valid delay field name.
for (auto iter = config.membersBegin(); iter != config.membersEnd(); ++iter) {
- if ((isEnabled && iter->hasSlaveDelay()) || (!isEnabled && iter->hasSecondaryDelaySecs())) {
- // TODO (SERVER-53354) If the feature flag is disabled, getVersion() will throw. In this
- // case, the version should default to kLatest. We use the generic FCV references here
- // to avoid having to update the FCV constants used after each continuous release. After
- // release, we should make sure to remove these references while removing the feature
- // flag.
- //
- //(Generic FCV reference): feature flag support
- auto featureFlagVersion = isEnabled
- ? FeatureCompatibilityVersionParser::toString(
- feature_flags::gUseSecondaryDelaySecs.getVersion())
- : FeatureCompatibilityVersionParser::toString(
- ServerGlobalParams::FeatureCompatibility::kLatest);
+ // TODO (SERVER-53354) If the feature flag is disabled, getVersion() will throw. In this
+ // case, the version should default to kLatest. We use the generic FCV references here
+ // to avoid having to update the FCV constants used after each continuous release. After
+ // release, we should make sure to remove these references while removing the feature
+ // flag.
+ //
+ //(Generic FCV reference): feature flag support
+ if (isEnabled && iter->hasSlaveDelay()) {
+ auto featureFlagVersion = FeatureCompatibilityVersionParser::toString(
+ feature_flags::gUseSecondaryDelaySecs.getVersion());
return Status(ErrorCodes::BadValue,
- str::stream() << "If the node is in FCV " << featureFlagVersion
- << ", we must use the secondaryDelaySecs field name "
- "instead of slaveDelay. Only nodes below FCV "
- << featureFlagVersion << " should use slaveDelay.");
+ str::stream()
+ << "Incompatible delay field name. If the node is in FCV "
+ << featureFlagVersion << ", it must use secondaryDelaySecs.");
+ }
+ //(Generic FCV reference): feature flag support
+ if (!isEnabled && iter->hasSecondaryDelaySecs() && !isNewShardServer) {
+ auto latestVersion = FeatureCompatibilityVersionParser::toString(
+ ServerGlobalParams::FeatureCompatibility::kLatest);
+ return Status(ErrorCodes::BadValue,
+ str::stream() << "Incompatible delay field name. In FCV versions below "
+ << latestVersion << ", nodes must use slaveDelay.");
}
}