diff options
-rw-r--r-- | src/mongo/db/commands.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/commands.h | 6 | ||||
-rw-r--r-- | src/mongo/db/s/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/s/config/configsvr_move_primary_command.cpp | 285 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_move_primary_cmd.cpp | 247 | ||||
-rw-r--r-- | src/mongo/s/request_types/move_primary.idl | 11 |
6 files changed, 313 insertions, 251 deletions
diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index ebf796282e6..ce98a97f97f 100644 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -75,6 +75,20 @@ ExportedServerParameter<bool, ServerParameterType::kStartupOnly> testCommandsPar Command::~Command() = default; +BSONObj Command::appendPassthroughFields(const BSONObj& cmdObjWithPassthroughFields, + const BSONObj& request) { + BSONObjBuilder b; + b.appendElements(request); + for (const auto& elem : cmdObjWithPassthroughFields) { + const auto name = elem.fieldNameStringData(); + // $db is one of the generic arguments, but is implicitly contained in request + if (Command::isGenericArgument(name) && !request.hasField(name) && name != "$db") { + b.append(elem); + } + } + return b.obj(); +} + string Command::parseNsFullyQualified(const string& dbname, const BSONObj& cmdObj) { BSONElement first = cmdObj.firstElement(); uassert(ErrorCodes::BadValue, diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h index 6ad9e536b47..13db6740e6b 100644 --- a/src/mongo/db/commands.h +++ b/src/mongo/db/commands.h @@ -488,6 +488,12 @@ public: const BSONObj& cmdObj); /** + * Appends passthrough fields from a cmdObj to a given request. + */ + static BSONObj appendPassthroughFields(const BSONObj& cmdObjWithPassthroughFields, + const BSONObj& request); + + /** * Returns true if the provided argument is one that is handled by the command processing layer * and should generally be ignored by individual command implementations. In particular, * commands that fail on unrecognized arguments must not fail for any of these. diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript index 841865d36a1..94d4ce8b128 100644 --- a/src/mongo/db/s/SConscript +++ b/src/mongo/db/s/SConscript @@ -202,6 +202,7 @@ env.Library( '$BUILD_DIR/mongo/db/dbhelpers', '$BUILD_DIR/mongo/db/index_d', '$BUILD_DIR/mongo/db/repl/repl_coordinator_global', + '$BUILD_DIR/mongo/s/commands/shared_cluster_commands', '$BUILD_DIR/mongo/s/sharding_request_types', 'balancer', 'collection_metadata', diff --git a/src/mongo/db/s/config/configsvr_move_primary_command.cpp b/src/mongo/db/s/config/configsvr_move_primary_command.cpp index b186b811fae..043db353644 100644 --- a/src/mongo/db/s/config/configsvr_move_primary_command.cpp +++ b/src/mongo/db/s/config/configsvr_move_primary_command.cpp @@ -17,40 +17,43 @@ * 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 GNU Affero General 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. + * must comply with the GNU Affero General 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. */ #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kSharding #include "mongo/platform/basic.h" -#include "mongo/db/audit.h" +#include "mongo/client/connpool.h" +#include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_type.h" +#include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authorization_session.h" -#include "mongo/db/auth/privilege.h" +#include "mongo/db/catalog/document_validation.h" +#include "mongo/db/client.h" #include "mongo/db/commands.h" -#include "mongo/db/namespace_string.h" -#include "mongo/db/repl/repl_set_config.h" -#include "mongo/db/repl/replication_coordinator.h" -#include "mongo/s/catalog/sharding_catalog_manager.h" -#include "mongo/s/catalog/type_shard.h" +#include "mongo/db/operation_context.h" +#include "mongo/s/catalog/sharding_catalog_client.h" +#include "mongo/s/catalog/type_database.h" +#include "mongo/s/catalog_cache.h" +#include "mongo/s/client/shard_registry.h" +#include "mongo/s/commands/cluster_commands_helpers.h" #include "mongo/s/grid.h" #include "mongo/s/request_types/move_primary_gen.h" #include "mongo/util/log.h" -#include "mongo/util/mongoutils/str.h" +#include "mongo/util/scopeguard.h" namespace mongo { -namespace { using std::string; -const long long kMaxSizeMBDefault = 0; +namespace { /** * Internal sharding command run on config servers to change a database's primary shard. @@ -59,38 +62,48 @@ class ConfigSvrMovePrimaryCommand : public Command { public: ConfigSvrMovePrimaryCommand() : Command("_configsvrMovePrimary") {} - void help(std::stringstream& help) const override { - help << "Internal command, which is exported by the sharding config server. Do not call " - "directly. Reassigns the primary shard of a database."; - } - - bool slaveOk() const override { + virtual bool slaveOk() const { return false; } - bool adminOnly() const override { + virtual bool adminOnly() const { return true; } - bool supportsWriteConcern(const BSONObj& cmd) const override { + virtual bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } - Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) override { + virtual void help(std::stringstream& help) const override { + help << "Internal command, which is exported by the sharding config server. Do not call " + "directly. Reassigns the primary shard of a database."; + } + + virtual Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) override { if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource( ResourcePattern::forClusterResource(), ActionType::internal)) { return Status(ErrorCodes::Unauthorized, "Unauthorized"); } + return Status::OK(); } + virtual std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const { + const auto nsElt = cmdObj.firstElement(); + uassert(ErrorCodes::InvalidNamespace, + "'movePrimary' must be of type String", + nsElt.type() == BSONType::String); + return nsElt.str(); + } + bool run(OperationContext* opCtx, - const std::string& unusedDbName, + const std::string& dbname_unused, const BSONObj& cmdObj, std::string& errmsg, - BSONObjBuilder& result) override { + BSONObjBuilder& result) { + if (serverGlobalParams.clusterRole != ClusterRole::ConfigServer) { return appendCommandStatus( result, @@ -98,8 +111,220 @@ public: "_configsvrMovePrimary can only be run on config servers")); } + auto movePrimaryRequest = + MovePrimary::parse(IDLParserErrorContext("ConfigSvrMovePrimary"), cmdObj); + const string dbname = parseNs("", cmdObj); + + uassert( + ErrorCodes::InvalidNamespace, + str::stream() << "invalid db name specified: " << dbname, + NamespaceString::validDBName(dbname, NamespaceString::DollarInDbNameBehavior::Allow)); + + if (dbname == NamespaceString::kAdminDb || dbname == NamespaceString::kConfigDb || + dbname == NamespaceString::kLocalDb) { + return appendCommandStatus( + result, + {ErrorCodes::InvalidOptions, + str::stream() << "Can't move primary for " << dbname << " database"}); + } + + auto const catalogClient = Grid::get(opCtx)->catalogClient(opCtx); + auto const catalogCache = Grid::get(opCtx)->catalogCache(); + auto const shardRegistry = Grid::get(opCtx)->shardRegistry(); + + auto dbType = uassertStatusOK(catalogClient->getDatabase(opCtx, dbname)).value; + + const std::string to = movePrimaryRequest.getTo().toString(); + + if (to.empty()) { + return appendCommandStatus( + result, + {ErrorCodes::InvalidOptions, + str::stream() << "you have to specify where you want to move it"}); + } + + const auto fromShard = uassertStatusOK(shardRegistry->getShard(opCtx, dbType.getPrimary())); + + const auto toShard = [&]() { + auto toShardStatus = shardRegistry->getShard(opCtx, to); + if (!toShardStatus.isOK()) { + const std::string msg( + str::stream() << "Could not move database '" << dbname << "' to shard '" << to + << "' due to " + << toShardStatus.getStatus().reason()); + log() << msg; + uasserted(toShardStatus.getStatus().code(), msg); + } + + return toShardStatus.getValue(); + }(); + + uassert(ErrorCodes::IllegalOperation, + "it is already the primary", + fromShard->getId() != toShard->getId()); + + log() << "Moving " << dbname << " primary from: " << fromShard->toString() + << " to: " << toShard->toString(); + + const std::string whyMessage(str::stream() << "Moving primary shard of " << dbname); + auto scopedDistLock = uassertStatusOK(catalogClient->getDistLockManager()->lock( + opCtx, dbname + "-movePrimary", whyMessage, DistLockManager::kDefaultLockTimeout)); + + const auto shardedColls = getAllShardedCollectionsForDb(opCtx, dbname); + + // Record start in changelog + uassertStatusOK(catalogClient->logChange( + opCtx, + "movePrimary.start", + dbname, + _buildMoveLogEntry(dbname, fromShard->toString(), toShard->toString(), shardedColls), + ShardingCatalogClient::kMajorityWriteConcern)); + + ScopedDbConnection toconn(toShard->getConnString()); + ON_BLOCK_EXIT([&toconn] { toconn.done(); }); + + // TODO ERH - we need a clone command which replays operations from clone start to now + // can just use local.oplog.$main + BSONObj cloneRes; + bool hasWCError = false; + + { + BSONArrayBuilder barr; + for (const auto& shardedColl : shardedColls) { + barr.append(shardedColl.ns()); + } + + const bool worked = toconn->runCommand( + dbname, + BSON("clone" << fromShard->getConnString().toString() << "collsToIgnore" + << barr.arr() + << bypassDocumentValidationCommandOption() + << true + << "writeConcern" + << opCtx->getWriteConcern().toBSON()), + cloneRes); + + if (!worked) { + log() << "clone failed" << redact(cloneRes); + return appendCommandStatus( + result, {ErrorCodes::OperationFailed, str::stream() << "clone failed"}); + } + + if (auto wcErrorElem = cloneRes["writeConcernError"]) { + appendWriteConcernErrorToCmdResponse(toShard->getId(), wcErrorElem, result); + hasWCError = true; + } + } + + // Update the new primary in the config server metadata + { + auto dbt = uassertStatusOK(catalogClient->getDatabase(opCtx, dbname)).value; + dbt.setPrimary(toShard->getId()); + uassertStatusOK(catalogClient->updateDatabase(opCtx, dbname, dbt)); + } + + // Ensure the next attempt to retrieve the database or any of its collections will do a full + // reload + catalogCache->purgeDatabase(dbname); + + const string oldPrimary = fromShard->getConnString().toString(); + + ScopedDbConnection fromconn(fromShard->getConnString()); + ON_BLOCK_EXIT([&fromconn] { fromconn.done(); }); + + if (shardedColls.empty()) { + // TODO: Collections can be created in the meantime, and we should handle in the future. + log() << "movePrimary dropping database on " << oldPrimary + << ", no sharded collections in " << dbname; + + try { + BSONObj dropDBInfo; + fromconn->dropDatabase(dbname.c_str(), opCtx->getWriteConcern(), &dropDBInfo); + if (!hasWCError) { + if (auto wcErrorElem = dropDBInfo["writeConcernError"]) { + appendWriteConcernErrorToCmdResponse( + fromShard->getId(), wcErrorElem, result); + hasWCError = true; + } + } + } catch (DBException& e) { + e.addContext(str::stream() << "movePrimary could not drop the database " << dbname + << " on " + << oldPrimary); + throw; + } + + } else if (cloneRes["clonedColls"].type() != Array) { + // Legacy behavior from old mongod with sharded collections, *do not* delete + // database, but inform user they can drop manually (or ignore). + warning() << "movePrimary legacy mongod behavior detected. " + << "User must manually remove unsharded collections in database " << dbname + << " on " << oldPrimary; + } else { + // We moved some unsharded collections, but not all + BSONObjIterator it(cloneRes["clonedColls"].Obj()); + + while (it.more()) { + BSONElement el = it.next(); + if (el.type() == String) { + try { + log() << "movePrimary dropping cloned collection " << el.String() << " on " + << oldPrimary; + BSONObj dropCollInfo; + fromconn->dropCollection( + el.String(), opCtx->getWriteConcern(), &dropCollInfo); + if (!hasWCError) { + if (auto wcErrorElem = dropCollInfo["writeConcernError"]) { + appendWriteConcernErrorToCmdResponse( + fromShard->getId(), wcErrorElem, result); + hasWCError = true; + } + } + + } catch (DBException& e) { + e.addContext(str::stream() + << "movePrimary could not drop the cloned collection " + << el.String() + << " on " + << oldPrimary); + throw; + } + } + } + } + + result << "primary" << toShard->toString(); + + // Record finish in changelog + uassertStatusOK(catalogClient->logChange( + opCtx, + "movePrimary", + dbname, + _buildMoveLogEntry(dbname, oldPrimary, toShard->toString(), shardedColls), + ShardingCatalogClient::kMajorityWriteConcern)); + return true; } + +private: + static BSONObj _buildMoveLogEntry(const std::string& db, + const std::string& from, + const std::string& to, + const std::vector<NamespaceString>& shardedColls) { + BSONObjBuilder details; + details.append("database", db); + details.append("from", from); + details.append("to", to); + + BSONArrayBuilder collB(details.subarrayStart("shardedCollections")); + for (const auto& shardedColl : shardedColls) { + collB.append(shardedColl.ns()); + } + collB.done(); + + return details.obj(); + } + } configsvrMovePrimaryCmd; } // namespace diff --git a/src/mongo/s/commands/cluster_move_primary_cmd.cpp b/src/mongo/s/commands/cluster_move_primary_cmd.cpp index 2e0f977753f..4c47ad42982 100644 --- a/src/mongo/s/commands/cluster_move_primary_cmd.cpp +++ b/src/mongo/s/commands/cluster_move_primary_cmd.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2015 MongoDB Inc. + * Copyright (C) 2017 MongoDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, @@ -30,32 +30,25 @@ #include "mongo/platform/basic.h" -#include <set> - -#include "mongo/client/connpool.h" -#include "mongo/db/auth/action_set.h" +#include "mongo/bson/util/bson_extract.h" +#include "mongo/db/audit.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authorization_session.h" -#include "mongo/db/catalog/document_validation.h" -#include "mongo/db/client.h" -#include "mongo/db/client.h" #include "mongo/db/commands.h" -#include "mongo/db/operation_context.h" -#include "mongo/rpc/get_status_from_command_result.h" +#include "mongo/rpc/write_concern_error_detail.h" #include "mongo/s/catalog/sharding_catalog_client.h" -#include "mongo/s/catalog/type_database.h" +#include "mongo/s/catalog/type_shard.h" #include "mongo/s/catalog_cache.h" #include "mongo/s/client/shard_registry.h" #include "mongo/s/commands/cluster_commands_helpers.h" #include "mongo/s/grid.h" #include "mongo/s/request_types/move_primary_gen.h" #include "mongo/util/log.h" +#include "mongo/util/scopeguard.h" namespace mongo { -using std::shared_ptr; -using std::set; using std::string; namespace { @@ -72,7 +65,6 @@ public: return true; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -101,229 +93,42 @@ public: } virtual bool run(OperationContext* opCtx, - const std::string& dbname_unused, + const std::string& dbname, const BSONObj& cmdObj, std::string& errmsg, BSONObjBuilder& result) { auto movePrimaryRequest = MovePrimary::parse(IDLParserErrorContext("MovePrimary"), cmdObj); - const string dbname = parseNs("", cmdObj); - - uassert( - ErrorCodes::InvalidNamespace, - str::stream() << "invalid db name specified: " << dbname, - NamespaceString::validDBName(dbname, NamespaceString::DollarInDbNameBehavior::Allow)); - - if (dbname == NamespaceString::kAdminDb || dbname == NamespaceString::kConfigDb || - dbname == NamespaceString::kLocalDb) { - errmsg = "can't move primary for " + dbname + " database"; - return false; - } - - auto const catalogClient = Grid::get(opCtx)->catalogClient(opCtx); - auto const catalogCache = Grid::get(opCtx)->catalogCache(); - auto const shardRegistry = Grid::get(opCtx)->shardRegistry(); - - // Flush all cached information. This can't be perfect, but it's better than nothing. - catalogCache->purgeDatabase(dbname); - - auto dbInfo = uassertStatusOK(catalogCache->getDatabase(opCtx, dbname)); - - const std::string to = movePrimaryRequest.getTo().toString(); - - if (to.empty()) { - errmsg = "you have to specify where you want to move it"; - return false; - } - - const auto fromShard = uassertStatusOK(shardRegistry->getShard(opCtx, dbInfo.primaryId())); - - const auto toShard = [&]() { - auto toShardStatus = shardRegistry->getShard(opCtx, to); - if (!toShardStatus.isOK()) { - const std::string msg( - str::stream() << "Could not move database '" << dbname << "' to shard '" << to - << "' due to " - << toShardStatus.getStatus().reason()); - log() << msg; - uasserted(toShardStatus.getStatus().code(), msg); - } - - return toShardStatus.getValue(); - }(); - - uassert(ErrorCodes::IllegalOperation, - "it is already the primary", - fromShard->getId() != toShard->getId()); - - log() << "Moving " << dbname << " primary from: " << fromShard->toString() - << " to: " << toShard->toString(); - - const std::string whyMessage(str::stream() << "Moving primary shard of " << dbname); - auto scopedDistLock = uassertStatusOK(catalogClient->getDistLockManager()->lock( - opCtx, dbname + "-movePrimary", whyMessage, DistLockManager::kDefaultLockTimeout)); - - const auto shardedColls = getAllShardedCollectionsForDb(opCtx, dbname); - - // Record start in changelog - catalogClient - ->logChange(opCtx, - "movePrimary.start", - dbname, - _buildMoveLogEntry( - dbname, fromShard->toString(), toShard->toString(), shardedColls), - ShardingCatalogClient::kMajorityWriteConcern) - .transitional_ignore(); - - ScopedDbConnection toconn(toShard->getConnString()); + const string db = parseNs("", cmdObj); + const NamespaceString nss(db); - // TODO ERH - we need a clone command which replays operations from clone start to now - // can just use local.oplog.$main - BSONObj cloneRes; - bool hasWCError = false; + ConfigsvrMovePrimary configMovePrimaryRequest; + configMovePrimaryRequest.set_configsvrMovePrimary(nss); + configMovePrimaryRequest.setTo(movePrimaryRequest.getTo()); - { - BSONArrayBuilder barr; - for (const auto& shardedColl : shardedColls) { - barr.append(shardedColl.ns()); - } + // Invalidate the routing table cache entry for this database so that we reload the + // collection the next time it's accessed, even if we receive a failure, e.g. NetworkError. + ON_BLOCK_EXIT([opCtx, db] { Grid::get(opCtx)->catalogCache()->purgeDatabase(db); }); - const bool worked = toconn->runCommand( - dbname, - BSON("clone" << fromShard->getConnString().toString() << "collsToIgnore" - << barr.arr() - << bypassDocumentValidationCommandOption() - << true - << "writeConcern" - << opCtx->getWriteConcern().toBSON()), - cloneRes); - toconn.done(); + auto configShard = Grid::get(opCtx)->shardRegistry()->getConfigShard(); - if (!worked) { - log() << "clone failed" << redact(cloneRes); - errmsg = "clone failed"; - return false; - } + auto cmdResponseStatus = uassertStatusOK(configShard->runCommandWithFixedRetryAttempts( + opCtx, + ReadPreferenceSetting(ReadPreference::PrimaryOnly), + "admin", + Command::appendPassthroughFields(cmdObj, configMovePrimaryRequest.toBSON()), + Shard::RetryPolicy::kIdempotent)); + uassertStatusOK(cmdResponseStatus.commandStatus); - if (auto wcErrorElem = cloneRes["writeConcernError"]) { - appendWriteConcernErrorToCmdResponse(toShard->getId(), wcErrorElem, result); - hasWCError = true; - } + if (!cmdResponseStatus.writeConcernStatus.isOK()) { + appendWriteConcernErrorToCmdResponse( + configShard->getId(), cmdResponseStatus.response["writeConcernError"], result); } - // Update the new primary in the config server metadata - { - auto dbt = uassertStatusOK(catalogClient->getDatabase(opCtx, dbname)).value; - dbt.setPrimary(toShard->getId()); - - uassertStatusOK(catalogClient->updateDatabase(opCtx, dbname, dbt)); - } - - // Ensure the next attempt to retrieve the database or any of its collections will do a full - // reload - catalogCache->purgeDatabase(dbname); - - const string oldPrimary = fromShard->getConnString().toString(); - - ScopedDbConnection fromconn(fromShard->getConnString()); - - if (shardedColls.empty()) { - // TODO: Collections can be created in the meantime, and we should handle in the future. - log() << "movePrimary dropping database on " << oldPrimary - << ", no sharded collections in " << dbname; - - try { - BSONObj dropDBInfo; - fromconn->dropDatabase(dbname.c_str(), opCtx->getWriteConcern(), &dropDBInfo); - if (!hasWCError) { - if (auto wcErrorElem = dropDBInfo["writeConcernError"]) { - appendWriteConcernErrorToCmdResponse( - fromShard->getId(), wcErrorElem, result); - hasWCError = true; - } - } - } catch (DBException& e) { - e.addContext(str::stream() << "movePrimary could not drop the database " << dbname - << " on " - << oldPrimary); - throw; - } - - } else if (cloneRes["clonedColls"].type() != Array) { - // Legacy behavior from old mongod with sharded collections, *do not* delete - // database, but inform user they can drop manually (or ignore). - warning() << "movePrimary legacy mongod behavior detected. " - << "User must manually remove unsharded collections in database " << dbname - << " on " << oldPrimary; - } else { - // We moved some unsharded collections, but not all - BSONObjIterator it(cloneRes["clonedColls"].Obj()); - - while (it.more()) { - BSONElement el = it.next(); - if (el.type() == String) { - try { - log() << "movePrimary dropping cloned collection " << el.String() << " on " - << oldPrimary; - BSONObj dropCollInfo; - fromconn->dropCollection( - el.String(), opCtx->getWriteConcern(), &dropCollInfo); - if (!hasWCError) { - if (auto wcErrorElem = dropCollInfo["writeConcernError"]) { - appendWriteConcernErrorToCmdResponse( - fromShard->getId(), wcErrorElem, result); - hasWCError = true; - } - } - - } catch (DBException& e) { - e.addContext(str::stream() - << "movePrimary could not drop the cloned collection " - << el.String() - << " on " - << oldPrimary); - throw; - } - } - } - } - - fromconn.done(); - - result << "primary" << toShard->toString(); - - // Record finish in changelog - catalogClient - ->logChange(opCtx, - "movePrimary", - dbname, - _buildMoveLogEntry(dbname, oldPrimary, toShard->toString(), shardedColls), - ShardingCatalogClient::kMajorityWriteConcern) - .transitional_ignore(); - return true; } -private: - static BSONObj _buildMoveLogEntry(const std::string& db, - const std::string& from, - const std::string& to, - const std::vector<NamespaceString>& shardedColls) { - BSONObjBuilder details; - details.append("database", db); - details.append("from", from); - details.append("to", to); - - BSONArrayBuilder collB(details.subarrayStart("shardedCollections")); - for (const auto& shardedColl : shardedColls) { - collB.append(shardedColl.ns()); - } - collB.done(); - - return details.obj(); - } - } clusterMovePrimaryCmd; } // namespace diff --git a/src/mongo/s/request_types/move_primary.idl b/src/mongo/s/request_types/move_primary.idl index a8909f7fd4b..d4f79660e60 100644 --- a/src/mongo/s/request_types/move_primary.idl +++ b/src/mongo/s/request_types/move_primary.idl @@ -48,3 +48,14 @@ structs: to: type: string description: "The shard serving as the destination for un-sharded collections." + + ConfigsvrMovePrimary: + description: "The internal movePrimary command on the config server" + strict: false + fields: + _configsvrMovePrimary: + type: namespacestring + description: "The namespace of the database whose primary shard is to be reassigned." + to: + type: string + description: "The shard serving as the destination for un-sharded collections."
\ No newline at end of file |