diff options
author | Judah Schvimer <judah@mongodb.com> | 2016-07-19 09:44:37 -0400 |
---|---|---|
committer | Judah Schvimer <judah@mongodb.com> | 2016-07-19 09:44:37 -0400 |
commit | 433ffe0574f19f879b16d195068ce81ee55ee681 (patch) | |
tree | 420b39857177c7f87039156b54ee69d39f9fecd3 /buildscripts | |
parent | 5f57ee740b1eaa188532363fc363f42234057748 (diff) | |
download | mongo-433ffe0574f19f879b16d195068ce81ee55ee681.tar.gz |
SERVER-24538 Add small_oplog_rs_initsync_static passthrough to include periodic initial sync members
Diffstat (limited to 'buildscripts')
3 files changed, 120 insertions, 3 deletions
diff --git a/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml new file mode 100644 index 00000000000..3963f9e16a3 --- /dev/null +++ b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml @@ -0,0 +1,33 @@ +selector: + js_test: + roots: + - jstests/core/*.js + exclude_files: + # These tests are not expected to pass with replica-sets: + - jstests/core/dbadmin.js + - jstests/core/opcounters_write_cmd.js + - jstests/core/read_after_optime.js + - jstests/core/capped_update.js + # Blacklisted due to SERVER-25131 + - jstests/core/bypass_doc_validation.js + +run_hook_interval: &run_hook_interval 20 +executor: + js_test: + config: + shell_options: + eval: "testingReplication = true;" + readMode: commands + hooks: + - class: IntermediateInitialSync + n: *run_hook_interval + - class: CleanEveryN + n: *run_hook_interval + fixture: + class: ReplicaSetFixture + mongod_options: + oplogSize: 511 + set_parameters: + enableTestCommands: 1 + num_nodes: 2 + start_initial_sync_node: True diff --git a/buildscripts/resmokelib/testing/fixtures/replicaset.py b/buildscripts/resmokelib/testing/fixtures/replicaset.py index be24295ece7..338979585d7 100644 --- a/buildscripts/resmokelib/testing/fixtures/replicaset.py +++ b/buildscripts/resmokelib/testing/fixtures/replicaset.py @@ -29,6 +29,7 @@ class ReplicaSetFixture(interface.ReplFixture): dbpath_prefix=None, preserve_dbpath=False, num_nodes=2, + start_initial_sync_node=False, write_concern_majority_journal_default=None, auth_options=None, replset_config_options=None): @@ -39,6 +40,7 @@ class ReplicaSetFixture(interface.ReplFixture): self.mongod_options = utils.default_if_none(mongod_options, {}) self.preserve_dbpath = preserve_dbpath self.num_nodes = num_nodes + self.start_initial_sync_node = start_initial_sync_node self.write_concern_majority_journal_default = write_concern_majority_journal_default self.auth_options = auth_options self.replset_config_options = utils.default_if_none(replset_config_options, {}) @@ -58,6 +60,8 @@ class ReplicaSetFixture(interface.ReplFixture): self.nodes = [] self.replset_name = None + self.initial_sync_node = None + self.initial_sync_node_idx = -1 def setup(self): self.replset_name = self.mongod_options.get("replSet", "rs") @@ -70,6 +74,14 @@ class ReplicaSetFixture(interface.ReplFixture): for node in self.nodes: node.setup() + if self.start_initial_sync_node: + if not self.initial_sync_node: + self.initial_sync_node_idx = len(self.nodes) + self.initial_sync_node = self._new_mongod(self.initial_sync_node_idx, + self.replset_name) + self.initial_sync_node.setup() + self.initial_sync_node.await_ready() + self.port = self.get_primary().port # Call await_ready() on each of the nodes here because we want to start the election as @@ -87,6 +99,13 @@ class ReplicaSetFixture(interface.ReplFixture): # Only 7 nodes in a replica set can vote, so the other members must be non-voting. member_info["votes"] = 0 members.append(member_info) + if self.initial_sync_node: + members.append({"_id": self.initial_sync_node_idx, + "host": self.initial_sync_node.get_connection_string(), + "priority": 0, + "hidden": 1, + "votes": 0}) + initiate_cmd_obj = {"replSetInitiate": {"_id": self.replset_name, "members": members}} if self.write_concern_majority_journal_default is not None: @@ -136,6 +155,9 @@ class ReplicaSetFixture(interface.ReplFixture): else: self.logger.info("Stopping all members of the replica set...") + if self.initial_sync_node: + success = self.initial_sync_node.teardown() and success + # Terminate the secondaries first to reduce noise in the logs. for node in reversed(self.nodes): success = node.teardown() and success @@ -146,7 +168,12 @@ class ReplicaSetFixture(interface.ReplFixture): return success def is_running(self): - return all(node.is_running() for node in self.nodes) + running = all(node.is_running() for node in self.nodes) + + if self.initial_sync_node: + running = self.initial_sync_node.is_running() or running + + return running def get_primary(self): # The primary is always the first element of the 'nodes' list because all other members of @@ -156,6 +183,9 @@ class ReplicaSetFixture(interface.ReplFixture): def get_secondaries(self): return self.nodes[1:] + def get_initial_sync_node(self): + return self.initial_sync_node + def _new_mongod(self, index, replset_name): """ Returns a standalone.MongoDFixture configured to be used as a @@ -175,12 +205,14 @@ class ReplicaSetFixture(interface.ReplFixture): def _get_logger_for_mongod(self, index): """ - Returns a new logging.Logger instance for use as the primary or - secondary of a replica-set. + Returns a new logging.Logger instance for use as the primary, secondary, or initial + sync member of a replica-set. """ if index == 0: logger_name = "%s:primary" % (self.logger.name) + elif index == self.initial_sync_node_idx: + logger_name = "%s:initsync" % (self.logger.name) else: suffix = str(index - 1) if self.num_nodes > 2 else "" logger_name = "%s:secondary%s" % (self.logger.name, suffix) @@ -192,4 +224,6 @@ class ReplicaSetFixture(interface.ReplFixture): raise ValueError("Must call setup() before calling get_connection_string()") conn_strs = [node.get_connection_string() for node in self.nodes] + if self.initial_sync_node: + conn_strs.append(self.initial_sync_node.get_connection_string()) return self.replset_name + "/" + ",".join(conn_strs) diff --git a/buildscripts/resmokelib/testing/hooks.py b/buildscripts/resmokelib/testing/hooks.py index 1a438cf0867..f845f0c7927 100644 --- a/buildscripts/resmokelib/testing/hooks.py +++ b/buildscripts/resmokelib/testing/hooks.py @@ -161,6 +161,55 @@ class JsCustomBehavior(CustomBehavior): test_report.stopTest(self.hook_test_case) +class IntermediateInitialSync(JsCustomBehavior): + """ + This hook accepts a parameter 'n' that specifies a number of tests after which it will start up + a node to initial sync, wait for replication to finish, and then validate the data. + + This requires the ReplicaSetFixture to be started with 'start_initial_sync_node=True'. + """ + + DEFAULT_N = CleanEveryN.DEFAULT_N + + def __init__(self, logger, fixture, n=DEFAULT_N): + description = "Intermediate Initial Sync" + js_filename = os.path.join("jstests", "hooks", "run_initial_sync_node_validation.js") + JsCustomBehavior.__init__(self, logger, fixture, js_filename, description) + + self.n = n + self.tests_run = 0 + + def after_test(self, test, test_report): + self.tests_run += 1 + sync_node = self.fixture.get_initial_sync_node(); + sync_node_conn = utils.new_mongo_client(port=sync_node.port) + + if self.tests_run >= self.n: + self.tests_run = 0 + teardown_success = sync_node.teardown() + + self.logger.info("Starting the initial sync node back up again...") + sync_node.setup() + sync_node.await_ready() + + # Do initial sync round. + self.logger.info("Waiting for initial sync node to go into SECONDARY state") + cmd = bson.SON([("replSetTest", 1), + ("waitForMemberState", 2), + ("timeoutMillis", 20 * 60 * 1000)]) + try: + sync_node_conn.admin.command(cmd) + except self.hook_test_case.failureException as err: + self.logger.exception("{0} failed".format(description)) + test_report.addFailure(self.hook_test_case, sys.exc_info()) + raise errors.TestFailure(err.args[0]) + + # Run data validation and dbhash checking. + JsCustomBehavior.after_test(self, test, test_report) + + if not teardown_success: + raise errors.TestFailure("%s did not exit cleanly" % (sync_node)) + class ValidateCollections(JsCustomBehavior): """ Runs full validation on all collections in all databases on every stand-alone @@ -215,4 +264,5 @@ _CUSTOM_BEHAVIORS = { "CleanEveryN": CleanEveryN, "CheckReplDBHash": CheckReplDBHash, "ValidateCollections": ValidateCollections, + "IntermediateInitialSync": IntermediateInitialSync, } |