diff options
author | XueruiFa <xuerui.fa@mongodb.com> | 2023-03-28 13:47:51 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-03-28 15:52:51 +0000 |
commit | 126ce85a4844f7d7bf794567fc327926b47c1505 (patch) | |
tree | adfb564608ab13e75edca5779dfc1232f9e8a721 /src | |
parent | a1bc513d167d4238b0d88a94de74e19e84817791 (diff) | |
download | mongo-126ce85a4844f7d7bf794567fc327926b47c1505.tar.gz |
SERVER-73691: Require confirmation for upgrade/downgrade
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/commands/set_feature_compatibility_version.idl | 10 | ||||
-rw-r--r-- | src/mongo/db/commands/set_feature_compatibility_version_command.cpp | 62 | ||||
-rw-r--r-- | src/mongo/db/repl/repl_server_parameters.idl | 11 | ||||
-rw-r--r-- | src/mongo/shell/replsettest.js | 32 | ||||
-rw-r--r-- | src/mongo/shell/servers.js | 15 |
5 files changed, 103 insertions, 27 deletions
diff --git a/src/mongo/db/commands/set_feature_compatibility_version.idl b/src/mongo/db/commands/set_feature_compatibility_version.idl index ecdf2e5b1c3..565f8ee180c 100644 --- a/src/mongo/db/commands/set_feature_compatibility_version.idl +++ b/src/mongo/db/commands/set_feature_compatibility_version.idl @@ -58,6 +58,16 @@ commands: api_version: "" type: fcv_string fields: + confirm: + description: "A required parameter that ensures that the user is + upgrading/downgrading with support assistance. Internal setFCV + commands issue from the config svr will not require this parameter. + If this parameter is not specified from a user command, the setFCV + command will error out. This parameter is declared optional so that + we can provide the user with a custom error message if it is not + specified." + type: safeBool + optional: true fromConfigServer: description: "A boolean that indicates whether the command is being requested by a config server. Normally FCV upgrades between last-lts and anything diff --git a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp index 030e8a9d389..44ad2baf745 100644 --- a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp +++ b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp @@ -262,26 +262,6 @@ public: const DatabaseName&, const BSONObj& cmdObj, BSONObjBuilder& result) override { - // Always wait for at least majority writeConcern to ensure all writes involved in the - // upgrade process cannot be rolled back. There is currently no mechanism to specify a - // default writeConcern, so we manually call waitForWriteConcern upon exiting this command. - // - // TODO SERVER-25778: replace this with the general mechanism for specifying a default - // writeConcern. - ON_BLOCK_EXIT([&] { - WriteConcernResult res; - auto waitForWCStatus = waitForWriteConcern( - opCtx, - repl::ReplClientInfo::forClient(opCtx->getClient()).getLastOp(), - WriteConcernOptions( - repl::ReplSetConfig::kMajorityWriteConcernModeName, - WriteConcernOptions::SyncMode::UNSET, - // Propagate the user's wTimeout if one was given. Default is kNoTimeout. - opCtx->getWriteConcern().wTimeout), - &res); - CommandHelpers::appendCommandWCStatus(result, waitForWCStatus, res); - }); - // Ensure that this operation will be killed by the RstlKillOpThread during step-up or // stepdown. opCtx->setAlwaysInterruptAtStepDownOrUp_UNSAFE(); @@ -302,9 +282,49 @@ public: const auto requestedVersion = request.getCommandParameter(); const auto actualVersion = serverGlobalParams.featureCompatibility.getVersion(); + auto isConfirmed = request.getConfirm().value_or(false); + // TODO (SERVER-74398): Remove this flag once 7.0 is last LTS. + if (mongo::repl::requireConfirmInSetFcv) { + const auto upgradeMsg = + "Once you have upgraded to {}, you will not be able to downgrade FCV and binary version without support assistance. Please re-run this command with 'confirm: true' to acknowledge this and continue with the FCV upgrade."_format( + multiversion::toString(requestedVersion)); + const auto downgradeMsg = + "Once you have downgraded the FCV, if you choose to downgrade the binary version, " + "it will require support assistance. Please re-run this command with 'confirm: " + "true' to acknowledge this and continue with the FCV downgrade."; + uassert(7369100, + (requestedVersion > actualVersion ? upgradeMsg : downgradeMsg), + // If the request is from a config svr, skip requiring the 'confirm: true' + // parameter. + (isFromConfigServer || isConfirmed)); + } + + // Always wait for at least majority writeConcern to ensure all writes involved in the + // upgrade/downgrade process cannot be rolled back. There is currently no mechanism to + // specify a default writeConcern, so we manually call waitForWriteConcern upon exiting this + // command. + // + // TODO SERVER-25778: replace this with the general mechanism for specifying a default + // writeConcern. + ON_BLOCK_EXIT([&] { + WriteConcernResult res; + auto waitForWCStatus = waitForWriteConcern( + opCtx, + repl::ReplClientInfo::forClient(opCtx->getClient()).getLastOp(), + WriteConcernOptions( + repl::ReplSetConfig::kMajorityWriteConcernModeName, + WriteConcernOptions::SyncMode::UNSET, + // Propagate the user's wTimeout if one was given. Default is kNoTimeout. + opCtx->getWriteConcern().wTimeout), + &res); + CommandHelpers::appendCommandWCStatus(result, waitForWCStatus, res); + }); + if (requestedVersion == actualVersion) { // Set the client's last opTime to the system last opTime so no-ops wait for - // writeConcern. + // writeConcern. This will wait for any previous setFCV disk writes to be majority + // committed before returning to the user, if the previous setFCV command had updated + // the FCV but encountered failover afterwards. repl::ReplClientInfo::forClient(opCtx->getClient()).setLastOpToSystemLastOpTime(opCtx); // TODO SERVER-72796: Remove once gGlobalIndexesShardingCatalog is enabled. diff --git a/src/mongo/db/repl/repl_server_parameters.idl b/src/mongo/db/repl/repl_server_parameters.idl index a2aaabcd23d..c55580c92e9 100644 --- a/src/mongo/db/repl/repl_server_parameters.idl +++ b/src/mongo/db/repl/repl_server_parameters.idl @@ -611,6 +611,17 @@ server_parameters: cpp_varname: enableReconfigRollbackCommittedWritesCheck default: true + # TODO (SERVER-74398): Remove special handling of 'confirm: true' in setFCV. + requireConfirmInSetFcv: + description: >- + Determines if we must specify 'confirm: true' in the setFCV command. Enabled by default. + Test-only. + test_only: true + set_at: startup + cpp_vartype: bool + cpp_varname: requireConfirmInSetFcv + default: true + initialSyncMethod: description: >- Specifies which method of initial sync to use. Valid options are: fileCopyBased, diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js index ad1c8e1c037..6667d5dba62 100644 --- a/src/mongo/shell/replsettest.js +++ b/src/mongo/shell/replsettest.js @@ -1437,8 +1437,17 @@ var ReplSetTest = function(opts) { asCluster(self.nodes, function setFCV() { let fcv = setLastLTSFCV ? lastLTSFCV : lastContinuousFCV; print("Setting feature compatibility version for replica set to '" + fcv + "'"); - assert.commandWorked( - self.getPrimary().adminCommand({setFeatureCompatibilityVersion: fcv})); + const res = self.getPrimary().adminCommand({setFeatureCompatibilityVersion: fcv}); + // TODO (SERVER-74398): Remove the retry with 'confirm: true' once 7.0 is last LTS. + if (!res.ok && res.code === 7369100) { + // We failed due to requiring 'confirm: true' on the command. This will only + // occur on 7.0+ nodes that have 'enableTestCommands' set to false. Retry the + // setFCV command with 'confirm: true'. + assert.commandWorked(self.getPrimary().adminCommand( + {setFeatureCompatibilityVersion: fcv, confirm: true})); + } else { + assert.commandWorked(res); + } checkFCV(self.getPrimary().getDB("admin"), fcv); // The server has a practice of adding a reconfig as part of upgrade/downgrade logic @@ -1606,8 +1615,17 @@ var ReplSetTest = function(opts) { asCluster(self.nodes, function setFCV() { let fcv = jsTest.options().replSetFeatureCompatibilityVersion; print("Setting feature compatibility version for replica set to '" + fcv + "'"); - assert.commandWorked( - self.getPrimary().adminCommand({setFeatureCompatibilityVersion: fcv})); + const res = self.getPrimary().adminCommand({setFeatureCompatibilityVersion: fcv}); + // TODO (SERVER-74398): Remove the retry with 'confirm: true' once 7.0 is last LTS. + if (!res.ok && res.code === 7369100) { + // We failed due to requiring 'confirm: true' on the command. This will only + // occur on 7.0+ nodes that have 'enableTestCommands' set to false. Retry the + // setFCV command with 'confirm: true'. + assert.commandWorked(self.getPrimary().adminCommand( + {setFeatureCompatibilityVersion: fcv, confirm: true})); + } else { + assert.commandWorked(res); + } // Wait for the new 'featureCompatibilityVersion' to propagate to all nodes in the // replica set. The 'setFeatureCompatibilityVersion' command only waits for @@ -2845,6 +2863,12 @@ var ReplSetTest = function(opts) { // downgrading from latest to last continuous. options.setParameter.disableTransitionFromLatestToLastContinuous = options.setParameter.disableTransitionFromLatestToLastContinuous || false; + + // TODO (SERVER-74398): Remove special handling of 'confirm: true' once we no longer run + // suites with v6.X. We disable this check by default now so that we can pass suites + // without individually handling each multiversion test running on old binaries. + options.setParameter.requireConfirmInSetFcv = + options.setParameter.requireConfirmInSetFcv || false; } if (tojson(options) != tojson({})) diff --git a/src/mongo/shell/servers.js b/src/mongo/shell/servers.js index 58808c2aaa7..2e6e5bbbb2e 100644 --- a/src/mongo/shell/servers.js +++ b/src/mongo/shell/servers.js @@ -710,10 +710,10 @@ MongoRunner.mongodOptions = function(opts = {}) { opts.pathOpts = Object.merge(opts.pathOpts, {dbpath: opts.dbpath}); - // TODO (SERVER-74847): Remove this transition once we remove testing around - // downgrading from latest to last continuous. opts.setParameter = opts.setParameter || {}; if (jsTestOptions().enableTestCommands && typeof opts.setParameter !== "string") { + // TODO (SERVER-74847): Remove this transition once we remove testing around + // downgrading from latest to last continuous. if (jsTestOptions().setParameters && jsTestOptions().setParameters.disableTransitionFromLatestToLastContinuous) { opts.setParameter["disableTransitionFromLatestToLastContinuous"] = @@ -721,6 +721,16 @@ MongoRunner.mongodOptions = function(opts = {}) { } else { opts.setParameter["disableTransitionFromLatestToLastContinuous"] = false; } + + // TODO (SERVER-74398): Remove special handling of 'confirm: true' once we no longer run + // suites with v6.X. We disable this check by default now so that we can pass suites + // without individually handling each multiversion test running on old binaries. + if (jsTestOptions().setParameters && jsTestOptions().setParameters.requireConfirmInSetFcv) { + opts.setParameter["requireConfirmInSetFcv"] = + jsTestOptions().setParameters.requireConfirmInSetFcv; + } else { + opts.setParameter["requireConfirmInSetFcv"] = false; + } } _removeSetParameterIfBeforeVersion(opts, "writePeriodicNoops", "3.3.12"); @@ -739,6 +749,7 @@ MongoRunner.mongodOptions = function(opts = {}) { opts, "internalQueryDisableExclusionProjectionFastPath", "6.2.0"); _removeSetParameterIfBeforeVersion( opts, "disableTransitionFromLatestToLastContinuous", "7.0.0"); + _removeSetParameterIfBeforeVersion(opts, "requireConfirmInSetFcv", "7.0.0"); if (!opts.logFile && opts.useLogFiles) { opts.logFile = opts.dbpath + "/mongod.log"; |