diff options
3 files changed, 18 insertions, 206 deletions
diff --git a/buildscripts/resmokeconfig/suites/sharding_continuous_config_stepdown.yml b/buildscripts/resmokeconfig/suites/sharding_continuous_config_stepdown.yml index 30e5ad0e760..0c5f5d33c9f 100644 --- a/buildscripts/resmokeconfig/suites/sharding_continuous_config_stepdown.yml +++ b/buildscripts/resmokeconfig/suites/sharding_continuous_config_stepdown.yml @@ -136,7 +136,6 @@ selector: - jstests/sharding/mongos_no_replica_set_refresh.js - jstests/sharding/movechunk_interrupt_at_primary_stepdown.js - jstests/sharding/primary_config_server_blackholed_from_mongos.js - - jstests/sharding/reconfig_fails_no_cwwc_set_sharding.js # Nothing is affected by config server step down - jstests/sharding/basic_sharding_params.js # ShardingTest is never used, so continuous step down thread never starts diff --git a/jstests/sharding/reconfig_fails_no_cwwc_set_sharding.js b/jstests/sharding/reconfig_fails_no_cwwc_set_sharding.js deleted file mode 100644 index eb59cd03598..00000000000 --- a/jstests/sharding/reconfig_fails_no_cwwc_set_sharding.js +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Test that a reconfig for a shard that would change the implicit default write concern to w:1 - * fails if CWWC is not set. - * - * @tags: [requires_fcv_50, requires_majority_read_concern, requires_persistence] - */ - -(function() { -'use strict'; - -load("jstests/replsets/rslib.js"); // For reconfig, isConfigCommitted and - // safeReconfigShouldFail. - -const configurationIncompatibleMsg = - "config that would change the implicit default write concern on the shard to {w: 1}."; - -const configServerUnreachableMsg = "the request to the config server is failing with error:"; - -let addNodeConfig = function(rst, nodeId, conn, arbiter) { - const config = rst.getReplSetConfigFromNode(); - if (arbiter) { - config.members.push({_id: nodeId, host: conn.host, arbiterOnly: true}); - } else { - config.members.push({_id: nodeId, host: conn.host}); - } - - return config; -}; - -let removeNodeConfig = function(rst, conn) { - const config = rst.getReplSetConfigFromNode(); - for (var i = 0; i < config.members.length; i++) { - if (config.members[i].host == conn.host) { - config.members.splice(i, 1); - break; - } - } - - return config; -}; - -function testReconfig(rst, config, shouldSucceed, errCode, errMsg) { - if (shouldSucceed) { - reconfig(rst, config); - assert.soon(() => isConfigCommitted(rst.getPrimary())); - rst.waitForConfigReplication(rst.getPrimary()); - rst.awaitReplication(); - } else { - safeReconfigShouldFail(rst, config, false /* force */, errCode, errMsg); - - // A force reconfig should also fail. - safeReconfigShouldFail(rst, config, true /* force */, errCode, errMsg); - } -} - -jsTestLog("Testing to reconfig a shard that is not yet added to a sharded cluster."); -let logPrefix = "While the shard is not part of a sharded cluster: "; -let shardServer = new ReplSetTest( - {name: "shardServer", nodes: 1, nodeOptions: {shardsvr: ""}, useHostName: true}); -shardServer.startSet(); -shardServer.initiate(); - -jsTestLog(logPrefix + "Adding an arbiter node that will change IDWC to (w:1) should succeed."); -let arbiter = shardServer.add(); -testReconfig(shardServer, - addNodeConfig(shardServer, 1 /* nodeId */, arbiter /* conn */, true /* arbiter */), - true /* shouldSucceed */); - -jsTestLog(logPrefix + - "Removing an arbiter node that will change IDWC to (w: 'Majority') should succeed."); -shardServer.remove(arbiter); -testReconfig(shardServer, removeNodeConfig(shardServer, arbiter), true /* shouldSucceed */); - -shardServer.stopSet(); - -jsTestLog("Testing to reconfig a shard that is part of a sharded cluster."); -logPrefix = "While the shard is part of a sharded cluster: "; -shardServer = new ReplSetTest( - {name: "shardServer", nodes: 1, nodeOptions: {shardsvr: ""}, useHostName: true}); -shardServer.startSet(); -shardServer.initiate(); - -const st = new ShardingTest({shards: 0, mongos: 1}); -var admin = st.getDB('admin'); - -jsTestLog("Adding the shard to the cluster should succeed."); -assert.commandWorked(admin.runCommand({addshard: shardServer.getURL()})); - -jsTestLog(logPrefix + - "Adding an non-arbiter node that will keep IDWC set to (w: 'Majority') should succeed."); -testReconfig( - shardServer, - addNodeConfig(shardServer, 1 /* nodeId */, shardServer.add() /* conn */, false /* arbiter */), - true /* shouldSucceed */); - -jsTestLog(logPrefix + "Adding an arbiter node that will change IDWC to (w:1) should fail."); -arbiter = shardServer.add(); -testReconfig(shardServer, - addNodeConfig(shardServer, 2 /* nodeId */, arbiter /* conn */, true /* arbiter */), - false /* shouldSucceed */, - ErrorCodes.NewReplicaSetConfigurationIncompatible, - configurationIncompatibleMsg); - -jsTestLog("Setting the CWWC on the cluster."); -logPrefix = "While CWWC is set on the sharded cluster: "; -assert.commandWorked( - st.s.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {w: "majority", wtimeout: 0}})); - -jsTestLog(logPrefix + "Adding an arbiter node that will change IDWC to (w:1) should succeed."); -testReconfig(shardServer, - addNodeConfig(shardServer, 2 /* nodeId */, arbiter /* conn */, true /* arbiter */), - true /* shouldSucceed */); - -jsTestLog("Testing when the config server is unreachable."); -logPrefix = "While config server is unreachable: "; -jsTestLog("Shutting down all config servers"); -for (var i = 0; i < st.configRS.nodes.length; i++) { - st.stopConfigServer(i); -} -st.configRS.awaitNoPrimary(); - -// The reason why this is okay is because CWWC had to have been set for the cluster to get to this -// point, even if we can't check the config servers for it. -jsTestLog(logPrefix + - "Removing an arbiter node that will change IDWC to (w: 'Majority') should succeed."); -shardServer.remove(arbiter); -testReconfig(shardServer, removeNodeConfig(shardServer, arbiter), true /* shouldSucceed */); - -jsTestLog(logPrefix + "Adding an arbiter node that will change IDWC to (w: 1) should fail."); -testReconfig(shardServer, - addNodeConfig(shardServer, 2 /* nodeId */, arbiter /* conn */, true /* arbiter */), - false /* shouldSucceed */, - ErrorCodes.ConfigServerUnreachable, - configServerUnreachableMsg); - -jsTestLog("Restarting the config servers."); -logPrefix = "While the config server is reachable: "; -for (var i = 0; i < st.configRS.nodes.length; i++) { - st.restartConfigServer(i, undefined, undefined, true /* wait */); -} -st.configRS.awaitNodesAgreeOnPrimary(); -print("Sleeping for 60 seconds to let the other shards restart their ReplicaSetMonitors"); -sleep(60000); - -jsTestLog(logPrefix + "Adding an arbiter node will change IDWC to (w:1) should succeed."); -arbiter = shardServer.add(); -testReconfig(shardServer, - addNodeConfig(shardServer, 2 /* nodeId */, arbiter /* conn */, true /* arbiter */), - true /* shouldSucceed */); - -jsTestLog("Stopping the cluster."); -st.stop(); - -jsTestLog("Stopping the shard."); -shardServer.stopSet(); -})();
\ No newline at end of file diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index f63f9b90ece..69b769e0cc6 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -3467,57 +3467,26 @@ Status ReplicationCoordinatorImpl::_doReplSetReconfig(OperationContext* opCtx, return status; ReplSetConfig newConfig = newConfigStatus.getValue(); - // Excluding reconfigs that bump the config term during step-up from checking against changing - // the implicit default write concern, as it is not needed. - if (!skipSafetyChecks /* skipping step-up reconfig */) { + // If the new config changes the replica set's implicit default write concern, we fail the + // reconfig command. This includes force reconfigs, but excludes reconfigs that bump the config + // term during step-up. The user should set a cluster-wide write concern and attempt the + // reconfig command again. We also need to exclude shard servers from this validation, as shard + // servers don't store the cluster-wide write concern. + if (!skipSafetyChecks /* skipping step-up reconfig */ && + repl::feature_flags::gDefaultWCMajority.isEnabled( + serverGlobalParams.featureCompatibility) && + serverGlobalParams.clusterRole != ClusterRole::ShardServer && + !repl::enableDefaultWriteConcernUpdatesForInitiate.load()) { bool currIDWC = oldConfig.isImplicitDefaultWriteConcernMajority(); bool newIDWC = newConfig.isImplicitDefaultWriteConcernMajority(); - - // If the new config changes the replica set's implicit default write concern, we fail the - // reconfig command. This includes force reconfigs. - // The user should set a cluster-wide write concern and attempt the reconfig command again. - if (serverGlobalParams.clusterRole != ClusterRole::ShardServer) { - if (repl::feature_flags::gDefaultWCMajority.isEnabled( - serverGlobalParams.featureCompatibility) && - !repl::enableDefaultWriteConcernUpdatesForInitiate.load() && currIDWC != newIDWC && - !ReadWriteConcernDefaults::get(opCtx).isCWWCSet(opCtx)) { - return Status( - ErrorCodes::NewReplicaSetConfigurationIncompatible, - str::stream() - << "Reconfig attempted to install a config that would change the implicit " - "default write concern. Use the setDefaultRWConcern command to set a " - "cluster-wide write concern and try the reconfig again."); - } - } else { - // Allow all reconfigs if the shard is not part of a sharded cluster yet, however - // prevent changing the implicit default write concern to (w: 1) after it becomes part - // of a sharded cluster and CWWC is not set on the cluster. - // Remote call to the configServer should be done to check if CWWC is set on the - // cluster. - if (_externalState->isShardPartOfShardedCluster(opCtx) && currIDWC != newIDWC && - !newIDWC) { - try { - // Initiates a remote call to the config server. - if (!_externalState->isCWWCSetOnConfigShard(opCtx)) { - return Status( - ErrorCodes::NewReplicaSetConfigurationIncompatible, - str::stream() - << "Reconfig attempted to install a config that would change the " - "implicit default write concern on the shard to {w: 1}. Use the " - "setDefaultRWConcern command to set a cluster-wide write " - "concern on the cluster and try the reconfig again."); - } - } catch (const DBException& ex) { - return Status( - ErrorCodes::ConfigServerUnreachable, - str::stream() - << "Reconfig attempted to install a config that would change the " - "implicit default write concern on the shard to {w: 1}, but the " - "shard can not check if CWWC is set on the cluster, as the request " - "to the config server is failing with error: " + - ex.toString()); - } - } + bool isCWWCSet = ReadWriteConcernDefaults::get(opCtx).isCWWCSet(opCtx); + if (!isCWWCSet && currIDWC != newIDWC) { + return Status( + ErrorCodes::NewReplicaSetConfigurationIncompatible, + str::stream() + << "Reconfig attempted to install a config that would change the " + "implicit default write concern. Use the setDefaultRWConcern command to " + "set a cluster-wide write concern and try the reconfig again."); } } |