summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiyuan Zhou <siyuan.zhou@mongodb.com>2020-02-05 23:06:59 +0000
committerevergreen <evergreen@mongodb.com>2020-02-05 23:06:59 +0000
commit244523d59e21d58bbf8af3ddd803c5148f767e13 (patch)
tree4b08326c8a96d565c38445c1eec2da94119cc178
parent134a81cad1d62af9327bf9df19c5720c6e72fe9e (diff)
downloadmongo-244523d59e21d58bbf8af3ddd803c5148f767e13.tar.gz
SERVER-45408 Enable serialization of config "term" field
SERVER-45092 Remove “term” field of config document on downgrade
-rw-r--r--jstests/multiVersion/remove_config_term_on_replset_downgrade.js73
-rw-r--r--jstests/replsets/reconfig_ignores_term_field.js3
-rw-r--r--src/mongo/db/commands/feature_compatibility_version.cpp11
-rw-r--r--src/mongo/db/repl/repl_set_config.cpp9
4 files changed, 91 insertions, 5 deletions
diff --git a/jstests/multiVersion/remove_config_term_on_replset_downgrade.js b/jstests/multiVersion/remove_config_term_on_replset_downgrade.js
new file mode 100644
index 00000000000..4315fdcc506
--- /dev/null
+++ b/jstests/multiVersion/remove_config_term_on_replset_downgrade.js
@@ -0,0 +1,73 @@
+/**
+ * Test the downgrade of a replica set from latest version to last-stable version succeeds and
+ * removes the "term" field of config document.
+ */
+
+(function() {
+'use strict';
+
+load('jstests/multiVersion/libs/multi_rs.js');
+load('jstests/libs/test_background_ops.js');
+
+let newVersion = "latest";
+let oldVersion = "last-stable";
+
+let nodes = {
+ n1: {binVersion: newVersion},
+ n2: {binVersion: newVersion},
+ n3: {binVersion: newVersion}
+};
+
+let rst = new ReplSetTest({nodes: nodes});
+rst.startSet();
+rst.initiate();
+
+let primary = rst.getPrimary();
+
+// The default FCV is latestFCV for non-shard replica sets.
+let primaryAdminDB = rst.getPrimary().getDB("admin");
+checkFCV(primaryAdminDB, latestFCV);
+
+// Reconfig in FCV 4.4.
+let originalConfig = rst.getReplSetConfigFromNode();
+originalConfig.version++;
+reconfig(rst, originalConfig);
+rst.awaitNodesAgreeOnConfigVersion();
+
+// Check that the term field exists in the config document on all nodes.
+rst.nodes.forEach(function(node) {
+ jsTestLog("Checking the config term on node " + tojson(node.host) + " before downgrade.");
+ let config = node.getDB("local").getCollection("system.replset").findOne();
+ assert(config.hasOwnProperty("term"));
+});
+
+// Remember the config from the primary before the downgrade.
+let configInNewVersion = rst.getReplSetConfigFromNode();
+
+jsTest.log("Downgrading FCV to 4.2");
+assert.commandWorked(primary.adminCommand({setFeatureCompatibilityVersion: lastStableFCV}));
+rst.awaitReplication();
+// Check that the term field doesn't exist in the config document on all nodes.
+rst.nodes.forEach(function(node) {
+ jsTestLog("Checking the config term on node " + tojson(node.host) + " after FCV downgrade.");
+ let config = node.getDB("local").getCollection("system.replset").findOne();
+ assert(!config.hasOwnProperty("term"), tojson(config));
+ config.term = configInNewVersion.term;
+ assert.docEq(configInNewVersion, config);
+});
+
+jsTest.log("Downgrading replica set..");
+rst.upgradeSet({binVersion: oldVersion});
+jsTest.log("Downgrade complete.");
+
+// Check that the term field doesn't exist in the config document on all nodes.
+rst.nodes.forEach(function(node) {
+ reconnect(node);
+ jsTestLog("Checking the config term on node " + tojson(node.host) + " after binary downgrade.");
+ let config = node.getDB("local").getCollection("system.replset").findOne();
+ assert(!config.hasOwnProperty("term"), tojson(config));
+ config.term = configInNewVersion.term;
+ assert.docEq(configInNewVersion, config);
+});
+rst.stopSet();
+})();
diff --git a/jstests/replsets/reconfig_ignores_term_field.js b/jstests/replsets/reconfig_ignores_term_field.js
index bfe3d5b9d20..2cc48ac950d 100644
--- a/jstests/replsets/reconfig_ignores_term_field.js
+++ b/jstests/replsets/reconfig_ignores_term_field.js
@@ -25,7 +25,6 @@ assert.commandWorked(primary.getDB("admin").runCommand({replSetReconfig: config}
replTest.awaitReplication();
config = primary.getDB("local").system.replset.findOne();
-// TODO SERVER-45408: uncomment once we enable serialization of the term field.
-// assert.eq(config.term, 1);
+assert.eq(config.term, 1);
replTest.stopSet();
}()); \ No newline at end of file
diff --git a/src/mongo/db/commands/feature_compatibility_version.cpp b/src/mongo/db/commands/feature_compatibility_version.cpp
index 48ed157c26f..c98457c1f86 100644
--- a/src/mongo/db/commands/feature_compatibility_version.cpp
+++ b/src/mongo/db/commands/feature_compatibility_version.cpp
@@ -162,6 +162,17 @@ void FeatureCompatibilityVersion::onInsertOrUpdate(OperationContext* opCtx, cons
<< FeatureCompatibilityVersionParser::toString(newVersion);
}
+ // Remove term field of config document on downgrade.
+ if (newVersion == ServerGlobalParams::FeatureCompatibility::Version::kFullyDowngradedTo42 &&
+ repl::ReplicationCoordinator::get(opCtx)->getReplicationMode() ==
+ repl::ReplicationCoordinator::modeReplSet) {
+ auto storageInterface = repl::StorageInterface::get(opCtx);
+ repl::UnreplicatedWritesBlock uwb(opCtx);
+ repl::TimestampedBSONObj update{BSON("$unset" << BSON("term" << 1)), Timestamp()};
+ uassertStatusOK(storageInterface->updateSingleton(
+ opCtx, NamespaceString::kSystemReplSetNamespace, {}, update));
+ }
+
opCtx->recoveryUnit()->onCommit([opCtx, newVersion](boost::optional<Timestamp>) {
serverGlobalParams.featureCompatibility.setVersion(newVersion);
updateMinWireVersion();
diff --git a/src/mongo/db/repl/repl_set_config.cpp b/src/mongo/db/repl/repl_set_config.cpp
index 375e2a73d61..5094f610c8e 100644
--- a/src/mongo/db/repl/repl_set_config.cpp
+++ b/src/mongo/db/repl/repl_set_config.cpp
@@ -862,9 +862,12 @@ BSONObj ReplSetConfig::toBSON() const {
BSONObjBuilder configBuilder;
configBuilder.append(kIdFieldName, _replSetName);
configBuilder.appendIntOrLL(kVersionFieldName, _version);
- // TODO (SERVER-45408): Enable serialization of the config "term" field once we can handle it
- // properly in upgrade/downgrade scenarios.
- // configBuilder.appendIntOrLL(kTermFieldName, _term);
+
+ if (serverGlobalParams.featureCompatibility.isVersion(
+ ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo44)) {
+ configBuilder.appendIntOrLL(kTermFieldName, _term);
+ }
+
if (_configServer) {
// Only include "configsvr" field if true
configBuilder.append(kConfigServerFieldName, _configServer);