summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan <thejonathanma@gmail.com>2018-12-21 08:18:07 -0800
committerJonathan <thejonathanma@gmail.com>2018-12-21 12:07:27 -0800
commita321412859c62f3d8439cebf9ccfd2450f5970ec (patch)
treec48dcbca98d2487c3b23ffc676b62521f6bc457f
parent23128892c8d73cb159b881cb00f2404d6ad67b2b (diff)
downloadmongo-a321412859c62f3d8439cebf9ccfd2450f5970ec.tar.gz
SERVER-36416 Add dropConnections administrative command
-rw-r--r--jstests/core/views/views_all_commands.js1
-rw-r--r--jstests/noPassthrough/drop_connections_replSet.js30
-rw-r--r--jstests/noPassthrough/drop_connections_sharded.js30
-rw-r--r--jstests/sharding/database_and_shard_versioning_all_commands.js1
-rw-r--r--jstests/sharding/libs/last_stable_mongos_commands.js2
-rw-r--r--jstests/sharding/safe_secondary_reads_drop_recreate.js1
-rw-r--r--jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js1
-rw-r--r--jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js1
-rw-r--r--src/mongo/db/auth/action_types.txt2
-rw-r--r--src/mongo/db/auth/role_graph_builtin_roles.cpp1
-rw-r--r--src/mongo/db/commands/SConscript3
-rw-r--r--src/mongo/db/commands/drop_connections.idl45
-rw-r--r--src/mongo/db/commands/drop_connections_command.cpp97
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