diff options
| author | Xuerui Fa <xuerui.fa@mongodb.com> | 2024-04-03 19:46:32 -0400 |
|---|---|---|
| committer | MongoDB Bot <mongo-bot@mongodb.com> | 2024-04-03 23:54:34 +0000 |
| commit | fb78dc746d92d85b1ad752eb9236a058912f2452 (patch) | |
| tree | 88543ddb3b9e4c8b31e7ff3717b58f929302dfef | |
| parent | 3a678285957b4a1695aa7d3ba65e90ceadf8db27 (diff) | |
SERVER-87898: Prepare server for FCV 8.1 upgrade (#20740)r8.1.0-alpha
GitOrigin-RevId: 0a8d8383477d3c96c5443e33242da2d74620ca21
29 files changed, 21 insertions, 2426 deletions
diff --git a/buildscripts/resmokeconfig/matrix_suites/generated_suites/multiversion_auth_future_git_tag.yml b/buildscripts/resmokeconfig/matrix_suites/generated_suites/multiversion_auth_future_git_tag.yml index 82bf30d5418..d48d7f0cfa1 100644 --- a/buildscripts/resmokeconfig/matrix_suites/generated_suites/multiversion_auth_future_git_tag.yml +++ b/buildscripts/resmokeconfig/matrix_suites/generated_suites/multiversion_auth_future_git_tag.yml @@ -32,7 +32,6 @@ selector: - jstests/multiVersion/genericBinVersion/minor_version_tags_new_old_new.js - jstests/multiVersion/genericSetFCVUsage/crash_mongos_against_upgraded_cluster.js - jstests/multiVersion/genericBinVersion/load_keys_on_upgrade.js - - jstests/multiVersion/targetedTestsLastLtsFeatures/oidc_multipurpose_idp.js exclude_with_any_tags: - DISABLED_TEMPORARILY_DUE_TO_FCV_UPGRADE roots: diff --git a/buildscripts/resmokeconfig/matrix_suites/overrides/multiversion.yml b/buildscripts/resmokeconfig/matrix_suites/overrides/multiversion.yml index e168edc0bda..ce8555f9a21 100644 --- a/buildscripts/resmokeconfig/matrix_suites/overrides/multiversion.yml +++ b/buildscripts/resmokeconfig/matrix_suites/overrides/multiversion.yml @@ -149,7 +149,6 @@ # Skip any tests that run with auth explicitly. - jstests/multiVersion/genericBinVersion/load_keys_on_upgrade.js - - jstests/multiVersion/targetedTestsLastLtsFeatures/oidc_multipurpose_idp.js exclude_with_any_tags: - DISABLED_TEMPORARILY_DUE_TO_FCV_UPGRADE executor: diff --git a/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_replica_sets_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_replica_sets_jscore_passthrough.yml index be13188c6e8..b6ef585ed7e 100644 --- a/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_replica_sets_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_replica_sets_jscore_passthrough.yml @@ -28,6 +28,7 @@ selector: - requires_fcv_72 - requires_fcv_73 - requires_fcv_80 + - requires_fcv_81 # Exclude tests that are not compatible with upgrade/downgrade. - cannot_run_during_upgrade_downgrade diff --git a/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_sharded_collections_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_sharded_collections_jscore_passthrough.yml index 79c99084b3c..a1296cfb261 100644 --- a/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_sharded_collections_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_sharded_collections_jscore_passthrough.yml @@ -197,6 +197,7 @@ selector: - requires_fcv_72 - requires_fcv_73 - requires_fcv_80 + - requires_fcv_81 # Exclude tests that are not compatible with upgrade/downgrade. - cannot_run_during_upgrade_downgrade diff --git a/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_sharding_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_sharding_jscore_passthrough.yml index ed645ac1c80..908e723d9c5 100644 --- a/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_sharding_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/fcv_upgrade_downgrade_sharding_jscore_passthrough.yml @@ -150,6 +150,7 @@ selector: - requires_fcv_72 - requires_fcv_73 - requires_fcv_80 + - requires_fcv_81 # Exclude tests that are not compatible with upgrade/downgrade. - cannot_run_during_upgrade_downgrade diff --git a/buildscripts/resmokeconfig/suites/multiversion_auth.yml b/buildscripts/resmokeconfig/suites/multiversion_auth.yml index 367f699ae84..af4df130c99 100644 --- a/buildscripts/resmokeconfig/suites/multiversion_auth.yml +++ b/buildscripts/resmokeconfig/suites/multiversion_auth.yml @@ -21,7 +21,6 @@ selector: # Skip any tests that run with auth explicitly. - jstests/multiVersion/genericBinVersion/load_keys_on_upgrade.js - - jstests/multiVersion/targetedTestsLastLtsFeatures/oidc_multipurpose_idp.js exclude_with_any_tags: - featureFlagToaster diff --git a/evergreen/multiversion_setup.sh b/evergreen/multiversion_setup.sh index c1cbc3ebae6..7a6e5f782b7 100644 --- a/evergreen/multiversion_setup.sh +++ b/evergreen/multiversion_setup.sh @@ -41,7 +41,7 @@ local_args="--edition $edition \ --resmokeCmd \"python buildscripts/resmoke.py\" \ --debug \ ${last_lts_arg} \ - ${last_continuous_arg} 4.2 4.4 5.0 6.0" + ${last_continuous_arg} 4.2 4.4 5.0 6.0 7.0" remote_invocation="${base_command} ${evergreen_args} ${local_args}" eval "${remote_invocation}" diff --git a/jstests/multiVersion/downgrade_fcv_only_if_internal_transaction_is_not_prepared.js b/jstests/multiVersion/downgrade_fcv_only_if_internal_transaction_is_not_prepared.js deleted file mode 100644 index 6648b16afba..00000000000 --- a/jstests/multiVersion/downgrade_fcv_only_if_internal_transaction_is_not_prepared.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Verify that during FCV downgrade we abort unprepared internal - * transactions and wait for prepared internal transactions to - * commit or abort. - * - * This test verifies this behavior with internal transactions in sessions with - * retryableWrite: {false, true}, distinguished through the specification of txnNumber in their - * lsids. Variables named with 0 correlates to the former and 1 with the latter. - * @tags: [requires_fcv_60] - */ -import {configureFailPoint} from "jstests/libs/fail_point_util.js"; -import { - makeAbortTransactionCmdObj, - makePrepareTransactionCmdObj -} from "jstests/sharding/libs/sharded_transactions_helpers.js"; - -const kDbName = "testDb"; -const kCollName = "testColl"; -let stmtId = 0; - -function makeInsertCmdObj(childLsid, txnNumber, startTransaction) { - const cmdObj = { - insert: kCollName, - documents: [{x: 0}], - lsid: childLsid, - txnNumber: txnNumber, - stmtId: NumberInt(stmtId++), - autocommit: false, - }; - if (startTransaction) { - cmdObj.startTransaction = true; - } - - return cmdObj; -} - -(() => { - jsTest.log( - "Verify internal transactions in an in-progress, unprepared state are aborted when FCV is downgraded."); - - const st = new ShardingTest({shards: {rs0: {nodes: 2}}}); - const shard0Rst = st.rs0; - const shard0Primary = shard0Rst.getPrimary(); - - const testDB = shard0Primary.getDB(kDbName); - - const sessionUUID = UUID(); - const childLsid0 = {id: sessionUUID, txnUUID: UUID()}; - const childLsid1 = {id: sessionUUID, txnNumber: NumberLong(5), txnUUID: UUID()}; - - // Start internal transactions inside sessions with retryableWrite: {false, true}. - assert.commandWorked(testDB.runCommand(makeInsertCmdObj(childLsid0, NumberLong(0), true))); - assert.commandWorked(testDB.runCommand(makeInsertCmdObj(childLsid1, NumberLong(0), true))); - - // By being unable to insert documents, verify that both transactions are aborted when FCV is - // downgraded. - assert.commandWorked( - shard0Primary.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true})); - - assert.commandFailedWithCode(testDB.runCommand(makeInsertCmdObj(childLsid0, NumberLong(0))), - ErrorCodes.NoSuchTransaction); - assert.commandFailedWithCode(testDB.runCommand(makeInsertCmdObj(childLsid1, NumberLong(0))), - ErrorCodes.NoSuchTransaction); - - st.stop(); -})(); - -(() => { - jsTest.log( - "Verify FCV cannot be downgraded when a session has a prepared internal transaction until the transaction is out of the prepared state (either aborted or committed)."); - - const st = new ShardingTest({shards: 1}); - const shard0Rst = st.rs0; - const shard0Primary = shard0Rst.getPrimary(); - - const testDB = shard0Primary.getDB(kDbName); - const adminDB = shard0Primary.getDB("admin"); - - const sessionUUID = UUID(); - const childLsid0 = {id: sessionUUID, txnUUID: UUID()}; - const childLsid1 = {id: sessionUUID, txnNumber: NumberLong(5), txnUUID: UUID()}; - - assert.commandWorked(testDB.createCollection(kCollName)); - - // Start internal transactions for writes executed in sessions with retryableWrite: {false, - // true} and bring to prepared state. - assert.commandWorked(testDB.runCommand(makeInsertCmdObj(childLsid0, NumberLong(0), true))); - assert.commandWorked(testDB.runCommand(makeInsertCmdObj(childLsid1, NumberLong(0), true))); - - assert.commandWorked( - shard0Primary.adminCommand(makePrepareTransactionCmdObj(childLsid0, NumberLong(0)))); - assert.commandWorked( - shard0Primary.adminCommand(makePrepareTransactionCmdObj(childLsid1, NumberLong(0)))); - - // The setFCV command will need to acquire a global S lock to complete. The global - // lock is currently held by prepare, so that will block. We use a failpoint to make that - // command fails when it tries to get the lock. - let fp = configureFailPoint(shard0Primary, "failNonIntentLocksIfWaitNeeded"); - assert.commandFailedWithCode( - testDB.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true}), - ErrorCodes.LockTimeout); - fp.wait(); - fp.off(); - - assert.commandWorked(adminDB.runCommand(makeAbortTransactionCmdObj(childLsid0, NumberLong(0)))); - fp = configureFailPoint(shard0Primary, "failNonIntentLocksIfWaitNeeded"); - assert.commandFailedWithCode( - testDB.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true}), - ErrorCodes.LockTimeout); - fp.wait(); - fp.off(); - assert.commandWorked(adminDB.runCommand(makeAbortTransactionCmdObj(childLsid1, NumberLong(0)))); - - // We are able to downgrade FCV only when both transactions are no longer in the prepared state. - assert.commandWorked( - shard0Primary.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true})); - - st.stop(); -})();
\ No newline at end of file diff --git a/jstests/multiVersion/genericBinVersion/timeseries_collection_mixed_type.js b/jstests/multiVersion/genericBinVersion/timeseries_collection_mixed_type.js index 2fff9a58098..1a1ab164cd6 100644 --- a/jstests/multiVersion/genericBinVersion/timeseries_collection_mixed_type.js +++ b/jstests/multiVersion/genericBinVersion/timeseries_collection_mixed_type.js @@ -13,6 +13,7 @@ const timeFieldName = "time"; // Note that this list will need to be kept up to date as versions are added/dropped. const upgradeVersions = [ {binVersion: "6.0", fcv: "6.0"}, + {binVersion: "7.0", fcv: "7.0"}, {binVersion: "last-lts", fcv: lastLTSFCV}, {binVersion: "latest"} ]; diff --git a/jstests/multiVersion/genericBinVersion/truncate_retryable_write_sessions_on_downgrade.js b/jstests/multiVersion/genericBinVersion/truncate_retryable_write_sessions_on_downgrade.js index 6710db83c4d..41eceadbeaa 100644 --- a/jstests/multiVersion/genericBinVersion/truncate_retryable_write_sessions_on_downgrade.js +++ b/jstests/multiVersion/genericBinVersion/truncate_retryable_write_sessions_on_downgrade.js @@ -5,6 +5,8 @@ * * TODO(SERVER-84271): Remove this test when featureFlagReplicateVectoredInsertsTransactionally is * removed. + * + * @tags: [DISABLED_TEMPORARILY_DUE_TO_FCV_UPGRADE] */ import "jstests/multiVersion/libs/multi_rs.js"; diff --git a/jstests/multiVersion/genericSetFCVUsage/major_version_upgrade.js b/jstests/multiVersion/genericSetFCVUsage/major_version_upgrade.js index e1fcbe18b4d..b81962b9311 100644 --- a/jstests/multiVersion/genericSetFCVUsage/major_version_upgrade.js +++ b/jstests/multiVersion/genericSetFCVUsage/major_version_upgrade.js @@ -33,6 +33,7 @@ const versions = [ {binVersion: '4.4', featureCompatibilityVersion: '4.4', testCollection: 'four_four'}, {binVersion: '5.0', featureCompatibilityVersion: '5.0', testCollection: 'five_zero'}, {binVersion: '6.0', featureCompatibilityVersion: '6.0', testCollection: 'six_zero'}, + {binVersion: '7.0', featureCompatibilityVersion: '7.0', testCollection: 'seven_zero'}, {binVersion: 'last-lts', featureCompatibilityVersion: lastLTSFCV, testCollection: 'last_lts'}, { binVersion: 'last-continuous', diff --git a/jstests/multiVersion/libs/dbcheck_old_format_keys_test.js b/jstests/multiVersion/libs/dbcheck_old_format_keys_test.js index b903299cf31..8879e7995f0 100644 --- a/jstests/multiVersion/libs/dbcheck_old_format_keys_test.js +++ b/jstests/multiVersion/libs/dbcheck_old_format_keys_test.js @@ -26,7 +26,8 @@ const upgradeVersions = { "4.4": {"fcv": "5.0", "nextVersion": "5.0"}, "5.0": {"fcv": "6.0", "nextVersion": "6.0"}, "6.0": {"fcv": "7.0", "nextVersion": "7.0"}, - "7.0": {"fcv": "8.0", "nextVersion": "latest"}, + "7.0": {"fcv": "8.0", "nextVersion": "8.0"}, + "8.0": {"fcv": "8.1", "nextVersion": "latest"}, // TODO (SERVER-66611): Automate modifying this list. "latest": {} } diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/bindata_convert_view_upgrade_downgrade.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/bindata_convert_view_upgrade_downgrade.js deleted file mode 100644 index 4de12016fa4..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/bindata_convert_view_upgrade_downgrade.js +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Verifies that BinData $convert behaves correctly in FCV upgrade/downgrade scenarios. - */ - -import "jstests/multiVersion/libs/multi_rs.js"; -import {assertDropAndRecreateCollection} from "jstests/libs/collection_drop_recreate.js"; - -const lastLTSVersion = { - binVersion: "last-lts" -}; -const latestVersion = { - binVersion: "latest" -}; - -const collectionName = "coll"; - -const rst = new ReplSetTest({ - name: jsTestName(), - nodes: [ - {...lastLTSVersion}, - {...lastLTSVersion}, - ], -}); -rst.startSet(); -rst.initiate(); - -const getAdminDB = () => rst.getPrimary().getDB("admin"); -const getDB = () => rst.getPrimary().getDB(jsTestName()); - -const coll = assertDropAndRecreateCollection(getDB(), collectionName); -assert.commandWorked(coll.insertMany([ - { - _id: 0, - asUuid: UUID("867dee52-c331-484e-92d1-c56479b8e67e"), - asString: "867dee52-c331-484e-92d1-c56479b8e67e", - }, - { - _id: 1, - asUuid: UUID("b6684187-f74d-4872-818f-7a6e97fd5c04"), - asString: "b6684187-f74d-4872-818f-7a6e97fd5c04", - }, -])); - -const toUUIDViewName = "toUUIDView"; -const toUUIDPipeline = [{$project: {uuidFromString: {$toUUID: "$asString"}}}]; - -const toStringViewName = "toStringView"; -const toStringPipeline = [{$project: {stringFromUuid: {$toString: "$asUuid"}}}]; - -{ - const db = getDB(); - - // View creation fails due to unknown $toUUID syntax. - db[toUUIDViewName].drop(); - assert.commandFailedWithCode(db.createView(toUUIDViewName, collectionName, toUUIDPipeline), - 31325); - - // View creation succeeds, but queries on the view fail due to unsupported bindata-to-string - // conversion. - db[toStringViewName].drop(); - assert.commandWorked(db.createView(toStringViewName, collectionName, toStringPipeline)); - assert.commandFailedWithCode(db.runCommand({find: toStringViewName, filter: {}}), - ErrorCodes.ConversionFailure); -} - -// Upgrade the binaries and the FCV. -rst.upgradeSet({...latestVersion}); -assert.commandWorked( - getAdminDB().runCommand({setFeatureCompatibilityVersion: latestFCV, confirm: true})); - -{ - // View creation and usage both succeed after upgrade. - const db = getDB(); - - db[toUUIDViewName].drop(); - assert.commandWorked(db.createView(toUUIDViewName, collectionName, toUUIDPipeline)); - assert.commandWorked(db.runCommand({find: toUUIDViewName, filter: {}})); - - db[toStringViewName].drop(); - assert.commandWorked(db.createView(toStringViewName, collectionName, toStringPipeline)); - assert.commandWorked(db.runCommand({find: toStringViewName, filter: {}})); -} - -// Downgrade FCV without restarting. -assert.commandWorked( - getAdminDB().runCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true})); - -{ - const db = getDB(); - - // Queries on views using BinData $convert should fail after downgrading the FCV. - assert.commandFailedWithCode(db.runCommand({find: toUUIDViewName, filter: {}}), - ErrorCodes.QueryFeatureNotAllowed); - assert.commandFailedWithCode(db.runCommand({find: toStringViewName, filter: {}}), - ErrorCodes.ConversionFailure); - - // BinData to string conversion still succeeds with onError value. - assert.commandWorked(db.runCommand({ - aggregate: collectionName, - cursor: {}, - pipeline: [{ - $project: { - stringFromUuid: { - $convert: { - input: "$asUuid", - to: "string", - onError: "NULL", - } - } - } - }] - })); - - // However, it should not succeed with a 'format' argument. - assert.commandFailedWithCode( - db.runCommand({ - aggregate: collectionName, - cursor: {}, - pipeline: [{ - $project: { - stringFromUuid: { - $convert: { - input: "$asUuid", - to: "string", - format: "uuid", - onError: "NULL", - } - } - } - }] - }), - ErrorCodes.FailedToParse, - ); -} - -rst.stopSet(); diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/change_stream_pre_image_truncate_with_mixed_version_replicaset.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/change_stream_pre_image_truncate_with_mixed_version_replicaset.js deleted file mode 100644 index 4da21202e9e..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/change_stream_pre_image_truncate_with_mixed_version_replicaset.js +++ /dev/null @@ -1,169 +0,0 @@ -// Tests behaviour of the preimage remover where initially the primary and secondary are on -// different binary versions, and the behaviour after upgrading to latest. -// -// @tags: [ -// requires_fcv_72, -// requires_replication, -// ] -import "jstests/multiVersion/libs/multi_rs.js"; -import {getPreImagesCollection} from "jstests/libs/change_stream_util.js"; -import {configureFailPoint} from "jstests/libs/fail_point_util.js"; -import { - setupTimeBasedPreImageRetentionPolicyTest, - verifyPreImages -} from "jstests/noPassthrough/libs/change_stream_pre_image_time_based_expiration_utils.js"; - -function serverParametersForVersionString(version) { - let options = { - binVersion: version, - }; - // Reduce period of removal job to speed up test. - let serverParams = {expiredChangeStreamPreImageRemovalJobSleepSecs: 1}; - if (version == "latest") { - serverParams["preImagesCollectionTruncateMarkersMinBytes"] = 1; - } - options["setParameter"] = serverParams; - return options; -} - -function setupMixedVersionReplicaSetTest(binVersionList) { - const nodeOptions = binVersionList.map(serverParametersForVersionString); - - const rst = new ReplSetTest({nodes: nodeOptions}); - rst.startSet(); - // Allow test cases to have complete control over which node is primary. - rst.initiateWithHighElectionTimeout(); - - return rst; -} - -function setChangeStreamPreImageRemoverCurrentTimeAndWaitForAllNodes( - rst, currentTimeForTimeBasedExpiration) { - rst.nodes.forEach(node => { - const currentTimeFailPoint = configureFailPoint( - node, - "changeStreamPreImageRemoverCurrentTime", - {currentTimeForTimeBasedExpiration: currentTimeForTimeBasedExpiration}); - - // Wait until at least 1 complete cycle of pre-image removal job is completed. - currentTimeFailPoint.wait({timesEntered: 2}); - }); -} - -function verifyPreImagesForAllNodes(rst, expectedPreImagesForNodes, collectionsInfo) { - // Verify that at some point in time, all expired pre-images will be deleted. - rst.nodes.forEach((node, idx) => { - const preImageColl = getPreImagesCollection(node); - assert.soon( - () => { - return preImageColl.find().toArray().length == - expectedPreImagesForNodes[idx].length; - }, - () => { - const preImages = preImageColl.find().toArray(); - return `Host (${node.host}): expected ${ - tojson(expectedPreImagesForNodes[idx])} for collectionsInfo ${ - tojson(collectionsInfo)} but found ${tojson(preImages)}`; - }); - verifyPreImages(preImageColl, expectedPreImagesForNodes[idx], collectionsInfo); - - if (node.host === rst.getPrimary().host) { - // Await for primary to replicate deletes, in case it does not use unreplicated - // truncates. - rst.awaitReplication(); - } - }); -} - -function setExpireAfterSeconds(rst, expireAfterSeconds) { - // Enable time-based pre-image expiration and configure the 'expireAfterSeconds'. - assert.commandWorked(rst.getPrimary().getDB("admin").runCommand({ - setClusterParameter: - {changeStreamOptions: {preAndPostImages: {expireAfterSeconds: expireAfterSeconds}}} - })); -} - -// Test case: primary using truncate deletes, secondary with replicated deletes. -// The secondary is expected to not delete anything because the primary is not replicating deletes. -// The situation should be resolved on upgrading the node. -function testPrimaryLatestSecondariesLastLts(shouldTruncateAllAfterUpgrade) { - jsTestLog("Running testPrimaryLatestSecondariesLastLts. shouldTruncateAllAfterUpgrade: " + - shouldTruncateAllAfterUpgrade); - - const rst = setupMixedVersionReplicaSetTest(["latest", "last-lts"]); - const primary = rst.getPrimary(); - const expireAfterSeconds = shouldTruncateAllAfterUpgrade ? 1 : 3600; - const {currentTimeForTimeBasedExpiration, _unused, shouldRetainDocs, allDocs, collectionsInfo} = - setupTimeBasedPreImageRetentionPolicyTest(primary, primary, expireAfterSeconds); - - // Fix wall time used by pre image remover. - setChangeStreamPreImageRemoverCurrentTimeAndWaitForAllNodes(rst, - currentTimeForTimeBasedExpiration); - - // Verify that when time-based pre-image expiration disabled, no pre-images are not deleted. - verifyPreImagesForAllNodes(rst, [allDocs, allDocs], collectionsInfo); - - // Enable time based expiration. - setExpireAfterSeconds(rst, expireAfterSeconds); - - // The secondary is expected to not have removed any documents. - verifyPreImagesForAllNodes(rst, [shouldRetainDocs, allDocs], collectionsInfo); - - // After upgrading the secondary to a version with truncate deletes, the preImages should be - // deleted. - rst.upgradeSecondaries(serverParametersForVersionString("latest")); - - // With shouldTruncateAllAfterUpgrade there's no need to simulate the current time given - // the low value for expireAfterSeconds (and that we want all documents to be truncated). - if (!shouldTruncateAllAfterUpgrade) { - // On the other hand, if we expect some documents to survive, we need to re-enable the - // failpoint to simulate the time to force expiration. - setChangeStreamPreImageRemoverCurrentTimeAndWaitForAllNodes( - rst, currentTimeForTimeBasedExpiration); - } - const upgradedNodeExpectedDocs = shouldTruncateAllAfterUpgrade ? [] : shouldRetainDocs; - verifyPreImagesForAllNodes(rst, [shouldRetainDocs, upgradedNodeExpectedDocs], collectionsInfo); - - rst.stopSet(); -} - -// Test case: primary using replicated deletes, secondary using truncate deletes. -// The secondary might try to delete the same document both with truncate and by applying the -// replicated delete. This should be fine. -function testPrimaryLastLtsSecondariesLatest(shouldTruncateAllAfterUpgrade) { - jsTestLog("Running testPrimaryLastLtsSecondariesLatest. shouldTruncateAllAfterUpgrade: " + - shouldTruncateAllAfterUpgrade); - const rst = setupMixedVersionReplicaSetTest(["last-lts", "latest"]); - const primary = rst.getPrimary(); - const expireAfterSeconds = shouldTruncateAllAfterUpgrade ? 1 : 3600; - const {currentTimeForTimeBasedExpiration, _unused, shouldRetainDocs, allDocs, collectionsInfo} = - setupTimeBasedPreImageRetentionPolicyTest(primary, primary, expireAfterSeconds); - - // Fix wall time used by pre image remover. - setChangeStreamPreImageRemoverCurrentTimeAndWaitForAllNodes(rst, - currentTimeForTimeBasedExpiration); - - // Verify that when time-based pre-image expiration disabled, no pre-images are not deleted. - verifyPreImagesForAllNodes(rst, [allDocs, allDocs], collectionsInfo); - - // Enable time based expiration. - setExpireAfterSeconds(rst, expireAfterSeconds); - - // Both primary and secondary should remove expired documents. - verifyPreImagesForAllNodes(rst, [shouldRetainDocs, shouldRetainDocs], collectionsInfo); - - // After upgrading the secondary to a version with truncate deletes, the preImages should be - // deleted. - rst.upgradePrimary(rst.getPrimary(), serverParametersForVersionString("latest")); - - const upgradedNodeExpectedDocs = shouldTruncateAllAfterUpgrade ? [] : shouldRetainDocs; - verifyPreImagesForAllNodes(rst, [upgradedNodeExpectedDocs, shouldRetainDocs], collectionsInfo); - - rst.stopSet(); -} - -testPrimaryLatestSecondariesLastLts(/*shouldTruncateAllAfterUpgrade=*/ true); -testPrimaryLatestSecondariesLastLts(/*shouldTruncateAllAfterUpgrade=*/ false); - -testPrimaryLastLtsSecondariesLatest(/*shouldTruncateAllAfterUpgrade=*/ true); -testPrimaryLastLtsSecondariesLatest(/*shouldTruncateAllAfterUpgrade=*/ false); diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/change_stream_v1_v2_within_txn.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/change_stream_v1_v2_within_txn.js deleted file mode 100644 index 4d35ae75da5..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/change_stream_v1_v2_within_txn.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Confirms that if a v1 token is used to resume a change stream from a point in the middle of a - * transaction, then a >16MB event later in that transaction will be successfully split if the - * '$changeStreamSplitLargeEvent' stage is present. - * @tags: [ - * uses_change_streams, - * uses_transactions, - * ] - */ -import "jstests/multiVersion/libs/multi_rs.js"; -import {assertDropAndRecreateCollection} from "jstests/libs/collection_drop_recreate.js"; - -// Create a new replica set with 2 nodes (otherwise 'rst.upgradeSet()' does not work). -const rst = new ReplSetTest({nodes: 2, nodeOptions: {binVersion: "last-lts"}}); -rst.startSet(); -rst.initiate(); - -// Set up DBs and collections used in this test. -let testDB = rst.getPrimary().getDB(jsTestName()); -let testColl = assertDropAndRecreateCollection( - testDB, "test_coll", {changeStreamPreAndPostImages: {enabled: true}}); - -// Open a change stream with batch size 1 and force it to create v1 tokens. -const csCursor = testColl.watch( - [{$changeStreamSplitLargeEvent: {}}], - {fullDocumentBeforeChange: "whenAvailable", batchSize: 1, $_generateV2ResumeTokens: false}); - -// Start a new transaction. -const session = testDB.getMongo().startSession(); -const sessionDB = session.getDatabase(testDB.getName()); -const sessionColl = sessionDB[testColl.getName()]; -session.startTransaction(); - -// Within the txn, insert a large document and then update it, then commit the transaction. -assert.commandWorked(sessionColl.insert({_id: 1, largeString: "x".repeat(15 * 1024 * 1024)})); -assert.commandWorked( - sessionColl.update({_id: 1}, {$set: {largeString: "y".repeat(15 * 1024 * 1024)}})); -session.commitTransaction(); - -// Assert that we see the first event (the insert) in the v1 stream. -assert.soon(() => csCursor.hasNext()); -const v1InsertEvent = csCursor.next(); -assert.eq(v1InsertEvent.operationType, "insert"); -// TODO SERVER-82330: Validate that the 'v1InsertEvent' has a v1 resume token. - -rst.upgradeSet({binVersion: "latest"}); - -testDB = rst.getPrimary().getDB(jsTestName()); -testColl = testDB[testColl.getName()]; - -// Now open a $changeStreamSplitLargeEvent pipeline and try to resume from the v1 token. -const csSplitCursor = testColl.watch( - [{$changeStreamSplitLargeEvent: {}}], - {resumeAfter: v1InsertEvent._id, fullDocumentBeforeChange: "whenAvailable", batchSize: 0}); - -// Confirm that the update within the same transaction is correctly split in the resumed stream. -assert.soon(() => csSplitCursor.hasNext()); -const postResumeEvent = csSplitCursor.next(); -assert.eq(postResumeEvent.operationType, "update"); -assert.eq(postResumeEvent.splitEvent.fragment, 1); - -rst.stopSet(); diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/change_streams_split_event_v1_v2_tokens.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/change_streams_split_event_v1_v2_tokens.js deleted file mode 100644 index 7dbf1d81cc5..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/change_streams_split_event_v1_v2_tokens.js +++ /dev/null @@ -1,222 +0,0 @@ -/** - * Tests the compatibility of v1 and v2 resume tokens across server version upgrade / downgrade. - * @tags: [uses_change_streams] - */ - -import "jstests/multiVersion/libs/multi_cluster.js"; -import { - assertCreateCollection, - assertDropCollection -} from "jstests/libs/collection_drop_recreate.js"; - -const kLargeStringSize = 15 * 1024 * 1024; - -const st = new ShardingTest({ - shards: 2, - config: 1, - other: { - mongosOptions: {binVersion: "last-lts"}, - configOptions: { - binVersion: "last-lts", - }, - rsOptions: { - binVersion: "last-lts", - }, - rs: {nodes: 2}, - } -}); - -let testDB = st.s.getDB(jsTestName()); -let testColl = testDB["test"]; - -// Helper function to retrieve high-watermark change stream tokens. -function getHighWaterMarkToken(collection, pipeline = [], options = {}) { - const csCursor = collection.watch(pipeline, {batchSize: 0, ...options}); - const result = csCursor.getResumeToken(); - csCursor.close(); - return result; -} - -// Record a high-watermark resume token marking the start point of the test. -const testStartV1HWMToken = getHighWaterMarkToken(testColl, [], {$_generateV2ResumeTokens: false}); - -// An array which will list the expected sequence of change events generated by the test. -const expectedEvents = []; - -// -// Below, we generate one of each type of change event so that we can later test resuming from a v1 -// token representing each such event. -// -testColl = assertCreateCollection(testDB, testColl.getName()); -expectedEvents.push({operationType: "create"}); - -assert.commandWorked(testColl.createIndexes([{shard: 1}, {shard: 1, _id: 1}, {largeField: 1}])); -expectedEvents.push({operationType: "createIndexes"}, - {operationType: "createIndexes"}, - {operationType: "createIndexes"}); - -// The 'modify' event has to come before sharding the collection, otherwise we get different number -// of events on 'last-lts' and on 'latest'. -assert.commandWorked(testDB.runCommand( - {collMod: testColl.getName(), changeStreamPreAndPostImages: {enabled: true}})); -expectedEvents.push({operationType: "modify"}); - -// Shard the test collection and split it into two chunks: one that contains all {shard: 1} -// documents and one that contains all {shard: 2} documents. -st.shardColl(testColl, {shard: 1} /* shard key */, {shard: 2} /* split at */); -expectedEvents.push({operationType: "shardCollection"}); - -assert.commandWorked(testColl.insertMany([ - {_id: "a", shard: 1, largeField: ""}, - {_id: "b", shard: 2, largeField: ""}, - {_id: "c", shard: 2, largeField: ""} -])); -expectedEvents.push({operationType: "insert", documentKey: {shard: 1, _id: "a"}}, - {operationType: "insert", documentKey: {shard: 2, _id: "b"}}, - {operationType: "insert", documentKey: {shard: 2, _id: "c"}}); - -// This high watermark token will be at the same clusterTime as the subsequent update event that -// needs to be split. -const v1HwmTokenBeforeUpdateWithSplit = getHighWaterMarkToken( - testColl, [{$changeStreamSplitLargeEvent: {}}], {$_generateV2ResumeTokens: false}); - -assert.commandWorked( - testColl.update({_id: "a", shard: 1}, {$set: {largeField: "x".repeat(kLargeStringSize)}})); -expectedEvents.push({operationType: "update", documentKey: {_id: "a", shard: 1}}); - -assert.commandWorked( - testColl.update({_id: "b", shard: 2}, {$set: {largeField: "x".repeat(kLargeStringSize)}})); -expectedEvents.push({operationType: "update", documentKey: {_id: "b", shard: 2}}); - -assert.commandWorked(testColl.replaceOne( - {_id: "a", shard: 1}, {_id: "a", shard: 1, largeField: "y".repeat(kLargeStringSize)})); -expectedEvents.push({operationType: "replace", documentKey: {_id: "a", shard: 1}}); - -assert.commandWorked(testColl.replaceOne( - {_id: "b", shard: 2}, {_id: "b", shard: 2, largeField: "y".repeat(kLargeStringSize)})); -expectedEvents.push({operationType: "replace", documentKey: {_id: "b", shard: 2}}); - -assert.commandWorked(testColl.remove({_id: "a"})); -expectedEvents.push({operationType: "delete", documentKey: {_id: "a", shard: 1}}); - -assert.commandWorked(testColl.remove({_id: "b"})); -expectedEvents.push({operationType: "delete", documentKey: {_id: "b", shard: 2}}); - -assert.commandWorked( - st.s.adminCommand({refineCollectionShardKey: testColl.getFullName(), key: {shard: 1, _id: 1}})); -expectedEvents.push({operationType: "refineCollectionShardKey"}); - -assert.commandWorked(st.s.adminCommand({reshardCollection: testColl.getFullName(), key: {_id: 1}})); -expectedEvents.push({operationType: "reshardCollection"}); - -assert.commandWorked(testColl.dropIndex({largeField: 1})); -expectedEvents.push({operationType: "dropIndexes"}); - -const newTestCollectionName = "test_"; -assert.commandWorked(testColl.renameCollection(newTestCollectionName)); -expectedEvents.push({operationType: "rename"}); - -assertDropCollection(testDB, newTestCollectionName); -expectedEvents.push({operationType: "drop"}); - -assert.commandWorked(testDB.dropDatabase()); -// A whole-DB stream will be invalidated by the dropDatabase event. We include a second dropDatabase -// event because one such event is generated on each shard, and will be reported if we resume after -// the invalidate. This second dropDatabase acts as a sentinel here, signifying that we have reached -// the end of the test stream. -expectedEvents.push({operationType: "dropDatabase"}, - {operationType: "invalidate"}, - {operationType: "dropDatabase"}); - -// Helper function to assert on the given event fields. -function assertEventMatches(event, expectedEvent, errorMsg) { - for (const k in expectedEvent) { - assert.docEq(expectedEvent[k], event[k], errorMsg + `: value mismatch for field '${k}'`) - } -} - -// Asserts the next change event with the given pipeline and options matches the expected event. -// Returns the resume token of the matched event on success. -function assertNextChangeEvent(expectedEvent, pipeline, options) { - const csCursor = testDB.watch([...pipeline], {showExpandedEvents: true, ...options}); - const errorMsg = "could not retrieve the expected event matching " + tojson(expectedEvent); - let event; - do { - assert.doesNotThrow(() => assert.soon(() => csCursor.hasNext()), [], errorMsg); - event = csCursor.next(); - // When using '$_generateV2ResumeTokens: false', the change stream will additionally - // emit non-public 'kNewShardDetected' event. Unfortunately, it cannot be filtered out - // by adding a '$match' stage, so we fast-forward all these events. - } while (event.operationType === "kNewShardDetected"); - assertEventMatches(event, expectedEvent, errorMsg); - csCursor.close(); - return event._id; -} - -// Helper function to retrieve change event tokens for all events referred by 'expectedEvents'. -function getTokensForExpectedEvents(expectedEvents, startToken, pipeline = [], options = {}) { - return expectedEvents - .reduce( - (result, expectedEvent) => { - const lastToken = result[result.length - 1]; - result.push(assertNextChangeEvent( - expectedEvent, pipeline, {startAfter: lastToken, ...options})); - return result; - }, - [startToken]) - .slice(1); -} - -// Generate v1 resume tokens for all expected events on 'last-lts'. -const resumeTokensLastLTS = getTokensForExpectedEvents( - expectedEvents, testStartV1HWMToken, [], {$_generateV2ResumeTokens: false}); -// TODO SERVER-82330: Validate that these tokens are indeed all v1 tokens. - -// Upgrade the cluster to 'latest' to allow testing v1 - v2 resume behaviour. -st.upgradeCluster("latest", true); -assert.commandWorked(st.s.adminCommand({setFeatureCompatibilityVersion: latestFCV, confirm: true})); - -testDB = st.s.getDB(jsTestName()); - -// Verify that we can resume from each of the v1 tokens on the new binary version and with the -// $changeStreamSplitLargeEvent stage in the pipeline. When resuming from (i-1)-th event's token we -// expect to get the i-th event. We do not need to test the last token, because it is simply a -// sentinel value that signifies the end of the test. -for (let i = 1; i < expectedEvents.length; ++i) { - assertNextChangeEvent(expectedEvents[i], - [{$changeStreamSplitLargeEvent: {}}], - {startAfter: resumeTokensLastLTS[i - 1]}); -} - -// Test that we can split the update events after 'v1HwmTokenBeforeUpdateWithSplit'. -const expectedSplitEvents = [ - {operationType: "update", splitEvent: {fragment: 1, of: 2}}, - {splitEvent: {fragment: 2, of: 2}}, - {operationType: "update", splitEvent: {fragment: 1, of: 2}}, - {splitEvent: {fragment: 2, of: 2}}, - {operationType: "replace"} -]; -// Generate a set of v2 resume tokens for each of the entries in 'expectedSplitEvents'. -const resumeTokensWithSplitLatest = getTokensForExpectedEvents(expectedSplitEvents, - v1HwmTokenBeforeUpdateWithSplit, - [{$changeStreamSplitLargeEvent: {}}], - {fullDocument: "required"}); - -// Downgrade back to the original version. -assert.commandWorked( - st.s.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true})); -st.downgradeCluster("latest", "last-lts", true); - -testDB = st.s.getDB(jsTestName()); - -// Test the v2 split 'update' event tokens on the downgraded binary version. When resuming from -// (i-1)-th event token we expect to get the i-th event. This means, after the last 'update' event -// we expect the first 'replace' event. -for (let i = 1; i < expectedSplitEvents.length; ++i) { - assertNextChangeEvent( - expectedSplitEvents[i], - [{$changeStreamSplitLargeEvent: {}}], - {resumeAfter: resumeTokensWithSplitLatest[i - 1], fullDocument: "required"}); -} - -st.stop(); diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/dbcheck_invocation_mixed_versions.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/dbcheck_invocation_mixed_versions.js index eee04b5c589..d13a44d25d1 100644 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/dbcheck_invocation_mixed_versions.js +++ b/jstests/multiVersion/targetedTestsLastLtsFeatures/dbcheck_invocation_mixed_versions.js @@ -29,31 +29,16 @@ function testDbCheckInvocationParameters(replSet) { function checkEntryBounds(start, end) { forEachNonArbiterNode(replSet, function(node) { const healthlog = node.getDB("local").system.healthlog; - let keyBoundsResult; - const nodeBinVersion = node.getDB("admin").serverStatus()["version"]; - if (nodeBinVersion == MongoRunner.getBinVersionFor("latest")) { - keyBoundsResult = healthlog.aggregate([ - {$match: {operation: "dbCheckBatch"}}, - { - $group: { - _id: null, - batchStart: {$min: "$data.batchStart._id"}, - batchEnd: {$max: "$data.batchEnd._id"} - } + const keyBoundsResult = healthlog.aggregate([ + {$match: {operation: "dbCheckBatch"}}, + { + $group: { + _id: null, + batchStart: {$min: "$data.batchStart._id"}, + batchEnd: {$max: "$data.batchEnd._id"} } - ]); - } else { - keyBoundsResult = healthlog.aggregate([ - {$match: {operation: "dbCheckBatch"}}, - { - $group: { - _id: null, - batchStart: {$min: "$data.minKey"}, - batchEnd: {$max: "$data.maxKey"} - } - } - ]); - } + } + ]); assert(keyBoundsResult.hasNext(), "dbCheck put no batches in health log"); diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/downgrade_from_autobootstrapped_cluster.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/downgrade_from_autobootstrapped_cluster.js deleted file mode 100644 index 59449ef92be..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/downgrade_from_autobootstrapped_cluster.js +++ /dev/null @@ -1,349 +0,0 @@ -// Must keep this test until v8.0 becomes last lts. - -import "jstests/multiVersion/libs/multi_rs.js"; - -const kDocId = 1; - -let makeNewCluster = function() { - let st = new ShardingTest({ - shards: {rs0: {nodes: 1, setParameter: {featureFlagAllMongodsAreSharded: true}}}, - other: {useAutoBootstrapProcedure: true} - }); - - assert.commandWorked(st.s.adminCommand({enableSharding: 'test'})); - assert.commandWorked(st.s.adminCommand({shardCollection: 'test.user', key: {_id: 1}})); - assert.commandWorked(st.s.getDB('test').user.insert({_id: kDocId, z: 1})); - - assert.commandWorked( - st.s.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true})); - - return st; -}; - -let makeUpgradedClusterFromOldReplSet = function() { - let nodeOption = {binVersion: 'last-lts'}; - // Need at least 2 nodes because upgradeSet method needs to be able call step down - // with another primariy eligible node available. - let replSet = new ReplSetTest({nodes: [nodeOption, nodeOption]}); - replSet.startSet(); - replSet.initiate(); - - replSet.upgradeSet({ - binVersion: 'latest', - setParameter: - {featureFlagAllMongodsAreSharded: true, featureFlagTransitionToCatalogShard: true} - }); - - let primary = replSet.getPrimary(); - assert.commandWorked( - primary.adminCommand({transitionToShardedCluster: 1, writeConcern: {w: 'majority'}})); - - return replSet; -}; - -let testCRUD = function(conn) { - let coll = conn.getDB('test').user; - - let doc = coll.findOne({_id: kDocId}); - assert.neq(null, doc); - - let res = coll.update({_id: kDocId}, {$inc: {x: 1}}); - assert.eq(1, res.nMatched, tojson(res)); -}; - -let removeShardingMetadata = function(conn) { - let config = conn.getDB('config'); - - config.actionlog.drop(); - config.databases.drop(); - config.cache.collections.drop(); - config.cache.databases.drop(); - config.migrationCoordinators.drop(); - config.migrationRecipients.drop(); - config.shardMergeRecipients.drop(); - config.shardSplitDonors.drop(); - config.rangeDeletions.drop(); - config.rangeDeletionsForRename.drop(); - config.reshardingOperations.drop(); - config.localReshardingOperations.donor.drop(); - config.localReshardingOperations.recipient.drop(); - config.localRenameParticipants.drop(); - config.settings.drop(); - config.localReshardingOperations.recipient.progress_applier.drop(); - config.localReshardingOperations.recipient.progress_txn_cloner.drop(); - config.collection_critical_sections.drop(); - config.sharding_configsvr_coordinators.drop(); - config.shards.drop(); - config.collections.drop(); - config.csrs.indexes.drop(); - config.shard.indexes.drop(); - config.shard.collections.drop(); - config.placementHistory.drop(); - config.lockpings.drop(); - config.locks.drop(); - config.analyzeShardKeySplitPoints.drop(); - config.changelog.drop(); - config.chunks.drop(); - config.tags.drop(); - config.getCollection('version').drop(); - config.mongos.drop(); - - let cachedChunkColls = conn.getDB('config').runCommand( - {listCollections: 1, filter: {name: /cache.chunks*/}, nameOnly: true}); - - assert.eq(0, cachedChunkColls.cursor.id); // Should fit on first response - cachedChunkColls.cursor.firstBatch.forEach((coll) => { - conn.getDB('config').getCollection(coll.name).drop(); - }); -}; - -let verifyConfigColl = function(conn) { - let expectedCollections = [ - 'system.sessions', - 'system.indexBuilds', - // system.* cannot be dropped - 'system.sharding_ddl_coordinators', - 'sampledQueries', - 'tenantMigrationDonors', - 'sampledQueriesDiff', - 'image_collection', - 'external_validation_keys', - 'tenantMigrationRecipients', - 'transactions', - 'system.preimages', - 'vectorClock', - ]; - - let configColls = conn.getDB('config').runCommand({listCollections: 1, nameOnly: true}); - - assert.eq(0, configColls.cursor.id); // Should fit on first response - - let unexpectedColls = []; - configColls.cursor.firstBatch.forEach((coll) => { - if (!expectedCollections.includes(coll.name)) { - unexpectedColls.push(coll.name); - } - }); - - assert.eq([], unexpectedColls); -}; - -(function() { -jsTest.log('Testing downgrade to sharded cluster from a fresh new cluster'); - -let st = makeNewCluster(); - -// Add a shard in order to be able to transition to dedicated config -const additionalShard = new ReplSetTest({name: "shard0", nodes: 1, nodeOptions: {shardsvr: ""}}); -additionalShard.startSet(); -additionalShard.initiate(); - -assert.commandWorked(st.s.adminCommand({addShard: additionalShard.getURL(), name: 'shard0'})); -assert.commandWorked(st.s.adminCommand( - {moveChunk: 'test.user', find: {_id: MinKey}, to: 'shard0', _waitForDelete: true})); -assert.commandWorked(st.s.adminCommand({movePrimary: 'test', to: 'shard0'})); -assert.commandWorked(st.s.adminCommand( - {moveChunk: "config.system.sessions", find: {_id: 0}, to: 'shard0', _waitForDelete: true})); - -let res = st.s.adminCommand({transitionToDedicatedConfigServer: 1}); -assert.eq("started", res.state); - -res = st.s.adminCommand({transitionToDedicatedConfigServer: 1}); -assert.eq("completed", res.state); - -st.stop({noCleanData: true}); // keep data files -additionalShard.stopSet(null /* signal */, true /* forRestart */, {noCleanData: true}); - -const oldConfig = st.rs0.nodes[0]; -let configConn = MongoRunner.runMongod({ - binVersion: 'last-lts', - noCleanData: true, - configsvr: '', - replSet: st.rs0.name, - dbpath: oldConfig.dbpath, - port: oldConfig.port -}); - -const oldShard = additionalShard.nodes[0]; -let shardConn = MongoRunner.runMongod({ - binVersion: 'last-lts', - noCleanData: true, - shardsvr: '', - replSet: additionalShard.name, - dbpath: oldShard.dbpath, - port: oldShard.port -}); - -const oldMongos = st.s; -const newOpt = Object.merge({binVersion: 'last-lts'}, oldMongos.fullOptions); -let mongosConn = MongoRunner.runMongos(newOpt); - -testCRUD(mongosConn); - -MongoRunner.stopMongos(mongosConn); -MongoRunner.stopMongod(shardConn); -MongoRunner.stopMongod(configConn); -})(); - -(function() { -jsTest.log('Testing downgrade to replica set from a fresh new cluster'); - -let st = makeNewCluster(); - -st.stop({noCleanData: true}); // keep data files - -const oldConfig = st.rs0.nodes[0]; -let configConn = MongoRunner.runMongod( - {binVersion: 'last-lts', noCleanData: true, dbpath: oldConfig.dbpath, port: oldConfig.port}); - -assert.commandWorked(configConn.getDB('local').system.replset.update({}, {$unset: {configsvr: 1}})); - -MongoRunner.stopMongod(configConn); - -configConn = MongoRunner.runMongod({ - binVersion: 'last-lts', - replSet: st.rs0.name, - noCleanData: true, - dbpath: oldConfig.dbpath, - port: oldConfig.port -}); - -assert.soon(() => { - let hello = configConn.getDB('admin')._helloOrLegacyHello(); - return hello.isWritablePrimary || hello.ismaster; -}); - -removeShardingMetadata(configConn); -verifyConfigColl(configConn); - -testCRUD(configConn); - -MongoRunner.stopMongod(configConn); -})(); - -(function() { -jsTest.log('Testing downgrade to standalone from a fresh new cluster'); - -let st = makeNewCluster(); - -st.stop({noCleanData: true}); // keep data files - -const oldConfig = st.rs0.nodes[0]; -let configConn = MongoRunner.runMongod( - {binVersion: 'last-lts', noCleanData: true, dbpath: oldConfig.dbpath, port: oldConfig.port}); - -assert.commandWorked(configConn.getDB('local').system.replset.update({}, {$unset: {configsvr: 1}})); - -MongoRunner.stopMongod(configConn); - -configConn = MongoRunner.runMongod( - {binVersion: 'last-lts', noCleanData: true, dbpath: oldConfig.dbpath, port: oldConfig.port}); - -let localDB = configConn.getDB("local"); -localDB.system.replset.remove({}, false /* justOne */); - -removeShardingMetadata(configConn); - -verifyConfigColl(configConn); -testCRUD(configConn); - -MongoRunner.stopMongod(configConn); - -// Can still convert to replSet after repl doc was deleted. - -configConn = MongoRunner.runMongod({ - binVersion: 'last-lts', - replSet: st.rs0.name, - noCleanData: true, - dbpath: oldConfig.dbpath, - port: oldConfig.port -}); - -assert.commandWorked(configConn.getDB('admin').runCommand({replSetInitiate: 1})); - -configConn.setSecondaryOk(); -assert.soon(() => { - let hello = configConn.getDB('admin')._helloOrLegacyHello(); - return hello.me && hello.me == hello.primary && (hello.isWritablePrimary || hello.ismaster); -}); - -testCRUD(configConn); -MongoRunner.stopMongod(configConn); -})(); - -(function() { -jsTest.log('Testing downgrade to sharded cluster from a cluster upgraded from replSet'); - -let replTest = makeUpgradedClusterFromOldReplSet(); - -const mongos = MongoRunner.runMongos( - {configdb: replTest.getURL(), setParameter: "featureFlagTransitionToCatalogShard=true"}); -assert(mongos); -assert.commandWorked(mongos.adminCommand({enableSharding: 'test'})); -assert.commandWorked(mongos.adminCommand({shardCollection: 'test.user', key: {_id: 1}})); -assert.commandWorked(mongos.getDB('test').user.insert({_id: kDocId, z: 1})); - -// Add a shard in order to be able to transition to dedicated config -const additionalShard = new ReplSetTest({name: "shard0", nodes: 2, nodeOptions: {shardsvr: ""}}); -additionalShard.startSet(); -additionalShard.initiate(); - -assert.commandWorked(mongos.adminCommand({addShard: additionalShard.getURL(), name: 'shard0'})); -assert.commandWorked(mongos.adminCommand( - {moveChunk: 'test.user', find: {_id: MinKey}, to: 'shard0', _waitForDelete: true})); -assert.commandWorked(mongos.adminCommand({movePrimary: 'test', to: 'shard0'})); - -let res = mongos.adminCommand({transitionToDedicatedConfigServer: 1}); -assert.eq("started", res.state); - -assert.soon(() => { - return mongos.adminCommand({transitionToDedicatedConfigServer: 1}).state == 'completed'; -}); - -let replConfig = replTest.getReplSetConfigFromNode(); -replConfig.version += 1; -replConfig.configsvr = true; - -assert.commandWorked(replTest.getPrimary().adminCommand({replSetReconfig: replConfig})); - -MongoRunner.stopMongos(mongos); - -delete replTest.nodeOptions['n0'].setParameter.featureFlagAllMongodsAreSharded; -delete replTest.nodeOptions['n1'].setParameter.featureFlagAllMongodsAreSharded; -replTest.upgradeSet({binVersion: 'last-lts', configsvr: ''}); -additionalShard.upgradeSet({binVersion: 'last-lts'}); - -const newOpt = Object.merge({binVersion: 'last-lts'}, mongos.fullOptions); -let mongosConn = MongoRunner.runMongos(newOpt); - -testCRUD(mongosConn); - -MongoRunner.stopMongos(mongosConn); -replTest.stopSet(); -additionalShard.stopSet(); -})(); - -(function() { -jsTest.log('Testing downgrade to replica set from a cluster upgraded from replSet'); - -let replTest = makeUpgradedClusterFromOldReplSet(); - -var mongos = MongoRunner.runMongos({configdb: replTest.getURL()}); -assert(mongos); -assert.commandWorked(mongos.adminCommand({enableSharding: 'test'})); -assert.commandWorked(mongos.adminCommand({shardCollection: 'test.user', key: {_id: 1}})); -assert.commandWorked(mongos.getDB('test').user.insert({_id: kDocId, z: 1})); -MongoRunner.stopMongos(mongos); - -delete replTest.nodeOptions['n0'].setParameter.featureFlagAllMongodsAreSharded; -delete replTest.nodeOptions['n1'].setParameter.featureFlagAllMongodsAreSharded; -replTest.upgradeSet({binVersion: 'last-lts'}); - -let configConn = replTest.getPrimary(); -removeShardingMetadata(configConn); -verifyConfigColl(configConn); - -testCRUD(configConn); - -replTest.stopSet(); -})(); diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/fle2_range_preview_rename.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/fle2_range_preview_rename.js deleted file mode 100644 index da8a700b448..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/fle2_range_preview_rename.js +++ /dev/null @@ -1,183 +0,0 @@ -/** - * Test edge cases for the rangePreview -> range rename. - */ -import "jstests/multiVersion/libs/multi_rs.js"; - -import {EncryptedClient} from "jstests/fle2/libs/encrypted_client_util.js"; - -const CRUDOnDeprecatedCollectionCode = 8575606; -const CreateDeprecatedCollectionCode = 8575605; -function testBinaryUpgradeWithRangePreviewCollection(upgradeConfig, fcvUpgradeShouldSucceed) { - const rst = new ReplSetTest({nodes: 2, nodeOptions: {binVersion: 'last-lts'}}); - rst.startSet(); - rst.initiate(); - let client = new EncryptedClient(rst.getPrimary(), "dbTest"); - // Old version; creating a new "rangePreview" collection succeeds. - assert.commandWorked(client.createEncryptionCollection("coll1", { - encryptedFields: { - "fields": [{ - path: "field1", - bsonType: "int", - queries: [{ - queryType: "rangePreview", - min: NumberInt(0), - max: NumberInt(8), - contention: NumberInt(0), - sparsity: 1 - }] - }] - } - })); - assert.commandWorked(client.createEncryptionCollection("coll2", { - encryptedFields: { - "fields": [{ - path: "field1", - bsonType: "int", - queries: [{ - queryType: "rangePreview", - min: NumberInt(0), - max: NumberInt(8), - contention: NumberInt(0), - sparsity: 1 - }] - }] - } - })); - - assert.commandWorked( - client.getDB().runCommand({insert: "coll1", documents: [{_id: 0, field1: NumberInt(1)}]})); - // The upgradeSet should always succeed and we should be able to start up with the rangePreview - // collection. - rst.upgradeSet(upgradeConfig); - client = new EncryptedClient(rst.getPrimary(), "dbTest"); - - // After upgrading, we can't do any CRUD ops on the collection - assert.commandFailedWithCode( - client.getDB().runCommand({insert: "coll1", documents: [{_id: 1, field1: NumberInt(2)}]}), - CRUDOnDeprecatedCollectionCode); - assert.commandFailedWithCode(client.getDB().runCommand({find: "coll1", filter: {}}), - CRUDOnDeprecatedCollectionCode); - - // We should be able to drop the collection - client.getDB().coll1.drop(); - - const res = - rst.getPrimary().adminCommand({setFeatureCompatibilityVersion: latestFCV, confirm: true}); - if (fcvUpgradeShouldSucceed) { - assert.commandWorked(res); - } else { - assert.commandFailedWithCode(res, ErrorCodes.CannotUpgrade); - client.getDB().coll2.drop(); - // After dropping both rangePreview collections, we should be able to upgrade (once drops - // clear). - assert.soon(() => { - assert.commandWorked(rst.getPrimary().adminCommand( - {setFeatureCompatibilityVersion: latestFCV, confirm: true})); - return true; - }); - } - rst.stopSet(); -} - -// When we set feature flag off, upgrading FCV will succeed because rangePreview is allowed when -// Range V2 is disabled -testBinaryUpgradeWithRangePreviewCollection( - {binVersion: 'latest', setParameter: {featureFlagQERangeV2: false}}, true); -// When we set it on, upgrading will fail -testBinaryUpgradeWithRangePreviewCollection( - {binVersion: 'latest', setParameter: {featureFlagQERangeV2: true}}, false); - -function testDowngradeWithRangeCollection(config) { - const rst = new ReplSetTest({nodes: 2, nodeOptions: config}); - rst.startSet(); - rst.initiate(); - let client = new EncryptedClient(rst.getPrimary(), "dbTest"); - // Old version; creating a new "rangePreview" collection succeeds. - assert.commandWorked(client.createEncryptionCollection("coll", { - encryptedFields: { - "fields": [{ - path: "field1", - bsonType: "int", - queries: [{ - queryType: "range", - min: NumberInt(0), - max: NumberInt(8), - contention: NumberInt(0), - sparsity: 1 - }] - }] - } - })); - - // Can't downgrade FCV to lastLTS with range collection, no matter if the feature flag is - // enabled. - assert.commandFailedWithCode( - rst.getPrimary().adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true}), - ErrorCodes.CannotDowngrade); - - client.getDB().coll.drop(); - // After dropping the collection, we should eventually be able to downgrade - assert.soon(() => { - assert.commandWorked(rst.getPrimary().adminCommand( - {setFeatureCompatibilityVersion: lastLTSFCV, confirm: true})); - return true; - }); - - rst.stopSet(); -} - -testDowngradeWithRangeCollection( - {binVersion: 'latest', setParameter: {featureFlagQERangeV2: false}}); -testDowngradeWithRangeCollection( - {binVersion: 'latest', setParameter: {featureFlagQERangeV2: true}}); - -function testCreateCollection(config) { - const rst = new ReplSetTest({nodes: 2, nodeConfig: config}); - rst.startSet(); - rst.initiate(); - const client = new EncryptedClient(rst.getPrimary(), "dbTest"); - // Creating a new rangePreview collection should fail. - assert.throwsWithCode(() => client.createEncryptionCollection("coll", { - encryptedFields: { - "fields": [{ - path: "field1", - bsonType: "int", - queries: [{ - queryType: "rangePreview", - min: NumberInt(0), - max: NumberInt(8), - contention: NumberInt(0), - sparsity: 1 - }] - }] - } - }), - CreateDeprecatedCollectionCode); - // Creating a new range collection should succeed. - assert.commandWorked(client.createEncryptionCollection("coll", { - encryptedFields: { - "fields": [{ - path: "field1", - bsonType: "int", - queries: [{ - queryType: "range", - min: NumberInt(0), - max: NumberInt(8), - contention: NumberInt(0), - sparsity: 1 - }] - }] - } - })); - - // CRUD operations should work fine on the range collection. - assert.commandWorked(client.getDB().runCommand( - {insert: "coll", documents: [{_id: 0, field1: NumberInt(1), field2: NumberInt(2)}]})); - assert.eq(client.getDB().coll.find({}, {__safeContent__: 0}).toArray(), - [{_id: 0, field1: NumberInt(1), field2: NumberInt(2)}]); - - rst.stopSet(); -} - -testCreateCollection({setParameter: {featureFlagQERangeV2: false}}); -testCreateCollection({setParameter: {featureFlagQERangeV2: true}}) diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/multi_update_coordinator_downgrade.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/multi_update_coordinator_downgrade.js deleted file mode 100644 index 8f5f5a6bd89..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/multi_update_coordinator_downgrade.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Tests that any running MultiUpdateCoordinators are aborted and properly - * cleaned up before downgrading to 7.0. - * - * @tags: [ - * requires_fcv_80 - * ] - */ - -import {migrationsAreAllowed} from "jstests/libs/chunk_manipulation_util.js"; -import {configureFailPoint} from "jstests/libs/fail_point_util.js"; -import {funWithArgs} from "jstests/libs/parallel_shell_helpers.js"; -import {CreateShardedCollectionUtil} from "jstests/sharding/libs/create_sharded_collection_util.js"; - -const dbName = "test"; -const collName = "coll"; -const namespace = `${dbName}.${collName}`; - -function runDowngradeTest(phase) { - jsTestLog(`Running MultiUpdateCoordinator downgrade test from phase ${phase}`); - const st = new ShardingTest(); - const mongos = st.s0; - - const sourceCollection = mongos.getCollection(namespace); - CreateShardedCollectionUtil.shardCollectionWithChunks(sourceCollection, {key: 1}, [ - {min: {key: MinKey}, max: {key: MaxKey}, shard: st.shard0.shardName}, - ]); - sourceCollection.insertMany([{key: 1, counter: 0}, {key: 2, counter: 0}]); - const dbPrimaryRsPrimary = st.getPrimaryShard(dbName).rs.getPrimary(); - - function downgradeFcvFromParallelShell() { - return startParallelShell( - () => {assert.commandWorked( - db.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true}))}, - st.s.port); - } - - function coordinateMultiUpdateFromParallelShell() { - return startParallelShell( - funWithArgs((nss, collName) => { - db.adminCommand({ - _shardsvrCoordinateMultiUpdate: nss, - uuid: UUID(), - command: { - update: collName, - updates: [{q: {counter: 0}, u: {$set: {counter: 1}}, multi: true}] - } - }); - }, namespace, collName), dbPrimaryRsPrimary.port); - } - - function assertNoDocumentsIn(dbName, collName) { - const docs = dbPrimaryRsPrimary.getDB(dbName).getCollection(collName).find({}).toArray(); - assert.eq(docs, []); - } - - const phaseFp = configureFailPoint(dbPrimaryRsPrimary, - "pauseDuringMultiUpdateCoordinatorPhaseTransition", - {progress: "after", phase}); - const abortFp = - configureFailPoint(dbPrimaryRsPrimary, "hangAfterAbortingMultiUpdateCoordinators"); - - const joinUpdate = coordinateMultiUpdateFromParallelShell(); - phaseFp.wait(); - const joinDowngrade = downgradeFcvFromParallelShell(); - abortFp.wait(); - abortFp.off(); - phaseFp.off(); - joinDowngrade(); - - assertNoDocumentsIn("config", "system.sharding_ddl_coordinators"); - assertNoDocumentsIn("config", "localMigrationBlockingOperations.multiUpdateCoordinators"); - assert(migrationsAreAllowed(st.s.getDB(dbName), collName)); - - joinUpdate(); - st.stop(); -} - -const phases = ["acquireSession", "blockMigrations", "performUpdate", "success", "done"]; -for (const phase of phases) { - runDowngradeTest(phase); -} diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/oidc_multipurpose_idp.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/oidc_multipurpose_idp.js deleted file mode 100644 index 1268857e56d..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/oidc_multipurpose_idp.js +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Test downgrade/upgrade of server with respect to OIDC multipurpose IDP support - */ -import "jstests/multiVersion/libs/multi_rs.js"; - -import {determineSSLProvider} from "jstests/ssl/libs/ssl_helpers.js"; -import { - OIDCKeyServer, - tryTokenAuth -} from "src/mongo/db/modules/enterprise/jstests/external_auth/lib/oidc_utils.js"; -import {OIDCVars} from "src/mongo/db/modules/enterprise/jstests/external_auth/lib/oidc_vars.js"; - -if (determineSSLProvider() !== 'openssl') { - print('Skipping test, OIDC is only available with OpenSSL'); - quit(); -} - -const keyMap = { - issuer1: 'src/mongo/db/modules/enterprise/jstests/external_auth/lib/custom-key-1.json', - issuer2: 'src/mongo/db/modules/enterprise/jstests/external_auth/lib/custom-key-1.json' -}; -const KeyServer = new OIDCKeyServer(JSON.stringify(keyMap)); -const issuer1 = KeyServer.getURL() + '/issuer1'; -const issuer2 = KeyServer.getURL() + '/issuer2'; -const kOIDCConfig = [ - { - issuer: issuer1, - audience: 'jwt@kernel.mongodb.com', - authNamePrefix: 'issuer1', - matchPattern: '@mongodb.com$', - clientId: 'deadbeefcafe', - requestScopes: ['email'], - principalName: 'sub', - authorizationClaim: 'mongodb-roles', - logClaims: ['sub', 'aud', 'mongodb-roles', 'does-not-exist'], - JWKSPollSecs: 15, - }, - { - issuer: issuer2, - audience: 'jwt@kernel.mongodb.com', - authNamePrefix: 'issuer2', - matchPattern: '@10gen.com$', - clientId: 'deadbeefcafe', - authorizationClaim: 'mongodb-roles', - JWKSPollSecs: 15, - } -]; - -const startupOptions = { - authenticationMechanisms: 'SCRAM-SHA-256,MONGODB-OIDC', - oidcIdentityProviders: tojson(kOIDCConfig), -}; - -const startupOptionsNotDowngradable = { - authenticationMechanisms: 'SCRAM-SHA-256,MONGODB-OIDC', - oidcIdentityProviders: tojson(kOIDCConfig.concat({ - issuer: issuer1, - audience: 'jwt@kernel.10gen.com', - authNamePrefix: 'issuer1-alt', - authorizationClaim: 'mongodb-roles', - supportsHumanFlows: false, - JWKSPollSecs: 15, - })), -}; - -const { - 'Token_OIDCAuth_user1': issuerOneToken, - 'Token_OIDCAuth_user1@10gen': issuerTwoToken, - 'Token_OIDCAuth_user1_alt_audience': issuerOneAltAudienceToken, -} = OIDCVars(KeyServer.getURL()).kOIDCTokens; - -function setup(conn) { - const adminDB = conn.getDB('admin'); - assert.commandWorked(conn.adminCommand({createUser: 'admin', 'pwd': 'foo', roles: ['root']})); - - // Create the roles corresponding to user1@mongodb.com and user1@10gen.com's groups. - assert.commandWorked(conn.adminCommand( - {createRole: 'issuer1/myReadRole', roles: ['readAnyDatabase'], privileges: []})); - assert.commandWorked( - conn.adminCommand({createRole: 'issuer2/myReadRole', roles: ['read'], privileges: []})); - assert.commandWorked( - conn.adminCommand({createRole: 'issuer1-alt/myreadRole', roles: ['read'], privileges: []})); - // Increase logging verbosity. - assert.commandWorked(adminDB.setLogLevel(3)); -} - -function runAuthTest(hostname, altCanAuth) { - let conn = new Mongo(hostname); - assert(tryTokenAuth(conn, issuerOneToken)); - assert.commandWorked(conn.adminCommand({listDatabases: 1})); - conn.close(); - - conn = new Mongo(hostname); - assert(tryTokenAuth(conn, issuerTwoToken)); - assert.commandWorked(conn.adminCommand({listDatabases: 1})); - conn.close(); - - conn = new Mongo(hostname); - assert(tryTokenAuth(conn, issuerOneAltAudienceToken) == altCanAuth); - if (altCanAuth) { - assert.commandWorked(conn.adminCommand({listDatabases: 1})); - } - conn.close(); -} - -function testBinaryUpgrade(initConfig, altCanAuthBefore, newConfig, altCanAuthAfter) { - jsTestLog("Testing upgrade from last-lts to latest"); - const rst = new ReplSetTest( - {nodes: 2, nodeOptions: {binVersion: 'last-lts', setParameter: initConfig}}); - rst.startSet(); - rst.initiate(); - - let conn = rst.getPrimary(); - setup(conn); - runAuthTest(conn.host, altCanAuthBefore); - - jsTestLog("Starting binary upgrade to latest"); - rst.upgradeSet({binVersion: 'latest', setParameter: newConfig}); - jsTestLog("Finished binary upgrade to latest"); - - conn = rst.getPrimary(); - runAuthTest(conn.host, altCanAuthAfter); - - rst.stopSet(); -} - -function testBinaryDowngrade(initConfig, altCanAuthBefore, newConfig, altCanAuthAfter) { - jsTestLog("Testing downgrade from latest to last-lts"); - const rst = new ReplSetTest({nodes: 2, nodeOptions: {setParameter: initConfig}}); - rst.startSet(); - rst.initiate(); - - let conn = rst.getPrimary(); - setup(conn); - runAuthTest(conn.host, altCanAuthBefore); - - { - const adminDB = conn.getDB('admin'); - assert.commandWorked(adminDB.runCommand( - {setFeatureCompatibilityVersion: lastLTSFCV, confirm: true, writeConcern: {w: 1}})); - checkFCV(adminDB, lastLTSFCV); - adminDB.logout(); - } - - jsTestLog("Starting binary downgrade to last LTS"); - rst.upgradeSet({binVersion: 'last-lts', setParameter: newConfig}); - jsTestLog("Finished binary downgrade to last LTS"); - - conn = rst.getPrimary(); - runAuthTest(conn.host, altCanAuthAfter); - - rst.stopSet(); -} - -KeyServer.start(); - -testBinaryUpgrade(startupOptions, false, startupOptions, false); -testBinaryUpgrade(startupOptions, false, startupOptionsNotDowngradable, true); - -testBinaryDowngrade(startupOptionsNotDowngradable, true, startupOptions, false); -testBinaryDowngrade(startupOptions, false, startupOptions, false); - -KeyServer.stop(); diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/query_stats_upgrade_downgrade.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/query_stats_upgrade_downgrade.js deleted file mode 100644 index fe8a90aed8f..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/query_stats_upgrade_downgrade.js +++ /dev/null @@ -1,268 +0,0 @@ -/** - * Verifies that $queryStats operates correctly when upgrading and downgrading. - */ - -import "jstests/multiVersion/libs/multi_rs.js"; -import "jstests/multiVersion/libs/multi_cluster.js"; -import {assertDropAndRecreateCollection} from "jstests/libs/collection_drop_recreate.js"; -import {getQueryStats, verifyMetrics} from "jstests/libs/query_stats_utils.js"; -(function() { -"use strict"; - -const lastLTSVersion = "last-lts"; - -class UpgradeDowngradeTestFixture { - constructor() { - this.collectionName = "coll"; - } - - getTestDB() { - return this.rst.getPrimary().getDB(jsTestName()); - } - - createAndPopulateTestCollection() { - let testDB = this.getTestDB(); - let coll = assertDropAndRecreateCollection(testDB, "coll"); - assert.commandWorked(coll.insertMany([{x: 0}, {x: 1}, {x: 2}])); - } - - setup() { - jsTestLog("Starting ReplicaSet Upgrade/Downgrade Test!"); - - this.rst = new ReplSetTest({ - name: jsTestName(), - nodes: [{binVersion: lastLTSVersion}, {binVersion: lastLTSVersion}] - }); - this.rst.startSet(); - this.rst.initiate(); - this.createAndPopulateTestCollection(); - } - - teardown() { - jsTestLog("Teardown ReplicaSet Upgrade/Downgrade Test!"); - - this.rst.stopSet(); - } - - getTestCollection() { - return this.getTestDB().getCollection(this.collectionName); - } - - adminCommand(command) { - return this.rst.getPrimary().getDB("admin").runCommand(command); - } - - upgradeBinaries() { - this.rst.upgradeSet({binVersion: "latest"}); - } - - upgradeFCV() { - assert.commandWorked( - this.adminCommand({setFeatureCompatibilityVersion: latestFCV, confirm: true})); - } - - downgradeFCV() { - // Downgrade FCV (without restarting) and check that $queryStats returns an error. - assert.commandWorked( - this.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true})); - } - - testQueryStatsParam(expectedResult) { - if (expectedResult === true) { - assert.commandWorked( - this.adminCommand({setParameter: 1, internalQueryStatsRateLimit: -1})); - } else { - // Check that $queryStats related parameter does not work. - assert.commandFailedWithCode( - this.adminCommand({setParameter: 1, internalQueryStatsRateLimit: -1}), 7373500); - } - } - - testQueryStatsCommandFailure(expectedErrorCode) { - assert.commandFailedWithCode( - this.adminCommand({aggregate: 1, pipeline: [{$queryStats: {}}], cursor: {}}), - expectedErrorCode); - } - - isShardedCluster() { - return false; - } - - verifyQueryStatsOutput({expectedNShapes}) { - const queryStats = getQueryStats(this); - assert.eq(expectedNShapes, queryStats.length, queryStats); - verifyMetrics(queryStats); - } -} - -class ShardedClusterUpgradeDowngradeTestFixture extends UpgradeDowngradeTestFixture { - setup() { - jsTestLog("Starting Sharded Upgrade/Downgrade Test!"); - this.shardedTest = new ShardingTest({ - name: jsTestName(), - shards: 1, - mongos: 1, - config: 1, - rs: {nodes: [{binVersion: lastLTSVersion}, {binVersion: lastLTSVersion}]}, - mongosOptions: {binVersion: lastLTSVersion}, - }); - this.createAndPopulateTestCollection(); - } - - isShardedCluster() { - return true; - } - - adminCommand(command) { - return this.shardedTest.s.adminCommand(command); - } - - getTestDB() { - return this.shardedTest.s.getDB(jsTestName()); - } - - upgradeBinaries() { - this.shardedTest.upgradeCluster('latest'); - } - - teardown() { - jsTestLog("Teardown ReplicaSet Upgrade/Downgrade Test!"); - this.shardedTest.stop(); - } -} - -function runTest(fixture) { - // 0. Initialize the fixture, we begin with a binary version that doesn't support queryStats. - fixture.setup(); - - // 1. Test that queryStats related features don't work in the base binary. - // 1.a. Verify queryStats is disabled by checking that setting queryStats related parameters and - // running the $queryStats stage both fail. - fixture.testQueryStatsParam(false); - fixture.testQueryStatsCommandFailure(ErrorCodes.QueryFeatureNotAllowed); - - // 1.b. Run some queries while running base binary. We don't expect these queries to be - // collected by queryStats. - { - let coll = fixture.getTestCollection(); - let res = coll.aggregate([{$match: {x: 2}}]).toArray(); - assert.eq(1, res.length, res); - - res = coll.find({x: 2}).toArray(); - assert.eq(1, res.length, res); - } - - // 2. Upgrade both the binaries and FCV. After the upgrade we expect query stats features - // to work. Further, we verify that the previously executed queries were not collected by - // checking the results from the $queryStats stage. - fixture.upgradeBinaries(); - fixture.upgradeFCV(); - - // 2.a. Verify that queryStats parameters can be set after the upgrade, and that previously - // executed queries were not collected. - fixture.testQueryStatsParam(true); - fixture.verifyQueryStatsOutput({expectedNShapes: 0}); - - // 2.b. Execute two new queries (i.e new query shapes) and check that they are collected. - { - let coll = fixture.getTestCollection(); - let res = coll.aggregate([{$match: {x: 2}}, {$sort: {x: -1}}]).toArray(); - assert.eq(1, res.length, res); - - res = coll.find({x: 2}, {noCursorTimeout: true}).toArray(); - assert.eq(1, res.length, res); - - fixture.verifyQueryStatsOutput({ - expectedNShapes: 3 /* 1 each for the above, plus $queryStats itself */ - }); - } - - // 3. Downgrade FCV (without restarting). Without restarting the server, we expect the - // queryStatsStore to keep existing entries, but to not collect any more statistics while an FCV - // that doesn't support queryStats is in place. - fixture.downgradeFCV(); - - // 3.a. Run additional queries (new query shapes) after the downgrade. - { - let coll = fixture.getTestCollection(); - let res = coll.aggregate([{$match: {x: 2}}]).toArray(); - assert.eq(1, res.length, res); - - res = coll.find({x: 2}).toArray(); - assert.eq(1, res.length, res); - } - - // 3.b. If we are testing a sharded cluster, we don't expect queryStats to be disabled after the - // FCV downgrade. This is because in a sharded cluster, query stats resides on mongos, and - // mongos doesn't have a concept of its own in memory FCV settings. When a sharded cluster has - // its FCV downgraded, it forwards the downgrade request to the shards and the config - // servers. However, the router itself bases its FCV on its binaries. In our case, once we - // upgrade the binary on the mongos, we can no longer downgrade the FCV to "disable" queryStats. - // As a result, in the sharded scenario we expect the two queries run after the downgrade to - // have been collected by query stats. - if (fixture.isShardedCluster()) { - fixture.verifyQueryStatsOutput({ - expectedNShapes: 5 /* 3 from the previous queries + the two additional ones captured - after the downgrade. */ - }); - fixture.teardown(); - return; - } - - // 3.c. After the FCV downgrade (i.e FCV v7.2), running $queryStats should return an error. - fixture.testQueryStatsCommandFailure(ErrorCodes.QueryFeatureNotAllowed); - - // 3.d. Upgrade the FCV without restart. QueryStatsStore should not have been cleared. Previous - // stats collected should be returned. The queries made during the downgrade should not - // have been collected. Note that getQueryStats() uses the same query to collect the statistics, - // so running $queryStats doesn't result in additional entries. - fixture.upgradeFCV(); - fixture.verifyQueryStatsOutput({expectedNShapes: 3}); - - // 4. Test query stats during a failed FCV downgrade. During the failed FCV downgrade, the FCV - // reverts back to the lastLTSFCV which doesn't support queryStats. - jsTestLog("Turning the failpoint on."); - assert.commandWorked( - fixture.adminCommand({configureFailPoint: 'failDowngrading', mode: "alwaysOn"})); - - assert.commandFailedWithCode( - fixture.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true}), 549181); - - // 4.a. Current FCV is lower than the FCV necessary (7.2) for queryStats to run. These queries - // should not be collected. - { - let coll = fixture.getTestCollection(); - let res = coll.aggregate([{$match: {x: 2}}]).toArray(); - assert.eq(1, res.length, res); - - res = coll.find({x: 2}).toArray(); - assert.eq(1, res.length, res); - } - // 4.b. Running $queryStats should return an error. - fixture.testQueryStatsCommandFailure(ErrorCodes.QueryFeatureNotAllowed); - - // 4.c. Successfully upgrade FCV. Check that the queries run during the failed downgrade were - // not collected. - fixture.upgradeFCV(); - fixture.verifyQueryStatsOutput({expectedNShapes: 3}); - - // 4.d. Execute two new queries (new query shapes), these should result in new entries. - { - let coll = fixture.getTestCollection(); - let res = coll.aggregate([{$match: {x: 2}}], {allowDiskUse: false}).toArray(); - assert.eq(1, res.length, res); - - res = coll.find({x: 2}, {allowPartialResults: true}).toArray(); - assert.eq(1, res.length, res); - - fixture.verifyQueryStatsOutput({expectedNShapes: 5}); - } - - fixture.teardown(); -} - -// Perform Upgrade/Downgrade test on replica set. -runTest(new UpgradeDowngradeTestFixture()); -// Perform Upgrade/Downgrade test on sharded cluster. -runTest(new ShardedClusterUpgradeDowngradeTestFixture()); -})(); diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/timeseries_fixed_bucket_match_rewrite.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/timeseries_fixed_bucket_match_rewrite.js deleted file mode 100644 index 360e42d70c6..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/timeseries_fixed_bucket_match_rewrite.js +++ /dev/null @@ -1,153 +0,0 @@ -/** - * Tests that the query rewrites for fixed bucketing can successfully be handled by a mixed cluster. - * The primary shard rewrites the query and sends it to the secondary shard that can handle running - * the rewritten query, even though the secondary shard's FCV is downgraded to 7.0. - */ -import "jstests/multiVersion/libs/multi_cluster.js"; - -import {getAggPlanStages} from "jstests/libs/analyze_plan.js"; -import {awaitRSClientHosts} from "jstests/replsets/rslib.js"; - -(function() { -"use strict"; - -const st = new ShardingTest({ - shards: 2, - rs: {nodes: 2}, - mongos: 1, - other: { - mongosOptions: {binVersion: "latest"}, - configOptions: {binVersion: "latest"}, - shardOptions: {binVersion: "latest"}, - rsOptions: {binVersion: "latest"} - } -}); -st.configRS.awaitReplication(); - -// Create a sharded time-series collection that has fixed buckets. -const dbName = "test"; -let testDB = st.s.getDB(dbName); -assert.commandWorked(st.s.adminCommand({enableSharding: dbName, primaryShard: st.shard0.name})); - -let coll = testDB["timeseries"]; -const timeField = "t"; -coll.drop(); -const shardKey = { - [timeField]: 1 -}; - -function runPipeline(predValue) { - // Run the query and confirm the correct results were returned. - let predicate = ISODate("2022-11-12"); - if (predValue) { - predicate = predValue; - } - const pipeline = [{$match: {[timeField]: {$lt: predicate}}}]; - const results = coll.aggregate(pipeline).toArray(); - assert.sameMembers(results, [docs[0], docs[1], docs[2]]); - - const explain = coll.explain().aggregate(pipeline); - const unpackStage = getAggPlanStages(explain, "$_internalUnpackBucket"); - // If data is on both of the shards, we will see 2 "$_internalUnpackBucket" stages in the - // explain plan. - assert.gte(unpackStage.length, 1, `Expected $_internalUnpackBucket in ${tojson(explain)}`); - return unpackStage[0]["$_internalUnpackBucket"]; -} - -assert.commandWorked(testDB.adminCommand({ - shardCollection: `${dbName}.${coll.getName()}`, - key: shardKey, - timeseries: {timeField, bucketRoundingSeconds: 3600, bucketMaxSpanSeconds: 3600} -})); - -// Set up the shards such that the primary shard has [MinKey, 2022-09-30), and the other shard has -// [2022-09-30, MaxKey]. -let splitPoint = {[`control.min.${timeField}`]: ISODate(`2022-09-30`)}; -assert.commandWorked( - testDB.adminCommand({split: `${dbName}.system.buckets.${coll.getName()}`, middle: splitPoint})); - -// Move one of the chunks into the second shard. -const primaryShard = st.getPrimaryShard(dbName); -const otherShard = st.getOther(primaryShard); -assert.commandWorked(testDB.adminCommand({ - movechunk: `${dbName}.system.buckets.${coll.getName()}`, - find: splitPoint, - to: otherShard.name, - _waitForDelete: true -})); - -// Insert 4 documents and expect 2 documents on each shard. -const docs = [ - {_id: 0, [timeField]: ISODate("2017-10-12")}, - {_id: 1, [timeField]: ISODate("2018-10-12")}, - {_id: 2, [timeField]: ISODate("2022-10-12")}, - {_id: 3, [timeField]: ISODate("2023-11-12")}, -]; -coll.insertMany(docs); - -// Run the pipeline, and expect no eventFilter, since the rewrite should occur. -let unpackStage = runPipeline(); -assert(!unpackStage["eventFilter"], "Expected no eventFilter, but got: " + tojson(unpackStage)); - -// Run a different pipeline, and expect an eventFilter. The rewrite does not apply because the -// predicate passed in does not align with the bucket boundaries. -unpackStage = runPipeline(ISODate("2022-11-12T07:30:10.957Z") /* predValue */); -assert(unpackStage["eventFilter"], "Expected an eventFilter, but got: " + tojson(unpackStage)); - -// Downgrade the FCV version. -jsTestLog('downgrading the FCV version.'); -assert.commandWorked(testDB.adminCommand({setFeatureCompatibilityVersion: '7.0', confirm: true})); - -// Run the pipeline, and expect an eventFilter, since the FCV version is downgraded. -unpackStage = runPipeline(); -assert(unpackStage["eventFilter"], "Expected an eventFilter, but got: " + tojson(unpackStage)); - -// Downgrade the mongos binary. -jsTestLog('downgrading mongos.'); -st.restartBinariesWithDowngradeBackCompat('latest'); -st.downgradeBinariesWithoutDowngradeBackCompat('last-lts', - {downgradeShards: false, downgradeConfigs: false}); -let mongosConn = st.s; -testDB = mongosConn.getDB(dbName); -coll = testDB[coll.getName()]; - -// Downgrade the other shard's binary. We now have a mixed cluster. -jsTestLog('downgrading other shard.'); -st.downgradeBinariesWithoutDowngradeBackCompat('last-lts', { - downgradeShards: false, - downgradeOneShard: st.rs1, - downgradeMongos: false, - downgradeConfigs: false -}); -awaitRSClientHosts(st.s, st.rs0.getPrimary(), {ok: true, ismaster: true}); -awaitRSClientHosts(st.s, st.rs1.getPrimary(), {ok: true, ismaster: true}); - -// Before running the query, restart the profiler. -const primaryDB = st.shard0.getDB(dbName); -const otherDB = st.shard1.getDB(dbName); -for (let shardDB of [primaryDB, otherDB]) { - shardDB.setProfilingLevel(0); - shardDB.system.profile.drop(); - shardDB.setProfilingLevel(2); -} -// Run the pipeline, and expect an eventFilter, since the FCV version is still downgraded. -unpackStage = runPipeline(); -assert(unpackStage["eventFilter"], "Expected an eventFilter, but got: " + tojson(unpackStage)); - -// Confirm the other shard ran the query. -let filter = {"command.aggregate": `system.buckets.${coll.getName()}`}; -const otherShardEntries = otherDB.system.profile.find(filter).toArray(); -assert.eq(otherShardEntries.length, 1, otherShardEntries); - -// Downgrade the rest of the shards and the config server. -jsTestLog('downgrading the rest of the shards and the config server.'); -st.downgradeBinariesWithoutDowngradeBackCompat('last-lts', {downgradeMongos: false}); -awaitRSClientHosts(st.s, st.rs0.getPrimary(), {ok: true, ismaster: true}); -awaitRSClientHosts(st.s, st.rs1.getPrimary(), {ok: true, ismaster: true}); - -// Run the pipeline, and expect an eventFilter, since the FCV version is still downgraded. -unpackStage = runPipeline(); -assert(unpackStage["eventFilter"], "Expected an eventFilter, but got: " + tojson(unpackStage)); - -st.stop(); -}()); diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/timeseries_fixed_param_flag.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/timeseries_fixed_param_flag.js deleted file mode 100644 index 36eca2bb822..00000000000 --- a/jstests/multiVersion/targetedTestsLastLtsFeatures/timeseries_fixed_param_flag.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Verifies that the internal collection catalog parameter is correctly cleanup after downgrade. - */ - -import "jstests/multiVersion/libs/multi_rs.js"; - -(function() { -"use strict"; - -const latestVersion = "latest"; -const rst = new ReplSetTest( - {name: jsTestName(), nodes: [{binVersion: latestVersion}, {binVersion: latestVersion}]}); -rst.startSet(); -rst.initiate(); -const testDB = rst.getPrimary().getDB("test"); - -const collectionName = "coll"; -assert.commandWorked(testDB.createCollection(collectionName, {timeseries: {timeField: 't'}})); -let output = assert.commandWorked( - testDB.runCommand({timeseriesCatalogBucketParamsChanged: 'system.buckets.coll'})); -assert.eq(output.changed, false); - -// Ensure that running empty collMod does not affect the flag while on latest FCV. -assert.commandWorked(testDB.runCommand({collMod: collectionName})); -output = assert.commandWorked( - testDB.runCommand({timeseriesCatalogBucketParamsChanged: 'system.buckets.coll'})); -assert.eq(output.changed, false); - -// Running a setFCV downgrade command should remove the catalog flag. -assert.commandWorked(rst.getPrimary().getDB("admin").runCommand( - {setFeatureCompatibilityVersion: lastLTSFCV, confirm: true})); -output = assert.commandWorked( - testDB.runCommand({timeseriesCatalogBucketParamsChanged: 'system.buckets.coll'})); -assert.eq(output.changed, undefined); - -// While FCV is in downgrading/downgraded state, collMod command should not effect the bucketing -// parameters flag. -assert.commandWorked( - testDB.runCommand({collMod: collectionName, timeseries: {granularity: "minutes"}})); -output = assert.commandWorked( - testDB.runCommand({timeseriesCatalogBucketParamsChanged: 'system.buckets.coll'})); -assert.eq(output.changed, undefined); - -assert.commandWorked(rst.getPrimary().getDB("admin").runCommand( - {setFeatureCompatibilityVersion: latestFCV, confirm: true})); - -// After the FCV is set to latest, the value of the flag of the collection should be undefined. -output = assert.commandWorked( - testDB.runCommand({timeseriesCatalogBucketParamsChanged: 'system.buckets.coll'})); -assert.eq(output.changed, undefined); - -// After FCV is set to latest, collMod command should explicity set the bucketing parameters flag -// to true. -assert.commandWorked(testDB.runCommand({ - collMod: collectionName, - timeseries: {bucketRoundingSeconds: 100000, bucketMaxSpanSeconds: 100000} -})); -output = assert.commandWorked( - testDB.runCommand({timeseriesCatalogBucketParamsChanged: 'system.buckets.coll'})); -assert.eq(output.changed, true); - -// Now that the feature is turned on, new time-series collections by default will have the flag set -// to 'false'. -const otherCollName = "other_coll"; -const otherCollBucketsName = "system.buckets.other_coll"; -assert.commandWorked(testDB.createCollection( - otherCollName, - {timeseries: {timeField: 't', bucketRoundingSeconds: 3600, bucketMaxSpanSeconds: 3600}})); -output = assert.commandWorked( - testDB.runCommand({timeseriesCatalogBucketParamsChanged: otherCollBucketsName})); -assert.eq(output.changed, false); - -// We will now test the flag is set correctly if the FCV downgrade fails after only reaching the -// `downgrading` FCV state, and then is fully upgraded again. -jsTestLog("Turning the failpoint on."); -assert.commandWorked( - rst.getPrimary().adminCommand({configureFailPoint: 'failDowngrading', mode: "alwaysOn"})); -assert.commandFailedWithCode( - testDB.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true}), 549181); - -// Confirm feature is still enabled since the FCV downgrade failed. -output = assert.commandWorked( - testDB.runCommand({timeseriesCatalogBucketParamsChanged: otherCollBucketsName})); -assert.eq(output.changed, false); - -assert.commandWorked(rst.getPrimary().getDB("admin").runCommand( - {setFeatureCompatibilityVersion: latestFCV, confirm: true})); - -// Confirm the feature remains enabled when the FCV is upgraded. Since the FCV is already at '7.1' -// the value of the flag should not change. -output = assert.commandWorked( - testDB.runCommand({timeseriesCatalogBucketParamsChanged: otherCollBucketsName})); -assert.eq(output.changed, false); - -// The flag should be set to true after a collMod command. -assert.commandWorked(testDB.runCommand({ - collMod: otherCollName, - timeseries: {bucketRoundingSeconds: 100000, bucketMaxSpanSeconds: 100000} -})); -output = assert.commandWorked( - testDB.runCommand({timeseriesCatalogBucketParamsChanged: otherCollBucketsName})); -assert.eq(output.changed, true); - -rst.stopSet(); -})(); diff --git a/jstests/noPassthrough/index_build_aborted_on_fcv_downgrade.js b/jstests/noPassthrough/index_build_aborted_on_fcv_downgrade.js deleted file mode 100644 index 9dd44910ddb..00000000000 --- a/jstests/noPassthrough/index_build_aborted_on_fcv_downgrade.js +++ /dev/null @@ -1,195 +0,0 @@ -/** - * Ensures that index builds are aborted when setFCV causes an FCV downgrade, and that during that - * period new index builds are blocked. - * - * TODO (SERVER-68290): remove test when removing index build abort on FCV downgrade and reintroduce - * "jstests/noPassthrough/index_downgrade_fcv.js". - * - * @tags: [ - * requires_fcv_71, - * requires_replication, - * ] - */ -import {configureFailPoint} from "jstests/libs/fail_point_util.js"; -import {funWithArgs} from "jstests/libs/parallel_shell_helpers.js"; -import {extractUUIDFromObject} from "jstests/libs/uuid_util.js"; -import {IndexBuildTest} from "jstests/noPassthrough/libs/index_build.js"; - -function startParallelSetFcv(primary, expectedError) { - return startParallelShell( - funWithArgs(function(expectedError) { - // Should fail due to failAfterReachingTransitioningState. - assert.commandFailedWithCode( - db.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV, confirm: true}), - expectedError); - }, expectedError), primary.port); -} - -function testIndexBuildsBlockedAndAbortedOnFcvDowngrade() { - const rst = new ReplSetTest({ - nodes: [ - {}, - { - // Disallow elections on secondary. - rsConfig: { - priority: 0, - }, - }, - ] - }); - rst.startSet(); - rst.initiate(); - - const dbName = 'test'; - const collName = 'coll'; - const primary = rst.getPrimary(); - const primaryDB = primary.getDB(dbName); - const primaryColl = primaryDB.getCollection(collName); - - assert.commandWorked(primaryColl.insert({a: 1})); - - rst.awaitReplication(); - - // Clear log to ensure checkLog does not see unrelated log entries. - assert.commandWorked(primaryDB.adminCommand({clearLog: 'global'})); - - // Hang an index build in the commit phase, to later check that FCV downgrade waits on a - // commiting index build. - const hangIndexBuildBeforeCommit = configureFailPoint(primary, "hangIndexBuildBeforeCommit"); - const createIdxCommit = IndexBuildTest.startIndexBuild( - primary, primaryColl.getFullName(), {c: 1}, null, [ErrorCodes.IndexBuildAborted]); - const commitBuildUUID = - IndexBuildTest - .assertIndexesSoon(primaryColl, 2, ['_id_'], ['c_1'], {includeBuildUUIDs: true})['c_1'] - .buildUUID; - hangIndexBuildBeforeCommit.wait(); - - // Setup index build to be aborted by the FCV downgrade. - const hangAfterInitializingIndexBuild = - configureFailPoint(primary, "hangAfterInitializingIndexBuild"); - const createIdxAborted = IndexBuildTest.startIndexBuild( - primary, primaryColl.getFullName(), {a: 1}, null, [ErrorCodes.IndexBuildAborted]); - - const abortedBuildUUID = - IndexBuildTest - .assertIndexesSoon( - primaryColl, 3, ['_id_'], ['a_1', 'c_1'], {includeBuildUUIDs: true})['a_1'] - .buildUUID; - - hangAfterInitializingIndexBuild.wait(); - - const hangAfterBlockingIndexBuildsForFcvDowngrade = - configureFailPoint(primary, "hangAfterBlockingIndexBuildsForFcvDowngrade"); - - // Ensure index build block and abort happens during the FCV transitioning state. - configureFailPoint(primary, "failAfterReachingTransitioningState"); - - const awaitSetFcv = startParallelSetFcv(primary, 7555200); - - hangAfterBlockingIndexBuildsForFcvDowngrade.wait(); - - // Start an index build while the block is active. - const createIdxBlocked = - IndexBuildTest.startIndexBuild(primary, primaryColl.getFullName(), {b: 1}); - // "Index build: new index builds are blocked, waiting". - checkLog.containsJson(primary, 7738700); - - hangAfterBlockingIndexBuildsForFcvDowngrade.off(); - - // "About to abort all index builders running". - assert.soon(() => checkLog.checkContainsWithCountJson(primary, - 7738702, - { - reason: function(reason) { - return reason.startsWith( - "FCV downgrade in progress"); - } - }, - /*count=*/ 1)); - - // "Index build: joined after abort". - checkLog.containsJson(primary, 20655, { - buildUUID: function(uuid) { - return uuid && uuid["uuid"]["$uuid"] === extractUUIDFromObject(abortedBuildUUID); - } - }); - - checkLog.containsJson(primary, 4725201, { - indexBuilds: function(uuidArray) { - return uuidArray && uuidArray.length == 1 && - uuidArray[0]["uuid"]["$uuid"] === extractUUIDFromObject(commitBuildUUID); - } - }); - hangIndexBuildBeforeCommit.off(); - hangAfterInitializingIndexBuild.off(); - - jsTestLog("Waiting for threads to join"); - createIdxAborted(); - createIdxCommit(); - awaitSetFcv(); - createIdxBlocked(); - - // The index build started before the FCV downgrade should have been aborted, while the build - // started while the index build block was in place should have succeeded. The index build which - // was already in the commit phase when the FCV downgrade took place should also have completed. - IndexBuildTest.assertIndexesSoon(primaryColl, 3, ['_id_', 'b_1', 'c_1']); - - rst.stopSet(); -} - -function testIndexBuildsUnblockedOnSetFcvCommandInterrupt() { - const rst = new ReplSetTest({ - nodes: [ - {}, - { - // Disallow elections on secondary. - rsConfig: { - priority: 0, - }, - }, - ] - }); - rst.startSet(); - rst.initiate(); - - const dbName = 'test'; - const collName = 'coll'; - const primary = rst.getPrimary(); - const primaryDB = primary.getDB(dbName); - const primaryColl = primaryDB.getCollection(collName); - - assert.commandWorked(primaryColl.insert({a: 1})); - - rst.awaitReplication(); - - // Clear log to ensure checkLog does not see unrelated log entries. - assert.commandWorked(primaryDB.adminCommand({clearLog: 'global'})); - - const hangAfterBlockingIndexBuildsForFcvDowngrade = - configureFailPoint(primary, "hangAfterBlockingIndexBuildsForFcvDowngrade"); - - // Verify the index builds are unblocked in case the setFCV command is interrupted. - const awaitKilledSetFcv = startParallelSetFcv(primary, ErrorCodes.Interrupted); - hangAfterBlockingIndexBuildsForFcvDowngrade.wait(); - - const pipeline = [ - {$currentOp: {allUsers: true, idleConnections: true}}, - {$match: {"command.setFeatureCompatibilityVersion": {$exists: true}}} - ]; - const curOpResult = - primary.getDB("admin").aggregate(pipeline, {readConcern: {level: "local"}}).toArray(); - assert.eq(curOpResult.length, 1); - assert.commandWorked(primary.adminCommand({killOp: 1, op: curOpResult[0].opid})); - - awaitKilledSetFcv(); - - const createIdxBlocked = - IndexBuildTest.startIndexBuild(primary, primaryColl.getFullName(), {b: 1}); - createIdxBlocked(); - IndexBuildTest.assertIndexesSoon(primaryColl, 2, ['_id_', 'b_1']); - - rst.stopSet(); -} - -testIndexBuildsBlockedAndAbortedOnFcvDowngrade(); -testIndexBuildsUnblockedOnSetFcvCommandInterrupt(); diff --git a/jstests/noPassthrough/queryStats/query_stats_disable_after_initial_request.js b/jstests/noPassthrough/queryStats/query_stats_disable_after_initial_request.js index f485f61e894..4ef1ae814f8 100644 --- a/jstests/noPassthrough/queryStats/query_stats_disable_after_initial_request.js +++ b/jstests/noPassthrough/queryStats/query_stats_disable_after_initial_request.js @@ -48,11 +48,6 @@ function setQueryStatsCacheSize(size) { assert.commandWorked(testDB.adminCommand({setParameter: 1, internalQueryStatsCacheSize: size})); } -function setFCV(newFCV) { - assert.commandWorked( - testDB.adminCommand({setFeatureCompatibilityVersion: newFCV, confirm: true})); -} - // Tests the scenario of disabling query stats by setting internalQueryStatsCacheSize to 0 and // ending the command by running it to completion. testStatsAreNotCollectedWhenDisabledBeforeCommandCompletion({ @@ -74,25 +69,4 @@ testStatsAreNotCollectedWhenDisabledBeforeCommandCompletion({ enableQueryStatsFn: () => setQueryStatsCacheSize("10MB") }); -// Tests the scenario of disabling query stats by downgrading the FCV and ending the command by -// running it to completion. -testStatsAreNotCollectedWhenDisabledBeforeCommandCompletion({ - conn: testDB, - coll, - disableQueryStatsFn: () => setFCV(lastLTSFCV), - endCommandFn: (cursor) => cursor.itcount(), - enableQueryStatsFn: () => setFCV(binVersionToFCV("latest")) -}); - -// Tests the scenario of disabling query stats by downgrading the FCV and ending the command by -// killing the cursor. -testStatsAreNotCollectedWhenDisabledBeforeCommandCompletion({ - conn: testDB, - coll, - disableQueryStatsFn: () => setFCV(lastLTSFCV), - endCommandFn: (cursor) => assert.commandWorked( - testDB.runCommand({killCursors: coll.getName(), cursors: [cursor.getId()]})), - enableQueryStatsFn: () => setFCV(binVersionToFCV("latest")) -}); - MongoRunner.stopMongod(conn); diff --git a/jstests/noPassthrough/queryStats/query_stats_upgrade.js b/jstests/noPassthrough/queryStats/query_stats_upgrade.js deleted file mode 100644 index 64b07068c9d..00000000000 --- a/jstests/noPassthrough/queryStats/query_stats_upgrade.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Test that query stats doesn't work on a lower FCV version but works after an FCV upgrade. - * @tags: [ - * # Query Stats is new in 7.1. - * requires_fcv_71, - * # Re-uses FCV state in the dbpath. - * requires_persistence - * ] - */ - -const dbpath = MongoRunner.dataPath + jsTestName(); -let conn = MongoRunner.runMongod({dbpath: dbpath}); -let testDB = conn.getDB(jsTestName()); - -function testLower(restart = false) { - let adminDB = conn.getDB("admin"); - assert.commandWorked(adminDB.runCommand( - {setFeatureCompatibilityVersion: binVersionToFCV("last-lts"), confirm: true})); - if (restart) { - MongoRunner.stopMongod(conn); - conn = MongoRunner.runMongod({dbpath: dbpath, noCleanData: true}); - testDB = conn.getDB(jsTestName()); - adminDB = conn.getDB("admin"); - } - - assert.commandFailedWithCode( - testDB.adminCommand({aggregate: 1, pipeline: [{$queryStats: {}}], cursor: {}}), - [6579000, ErrorCodes.QueryFeatureNotAllowed]); - - // Upgrade FCV. - assert.commandWorked(adminDB.runCommand( - {setFeatureCompatibilityVersion: binVersionToFCV("latest"), confirm: true})); - - // We should be able to run a query stats pipeline now that the FCV is correct. - assert.commandWorked( - testDB.adminCommand({aggregate: 1, pipeline: [{$queryStats: {}}], cursor: {}}), - ); -} -testLower(true); -testLower(false); -MongoRunner.stopMongod(conn); diff --git a/jstests/serverless/shard_merge_enabled.js b/jstests/serverless/shard_merge_enabled.js deleted file mode 100644 index ef7a4179914..00000000000 --- a/jstests/serverless/shard_merge_enabled.js +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Tests that the "shard merge" protocol is enabled only in the proper FCV. - * - * @tags: [ - * requires_shard_merge, - * serverless, - * requires_fcv_71, - * ] - */ - -import {configureFailPoint} from "jstests/libs/fail_point_util.js"; - -function runTest(downgradeFCV) { - const rst = new ReplSetTest({nodes: 1, serverless: true}); - rst.startSet(); - rst.initiate(); - - const primary = rst.getPrimary(); - - const adminDB = primary.getDB("admin"); - const kDummyConnStr = "mongodb://localhost/?replicaSet=foo"; - const readPreference = {mode: 'primary'}; - - // A function, not a constant, to ensure unique UUIDs. - function donorStartMigrationCmd() { - return { - donorStartMigration: 1, - protocol: "shard merge", - migrationId: UUID(), - recipientConnectionString: kDummyConnStr, - readPreference: readPreference, - tenantIds: [ObjectId()] - }; - } - - function recipientSyncDataCmd() { - return { - recipientSyncData: 1, - protocol: "shard merge", - migrationId: UUID(), - tenantIds: [ObjectId()], - donorConnectionString: kDummyConnStr, - readPreference: readPreference, - startMigrationDonorTimestamp: Timestamp(1, 1), - }; - } - - function recipientForgetMigrationCmd() { - return { - recipientForgetMigration: 1, - protocol: "shard merge", - migrationId: UUID(), - tenantIds: [ObjectId()], - donorConnectionString: kDummyConnStr, - readPreference: readPreference, - decision: "committed" - }; - } - - function func(cmd) { - return eval(cmd + "Cmd()"); - } - - function testCommandWithShardMerge(cmd) { - let msg = cmd + " shouldn't reject 'shard merge' protocol when it's enabled"; - assert.commandWorked(adminDB.runCommand(func(cmd)), msg); - } - - function testCommandFailsWithShardMerge(cmd, reason, expectedErrorMsg, expectedErrorCode) { - let msg = `${cmd} ${reason}`; - let response = - assert.commandFailedWithCode(adminDB.runCommand(func(cmd)), expectedErrorCode, msg); - assert.neq(-1, - response.errmsg.indexOf(expectedErrorMsg), - "Error message did not contain '" + expectedErrorMsg + "', found:\n" + - tojson(response)); - } - - function testCommandFailsShardMergeNotSupported(cmd) { - testCommandFailsWithShardMerge(cmd, - "should reject 'shard merge' protocol when it's disabled", - "protocol 'shard merge' not supported", - ErrorCodes.IllegalOperation); - } - - function testCommandFailsProtocolFieldNotSupported(cmd) { - testCommandFailsWithShardMerge(cmd, - "should reject 'protocol' field when it's disabled", - "'protocol' field is not supported for FCV below 5.2'", - ErrorCodes.InvalidOptions); - } - - // Enable below fail points to prevent starting the donor/recipient POS instance. - configureFailPoint(primary, "returnResponseCommittedForDonorStartMigrationCmd"); - configureFailPoint(primary, "returnResponseOkForRecipientSyncDataCmd"); - configureFailPoint(primary, "returnResponseOkForRecipientForgetMigrationCmd"); - - // Preconditions: the shard merge feature is enabled and our fresh RS is on the latest FCV. - assert.eq(getFCVConstants().latest, - adminDB.system.version.findOne({_id: 'featureCompatibilityVersion'}).version); - - // Shard merge is enabled, so this call should work. - let cmds = ["donorStartMigration", "recipientSyncData", "recipientForgetMigration"]; - cmds.forEach((cmd) => { - testCommandWithShardMerge(cmd); - }); - - assert.commandWorked( - adminDB.adminCommand({setFeatureCompatibilityVersion: downgradeFCV, confirm: true})); - // Now that FCV is downgraded, shard merge is automatically disabled. - cmds.forEach((cmd) => { - if (MongoRunner.compareBinVersions(downgradeFCV, "5.2") >= 0) { - // The "protocol" field is ok, but it can't be "shard merge". - testCommandFailsShardMergeNotSupported(cmd); - } else { - // The "protocol" field is not supported. - testCommandFailsProtocolFieldNotSupported(cmd); - } - }); - - rst.stopSet(); -} - -runFeatureFlagMultiversionTest('featureFlagShardMerge', runTest); diff --git a/src/mongo/util/version/releases.yml b/src/mongo/util/version/releases.yml index e31f246c601..8d92bd371ca 100644 --- a/src/mongo/util/version/releases.yml +++ b/src/mongo/util/version/releases.yml @@ -24,6 +24,7 @@ featureCompatibilityVersions: - "7.2" - "7.3" - "8.0" + - "8.1" - "100.0" # This version is not an actual version and used for testing only # All LTS releases starting with 4.0. longTermSupportReleases: @@ -33,6 +34,7 @@ longTermSupportReleases: - "5.0" - "6.0" - "7.0" + - "8.0" # List of stable MongoDB versions since 2.0 that have been EOL'd. # Entries to this section will also stop them from running as "old" versions in |
