summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorJason Chan <jason.chan@mongodb.com>2020-09-09 19:50:15 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-09-24 16:30:58 +0000
commit3a6bde797e31d9e06e982aa20b89a856cfeef95c (patch)
tree9a82a3bae80a2c66ffd09deac4d0e1c6c924cbab /src/mongo
parent1bf955ec900a5e78ba9437f90a76dab906dbc2f2 (diff)
downloadmongo-3a6bde797e31d9e06e982aa20b89a856cfeef95c.tar.gz
SERVER-50706 Add fromConfigServer parameter to allow transitioning a shard server from lastLTS FCV to lastContinuousFCV
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/commands/feature_compatibility_version.cpp101
-rw-r--r--src/mongo/db/commands/feature_compatibility_version.h7
-rw-r--r--src/mongo/db/commands/feature_compatibility_version_parser.cpp61
-rw-r--r--src/mongo/db/commands/feature_compatibility_version_parser.h55
-rw-r--r--src/mongo/db/commands/set_feature_compatibility_version.idl5
-rw-r--r--src/mongo/db/commands/set_feature_compatibility_version_command.cpp67
-rw-r--r--src/mongo/db/fcv_op_observer.cpp12
-rw-r--r--src/mongo/db/s/SConscript1
-rw-r--r--src/mongo/db/s/config/sharding_catalog_manager_add_shard_test.cpp12
-rw-r--r--src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp91
-rw-r--r--src/mongo/db/server_options.h15
11 files changed, 276 insertions, 151 deletions
diff --git a/src/mongo/db/commands/feature_compatibility_version.cpp b/src/mongo/db/commands/feature_compatibility_version.cpp
index 4e4ddb99af7..ce27ffd1ae1 100644
--- a/src/mongo/db/commands/feature_compatibility_version.cpp
+++ b/src/mongo/db/commands/feature_compatibility_version.cpp
@@ -118,17 +118,64 @@ void runUpdateCommand(OperationContext* opCtx, const FeatureCompatibilityVersion
client.runCommand(nss.db().toString(), updateCmd.obj(), updateResult);
uassertStatusOK(getStatusFromWriteCommandReply(updateResult));
}
+
+/**
+ * Returns the expected value of the 'targetVersion' field in the FCV document based on the
+ * in-memory FCV value. Returns boost::none if current FCV is not currently upgrading or
+ * downgrading.
+ */
+boost::optional<FeatureCompatibilityParams::Version> getFcvDocTargetVersionField() {
+ if (!serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
+ return boost::none;
+ }
+ const auto currentFcv = serverGlobalParams.featureCompatibility.getVersion();
+ if (currentFcv == FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest ||
+ currentFcv == FeatureCompatibilityParams::kUpgradingFromLastContinuousToLatest) {
+ return FeatureCompatibilityParams::kLatest;
+ } else if (currentFcv == FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous ||
+ currentFcv == FeatureCompatibilityParams::kDowngradingFromLatestToLastContinuous) {
+ return FeatureCompatibilityParams::kLastContinuous;
+ } else {
+ invariant(currentFcv == FeatureCompatibilityParams::kDowngradingFromLatestToLastLTS);
+ return FeatureCompatibilityParams::kLastLTS;
+ }
+}
+
+/**
+ * Returns the expected value of the 'version' field in the FCV document based on the in-memory FCV
+ * value.
+ */
+FeatureCompatibilityParams::Version getFcvDocVersionField() {
+ if (!serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
+ return serverGlobalParams.featureCompatibility.getVersion();
+ }
+ const auto currentFcv = serverGlobalParams.featureCompatibility.getVersion();
+ if (currentFcv == FeatureCompatibilityParams::kUpgradingFromLastContinuousToLatest ||
+ currentFcv == FeatureCompatibilityParams::kDowngradingFromLatestToLastContinuous) {
+ return FeatureCompatibilityParams::kLastContinuous;
+ } else {
+ invariant(currentFcv == FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous ||
+ currentFcv == FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest ||
+ currentFcv == FeatureCompatibilityParams::kDowngradingFromLatestToLastLTS);
+ return FeatureCompatibilityParams::kLastLTS;
+ }
+}
} // namespace
void FeatureCompatibilityVersion::setTargetUpgradeFrom(
- OperationContext* opCtx, FeatureCompatibilityParams::Version fromVersion) {
+ OperationContext* opCtx,
+ FeatureCompatibilityParams::Version fromVersion,
+ FeatureCompatibilityParams::Version newVersion) {
+ invariant(fromVersion < newVersion);
+
FeatureCompatibilityParams::Version version;
// It is possible that we did not fully complete a previous upgrade. In that case, we
// must set the source version to be the fully downgraded version as the FCV document
// serializer does not recognize upgrading/downgrading states.
if (fromVersion == FeatureCompatibilityParams::kUpgradingFromLastContinuousToLatest) {
version = FeatureCompatibilityParams::kLastContinuous;
- } else if (fromVersion == FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest) {
+ } else if (fromVersion == FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest ||
+ fromVersion == FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous) {
version = FeatureCompatibilityParams::kLastLTS;
} else {
version = fromVersion;
@@ -136,9 +183,9 @@ void FeatureCompatibilityVersion::setTargetUpgradeFrom(
// Sets both 'version' and 'targetVersion' fields.
FeatureCompatibilityVersionDocument fcvDoc;
fcvDoc.setVersion(version);
- fcvDoc.setTargetVersion(FeatureCompatibilityParams::kLatest);
+ fcvDoc.setTargetVersion(newVersion);
runUpdateCommand(opCtx, fcvDoc);
-}
+} // namespace mongo
void FeatureCompatibilityVersion::setTargetDowngrade(OperationContext* opCtx,
FeatureCompatibilityParams::Version version) {
@@ -211,25 +258,24 @@ bool FeatureCompatibilityVersion::isCleanStartUp() {
void FeatureCompatibilityVersion::updateMinWireVersion() {
WireSpec& wireSpec = WireSpec::instance();
-
- if (serverGlobalParams.featureCompatibility.isGreaterThanOrEqualTo(
- FeatureCompatibilityParams::kLatest) ||
- serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
- // FCV == kLatest or FCV is upgrading/downgrading.
+ const auto currentFcv = serverGlobalParams.featureCompatibility.getVersion();
+ if (currentFcv == FeatureCompatibilityParams::kLatest ||
+ (serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading() &&
+ currentFcv != FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous)) {
+ // FCV == kLatest or FCV is upgrading/downgrading to or from kLatest.
WireSpec::Specification newSpec = *wireSpec.get();
newSpec.incomingInternalClient.minWireVersion = LATEST_WIRE_VERSION;
newSpec.outgoing.minWireVersion = LATEST_WIRE_VERSION;
wireSpec.reset(std::move(newSpec));
- } else if (serverGlobalParams.featureCompatibility.isGreaterThanOrEqualTo(
- FeatureCompatibilityParams::kLastContinuous)) {
- // FCV == kLastContinuous
+ } else if (currentFcv == FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous ||
+ currentFcv == FeatureCompatibilityParams::kLastContinuous) {
+ // FCV == kLastContinuous or upgrading to kLastContinuous.
WireSpec::Specification newSpec = *wireSpec.get();
newSpec.incomingInternalClient.minWireVersion = LAST_CONT_WIRE_VERSION;
newSpec.outgoing.minWireVersion = LAST_CONT_WIRE_VERSION;
wireSpec.reset(std::move(newSpec));
} else {
- // FCV == kLastLTS
- invariant(serverGlobalParams.featureCompatibility.isVersionInitialized());
+ invariant(currentFcv == FeatureCompatibilityParams::kLastLTS);
WireSpec::Specification newSpec = *wireSpec.get();
newSpec.incomingInternalClient.minWireVersion = LAST_LTS_WIRE_VERSION;
newSpec.outgoing.minWireVersion = LAST_LTS_WIRE_VERSION;
@@ -337,23 +383,16 @@ void FeatureCompatibilityVersionParameter::append(OperationContext* opCtx,
FeatureCompatibilityVersionDocument fcvDoc;
BSONObjBuilder featureCompatibilityVersionBuilder(b.subobjStart(name));
auto version = serverGlobalParams.featureCompatibility.getVersion();
- switch (version) {
- case ServerGlobalParams::FeatureCompatibility::kLatest:
- case ServerGlobalParams::FeatureCompatibility::kLastLTS:
- fcvDoc.setVersion(version);
- break;
- case ServerGlobalParams::FeatureCompatibility::kUpgradingFromLastLTSToLatest:
- fcvDoc.setVersion(ServerGlobalParams::FeatureCompatibility::kLastLTS);
- fcvDoc.setTargetVersion(ServerGlobalParams::FeatureCompatibility::kLatest);
- break;
- case ServerGlobalParams::FeatureCompatibility::kDowngradingFromLatestToLastLTS:
- fcvDoc.setVersion(ServerGlobalParams::FeatureCompatibility::kLastLTS);
- fcvDoc.setTargetVersion(ServerGlobalParams::FeatureCompatibility::kLastLTS);
- fcvDoc.setPreviousVersion(ServerGlobalParams::FeatureCompatibility::kLatest);
- break;
- case ServerGlobalParams::FeatureCompatibility::Version::kUnsetDefault44Behavior:
- // getVersion() does not return this value.
- MONGO_UNREACHABLE;
+ if (serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
+ fcvDoc.setVersion(getFcvDocVersionField());
+ fcvDoc.setTargetVersion(getFcvDocTargetVersionField());
+ if (version == FeatureCompatibilityParams::kDowngradingFromLatestToLastContinuous ||
+ version == FeatureCompatibilityParams::kDowngradingFromLatestToLastLTS) {
+ // We only support downgrading from the latest FCV.
+ fcvDoc.setPreviousVersion(FeatureCompatibilityParams::kLatest);
+ }
+ } else {
+ fcvDoc.setVersion(version);
}
featureCompatibilityVersionBuilder.appendElements(fcvDoc.toBSON().removeField("_id"));
}
diff --git a/src/mongo/db/commands/feature_compatibility_version.h b/src/mongo/db/commands/feature_compatibility_version.h
index 3f458066614..57f39cd7d60 100644
--- a/src/mongo/db/commands/feature_compatibility_version.h
+++ b/src/mongo/db/commands/feature_compatibility_version.h
@@ -67,12 +67,13 @@ public:
static void fassertInitializedAfterStartup(OperationContext* opCtx);
/**
- * Records intent to perform a currentVersion -> kLatest upgrade by updating the on-disk
+ * Records intent to perform a fromVersion -> newVersion upgrade by updating the on-disk
* feature compatibility version document to have 'version'=currentVersion,
- * 'targetVersion'=kLatest. Should be called before schemas are modified.
+ * 'targetVersion'=newVersion. Should be called before schemas are modified.
*/
static void setTargetUpgradeFrom(OperationContext* opCtx,
- ServerGlobalParams::FeatureCompatibility::Version fromVersion);
+ ServerGlobalParams::FeatureCompatibility::Version fromVersion,
+ ServerGlobalParams::FeatureCompatibility::Version newVersion);
/**
* Records intent to perform a downgrade from the latest version by updating the on-disk feature
diff --git a/src/mongo/db/commands/feature_compatibility_version_parser.cpp b/src/mongo/db/commands/feature_compatibility_version_parser.cpp
index 650557ca644..76fa31fa030 100644
--- a/src/mongo/db/commands/feature_compatibility_version_parser.cpp
+++ b/src/mongo/db/commands/feature_compatibility_version_parser.cpp
@@ -39,22 +39,24 @@
namespace mongo {
+using FeatureCompatibilityParams = ServerGlobalParams::FeatureCompatibility;
+
constexpr StringData FeatureCompatibilityVersionParser::kParameterName;
constexpr StringData FeatureCompatibilityVersionParser::kLastLTS;
constexpr StringData FeatureCompatibilityVersionParser::kLastContinuous;
constexpr StringData FeatureCompatibilityVersionParser::kLatest;
-ServerGlobalParams::FeatureCompatibility::Version FeatureCompatibilityVersionParser::parseVersion(
+FeatureCompatibilityParams::Version FeatureCompatibilityVersionParser::parseVersion(
StringData versionString) {
if (versionString == kLastLTS) {
- return ServerGlobalParams::FeatureCompatibility::kLastLTS;
+ return FeatureCompatibilityParams::kLastLTS;
}
if (versionString == kLastContinuous) {
- return ServerGlobalParams::FeatureCompatibility::kLastContinuous;
+ return FeatureCompatibilityParams::kLastContinuous;
}
if (versionString == kLatest) {
- return ServerGlobalParams::FeatureCompatibility::kLatest;
+ return FeatureCompatibilityParams::kLatest;
}
uasserted(4926900,
str::stream() << "Invalid value for " << kParameterName << "document in "
@@ -66,14 +68,14 @@ ServerGlobalParams::FeatureCompatibility::Version FeatureCompatibilityVersionPar
}
StringData FeatureCompatibilityVersionParser::serializeVersion(
- ServerGlobalParams::FeatureCompatibility::Version version) {
- if (version == ServerGlobalParams::FeatureCompatibility::kLastLTS) {
+ FeatureCompatibilityParams::Version version) {
+ if (version == FeatureCompatibilityParams::kLastLTS) {
return kLastLTS;
}
- if (version == ServerGlobalParams::FeatureCompatibility::kLastContinuous) {
+ if (version == FeatureCompatibilityParams::kLastContinuous) {
return kLastContinuous;
}
- if (version == ServerGlobalParams::FeatureCompatibility::kLatest) {
+ if (version == FeatureCompatibilityParams::kLatest) {
return kLatest;
}
// It is a bug if we hit here.
@@ -82,16 +84,16 @@ StringData FeatureCompatibilityVersionParser::serializeVersion(
}
Status FeatureCompatibilityVersionParser::validatePreviousVersionField(
- ServerGlobalParams::FeatureCompatibility::Version version) {
- if (version == ServerGlobalParams::FeatureCompatibility::kLatest) {
+ FeatureCompatibilityParams::Version version) {
+ if (version == FeatureCompatibilityParams::kLatest) {
return Status::OK();
}
return Status(ErrorCodes::Error(4926901),
"when present, 'previousVersion' field must be the latest binary version");
}
-StatusWith<ServerGlobalParams::FeatureCompatibility::Version>
-FeatureCompatibilityVersionParser::parse(const BSONObj& featureCompatibilityVersionDoc) {
+StatusWith<FeatureCompatibilityParams::Version> FeatureCompatibilityVersionParser::parse(
+ const BSONObj& featureCompatibilityVersionDoc) {
try {
auto fcvDoc = FeatureCompatibilityVersionDocument::parse(
IDLParserErrorContext("FeatureCompatibilityVersionParser"),
@@ -101,8 +103,8 @@ FeatureCompatibilityVersionParser::parse(const BSONObj& featureCompatibilityVers
auto previousVersion = fcvDoc.getPreviousVersion();
// Downgrading FCV.
- if ((version == ServerGlobalParams::FeatureCompatibility::kLastLTS ||
- version == ServerGlobalParams::FeatureCompatibility::kLastContinuous) &&
+ if ((version == FeatureCompatibilityParams::kLastLTS ||
+ version == FeatureCompatibilityParams::kLastContinuous) &&
version == targetVersion) {
// Downgrading FCV must have a "previousVersion" field.
if (!previousVersion) {
@@ -117,12 +119,11 @@ FeatureCompatibilityVersionParser::parse(const BSONObj& featureCompatibilityVers
<< feature_compatibility_version_documentation::kCompatibilityLink
<< ".");
}
- if (version == ServerGlobalParams::FeatureCompatibility::kLastLTS) {
+ if (version == FeatureCompatibilityParams::kLastLTS) {
// Downgrading to last-lts.
- return ServerGlobalParams::FeatureCompatibility::kDowngradingFromLatestToLastLTS;
+ return FeatureCompatibilityParams::kDowngradingFromLatestToLastLTS;
} else {
- return ServerGlobalParams::FeatureCompatibility::
- kDowngradingFromLatestToLastContinuous;
+ return FeatureCompatibilityParams::kDowngradingFromLatestToLastContinuous;
}
}
@@ -142,9 +143,9 @@ FeatureCompatibilityVersionParser::parse(const BSONObj& featureCompatibilityVers
// Upgrading FCV.
if (targetVersion) {
- // For upgrading FCV, "targetVersion" must be kLatest and "version" must be
- // kLastContinuous or kLastLTS.
- if (targetVersion != ServerGlobalParams::FeatureCompatibility::kLatest ||
+ // For upgrading FCV, "targetVersion" must be kLatest or kLastContinuous and "version"
+ // must be kLastContinuous or kLastLTS.
+ if (targetVersion == FeatureCompatibilityParams::kLastLTS ||
version == ServerGlobalParams::FeatureCompatibility::kLatest) {
return Status(ErrorCodes::Error(4926904),
str::stream()
@@ -155,12 +156,20 @@ FeatureCompatibilityVersionParser::parse(const BSONObj& featureCompatibilityVers
<< ".");
}
- if (version == ServerGlobalParams::FeatureCompatibility::kLastLTS) {
- return ServerGlobalParams::FeatureCompatibility::kUpgradingFromLastLTSToLatest;
+ if (version == FeatureCompatibilityParams::kLastLTS) {
+ return targetVersion == FeatureCompatibilityParams::kLastContinuous
+ ? FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous
+ : FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest;
} else {
- invariant(version == ServerGlobalParams::FeatureCompatibility::kLastContinuous);
- return ServerGlobalParams::FeatureCompatibility::
- kUpgradingFromLastContinuousToLatest;
+ uassert(5070601,
+ str::stream()
+ << "Invalid " << kParameterName << " document in "
+ << NamespaceString::kServerConfigurationNamespace.toString() << ": "
+ << featureCompatibilityVersionDoc << ". See "
+ << feature_compatibility_version_documentation::kCompatibilityLink
+ << ".",
+ version == ServerGlobalParams::FeatureCompatibility::kLastContinuous);
+ return FeatureCompatibilityParams::kUpgradingFromLastContinuousToLatest;
}
}
diff --git a/src/mongo/db/commands/feature_compatibility_version_parser.h b/src/mongo/db/commands/feature_compatibility_version_parser.h
index 6c9f9ab4364..d1e90016ab3 100644
--- a/src/mongo/db/commands/feature_compatibility_version_parser.h
+++ b/src/mongo/db/commands/feature_compatibility_version_parser.h
@@ -32,6 +32,7 @@
#include "mongo/db/server_options.h"
namespace mongo {
+using FeatureCompatibilityParams = ServerGlobalParams::FeatureCompatibility;
/**
* Helpers to parse featureCompatibilityVersion document BSON objects into
@@ -51,40 +52,56 @@ public:
static constexpr StringData kLastLTS = kVersion44;
static constexpr StringData kLastContinuous = kVersion44;
static constexpr StringData kLatest = kVersion47;
+ static constexpr StringData kUpgradingFromLastLTSToLatest = kVersionUpgradingFrom44To47;
+ static constexpr StringData kUpgradingFromLastContinuousToLatest = kVersionUpgradingFrom44To47;
+ // kVersionUpgradingFromLastLTSToLastContinuous should assigned kVersionUnset when kLastLTS and
+ // kLastContinuous are equal.
+ static constexpr StringData kVersionUpgradingFromLastLTSToLastContinuous = kVersionUnset;
+ static constexpr StringData kDowngradingFromLatestToLastLTS = kVersionDowngradingFrom47To44;
+ static constexpr StringData kDowngradingFromLatestToLastContinuous =
+ kVersionDowngradingFrom47To44;
- static ServerGlobalParams::FeatureCompatibility::Version parseVersion(StringData versionString);
+ static FeatureCompatibilityParams::Version parseVersion(StringData versionString);
- static StringData serializeVersion(ServerGlobalParams::FeatureCompatibility::Version version);
+ static StringData serializeVersion(FeatureCompatibilityParams::Version version);
- static Status validatePreviousVersionField(
- ServerGlobalParams::FeatureCompatibility::Version version);
+ static Status validatePreviousVersionField(FeatureCompatibilityParams::Version version);
/**
* Parses the featureCompatibilityVersion document from the server configuration collection
* (admin.system.version), and returns the state represented by the combination of the
* targetVersion and version.
*/
- static StatusWith<ServerGlobalParams::FeatureCompatibility::Version> parse(
+ static StatusWith<FeatureCompatibilityParams::Version> parse(
const BSONObj& featureCompatibilityVersionDoc);
/**
* Useful for message logging.
*/
- static StringData toString(ServerGlobalParams::FeatureCompatibility::Version version) {
- switch (version) {
- case ServerGlobalParams::FeatureCompatibility::Version::kUnsetDefault44Behavior:
- return kVersionUnset;
- case ServerGlobalParams::FeatureCompatibility::Version::kFullyDowngradedTo44:
- return kVersion44;
- case ServerGlobalParams::FeatureCompatibility::Version::kUpgradingFrom44To47:
- return kVersionUpgradingFrom44To47;
- case ServerGlobalParams::FeatureCompatibility::Version::kDowngradingFrom47To44:
- return kVersionDowngradingFrom47To44;
- case ServerGlobalParams::FeatureCompatibility::Version::kVersion47:
- return kVersion47;
- default:
- MONGO_UNREACHABLE;
+ static StringData toString(FeatureCompatibilityParams::Version version) {
+ if (version == FeatureCompatibilityParams::Version::kUnsetDefault44Behavior) {
+ return kVersionUnset;
+ } else if (version == FeatureCompatibilityParams::kLastLTS) {
+ return kLastLTS;
+ } else if (version == FeatureCompatibilityParams::kDowngradingFromLatestToLastLTS) {
+ return kDowngradingFromLatestToLastLTS;
+ } else if (version == FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous) {
+ // kUpgradingFromLastLTSToLastContinuous is only a valid FCV state when last-continuous
+ // and last-lts are not equal. Otherwise, it is set to kInvalid.
+ invariant(version != FeatureCompatibilityParams::Version::kInvalid);
+ return kVersionUpgradingFromLastLTSToLastContinuous;
+ } else if (version == FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest) {
+ return kUpgradingFromLastLTSToLatest;
+ } else if (version == FeatureCompatibilityParams::kLastContinuous) {
+ return kLastContinuous;
+ } else if (version == FeatureCompatibilityParams::kDowngradingFromLatestToLastContinuous) {
+ return kDowngradingFromLatestToLastContinuous;
+ } else if (version == FeatureCompatibilityParams::kUpgradingFromLastContinuousToLatest) {
+ return kUpgradingFromLastContinuousToLatest;
+ } else if (version == FeatureCompatibilityParams::kLatest) {
+ return kLatest;
}
+ MONGO_UNREACHABLE;
}
};
diff --git a/src/mongo/db/commands/set_feature_compatibility_version.idl b/src/mongo/db/commands/set_feature_compatibility_version.idl
index b1c7df315d7..793fa587098 100644
--- a/src/mongo/db/commands/set_feature_compatibility_version.idl
+++ b/src/mongo/db/commands/set_feature_compatibility_version.idl
@@ -49,3 +49,8 @@ commands:
downgraded featureCompatibilityVersion."
type: safeBool
optional: true
+ fromConfigServer:
+ description: "A boolean that indicates whether the command is being requested by a
+ config server."
+ type: safeBool
+ optional: true
diff --git a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
index 48b3c04c5b7..0be6e6b0e5f 100644
--- a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
+++ b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
@@ -135,18 +135,44 @@ Status validateDowngradeRequest(FeatureCompatibilityParams::Version actualVersio
}
Status validateUpgradeRequest(FeatureCompatibilityParams::Version actualVersion,
- FeatureCompatibilityParams::Version requestedVersion) {
+ FeatureCompatibilityParams::Version requestedVersion,
+ boost::optional<bool> fromConfigServer) {
+ invariant(actualVersion < requestedVersion);
+
if (actualVersion == FeatureCompatibilityParams::kDowngradingFromLatestToLastLTS ||
actualVersion == FeatureCompatibilityParams::kDowngradingFromLatestToLastContinuous) {
return Status(ErrorCodes::IllegalOperation,
str::stream() << "cannot initiate featureCompatibilityVersion upgrade to "
- << FCVP::kLatest
+ << FCVP::toString(requestedVersion)
<< " while a previous featureCompatibilityVersion downgrade to "
<< FCVP::kLastLTS << " or " << FCVP::kLastContinuous
<< " has not completed. Finish downgrade then upgrade to "
<< FCVP::kLatest);
}
+ if ((actualVersion == FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest &&
+ requestedVersion == FeatureCompatibilityParams::kLastContinuous) ||
+ (actualVersion == FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous &&
+ requestedVersion == FeatureCompatibilityParams::kLatest)) {
+ auto incompleteUpgradeVersionString =
+ actualVersion == FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest
+ ? FCVP::kLatest
+ : FCVP::kLastContinuous;
+ return Status(ErrorCodes::Error(5070602),
+ str::stream()
+ << "cannot initiate featureCompatibilityVersion upgrade to "
+ << FCVP::toString(requestedVersion) << " while a previous upgrade to "
+ << incompleteUpgradeVersionString
+ << " has not yet completed. Finish upgrade then try again.");
+ }
+
+ if (requestedVersion == FeatureCompatibilityParams::kLastContinuous &&
+ !fromConfigServer.get_value_or(false)) {
+ return Status(ErrorCodes::Error(5070603),
+ str::stream() << "cannot initiate featureCompatibilityVersion upgrade from "
+ << FCVP::kLastLTS << " to " << FCVP::kLastContinuous << ".");
+ }
+
return Status::OK();
}
@@ -243,9 +269,9 @@ public:
const auto requestedVersionString = FCVP::serializeVersion(requestedVersion);
FeatureCompatibilityParams::Version actualVersion =
serverGlobalParams.featureCompatibility.getVersion();
-
if (request.getDowngradeOnDiskChanges() &&
- requestedVersion != FeatureCompatibilityParams::kLastContinuous) {
+ (requestedVersion != FeatureCompatibilityParams::kLastContinuous ||
+ actualVersion < requestedVersion)) {
std::stringstream downgradeOnDiskErrorSS;
downgradeOnDiskErrorSS
<< "cannot set featureCompatibilityVersion to " << requestedVersionString
@@ -255,18 +281,19 @@ public:
uasserted(ErrorCodes::IllegalOperation, downgradeOnDiskErrorSS.str());
}
- if (requestedVersion == FeatureCompatibilityParams::kLatest) {
- uassertStatusOK(validateUpgradeRequest(actualVersion, requestedVersion));
- if (actualVersion == FeatureCompatibilityParams::kLatest) {
- // Set the client's last opTime to the system last opTime so no-ops wait for
- // writeConcern.
- repl::ReplClientInfo::forClient(opCtx->getClient())
- .setLastOpToSystemLastOpTime(opCtx);
- return true;
- }
+ if (actualVersion == requestedVersion) {
+ // Set the client's last opTime to the system last opTime so no-ops wait for
+ // writeConcern.
+ repl::ReplClientInfo::forClient(opCtx->getClient()).setLastOpToSystemLastOpTime(opCtx);
+ return true;
+ }
- FeatureCompatibilityVersion::setTargetUpgradeFrom(opCtx, actualVersion);
+ if (actualVersion < requestedVersion) {
+ uassertStatusOK(validateUpgradeRequest(
+ actualVersion, requestedVersion, request.getFromConfigServer()));
+ FeatureCompatibilityVersion::setTargetUpgradeFrom(
+ opCtx, actualVersion, requestedVersion);
{
// Take the global lock in S mode to create a barrier for operations taking the
// global IX or X locks. This ensures that either
@@ -298,19 +325,9 @@ public:
hangWhileUpgrading.pauseWhileSet(opCtx);
FeatureCompatibilityVersion::unsetTargetUpgradeOrDowngrade(opCtx, requestedVersion);
- } else if (requestedVersion == FeatureCompatibilityParams::kLastLTS ||
- requestedVersion == FeatureCompatibilityParams::kLastContinuous) {
+ } else {
uassertStatusOK(validateDowngradeRequest(actualVersion, requestedVersion));
- if (actualVersion == FeatureCompatibilityParams::kLastLTS ||
- actualVersion == FeatureCompatibilityParams::kLastContinuous) {
- // Set the client's last opTime to the system last opTime so no-ops wait for
- // writeConcern.
- repl::ReplClientInfo::forClient(opCtx->getClient())
- .setLastOpToSystemLastOpTime(opCtx);
- return true;
- }
-
auto replCoord = repl::ReplicationCoordinator::get(opCtx);
const bool isReplSet =
replCoord->getReplicationMode() == repl::ReplicationCoordinator::modeReplSet;
diff --git a/src/mongo/db/fcv_op_observer.cpp b/src/mongo/db/fcv_op_observer.cpp
index bb70616821c..73d8b4b23ee 100644
--- a/src/mongo/db/fcv_op_observer.cpp
+++ b/src/mongo/db/fcv_op_observer.cpp
@@ -52,6 +52,11 @@ using FeatureCompatibilityParams = ServerGlobalParams::FeatureCompatibility;
void FcvOpObserver::_setVersion(OperationContext* opCtx,
ServerGlobalParams::FeatureCompatibility::Version newVersion) {
+ boost::optional<FeatureCompatibilityParams::Version> prevVersion;
+
+ if (serverGlobalParams.featureCompatibility.isVersionInitialized()) {
+ prevVersion = serverGlobalParams.featureCompatibility.getVersion();
+ }
serverGlobalParams.mutableFeatureCompatibility.setVersion(newVersion);
FeatureCompatibilityVersion::updateMinWireVersion();
@@ -92,9 +97,12 @@ void FcvOpObserver::_setVersion(OperationContext* opCtx,
// (Generic FCV reference): This FCV check should exist across LTS binary versions.
const auto shouldIncrementTopologyVersion =
newVersion == FeatureCompatibilityParams::kLastLTS ||
- newVersion == FeatureCompatibilityParams::kLastContinuous ||
+ (prevVersion &&
+ prevVersion.get() == FeatureCompatibilityParams::kDowngradingFromLatestToLastContinuous) ||
newVersion == FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest ||
- newVersion == FeatureCompatibilityParams::kUpgradingFromLastContinuousToLatest;
+ newVersion == FeatureCompatibilityParams::kUpgradingFromLastContinuousToLatest ||
+ newVersion == FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous;
+
if (isReplSet && shouldIncrementTopologyVersion) {
replCoordinator->incrementTopologyVersion();
}
diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript
index 8b7b0e82f39..31afa9701a4 100644
--- a/src/mongo/db/s/SConscript
+++ b/src/mongo/db/s/SConscript
@@ -535,6 +535,7 @@ env.CppUnitTest(
],
LIBDEPS=[
'$BUILD_DIR/mongo/db/auth/authmocks',
+ '$BUILD_DIR/mongo/db/commands/set_feature_compatibility_version_idl',
'$BUILD_DIR/mongo/db/pipeline/document_source_mock',
'$BUILD_DIR/mongo/db/read_write_concern_defaults_mock',
'$BUILD_DIR/mongo/db/repl/replication_info',
diff --git a/src/mongo/db/s/config/sharding_catalog_manager_add_shard_test.cpp b/src/mongo/db/s/config/sharding_catalog_manager_add_shard_test.cpp
index 08c2dced011..777b23622ee 100644
--- a/src/mongo/db/s/config/sharding_catalog_manager_add_shard_test.cpp
+++ b/src/mongo/db/s/config/sharding_catalog_manager_add_shard_test.cpp
@@ -37,6 +37,7 @@
#include "mongo/client/remote_command_targeter_factory_mock.h"
#include "mongo/client/remote_command_targeter_mock.h"
#include "mongo/db/commands.h"
+#include "mongo/db/commands/set_feature_compatibility_version_gen.h"
#include "mongo/db/ops/write_ops.h"
#include "mongo/db/repl/replication_coordinator_mock.h"
#include "mongo/db/s/add_shard_cmd_gen.h"
@@ -134,13 +135,16 @@ protected:
void expectSetFeatureCompatibilityVersion(const HostAndPort& target,
StatusWith<BSONObj> response,
BSONObj writeConcern) {
+ // (Generic FCV reference): This FCV reference should exist across LTS binary versions.
+ SetFeatureCompatibilityVersion fcvCmd(ServerGlobalParams::FeatureCompatibility::kLatest);
+ fcvCmd.setFromConfigServer(true);
+ fcvCmd.setDbName(NamespaceString::kAdminDb);
+ const auto setFcvObj = fcvCmd.toBSON(BSON("writeConcern" << writeConcern));
+
onCommandForAddShard([&, target, response](const RemoteCommandRequest& request) {
ASSERT_EQ(request.target, target);
ASSERT_EQ(request.dbname, "admin");
- ASSERT_BSONOBJ_EQ(request.cmdObj,
- BSON("setFeatureCompatibilityVersion"
- << "4.7"
- << "writeConcern" << writeConcern));
+ ASSERT_BSONOBJ_EQ(request.cmdObj, setFcvObj);
return response;
});
diff --git a/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp b/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp
index f03ee603838..d10ba0288d3 100644
--- a/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp
+++ b/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp
@@ -84,6 +84,7 @@ using CallbackHandle = executor::TaskExecutor::CallbackHandle;
using CallbackArgs = executor::TaskExecutor::CallbackArgs;
using RemoteCommandCallbackArgs = executor::TaskExecutor::RemoteCommandCallbackArgs;
using RemoteCommandCallbackFn = executor::TaskExecutor::RemoteCommandCallbackFn;
+using FeatureCompatibilityParams = ServerGlobalParams::FeatureCompatibility;
const ReadPreferenceSetting kConfigReadSelector(ReadPreference::Nearest, TagSet{});
@@ -338,23 +339,24 @@ StatusWith<ShardType> ShardingCatalogManager::_validateHostAsShard(
<< "field when attempting to add "
<< connectionString.toString() << " as a shard");
}
+ const auto currentFcv = serverGlobalParams.featureCompatibility.getVersion();
// (Generic FCV reference): These FCV checks should exist across LTS binary versions.
- if (serverGlobalParams.featureCompatibility.isGreaterThanOrEqualTo(
- ServerGlobalParams::FeatureCompatibility::kLatest) ||
- serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
- // If the cluster's FCV is kLatest, or upgrading to / downgrading from, the node being added
- // must be a version kLatest binary.
+ if (currentFcv == FeatureCompatibilityParams::kLatest ||
+ currentFcv == FeatureCompatibilityParams::kDowngradingFromLatestToLastContinuous ||
+ currentFcv == FeatureCompatibilityParams::kDowngradingFromLatestToLastLTS ||
+ currentFcv == FeatureCompatibilityParams::kUpgradingFromLastContinuousToLatest ||
+ currentFcv == FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest) {
+ // If the cluster's FCV is kLatest, or upgrading to / downgrading from kLatest, the node
+ // being added must be a version kLatest binary.
invariant(maxWireVersion == WireVersion::LATEST_WIRE_VERSION);
- } else if (serverGlobalParams.featureCompatibility.isGreaterThanOrEqualTo(
- ServerGlobalParams::FeatureCompatibility::kLastContinuous)) {
- // If we are using the kLastContinuous FCV, the node being added must be of the
- // last-continuous or latest binary version.
+ } else if (currentFcv == FeatureCompatibilityParams::kLastContinuous ||
+ currentFcv == FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous) {
+ // If we are using the kLastContinuous or upgrading to kLastContinuous FCV, the node being
+ // added must be of the last-continuous or latest binary version.
invariant(maxWireVersion >= WireVersion::LAST_CONT_WIRE_VERSION);
} else {
- // If we are using the kLastLTS FCV, the node being added must be of the last-lts or latest
- // binary version.
- invariant(maxWireVersion == WireVersion::LAST_LTS_WIRE_VERSION ||
- maxWireVersion == WireVersion::LATEST_WIRE_VERSION);
+ // (Generic FCV reference): These FCV checks should exist across LTS binary versions.
+ invariant(currentFcv == FeatureCompatibilityParams::kLastLTS);
}
// Check whether there is a master. If there isn't, the replica set may not have been
@@ -656,32 +658,49 @@ StatusWith<std::string> ShardingCatalogManager::addShard(
invariant(!opCtx->lockState()->isLocked());
Lock::SharedLock lk(opCtx->lockState(), FeatureCompatibilityVersion::fcvLock);
- BSONObjBuilder setFCVBuilder;
- // (Generic FCV reference): These FCV checks should exist across LTS binary versions.
- switch (serverGlobalParams.featureCompatibility.getVersion()) {
- case ServerGlobalParams::FeatureCompatibility::kLatest:
- case ServerGlobalParams::FeatureCompatibility::Version::kUpgradingFrom44To47: {
- SetFeatureCompatibilityVersion setLatestCmd(
- ServerGlobalParams::FeatureCompatibility::kLatest);
- // The serialize function generated by IDL requires the DB name to be set.
- setLatestCmd.setDbName(NamespaceString::kAdminDb);
- setLatestCmd.serialize({}, &setFCVBuilder);
- break;
- }
- default:
+ // Get the target version that the newly added shard should be set to.
+ const FeatureCompatibilityParams::Version setVersion = [] {
+ const auto currentFcv = serverGlobalParams.featureCompatibility.getVersion();
+ // (Generic FCV reference): These FCV checks should exist across LTS binary versions.
+ if (currentFcv == FeatureCompatibilityParams::kLatest ||
+ currentFcv == FeatureCompatibilityParams::kUpgradingFromLastContinuousToLatest ||
+ currentFcv == FeatureCompatibilityParams::kUpgradingFromLastLTSToLatest) {
+ return FeatureCompatibilityParams::kLatest;
+ } else if (currentFcv == FeatureCompatibilityParams::kLastContinuous ||
+ currentFcv ==
+ FeatureCompatibilityParams::kDowngradingFromLatestToLastContinuous ||
+ currentFcv ==
+ FeatureCompatibilityParams::kUpgradingFromLastLTSToLastContinuous) {
+ // (Generic FCV reference): These FCV checks should exist across LTS binary
+ // versions.
+ return FeatureCompatibilityParams::kLastContinuous;
+ } else {
// (Generic FCV reference): This FCV reference should exist across LTS binary
// versions.
- SetFeatureCompatibilityVersion setLastLTSCmd(
- ServerGlobalParams::FeatureCompatibility::kLastLTS);
- // The serialize function generated by IDL requires the DB name to be set.
- setLastLTSCmd.setDbName(NamespaceString::kAdminDb);
- setLastLTSCmd.serialize({}, &setFCVBuilder);
- break;
+ invariant(currentFcv ==
+ FeatureCompatibilityParams::kDowngradingFromLatestToLastLTS ||
+ currentFcv == FeatureCompatibilityParams::kLastLTS);
+ return FeatureCompatibilityParams::kLastLTS;
+ }
+ }();
+
+ SetFeatureCompatibilityVersion setFcvCmd(setVersion);
+ setFcvCmd.setDbName(NamespaceString::kAdminDb);
+ // TODO (SERVER-50954): Remove this FCV check once 4.4 is no longer the last LTS
+ // version.
+ if (serverGlobalParams.featureCompatibility.isGreaterThanOrEqualTo(
+ FeatureCompatibilityParams::Version::kVersion47)) {
+ // fromConfigServer is a new parameter added to 4.8 with intention to be backported
+ // to 4.7.
+ setFcvCmd.setFromConfigServer(true);
}
- setFCVBuilder.append(WriteConcernOptions::kWriteConcernField,
- opCtx->getWriteConcern().toBSON());
- auto versionResponse = _runCommandForAddShard(
- opCtx, targeter.get(), NamespaceString::kAdminDb, setFCVBuilder.obj());
+
+ auto versionResponse =
+ _runCommandForAddShard(opCtx,
+ targeter.get(),
+ NamespaceString::kAdminDb,
+ setFcvCmd.toBSON(BSON(WriteConcernOptions::kWriteConcernField
+ << opCtx->getWriteConcern().toBSON())));
if (!versionResponse.isOK()) {
return versionResponse.getStatus();
}
diff --git a/src/mongo/db/server_options.h b/src/mongo/db/server_options.h
index dcdc09967bb..ae3a87ec5e1 100644
--- a/src/mongo/db/server_options.h
+++ b/src/mongo/db/server_options.h
@@ -193,11 +193,12 @@ struct ServerGlobalParams {
// The order of these enums matter, higher upgrades having higher values, so that
// features can be active or inactive if the version is higher than some minimum or
// lower than some maximum, respectively.
- kUnsetDefault44Behavior = 0,
- kFullyDowngradedTo44 = 1,
- kDowngradingFrom47To44 = 2,
- kUpgradingFrom44To47 = 3,
- kVersion47 = 4,
+ kInvalid = 0,
+ kUnsetDefault44Behavior = 1,
+ kFullyDowngradedTo44 = 2,
+ kDowngradingFrom47To44 = 3,
+ kUpgradingFrom44To47 = 4,
+ kVersion47 = 5,
};
// These constants should only be used for generic FCV references. Generic references are
@@ -215,6 +216,10 @@ struct ServerGlobalParams {
static constexpr Version kDowngradingFromLatestToLastLTS = Version::kDowngradingFrom47To44;
static constexpr Version kDowngradingFromLatestToLastContinuous =
Version::kDowngradingFrom47To44;
+ // kUpgradingFromLastLTSToLastContinuous is only ever set to a valid FCV when
+ // kLastLTS and kLastContinuous are not equal. Otherwise, this value should be set to
+ // kInvalid.
+ static constexpr Version kUpgradingFromLastLTSToLastContinuous = Version::kInvalid;
/**
* On startup, the featureCompatibilityVersion may not have been explicitly set yet. This