summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorHugh Han <hughhan1@gmail.com>2017-07-26 13:28:57 -0400
committerHugh Han <hughhan1@gmail.com>2017-08-15 12:11:40 -0400
commitf14037e54577ce79cec00e06735f914c01b3f80e (patch)
tree1ed1025a3a4d5dd7594716fd46c711ab638d091a /src/mongo/db
parent578e5c4f168db90ebb7ec661831363575d801f5b (diff)
downloadmongo-f14037e54577ce79cec00e06735f914c01b3f80e.tar.gz
SERVER-30324 Move cluster_remove_shard_cmd to mongod
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/s/config/configsvr_remove_shard_command.cpp106
1 files changed, 105 insertions, 1 deletions
diff --git a/src/mongo/db/s/config/configsvr_remove_shard_command.cpp b/src/mongo/db/s/config/configsvr_remove_shard_command.cpp
index 5ac9d2dc224..d24516b0a9c 100644
--- a/src/mongo/db/s/config/configsvr_remove_shard_command.cpp
+++ b/src/mongo/db/s/config/configsvr_remove_shard_command.cpp
@@ -42,6 +42,7 @@
#include "mongo/s/catalog/sharding_catalog_manager.h"
#include "mongo/s/catalog/type_database.h"
#include "mongo/s/catalog_cache.h"
+#include "mongo/s/client/shard_registry.h"
#include "mongo/s/grid.h"
#include "mongo/util/log.h"
#include "mongo/util/scopeguard.h"
@@ -65,7 +66,7 @@ public:
}
virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
- return false;
+ return true;
}
virtual void help(std::stringstream& help) const override {
@@ -73,11 +74,114 @@ public:
"directly. Removes a shard from the cluster.";
}
+ 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();
+ }
+
bool run(OperationContext* opCtx,
const std::string& dbname,
const BSONObj& cmdObj,
BSONObjBuilder& result) {
+ uassert(ErrorCodes::IllegalOperation,
+ "_configsvrRemoveShard can only be run on config servers",
+ serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
+
+ uassert(ErrorCodes::TypeMismatch,
+ str::stream() << "Field '" << cmdObj.firstElement().fieldName()
+ << "' must be of type string",
+ cmdObj.firstElement().type() == BSONType::String);
+ const std::string target = cmdObj.firstElement().str();
+
+ const auto shardStatus = grid.shardRegistry()->getShard(opCtx, ShardId(target));
+ if (!shardStatus.isOK()) {
+ std::string msg(str::stream() << "Could not drop shard '" << target
+ << "' because it does not exist");
+ log() << msg;
+ return appendCommandStatus(result, Status(ErrorCodes::ShardNotFound, msg));
+ }
+ const auto shard = shardStatus.getValue();
+
+ const auto shardingCatalogManager = ShardingCatalogManager::get(opCtx);
+
+ StatusWith<ShardDrainingStatus> removeShardResult =
+ shardingCatalogManager->removeShard(opCtx, shard->getId());
+ if (!removeShardResult.isOK()) {
+ return appendCommandStatus(result, removeShardResult.getStatus());
+ }
+
+ std::vector<std::string> databases;
+ Status status =
+ shardingCatalogManager->getDatabasesForShard(opCtx, shard->getId(), &databases);
+ if (!status.isOK()) {
+ return appendCommandStatus(result, status);
+ }
+
+ // Get BSONObj containing:
+ // 1) note about moving or dropping databases in a shard
+ // 2) list of databases (excluding 'local' database) that need to be moved
+ BSONObj dbInfo;
+ {
+ BSONObjBuilder dbInfoBuilder;
+ dbInfoBuilder.append("note", "you need to drop or movePrimary these databases");
+ BSONArrayBuilder dbs(dbInfoBuilder.subarrayStart("dbsToMove"));
+ for (std::vector<std::string>::const_iterator it = databases.begin();
+ it != databases.end();
+ it++) {
+ if (*it != "local") {
+ dbs.append(*it);
+ }
+ }
+ dbs.doneFast();
+ dbInfo = dbInfoBuilder.obj();
+ }
+
+ // TODO: Standardize/Seperate how we append to the result object
+ switch (removeShardResult.getValue()) {
+ case ShardDrainingStatus::STARTED:
+ result.append("msg", "draining started successfully");
+ result.append("state", "started");
+ result.append("shard", shard->getId().toString());
+ result.appendElements(dbInfo);
+ break;
+ case ShardDrainingStatus::ONGOING: {
+ std::vector<ChunkType> chunks;
+ Status status = Grid::get(opCtx)->catalogClient()->getChunks(
+ opCtx,
+ BSON(ChunkType::shard(shard->getId().toString())),
+ BSONObj(),
+ boost::none, // return all
+ &chunks,
+ nullptr,
+ repl::ReadConcernLevel::kMajorityReadConcern);
+ if (!status.isOK()) {
+ return appendCommandStatus(result, status);
+ }
+
+ result.append("msg", "draining ongoing");
+ result.append("state", "ongoing");
+ {
+ BSONObjBuilder inner;
+ inner.append("chunks", static_cast<long long>(chunks.size()));
+ inner.append("dbs", static_cast<long long>(databases.size()));
+ BSONObj b = inner.obj();
+ result.append("remaining", b);
+ }
+ result.appendElements(dbInfo);
+ break;
+ }
+ case ShardDrainingStatus::COMPLETED:
+ result.append("msg", "removeshard completed successfully");
+ result.append("state", "completed");
+ result.append("shard", shard->getId().toString());
+ }
+
return true;
}