summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/auth_schema_upgrade_d.cpp
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@10gen.com>2014-01-08 17:12:26 -0500
committerAndy Schwerin <schwerin@10gen.com>2014-01-14 15:23:42 -0500
commit89126c21f0eb3b9b1674ee64d0f75d91a841084e (patch)
treee89dd7e7dc8b0e580c0b08ae03b6012515a67d19 /src/mongo/db/commands/auth_schema_upgrade_d.cpp
parent13226efcd6638b707e0f4a64564d655cea9bc9c7 (diff)
downloadmongo-89126c21f0eb3b9b1674ee64d0f75d91a841084e.tar.gz
SERVER-12156 Check replicaset member versions before doing auth schema upgrade.
Diffstat (limited to 'src/mongo/db/commands/auth_schema_upgrade_d.cpp')
-rw-r--r--src/mongo/db/commands/auth_schema_upgrade_d.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/mongo/db/commands/auth_schema_upgrade_d.cpp b/src/mongo/db/commands/auth_schema_upgrade_d.cpp
index 13596980ff7..d18fb04356c 100644
--- a/src/mongo/db/commands/auth_schema_upgrade_d.cpp
+++ b/src/mongo/db/commands/auth_schema_upgrade_d.cpp
@@ -33,10 +33,84 @@
#include "mongo/db/auth/authz_documents_update_guard.h"
#include "mongo/db/auth/user_management_commands_parser.h"
#include "mongo/db/commands/user_management_commands.h"
+#include "mongo/db/repl/multicmd.h"
+#include "mongo/db/repl/rs.h"
+#include "mongo/db/repl/rs_config.h"
+#include "mongo/util/mongoutils/str.h"
+#include "mongo/util/version.h"
namespace mongo {
namespace {
+ Status checkReplicaMemberVersions() {
+ if (!theReplSet)
+ return Status::OK();
+
+
+ std::list<Target> rsMembers;
+ try {
+ const unsigned rsSelfId = theReplSet->selfId();
+ const std::vector<ReplSetConfig::MemberCfg>& rsMemberConfigs =
+ theReplSet->config().members;
+ for (size_t i = 0; i < rsMemberConfigs.size(); ++i) {
+ const unsigned otherId = rsMemberConfigs[i]._id;
+ if (rsSelfId == otherId)
+ continue;
+ const Member* other = theReplSet->findById(otherId);
+ if (!other) {
+ log() << "During authSchemaUpgrade, no information about replica set member "
+ "with id " << otherId << "; ignoring.";
+ continue;
+ }
+ if (!other->hbinfo().maybeUp()) {
+ log() << "During authSchemaUpgrade, replica set member " << other->h() <<
+ " is down; ignoring.";
+ continue;
+ }
+ rsMembers.push_back(Target(other->fullName()));
+ }
+
+ multiCommand(BSON("buildInfo" << 1), rsMembers);
+ }
+ catch (const DBException& ex) {
+ return ex.toStatus();
+ }
+
+ for (std::list<Target>::const_iterator iter = rsMembers.begin(), end = rsMembers.end();
+ iter != end;
+ ++iter) {
+
+ if (!iter->ok) {
+ logger::LogstreamBuilder wlog = warning();
+ wlog << "During authSchemaUpgrade, could not run buildInfo command on " <<
+ iter->toHost;
+ if (!iter->result.isEmpty())
+ wlog << "; response was " << iter->result.toString();
+ wlog << "; ignoring.";
+ continue;
+ }
+
+ const char* version = iter->result["version"].valuestrsafe();
+ if (!*version) {
+ return Status(ErrorCodes::RemoteValidationError, mongoutils::str::stream() <<
+ "Missing or non-string \"version\" field in result of buildInfo "
+ "command sent to " << iter->toHost << "; found " <<
+ iter->result["version"]);
+ }
+
+ if (!isSameMajorVersion(version)) {
+ BSONArray foundVersionArray = toVersionArray(version);
+ return Status(ErrorCodes::RemoteValidationError, mongoutils::str::stream() <<
+ "To upgrade auth schema in a replica set, all members must be "
+ "running the same release series of mongod; found " <<
+ foundVersionArray["0"] << '.' << foundVersionArray["1"] <<
+ " on host " << iter->toHost << " but expected " <<
+ versionArray["0"] << '.' << versionArray["1"]);
+ }
+ }
+ return Status::OK();
+ }
+
class CmdAuthSchemaUpgradeD : public CmdAuthSchemaUpgrade {
virtual bool run(
const string& dbname,
@@ -68,6 +142,10 @@ namespace {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
+ status = checkReplicaMemberVersions();
+ if (!status.isOK())
+ return appendCommandStatus(result, status);
+
status = authzManager->upgradeSchema(maxSteps, writeConcern);
if (status.isOK())
result.append("done", true);