Skip to content

Commit b87b25e

Browse files
ldennisEvergreen Agent
authored andcommitted
SERVER-50122: Support running mixed versions with last-continuous in ReplSetTest/ShardingTest
1 parent f719f1b commit b87b25e

File tree

3 files changed

+144
-111
lines changed

3 files changed

+144
-111
lines changed

jstests/sharding/explainFind_stale_mongos.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ assert.commandWorked(freshMongos.adminCommand({enableSharding: dbName}));
2222
assert.commandWorked(freshMongos.adminCommand({shardCollection: ns, key: {"_id": 1}}));
2323

2424
jsTest.log("Ensure the shard knows " + ns + " is sharded");
25-
if (st.isMixedVersionCluster()) {
25+
const clusterVersionInfo = st.getClusterVersionInfo();
26+
if (clusterVersionInfo.isMixedVersion) {
2627
assert.commandWorked(
2728
st.shard0.adminCommand({_flushRoutingTableCacheUpdates: ns, syncFromConfig: true}));
2829
} else {

src/mongo/shell/replsettest.js

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,21 +1294,31 @@ var ReplSetTest = function(opts) {
12941294
cmd[cmdKey] = config;
12951295

12961296
// Initiating a replica set with a single node will use "latest" FCV. This will
1297-
// cause IncompatibleServerVersion errors if additional "last-lts" binary version
1298-
// nodes are subsequently added to the set, since such nodes cannot set their FCV to
1299-
// "latest". Therefore, we make sure the primary is "last-lts" FCV before adding in
1300-
// nodes of different binary versions to the replica set.
1297+
// cause IncompatibleServerVersion errors if additional "last-lts"/"last-continuous" binary
1298+
// version nodes are subsequently added to the set, since such nodes cannot set their FCV to
1299+
// "latest". Therefore, we make sure the primary is "last-lts"/"last-continuous" FCV before
1300+
// adding in nodes of different binary versions to the replica set.
13011301
let lastLTSBinVersionWasSpecifiedForSomeNode = false;
1302+
let lastContinuousBinVersionWasSpecifiedForSomeNode = false;
13021303
let explicitBinVersionWasSpecifiedForSomeNode = false;
13031304
Object.keys(this.nodeOptions).forEach(function(key, index) {
13041305
let val = self.nodeOptions[key];
13051306
if (typeof (val) === "object" && val.hasOwnProperty("binVersion")) {
13061307
lastLTSBinVersionWasSpecifiedForSomeNode =
13071308
MongoRunner.areBinVersionsTheSame(val.binVersion, lastLTSFCV);
1309+
lastContinuousBinVersionWasSpecifiedForSomeNode =
1310+
(lastLTSFCV !== lastContinuousFCV) &&
1311+
MongoRunner.areBinVersionsTheSame(val.binVersion, lastContinuousFCV);
13081312
explicitBinVersionWasSpecifiedForSomeNode = true;
13091313
}
13101314
});
13111315

1316+
if (lastLTSBinVersionWasSpecifiedForSomeNode &&
1317+
lastContinuousBinVersionWasSpecifiedForSomeNode) {
1318+
throw new Error("Can only specify one of 'last-lts' and 'last-continuous' " +
1319+
"in binVersion, not both.");
1320+
}
1321+
13121322
// If no binVersions have been explicitly set, then we should be using the latest binary
13131323
// version, which allows us to use the failpoint below.
13141324
let explicitBinVersion =
@@ -1347,26 +1357,33 @@ var ReplSetTest = function(opts) {
13471357
print("ReplSetTest initiate command took " + (new Date() - initiateStart) + "ms for " +
13481358
this.nodes.length + " nodes in set '" + this.name + "'");
13491359

1350-
// Set the FCV to 'last-lts' if we are running a mixed version replica set. If this is a
1351-
// config server, the FCV will be set as part of ShardingTest.
1360+
// Set the FCV to 'last-lts'/'last-continuous' if we are running a mixed version replica
1361+
// set. If this is a config server, the FCV will be set as part of ShardingTest.
1362+
// TODO SERVER-50389: Set FCV to 'last-continuous' properly when last-continuous binary
1363+
// versions are supported with the useRandomBinVersionsWithinReplicaSet option.
13521364
let setLastLTSFCV = (lastLTSBinVersionWasSpecifiedForSomeNode ||
13531365
jsTest.options().useRandomBinVersionsWithinReplicaSet) &&
13541366
!self.isConfigServer;
1355-
if (setLastLTSFCV && jsTest.options().replSetFeatureCompatibilityVersion) {
1367+
let setLastContinuousFCV = !setLastLTSFCV &&
1368+
lastContinuousBinVersionWasSpecifiedForSomeNode && !self.isConfigServer;
1369+
1370+
if ((setLastLTSFCV || setLastContinuousFCV) &&
1371+
jsTest.options().replSetFeatureCompatibilityVersion) {
1372+
const fcv = setLastLTSFCV ? lastLTSFCV : lastContinuousFCV;
13561373
throw new Error(
1357-
"The FCV will be set to 'last-lts' automatically when starting up a replica " +
1374+
"The FCV will be set to '" + fcv + "' automatically when starting up a replica " +
13581375
"set with mixed binary versions. Therefore, we expect an empty value for " +
13591376
"'replSetFeatureCompatibilityVersion'.");
13601377
}
13611378

1362-
if (setLastLTSFCV) {
1379+
if (setLastLTSFCV || setLastContinuousFCV) {
13631380
// Authenticate before running the command.
13641381
asCluster(self.nodes, function setFCV() {
1365-
let fcv = lastLTSFCV;
1382+
let fcv = setLastLTSFCV ? lastLTSFCV : lastContinuousFCV;
13661383
print("Setting feature compatibility version for replica set to '" + fcv + "'");
13671384
assert.commandWorked(
13681385
self.getPrimary().adminCommand({setFeatureCompatibilityVersion: fcv}));
1369-
checkFCV(self.getPrimary().getDB("admin"), lastLTSFCV);
1386+
checkFCV(self.getPrimary().getDB("admin"), fcv);
13701387
print("Fetch the config version from primay since 4.4 downgrade runs a reconfig.");
13711388
config.version = self.getReplSetConfigFromNode().version;
13721389
});
@@ -2946,6 +2963,8 @@ var ReplSetTest = function(opts) {
29462963
options.binVersion = "latest";
29472964
} else {
29482965
const rand = Random.rand();
2966+
// TODO SERVER-50389: Support last-continuous binary version with
2967+
// useRandomBinVersionsWithinReplicaSet.
29492968
options.binVersion = rand < 0.5 ? "latest" : "last-lts";
29502969
}
29512970
print("Randomly assigned binary version: " + options.binVersion + " to node: " + n);

src/mongo/shell/shardingtest.js

Lines changed: 112 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -980,76 +980,92 @@ var ShardingTest = function(params) {
980980
};
981981

982982
/**
983-
* Returns whether any settings to ShardingTest or jsTestOptions indicate this is a multiversion
984-
* cluster.
983+
* Returns a document {isMixedVersion: <bool>, oldestBinVersion: <string>}.
984+
* The 'isMixedVersion' field is true if any settings to ShardingTest or jsTestOptions indicate
985+
* this is a multiversion cluster.
986+
* The 'oldestBinVersion' field is set to the oldest binary version used in this cluster, one of
987+
* 'latest', 'last-continuous' and 'last-lts'.
988+
* Note: Mixed version cluster with binary versions older than 'last-lts' is not supported. If
989+
* such binary exists in the cluster, this function assumes this is not a mixed version cluster
990+
* and returns 'oldestBinVersion' as 'latest'.
985991
*
986-
* Checks for 'last-lts' bin versions via:
992+
* Checks for bin versions via:
987993
* jsTestOptions().shardMixedBinVersions, jsTestOptions().mongosBinVersion,
988994
* otherParams.configOptions.binVersion, otherParams.shardOptions.binVersion,
989995
* otherParams.mongosOptions.binVersion
990996
*/
991-
this.isMixedVersionCluster = function() {
992-
var lastLTSBinVersion = MongoRunner.getBinVersionFor('last-lts');
993-
994-
// Must check shardMixedBinVersion because it causes shardOptions.binVersion to be an object
995-
// (versionIterator) rather than a version string. Must check mongosBinVersion, as well,
996-
// because it does not update mongosOptions.binVersion.
997-
if (jsTestOptions().shardMixedBinVersions ||
998-
(jsTestOptions().mongosBinVersion &&
999-
MongoRunner.areBinVersionsTheSame(lastLTSBinVersion,
1000-
jsTestOptions().mongosBinVersion))) {
1001-
return true;
1002-
}
997+
this.getClusterVersionInfo = function() {
998+
function clusterHasBinVersion(version) {
999+
const binVersion = MongoRunner.getBinVersionFor(version);
1000+
const hasBinVersionInParams = (params) => {
1001+
return params && params.binVersion &&
1002+
MongoRunner.areBinVersionsTheSame(
1003+
binVersion, MongoRunner.getBinVersionFor(params.binVersion));
1004+
};
10031005

1004-
// Check for 'last-lts' config servers.
1005-
if (otherParams.configOptions && otherParams.configOptions.binVersion &&
1006-
MongoRunner.areBinVersionsTheSame(
1007-
lastLTSBinVersion,
1008-
MongoRunner.getBinVersionFor(otherParams.configOptions.binVersion))) {
1009-
return true;
1010-
}
1011-
for (var i = 0; i < numConfigs; ++i) {
1012-
if (otherParams['c' + i] && otherParams['c' + i].binVersion &&
1013-
MongoRunner.areBinVersionsTheSame(
1014-
lastLTSBinVersion,
1015-
MongoRunner.getBinVersionFor(otherParams['c' + i].binVersion))) {
1006+
// Must check shardMixedBinVersion because it causes shardOptions.binVersion to be an
1007+
// object (versionIterator) rather than a version string. Must check mongosBinVersion,
1008+
// as well, because it does not update mongosOptions.binVersion.
1009+
// TODO SERVER-50389: Differentiate between 'last-lts' and 'last-continuous' when
1010+
// last-continuous is supported with shardMixedBinVersions.
1011+
if (jsTestOptions().shardMixedBinVersions ||
1012+
(jsTestOptions().mongosBinVersion &&
1013+
MongoRunner.areBinVersionsTheSame(binVersion, jsTestOptions().mongosBinVersion))) {
10161014
return true;
10171015
}
1018-
}
10191016

1020-
// Check for 'last-lts' mongod servers.
1021-
if (otherParams.shardOptions && otherParams.shardOptions.binVersion &&
1022-
MongoRunner.areBinVersionsTheSame(
1023-
lastLTSBinVersion,
1024-
MongoRunner.getBinVersionFor(otherParams.shardOptions.binVersion))) {
1025-
return true;
1026-
}
1027-
for (var i = 0; i < numShards; ++i) {
1028-
if (otherParams['d' + i] && otherParams['d' + i].binVersion &&
1029-
MongoRunner.areBinVersionsTheSame(
1030-
lastLTSBinVersion,
1031-
MongoRunner.getBinVersionFor(otherParams['d' + i].binVersion))) {
1017+
// Check for config servers.
1018+
if (hasBinVersionInParams(otherParams.configOptions)) {
10321019
return true;
10331020
}
1034-
}
1021+
for (let i = 0; i < numConfigs; ++i) {
1022+
if (hasBinVersionInParams(otherParams['c' + i])) {
1023+
return true;
1024+
}
1025+
}
10351026

1036-
// Check for 'last-lts' mongos servers.
1037-
if (otherParams.mongosOptions && otherParams.mongosOptions.binVersion &&
1038-
MongoRunner.areBinVersionsTheSame(
1039-
lastLTSBinVersion,
1040-
MongoRunner.getBinVersionFor(otherParams.mongosOptions.binVersion))) {
1041-
return true;
1042-
}
1043-
for (var i = 0; i < numMongos; ++i) {
1044-
if (otherParams['s' + i] && otherParams['s' + i].binVersion &&
1045-
MongoRunner.areBinVersionsTheSame(
1046-
lastLTSBinVersion,
1047-
MongoRunner.getBinVersionFor(otherParams['s' + i].binVersion))) {
1027+
// Check for mongod servers.
1028+
if (hasBinVersionInParams(otherParams.shardOptions)) {
1029+
return true;
1030+
}
1031+
if (hasBinVersionInParams(otherParams.rs)) {
10481032
return true;
10491033
}
1034+
for (let i = 0; i < numShards; ++i) {
1035+
if (hasBinVersionInParams(otherParams['d' + i])) {
1036+
return true;
1037+
}
1038+
if (hasBinVersionInParams(otherParams['rs' + i])) {
1039+
return true;
1040+
}
1041+
}
1042+
1043+
// Check for mongos servers.
1044+
if (hasBinVersionInParams(otherParams.mongosOptions)) {
1045+
return true;
1046+
}
1047+
for (let i = 0; i < numMongos; ++i) {
1048+
if (hasBinVersionInParams(otherParams['s' + i])) {
1049+
return true;
1050+
}
1051+
}
1052+
1053+
return false;
10501054
}
10511055

1052-
return false;
1056+
let hasLastLTS = clusterHasBinVersion("last-lts");
1057+
let hasLastContinuous = clusterHasBinVersion("last-continuous");
1058+
if ((lastLTSFCV !== lastContinuousFCV) && hasLastLTS && hasLastContinuous) {
1059+
throw new Error("Can only specify one of 'last-lts' and 'last-continuous' " +
1060+
"in binVersion, not both.");
1061+
}
1062+
if (hasLastLTS) {
1063+
return {isMixedVersion: true, oldestBinVersion: "last-lts"};
1064+
} else if (hasLastContinuous) {
1065+
return {isMixedVersion: true, oldestBinVersion: "last-continuous"};
1066+
} else {
1067+
return {isMixedVersion: false, oldestBinVersion: "latest"};
1068+
}
10531069
};
10541070

10551071
/**
@@ -1279,6 +1295,8 @@ var ShardingTest = function(params) {
12791295
// version
12801296
// shard cluster that randomly assigns shard binVersions, half "latest" and half
12811297
// "last-lts".
1298+
// TODO SERVER-50389: Support last-continuous binary version with
1299+
// shardMixedBinVersions.
12821300
if (!otherParams.shardOptions.binVersion) {
12831301
Random.setRandomSeed();
12841302
otherParams.shardOptions.binVersion =
@@ -1354,6 +1372,8 @@ var ShardingTest = function(params) {
13541372
// If the test doesn't depend on specific shard binVersions, create a mixed version
13551373
// shard cluster that randomly assigns shard binVersions, half "latest" and half
13561374
// "last-lts".
1375+
// TODO SERVER-50389: Support last-continuous binary version with
1376+
// shardMixedBinVersions.
13571377
if (!otherParams.shardOptions.binVersion) {
13581378
Random.setRandomSeed();
13591379
otherParams.shardOptions.binVersion =
@@ -1646,10 +1666,11 @@ var ShardingTest = function(params) {
16461666
}
16471667

16481668
const configRS = this.configRS;
1649-
if (_hasNewFeatureCompatibilityVersion() && this.isMixedVersionCluster()) {
1669+
const clusterVersionInfo = this.getClusterVersionInfo();
1670+
if (_hasNewFeatureCompatibilityVersion() && clusterVersionInfo.isMixedVersion) {
1671+
const fcv = binVersionToFCV(clusterVersionInfo.oldestBinVersion);
16501672
function setFeatureCompatibilityVersion() {
1651-
assert.commandWorked(
1652-
csrsPrimary.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV}));
1673+
assert.commandWorked(csrsPrimary.adminCommand({setFeatureCompatibilityVersion: fcv}));
16531674

16541675
// Wait for the new featureCompatibilityVersion to propagate to all nodes in the CSRS
16551676
// to ensure that older versions of mongos can successfully connect.
@@ -1798,50 +1819,42 @@ var ShardingTest = function(params) {
17981819
// Ensure that the sessions collection exists so jstests can run things with
17991820
// logical sessions and test them. We do this by forcing an immediate cache refresh
18001821
// on the config server, which auto-shards the collection for the cluster.
1801-
var lastLTSBinVersion = MongoRunner.getBinVersionFor('last-lts');
1802-
if ((!otherParams.configOptions) ||
1803-
(otherParams.configOptions && !otherParams.configOptions.binVersion) ||
1804-
(otherParams.configOptions && otherParams.configOptions.binVersion &&
1805-
MongoRunner.areBinVersionsTheSame(
1806-
lastLTSBinVersion,
1807-
MongoRunner.getBinVersionFor(otherParams.configOptions.binVersion)))) {
1808-
this.configRS.getPrimary().getDB("admin").runCommand({refreshLogicalSessionCacheNow: 1});
1809-
1810-
const x509AuthRequired = (mongosOptions[0] && mongosOptions[0].clusterAuthMode &&
1811-
mongosOptions[0].clusterAuthMode === "x509");
1812-
1813-
// Flushes the routing table cache on connection 'conn'. If 'keyFileLocal' is defined,
1814-
// authenticates the keyfile user on 'authConn' - a connection or set of connections for
1815-
// the shard - before executing the flush.
1816-
const flushRT = function flushRoutingTableAndHandleAuth(conn, authConn, keyFileLocal) {
1817-
// Invokes the actual execution of cache refresh.
1818-
const execFlushRT = (conn) => {
1819-
assert.commandWorked(conn.getDB("admin").runCommand(
1820-
{_flushRoutingTableCacheUpdates: "config.system.sessions"}));
1821-
};
1822-
1823-
if (keyFileLocal) {
1824-
authutil.asCluster(authConn, keyFileLocal, () => execFlushRT(conn));
1825-
} else {
1826-
execFlushRT(conn);
1827-
}
1822+
this.configRS.getPrimary().getDB("admin").runCommand({refreshLogicalSessionCacheNow: 1});
1823+
1824+
const x509AuthRequired = (mongosOptions[0] && mongosOptions[0].clusterAuthMode &&
1825+
mongosOptions[0].clusterAuthMode === "x509");
1826+
1827+
// Flushes the routing table cache on connection 'conn'. If 'keyFileLocal' is defined,
1828+
// authenticates the keyfile user on 'authConn' - a connection or set of connections for
1829+
// the shard - before executing the flush.
1830+
const flushRT = function flushRoutingTableAndHandleAuth(conn, authConn, keyFileLocal) {
1831+
// Invokes the actual execution of cache refresh.
1832+
const execFlushRT = (conn) => {
1833+
assert.commandWorked(conn.getDB("admin").runCommand(
1834+
{_flushRoutingTableCacheUpdates: "config.system.sessions"}));
18281835
};
18291836

1830-
// TODO SERVER-45108: Enable support for x509 auth for _flushRoutingTableCacheUpdates.
1831-
if (!otherParams.manualAddShard && !x509AuthRequired) {
1832-
for (let i = 0; i < numShards; i++) {
1833-
const keyFileLocal =
1834-
(otherParams.shards && otherParams.shards[i] && otherParams.shards[i].keyFile)
1835-
? otherParams.shards[i].keyFile
1836-
: this.keyFile;
1837-
1838-
if (otherParams.rs || otherParams["rs" + i] || startShardsAsRS) {
1839-
const rs = this._rs[i].test;
1840-
flushRT(rs.getPrimary(), rs.nodes, keyFileLocal);
1841-
} else {
1842-
// If specified, use the keyFile for the standalone shard.
1843-
flushRT(this["shard" + i], this["shard" + i], keyFileLocal);
1844-
}
1837+
if (keyFileLocal) {
1838+
authutil.asCluster(authConn, keyFileLocal, () => execFlushRT(conn));
1839+
} else {
1840+
execFlushRT(conn);
1841+
}
1842+
};
1843+
1844+
// TODO SERVER-45108: Enable support for x509 auth for _flushRoutingTableCacheUpdates.
1845+
if (!otherParams.manualAddShard && !x509AuthRequired) {
1846+
for (let i = 0; i < numShards; i++) {
1847+
const keyFileLocal =
1848+
(otherParams.shards && otherParams.shards[i] && otherParams.shards[i].keyFile)
1849+
? otherParams.shards[i].keyFile
1850+
: this.keyFile;
1851+
1852+
if (otherParams.rs || otherParams["rs" + i] || startShardsAsRS) {
1853+
const rs = this._rs[i].test;
1854+
flushRT(rs.getPrimary(), rs.nodes, keyFileLocal);
1855+
} else {
1856+
// If specified, use the keyFile for the standalone shard.
1857+
flushRT(this["shard" + i], this["shard" + i], keyFileLocal);
18451858
}
18461859
}
18471860
}

0 commit comments

Comments
 (0)