diff options
author | Sergey Galtsev <sergey.galtsev@mongodb.com> | 2021-03-10 17:50:34 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-03-10 18:57:54 +0000 |
commit | 150548f8317e2e0353ee1c319cda9149bb1d68f6 (patch) | |
tree | 5ce609e85855c73ee6b950469633f260d6bf8670 /src/mongo/db | |
parent | 867520870aa9b31d6c774ec9254382614dc7ec44 (diff) | |
download | mongo-150548f8317e2e0353ee1c319cda9149bb1d68f6.tar.gz |
SERVER-50827 Nodes with IP addresses in split horizons must be able to start
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/repl/repl_set_config.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/repl/repl_set_config.h | 11 | ||||
-rw-r--r-- | src/mongo/db/repl/repl_set_config_checks.cpp | 26 | ||||
-rw-r--r-- | src/mongo/db/repl/repl_set_config_checks.h | 10 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl.cpp | 5 |
5 files changed, 54 insertions, 8 deletions
diff --git a/src/mongo/db/repl/repl_set_config.cpp b/src/mongo/db/repl/repl_set_config.cpp index c40b7428203..85284321c74 100644 --- a/src/mongo/db/repl/repl_set_config.cpp +++ b/src/mongo/db/repl/repl_set_config.cpp @@ -190,6 +190,14 @@ Status ReplSetConfig::_initialize(bool forInitiate, } Status ReplSetConfig::validate() const { + return _validate(false); +} + +Status ReplSetConfig::validateAllowingSplitHorizonIP() const { + return _validate(true); +} + +Status ReplSetConfig::_validate(bool allowSplitHorizonIP) const { if (getMembers().size() > kMaxMembers || getMembers().empty()) { return Status(ErrorCodes::BadValue, str::stream() << "Replica set configuration contains " << getMembers().size() @@ -220,7 +228,7 @@ Status ReplSetConfig::validate() const { const MemberConfig& memberI = getMembers()[i]; // Check that no horizon mappings contain IP addresses - if (!disableSplitHorizonIPCheck) { + if (!disableSplitHorizonIPCheck && !allowSplitHorizonIP) { for (auto&& mapping : memberI.getHorizonMappings()) { // Ignore the default horizon -- this can be an IP if (mapping.first == SplitHorizon::kDefaultHorizon) { diff --git a/src/mongo/db/repl/repl_set_config.h b/src/mongo/db/repl/repl_set_config.h index 5148d0fa8ea..df9a0481d26 100644 --- a/src/mongo/db/repl/repl_set_config.h +++ b/src/mongo/db/repl/repl_set_config.h @@ -252,6 +252,12 @@ public: Status validate() const; /** + * Performs basic consistency checks on the replica set configuration, but does not fail on + * IP addresses in split horizon configuration + */ + Status validateAllowingSplitHorizonIP() const; + + /** * Checks if this configuration can satisfy the given write concern. * * Things that are taken into consideration include: @@ -550,6 +556,11 @@ private: void _setRequiredFields(); /** + * Performs basic consistency checks on the replica set configuration. + */ + Status _validate(bool allowSplitHorizonIP) const; + + /** * Common code used by constructors */ Status _initialize(bool forInitiate, diff --git a/src/mongo/db/repl/repl_set_config_checks.cpp b/src/mongo/db/repl/repl_set_config_checks.cpp index e4da3276793..6f51fc82b38 100644 --- a/src/mongo/db/repl/repl_set_config_checks.cpp +++ b/src/mongo/db/repl/repl_set_config_checks.cpp @@ -375,7 +375,7 @@ StatusWith<int> findSelfInConfigIfElectable(ReplicationCoordinatorExternalState* StatusWith<int> validateConfigForStartUp(ReplicationCoordinatorExternalState* externalState, const ReplSetConfig& newConfig, ServiceContext* ctx) { - Status status = newConfig.validate(); + Status status = newConfig.validateAllowingSplitHorizonIP(); if (!status.isOK()) { return StatusWith<int>(status); } @@ -426,10 +426,12 @@ StatusWith<int> validateConfigForInitiate(ReplicationCoordinatorExternalState* e return findSelfInConfigIfElectable(externalState, newConfig, ctx); } -Status validateConfigForReconfig(const ReplSetConfig& oldConfig, - const ReplSetConfig& newConfig, - bool force) { - Status status = newConfig.validate(); +Status _validateConfigForReconfig(const ReplSetConfig& oldConfig, + const ReplSetConfig& newConfig, + bool force, + bool allowSplitHorizonIP) { + Status status = + allowSplitHorizonIP ? newConfig.validateAllowingSplitHorizonIP() : newConfig.validate(); if (!status.isOK()) { return status; } @@ -468,11 +470,23 @@ Status validateConfigForReconfig(const ReplSetConfig& oldConfig, return Status::OK(); } +Status validateConfigForReconfig(const ReplSetConfig& oldConfig, + const ReplSetConfig& newConfig, + bool force) { + return _validateConfigForReconfig(oldConfig, newConfig, force, false); +} + +Status validateConfigForOplogReconfig(const ReplSetConfig& oldConfig, + const ReplSetConfig& newConfig) { + return _validateConfigForReconfig(oldConfig, newConfig, true, true); +} + + StatusWith<int> validateConfigForHeartbeatReconfig( ReplicationCoordinatorExternalState* externalState, const ReplSetConfig& newConfig, ServiceContext* ctx) { - Status status = newConfig.validate(); + Status status = newConfig.validateAllowingSplitHorizonIP(); if (!status.isOK()) { return StatusWith<int>(status); } diff --git a/src/mongo/db/repl/repl_set_config_checks.h b/src/mongo/db/repl/repl_set_config_checks.h index 7b96c73f2ee..16d84d2e2ec 100644 --- a/src/mongo/db/repl/repl_set_config_checks.h +++ b/src/mongo/db/repl/repl_set_config_checks.h @@ -100,6 +100,16 @@ Status validateConfigForReconfig(const ReplSetConfig& oldConfig, bool force); /** + * Validates that "newConfig" is a legal successor configuration to "oldConfig" that can be + * initiated by the current node (identified via "externalState"). Ignores an error condition + * when an IP address exists in split horizon configuration + * + * Returns an indicative error on validation failure. + */ +Status validateConfigForOplogReconfig(const ReplSetConfig& oldConfig, + const ReplSetConfig& newConfig); + +/** * Validates that "newConfig" is an acceptable configuration when received in a heartbeat * reasponse. * diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index a7edca785fa..a7d83fa9558 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -3431,7 +3431,10 @@ Status ReplicationCoordinatorImpl::doReplSetReconfig(OperationContext* opCtx, BSONObj newConfigObj = newConfig.toBSON(); audit::logReplSetReconfig(opCtx->getClient(), &oldConfigObj, &newConfigObj); - Status validateStatus = validateConfigForReconfig(oldConfig, newConfig, force); + bool isManualReconfig = opCtx->getClient()->hasRemote(); + Status validateStatus = isManualReconfig + ? validateConfigForReconfig(oldConfig, newConfig, force) + : validateConfigForOplogReconfig(oldConfig, newConfig); if (!validateStatus.isOK()) { LOGV2_ERROR(21420, "replSetReconfig got {error} while validating {newConfig}", |