diff options
Diffstat (limited to 'jstests/replsets/rslib.js')
-rw-r--r-- | jstests/replsets/rslib.js | 774 |
1 files changed, 383 insertions, 391 deletions
diff --git a/jstests/replsets/rslib.js b/jstests/replsets/rslib.js index 2423baea807..209ed8172e1 100644 --- a/jstests/replsets/rslib.js +++ b/jstests/replsets/rslib.js @@ -16,449 +16,441 @@ var getLastOpTime; var setLogVerbosity; (function() { - "use strict"; - load("jstests/libs/write_concern_util.js"); - - var count = 0; - var w = 0; - - /** - * A wrapper around `replSetSyncFrom` to ensure that the desired sync source is ahead of the - * syncing node so that the syncing node can choose to sync from the desired sync source. - * It first stops replication on the syncing node so that it can do a write on the desired - * sync source and make sure it's ahead. When replication is restarted, the desired sync - * source will be a valid sync source for the syncing node. - */ - syncFrom = function(syncingNode, desiredSyncSource, rst) { - jsTestLog("Forcing " + syncingNode.name + " to sync from " + desiredSyncSource.name); - - // Ensure that 'desiredSyncSource' doesn't already have the dummy write sitting around from - // a previous syncFrom attempt. - var dummyName = "dummyForSyncFrom"; - rst.getPrimary().getDB(dummyName).getCollection(dummyName).drop(); - assert.soonNoExcept(function() { - return desiredSyncSource.getDB(dummyName).getCollection(dummyName).findOne() == null; - }); - - stopServerReplication(syncingNode); - - assert.writeOK(rst.getPrimary().getDB(dummyName).getCollection(dummyName).insert({a: 1})); - // Wait for 'desiredSyncSource' to get the dummy write we just did so we know it's - // definitely ahead of 'syncingNode' before we call replSetSyncFrom. - assert.soonNoExcept(function() { - return desiredSyncSource.getDB(dummyName).getCollection(dummyName).findOne({a: 1}); - }); - - assert.commandWorked(syncingNode.adminCommand({replSetSyncFrom: desiredSyncSource.name})); - restartServerReplication(syncingNode); - rst.awaitSyncSource(syncingNode, desiredSyncSource); - }; - - /** - * Calls a function 'f' once a second until it returns true. Throws an exception once 'f' has - * been called more than 'retries' times without returning true. If 'retries' is not given, - * it defaults to 200. 'retries' must be an integer greater than or equal to zero. - */ - wait = function(f, msg, retries) { - w++; - var n = 0; - var default_retries = 200; - var delay_interval_ms = 1000; - - // Set default value if 'retries' was not given. - if (retries === undefined) { - retries = default_retries; +"use strict"; +load("jstests/libs/write_concern_util.js"); + +var count = 0; +var w = 0; + +/** + * A wrapper around `replSetSyncFrom` to ensure that the desired sync source is ahead of the + * syncing node so that the syncing node can choose to sync from the desired sync source. + * It first stops replication on the syncing node so that it can do a write on the desired + * sync source and make sure it's ahead. When replication is restarted, the desired sync + * source will be a valid sync source for the syncing node. + */ +syncFrom = function(syncingNode, desiredSyncSource, rst) { + jsTestLog("Forcing " + syncingNode.name + " to sync from " + desiredSyncSource.name); + + // Ensure that 'desiredSyncSource' doesn't already have the dummy write sitting around from + // a previous syncFrom attempt. + var dummyName = "dummyForSyncFrom"; + rst.getPrimary().getDB(dummyName).getCollection(dummyName).drop(); + assert.soonNoExcept(function() { + return desiredSyncSource.getDB(dummyName).getCollection(dummyName).findOne() == null; + }); + + stopServerReplication(syncingNode); + + assert.writeOK(rst.getPrimary().getDB(dummyName).getCollection(dummyName).insert({a: 1})); + // Wait for 'desiredSyncSource' to get the dummy write we just did so we know it's + // definitely ahead of 'syncingNode' before we call replSetSyncFrom. + assert.soonNoExcept(function() { + return desiredSyncSource.getDB(dummyName).getCollection(dummyName).findOne({a: 1}); + }); + + assert.commandWorked(syncingNode.adminCommand({replSetSyncFrom: desiredSyncSource.name})); + restartServerReplication(syncingNode); + rst.awaitSyncSource(syncingNode, desiredSyncSource); +}; + +/** + * Calls a function 'f' once a second until it returns true. Throws an exception once 'f' has + * been called more than 'retries' times without returning true. If 'retries' is not given, + * it defaults to 200. 'retries' must be an integer greater than or equal to zero. + */ +wait = function(f, msg, retries) { + w++; + var n = 0; + var default_retries = 200; + var delay_interval_ms = 1000; + + // Set default value if 'retries' was not given. + if (retries === undefined) { + retries = default_retries; + } + while (!f()) { + if (n % 4 == 0) { + print("Waiting " + w); } - while (!f()) { - if (n % 4 == 0) { - print("Waiting " + w); - } - if (++n == 4) { - print("" + f); - } - if (n >= retries) { - throw new Error('Tried ' + retries + ' times, giving up on ' + msg); - } - sleep(delay_interval_ms); + if (++n == 4) { + print("" + f); } - }; - - /** - * Use this to do something once every 4 iterations. - * - * <pre> - * for (i=0; i<1000; i++) { - * occasionally(function() { print("4 more iterations"); }); - * } - * </pre> - */ - occasionally = function(f, n) { - var interval = n || 4; - if (count % interval == 0) { - f(); + if (n >= retries) { + throw new Error('Tried ' + retries + ' times, giving up on ' + msg); } - count++; - }; + sleep(delay_interval_ms); + } +}; + +/** + * Use this to do something once every 4 iterations. + * + * <pre> + * for (i=0; i<1000; i++) { + * occasionally(function() { print("4 more iterations"); }); + * } + * </pre> + */ +occasionally = function(f, n) { + var interval = n || 4; + if (count % interval == 0) { + f(); + } + count++; +}; + +/** + * Attempt to re-establish and re-authenticate a Mongo connection if it was dropped, with + * multiple retries. + * + * Returns upon successful re-connnection. If connection cannot be established after 200 + * retries, throws an exception. + * + * @param conn - a Mongo connection object or DB object. + */ +reconnect = function(conn) { + var retries = 200; + wait(function() { + var db; + try { + // Make this work with either dbs or connections. + if (typeof (conn.getDB) == "function") { + db = conn.getDB('foo'); + } else { + db = conn; + } - /** - * Attempt to re-establish and re-authenticate a Mongo connection if it was dropped, with - * multiple retries. - * - * Returns upon successful re-connnection. If connection cannot be established after 200 - * retries, throws an exception. - * - * @param conn - a Mongo connection object or DB object. - */ - reconnect = function(conn) { - var retries = 200; - wait(function() { - var db; - try { - // Make this work with either dbs or connections. - if (typeof(conn.getDB) == "function") { - db = conn.getDB('foo'); - } else { - db = conn; - } + // Run a simple command to re-establish connection. + db.bar.stats(); - // Run a simple command to re-establish connection. - db.bar.stats(); + // SERVER-4241: Shell connections don't re-authenticate on reconnect. + if (jsTest.options().keyFile) { + return jsTest.authenticate(db.getMongo()); + } + return true; + } catch (e) { + print(e); + return false; + } + }, retries); +}; + +getLatestOp = function(server) { + server.getDB("admin").getMongo().setSlaveOk(); + var log = server.getDB("local")['oplog.rs']; + var cursor = log.find({}).sort({'$natural': -1}).limit(1); + if (cursor.hasNext()) { + return cursor.next(); + } + return null; +}; + +getLeastRecentOp = function({server, readConcern}) { + server.getDB("admin").getMongo().setSlaveOk(); + const oplog = server.getDB("local").oplog.rs; + const cursor = oplog.find().sort({$natural: 1}).limit(1).readConcern(readConcern); + if (cursor.hasNext()) { + return cursor.next(); + } + return null; +}; + +waitForAllMembers = function(master, timeout) { + var failCount = 0; + + assert.soon(function() { + var state = null; + try { + state = master.getSisterDB("admin").runCommand({replSetGetStatus: 1}); + failCount = 0; + } catch (e) { + // Connection can get reset on replica set failover causing a socket exception + print("Calling replSetGetStatus failed"); + print(e); + return false; + } + occasionally(function() { + printjson(state); + }, 10); - // SERVER-4241: Shell connections don't re-authenticate on reconnect. - if (jsTest.options().keyFile) { - return jsTest.authenticate(db.getMongo()); - } - return true; - } catch (e) { - print(e); + for (var m in state.members) { + if (state.members[m].state != 1 && // PRIMARY + state.members[m].state != 2 && // SECONDARY + state.members[m].state != 7) { // ARBITER return false; } - }, retries); - }; + } + printjson(state); + return true; + }, "not all members ready", timeout || 10 * 60 * 1000); + + print("All members are now in state PRIMARY, SECONDARY, or ARBITER"); +}; - getLatestOp = function(server) { - server.getDB("admin").getMongo().setSlaveOk(); - var log = server.getDB("local")['oplog.rs']; - var cursor = log.find({}).sort({'$natural': -1}).limit(1); - if (cursor.hasNext()) { - return cursor.next(); +reconfig = function(rs, config, force) { + "use strict"; + var admin = rs.getPrimary().getDB("admin"); + var e; + var master; + try { + var reconfigCommand = {replSetReconfig: rs._updateConfigIfNotDurable(config), force: force}; + var res = admin.runCommand(reconfigCommand); + + // Retry reconfig if quorum check failed because not enough voting nodes responded. + if (!res.ok && res.code === ErrorCodes.NodeNotFound) { + print("Replset reconfig failed because quorum check failed. Retry reconfig once. " + + "Error: " + tojson(res)); + res = admin.runCommand(reconfigCommand); } - return null; - }; - getLeastRecentOp = function({server, readConcern}) { - server.getDB("admin").getMongo().setSlaveOk(); - const oplog = server.getDB("local").oplog.rs; - const cursor = oplog.find().sort({$natural: 1}).limit(1).readConcern(readConcern); - if (cursor.hasNext()) { - return cursor.next(); + assert.commandWorked(res); + } catch (e) { + if (!isNetworkError(e)) { + throw e; } - return null; - }; + print("Calling replSetReconfig failed. " + tojson(e)); + } - waitForAllMembers = function(master, timeout) { - var failCount = 0; + var master = rs.getPrimary().getDB("admin"); + waitForAllMembers(master); - assert.soon(function() { - var state = null; + return master; +}; + +awaitOpTime = function(catchingUpNode, latestOpTimeNode) { + var ts, ex, opTime; + assert.soon( + function() { try { - state = master.getSisterDB("admin").runCommand({replSetGetStatus: 1}); - failCount = 0; - } catch (e) { - // Connection can get reset on replica set failover causing a socket exception - print("Calling replSetGetStatus failed"); - print(e); - return false; - } - occasionally(function() { - printjson(state); - }, 10); - - for (var m in state.members) { - if (state.members[m].state != 1 && // PRIMARY - state.members[m].state != 2 && // SECONDARY - state.members[m].state != 7) { // ARBITER - return false; + // The following statement extracts the timestamp field from the most recent + // element of + // the oplog, and stores it in "ts". + ts = getLatestOp(catchingUpNode).ts; + opTime = getLatestOp(latestOpTimeNode).ts; + if ((ts.t == opTime.t) && (ts.i == opTime.i)) { + return true; } + ex = null; + return false; + } catch (ex) { + return false; } - printjson(state); - return true; - }, "not all members ready", timeout || 10 * 60 * 1000); - - print("All members are now in state PRIMARY, SECONDARY, or ARBITER"); - }; - - reconfig = function(rs, config, force) { - "use strict"; - var admin = rs.getPrimary().getDB("admin"); - var e; - var master; - try { - var reconfigCommand = { - replSetReconfig: rs._updateConfigIfNotDurable(config), - force: force - }; - var res = admin.runCommand(reconfigCommand); - - // Retry reconfig if quorum check failed because not enough voting nodes responded. - if (!res.ok && res.code === ErrorCodes.NodeNotFound) { - print("Replset reconfig failed because quorum check failed. Retry reconfig once. " + - "Error: " + tojson(res)); - res = admin.runCommand(reconfigCommand); + }, + function() { + var message = "Node " + catchingUpNode + " only reached optime " + tojson(ts) + + " not " + tojson(opTime); + if (ex) { + message += "; last attempt failed with exception " + tojson(ex); } - - assert.commandWorked(res); - } catch (e) { - if (!isNetworkError(e)) { - throw e; + return message; + }); +}; + +/** + * Uses the results of running replSetGetStatus against an arbitrary replset node to wait until + * all nodes in the set are replicated through the same optime. + * 'rs' is an array of connections to replica set nodes. This function is useful when you + * don't have a ReplSetTest object to use, otherwise ReplSetTest.awaitReplication is preferred. + */ +waitUntilAllNodesCaughtUp = function(rs, timeout) { + var rsStatus; + var firstConflictingIndex; + var ot; + var otherOt; + assert.soon( + function() { + rsStatus = rs[0].adminCommand('replSetGetStatus'); + if (rsStatus.ok != 1) { + return false; } - print("Calling replSetReconfig failed. " + tojson(e)); - } - - var master = rs.getPrimary().getDB("admin"); - waitForAllMembers(master); - - return master; - }; - - awaitOpTime = function(catchingUpNode, latestOpTimeNode) { - var ts, ex, opTime; - assert.soon( - function() { - try { - // The following statement extracts the timestamp field from the most recent - // element of - // the oplog, and stores it in "ts". - ts = getLatestOp(catchingUpNode).ts; - opTime = getLatestOp(latestOpTimeNode).ts; - if ((ts.t == opTime.t) && (ts.i == opTime.i)) { - return true; - } - ex = null; + assert.eq(rs.length, rsStatus.members.length, tojson(rsStatus)); + ot = rsStatus.members[0].optime; + for (var i = 1; i < rsStatus.members.length; ++i) { + var otherNode = rsStatus.members[i]; + + // Must be in PRIMARY or SECONDARY state. + if (otherNode.state != ReplSetTest.State.PRIMARY && + otherNode.state != ReplSetTest.State.SECONDARY) { return false; - } catch (ex) { - return false; - } - }, - function() { - var message = "Node " + catchingUpNode + " only reached optime " + tojson(ts) + - " not " + tojson(opTime); - if (ex) { - message += "; last attempt failed with exception " + tojson(ex); } - return message; - }); - }; - /** - * Uses the results of running replSetGetStatus against an arbitrary replset node to wait until - * all nodes in the set are replicated through the same optime. - * 'rs' is an array of connections to replica set nodes. This function is useful when you - * don't have a ReplSetTest object to use, otherwise ReplSetTest.awaitReplication is preferred. - */ - waitUntilAllNodesCaughtUp = function(rs, timeout) { - var rsStatus; - var firstConflictingIndex; - var ot; - var otherOt; - assert.soon( - function() { - rsStatus = rs[0].adminCommand('replSetGetStatus'); - if (rsStatus.ok != 1) { + // Fail if optimes are not equal. + otherOt = otherNode.optime; + if (!friendlyEqual(otherOt, ot)) { + firstConflictingIndex = i; return false; } - assert.eq(rs.length, rsStatus.members.length, tojson(rsStatus)); - ot = rsStatus.members[0].optime; - for (var i = 1; i < rsStatus.members.length; ++i) { - var otherNode = rsStatus.members[i]; - - // Must be in PRIMARY or SECONDARY state. - if (otherNode.state != ReplSetTest.State.PRIMARY && - otherNode.state != ReplSetTest.State.SECONDARY) { - return false; - } - - // Fail if optimes are not equal. - otherOt = otherNode.optime; - if (!friendlyEqual(otherOt, ot)) { - firstConflictingIndex = i; - return false; - } - } - return true; - }, - function() { - return "Optimes of members 0 (" + tojson(ot) + ") and " + firstConflictingIndex + - " (" + tojson(otherOt) + ") are different in " + tojson(rsStatus); - }, - timeout); - }; - - /** - * Waits for the given node to reach the given state, ignoring network errors. Ensures that the - * connection is re-connected and usable when the function returns. - */ - waitForState = function(node, state) { - assert.soonNoExcept(function() { - assert.commandWorked(node.adminCommand( - {replSetTest: 1, waitForMemberState: state, timeoutMillis: 60 * 1000 * 5})); - return true; - }); - // Some state transitions cause connections to be closed, but whether the connection close - // happens before or after the replSetTest command above returns is racy, so to ensure that - // the connection to 'node' is usable after this function returns, reconnect it first. - reconnect(node); - }; - - /** - * Starts each node in the given replica set if the storage engine supports readConcern - *'majority'. - * Returns true if the replica set was started successfully and false otherwise. - * - * @param replSetTest - The instance of {@link ReplSetTest} to start - * @param options - The options passed to {@link ReplSetTest.startSet} - */ - startSetIfSupportsReadMajority = function(replSetTest, options) { - replSetTest.startSet(options); - return replSetTest.nodes[0] - .adminCommand("serverStatus") - .storageEngine.supportsCommittedReads; - }; - - /** - * Performs a reInitiate() call on 'replSetTest', ignoring errors that are related to an aborted - * secondary member. All other errors are rethrown. - */ - reInitiateWithoutThrowingOnAbortedMember = function(replSetTest) { - try { - replSetTest.reInitiate(); - } catch (e) { - // reInitiate can throw because it tries to run an ismaster command on - // all secondaries, including the new one that may have already aborted - const errMsg = tojson(e); - if (isNetworkError(e)) { - // Ignore these exceptions, which are indicative of an aborted node - } else { - throw e; } + return true; + }, + function() { + return "Optimes of members 0 (" + tojson(ot) + ") and " + firstConflictingIndex + " (" + + tojson(otherOt) + ") are different in " + tojson(rsStatus); + }, + timeout); +}; + +/** + * Waits for the given node to reach the given state, ignoring network errors. Ensures that the + * connection is re-connected and usable when the function returns. + */ +waitForState = function(node, state) { + assert.soonNoExcept(function() { + assert.commandWorked(node.adminCommand( + {replSetTest: 1, waitForMemberState: state, timeoutMillis: 60 * 1000 * 5})); + return true; + }); + // Some state transitions cause connections to be closed, but whether the connection close + // happens before or after the replSetTest command above returns is racy, so to ensure that + // the connection to 'node' is usable after this function returns, reconnect it first. + reconnect(node); +}; + +/** + * Starts each node in the given replica set if the storage engine supports readConcern + *'majority'. + * Returns true if the replica set was started successfully and false otherwise. + * + * @param replSetTest - The instance of {@link ReplSetTest} to start + * @param options - The options passed to {@link ReplSetTest.startSet} + */ +startSetIfSupportsReadMajority = function(replSetTest, options) { + replSetTest.startSet(options); + return replSetTest.nodes[0].adminCommand("serverStatus").storageEngine.supportsCommittedReads; +}; + +/** + * Performs a reInitiate() call on 'replSetTest', ignoring errors that are related to an aborted + * secondary member. All other errors are rethrown. + */ +reInitiateWithoutThrowingOnAbortedMember = function(replSetTest) { + try { + replSetTest.reInitiate(); + } catch (e) { + // reInitiate can throw because it tries to run an ismaster command on + // all secondaries, including the new one that may have already aborted + const errMsg = tojson(e); + if (isNetworkError(e)) { + // Ignore these exceptions, which are indicative of an aborted node + } else { + throw e; + } + } +}; + +/** + * Waits for the specified hosts to enter a certain state. + */ +awaitRSClientHosts = function(conn, host, hostOk, rs, timeout) { + var hostCount = host.length; + if (hostCount) { + for (var i = 0; i < hostCount; i++) { + awaitRSClientHosts(conn, host[i], hostOk, rs); } - }; - /** - * Waits for the specified hosts to enter a certain state. - */ - awaitRSClientHosts = function(conn, host, hostOk, rs, timeout) { - var hostCount = host.length; - if (hostCount) { - for (var i = 0; i < hostCount; i++) { - awaitRSClientHosts(conn, host[i], hostOk, rs); - } + return; + } - return; - } + timeout = timeout || 5 * 60 * 1000; - timeout = timeout || 5 * 60 * 1000; + if (hostOk == undefined) + hostOk = {ok: true}; + if (host.host) + host = host.host; + if (rs) + rs = rs.name; - if (hostOk == undefined) - hostOk = {ok: true}; - if (host.host) - host = host.host; - if (rs) - rs = rs.name; + print("Awaiting " + host + " to be " + tojson(hostOk) + " for " + conn + " (rs: " + rs + ")"); - print("Awaiting " + host + " to be " + tojson(hostOk) + " for " + conn + " (rs: " + rs + - ")"); + var tests = 0; - var tests = 0; + assert.soon(function() { + var rsClientHosts = conn.adminCommand('connPoolStats').replicaSets; + if (tests++ % 10 == 0) { + printjson(rsClientHosts); + } - assert.soon(function() { - var rsClientHosts = conn.adminCommand('connPoolStats').replicaSets; - if (tests++ % 10 == 0) { - printjson(rsClientHosts); - } + for (var rsName in rsClientHosts) { + if (rs && rs != rsName) + continue; - for (var rsName in rsClientHosts) { - if (rs && rs != rsName) + for (var i = 0; i < rsClientHosts[rsName].hosts.length; i++) { + var clientHost = rsClientHosts[rsName].hosts[i]; + if (clientHost.addr != host) continue; - for (var i = 0; i < rsClientHosts[rsName].hosts.length; i++) { - var clientHost = rsClientHosts[rsName].hosts[i]; - if (clientHost.addr != host) - continue; + // Check that *all* host properties are set correctly + var propOk = true; + for (var prop in hostOk) { + // Use special comparator for tags because isMaster can return the fields in + // different order. The fields of the tags should be treated like a set of + // strings and 2 tags should be considered the same if the set is equal. + if (prop == 'tags') { + if (!clientHost.tags) { + propOk = false; + break; + } - // Check that *all* host properties are set correctly - var propOk = true; - for (var prop in hostOk) { - // Use special comparator for tags because isMaster can return the fields in - // different order. The fields of the tags should be treated like a set of - // strings and 2 tags should be considered the same if the set is equal. - if (prop == 'tags') { - if (!clientHost.tags) { + for (var hostTag in hostOk.tags) { + if (clientHost.tags[hostTag] != hostOk.tags[hostTag]) { propOk = false; break; } - - for (var hostTag in hostOk.tags) { - if (clientHost.tags[hostTag] != hostOk.tags[hostTag]) { - propOk = false; - break; - } - } - - for (var clientTag in clientHost.tags) { - if (clientHost.tags[clientTag] != hostOk.tags[clientTag]) { - propOk = false; - break; - } - } - - continue; } - if (isObject(hostOk[prop])) { - if (!friendlyEqual(hostOk[prop], clientHost[prop])) { + for (var clientTag in clientHost.tags) { + if (clientHost.tags[clientTag] != hostOk.tags[clientTag]) { propOk = false; break; } - } else if (clientHost[prop] != hostOk[prop]) { + } + + continue; + } + + if (isObject(hostOk[prop])) { + if (!friendlyEqual(hostOk[prop], clientHost[prop])) { propOk = false; break; } + } else if (clientHost[prop] != hostOk[prop]) { + propOk = false; + break; } + } - if (propOk) { - return true; - } + if (propOk) { + return true; } } + } - return false; - }, 'timed out waiting for replica set client to recognize hosts', timeout); - }; - - /** - * Returns the last opTime of the connection based from replSetGetStatus. Can only - * be used on replica set nodes. - */ - getLastOpTime = function(conn) { - var replSetStatus = - assert.commandWorked(conn.getDB("admin").runCommand({replSetGetStatus: 1})); - var connStatus = replSetStatus.members.filter(m => m.self)[0]; - return connStatus.optime; - }; - - /** - * Set log verbosity on all given nodes. - * e.g. setLogVerbosity(replTest.nodes, { "replication": {"verbosity": 3} }); - */ - setLogVerbosity = function(nodes, logVerbosity) { - var verbosity = { - "setParameter": 1, - "logComponentVerbosity": logVerbosity, - }; - nodes.forEach(function(node) { - assert.commandWorked(node.adminCommand(verbosity)); - }); + return false; + }, 'timed out waiting for replica set client to recognize hosts', timeout); +}; + +/** + * Returns the last opTime of the connection based from replSetGetStatus. Can only + * be used on replica set nodes. + */ +getLastOpTime = function(conn) { + var replSetStatus = assert.commandWorked(conn.getDB("admin").runCommand({replSetGetStatus: 1})); + var connStatus = replSetStatus.members.filter(m => m.self)[0]; + return connStatus.optime; +}; + +/** + * Set log verbosity on all given nodes. + * e.g. setLogVerbosity(replTest.nodes, { "replication": {"verbosity": 3} }); + */ +setLogVerbosity = function(nodes, logVerbosity) { + var verbosity = { + "setParameter": 1, + "logComponentVerbosity": logVerbosity, }; - + nodes.forEach(function(node) { + assert.commandWorked(node.adminCommand(verbosity)); + }); +}; }()); |