diff options
author | Jonathan <thejonathanma@gmail.com> | 2018-12-21 08:18:07 -0800 |
---|---|---|
committer | Jonathan <thejonathanma@gmail.com> | 2018-12-21 12:07:27 -0800 |
commit | a321412859c62f3d8439cebf9ccfd2450f5970ec (patch) | |
tree | c48dcbca98d2487c3b23ffc676b62521f6bc457f | |
parent | 23128892c8d73cb159b881cb00f2404d6ad67b2b (diff) | |
download | mongo-a321412859c62f3d8439cebf9ccfd2450f5970ec.tar.gz |
SERVER-36416 Add dropConnections administrative command
13 files changed, 213 insertions, 2 deletions
diff --git a/jstests/core/views/views_all_commands.js b/jstests/core/views/views_all_commands.js index 708b5b56889..045497b3033 100644 --- a/jstests/core/views/views_all_commands.js +++ b/jstests/core/views/views_all_commands.js @@ -217,6 +217,7 @@ drop: {command: {drop: "view"}}, dropAllRolesFromDatabase: {skip: isUnrelated}, dropAllUsersFromDatabase: {skip: isUnrelated}, + dropConnections: {skip: isUnrelated}, dropDatabase: {command: {dropDatabase: 1}}, dropIndexes: {command: {dropIndexes: "view"}, expectFailure: true}, dropRole: { diff --git a/jstests/noPassthrough/drop_connections_replSet.js b/jstests/noPassthrough/drop_connections_replSet.js new file mode 100644 index 00000000000..29c41659107 --- /dev/null +++ b/jstests/noPassthrough/drop_connections_replSet.js @@ -0,0 +1,30 @@ +// verify dropConnections command works for replica sets + +(function() { + "use strict"; + + const rst = new ReplSetTest({nodes: 3}); + rst.startSet(); + rst.initiate(); + + const primary = rst.getPrimary(); + rst.awaitSecondaryNodes(); + + const cfg = primary.getDB('local').system.replset.findOne(); + const memberHost = cfg.members[2].host; + const removedMember = cfg.members.splice(2, 1); + cfg.version++; + + assert.commandWorked(primary.adminCommand({replSetReconfig: cfg})); + + assert.eq(1, primary.adminCommand({connPoolStats: 1}).hosts[memberHost].available); + assert.commandWorked(primary.adminCommand({dropConnections: 1, hostAndPort: [memberHost]})); + assert.eq(0, primary.adminCommand({connPoolStats: 1}).hosts[memberHost].available); + + // need to re-add removed node or test complain about the replset config + cfg.members.push(removedMember[0]); + cfg.version++; + assert.commandWorked(primary.adminCommand({replSetReconfig: cfg})); + + rst.stopSet(); +})(); diff --git a/jstests/noPassthrough/drop_connections_sharded.js b/jstests/noPassthrough/drop_connections_sharded.js new file mode 100644 index 00000000000..f41aa653b4d --- /dev/null +++ b/jstests/noPassthrough/drop_connections_sharded.js @@ -0,0 +1,30 @@ +// verify dropConnections command works for sharded clusters + +(function() { + "use strict"; + + const st = new ShardingTest({shards: 1, rs0: {nodes: 3}, mongos: 1}); + const mongos = st.s0; + const rst = st.rs0; + const primary = rst.getPrimary(); + + mongos.adminCommand({multicast: {ping: 0}}); + + const cfg = primary.getDB('local').system.replset.findOne(); + const memberHost = cfg.members[2].host; + const removedMember = cfg.members.splice(2, 1); + cfg.version++; + + assert.commandWorked(primary.adminCommand({replSetReconfig: cfg})); + + assert.eq(1, mongos.adminCommand({connPoolStats: 1}).hosts[memberHost].available); + assert.commandWorked(mongos.adminCommand({dropConnections: 1, hostAndPort: [memberHost]})); + assert.eq(0, mongos.adminCommand({connPoolStats: 1}).hosts[memberHost].available); + + // need to re-add removed node or test complain about the replset config + cfg.members.push(removedMember[0]); + cfg.version++; + assert.commandWorked(primary.adminCommand({replSetReconfig: cfg})); + + st.stop(); +})(); diff --git a/jstests/sharding/database_and_shard_versioning_all_commands.js b/jstests/sharding/database_and_shard_versioning_all_commands.js index 6016478ebcd..85773bfb19e 100644 --- a/jstests/sharding/database_and_shard_versioning_all_commands.js +++ b/jstests/sharding/database_and_shard_versioning_all_commands.js @@ -181,6 +181,7 @@ }, dropAllRolesFromDatabase: {skip: "always targets the config server"}, dropAllUsersFromDatabase: {skip: "always targets the config server"}, + dropConnections: {skip: "not on a user database"}, dropDatabase: {skip: "drops the database from the cluster, changing the UUID"}, dropIndexes: { sendsDbVersion: true, diff --git a/jstests/sharding/libs/last_stable_mongos_commands.js b/jstests/sharding/libs/last_stable_mongos_commands.js index 0f3a5b7a19b..5e06996374b 100644 --- a/jstests/sharding/libs/last_stable_mongos_commands.js +++ b/jstests/sharding/libs/last_stable_mongos_commands.js @@ -14,4 +14,4 @@ const commandsRemovedFromMongosIn42 = [ // These commands were added in mongos 4.2, so will not appear in the listCommands output of a 4.0 // mongos. We will allow these commands to have a test defined without always existing on the mongos // being used. -const commandsAddedToMongosIn42 = ['abortTransaction', 'commitTransaction']; +const commandsAddedToMongosIn42 = ['abortTransaction', 'commitTransaction', 'dropConnections']; diff --git a/jstests/sharding/safe_secondary_reads_drop_recreate.js b/jstests/sharding/safe_secondary_reads_drop_recreate.js index 843556e2e4b..64f4cbbcf52 100644 --- a/jstests/sharding/safe_secondary_reads_drop_recreate.js +++ b/jstests/sharding/safe_secondary_reads_drop_recreate.js @@ -143,6 +143,7 @@ drop: {skip: "primary only"}, dropAllRolesFromDatabase: {skip: "primary only"}, dropAllUsersFromDatabase: {skip: "primary only"}, + dropConnections: {skip: "does not return user data"}, dropDatabase: {skip: "primary only"}, dropIndexes: {skip: "primary only"}, dropRole: {skip: "primary only"}, diff --git a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js index e2f05fb27de..720fcd27fd3 100644 --- a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js +++ b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js @@ -167,6 +167,7 @@ drop: {skip: "primary only"}, dropAllRolesFromDatabase: {skip: "primary only"}, dropAllUsersFromDatabase: {skip: "primary only"}, + dropConnections: {skip: "does not return user data"}, dropDatabase: {skip: "primary only"}, dropIndexes: {skip: "primary only"}, dropRole: {skip: "primary only"}, diff --git a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js index 9d554cba9f1..e85cd608d32 100644 --- a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js +++ b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js @@ -145,6 +145,7 @@ drop: {skip: "primary only"}, dropAllRolesFromDatabase: {skip: "primary only"}, dropAllUsersFromDatabase: {skip: "primary only"}, + dropConnections: {skip: "does not return user data"}, dropDatabase: {skip: "primary only"}, dropIndexes: {skip: "primary only"}, dropRole: {skip: "primary only"}, diff --git a/src/mongo/db/auth/action_types.txt b/src/mongo/db/auth/action_types.txt index 644f60e3928..303022bf3a9 100644 --- a/src/mongo/db/auth/action_types.txt +++ b/src/mongo/db/auth/action_types.txt @@ -39,6 +39,7 @@ "dropAllRolesFromDatabase", # Not used for permissions checks, but to id the event in logs. "dropAllUsersFromDatabase", # Not used for permissions checks, but to id the event in logs. "dropCollection", +"dropConnections", "dropDatabase", "dropIndex", "dropRole", @@ -122,4 +123,3 @@ "validate", "viewRole", "viewUser"] - diff --git a/src/mongo/db/auth/role_graph_builtin_roles.cpp b/src/mongo/db/auth/role_graph_builtin_roles.cpp index 3de5d8b2e53..dd8bb4a8a15 100644 --- a/src/mongo/db/auth/role_graph_builtin_roles.cpp +++ b/src/mongo/db/auth/role_graph_builtin_roles.cpp @@ -209,6 +209,7 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) { << ActionType::applicationMessage // clusterManager gets this also << ActionType::connPoolSync << ActionType::cpuProfiler + << ActionType::dropConnections << ActionType::logRotate << ActionType::setParameter << ActionType::shutdown diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript index eabb2df44fa..35808b12da5 100644 --- a/src/mongo/db/commands/SConscript +++ b/src/mongo/db/commands/SConscript @@ -134,6 +134,8 @@ env.Library( "conn_pool_stats.cpp", "conn_pool_sync.cpp", "connection_status.cpp", + "drop_connections_command.cpp", + env.Idlc('drop_connections.idl')[0], "generic_servers.cpp", "isself.cpp", "mr_common.cpp", @@ -156,6 +158,7 @@ env.Library( '$BUILD_DIR/mongo/db/logical_session_id_helpers', '$BUILD_DIR/mongo/db/repl/isself', '$BUILD_DIR/mongo/db/repl/repl_coordinator_interface', + '$BUILD_DIR/mongo/executor/egress_tag_closer_manager', '$BUILD_DIR/mongo/executor/task_executor_pool', '$BUILD_DIR/mongo/s/sharding_legacy_api', '$BUILD_DIR/mongo/s/coreshard', diff --git a/src/mongo/db/commands/drop_connections.idl b/src/mongo/db/commands/drop_connections.idl new file mode 100644 index 00000000000..7d41e108889 --- /dev/null +++ b/src/mongo/db/commands/drop_connections.idl @@ -0,0 +1,45 @@ +# 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. +# + +# dropConnections IDL File. + +global: + cpp_namespace: "mongo" + +imports: + - "mongo/idl/basic_types.idl" + - "mongo/util/net/hostandport.idl" + +commands: + dropConnections: + description: "An administrative command which takes a list of host and ports and drops pooled connections to them" + namespace: ignored + fields: + hostAndPort: + description: "List of host and ports" + type: array<HostAndPort> diff --git a/src/mongo/db/commands/drop_connections_command.cpp b/src/mongo/db/commands/drop_connections_command.cpp new file mode 100644 index 00000000000..73c9a285c5e --- /dev/null +++ b/src/mongo/db/commands/drop_connections_command.cpp @@ -0,0 +1,97 @@ + +/** + * 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_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kCommand + +#include "mongo/platform/basic.h" + +#include "mongo/db/auth/authorization_session.h" +#include "mongo/db/commands.h" +#include "mongo/db/commands/drop_connections_gen.h" +#include "mongo/executor/egress_tag_closer_manager.h" +#include "mongo/util/log.h" +#include "mongo/util/net/hostandport.h" + +namespace mongo { +namespace { + +class DropConnectionsCmd final : public TypedCommand<DropConnectionsCmd> { +public: + using Request = DropConnections; + + std::string help() const override { + return "Drop egress connections to specified host and port"; + } + + bool adminOnly() const override { + return true; + } + + AllowedOnSecondary secondaryAllowed(ServiceContext*) const override { + return AllowedOnSecondary::kAlways; + } + + class Invocation final : public InvocationBase { + public: + using InvocationBase::InvocationBase; + + void typedRun(OperationContext* opCtx) { + + const auto& hostAndPorts = request().getHostAndPort(); + + auto& egressTagCloserManager = + executor::EgressTagCloserManager::get(opCtx->getServiceContext()); + + for (const auto& hostAndPort : hostAndPorts) { + egressTagCloserManager.dropConnections(hostAndPort); + } + } + + NamespaceString ns() const override { + return NamespaceString(); + } + + bool supportsWriteConcern() const override { + return false; + } + + void doCheckAuthorization(OperationContext* opCtx) const override { + uassert(ErrorCodes::Unauthorized, + "Unauthorized", + AuthorizationSession::get(opCtx->getClient()) + ->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(), + ActionType::dropConnections)); + } + }; + +} dropConnectionsCmd; + +} // namespace +} // namespace mongo |