summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuganthi Mani <suganthi.mani@mongodb.com>2021-10-23 01:21:32 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-10-23 01:50:13 +0000
commit56a5ddbf5a2ba92169e81ec24f9387c5fe1c0931 (patch)
tree9d045046d63e41db85bd5d827d6b39d104129c33
parent58bc7ee16dcc0bbda6c5c1a437b39982b9630cd0 (diff)
downloadmongo-56a5ddbf5a2ba92169e81ec24f9387c5fe1c0931.tar.gz
SERVER-59495 Donor and recipient tenant migration state machines will persist the migration protocol info and tenantId info will be an empty string for 'Merge' protcol.
Added a new optional "protocol" field to 'recipientSyncData' cmd & made 'tenantId' field as optional.
-rw-r--r--buildscripts/idl/idl/generator.py21
-rw-r--r--jstests/replsets/libs/tenant_migration_util.js2
-rw-r--r--jstests/replsets/shard_merge_enabled.js44
-rw-r--r--jstests/replsets/tenant_migration_invalid_inputs.js28
-rw-r--r--src/mongo/db/commands/SConscript1
-rw-r--r--src/mongo/db/commands/tenant_migration_donor_cmds.cpp25
-rw-r--r--src/mongo/db/commands/tenant_migration_donor_cmds.idl14
-rw-r--r--src/mongo/db/commands/tenant_migration_recipient_cmds.cpp17
-rw-r--r--src/mongo/db/commands/tenant_migration_recipient_cmds.idl6
-rw-r--r--src/mongo/db/repl/SConscript1
-rw-r--r--src/mongo/db/repl/tenant_migration_donor_service.cpp16
-rw-r--r--src/mongo/db/repl/tenant_migration_donor_service.h6
-rw-r--r--src/mongo/db/repl/tenant_migration_donor_service_test.cpp3
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp30
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_service.cpp7
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_service.h6
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_service_test.cpp156
-rw-r--r--src/mongo/db/repl/tenant_migration_state_machine.idl7
-rw-r--r--src/mongo/db/repl/tenant_migration_util.h30
-rw-r--r--src/mongo/db/serverless/SConscript12
-rw-r--r--src/mongo/db/serverless/serverless_types.idl40
21 files changed, 355 insertions, 117 deletions
diff --git a/buildscripts/idl/idl/generator.py b/buildscripts/idl/idl/generator.py
index 51569af4d4f..c806d016296 100644
--- a/buildscripts/idl/idl/generator.py
+++ b/buildscripts/idl/idl/generator.py
@@ -230,24 +230,15 @@ class _FastFieldUsageChecker(_FieldUsageCheckerBase):
with writer.IndentedScopedBlock(self._writer, 'if (MONGO_unlikely(!usedFields.all())) {',
'}'):
for field in self._fields:
- if (not field.optional) and (not field.ignore):
+ # If 'field.default' is true, the fields(members) gets initialized with the default
+ # value in the class definition. So, it's ok to skip setting the field to
+ # default value here.
+ if (not field.optional) and (not field.ignore) and (not field.default):
with writer.IndentedScopedBlock(
self._writer,
'if (!usedFields[%s]) {' % (_gen_field_usage_constant(field)), '}'):
- if field.default:
- default_value = (field.type.cpp_type + "::" + field.default) \
- if field.type.is_enum else field.default
- if field.chained_struct_field:
- self._writer.write_line(
- '%s.%s(%s);' %
- (_get_field_member_name(field.chained_struct_field),
- _get_field_member_setter_name(field), default_value))
- else:
- self._writer.write_line(
- '%s = %s;' % (_get_field_member_name(field), default_value))
- else:
- self._writer.write_line(
- 'ctxt.throwMissingField(%s);' % (_get_field_constant_name(field)))
+ self._writer.write_line(
+ 'ctxt.throwMissingField(%s);' % (_get_field_constant_name(field)))
class _SlowFieldUsageChecker(_FastFieldUsageChecker):
diff --git a/jstests/replsets/libs/tenant_migration_util.js b/jstests/replsets/libs/tenant_migration_util.js
index 9d89ceee585..6a07a83065c 100644
--- a/jstests/replsets/libs/tenant_migration_util.js
+++ b/jstests/replsets/libs/tenant_migration_util.js
@@ -37,7 +37,7 @@ var TenantMigrationUtil = (function() {
*/
function donorStartMigrationWithProtocol(cmd, db) {
// If we don't pass "protocol", the server uses "multitenant migrations" by default.
- if (isShardMergeEnabled(db)) {
+ if (cmd['protocol'] === undefined && isShardMergeEnabled(db)) {
return Object.assign(Object.assign({}, cmd), {protocol: "shard merge"});
}
diff --git a/jstests/replsets/shard_merge_enabled.js b/jstests/replsets/shard_merge_enabled.js
index 8c02658fad0..66760137999 100644
--- a/jstests/replsets/shard_merge_enabled.js
+++ b/jstests/replsets/shard_merge_enabled.js
@@ -7,6 +7,7 @@
"use strict";
load("jstests/replsets/libs/tenant_migration_util.js");
+load("jstests/libs/fail_point_util.js");
function runTest(downgradeFCV) {
let rst = new ReplSetTest({nodes: 1});
@@ -16,37 +17,62 @@ function runTest(downgradeFCV) {
let primary = rst.getPrimary();
let adminDB = primary.getDB("admin");
const kDummyConnStr = "mongodb://localhost/?replicaSet=foo";
+ const readPreference = {mode: 'primary'};
+ const migrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForTest();
+
// A function, not a constant, to ensure unique UUIDs.
function donorStartMigrationCmd() {
return {
donorStartMigration: 1,
protocol: "shard merge",
- tenantId: "foo",
migrationId: UUID(),
recipientConnectionString: kDummyConnStr,
- readPreference: {mode: "primary"},
+ readPreference: readPreference,
+ donorCertificateForRecipient: migrationCertificates.donorCertificateForRecipient,
+ recipientCertificateForDonor: migrationCertificates.recipientCertificateForDonor
+ };
+ }
+
+ function recipientSyncDataCmd() {
+ return {
+ recipientSyncData: 1,
+ protocol: "shard merge",
+ migrationId: UUID(),
+ donorConnectionString: kDummyConnStr,
+ readPreference: readPreference,
+ startMigrationDonorTimestamp: Timestamp(1, 1),
+ recipientCertificateForDonor: migrationCertificates.recipientCertificateForDonor
};
}
+ // Enable below fail points to prevent starting the donor/recipient POS instance.
+ configureFailPoint(primary, "returnResponseCommittedForDonorStartMigrationCmd");
+ configureFailPoint(primary, "returnResponseOkForRecipientSyncDataCmd");
+
// Preconditions: the shard merge feature is enabled and our fresh RS is on the latest FCV.
assert(TenantMigrationUtil.isShardMergeEnabled(adminDB));
assert.eq(getFCVConstants().latest,
adminDB.system.version.findOne({_id: 'featureCompatibilityVersion'}).version);
- // Shard merge is enabled, so this call will fail for some *other* reason, e.g. no certificates,
- // recipient is unavailable.
- let res = adminDB.runCommand(donorStartMigrationCmd());
- assert.neq(res.code,
- 5949300,
- "donorStartMigration shouldn't reject 'shard merge' protocol when it's enabled");
+ // Shard merge is enabled, so this call should work.
+ assert.commandWorked(
+ adminDB.runCommand(donorStartMigrationCmd()),
+ "donorStartMigration shouldn't reject 'shard merge' protocol when it's enabled");
+ assert.commandWorked(
+ adminDB.runCommand(recipientSyncDataCmd()),
+ "recipientSyncDataCmd shouldn't reject 'shard merge' protocol when it's enabled");
assert.commandWorked(adminDB.adminCommand({setFeatureCompatibilityVersion: downgradeFCV}));
// Now that FCV is downgraded, shard merge is automatically disabled.
assert.commandFailedWithCode(
adminDB.runCommand(donorStartMigrationCmd()),
- 5949300,
+ ErrorCodes.IllegalOperation,
"donorStartMigration should reject 'shard merge' protocol when it's disabled");
+ assert.commandFailedWithCode(
+ adminDB.runCommand(recipientSyncDataCmd()),
+ ErrorCodes.IllegalOperation,
+ "recipientSyncDataCmd should reject 'shard merge' protocol when it's disabled");
rst.stopSet();
}
diff --git a/jstests/replsets/tenant_migration_invalid_inputs.js b/jstests/replsets/tenant_migration_invalid_inputs.js
index a680a7164d8..3ac39c57fe0 100644
--- a/jstests/replsets/tenant_migration_invalid_inputs.js
+++ b/jstests/replsets/tenant_migration_invalid_inputs.js
@@ -9,6 +9,7 @@
* incompatible_with_macos,
* incompatible_with_windows_tls,
* requires_persistence,
+ * requires_fcv_51,
* ]
*/
@@ -32,6 +33,21 @@ const migrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForTe
jsTestLog("Testing 'donorStartMigration' command provided with invalid options.");
+// Test missing tenantId field for protocol 'multitenant migrations'.
+assert.commandFailedWithCode(
+ donorPrimary.adminCommand(
+ TenantMigrationUtil.donorStartMigrationWithProtocol({
+ donorStartMigration: 1,
+ protocol: 'multitenant migrations',
+ migrationId: UUID(),
+ recipientConnectionString: tenantMigrationTest.getRecipientRst().getURL(),
+ readPreference: readPreference,
+ donorCertificateForRecipient: migrationCertificates.donorCertificateForRecipient,
+ recipientCertificateForDonor: migrationCertificates.recipientCertificateForDonor,
+ },
+ donorPrimary.getDB("admin"))),
+ ErrorCodes.InvalidOptions);
+
// Test unsupported database prefixes.
const unsupportedtenantIds = ['', 'admin', 'local', 'config'];
unsupportedtenantIds.forEach((invalidTenantId) => {
@@ -98,6 +114,18 @@ assert.commandFailedWithCode(
jsTestLog("Testing 'recipientSyncData' command provided with invalid options.");
+// Test missing tenantId field for protocol 'multitenant migrations'.
+assert.commandFailedWithCode(recipientPrimary.adminCommand({
+ recipientSyncData: 1,
+ protocol: 'multitenant migrations',
+ migrationId: UUID(),
+ donorConnectionString: tenantMigrationTest.getDonorRst().getURL(),
+ startMigrationDonorTimestamp: Timestamp(1, 1),
+ readPreference: readPreference,
+ recipientCertificateForDonor: migrationCertificates.recipientCertificateForDonor,
+}),
+ ErrorCodes.InvalidOptions);
+
// Test unsupported database prefixes.
unsupportedtenantIds.forEach((invalidTenantId) => {
assert.commandFailedWithCode(recipientPrimary.adminCommand({
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index a9281408827..92de98db68b 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -625,6 +625,7 @@ env.Library(
'$BUILD_DIR/mongo/client/read_preference',
'$BUILD_DIR/mongo/db/repl/repl_coordinator_interface',
'$BUILD_DIR/mongo/db/repl/tenant_migration_state_machine_idl',
+ '$BUILD_DIR/mongo/db/serverless/serverless_types_idl',
'$BUILD_DIR/mongo/idl/idl_parser',
]
)
diff --git a/src/mongo/db/commands/tenant_migration_donor_cmds.cpp b/src/mongo/db/commands/tenant_migration_donor_cmds.cpp
index fb78d7099b1..f23c320391a 100644
--- a/src/mongo/db/commands/tenant_migration_donor_cmds.cpp
+++ b/src/mongo/db/commands/tenant_migration_donor_cmds.cpp
@@ -26,6 +26,7 @@
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/commands.h"
@@ -36,10 +37,13 @@
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/repl/tenant_migration_access_blocker_util.h"
#include "mongo/db/repl/tenant_migration_donor_service.h"
+#include "mongo/logv2/log.h"
namespace mongo {
namespace {
+MONGO_FAIL_POINT_DEFINE(returnResponseCommittedForDonorStartMigrationCmd);
+
class DonorStartMigrationCmd : public TypedCommand<DonorStartMigrationCmd> {
public:
using Request = DonorStartMigration;
@@ -68,19 +72,14 @@ public:
const auto& cmd = request();
- if (cmd.getProtocol().value_or(MigrationProtocolEnum::kMultitenantMigrations) ==
- MigrationProtocolEnum::kShardMerge) {
- uassert(5949300,
- "protocol \"shard merge\" not supported",
- repl::feature_flags::gShardMerge.isEnabled(
- serverGlobalParams.featureCompatibility));
- }
+ tenant_migration_util::protocolCompatibilityCheck(cmd.getProtocol(),
+ cmd.getTenantId().toString());
- // TODO (SERVER-59494): tenantId should be optional in the state doc. Include protocol.
TenantMigrationDonorDocument stateDoc(cmd.getMigrationId(),
cmd.getRecipientConnectionString().toString(),
cmd.getReadPreference(),
- cmd.getTenantId().toString());
+ cmd.getTenantId().toString(),
+ cmd.getProtocol());
if (!repl::tenantMigrationDisableX509Auth) {
uassert(ErrorCodes::InvalidOptions,
@@ -97,6 +96,14 @@ public:
const auto stateDocBson = stateDoc.toBSON();
+ if (MONGO_unlikely(returnResponseCommittedForDonorStartMigrationCmd.shouldFail())) {
+ LOGV2(5949401,
+ "Immediately returning committed because "
+ "'returnResponseCommittedForDonorStartMigrationCmd' failpoint is enabled",
+ "tenantMigrationDonorInstance"_attr = stateDoc.toBSON());
+ return Response(TenantMigrationDonorStateEnum::kCommitted);
+ }
+
auto donorService =
repl::PrimaryOnlyServiceRegistry::get(opCtx->getServiceContext())
->lookupServiceByName(TenantMigrationDonorService::kServiceName);
diff --git a/src/mongo/db/commands/tenant_migration_donor_cmds.idl b/src/mongo/db/commands/tenant_migration_donor_cmds.idl
index 750504590f9..3c08f095093 100644
--- a/src/mongo/db/commands/tenant_migration_donor_cmds.idl
+++ b/src/mongo/db/commands/tenant_migration_donor_cmds.idl
@@ -35,17 +35,10 @@ global:
imports:
- "mongo/client/read_preference_setting.idl"
- "mongo/db/repl/tenant_migration_state_machine.idl"
+ - "mongo/db/serverless/serverless_types.idl"
- "mongo/idl/basic_types.idl"
- "mongo/s/sharding_types.idl"
-enums:
- MigrationProtocol:
- description: "Determines which tenant migration protocol to use."
- type: string
- values:
- kMultitenantMigrations: "multitenant migrations"
- kShardMerge: "shard merge"
-
structs:
DonorStartMigrationResponse:
description: "Response of the donorStartMigration command"
@@ -78,6 +71,7 @@ commands:
tenantId:
description: "The prefix from which the migrating database will be matched. The prefixes 'admin', 'local', 'config', the empty string, are not allowed."
type: string
+ default: '""'
validator:
callback: "tenant_migration_util::validateDatabasePrefix"
readPreference:
@@ -98,9 +92,9 @@ commands:
# TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
optional: true
protocol:
- description: "Which migration protocol to use, default 'multitenant migrations'."
+ description: "Which migration protocol to use."
type: MigrationProtocol
- optional: true
+ default: kMultitenantMigrations
donorForgetMigration:
description: "Parser for the 'donorForgetMigration' command."
diff --git a/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp b/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
index b18f5b4c013..dc9f4d9889e 100644
--- a/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
+++ b/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
@@ -34,7 +34,6 @@
#include "mongo/db/commands/tenant_migration_donor_cmds_gen.h"
#include "mongo/db/commands/tenant_migration_recipient_cmds_gen.h"
#include "mongo/db/repl/primary_only_service.h"
-#include "mongo/db/repl/repl_server_parameters_gen.h"
#include "mongo/db/repl/tenant_migration_recipient_service.h"
#include "mongo/logv2/log.h"
@@ -70,11 +69,16 @@ public:
const auto& cmd = request();
+ tenant_migration_util::protocolCompatibilityCheck(cmd.getProtocol(),
+ cmd.getTenantId().toString());
+
TenantMigrationRecipientDocument stateDoc(cmd.getMigrationId(),
cmd.getDonorConnectionString().toString(),
cmd.getTenantId().toString(),
cmd.getStartMigrationDonorTimestamp(),
- cmd.getReadPreference());
+ cmd.getReadPreference(),
+ cmd.getProtocol());
+
if (!repl::tenantMigrationDisableX509Auth) {
uassert(ErrorCodes::InvalidOptions,
@@ -88,7 +92,8 @@ public:
if (MONGO_unlikely(returnResponseOkForRecipientSyncDataCmd.shouldFail())) {
LOGV2(4879608,
- "'returnResponseOkForRecipientSyncDataCmd' failpoint enabled.",
+ "Immediately returning OK because 'returnResponseOkForRecipientSyncDataCmd' "
+ "failpoint is enabled.",
"tenantMigrationRecipientInstance"_attr = stateDoc.toBSON());
return Response(repl::OpTime());
}
@@ -180,6 +185,9 @@ public:
const auto& cmd = request();
+ tenant_migration_util::protocolCompatibilityCheck(cmd.getProtocol(),
+ cmd.getTenantId().toString());
+
opCtx->setAlwaysInterruptAtStepDownOrUp();
auto recipientService =
repl::PrimaryOnlyServiceRegistry::get(opCtx->getServiceContext())
@@ -195,7 +203,8 @@ public:
cmd.getDonorConnectionString().toString(),
cmd.getTenantId().toString(),
kUnusedStartMigrationTimestamp,
- cmd.getReadPreference());
+ cmd.getReadPreference(),
+ cmd.getProtocol());
if (!repl::tenantMigrationDisableX509Auth) {
uassert(ErrorCodes::InvalidOptions,
str::stream() << "'" << Request::kRecipientCertificateForDonorFieldName
diff --git a/src/mongo/db/commands/tenant_migration_recipient_cmds.idl b/src/mongo/db/commands/tenant_migration_recipient_cmds.idl
index 6a4b44c9752..60ed03fa4de 100644
--- a/src/mongo/db/commands/tenant_migration_recipient_cmds.idl
+++ b/src/mongo/db/commands/tenant_migration_recipient_cmds.idl
@@ -36,6 +36,7 @@ global:
imports:
- "mongo/client/read_preference_setting.idl"
- "mongo/db/repl/tenant_migration_pem_payload.idl"
+ - "mongo/db/serverless/serverless_types.idl"
- "mongo/idl/basic_types.idl"
- "mongo/s/sharding_types.idl"
- "mongo/db/repl/replication_types.idl"
@@ -68,6 +69,7 @@ structs:
The prefix from which the migrating database will be matched. The prefixes 'admin',
'local', 'config', the empty string, are not allowed.
type: string
+ default: '""'
validator:
callback: "tenant_migration_util::validateDatabasePrefix"
readPreference:
@@ -81,6 +83,10 @@ structs:
type: TenantMigrationPEMPayload
# TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
optional: true
+ protocol:
+ description: "Which migration protocol to use."
+ type: MigrationProtocol
+ default: kMultitenantMigrations
commands:
recipientSyncData:
diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript
index 2a35874c14b..adb0d690fc7 100644
--- a/src/mongo/db/repl/SConscript
+++ b/src/mongo/db/repl/SConscript
@@ -1277,6 +1277,7 @@ env.Library(
'$BUILD_DIR/mongo/client/connection_string',
'$BUILD_DIR/mongo/client/read_preference',
'$BUILD_DIR/mongo/db/commands/mongod_fcv',
+ '$BUILD_DIR/mongo/db/serverless/serverless_types_idl',
'$BUILD_DIR/mongo/idl/idl_parser',
'$BUILD_DIR/mongo/util/net/ssl_manager',
'optime',
diff --git a/src/mongo/db/repl/tenant_migration_donor_service.cpp b/src/mongo/db/repl/tenant_migration_donor_service.cpp
index b029481101f..6b93c558456 100644
--- a/src/mongo/db/repl/tenant_migration_donor_service.cpp
+++ b/src/mongo/db/repl/tenant_migration_donor_service.cpp
@@ -235,10 +235,11 @@ TenantMigrationDonorService::Instance::Instance(ServiceContext* const serviceCon
_serviceContext(serviceContext),
_donorService(donorService),
_stateDoc(tenant_migration_access_blocker::parseDonorStateDocument(initialState)),
- _instanceName(kServiceName + "-" + _stateDoc.getTenantId()),
+ _instanceName(kServiceName + "-" + _stateDoc.getId().toString()),
_recipientUri(
uassertStatusOK(MongoURI::parse(_stateDoc.getRecipientConnectionString().toString()))),
_tenantId(_stateDoc.getTenantId()),
+ _protocol(_stateDoc.getProtocol()),
_recipientConnectionString(_stateDoc.getRecipientConnectionString()),
_readPreference(_stateDoc.getReadPreference()),
_migrationUuid(_stateDoc.getId()),
@@ -246,6 +247,7 @@ TenantMigrationDonorService::Instance::Instance(ServiceContext* const serviceCon
_recipientCertificateForDonor(_stateDoc.getRecipientCertificateForDonor()),
_sslMode(repl::tenantMigrationDisableX509Auth ? transport::kGlobalSSLMode
: transport::kEnableSSL) {
+
_recipientCmdExecutor = _makeRecipientCmdExecutor();
_recipientCmdExecutor->startup();
@@ -384,7 +386,7 @@ Status TenantMigrationDonorService::Instance::checkIfOptionsConflict(
stdx::lock_guard<Latch> lg(_mutex);
invariant(stateDoc.getId() == _migrationUuid);
- if (stateDoc.getTenantId() == _tenantId &&
+ if (stateDoc.getProtocol() == _protocol && stateDoc.getTenantId() == _tenantId &&
stateDoc.getRecipientConnectionString() == _recipientConnectionString &&
stateDoc.getReadPreference().equals(_readPreference) &&
stateDoc.getDonorCertificateForRecipient() == _donorCertificateForRecipient &&
@@ -716,8 +718,11 @@ ExecutorFuture<void> TenantMigrationDonorService::Instance::_sendRecipientSyncDa
request.setDbName(NamespaceString::kAdminDb);
MigrationRecipientCommonData commonData(
- _migrationUuid, donorConnString.toString(), _tenantId, _readPreference);
+ _migrationUuid, donorConnString.toString(), _readPreference);
commonData.setRecipientCertificateForDonor(_recipientCertificateForDonor);
+ commonData.setProtocol(_protocol);
+ // TODO: Pass tenantId only for 'kMultitenantMigrations' protocol.
+ commonData.setTenantId(_tenantId);
request.setMigrationRecipientCommonData(commonData);
stdx::lock_guard<Latch> lg(_mutex);
@@ -743,8 +748,11 @@ ExecutorFuture<void> TenantMigrationDonorService::Instance::_sendRecipientForget
request.setDbName(NamespaceString::kAdminDb);
MigrationRecipientCommonData commonData(
- _migrationUuid, donorConnString.toString(), _tenantId, _readPreference);
+ _migrationUuid, donorConnString.toString(), _readPreference);
commonData.setRecipientCertificateForDonor(_recipientCertificateForDonor);
+ commonData.setProtocol(_protocol);
+ // TODO: Pass tenantId only for 'kMultitenantMigrations' protocol.
+ commonData.setTenantId(_tenantId);
request.setMigrationRecipientCommonData(commonData);
return _sendCommandToRecipient(executor, recipientTargeterRS, request.toBSON(BSONObj()), token);
diff --git a/src/mongo/db/repl/tenant_migration_donor_service.h b/src/mongo/db/repl/tenant_migration_donor_service.h
index 5322703b201..5a167edeb81 100644
--- a/src/mongo/db/repl/tenant_migration_donor_service.h
+++ b/src/mongo/db/repl/tenant_migration_donor_service.h
@@ -33,7 +33,6 @@
#include "mongo/client/fetcher.h"
#include "mongo/client/remote_command_targeter_rs.h"
#include "mongo/db/repl/primary_only_service.h"
-#include "mongo/db/repl/repl_server_parameters_gen.h"
#include "mongo/db/repl/tenant_migration_access_blocker_util.h"
#include "mongo/executor/thread_pool_task_executor.h"
#include "mongo/util/cancellation.h"
@@ -139,6 +138,10 @@ public:
return _stateDoc.getTenantId();
}
+ MigrationProtocolEnum getProtocol() const {
+ return _stateDoc.getProtocol();
+ }
+
StringData getRecipientConnectionString() const {
return _stateDoc.getRecipientConnectionString();
}
@@ -330,6 +333,7 @@ public:
// This data is provided in the initial state doc and never changes. We keep copies to
// avoid having to obtain the mutex to access them.
const std::string _tenantId;
+ const MigrationProtocolEnum _protocol;
const std::string _recipientConnectionString;
const ReadPreferenceSetting _readPreference;
const UUID _migrationUuid;
diff --git a/src/mongo/db/repl/tenant_migration_donor_service_test.cpp b/src/mongo/db/repl/tenant_migration_donor_service_test.cpp
index 53588c3c158..94c244e40d9 100644
--- a/src/mongo/db/repl/tenant_migration_donor_service_test.cpp
+++ b/src/mongo/db/repl/tenant_migration_donor_service_test.cpp
@@ -186,7 +186,8 @@ TEST_F(TenantMigrationDonorServiceTest, CheckSettingMigrationStartDate) {
migrationUUID,
"donor-rs/localhost:12345",
ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()),
- "tenantA");
+ "tenantA",
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setDonorCertificateForRecipient(kDonorPEMPayload);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
diff --git a/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp b/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp
index 980f5243591..6d2aa049d85 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp
@@ -116,7 +116,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
"donor-rs0/localhost:12345",
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
activeTenantAStateDoc.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), activeTenantAStateDoc));
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), activeTenantAStateDoc));
@@ -126,7 +127,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
"donor-rs1/localhost:12345",
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
stateDoc1.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto status = insertStateDoc(opCtx.get(), stateDoc1);
ASSERT_EQUALS(ErrorCodes::ConflictingOperationInProgress, status.code());
@@ -137,7 +139,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
"donor-rs0/localhost:12345",
"tenantB",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
stateDoc2.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_THROWS_CODE(
insertStateDoc(opCtx.get(), stateDoc2), DBException, ErrorCodes::DuplicateKey);
@@ -148,7 +151,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
"donor-rs0/localhost:12345",
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
stateDoc3.setRecipientCertificateForDonor(kRecipientPEMPayload);
status = insertStateDoc(opCtx.get(), stateDoc3);
ASSERT_EQUALS(ErrorCodes::ConflictingOperationInProgress, status.code());
@@ -159,7 +163,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
"donor-rs0/localhost:12345",
"tenantB",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
stateDoc4.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), stateDoc4));
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), stateDoc4));
@@ -175,7 +180,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
"donor-rs0/localhost:12345",
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
inactiveTenantAStateDoc.setRecipientCertificateForDonor(kRecipientPEMPayload);
inactiveTenantAStateDoc.setExpireAt(Date_t::now());
ASSERT_OK(insertStateDoc(opCtx.get(), inactiveTenantAStateDoc));
@@ -186,7 +192,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
"donor-rs1/localhost:12345",
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
stateDoc1.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_THROWS_CODE(
insertStateDoc(opCtx.get(), stateDoc1), DBException, ErrorCodes::DuplicateKey);
@@ -197,7 +204,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
"donor-rs0/localhost:12345",
"tenantB",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
stateDoc2.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_THROWS_CODE(
insertStateDoc(opCtx.get(), stateDoc2), DBException, ErrorCodes::DuplicateKey);
@@ -208,7 +216,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
"donor-rs0/localhost:12345",
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
stateDoc3.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), stateDoc3));
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), stateDoc3));
@@ -218,7 +227,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
"donor-rs0/localhost:12345",
"tenantC",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
stateDoc4.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), stateDoc4));
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), stateDoc4));
diff --git a/src/mongo/db/repl/tenant_migration_recipient_service.cpp b/src/mongo/db/repl/tenant_migration_recipient_service.cpp
index 9c23744955e..877fa85568c 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_service.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_service.cpp
@@ -306,6 +306,7 @@ TenantMigrationRecipientService::Instance::Instance(
_stateDoc(TenantMigrationRecipientDocument::parse(IDLParserErrorContext("recipientStateDoc"),
stateDoc)),
_tenantId(_stateDoc.getTenantId().toString()),
+ _protocol(_stateDoc.getProtocol()),
_migrationUuid(_stateDoc.getId()),
_donorConnectionString(_stateDoc.getDonorConnectionString().toString()),
_donorUri(uassertStatusOK(MongoURI::parse(_stateDoc.getDonorConnectionString().toString()))),
@@ -409,7 +410,7 @@ Status TenantMigrationRecipientService::Instance::checkIfOptionsConflict(
stdx::lock_guard<Latch> lg(_mutex);
invariant(stateDoc.getId() == _migrationUuid);
- if (stateDoc.getTenantId() == _tenantId &&
+ if (stateDoc.getProtocol() == _protocol && stateDoc.getTenantId() == _tenantId &&
stateDoc.getDonorConnectionString() == _donorConnectionString &&
stateDoc.getReadPreference().equals(_readPreference) &&
stateDoc.getRecipientCertificateForDonor() == _recipientCertificateForDonor) {
@@ -2487,5 +2488,9 @@ const std::string& TenantMigrationRecipientService::Instance::getTenantId() cons
return _tenantId;
}
+const MigrationProtocolEnum TenantMigrationRecipientService::Instance::getProtocol() const {
+ return _protocol;
+}
+
} // namespace repl
} // namespace mongo
diff --git a/src/mongo/db/repl/tenant_migration_recipient_service.h b/src/mongo/db/repl/tenant_migration_recipient_service.h
index 4fbb25126a7..99ee45ba6d1 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_service.h
+++ b/src/mongo/db/repl/tenant_migration_recipient_service.h
@@ -138,6 +138,11 @@ public:
*/
const std::string& getTenantId() const;
+ /*
+ * Returns the migration protocol.
+ */
+ const MigrationProtocolEnum getProtocol() const;
+
/**
* To be called on the instance returned by PrimaryOnlyService::getOrCreate(). Returns an
* error if the options this Instance was created with are incompatible with the options
@@ -572,6 +577,7 @@ public:
// This data is provided in the initial state doc and never changes. We keep copies to
// avoid having to obtain the mutex to access them.
const std::string _tenantId; // (R)
+ const MigrationProtocolEnum _protocol; // (R)
const UUID _migrationUuid; // (R)
const std::string _donorConnectionString; // (R)
const MongoURI _donorUri; // (R)
diff --git a/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp b/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
index b30dee191a0..4eca8a03fb0 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
@@ -479,7 +479,8 @@ TEST_F(TenantMigrationRecipientServiceTest, BasicTenantMigrationRecipientService
"donor-rs/localhost:12345",
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -504,7 +505,8 @@ TEST_F(TenantMigrationRecipientServiceTest, InstanceReportsErrorOnFailureWhilePe
"donor-rs/localhost:12345",
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -539,7 +541,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_P
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -590,7 +593,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_S
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::SecondaryOnly));
+ ReadPreferenceSetting(ReadPreference::SecondaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -642,7 +646,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
@@ -700,7 +705,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
@@ -772,7 +778,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::Nearest));
+ ReadPreferenceSetting(ReadPreference::Nearest),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
@@ -833,7 +840,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
+ ReadPreferenceSetting(ReadPreference::PrimaryPreferred),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
@@ -902,7 +910,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
+ ReadPreferenceSetting(ReadPreference::PrimaryPreferred),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
@@ -974,7 +983,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::SecondaryOnly));
+ ReadPreferenceSetting(ReadPreference::SecondaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
@@ -1035,7 +1045,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::SecondaryPreferred));
+ ReadPreferenceSetting(ReadPreference::SecondaryPreferred),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
@@ -1114,7 +1125,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
+ ReadPreferenceSetting(ReadPreference::PrimaryPreferred),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
initialStateDocument.setStartApplyingDonorOpTime(startApplyingOpTime);
@@ -1172,7 +1184,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
startMigrationDonorTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
+ ReadPreferenceSetting(ReadPreference::PrimaryPreferred),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -1233,7 +1246,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_P
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
+ ReadPreferenceSetting(ReadPreference::PrimaryPreferred),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -1277,7 +1291,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_B
"broken,connect,string,no,set,name",
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -1299,7 +1314,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
"localhost:12345",
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -1325,7 +1341,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientGetStartOpTi
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -1364,7 +1381,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -1409,7 +1427,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientGetStartOpTi
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -1456,7 +1475,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -1492,7 +1512,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance. Fail to populate the remote oplog mock.
@@ -1527,7 +1548,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientStartOplogFe
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto opCtx = makeOperationContext();
@@ -1582,7 +1604,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientStartsCloner
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto opCtx = makeOperationContext();
@@ -1637,7 +1660,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherFailsDuringOplogApplicat
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
@@ -1693,7 +1717,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherResumesFromTopOfOplogBuf
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
@@ -1800,7 +1825,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherNoDocInBufferToResumeFro
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
@@ -1909,7 +1935,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierResumesFromLastNoOpOplog
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
@@ -2034,7 +2061,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
@@ -2207,7 +2235,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierResumesFromStartDonorApp
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
@@ -2352,7 +2381,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
@@ -2458,7 +2488,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierFails) {
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
@@ -2524,7 +2555,8 @@ TEST_F(TenantMigrationRecipientServiceTest, StoppingApplierAllowsCompletion) {
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
@@ -2579,7 +2611,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientAddResumeTok
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
@@ -2682,7 +2715,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_BeforeRun)
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto fp = globalFailPointRegistry().find("pauseBeforeRunTenantMigrationRecipientInstance");
@@ -2720,7 +2754,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_FailToIniti
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto opCtx = makeOperationContext();
@@ -2754,7 +2789,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_WaitUntilSt
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto fp = globalFailPointRegistry().find("pauseAfterRunTenantMigrationRecipientInstance");
@@ -2838,7 +2874,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterStartO
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -2901,7 +2938,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterConsis
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
@@ -2989,7 +3027,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterFail)
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
@@ -3071,7 +3110,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_FailToMarkG
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -3123,7 +3163,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientServiceRecor
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -3158,7 +3199,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Add an FCV value as if it was from a previous attempt.
@@ -3197,7 +3239,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Add an FCV value as if it was from a previous attempt, making sure we set a different
@@ -3244,7 +3287,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -3279,7 +3323,8 @@ TEST_F(TenantMigrationRecipientServiceTest, WaitUntilMigrationReachesReturnAfter
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
@@ -3339,7 +3384,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientReceivesRetriableFetcherErr
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -3403,7 +3449,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientReceivesNonRetriableFetcher
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -3462,7 +3509,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientWillNotRetryOnExternalInter
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -3520,7 +3568,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientReceivesRetriableClonerErro
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -3592,7 +3641,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientReceivesNonRetriableClonerE
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
@@ -3646,7 +3696,8 @@ TEST_F(TenantMigrationRecipientServiceTest, IncrementNumRestartsDueToRecipientFa
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Starting a migration where the state is not 'kUninitialized' indicates that we are restarting
// from failover.
@@ -3697,7 +3748,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
replSet.getConnectionString(),
"tenantA",
kDefaultStartMigrationTimestamp,
- ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ MigrationProtocolEnum::kMultitenantMigrations);
initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Starting a migration where the state is not 'kUninitialized' indicates that we are restarting
// from failover.
diff --git a/src/mongo/db/repl/tenant_migration_state_machine.idl b/src/mongo/db/repl/tenant_migration_state_machine.idl
index f8a6291d5a6..fb0644bfeaf 100644
--- a/src/mongo/db/repl/tenant_migration_state_machine.idl
+++ b/src/mongo/db/repl/tenant_migration_state_machine.idl
@@ -36,6 +36,7 @@ imports:
- "mongo/client/read_preference_setting.idl"
- "mongo/db/repl/replication_types.idl"
- "mongo/db/repl/tenant_migration_pem_payload.idl"
+ - "mongo/db/serverless/serverless_types.idl"
- "mongo/idl/basic_types.idl"
enums:
@@ -137,6 +138,9 @@ structs:
description: >-
The wall-clock time at which the migration has started.
optional: true
+ protocol:
+ description: "Which migration protocol to use."
+ type: MigrationProtocol
tenantMigrationRecipientDocument:
description: "Represents an in-progress tenant migration on the migration recipient."
@@ -171,6 +175,9 @@ structs:
description: >-
The read preference setting that the recipient will use to determine
which node in the donor replica set to clone from.
+ protocol:
+ description: "Which migration protocol to use."
+ type: MigrationProtocol
state:
type: TenantMigrationRecipientState
description: "The state of the tenant migration."
diff --git a/src/mongo/db/repl/tenant_migration_util.h b/src/mongo/db/repl/tenant_migration_util.h
index 18d303d6984..29fef1c44fe 100644
--- a/src/mongo/db/repl/tenant_migration_util.h
+++ b/src/mongo/db/repl/tenant_migration_util.h
@@ -38,7 +38,9 @@
#include "mongo/db/catalog/database.h"
#include "mongo/db/keys_collection_document_gen.h"
#include "mongo/db/pipeline/pipeline.h"
+#include "mongo/db/repl/repl_server_parameters_gen.h"
#include "mongo/db/repl/replication_coordinator.h"
+#include "mongo/db/serverless/serverless_types_gen.h"
#include "mongo/executor/scoped_task_executor.h"
#include "mongo/util/net/ssl_util.h"
#include "mongo/util/str.h"
@@ -128,6 +130,34 @@ inline Status validatePrivateKeyPEMPayload(const StringData& payload) {
#endif
}
+inline void protocolCompatibilityCheck(const MigrationProtocolEnum protocol,
+ const std::string& tenantId) {
+ switch (protocol) {
+ case MigrationProtocolEnum::kShardMerge: {
+ uassert(ErrorCodes::IllegalOperation,
+ str::stream() << "protocol '" << MigrationProtocol_serializer(protocol)
+ << "' not supported",
+ repl::feature_flags::gShardMerge.isEnabled(
+ serverGlobalParams.featureCompatibility));
+
+ // TODO: SERVER-59495 Add a check to ensure tenantId is not provided for 'Merge'
+ // protocol.
+ break;
+ }
+ case MigrationProtocolEnum::kMultitenantMigrations: {
+ uassert(ErrorCodes::InvalidOptions,
+ str::stream() << "'tenantId' is required for protocol '"
+ << MigrationProtocol_serializer(protocol) << "'",
+ !tenantId.empty());
+
+
+ break;
+ }
+ default:
+ MONGO_UNREACHABLE;
+ }
+}
+
/*
* 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/serverless/SConscript b/src/mongo/db/serverless/SConscript
index 0f3259271f6..b2ebb792ae7 100644
--- a/src/mongo/db/serverless/SConscript
+++ b/src/mongo/db/serverless/SConscript
@@ -4,6 +4,18 @@ Import("env")
env = env.Clone()
env.Library(
+ target='serverless_types_idl',
+ source=[
+ 'serverless_types.idl',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/idl/basic_types',
+ '$BUILD_DIR/mongo/idl/idl_parser'
+ ],
+)
+
+env.Library(
target='tenant_split_state_machine',
source=[
'tenant_split_state_machine.idl',
diff --git a/src/mongo/db/serverless/serverless_types.idl b/src/mongo/db/serverless/serverless_types.idl
new file mode 100644
index 00000000000..e906e7a52c3
--- /dev/null
+++ b/src/mongo/db/serverless/serverless_types.idl
@@ -0,0 +1,40 @@
+# Copyright (C) 2021-present MongoDB, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the Server Side Public License, version 1,
+# as published by MongoDB, Inc.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Server Side Public License for more details.
+#
+# You should have received a copy of the Server Side Public License
+# along with this program. If not, see
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# As a special exception, the copyright holders give permission to link the
+# code of portions of this program with the OpenSSL library under certain
+# conditions as described in each individual source file and distribute
+# linked combinations including the program with the OpenSSL library. You
+# must comply with the Server Side Public License in all respects for
+# all of the code used other than as permitted herein. If you modify file(s)
+# with this exception, you may extend this exception to your version of the
+# file(s), but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version. If you delete this
+# exception statement from all source files in the program, then also delete
+# it in the license file.
+#
+global:
+ cpp_namespace: "mongo"
+
+imports:
+ - "mongo/idl/basic_types.idl"
+
+enums:
+ MigrationProtocol:
+ description: "Determines which tenant migration protocol to use."
+ type: string
+ values:
+ kMultitenantMigrations: "multitenant migrations"
+ kShardMerge: "shard merge"