mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
281 lines
10 KiB
JavaScript
281 lines
10 KiB
JavaScript
/**
|
|
* check all the easily testable fields in the document returned by the isMaster() command
|
|
* also checks that fields that should not be in the document are absent
|
|
*/
|
|
|
|
load("jstests/replsets/rslib.js");
|
|
|
|
// function create the error message if an assert fails
|
|
var generateErrorString = function (badFields, missingFields, badValues, result) {
|
|
var str = "\nThe result was:\n" + tojson(result);
|
|
if (badFields.length !== 0) {
|
|
str += "\nIt had the following fields which it shouldn't have: ";
|
|
str += badFields;
|
|
}
|
|
if (missingFields.length !== 0) {
|
|
str += "\nIt lacked the following fields which it should have contained: ";
|
|
str += missingFields;
|
|
}
|
|
if (badValues.length !== 0) {
|
|
for (i = 0; i < badValues.length; i+=3) {
|
|
str += "\nIts value for " + badValues[i] + " is " + badValues[i+1];
|
|
str += " but should be " + badValues[i+2];
|
|
}
|
|
}
|
|
return str;
|
|
};
|
|
|
|
// function to check a single result
|
|
var checkMember = function (memberInfo) {
|
|
// run isMaster on the connection
|
|
result = memberInfo.conn.getDB("admin").runCommand({isMaster:1});
|
|
|
|
// make sure result doesn't contain anything it shouldn't
|
|
var badFields = [];
|
|
for (field in result) {
|
|
if (!result.hasOwnProperty(field)){
|
|
continue;
|
|
}
|
|
if (Array.contains(memberInfo.unwantedFields, field)) {
|
|
badFields.push(field);
|
|
}
|
|
}
|
|
|
|
// make sure result contains the fields we want
|
|
var missingFields = [];
|
|
for (i = 0; i < memberInfo.wantedFields.length; i++) {
|
|
field = memberInfo.wantedFields[i];
|
|
if (!result.hasOwnProperty(field)) {
|
|
missingFields.push(field);
|
|
print(field);
|
|
}
|
|
}
|
|
|
|
// make sure the result has proper values for fields with known values
|
|
var badValues = []; // each mistake will be saved as three entries (key, badvalue, goodvalue)
|
|
for (field in memberInfo.goodValues) {
|
|
if (typeof(memberInfo.goodValues[field]) === "object") {
|
|
// assumes nested obj is disk in tags this is currently true, but may change
|
|
if (result[field].disk !== memberInfo.goodValues[field].disk) {
|
|
badValues.push("tags.disk");
|
|
badValues.push(result[field].disk);
|
|
badValues.push(memberInfo.goodValues[field].disk);
|
|
}
|
|
}
|
|
else {
|
|
if (result[field] !== memberInfo.goodValues[field]) {
|
|
badValues.push(field);
|
|
badValues.push(result[field]);
|
|
badValues.push(memberInfo.goodValues[field]);
|
|
}
|
|
}
|
|
}
|
|
assert(badFields.length === 0 && missingFields.length === 0 && badValues.length === 0,
|
|
memberInfo.name + " had the following problems."
|
|
+ generateErrorString(badFields, missingFields, badValues, result));
|
|
}
|
|
|
|
// start of test code
|
|
var name = "ismaster";
|
|
var replTest = new ReplSetTest({name: name, nodes: 4});
|
|
var nodes = replTest.startSet();
|
|
|
|
var config = replTest.getReplSetConfig();
|
|
config.members[1].priority = 0;
|
|
config.members[2].priority = 0;
|
|
config.members[2].hidden = true;
|
|
config.members[2].slaveDelay = 3;
|
|
config.members[2].buildIndexes = false;
|
|
config.members[3].arbiterOnly = true;
|
|
replTest.initiate(config);
|
|
|
|
var agreeOnPrimaryAndSetVersion = function( setVersion ) {
|
|
|
|
print( "Waiting for primary and replica set version " + setVersion );
|
|
|
|
var nodes = replTest.nodes;
|
|
var primary = undefined;
|
|
var lastSetVersion = setVersion;
|
|
for ( var i = 0; i < nodes.length; i++ ) {
|
|
try {
|
|
var isMasterResult = nodes[i].getDB( "admin" ).runCommand({ isMaster : 1 });
|
|
}
|
|
catch (e) {
|
|
// handle reconnect errors due to step downs
|
|
print("Error while calling isMaster on " + nodes[i] + ": " + e);
|
|
return false;
|
|
}
|
|
|
|
printjson( isMasterResult );
|
|
if ( !primary ) primary = isMasterResult.primary;
|
|
if ( !lastSetVersion ) lastSetVersion = isMasterResult.setVersion;
|
|
if ( isMasterResult.primary != primary || !primary ) return false;
|
|
if ( isMasterResult.setVersion != lastSetVersion ) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
var master = replTest.getMaster();
|
|
assert.soon( function() { return agreeOnPrimaryAndSetVersion( 1 ); },
|
|
"Nodes did not initiate in less than a minute", 60000 );
|
|
|
|
// check to see if the information from isMaster() is correct at each node
|
|
// the checker only checks that the field exists when its value is "has"
|
|
checkMember({ conn: master,
|
|
name: "master",
|
|
goodValues: {
|
|
setName: "ismaster",
|
|
setVersion: 1,
|
|
ismaster: true,
|
|
secondary: false,
|
|
ok: 1
|
|
},
|
|
wantedFields: ["hosts", "passives", "arbiters", "primary", "me", "maxBsonObjectSize",
|
|
"localTime"],
|
|
unwantedFields: ["arbiterOnly", "passive", "slaveDelay", "hidden", "tags",
|
|
"buildIndexes"]
|
|
});
|
|
|
|
checkMember({ conn: replTest.liveNodes.slaves[0],
|
|
name: "slave",
|
|
goodValues: {
|
|
setName: "ismaster",
|
|
setVersion: 1,
|
|
ismaster: false,
|
|
secondary: true,
|
|
passive: true,
|
|
ok: 1
|
|
},
|
|
wantedFields: ["hosts", "passives", "arbiters", "primary", "me", "maxBsonObjectSize",
|
|
"localTime"],
|
|
unwantedFields: ["arbiterOnly", "slaveDelay", "hidden", "tags", "buildIndexes"]
|
|
});
|
|
|
|
checkMember({ conn: replTest.liveNodes.slaves[1],
|
|
name: "delayed_slave",
|
|
goodValues: {
|
|
setName: "ismaster",
|
|
setVersion: 1,
|
|
ismaster: false,
|
|
secondary: true,
|
|
passive: true,
|
|
slaveDelay: 3,
|
|
buildIndexes: false,
|
|
ok: 1
|
|
},
|
|
wantedFields: ["hosts", "passives", "arbiters", "primary", "me", "maxBsonObjectSize",
|
|
"localTime"],
|
|
unwantedFields: ["arbiterOnly", "tags"]
|
|
});
|
|
|
|
checkMember({ conn: replTest.liveNodes.slaves[2],
|
|
name: "arbiter",
|
|
goodValues: {
|
|
setName: "ismaster",
|
|
setVersion: 1,
|
|
ismaster: false,
|
|
secondary: false,
|
|
arbiterOnly: true,
|
|
ok: 1
|
|
},
|
|
wantedFields: ["hosts", "passives", "arbiters", "primary", "me", "maxBsonObjectSize",
|
|
"localTime"],
|
|
unwantedFields: ["slaveDelay", "hidden", "tags", "buildIndexes", "passive"]
|
|
});
|
|
|
|
// reconfigure and make sure the changes show up in ismaster on all members
|
|
config = master.getDB("local").system.replset.findOne();
|
|
config.version = config.version+1;
|
|
config.members[0].tags = {disk: "ssd"};
|
|
config.members[1].tags = {disk: "ssd"};
|
|
config.members[1].hidden = true;
|
|
config.members[2].slaveDelay = 300000;
|
|
config.members[2].tags = {disk: "hdd"};
|
|
try {
|
|
result = master.getDB("admin").runCommand({replSetReconfig : config});
|
|
}
|
|
catch(e) {
|
|
print(e);
|
|
}
|
|
|
|
master = replTest.getMaster();
|
|
assert.soon( function() { return agreeOnPrimaryAndSetVersion( 2 ); },
|
|
"Nodes did not sync in less than a minute", 60000 );
|
|
|
|
// check nodes for their new settings
|
|
checkMember({ conn: master,
|
|
name: "master2",
|
|
goodValues: {
|
|
setName: "ismaster",
|
|
setVersion: 2,
|
|
ismaster: true,
|
|
secondary: false,
|
|
tags: {"disk": "ssd"},
|
|
ok: 1
|
|
},
|
|
wantedFields: ["hosts", "arbiters", "primary", "me", "maxBsonObjectSize",
|
|
"localTime"],
|
|
unwantedFields: ["arbiterOnly", "passives", "passive", "slaveDelay", "hidden", "buildIndexes"]
|
|
});
|
|
|
|
checkMember({ conn: replTest.liveNodes.slaves[0],
|
|
name: "first_slave",
|
|
goodValues: {
|
|
setName: "ismaster",
|
|
setVersion: 2,
|
|
ismaster: false,
|
|
secondary: true,
|
|
tags: {"disk": "ssd"},
|
|
passive: true,
|
|
hidden: true,
|
|
ok: 1
|
|
},
|
|
wantedFields: ["hosts", "arbiters", "primary", "me", "maxBsonObjectSize",
|
|
"localTime"],
|
|
unwantedFields: ["arbiterOnly", "passives", "slaveDelayed", "buildIndexes"]
|
|
});
|
|
|
|
checkMember({ conn: replTest.liveNodes.slaves[1],
|
|
name: "very_delayed_slave",
|
|
goodValues: {
|
|
setName: "ismaster",
|
|
setVersion: 2,
|
|
ismaster: false,
|
|
secondary: true,
|
|
tags: {"disk": "hdd"},
|
|
passive: true,
|
|
slaveDelay: 300000,
|
|
buildIndexes: false,
|
|
hidden: true,
|
|
ok: 1
|
|
},
|
|
wantedFields: ["hosts", "arbiters", "primary", "me", "maxBsonObjectSize",
|
|
"localTime"],
|
|
unwantedFields: ["arbiterOnly", "passives"]
|
|
});
|
|
|
|
checkMember({ conn: replTest.liveNodes.slaves[2],
|
|
name: "arbiter",
|
|
goodValues: {
|
|
setName: "ismaster",
|
|
setVersion: 2,
|
|
ismaster: false,
|
|
secondary: false,
|
|
arbiterOnly: true,
|
|
ok: 1
|
|
},
|
|
wantedFields: ["hosts", "arbiters", "primary", "me", "maxBsonObjectSize",
|
|
"localTime"],
|
|
unwantedFields: ["slaveDelay", "hidden", "tags", "buildIndexes", "passive"]
|
|
});
|
|
|
|
// force reconfig and ensure all have the same setVersion afterwards
|
|
config = master.getDB("local").system.replset.findOne();
|
|
master.getDB("admin").runCommand({replSetReconfig : config, force: true});
|
|
|
|
assert.soon( function() { return agreeOnPrimaryAndSetVersion(); },
|
|
"Nodes did not sync in less than a minute after forced reconfig", 60000 );
|
|
|
|
replTest.stopSet();
|