summaryrefslogtreecommitdiff
path: root/src/mongo/s
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2020-06-05 07:58:16 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-06-08 07:38:58 +0000
commit43becb34df823529e205e41137e503feb9f3ee63 (patch)
tree14bc783762dad78cb1ea20fdc729117f0ba0abda /src/mongo/s
parent3a08edc2ed39f7747fa034b449caa569dba72ace (diff)
downloadmongo-43becb34df823529e205e41137e503feb9f3ee63.tar.gz
SERVER-47979 Perform the collation check for `shardCollection` on the shard
.... rather than doing it on the config server, because the stability of the collection cannot be guaranteed.
Diffstat (limited to 'src/mongo/s')
-rw-r--r--src/mongo/s/commands/SConscript11
-rw-r--r--src/mongo/s/commands/cluster_commands.idl (renamed from src/mongo/s/commands/kill_sessions_remote.idl)56
-rw-r--r--src/mongo/s/commands/cluster_list_collections_cmd.cpp227
-rw-r--r--src/mongo/s/commands/cluster_list_indexes_cmd.cpp135
-rw-r--r--src/mongo/s/commands/cluster_multicast.idl50
-rw-r--r--src/mongo/s/commands/cluster_multicast_cmd.cpp (renamed from src/mongo/s/commands/cluster_multicast.cpp)45
-rw-r--r--src/mongo/s/commands/cluster_passthrough_commands.cpp274
-rw-r--r--src/mongo/s/commands/cluster_set_free_monitoring_cmd.cpp (renamed from src/mongo/s/commands/cluster_set_free_monitoring.cpp)0
-rw-r--r--src/mongo/s/commands/cluster_shard_collection_cmd.cpp17
-rw-r--r--src/mongo/s/commands/commands_public.cpp569
-rw-r--r--src/mongo/s/commands/kill_sessions_remote.cpp8
-rw-r--r--src/mongo/s/commands/kill_sessions_remote.h5
-rw-r--r--src/mongo/s/request_types/shard_collection.idl46
13 files changed, 722 insertions, 721 deletions
diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript
index 9f7c310ffef..3db993ea17e 100644
--- a/src/mongo/s/commands/SConscript
+++ b/src/mongo/s/commands/SConscript
@@ -62,15 +62,18 @@ env.Library(
'cluster_kill_op.cpp',
'cluster_killcursors_cmd.cpp',
'cluster_killoperations_cmd.cpp',
+ 'cluster_list_collections_cmd.cpp',
'cluster_list_databases_cmd.cpp',
+ 'cluster_list_indexes_cmd.cpp',
'cluster_list_shards_cmd.cpp',
'cluster_map_reduce_agg.cpp',
'cluster_map_reduce_cmd.cpp',
'cluster_merge_chunks_cmd.cpp',
'cluster_move_chunk_cmd.cpp',
'cluster_move_primary_cmd.cpp',
- 'cluster_multicast.cpp',
+ 'cluster_multicast_cmd.cpp',
'cluster_netstat_cmd.cpp',
+ 'cluster_passthrough_commands.cpp',
'cluster_pipeline_cmd.cpp',
'cluster_plan_cache_clear_cmd.cpp',
'cluster_profile_cmd.cpp',
@@ -81,7 +84,7 @@ env.Library(
'cluster_reset_error_cmd.cpp',
'cluster_rwc_defaults_commands.cpp',
'cluster_set_feature_compatibility_version_cmd.cpp',
- 'cluster_set_free_monitoring.cpp' if get_option("enable-free-mon") == 'on' else [],
+ 'cluster_set_free_monitoring_cmd.cpp' if get_option("enable-free-mon") == 'on' else [],
'cluster_set_index_commit_quorum_cmd.cpp',
'cluster_shard_collection_cmd.cpp',
'cluster_shutdown_cmd.cpp',
@@ -91,13 +94,11 @@ env.Library(
'cluster_validate_cmd.cpp',
'cluster_whats_my_uri_cmd.cpp',
'cluster_write_cmd.cpp',
- 'commands_public.cpp',
'document_shard_key_update_util.cpp',
'kill_sessions_remote.cpp',
's_read_write_concern_defaults_server_status.cpp',
'strategy.cpp',
- env.Idlc('cluster_multicast.idl')[0],
- env.Idlc('kill_sessions_remote.idl')[0],
+ env.Idlc('cluster_commands.idl')[0],
],
LIBDEPS=[
'$BUILD_DIR/mongo/db/commands/servers',
diff --git a/src/mongo/s/commands/kill_sessions_remote.idl b/src/mongo/s/commands/cluster_commands.idl
index e48f99f7162..3f95b7f0181 100644
--- a/src/mongo/s/commands/kill_sessions_remote.idl
+++ b/src/mongo/s/commands/cluster_commands.idl
@@ -1,4 +1,4 @@
-# Copyright (C) 2019-present MongoDB, Inc.
+# Copyright (C) 2018-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,
@@ -24,9 +24,13 @@
# 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
+ cpp_namespace: "mongo"
+
+imports:
+ - "mongo/idl/basic_types.idl"
server_parameters:
KillSessionsMaxConcurrency:
@@ -44,3 +48,51 @@ server_parameters:
cpp_vartype: int
cpp_varname: gKillSessionsPerHostTimeoutMS
default: 60000
+
+structs:
+ ClusterMulticast:
+ description: "A struct representing the 'multicast' command's arguments"
+ strict: false
+ fields:
+ multicast: object
+ $db:
+ type: string
+ cpp_name: db
+ concurrency:
+ type: int
+ optional: true
+ timeout:
+ type: int
+ optional: true
+
+ ShardCollection:
+ description: "The public shardCollection command on mongos"
+ strict: false
+ fields:
+ shardCollection:
+ type: namespacestring
+ description: "The namespace of the collection to shard in the form <database>.<collection>."
+ optional: true
+ shardcollection:
+ type: namespacestring
+ description: "Same as the previous field, but refers to the deprecated version of this command's name"
+ optional: true
+ key:
+ type: object
+ description: "The index specification document to use as the shard key."
+ unique:
+ type: bool
+ description: "Whether the shard key index should enforce a unique constraint"
+ default: false
+ numInitialChunks:
+ type: safeInt64
+ description: "The number of chunks to create initially when sharding an empty collection with a hashed shard key."
+ default: 0
+ presplitHashedZones:
+ type: bool
+ description: "True if the chunks should be pre-split based on the existing zones when sharding a collection with hashed shard key"
+ default: false
+ collation:
+ type: object
+ description: "The collation to use for the shard key index."
+ optional: true
diff --git a/src/mongo/s/commands/cluster_list_collections_cmd.cpp b/src/mongo/s/commands/cluster_list_collections_cmd.cpp
new file mode 100644
index 00000000000..255d4ec7453
--- /dev/null
+++ b/src/mongo/s/commands/cluster_list_collections_cmd.cpp
@@ -0,0 +1,227 @@
+/**
+ * Copyright (C) 2020-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.
+ */
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/bson/mutable/algorithm.h"
+#include "mongo/bson/mutable/document.h"
+#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/commands.h"
+#include "mongo/s/cluster_commands_helpers.h"
+#include "mongo/s/query/store_possible_cursor.h"
+
+namespace mongo {
+namespace {
+
+bool cursorCommandPassthroughPrimaryShard(OperationContext* opCtx,
+ StringData dbName,
+ const CachedDatabaseInfo& dbInfo,
+ const BSONObj& cmdObj,
+ const NamespaceString& nss,
+ BSONObjBuilder* out,
+ const PrivilegeVector& privileges) {
+ auto response = executeCommandAgainstDatabasePrimary(
+ opCtx,
+ dbName,
+ dbInfo,
+ CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
+ ReadPreferenceSetting::get(opCtx),
+ Shard::RetryPolicy::kIdempotent);
+ const auto cmdResponse = uassertStatusOK(std::move(response.swResponse));
+
+ auto transformedResponse = uassertStatusOK(
+ storePossibleCursor(opCtx,
+ dbInfo.primaryId(),
+ *response.shardHostAndPort,
+ cmdResponse.data,
+ nss,
+ Grid::get(opCtx)->getExecutorPool()->getArbitraryExecutor(),
+ Grid::get(opCtx)->getCursorManager(),
+ privileges));
+
+ CommandHelpers::filterCommandReplyForPassthrough(transformedResponse, out);
+ return true;
+}
+
+BSONObj rewriteCommandForListingOwnCollections(OperationContext* opCtx,
+ const std::string& dbName,
+ const BSONObj& cmdObj) {
+ mutablebson::Document rewrittenCmdObj(cmdObj);
+ mutablebson::Element ownCollections =
+ mutablebson::findFirstChildNamed(rewrittenCmdObj.root(), "authorizedCollections");
+
+ AuthorizationSession* authzSession = AuthorizationSession::get(opCtx->getClient());
+
+ // We must strip $ownCollections from the delegated command.
+ uassertStatusOK(ownCollections.remove());
+
+ BSONObj collectionFilter;
+
+ // Extract and retain any previous filter
+ mutablebson::Element oldFilter =
+ mutablebson::findFirstChildNamed(rewrittenCmdObj.root(), "filter");
+
+ // Make a new filter, containing a $and array.
+ mutablebson::Element newFilter = rewrittenCmdObj.makeElementObject("filter");
+ mutablebson::Element newFilterAnd = rewrittenCmdObj.makeElementArray("$and");
+ uassertStatusOK(newFilter.pushBack(newFilterAnd));
+
+ mutablebson::Element newFilterOr = rewrittenCmdObj.makeElementArray("$or");
+ mutablebson::Element newFilterOrObj = rewrittenCmdObj.makeElementObject("");
+ uassertStatusOK(newFilterOrObj.pushBack(newFilterOr));
+ uassertStatusOK(newFilterAnd.pushBack(newFilterOrObj));
+
+ // DB resource grants all non-system collections, so filter out system collections. This is done
+ // inside the $or, since some system collections might be granted specific privileges.
+ if (authzSession->isAuthorizedForAnyActionOnResource(
+ ResourcePattern::forDatabaseName(dbName))) {
+ mutablebson::Element systemCollectionsFilter = rewrittenCmdObj.makeElementObject(
+ "", BSON("name" << BSON("$regex" << BSONRegEx("^(?!system\\.)"))));
+ uassertStatusOK(newFilterOr.pushBack(systemCollectionsFilter));
+ }
+
+ // Compute the set of collection names which would be permissible to return.
+ std::set<std::string> collectionNames;
+ for (UserNameIterator nameIter = authzSession->getAuthenticatedUserNames(); nameIter.more();
+ nameIter.next()) {
+ User* authUser = authzSession->lookupUser(*nameIter);
+ const User::ResourcePrivilegeMap& resourcePrivilegeMap = authUser->getPrivileges();
+ for (const std::pair<ResourcePattern, Privilege>& resourcePrivilege :
+ resourcePrivilegeMap) {
+ const auto& resource = resourcePrivilege.first;
+ if (resource.isCollectionPattern() ||
+ (resource.isExactNamespacePattern() && resource.databaseToMatch() == dbName)) {
+ collectionNames.emplace(resource.collectionToMatch().toString());
+ }
+ }
+ }
+
+ // Construct a new filter predicate which returns only collections we were found to have
+ // privileges for.
+ BSONObjBuilder predicateBuilder;
+ BSONObjBuilder nameBuilder(predicateBuilder.subobjStart("name"));
+ BSONArrayBuilder setBuilder(nameBuilder.subarrayStart("$in"));
+
+ // Load the de-duplicated set into a BSON array
+ for (StringData collectionName : collectionNames) {
+ setBuilder << collectionName;
+ }
+ setBuilder.done();
+ nameBuilder.done();
+
+ collectionFilter = predicateBuilder.obj();
+
+ // Filter the results by our collection names.
+ mutablebson::Element newFilterCollections =
+ rewrittenCmdObj.makeElementObject("", collectionFilter);
+ uassertStatusOK(newFilterOr.pushBack(newFilterCollections));
+
+ // If there was a pre-existing filter, compose it with our new one.
+ if (oldFilter.ok()) {
+ uassertStatusOK(oldFilter.remove());
+ uassertStatusOK(newFilterAnd.pushBack(oldFilter));
+ }
+
+ // Attach our new composite filter back onto the listCollections command object.
+ uassertStatusOK(rewrittenCmdObj.root().pushBack(newFilter));
+
+ return rewrittenCmdObj.getObject();
+}
+
+class CmdListCollections : public BasicCommand {
+public:
+ CmdListCollections() : BasicCommand("listCollections") {}
+
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kAlways;
+ }
+
+ bool maintenanceOk() const override {
+ return false;
+ }
+
+ bool adminOnly() const override {
+ return false;
+ }
+
+ Status checkAuthForCommand(Client* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) const final {
+ AuthorizationSession* authzSession = AuthorizationSession::get(client);
+
+ if (authzSession->checkAuthorizedToListCollections(dbname, cmdObj).isOK()) {
+ return Status::OK();
+ }
+
+ return Status(ErrorCodes::Unauthorized,
+ str::stream() << "Not authorized to list collections on db: " << dbname);
+ }
+
+ bool run(OperationContext* opCtx,
+ const std::string& dbName,
+ const BSONObj& cmdObj,
+ BSONObjBuilder& result) override {
+ CommandHelpers::handleMarkKillOnClientDisconnect(opCtx);
+
+ const auto nss(NamespaceString::makeListCollectionsNSS(dbName));
+
+ BSONObj newCmd = cmdObj;
+
+ AuthorizationSession* authzSession = AuthorizationSession::get(opCtx->getClient());
+ if (authzSession->getAuthorizationManager().isAuthEnabled() &&
+ newCmd["authorizedCollections"].trueValue()) {
+ newCmd = rewriteCommandForListingOwnCollections(opCtx, dbName, cmdObj);
+ }
+
+ auto dbInfoStatus = Grid::get(opCtx)->catalogCache()->getDatabase(opCtx, dbName);
+ if (!dbInfoStatus.isOK()) {
+ return appendEmptyResultSet(opCtx, result, dbInfoStatus.getStatus(), nss.ns());
+ }
+
+ return cursorCommandPassthroughPrimaryShard(
+ opCtx,
+ dbName,
+ dbInfoStatus.getValue(),
+ applyReadWriteConcern(opCtx, this, newCmd),
+ nss,
+ &result,
+ uassertStatusOK(AuthorizationSession::get(opCtx->getClient())
+ ->checkAuthorizedToListCollections(dbName, cmdObj)));
+ }
+
+} cmdListCollections;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_list_indexes_cmd.cpp b/src/mongo/s/commands/cluster_list_indexes_cmd.cpp
new file mode 100644
index 00000000000..56828a9ee95
--- /dev/null
+++ b/src/mongo/s/commands/cluster_list_indexes_cmd.cpp
@@ -0,0 +1,135 @@
+/**
+ * Copyright (C) 2020-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.
+ */
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/commands.h"
+#include "mongo/s/cluster_commands_helpers.h"
+#include "mongo/s/query/store_possible_cursor.h"
+
+namespace mongo {
+namespace {
+
+bool cursorCommandPassthroughShardWithMinKeyChunk(OperationContext* opCtx,
+ const NamespaceString& nss,
+ const CachedCollectionRoutingInfo& routingInfo,
+ const BSONObj& cmdObj,
+ BSONObjBuilder* out,
+ const PrivilegeVector& privileges) {
+ auto response = executeCommandAgainstShardWithMinKeyChunk(
+ opCtx,
+ nss,
+ routingInfo,
+ CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
+ ReadPreferenceSetting::get(opCtx),
+ Shard::RetryPolicy::kIdempotent);
+ const auto cmdResponse = uassertStatusOK(std::move(response.swResponse));
+
+ auto transformedResponse = uassertStatusOK(
+ storePossibleCursor(opCtx,
+ response.shardId,
+ *response.shardHostAndPort,
+ cmdResponse.data,
+ nss,
+ Grid::get(opCtx)->getExecutorPool()->getArbitraryExecutor(),
+ Grid::get(opCtx)->getCursorManager(),
+ privileges));
+
+ CommandHelpers::filterCommandReplyForPassthrough(transformedResponse, out);
+ return true;
+}
+
+class CmdListIndexes : public BasicCommand {
+public:
+ CmdListIndexes() : BasicCommand("listIndexes") {}
+
+ std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
+ return CommandHelpers::parseNsCollectionRequired(dbname, cmdObj).ns();
+ }
+
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kAlways;
+ }
+
+ bool maintenanceOk() const override {
+ return false;
+ }
+
+ bool adminOnly() const override {
+ return false;
+ }
+
+ Status checkAuthForCommand(Client* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) const override {
+ AuthorizationSession* authzSession = AuthorizationSession::get(client);
+
+ // Check for the listIndexes ActionType on the database.
+ const NamespaceString ns(parseNs(dbname, cmdObj));
+
+ if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forExactNamespace(ns),
+ ActionType::listIndexes)) {
+ return Status::OK();
+ }
+
+ return Status(ErrorCodes::Unauthorized,
+ str::stream()
+ << "Not authorized to list indexes on collection: " << ns.coll());
+ }
+
+ bool run(OperationContext* opCtx,
+ const std::string& dbName,
+ const BSONObj& cmdObj,
+ BSONObjBuilder& result) override {
+ CommandHelpers::handleMarkKillOnClientDisconnect(opCtx);
+
+ const NamespaceString nss(parseNs(dbName, cmdObj));
+ const auto routingInfo =
+ uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
+
+ return cursorCommandPassthroughShardWithMinKeyChunk(
+ opCtx,
+ nss,
+ routingInfo,
+ applyReadWriteConcern(opCtx, this, cmdObj),
+ &result,
+ {Privilege(ResourcePattern::forExactNamespace(nss), ActionType::listIndexes)});
+ }
+
+} cmdListIndexes;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_multicast.idl b/src/mongo/s/commands/cluster_multicast.idl
deleted file mode 100644
index ec3afe474d4..00000000000
--- a/src/mongo/s/commands/cluster_multicast.idl
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (C) 2018-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"
-
-structs:
-
- ClusterMulticastArgs:
- description: "A struct representing cluster multicast args"
- strict: false
- fields:
- multicast: object
- $db:
- type: string
- cpp_name: db
- concurrency:
- type: int
- optional: true
- timeout:
- type: int
- optional: true
diff --git a/src/mongo/s/commands/cluster_multicast.cpp b/src/mongo/s/commands/cluster_multicast_cmd.cpp
index 496232aa191..f74c4da2112 100644
--- a/src/mongo/s/commands/cluster_multicast.cpp
+++ b/src/mongo/s/commands/cluster_multicast_cmd.cpp
@@ -36,10 +36,9 @@
#include "mongo/db/commands/test_commands_enabled.h"
#include "mongo/executor/async_multicaster.h"
#include "mongo/executor/task_executor_pool.h"
-#include "mongo/s/catalog/sharding_catalog_client.h"
#include "mongo/s/catalog/type_shard.h"
#include "mongo/s/client/shard_registry.h"
-#include "mongo/s/commands/cluster_multicast_gen.h"
+#include "mongo/s/commands/cluster_commands_gen.h"
#include "mongo/s/grid.h"
namespace mongo {
@@ -64,18 +63,18 @@ std::vector<HostAndPort> getAllClusterHosts(OperationContext* opCtx) {
return servers;
}
-class MulticastCmd : public BasicCommand {
+class ClusterMulticastCmd : public BasicCommand {
public:
- MulticastCmd() : BasicCommand("multicast") {}
+ ClusterMulticastCmd() : BasicCommand("multicast") {}
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
+
bool adminOnly() const override {
return true;
}
-
bool supportsWriteConcern(const BSONObj& cmd) const override {
return false;
}
@@ -93,8 +92,8 @@ public:
const std::string& dbname,
const BSONObj& cmdObj,
BSONObjBuilder& result) override {
- IDLParserErrorContext ctx("ClusterMulticastArgs");
- auto args = ClusterMulticastArgs::parse(ctx, cmdObj);
+ IDLParserErrorContext ctx("ClusterMulticast");
+ auto args = ClusterMulticast::parse(ctx, cmdObj);
// Grab an arbitrary executor.
auto executor = Grid::get(opCtx)->getExecutorPool()->getArbitraryExecutor();
@@ -118,26 +117,24 @@ public:
bool success = true;
- {
- BSONObjBuilder bob(result.subobjStart("hosts"));
+ BSONObjBuilder bob(result.subobjStart("hosts"));
- for (const auto& r : results) {
- HostAndPort host;
- executor::RemoteCommandResponse response;
- std::tie(host, response) = r;
+ for (const auto& r : results) {
+ HostAndPort host;
+ executor::RemoteCommandResponse response;
+ std::tie(host, response) = r;
- if (!response.isOK() || !response.data["ok"].trueValue()) {
- success = false;
- }
+ if (!response.isOK() || !response.data["ok"].trueValue()) {
+ success = false;
+ }
- {
- BSONObjBuilder subbob(bob.subobjStart(host.toString()));
+ {
+ BSONObjBuilder subbob(bob.subobjStart(host.toString()));
- if (CommandHelpers::appendCommandStatusNoThrow(subbob, response.status)) {
- subbob.append("data", response.data);
- if (response.elapsedMillis) {
- subbob.append("elapsedMillis", response.elapsedMillis->count());
- }
+ if (CommandHelpers::appendCommandStatusNoThrow(subbob, response.status)) {
+ subbob.append("data", response.data);
+ if (response.elapsedMillis) {
+ subbob.append("elapsedMillis", response.elapsedMillis->count());
}
}
}
@@ -147,7 +144,7 @@ public:
}
};
-MONGO_REGISTER_TEST_COMMAND(MulticastCmd);
+MONGO_REGISTER_TEST_COMMAND(ClusterMulticastCmd);
} // namespace
} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_passthrough_commands.cpp b/src/mongo/s/commands/cluster_passthrough_commands.cpp
new file mode 100644
index 00000000000..ccb5ee5799d
--- /dev/null
+++ b/src/mongo/s/commands/cluster_passthrough_commands.cpp
@@ -0,0 +1,274 @@
+/**
+ * Copyright (C) 2018-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.
+ */
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/auth/action_set.h"
+#include "mongo/db/auth/action_type.h"
+#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/auth/privilege.h"
+#include "mongo/db/commands.h"
+#include "mongo/db/commands/rename_collection_common.h"
+#include "mongo/db/commands/rename_collection_gen.h"
+#include "mongo/executor/task_executor_pool.h"
+#include "mongo/rpc/get_status_from_command_result.h"
+#include "mongo/s/cluster_commands_helpers.h"
+#include "mongo/s/grid.h"
+
+namespace mongo {
+namespace {
+
+bool nonShardedCollectionCommandPassthrough(OperationContext* opCtx,
+ StringData dbName,
+ const NamespaceString& nss,
+ const CachedCollectionRoutingInfo& routingInfo,
+ const BSONObj& cmdObj,
+ Shard::RetryPolicy retryPolicy,
+ BSONObjBuilder* out) {
+ const StringData cmdName(cmdObj.firstElementFieldName());
+ uassert(ErrorCodes::IllegalOperation,
+ str::stream() << "Can't do command: " << cmdName << " on a sharded collection",
+ !routingInfo.cm());
+
+ auto responses = scatterGatherVersionedTargetByRoutingTable(opCtx,
+ dbName,
+ nss,
+ routingInfo,
+ cmdObj,
+ ReadPreferenceSetting::get(opCtx),
+ retryPolicy,
+ {},
+ {});
+ invariant(responses.size() == 1);
+
+ const auto cmdResponse = uassertStatusOK(std::move(responses.front().swResponse));
+ const auto status = getStatusFromCommandResult(cmdResponse.data);
+
+ uassert(ErrorCodes::IllegalOperation,
+ str::stream() << "Can't do command: " << cmdName << " on a sharded collection",
+ !ErrorCodes::isStaleShardVersionError(status));
+
+ out->appendElementsUnique(CommandHelpers::filterCommandReplyForPassthrough(cmdResponse.data));
+ return status.isOK();
+}
+
+class RenameCollectionCmd : public BasicCommand {
+public:
+ RenameCollectionCmd() : BasicCommand("renameCollection") {}
+
+ std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
+ return CommandHelpers::parseNsFullyQualified(cmdObj);
+ }
+
+ bool adminOnly() const override {
+ return true;
+ }
+
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kNever;
+ }
+
+ Status checkAuthForCommand(Client* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) const override {
+ return rename_collection::checkAuthForRenameCollectionCommand(client, dbname, cmdObj);
+ }
+
+ bool run(OperationContext* opCtx,
+ const std::string& dbName,
+ const BSONObj& cmdObj,
+ BSONObjBuilder& result) override {
+ auto renameRequest =
+ RenameCollectionCommand::parse(IDLParserErrorContext("renameCollection"), cmdObj);
+ auto fromNss = renameRequest.getCommandParameter();
+ auto toNss = renameRequest.getTo();
+
+ uassert(ErrorCodes::InvalidNamespace,
+ str::stream() << "Invalid target namespace: " << toNss.ns(),
+ toNss.isValid());
+
+ const auto fromRoutingInfo = uassertStatusOK(
+ Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, fromNss));
+ uassert(13138, "You can't rename a sharded collection", !fromRoutingInfo.cm());
+
+ const auto toRoutingInfo = uassertStatusOK(
+ Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, toNss));
+ uassert(13139, "You can't rename to a sharded collection", !toRoutingInfo.cm());
+
+ uassert(13137,
+ "Source and destination collections must be on same shard",
+ fromRoutingInfo.db().primaryId() == toRoutingInfo.db().primaryId());
+
+ return nonShardedCollectionCommandPassthrough(
+ opCtx,
+ NamespaceString::kAdminDb,
+ fromNss,
+ fromRoutingInfo,
+ applyReadWriteConcern(
+ opCtx, this, CommandHelpers::filterCommandRequestForPassthrough(cmdObj)),
+ Shard::RetryPolicy::kNoRetry,
+ &result);
+ }
+
+} renameCollectionCmd;
+
+class ConvertToCappedCmd : public BasicCommand {
+public:
+ ConvertToCappedCmd() : BasicCommand("convertToCapped") {}
+
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kNever;
+ }
+
+ std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
+ return CommandHelpers::parseNsCollectionRequired(dbname, cmdObj).ns();
+ }
+
+ void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) const override {
+ ActionSet actions;
+ actions.addAction(ActionType::convertToCapped);
+ out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions));
+ }
+
+ bool run(OperationContext* opCtx,
+ const std::string& dbName,
+ const BSONObj& cmdObj,
+ BSONObjBuilder& result) override {
+ const NamespaceString nss(parseNs(dbName, cmdObj));
+ const auto routingInfo =
+ uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
+ uassert(ErrorCodes::IllegalOperation,
+ "You can't convertToCapped a sharded collection",
+ !routingInfo.cm());
+
+ // convertToCapped creates a temp collection and renames it at the end. It will require
+ // special handling for create collection.
+ return nonShardedCollectionCommandPassthrough(
+ opCtx,
+ dbName,
+ nss,
+ routingInfo,
+ applyReadWriteConcern(
+ opCtx, this, CommandHelpers::filterCommandRequestForPassthrough(cmdObj)),
+ Shard::RetryPolicy::kIdempotent,
+ &result);
+ }
+
+} convertToCappedCmd;
+
+class SplitVectorCmd : public BasicCommand {
+public:
+ SplitVectorCmd() : BasicCommand("splitVector") {}
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kAlways;
+ }
+
+ std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
+ return CommandHelpers::parseNsFullyQualified(cmdObj);
+ }
+
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
+ Status checkAuthForCommand(Client* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) const override {
+ if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
+ ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname, cmdObj))),
+ ActionType::splitVector)) {
+ return Status(ErrorCodes::Unauthorized, "Unauthorized");
+ }
+ return Status::OK();
+ }
+
+ bool run(OperationContext* opCtx,
+ const std::string& dbName,
+ const BSONObj& cmdObj,
+ BSONObjBuilder& result) override {
+ const NamespaceString nss(parseNs(dbName, cmdObj));
+ uassert(ErrorCodes::IllegalOperation,
+ "Performing splitVector across dbs isn't supported via mongos",
+ nss.db() == dbName);
+
+ const auto routingInfo =
+ uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
+ uassert(ErrorCodes::IllegalOperation,
+ str::stream() << "can't do command: " << getName() << " on sharded collection",
+ !routingInfo.cm());
+
+ const auto primaryShard = routingInfo.db().primary();
+
+ // Here, we first filter the command before appending an UNSHARDED shardVersion, because
+ // "shardVersion" is one of the fields that gets filtered out.
+ BSONObj filteredCmdObj(applyReadWriteConcern(
+ opCtx, this, CommandHelpers::filterCommandRequestForPassthrough(cmdObj)));
+ BSONObj filteredCmdObjWithVersion(
+ appendShardVersion(filteredCmdObj, ChunkVersion::UNSHARDED()));
+
+ auto commandResponse = uassertStatusOK(primaryShard->runCommandWithFixedRetryAttempts(
+ opCtx,
+ ReadPreferenceSetting::get(opCtx),
+ dbName,
+ primaryShard->isConfig() ? filteredCmdObj : filteredCmdObjWithVersion,
+ Shard::RetryPolicy::kIdempotent));
+
+ uassert(ErrorCodes::IllegalOperation,
+ str::stream() << "can't do command: " << getName() << " on a sharded collection",
+ !ErrorCodes::isStaleShardVersionError(commandResponse.commandStatus.code()));
+
+ uassertStatusOK(commandResponse.commandStatus);
+
+ if (!commandResponse.writeConcernStatus.isOK()) {
+ appendWriteConcernErrorToCmdResponse(
+ primaryShard->getId(), commandResponse.response["writeConcernError"], result);
+ }
+ result.appendElementsUnique(
+ CommandHelpers::filterCommandReplyForPassthrough(std::move(commandResponse.response)));
+
+ return true;
+ }
+
+} splitVectorCmd;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_set_free_monitoring.cpp b/src/mongo/s/commands/cluster_set_free_monitoring_cmd.cpp
index d54cd80b219..d54cd80b219 100644
--- a/src/mongo/s/commands/cluster_set_free_monitoring.cpp
+++ b/src/mongo/s/commands/cluster_set_free_monitoring_cmd.cpp
diff --git a/src/mongo/s/commands/cluster_shard_collection_cmd.cpp b/src/mongo/s/commands/cluster_shard_collection_cmd.cpp
index c0f311de262..d27fd037d30 100644
--- a/src/mongo/s/commands/cluster_shard_collection_cmd.cpp
+++ b/src/mongo/s/commands/cluster_shard_collection_cmd.cpp
@@ -31,33 +31,18 @@
#include "mongo/platform/basic.h"
-#include <list>
-#include <set>
-#include <vector>
-
-#include "mongo/bson/simple_bsonelement_comparator.h"
-#include "mongo/bson/simple_bsonobj_comparator.h"
-#include "mongo/bson/util/bson_extract.h"
-#include "mongo/client/connpool.h"
#include "mongo/db/audit.h"
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/client.h"
#include "mongo/db/commands.h"
-#include "mongo/db/hasher.h"
-#include "mongo/db/index/index_descriptor.h"
-#include "mongo/db/operation_context.h"
-#include "mongo/db/query/collation/collator_factory_interface.h"
-#include "mongo/db/write_concern_options.h"
-#include "mongo/s/balancer_configuration.h"
-#include "mongo/s/catalog/sharding_catalog_client.h"
#include "mongo/s/catalog_cache.h"
#include "mongo/s/client/shard_registry.h"
#include "mongo/s/cluster_commands_helpers.h"
+#include "mongo/s/commands/cluster_commands_gen.h"
#include "mongo/s/config_server_client.h"
#include "mongo/s/grid.h"
-#include "mongo/s/request_types/migration_secondary_throttle_options.h"
#include "mongo/s/request_types/shard_collection_gen.h"
#include "mongo/util/scopeguard.h"
diff --git a/src/mongo/s/commands/commands_public.cpp b/src/mongo/s/commands/commands_public.cpp
deleted file mode 100644
index d943afc4e5c..00000000000
--- a/src/mongo/s/commands/commands_public.cpp
+++ /dev/null
@@ -1,569 +0,0 @@
-/**
- * Copyright (C) 2018-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.
- */
-
-#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/bson/mutable/algorithm.h"
-#include "mongo/bson/mutable/document.h"
-#include "mongo/db/auth/action_set.h"
-#include "mongo/db/auth/action_type.h"
-#include "mongo/db/auth/authorization_session.h"
-#include "mongo/db/auth/privilege.h"
-#include "mongo/db/commands.h"
-#include "mongo/db/commands/rename_collection.h"
-#include "mongo/db/commands/rename_collection_gen.h"
-#include "mongo/executor/task_executor_pool.h"
-#include "mongo/rpc/get_status_from_command_result.h"
-#include "mongo/s/cluster_commands_helpers.h"
-#include "mongo/s/commands/cluster_explain.h"
-#include "mongo/s/grid.h"
-#include "mongo/s/query/store_possible_cursor.h"
-#include "mongo/util/fail_point.h"
-#include "mongo/util/timer.h"
-
-namespace mongo {
-
-namespace {
-
-bool cursorCommandPassthroughPrimaryShard(OperationContext* opCtx,
- StringData dbName,
- const CachedDatabaseInfo& dbInfo,
- const BSONObj& cmdObj,
- const NamespaceString& nss,
- BSONObjBuilder* out,
- const PrivilegeVector& privileges) {
- auto response = executeCommandAgainstDatabasePrimary(
- opCtx,
- dbName,
- dbInfo,
- CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
- ReadPreferenceSetting::get(opCtx),
- Shard::RetryPolicy::kIdempotent);
- const auto cmdResponse = uassertStatusOK(std::move(response.swResponse));
-
- auto transformedResponse = uassertStatusOK(
- storePossibleCursor(opCtx,
- dbInfo.primaryId(),
- *response.shardHostAndPort,
- cmdResponse.data,
- nss,
- Grid::get(opCtx)->getExecutorPool()->getArbitraryExecutor(),
- Grid::get(opCtx)->getCursorManager(),
- privileges));
-
- CommandHelpers::filterCommandReplyForPassthrough(transformedResponse, out);
- return true;
-}
-
-bool cursorCommandPassthroughShardWithMinKeyChunk(OperationContext* opCtx,
- const NamespaceString& nss,
- const CachedCollectionRoutingInfo& routingInfo,
- const BSONObj& cmdObj,
- BSONObjBuilder* out,
- const PrivilegeVector& privileges) {
- auto response = executeCommandAgainstShardWithMinKeyChunk(
- opCtx,
- nss,
- routingInfo,
- CommandHelpers::filterCommandRequestForPassthrough(cmdObj),
- ReadPreferenceSetting::get(opCtx),
- Shard::RetryPolicy::kIdempotent);
- const auto cmdResponse = uassertStatusOK(std::move(response.swResponse));
-
- auto transformedResponse = uassertStatusOK(
- storePossibleCursor(opCtx,
- response.shardId,
- *response.shardHostAndPort,
- cmdResponse.data,
- nss,
- Grid::get(opCtx)->getExecutorPool()->getArbitraryExecutor(),
- Grid::get(opCtx)->getCursorManager(),
- privileges));
-
- CommandHelpers::filterCommandReplyForPassthrough(transformedResponse, out);
- return true;
-}
-
-bool nonShardedCollectionCommandPassthrough(OperationContext* opCtx,
- StringData dbName,
- const NamespaceString& nss,
- const CachedCollectionRoutingInfo& routingInfo,
- const BSONObj& cmdObj,
- Shard::RetryPolicy retryPolicy,
- BSONObjBuilder* out) {
- const StringData cmdName(cmdObj.firstElementFieldName());
- uassert(ErrorCodes::IllegalOperation,
- str::stream() << "Can't do command: " << cmdName << " on a sharded collection",
- !routingInfo.cm());
-
- auto responses = scatterGatherVersionedTargetByRoutingTable(opCtx,
- dbName,
- nss,
- routingInfo,
- cmdObj,
- ReadPreferenceSetting::get(opCtx),
- retryPolicy,
- {},
- {});
- invariant(responses.size() == 1);
-
- const auto cmdResponse = uassertStatusOK(std::move(responses.front().swResponse));
- const auto status = getStatusFromCommandResult(cmdResponse.data);
-
- uassert(ErrorCodes::IllegalOperation,
- str::stream() << "Can't do command: " << cmdName << " on a sharded collection",
- !ErrorCodes::isStaleShardVersionError(status));
-
- out->appendElementsUnique(CommandHelpers::filterCommandReplyForPassthrough(cmdResponse.data));
- return status.isOK();
-}
-
-class NotAllowedOnShardedCollectionCmd : public BasicCommand {
-protected:
- NotAllowedOnShardedCollectionCmd(const char* n) : BasicCommand(n) {}
-
- AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
- return AllowedOnSecondary::kAlways;
- }
-
- bool run(OperationContext* opCtx,
- const std::string& dbName,
- const BSONObj& cmdObj,
- BSONObjBuilder& result) override {
- const NamespaceString nss(parseNs(dbName, cmdObj));
-
- const auto routingInfo =
- uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
- uassert(ErrorCodes::IllegalOperation,
- str::stream() << "can't do command: " << getName() << " on sharded collection",
- !routingInfo.cm());
-
- const auto primaryShard = routingInfo.db().primary();
-
- // Here, we first filter the command before appending an UNSHARDED shardVersion, because
- // "shardVersion" is one of the fields that gets filtered out.
- BSONObj filteredCmdObj(applyReadWriteConcern(
- opCtx, this, CommandHelpers::filterCommandRequestForPassthrough(cmdObj)));
- BSONObj filteredCmdObjWithVersion(
- appendShardVersion(filteredCmdObj, ChunkVersion::UNSHARDED()));
-
- auto commandResponse = uassertStatusOK(primaryShard->runCommandWithFixedRetryAttempts(
- opCtx,
- ReadPreferenceSetting::get(opCtx),
- dbName,
- primaryShard->isConfig() ? filteredCmdObj : filteredCmdObjWithVersion,
- Shard::RetryPolicy::kIdempotent));
-
- uassert(ErrorCodes::IllegalOperation,
- str::stream() << "can't do command: " << getName() << " on a sharded collection",
- !ErrorCodes::isStaleShardVersionError(commandResponse.commandStatus.code()));
-
- uassertStatusOK(commandResponse.commandStatus);
-
- if (!commandResponse.writeConcernStatus.isOK()) {
- appendWriteConcernErrorToCmdResponse(
- primaryShard->getId(), commandResponse.response["writeConcernError"], result);
- }
- result.appendElementsUnique(
- CommandHelpers::filterCommandReplyForPassthrough(std::move(commandResponse.response)));
-
- return true;
- }
-};
-
-class RenameCollectionCmd : public BasicCommand {
-public:
- RenameCollectionCmd() : BasicCommand("renameCollection") {}
-
- std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
- return CommandHelpers::parseNsFullyQualified(cmdObj);
- }
-
- bool adminOnly() const override {
- return true;
- }
-
- bool supportsWriteConcern(const BSONObj& cmd) const override {
- return true;
- }
-
- AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
- return AllowedOnSecondary::kNever;
- }
-
- Status checkAuthForCommand(Client* client,
- const std::string& dbname,
- const BSONObj& cmdObj) const override {
- return rename_collection::checkAuthForRenameCollectionCommand(client, dbname, cmdObj);
- }
-
- bool run(OperationContext* opCtx,
- const std::string& dbName,
- const BSONObj& cmdObj,
- BSONObjBuilder& result) override {
- auto renameRequest =
- RenameCollectionCommand::parse(IDLParserErrorContext("renameCollection"), cmdObj);
- auto fromNss = renameRequest.getCommandParameter();
- auto toNss = renameRequest.getTo();
-
- uassert(ErrorCodes::InvalidNamespace,
- str::stream() << "Invalid target namespace: " << toNss.ns(),
- toNss.isValid());
-
- const auto fromRoutingInfo = uassertStatusOK(
- Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, fromNss));
- uassert(13138, "You can't rename a sharded collection", !fromRoutingInfo.cm());
-
- const auto toRoutingInfo = uassertStatusOK(
- Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, toNss));
- uassert(13139, "You can't rename to a sharded collection", !toRoutingInfo.cm());
-
- uassert(13137,
- "Source and destination collections must be on same shard",
- fromRoutingInfo.db().primaryId() == toRoutingInfo.db().primaryId());
-
- return nonShardedCollectionCommandPassthrough(
- opCtx,
- NamespaceString::kAdminDb,
- fromNss,
- fromRoutingInfo,
- applyReadWriteConcern(
- opCtx, this, CommandHelpers::filterCommandRequestForPassthrough(cmdObj)),
- Shard::RetryPolicy::kNoRetry,
- &result);
- }
-
-} renameCollectionCmd;
-
-class ConvertToCappedCmd : public BasicCommand {
-public:
- ConvertToCappedCmd() : BasicCommand("convertToCapped") {}
-
- bool supportsWriteConcern(const BSONObj& cmd) const override {
- return true;
- }
-
- AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
- return AllowedOnSecondary::kNever;
- }
-
- std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
- return CommandHelpers::parseNsCollectionRequired(dbname, cmdObj).ns();
- }
-
- void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) const override {
- ActionSet actions;
- actions.addAction(ActionType::convertToCapped);
- out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions));
- }
-
- bool run(OperationContext* opCtx,
- const std::string& dbName,
- const BSONObj& cmdObj,
- BSONObjBuilder& result) override {
- const NamespaceString nss(parseNs(dbName, cmdObj));
- const auto routingInfo =
- uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
- uassert(ErrorCodes::IllegalOperation,
- "You can't convertToCapped a sharded collection",
- !routingInfo.cm());
-
- // convertToCapped creates a temp collection and renames it at the end. It will require
- // special handling for create collection.
- return nonShardedCollectionCommandPassthrough(
- opCtx,
- dbName,
- nss,
- routingInfo,
- applyReadWriteConcern(
- opCtx, this, CommandHelpers::filterCommandRequestForPassthrough(cmdObj)),
- Shard::RetryPolicy::kIdempotent,
- &result);
- }
-
-} convertToCappedCmd;
-
-class SplitVectorCmd : public NotAllowedOnShardedCollectionCmd {
-public:
- SplitVectorCmd() : NotAllowedOnShardedCollectionCmd("splitVector") {}
-
- std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
- return CommandHelpers::parseNsFullyQualified(cmdObj);
- }
-
- bool supportsWriteConcern(const BSONObj& cmd) const override {
- return false;
- }
-
- Status checkAuthForCommand(Client* client,
- const std::string& dbname,
- const BSONObj& cmdObj) const override {
- if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
- ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname, cmdObj))),
- ActionType::splitVector)) {
- return Status(ErrorCodes::Unauthorized, "Unauthorized");
- }
- return Status::OK();
- }
-
- bool run(OperationContext* opCtx,
- const std::string& dbName,
- const BSONObj& cmdObj,
- BSONObjBuilder& result) override {
- const NamespaceString nss(parseNs(dbName, cmdObj));
- uassert(ErrorCodes::IllegalOperation,
- "Performing splitVector across dbs isn't supported via mongos",
- nss.db() == dbName);
-
- return NotAllowedOnShardedCollectionCmd::run(opCtx, dbName, cmdObj, result);
- }
-
-} splitVectorCmd;
-
-class CmdListCollections : public BasicCommand {
-public:
- CmdListCollections() : BasicCommand("listCollections") {}
-
- bool supportsWriteConcern(const BSONObj& cmd) const override {
- return false;
- }
-
- AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
- return AllowedOnSecondary::kAlways;
- }
-
- bool maintenanceOk() const override {
- return false;
- }
-
- bool adminOnly() const override {
- return false;
- }
-
- Status checkAuthForCommand(Client* client,
- const std::string& dbname,
- const BSONObj& cmdObj) const final {
- AuthorizationSession* authzSession = AuthorizationSession::get(client);
-
- if (authzSession->checkAuthorizedToListCollections(dbname, cmdObj).isOK()) {
- return Status::OK();
- }
-
- return Status(ErrorCodes::Unauthorized,
- str::stream() << "Not authorized to list collections on db: " << dbname);
- }
-
- BSONObj rewriteCommandForListingOwnCollections(OperationContext* opCtx,
- const std::string& dbName,
- const BSONObj& cmdObj) {
- mutablebson::Document rewrittenCmdObj(cmdObj);
- mutablebson::Element ownCollections =
- mutablebson::findFirstChildNamed(rewrittenCmdObj.root(), "authorizedCollections");
-
- AuthorizationSession* authzSession = AuthorizationSession::get(opCtx->getClient());
-
- // We must strip $ownCollections from the delegated command.
- uassertStatusOK(ownCollections.remove());
-
- BSONObj collectionFilter;
-
- // Extract and retain any previous filter
- mutablebson::Element oldFilter =
- mutablebson::findFirstChildNamed(rewrittenCmdObj.root(), "filter");
-
- // Make a new filter, containing a $and array.
- mutablebson::Element newFilter = rewrittenCmdObj.makeElementObject("filter");
- mutablebson::Element newFilterAnd = rewrittenCmdObj.makeElementArray("$and");
- uassertStatusOK(newFilter.pushBack(newFilterAnd));
-
- mutablebson::Element newFilterOr = rewrittenCmdObj.makeElementArray("$or");
- mutablebson::Element newFilterOrObj = rewrittenCmdObj.makeElementObject("");
- uassertStatusOK(newFilterOrObj.pushBack(newFilterOr));
- uassertStatusOK(newFilterAnd.pushBack(newFilterOrObj));
-
- // DB resource grants all non-system collections, so filter out system collections.
- // This is done inside the $or, since some system collections might be granted specific
- // privileges.
- if (authzSession->isAuthorizedForAnyActionOnResource(
- ResourcePattern::forDatabaseName(dbName))) {
- mutablebson::Element systemCollectionsFilter = rewrittenCmdObj.makeElementObject(
- "", BSON("name" << BSON("$regex" << BSONRegEx("^(?!system\\.)"))));
- uassertStatusOK(newFilterOr.pushBack(systemCollectionsFilter));
- }
-
- // Compute the set of collection names which would be permissible to return.
- std::set<std::string> collectionNames;
- for (UserNameIterator nameIter = authzSession->getAuthenticatedUserNames(); nameIter.more();
- nameIter.next()) {
- User* authUser = authzSession->lookupUser(*nameIter);
- const User::ResourcePrivilegeMap& resourcePrivilegeMap = authUser->getPrivileges();
- for (const std::pair<ResourcePattern, Privilege>& resourcePrivilege :
- resourcePrivilegeMap) {
- const auto& resource = resourcePrivilege.first;
- if (resource.isCollectionPattern() ||
- (resource.isExactNamespacePattern() && resource.databaseToMatch() == dbName)) {
- collectionNames.emplace(resource.collectionToMatch().toString());
- }
- }
- }
-
- // Construct a new filter predicate which returns only collections we were found to
- // have privileges for.
- BSONObjBuilder predicateBuilder;
- BSONObjBuilder nameBuilder(predicateBuilder.subobjStart("name"));
- BSONArrayBuilder setBuilder(nameBuilder.subarrayStart("$in"));
-
- // Load the de-duplicated set into a BSON array
- for (StringData collectionName : collectionNames) {
- setBuilder << collectionName;
- }
- setBuilder.done();
- nameBuilder.done();
-
- collectionFilter = predicateBuilder.obj();
-
- // Filter the results by our collection names.
- mutablebson::Element newFilterCollections =
- rewrittenCmdObj.makeElementObject("", collectionFilter);
- uassertStatusOK(newFilterOr.pushBack(newFilterCollections));
-
- // If there was a pre-existing filter, compose it with our new one.
- if (oldFilter.ok()) {
- uassertStatusOK(oldFilter.remove());
- uassertStatusOK(newFilterAnd.pushBack(oldFilter));
- }
-
- // Attach our new composite filter back onto the listCollections command object.
- uassertStatusOK(rewrittenCmdObj.root().pushBack(newFilter));
-
- return rewrittenCmdObj.getObject();
- }
-
- bool run(OperationContext* opCtx,
- const std::string& dbName,
- const BSONObj& cmdObj,
- BSONObjBuilder& result) override {
- CommandHelpers::handleMarkKillOnClientDisconnect(opCtx);
-
- const auto nss(NamespaceString::makeListCollectionsNSS(dbName));
-
- BSONObj newCmd = cmdObj;
-
- AuthorizationSession* authzSession = AuthorizationSession::get(opCtx->getClient());
- if (authzSession->getAuthorizationManager().isAuthEnabled() &&
- newCmd["authorizedCollections"].trueValue()) {
- newCmd = rewriteCommandForListingOwnCollections(opCtx, dbName, cmdObj);
- }
-
- auto dbInfoStatus = Grid::get(opCtx)->catalogCache()->getDatabase(opCtx, dbName);
- if (!dbInfoStatus.isOK()) {
- return appendEmptyResultSet(opCtx, result, dbInfoStatus.getStatus(), nss.ns());
- }
-
- return cursorCommandPassthroughPrimaryShard(
- opCtx,
- dbName,
- dbInfoStatus.getValue(),
- applyReadWriteConcern(opCtx, this, newCmd),
- nss,
- &result,
- uassertStatusOK(AuthorizationSession::get(opCtx->getClient())
- ->checkAuthorizedToListCollections(dbName, cmdObj)));
- }
-} cmdListCollections;
-
-class CmdListIndexes : public BasicCommand {
-public:
- CmdListIndexes() : BasicCommand("listIndexes") {}
-
- std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
- return CommandHelpers::parseNsCollectionRequired(dbname, cmdObj).ns();
- }
-
- bool supportsWriteConcern(const BSONObj& cmd) const override {
- return false;
- }
-
- AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
- return AllowedOnSecondary::kAlways;
- }
-
- bool maintenanceOk() const override {
- return false;
- }
-
- bool adminOnly() const override {
- return false;
- }
-
- Status checkAuthForCommand(Client* client,
- const std::string& dbname,
- const BSONObj& cmdObj) const override {
- AuthorizationSession* authzSession = AuthorizationSession::get(client);
-
- // Check for the listIndexes ActionType on the database.
- const NamespaceString ns(parseNs(dbname, cmdObj));
-
- if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forExactNamespace(ns),
- ActionType::listIndexes)) {
- return Status::OK();
- }
-
- return Status(ErrorCodes::Unauthorized,
- str::stream()
- << "Not authorized to list indexes on collection: " << ns.coll());
- }
-
- bool run(OperationContext* opCtx,
- const std::string& dbName,
- const BSONObj& cmdObj,
- BSONObjBuilder& result) override {
- CommandHelpers::handleMarkKillOnClientDisconnect(opCtx);
-
- const NamespaceString nss(parseNs(dbName, cmdObj));
- const auto routingInfo =
- uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
-
- return cursorCommandPassthroughShardWithMinKeyChunk(
- opCtx,
- nss,
- routingInfo,
- applyReadWriteConcern(opCtx, this, cmdObj),
- &result,
- {Privilege(ResourcePattern::forExactNamespace(nss), ActionType::listIndexes)});
- }
-
-} cmdListIndexes;
-
-} // namespace
-} // namespace mongo
diff --git a/src/mongo/s/commands/kill_sessions_remote.cpp b/src/mongo/s/commands/kill_sessions_remote.cpp
index 6c3782cbb2b..d9b5ce26ccf 100644
--- a/src/mongo/s/commands/kill_sessions_remote.cpp
+++ b/src/mongo/s/commands/kill_sessions_remote.cpp
@@ -32,21 +32,19 @@
#include "mongo/platform/basic.h"
#include "mongo/s/commands/kill_sessions_remote.h"
-#include "mongo/s/commands/kill_sessions_remote_gen.h"
#include "mongo/db/client.h"
#include "mongo/db/kill_sessions_common.h"
#include "mongo/db/operation_context.h"
-#include "mongo/db/service_context.h"
#include "mongo/executor/async_multicaster.h"
#include "mongo/executor/task_executor_pool.h"
#include "mongo/s/client/shard.h"
#include "mongo/s/client/shard_registry.h"
+#include "mongo/s/commands/cluster_commands_gen.h"
#include "mongo/s/grid.h"
#include "mongo/s/query/cluster_cursor_manager.h"
namespace mongo {
-
namespace {
/**
@@ -112,10 +110,6 @@ Status killSessionsRemoteKillCursor(OperationContext* opCtx,
} // namespace
-/**
- * This kill function (meant for mongos), kills matching local ops first, then fans out to all other
- * nodes in the cluster to kill them as well.
- */
SessionKiller::Result killSessionsRemote(OperationContext* opCtx,
const SessionKiller::Matcher& matcher,
SessionKiller::UniformRandomBitGenerator* urbg) {
diff --git a/src/mongo/s/commands/kill_sessions_remote.h b/src/mongo/s/commands/kill_sessions_remote.h
index ecd63341b9d..ef59d7769bd 100644
--- a/src/mongo/s/commands/kill_sessions_remote.h
+++ b/src/mongo/s/commands/kill_sessions_remote.h
@@ -29,14 +29,13 @@
#pragma once
-#include "mongo/db/kill_sessions.h"
-
#include "mongo/db/session_killer.h"
namespace mongo {
/**
- * The killSessions killer for running on mongos
+ * The killSessions killer for running on mongos. It kills matching local ops first, then fans out
+ * to all other nodes in the cluster to kill them as well.
*/
SessionKiller::Result killSessionsRemote(OperationContext* opCtx,
const SessionKiller::Matcher& patterns,
diff --git a/src/mongo/s/request_types/shard_collection.idl b/src/mongo/s/request_types/shard_collection.idl
index 5df76c033e7..6440111a61b 100644
--- a/src/mongo/s/request_types/shard_collection.idl
+++ b/src/mongo/s/request_types/shard_collection.idl
@@ -35,38 +35,6 @@ imports:
- "mongo/idl/basic_types.idl"
structs:
- shardCollection:
- description: "The public shardCollection command on mongos"
- strict: false
- fields:
- shardCollection:
- type: namespacestring
- description: "The namespace of the collection to shard in the form <database>.<collection>."
- optional: true
- shardcollection:
- type: namespacestring
- description: "The deprecated version of this command's name"
- optional: true
- key:
- type: object
- description: "The index specification document to use as the shard key."
- unique:
- type: bool
- description: "Whether the shard key index should enforce a unique constraint"
- default: false
- numInitialChunks:
- type: safeInt64
- description: "The number of chunks to create initially when sharding an empty collection with a hashed shard key."
- default: 0
- presplitHashedZones:
- type: bool
- description: "True if the chunks should be pre-split based on the existing zones when sharding a collection with hashed shard key"
- default: false
- collation:
- type: object
- description: "The collation to use for the shard key index."
- optional: true
-
ConfigsvrShardCollectionRequest:
description: "The request format of the internal shardCollection command on the config server"
strict: false
@@ -115,7 +83,7 @@ structs:
description: "The UUID of the collection that just got sharded."
optional: true
- ShardsvrShardCollection:
+ ShardsvrShardCollectionRequest:
description: "The internal shardCollection command on a primary shard"
strict: false
fields:
@@ -162,15 +130,3 @@ structs:
type: uuid
description: "The UUID of the collection that just got sharded."
optional: true
-
- ConfigsvrCommitShardCollection:
- description: "The internal commitShardCollection command on the config server"
- strict: false
- fields:
- _configsvrCommitShardCollection:
- type: string
- description: "The name of the collection that just got sharded."
- collectionUUID:
- type: uuid
- description: "The UUID of the collection that just got sharded."
- optional: true