summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHuayu Ouyang <huayu.ouyang@mongodb.com>2021-12-13 17:55:35 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-05 22:44:14 +0000
commit71f035d8baf7d7827ad52981a81ac78951210db4 (patch)
tree285f7d9a14fdef00c6a78b25e75b89fb0ac75cec
parent60af56dfe1a17c60bbd628163fda0a161105b6c0 (diff)
downloadmongo-71f035d8baf7d7827ad52981a81ac78951210db4.tar.gz
SERVER-61005 rs.initiate() fails with "Invariant failure" under specific startup options
(cherry picked from commit 684d193982c2b53821f74c86cce76d88e90c5b15)
-rw-r--r--buildscripts/resmokeconfig/suites/replica_sets_auth.yml1
-rw-r--r--jstests/replsets/replsetinitiate_works_with_keyfile_profile_verbose_options.js23
-rw-r--r--src/mongo/db/commands/feature_compatibility_version.cpp13
-rw-r--r--src/mongo/db/commands/feature_compatibility_version.h12
-rw-r--r--src/mongo/db/repl/README.md13
5 files changed, 45 insertions, 17 deletions
diff --git a/buildscripts/resmokeconfig/suites/replica_sets_auth.yml b/buildscripts/resmokeconfig/suites/replica_sets_auth.yml
index bb63cc70d37..bb670e20e7d 100644
--- a/buildscripts/resmokeconfig/suites/replica_sets_auth.yml
+++ b/buildscripts/resmokeconfig/suites/replica_sets_auth.yml
@@ -21,6 +21,7 @@ selector:
- jstests/replsets/tenant_migration_concurrent_writes_on_donor.js
- jstests/replsets/tenant_migration_external_cluster_validation.js
- jstests/replsets/user_management_wc.js
+ - jstests/replsets/replsetinitiate_works_with_keyfile_profile_verbose_options.js
# Also skip tests that require a Thread, because Threads don't inherit credentials.
- jstests/replsets/interrupted_batch_insert.js
- jstests/replsets/transactions_reaped_with_tickets_exhausted.js
diff --git a/jstests/replsets/replsetinitiate_works_with_keyfile_profile_verbose_options.js b/jstests/replsets/replsetinitiate_works_with_keyfile_profile_verbose_options.js
new file mode 100644
index 00000000000..daf734a9d30
--- /dev/null
+++ b/jstests/replsets/replsetinitiate_works_with_keyfile_profile_verbose_options.js
@@ -0,0 +1,23 @@
+/**
+ * Tests that a standalone node started with --verbose, --profile, and --keyfile can
+ * successfully run the replSetInitiate command.
+ */
+(function() {
+let options = {verbose: 1, profile: 1, keyFile: 'jstests/libs/key1', replSet: "rs0", port: 27017};
+
+const conn = MongoRunner.runMongod(options);
+
+assert.commandWorked(conn.getDB('admin').runCommand(
+ {replSetInitiate: {"_id": "rs0", "members": [{"_id": 0, "host": "127.0.0.1:27017"}]}}));
+
+assert.soon(function() {
+ const res = assert.commandWorked(conn.adminCommand({hello: 1}));
+ return res.isWritablePrimary;
+});
+
+const admin = conn.getDB('admin');
+admin.createUser({user: 'foo', pwd: 'bar', roles: jsTest.adminUserRoles});
+assert(admin.auth({user: 'foo', pwd: 'bar'}));
+assert.commandWorked(admin.test.insert({x: 1}));
+MongoRunner.stopMongod(conn);
+})();
diff --git a/src/mongo/db/commands/feature_compatibility_version.cpp b/src/mongo/db/commands/feature_compatibility_version.cpp
index 70a125c59df..9080a5e1b82 100644
--- a/src/mongo/db/commands/feature_compatibility_version.cpp
+++ b/src/mongo/db/commands/feature_compatibility_version.cpp
@@ -346,7 +346,7 @@ void FeatureCompatibilityVersion::updateFeatureCompatibilityVersionDocument(
void FeatureCompatibilityVersion::setIfCleanStartup(OperationContext* opCtx,
repl::StorageInterface* storageInterface) {
- if (!isCleanStartUp())
+ if (!hasNoReplicatedCollections(opCtx))
return;
// If the server was not started with --shardsvr, the default featureCompatibilityVersion on
@@ -382,13 +382,16 @@ void FeatureCompatibilityVersion::setIfCleanStartup(OperationContext* opCtx,
// replicated.
}
-bool FeatureCompatibilityVersion::isCleanStartUp() {
+bool FeatureCompatibilityVersion::hasNoReplicatedCollections(OperationContext* opCtx) {
StorageEngine* storageEngine = getGlobalServiceContext()->getStorageEngine();
std::vector<std::string> dbNames = storageEngine->listDatabases();
-
+ auto catalog = CollectionCatalog::get(opCtx);
for (auto&& dbName : dbNames) {
- if (dbName != "local") {
- return false;
+ Lock::DBLock dbLock(opCtx, dbName, MODE_S);
+ for (auto&& collNss : catalog->getAllCollectionNamesFromDb(opCtx, dbName)) {
+ if (collNss.isReplicated()) {
+ return false;
+ }
}
}
return true;
diff --git a/src/mongo/db/commands/feature_compatibility_version.h b/src/mongo/db/commands/feature_compatibility_version.h
index 24c7223fc20..cbdd5afdb51 100644
--- a/src/mongo/db/commands/feature_compatibility_version.h
+++ b/src/mongo/db/commands/feature_compatibility_version.h
@@ -84,18 +84,18 @@ public:
bool setTargetVersion);
/**
- * If there are no non-local databases, store the featureCompatibilityVersion document. If we
- * are not running with --shardsvr, set the version to be the upgrade value. If we are running
- * with --shardsvr, set the version to be the downgrade value.
+ * If we are in clean startup (the server has no replicated collections), store the
+ * featureCompatibilityVersion document. If we are not running with --shardsvr, set the version
+ * to be the upgrade value. If we are running with --shardsvr, set the version to be the
+ * downgrade value.
*/
static void setIfCleanStartup(OperationContext* opCtx,
repl::StorageInterface* storageInterface);
/**
- * Returns true if the server is on a clean startup. A clean startup means there are no
- * databases on disk besides the local database.
+ * Returns true if the server has no replicated collections.
*/
- static bool isCleanStartUp();
+ static bool hasNoReplicatedCollections(OperationContext* opCtx);
/**
* Sets the server's outgoing and incomingInternalClient minWireVersions according to the
diff --git a/src/mongo/db/repl/README.md b/src/mongo/db/repl/README.md
index d619d64957d..bcf8e14cec0 100644
--- a/src/mongo/db/repl/README.md
+++ b/src/mongo/db/repl/README.md
@@ -1883,12 +1883,13 @@ This document is present in every mongod in the cluster and is replicated to oth
replica set whenever it is updated via writes to the `admin.system.version` collection. The FCV
document is also present on standalone nodes.
-On a clean startup (the server currently has no non-local databases), the server will create the FCV
-document for the first time. If it is running as a shard server (with the `--shardsvr option`), the
-server will set the FCV to be the last LTS version. This is to ensure compatibility when adding the
-shard to a downgraded version cluster. The config server will run `setFeatureCompatibilityVersion`
-on the shard to match the clusters FCV as part of `addShard`. If the server is not running as a
-shard server, then the server will set its FCV to the latest version by default.
+On a clean startup (the server currently has no replicated collections), the server will create the
+FCV document for the first time. If it is running as a shard server (with the `--shardsvr option`),
+the server will set the FCV to be the last LTS version. This is to ensure compatibility when adding
+the shard to a downgraded version cluster. The config server will run
+`setFeatureCompatibilityVersion`on the shard to match the clusters FCV as part of `addShard`. If the
+server is not running as a shard server, then the server will set its FCV to the latest version by
+default.
As part of a startup with an existing FCV document, the server caches an in-memory value of the FCV
from disk. The `FcvOpObserver` keeps this in-memory value in sync with the on-disk FCV document