mirror of https://github.com/mongodb/mongo
SERVER-112868 Introduce option to ReplSetTest and ShardingTest for opening a maintenance port (#43334)
Co-authored-by: Steve McClure <steve.mcclure@mongodb.com> GitOrigin-RevId: 3e18489bb2ecb4da1167b51c2832a3d01e54a8c1
This commit is contained in:
parent
c2c67e0bb2
commit
df9c6590ef
|
|
@ -68,6 +68,8 @@ export class ReplSetTest {
|
|||
* ShardingTest, the seed is generated as part of ShardingTest.
|
||||
* @param {boolean} [opts.useAutoBootstrapProcedure] If true, follow the procedure for
|
||||
* auto-bootstrapped replica sets.
|
||||
* @param {boolean} [opts.useMaintenancePorts=false] If true, then a maintenance port will be
|
||||
* opened for each node in the replica set.
|
||||
* @param {number} [opts.timeoutMS] Timeout value in milliseconds.
|
||||
*/
|
||||
constructor(opts) {
|
||||
|
|
@ -306,6 +308,14 @@ export class ReplSetTest {
|
|||
return this.ports[n];
|
||||
}
|
||||
|
||||
getMaintenancePort(n) {
|
||||
const translatedN = this.getNodeId(n);
|
||||
if (this._maintenancePorts?.[translatedN] < 1) {
|
||||
throw new Error("Maintenance port not set for node");
|
||||
}
|
||||
return this._maintenancePorts[translatedN];
|
||||
}
|
||||
|
||||
getDbPath(node) {
|
||||
// Get a replica set node (check for use of bridge).
|
||||
const n = this.getNodeId(node);
|
||||
|
|
@ -1007,6 +1017,10 @@ export class ReplSetTest {
|
|||
this._unbridgedPorts.push(this._allocatePortForBridge());
|
||||
}
|
||||
|
||||
if (this._useMaintenancePorts) {
|
||||
this._maintenancePorts.push(this._allocatePortForNode());
|
||||
}
|
||||
|
||||
if (jsTestOptions().shellGRPC) {
|
||||
const nextPort = this._allocatePortForNode();
|
||||
jsTest.log.info("ReplSetTest Next gRPC port: " + nextPort);
|
||||
|
|
@ -1036,6 +1050,10 @@ export class ReplSetTest {
|
|||
this._unbridgedPorts.splice(nodeId, 1);
|
||||
this._unbridgedNodes.splice(nodeId, 1);
|
||||
}
|
||||
|
||||
if (this._maintenancePorts) {
|
||||
this._maintenancePorts.splice(nodeId, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2793,6 +2811,9 @@ export class ReplSetTest {
|
|||
port: this._useBridge ? this._unbridgedPorts[n] : this.ports[n],
|
||||
dbpath: "$set-$node",
|
||||
};
|
||||
if (this._maintenancePorts?.[n] > 0) {
|
||||
defaults.maintenancePort = this._maintenancePorts[n];
|
||||
}
|
||||
if (jsTestOptions().shellGRPC) {
|
||||
defaults.grpcPort = this.grpcPorts[n];
|
||||
}
|
||||
|
|
@ -3537,6 +3558,11 @@ function _constructStartNewInstances(rst, opts) {
|
|||
|
||||
rst._bridgeOptions = opts.bridgeOptions || {};
|
||||
|
||||
rst._useMaintenancePorts = opts.useMaintenancePorts ?? false;
|
||||
if (rst._useMaintenancePorts) {
|
||||
assert(!rst._useBridge, "useMaintenancePorts is not supported when using MongoBridge.");
|
||||
}
|
||||
|
||||
rst._causalConsistency = opts.causallyConsistent || false;
|
||||
|
||||
rst._configSettings = opts.settings || false;
|
||||
|
|
@ -3618,6 +3644,9 @@ function _constructStartNewInstances(rst, opts) {
|
|||
rst._unbridgedNodes = [];
|
||||
} else {
|
||||
rst.ports = opts.ports || Array.from({length: numNodes}, rst._allocatePortForNode);
|
||||
if (rst._useMaintenancePorts) {
|
||||
rst._maintenancePorts = Array.from({length: numNodes}, rst._allocatePortForNode);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < numNodes; i++) {
|
||||
|
|
@ -3629,6 +3658,12 @@ function _constructStartNewInstances(rst, opts) {
|
|||
rst.ports[i] = nodeOpts.port;
|
||||
}
|
||||
}
|
||||
if (nodeOpts?.hasOwnProperty("maintenancePort")) {
|
||||
if (!rst._maintenancePorts) {
|
||||
rst._maintenancePorts = Array(numNodes).fill(-1);
|
||||
}
|
||||
rst._maintenancePorts[i] = nodeOpts.maintenancePort;
|
||||
}
|
||||
}
|
||||
|
||||
if (jsTestOptions().shellGRPC) {
|
||||
|
|
|
|||
|
|
@ -929,6 +929,8 @@ export class ShardingTest {
|
|||
* @property {Object} [bridgeOptions={}] Options to apply to all mongobridge processes.
|
||||
* @property {Object} [rsOptions] Same as the `rs` parameter to ShardingTest constructor. Can be
|
||||
* used to specify options that are common all replica members.
|
||||
* @property {boolean} [useMaintenancePorts=false] If true, then a maintenance port will be
|
||||
* specified for each node in the cluster.
|
||||
*
|
||||
* // replica Set only:
|
||||
* @property {boolean} [useHostname] if true, use hostname of machine, otherwise use localhost
|
||||
|
|
@ -1116,6 +1118,7 @@ export class ShardingTest {
|
|||
otherParams.useBridge = otherParams.useBridge || false;
|
||||
otherParams.bridgeOptions = otherParams.bridgeOptions || {};
|
||||
otherParams.causallyConsistent = otherParams.causallyConsistent || false;
|
||||
otherParams.useMaintenancePorts = otherParams.useMaintenancePorts ?? false;
|
||||
|
||||
if (jsTestOptions().networkMessageCompressors) {
|
||||
otherParams.bridgeOptions["networkMessageCompressors"] =
|
||||
|
|
@ -1142,6 +1145,7 @@ export class ShardingTest {
|
|||
"useBridge cannot be true when using TLS. Add the requires_mongobridge tag to the test to ensure it will be skipped on variants that use TLS.",
|
||||
);
|
||||
}
|
||||
this._useMaintenancePorts = otherParams.useMaintenancePorts;
|
||||
|
||||
this._unbridgedMongos = [];
|
||||
let _allocatePortForMongos;
|
||||
|
|
@ -1221,6 +1225,7 @@ export class ShardingTest {
|
|||
host: hostName,
|
||||
useBridge: otherParams.useBridge,
|
||||
bridgeOptions: otherParams.bridgeOptions,
|
||||
useMaintenancePorts: otherParams.useMaintenancePorts,
|
||||
keyFile: this.keyFile,
|
||||
waitForKeys: false,
|
||||
name: testName + "-configRS",
|
||||
|
|
@ -1359,6 +1364,7 @@ export class ShardingTest {
|
|||
useHostName: otherParams.useHostname,
|
||||
useBridge: otherParams.useBridge,
|
||||
bridgeOptions: otherParams.bridgeOptions,
|
||||
useMaintenancePorts: otherParams.useMaintenancePorts,
|
||||
keyFile: this.keyFile,
|
||||
protocolVersion: protocolVersion,
|
||||
waitForKeys: false,
|
||||
|
|
@ -1643,6 +1649,9 @@ export class ShardingTest {
|
|||
}
|
||||
|
||||
options.port = options.port || _allocatePortForMongos();
|
||||
if (this._useMaintenancePorts || options.hasOwnProperty("maintenancePort")) {
|
||||
options.maintenancePort = options.hasOwnProperty("maintenancePort") ? options.maintenancePort : _allocatePortForMongos();
|
||||
}
|
||||
if (jsTestOptions().shellGRPC) {
|
||||
options.grpcPort = options.grpcPort || _allocatePortForMongos();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* Test that the maintenance port option is specified correctly in a ReplSetTest and a ShardingTest.
|
||||
*
|
||||
* TODO (SERVER-112674): Extend the integration to expose connections on both the main and
|
||||
* maintenance ports and add replace the testing coverage via logging with connection based tests.
|
||||
*
|
||||
* @tags: [
|
||||
* requires_replication,
|
||||
* requires_sharding,
|
||||
* featureFlagDedicatedPortForMaintenanceOperations,
|
||||
* ]
|
||||
*/
|
||||
|
||||
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
||||
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
||||
import {describe, it} from "jstests/libs/mochalite.js";
|
||||
|
||||
describe("Tests for maintenance port usage within JS test helpers", function () {
|
||||
const checkMaintenancePortSet = (conn, port) => {
|
||||
assert.eq(port, conn.maintenancePort);
|
||||
assert(
|
||||
checkLog.checkContainsOnceJson(conn, 21951, {
|
||||
options: (opts) => {
|
||||
return opts.net.maintenancePort == port;
|
||||
},
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
// TODO (SERVER-112674): Remove this. For now, we set the log verbosity very low to ensure we still see the startup logs
|
||||
const verbosityOptions = {setParameter: {logComponentVerbosity: {verbosity: 0}}};
|
||||
|
||||
it("Starting up a replica set with maintenance ports", () => {
|
||||
const rs = new ReplSetTest({nodes: 3, useMaintenancePorts: true, nodeOptions: verbosityOptions});
|
||||
rs.startSet();
|
||||
rs.initiate();
|
||||
|
||||
rs.nodes.forEach((conn) => {
|
||||
let maintenancePort = rs.getMaintenancePort(conn);
|
||||
checkMaintenancePortSet(conn, maintenancePort);
|
||||
});
|
||||
|
||||
rs.stopSet();
|
||||
});
|
||||
|
||||
it("Starting up a replica set with a specific node having a maintenance port", () => {
|
||||
const rs = new ReplSetTest({nodes: [{}, {maintenancePort: 27021}, {}], nodeOptions: verbosityOptions});
|
||||
rs.startSet();
|
||||
rs.initiate();
|
||||
|
||||
let countFoundPorts = 0;
|
||||
|
||||
rs.nodes.forEach((conn) => {
|
||||
try {
|
||||
assert.eq(27021, rs.getMaintenancePort(conn));
|
||||
checkMaintenancePortSet(conn, 27021);
|
||||
countFoundPorts += 1;
|
||||
} catch (e) {
|
||||
// This should throw if the maintenance port is not set for the node.
|
||||
assert(!conn.maintenancePort);
|
||||
}
|
||||
});
|
||||
|
||||
assert.eq(countFoundPorts, 1);
|
||||
|
||||
rs.stopSet();
|
||||
});
|
||||
|
||||
it("Starting up a sharded cluster with maintenance ports", () => {
|
||||
const st = new ShardingTest({
|
||||
shards: 1,
|
||||
mongos: 2,
|
||||
useMaintenancePorts: true,
|
||||
other: {nodeOptions: verbosityOptions, configOptions: verbosityOptions, mongosOptions: verbosityOptions},
|
||||
});
|
||||
|
||||
st.configRS.nodes.forEach((conn) => {
|
||||
let maintenancePort = st.configRS.getMaintenancePort(conn);
|
||||
checkMaintenancePortSet(conn, maintenancePort);
|
||||
});
|
||||
|
||||
st.rs0.nodes.forEach((conn) => {
|
||||
let maintenancePort = st.rs0.getMaintenancePort(conn);
|
||||
checkMaintenancePortSet(conn, maintenancePort);
|
||||
});
|
||||
|
||||
st._mongos.forEach((conn) => {
|
||||
let maintenancePort = conn.maintenancePort;
|
||||
checkMaintenancePortSet(conn, maintenancePort);
|
||||
});
|
||||
|
||||
st.stop();
|
||||
});
|
||||
});
|
||||
|
|
@ -961,6 +961,9 @@ MongoRunner.runMongod = function (opts) {
|
|||
mongod.name = mongod.hostNoPort + ":" + mongod.commandLine.port;
|
||||
mongod.host = mongod.hostNoPort + ":" + connectPort;
|
||||
mongod.port = parseInt(connectPort);
|
||||
if (mongod.commandLine.maintenancePort > 0) {
|
||||
mongod.maintenancePort = mongod.commandLine.maintenancePort;
|
||||
}
|
||||
mongod.runId = runId || ObjectId();
|
||||
mongod.dbpath = fullOptions.dbpath;
|
||||
mongod.savedOptions = MongoRunner.savedOptions[mongod.runId];
|
||||
|
|
@ -1005,6 +1008,9 @@ MongoRunner.runMongos = function (opts) {
|
|||
mongos.name = MongoRunner.getMongosName(mongos.commandLine.port, useHostName);
|
||||
mongos.host = MongoRunner.getMongosName(connectPort, useHostName);
|
||||
mongos.port = parseInt(connectPort);
|
||||
if (mongos.commandLine.maintenancePort > 0) {
|
||||
mongos.maintenancePort = mongos.commandLine.maintenancePort;
|
||||
}
|
||||
mongos.runId = runId || ObjectId();
|
||||
mongos.savedOptions = MongoRunner.savedOptions[mongos.runId];
|
||||
mongos.fullOptions = fullOptions;
|
||||
|
|
|
|||
Loading…
Reference in New Issue