1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
// Runner for validateCollections that runs full validation on all collections when loaded into
// the mongo shell.
'use strict';
(function() {
load('jstests/libs/discover_topology.js'); // For Topology and DiscoverTopology.
load('jstests/hooks/validate_collections.js'); // For CollectionValidator.
assert.eq(typeof db, 'object', 'Invalid `db` object, is the shell connected to a mongod?');
const topology = DiscoverTopology.findConnectedNodes(db.getMongo());
const hostList = [];
let configPrimary;
if (topology.type === Topology.kStandalone) {
hostList.push(topology.mongod);
} else if (topology.type === Topology.kReplicaSet) {
hostList.push(...topology.nodes);
} else if (topology.type === Topology.kShardedCluster) {
hostList.push(...topology.configsvr.nodes);
for (let shardName of Object.keys(topology.shards)) {
const shard = topology.shards[shardName];
if (shard.type === Topology.kStandalone) {
hostList.push(shard.mongod);
} else if (shard.type === Topology.kReplicaSet) {
hostList.push(...shard.nodes);
} else {
throw new Error('Unrecognized topology format: ' + tojson(topology));
}
}
configPrimary = new Mongo(topology.configsvr.primary);
} else {
throw new Error('Unrecognized topology format: ' + tojson(topology));
}
// Set the fail point on config server to allow FCV downgrade even in the presence of a
// collection sharded on a compound hashed key.
if (configPrimary) {
assert.commandWorked(configPrimary.getDB('admin').runCommand(
{configureFailPoint: 'allowFCVDowngradeWithCompoundHashedShardKey', mode: 'alwaysOn'}));
}
const adminDB = db.getSiblingDB('admin');
const requiredFCV = jsTest.options().forceValidationWithFeatureCompatibilityVersion;
let originalFCV;
let originalTransactionLifetimeLimitSeconds;
let skipFCV = false;
if (requiredFCV) {
// Can't set the FCV to 4.2 while having long collection names present.
adminDB.runCommand("listDatabases").databases.forEach(function(d) {
const mdb = adminDB.getSiblingDB(d.name);
try {
mdb.getCollectionInfos().forEach(function(c) {
const namespace = d.name + "." + c.name;
const namespaceLenBytes = encodeURIComponent(namespace).length;
if (namespaceLenBytes > 120) {
skipFCV = true;
}
});
} catch (e) {
skipFCV = true;
}
});
// Running the setFeatureCompatibilityVersion command may implicitly involve running a
// multi-statement transaction. We temporarily raise the transactionLifetimeLimitSeconds to be
// 24 hours to avoid spurious failures from it having been set to a lower value.
originalTransactionLifetimeLimitSeconds = hostList.map(hostStr => {
const conn = new Mongo(hostStr);
const res = assert.commandWorked(
conn.adminCommand({setParameter: 1, transactionLifetimeLimitSeconds: 24 * 60 * 60}));
return {conn, originalValue: res.was};
});
originalFCV = adminDB.system.version.findOne({_id: 'featureCompatibilityVersion'});
if (originalFCV.targetVersion) {
// If a previous FCV upgrade or downgrade was interrupted, then we run the
// setFeatureCompatibilityVersion command to complete it before attempting to set the
// feature compatibility version to 'requiredFCV'.
assert.commandWorked(
adminDB.runCommand({setFeatureCompatibilityVersion: originalFCV.targetVersion}));
checkFCV(adminDB, originalFCV.targetVersion);
}
// Now that we are certain that an upgrade or downgrade of the FCV is not in progress, ensure
// the 'requiredFCV' is set.
if (!skipFCV) {
assert.commandWorked(adminDB.runCommand({setFeatureCompatibilityVersion: requiredFCV}));
}
}
new CollectionValidator().validateNodes(hostList, skipFCV);
if (originalFCV && originalFCV.version !== requiredFCV && !skipFCV) {
assert.commandWorked(adminDB.runCommand({setFeatureCompatibilityVersion: originalFCV.version}));
}
if (originalTransactionLifetimeLimitSeconds) {
for (let {conn, originalValue} of originalTransactionLifetimeLimitSeconds) {
assert.commandWorked(
conn.adminCommand({setParameter: 1, transactionLifetimeLimitSeconds: originalValue}));
}
}
// Disable the failpoint that was set earlier on sharded clusters.
if (configPrimary) {
assert.commandWorked(configPrimary.getDB('admin').runCommand(
{configureFailPoint: 'allowFCVDowngradeWithCompoundHashedShardKey', mode: 'off'}));
}
})();
|