summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjannaerin <golden.janna@gmail.com>2021-12-06 16:19:51 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-04 18:06:22 +0000
commitda82e5278ca717d3228e4837a3e815c5ced876e0 (patch)
tree4a3bdda5c9a9d3d39a15dbcce1264a9e34dc72d2
parent863684a584bfa5b4beeffb8d2a79e735299c1de7 (diff)
downloadmongo-da82e5278ca717d3228e4837a3e815c5ced876e0.tar.gz
SERVER-61474 Ban directoryPerDb and directoryForIndexes with Merge
-rw-r--r--jstests/replsets/shard_merge_invalid_options.js74
-rw-r--r--src/mongo/db/commands/tenant_migration_donor_cmds.cpp2
-rw-r--r--src/mongo/db/commands/tenant_migration_recipient_cmds.cpp2
-rw-r--r--src/mongo/db/repl/tenant_migration_util.h16
-rw-r--r--src/mongo/db/storage/storage_engine.h2
-rw-r--r--src/mongo/db/storage/storage_engine_impl.h4
-rw-r--r--src/mongo/db/storage/storage_engine_mock.h3
7 files changed, 103 insertions, 0 deletions
diff --git a/jstests/replsets/shard_merge_invalid_options.js b/jstests/replsets/shard_merge_invalid_options.js
new file mode 100644
index 00000000000..4d7eee88a40
--- /dev/null
+++ b/jstests/replsets/shard_merge_invalid_options.js
@@ -0,0 +1,74 @@
+/**
+ * Tests that the donorStartMigration and recipientSyncData commands throw when a node has options
+ * set that are incompatible with protocol shard merge.
+ *
+ * @tags: [requires_fcv_53, featureFlagShardMerge]
+ * ]
+ */
+
+(function() {
+"use strict";
+
+load("jstests/replsets/libs/tenant_migration_util.js");
+load("jstests/libs/fail_point_util.js");
+
+function runTest(nodeOptions, expectedError) {
+ let rst = new ReplSetTest({nodes: 1, nodeOptions: nodeOptions});
+ rst.startSet();
+ rst.initiate();
+
+ let primary = rst.getPrimary();
+ let adminDB = primary.getDB("admin");
+ const kDummyConnStr = "mongodb://localhost/?replicaSet=foo";
+ const readPreference = {mode: 'primary'};
+ const migrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForTest();
+
+ // Enable below fail points to prevent starting the donor/recipient POS instance.
+ configureFailPoint(primary, "returnResponseCommittedForDonorStartMigrationCmd");
+ configureFailPoint(primary, "returnResponseOkForRecipientSyncDataCmd");
+ configureFailPoint(primary, "returnResponseOkForRecipientForgetMigrationCmd");
+
+ // Ensure the feature flag is enabled and FCV is latest
+ assert(TenantMigrationUtil.isShardMergeEnabled(adminDB));
+ assert.eq(getFCVConstants().latest,
+ adminDB.system.version.findOne({_id: 'featureCompatibilityVersion'}).version);
+
+ // Assert that donorStartMigration fails with the expected code
+ assert.commandFailedWithCode(
+ adminDB.runCommand({
+ donorStartMigration: 1,
+ protocol: "shard merge",
+ migrationId: UUID(),
+ recipientConnectionString: kDummyConnStr,
+ readPreference: readPreference,
+ donorCertificateForRecipient: migrationCertificates.donorCertificateForRecipient,
+ recipientCertificateForDonor: migrationCertificates.recipientCertificateForDonor
+ }),
+ expectedError,
+ "Expected donorStartMigration to fail when protocol is 'shard merge' and node options " +
+ tojson(nodeOptions) + " are set, but did not");
+
+ // Assert that recipientSyncData fails with the expected code
+ assert.commandFailedWithCode(
+ adminDB.runCommand({
+ recipientSyncData: 1,
+ protocol: "shard merge",
+ migrationId: UUID(),
+ donorConnectionString: kDummyConnStr,
+ readPreference: readPreference,
+ startMigrationDonorTimestamp: Timestamp(1, 1),
+ recipientCertificateForDonor: migrationCertificates.recipientCertificateForDonor
+ }),
+ expectedError,
+ "Expected recipientSyncData to fail when protocol is 'shard merge' and node options " +
+ tojson(nodeOptions) + " are set, but did not");
+
+ rst.stopSet();
+}
+
+// Shard merge is not allowed when directoryperdb is enabled
+runTest({directoryperdb: ""}, ErrorCodes.InvalidOptions);
+
+// Shard merge is not allowed when directoryForIndexes is enabled
+runTest({"wiredTigerDirectoryForIndexes": ""}, ErrorCodes.InvalidOptions);
+})();
diff --git a/src/mongo/db/commands/tenant_migration_donor_cmds.cpp b/src/mongo/db/commands/tenant_migration_donor_cmds.cpp
index 00e283d8563..e94f865d1cb 100644
--- a/src/mongo/db/commands/tenant_migration_donor_cmds.cpp
+++ b/src/mongo/db/commands/tenant_migration_donor_cmds.cpp
@@ -76,6 +76,8 @@ public:
uassertStatusOK(tenant_migration_util::protocolTenantIdCompatibilityCheck(
migrationProtocol, cmd.getTenantId().toString()));
+ tenant_migration_util::protocolStorageOptionsCompatibilityCheck(opCtx,
+ migrationProtocol);
TenantMigrationDonorDocument stateDoc(cmd.getMigrationId(),
cmd.getRecipientConnectionString().toString(),
diff --git a/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp b/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
index 9952d301d47..c81f8ecb697 100644
--- a/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
+++ b/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
@@ -74,6 +74,8 @@ public:
uassertStatusOK(tenant_migration_util::protocolTenantIdCompatibilityCheck(
migrationProtocol, cmd.getTenantId().toString()));
+ tenant_migration_util::protocolStorageOptionsCompatibilityCheck(opCtx,
+ migrationProtocol);
TenantMigrationRecipientDocument stateDoc(cmd.getMigrationId(),
cmd.getDonorConnectionString().toString(),
diff --git a/src/mongo/db/repl/tenant_migration_util.h b/src/mongo/db/repl/tenant_migration_util.h
index 818ffba2649..f3350458182 100644
--- a/src/mongo/db/repl/tenant_migration_util.h
+++ b/src/mongo/db/repl/tenant_migration_util.h
@@ -186,6 +186,22 @@ inline Status protocolTenantIdCompatibilityCheck(const MigrationProtocolEnum& pr
return Status::OK();
}
+inline void protocolStorageOptionsCompatibilityCheck(OperationContext* opCtx,
+ const MigrationProtocolEnum& protocol) {
+ if (protocol != MigrationProtocolEnum::kShardMerge)
+ return;
+
+ uassert(ErrorCodes::InvalidOptions,
+ str::stream() << "protocol '" << MigrationProtocol_serializer(protocol)
+ << "' is not allowed when storage option 'directoryPerDb' is enabled",
+ !storageGlobalParams.directoryperdb);
+ uassert(
+ ErrorCodes::InvalidOptions,
+ str::stream() << "protocol '" << MigrationProtocol_serializer(protocol)
+ << "' is not allowed when storage option 'directoryForIndexes' is enabled",
+ !opCtx->getServiceContext()->getStorageEngine()->isUsingDirectoryForIndexes());
+}
+
/*
* Creates an ExternalKeysCollectionDocument representing an config.external_validation_keys
* document from the given the admin.system.keys document BSONObj.
diff --git a/src/mongo/db/storage/storage_engine.h b/src/mongo/db/storage/storage_engine.h
index f7c706b96a6..2160a430aa0 100644
--- a/src/mongo/db/storage/storage_engine.h
+++ b/src/mongo/db/storage/storage_engine.h
@@ -643,6 +643,8 @@ public:
virtual bool isUsingDirectoryPerDb() const = 0;
+ virtual bool isUsingDirectoryForIndexes() const = 0;
+
virtual KVEngine* getEngine() = 0;
virtual const KVEngine* getEngine() const = 0;
virtual DurableCatalog* getCatalog() = 0;
diff --git a/src/mongo/db/storage/storage_engine_impl.h b/src/mongo/db/storage/storage_engine_impl.h
index f2b69e8d2ee..4f25de8f7d2 100644
--- a/src/mongo/db/storage/storage_engine_impl.h
+++ b/src/mongo/db/storage/storage_engine_impl.h
@@ -348,6 +348,10 @@ public:
return _options.directoryPerDB;
}
+ bool isUsingDirectoryForIndexes() const override {
+ return _options.directoryForIndexes;
+ }
+
StatusWith<Timestamp> pinOldestTimestamp(OperationContext* opCtx,
const std::string& requestingServiceName,
Timestamp requestedTimestamp,
diff --git a/src/mongo/db/storage/storage_engine_mock.h b/src/mongo/db/storage/storage_engine_mock.h
index 7032a3afe87..93a187c7615 100644
--- a/src/mongo/db/storage/storage_engine_mock.h
+++ b/src/mongo/db/storage/storage_engine_mock.h
@@ -179,6 +179,9 @@ public:
bool isUsingDirectoryPerDb() const final {
return false;
}
+ bool isUsingDirectoryForIndexes() const final {
+ return false;
+ }
KVEngine* getEngine() final {
return nullptr;
}