diff options
author | Andy Schwerin <schwerin@10gen.com> | 2014-01-08 17:12:26 -0500 |
---|---|---|
committer | Andy Schwerin <schwerin@10gen.com> | 2014-01-14 15:23:42 -0500 |
commit | 89126c21f0eb3b9b1674ee64d0f75d91a841084e (patch) | |
tree | e89dd7e7dc8b0e580c0b08ae03b6012515a67d19 /src/mongo/db/commands/auth_schema_upgrade_d.cpp | |
parent | 13226efcd6638b707e0f4a64564d655cea9bc9c7 (diff) | |
download | mongo-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.cpp | 78 |
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); |