summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorSergey Galtsev <sergey.galtsev@mongodb.com>2021-03-10 17:50:34 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-03-10 18:57:54 +0000
commit150548f8317e2e0353ee1c319cda9149bb1d68f6 (patch)
tree5ce609e85855c73ee6b950469633f260d6bf8670 /src/mongo/db
parent867520870aa9b31d6c774ec9254382614dc7ec44 (diff)
downloadmongo-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.cpp10
-rw-r--r--src/mongo/db/repl/repl_set_config.h11
-rw-r--r--src/mongo/db/repl/repl_set_config_checks.cpp26
-rw-r--r--src/mongo/db/repl/repl_set_config_checks.h10
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp5
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}",