diff options
author | Jason Chan <jason.chan@mongodb.com> | 2019-11-25 19:48:23 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-11-25 19:48:23 +0000 |
commit | 5c86d41207c3a8aba3adffc1c992561599d2aaa5 (patch) | |
tree | 1fdae50c0c78817276e7089d70708b8d73d2335c /buildscripts | |
parent | 96be927c235887791941fe9cffc57c9d3e66df57 (diff) | |
download | mongo-5c86d41207c3a8aba3adffc1c992561599d2aaa5.tar.gz |
SERVER-44702 Add ability to configure num replica set nodes and linear chaining through command line.
Diffstat (limited to 'buildscripts')
-rwxr-xr-x | buildscripts/evergreen_gen_fuzzer_tests.py | 13 | ||||
-rwxr-xr-x | buildscripts/evergreen_gen_multiversion_tests.py | 113 | ||||
-rwxr-xr-x | buildscripts/evergreen_generate_resmoke_tasks.py | 5 | ||||
-rw-r--r-- | buildscripts/resmokelib/config.py | 12 | ||||
-rw-r--r-- | buildscripts/resmokelib/parser.py | 17 | ||||
-rw-r--r-- | buildscripts/resmokelib/testing/fixtures/replicaset.py | 13 | ||||
-rw-r--r-- | buildscripts/resmokelib/testing/fixtures/shardedcluster.py | 7 |
7 files changed, 83 insertions, 97 deletions
diff --git a/buildscripts/evergreen_gen_fuzzer_tests.py b/buildscripts/evergreen_gen_fuzzer_tests.py index a33f493d388..276cff5623d 100755 --- a/buildscripts/evergreen_gen_fuzzer_tests.py +++ b/buildscripts/evergreen_gen_fuzzer_tests.py @@ -18,7 +18,6 @@ import buildscripts.util.read_config as read_config import buildscripts.util.taskname as taskname CONFIG_DIRECTORY = "generated_resmoke_config" -TEST_SUITE_DIR = generate_resmoke.DEFAULT_TEST_SUITE_DIR ConfigOptions = namedtuple("ConfigOptions", [ "num_files", @@ -95,15 +94,6 @@ def _name_task(parent_name, task_index, total_tasks): return "{0}_{1}".format(parent_name, str(task_index).zfill(index_width)) -def _write_fuzzer_yaml(options): - """Write the fuzzer yaml to CONFIG_DIRECTORY.""" - suite_file = options.suite + ".yml" - source_config = generate_resmoke.read_yaml(TEST_SUITE_DIR, suite_file) - gen_yml = generate_resmoke.generate_resmoke_suite_config(source_config, suite_file) - file_dict = {f"{options.suite}.yml": gen_yml} - generate_resmoke.write_file_dict(CONFIG_DIRECTORY, file_dict) - - def generate_evg_tasks(options, evg_config, task_name_suffix=None, display_task=None): """ Generate an evergreen configuration for fuzzers based on the options given. @@ -138,7 +128,7 @@ def generate_evg_tasks(options, evg_config, task_name_suffix=None, display_task= })) # Unix path separators are used because Evergreen only runs this script in unix shells, # even on Windows. - suite_arg = f"--suites={CONFIG_DIRECTORY}/{options.suite}.yml" + suite_arg = f"--suites={options.suite}" run_tests_vars = { "continue_on_failure": options.continue_on_failure, "resmoke_args": f"{suite_arg} {options.resmoke_args}", @@ -195,7 +185,6 @@ def main(): config_options = _get_config_options(options, options.expansion_file) evg_config = Configuration() - _write_fuzzer_yaml(config_options) generate_evg_tasks(config_options, evg_config) if not os.path.exists(CONFIG_DIRECTORY): diff --git a/buildscripts/evergreen_gen_multiversion_tests.py b/buildscripts/evergreen_gen_multiversion_tests.py index bb55e5b6b63..06e40947818 100755 --- a/buildscripts/evergreen_gen_multiversion_tests.py +++ b/buildscripts/evergreen_gen_multiversion_tests.py @@ -82,33 +82,11 @@ def is_suite_sharded(suite_dir, suite_name): return source_config["executor"]["fixture"]["class"] == "ShardedClusterFixture" -def update_suite_config_for_multiversion_replset(suite_config): - """Update suite_config with arguments for multiversion tests using ReplicaSetFixture.""" - suite_config["executor"]["fixture"]["num_nodes"] = 3 - suite_config["executor"]["fixture"]["linear_chain"] = True - - -def update_suite_config_for_multiversion_sharded(suite_config): - """Update suite_config with arguments for multiversion tests using ShardedClusterFixture.""" - - fixture_config = suite_config["executor"]["fixture"] - default_shards = "default_shards" - default_num_nodes = "default_nodes" - base_num_shards = (default_shards if "num_shards" not in fixture_config - or not fixture_config["num_shards"] else fixture_config["num_shards"]) - base_num_rs_nodes_per_shard = (default_num_nodes - if "num_rs_nodes_per_shard" not in fixture_config - or not fixture_config["num_rs_nodes_per_shard"] else - fixture_config["num_rs_nodes_per_shard"]) - - if base_num_shards is not default_shards or base_num_rs_nodes_per_shard is not default_num_nodes: - num_shard_num_nodes_pair = "{}-{}".format(base_num_shards, base_num_rs_nodes_per_shard) - assert num_shard_num_nodes_pair in {"default_shards-2", "2-default_nodes", "2-3"}, \ - "The multiversion suite runs sharded clusters with 2 shards and 2 nodes per shard. "\ - " acceptable, please add '{}' to this assert.".format(num_shard_num_nodes_pair) - - suite_config["executor"]["fixture"]["num_shards"] = 2 - suite_config["executor"]["fixture"]["num_rs_nodes_per_shard"] = 2 +def get_multiversion_resmoke_args(is_sharded): + """Return resmoke args used to configure a cluster for multiversion testing.""" + args_for_sharded_cluster = "--numShards=2 --numReplSetNodes=2 " + args_for_replset = "--numReplSetNodes=3 --linearChain=on " + return args_for_sharded_cluster if is_sharded else args_for_replset def get_backports_required_last_stable_hash(task_path_suffix): @@ -144,15 +122,6 @@ def get_last_stable_yaml(last_stable_commit_hash, suite_name): return backports_required_last_stable[suite_name] -class MultiversionConfig(object): - """An object containing the configurations to generate and run the multiversion tests with.""" - - def __init__(self, update_yaml, version_configs): - """Create new MultiversionConfig object.""" - self.update_yaml = update_yaml - self.version_configs = version_configs - - class EvergreenConfigGenerator(object): """Generate evergreen configurations for multiversion tests.""" @@ -167,7 +136,7 @@ class EvergreenConfigGenerator(object): self.task = generate_resmoke.remove_gen_suffix(self.options.task) def _generate_sub_task(self, mixed_version_config, task, task_index, suite, num_suites, - burn_in_test=None): + is_sharded, burn_in_test=None): # pylint: disable=too-many-arguments """Generate a sub task to be run with the provided suite and mixed version config.""" @@ -188,11 +157,15 @@ class EvergreenConfigGenerator(object): ] run_tests_vars = { "resmoke_args": - "{0} --suite={1} --mixedBinVersions={2} --excludeWithAnyTags={3} ".format( - self.options.resmoke_args, suite, mixed_version_config, EXCLUDE_TAGS), + "{0} --suite={1} --mixedBinVersions={2} --excludeWithAnyTags={3} --originSuite={4} " + .format(self.options.resmoke_args, suite, mixed_version_config, EXCLUDE_TAGS, + self.options.suite), "task": gen_task_name, } + # Update the resmoke args to configure the cluster for multiversion testing. + run_tests_vars["resmoke_args"] += get_multiversion_resmoke_args(is_sharded) + if burn_in_test is not None: run_tests_vars["resmoke_args"] += burn_in_test @@ -213,42 +186,38 @@ class EvergreenConfigGenerator(object): .execution_task("{0}_gen".format(task_name)) self.evg_config.variant(self.options.variant).tasks(task_specs).display_task(dt) - def _generate_burn_in_execution_tasks(self, config, suites, burn_in_test, burn_in_idx): + def _generate_burn_in_execution_tasks(self, version_configs, suites, burn_in_test, burn_in_idx, + is_sharded): + # pylint: disable=too-many-arguments burn_in_prefix = "burn_in_multiversion" task = "{0}:{1}".format(burn_in_prefix, self.task) - for version_config in config.version_configs: + for version_config in version_configs: # For burn in tasks, it doesn't matter which generated suite yml to use as all the # yaml configurations are the same. source_suite = os.path.join(CONFIG_DIR, suites[0].name + ".yml") - self._generate_sub_task(version_config, task, burn_in_idx, source_suite, 1, + self._generate_sub_task(version_config, task, burn_in_idx, source_suite, 1, is_sharded, burn_in_test) return self.evg_config - def _get_fuzzer_options(self, version_config, suite_file): + def _get_fuzzer_options(self, version_config, is_sharded): fuzzer_config = generate_resmoke.ConfigOptions(self.options.config) fuzzer_config.name = f"{self.options.suite}_multiversion" fuzzer_config.num_files = int(self.options.num_files) fuzzer_config.num_tasks = int(self.options.num_tasks) + add_resmoke_args = get_multiversion_resmoke_args(is_sharded) fuzzer_config.resmoke_args = f"{self.options.resmoke_args} "\ - f"--mixedBinVersions={version_config} --excludeWithAnyTags={EXCLUDE_TAGS}"\ - f" --suites={CONFIG_DIR}/{suite_file}" + f"--mixedBinVersions={version_config} {add_resmoke_args}" return fuzzer_config - def _generate_fuzzer_tasks(self, config): - suite_file = self.options.suite + ".yml" - # Update the jstestfuzz yml suite with the proper multiversion configurations. - source_config = generate_resmoke.read_yaml(TEST_SUITE_DIR, suite_file) - config.update_yaml(source_config) - updated_yml = generate_resmoke.generate_resmoke_suite_config(source_config, suite_file) - file_dict = {f"{self.options.suite}.yml": updated_yml} + def _generate_fuzzer_tasks(self, version_configs, is_sharded): dt = DisplayTaskDefinition(self.task) - for version_config in config.version_configs: - fuzzer_config = self._get_fuzzer_options(version_config, suite_file) + for version_config in version_configs: + fuzzer_config = generate_resmoke.ConfigOptions(self.options.config) + fuzzer_config = self._get_fuzzer_options(version_config, is_sharded) gen_fuzzer.generate_evg_tasks(fuzzer_config, self.evg_config, task_name_suffix=version_config, display_task=dt) - generate_resmoke.write_file_dict(CONFIG_DIR, file_dict) dt.execution_task(f"{fuzzer_config.name}_gen") self.evg_config.variant(self.options.variant).display_task(dt) return self.evg_config @@ -263,15 +232,14 @@ class EvergreenConfigGenerator(object): :param burn_in_test: The test to be run as part of the burn in multiversion suite. """ - if is_suite_sharded(TEST_SUITE_DIR, self.options.suite): - config = MultiversionConfig(update_suite_config_for_multiversion_sharded, - SHARDED_MIXED_VERSION_CONFIGS) + is_sharded = is_suite_sharded(TEST_SUITE_DIR, self.options.suite) + if is_sharded: + version_configs = SHARDED_MIXED_VERSION_CONFIGS else: - config = MultiversionConfig(update_suite_config_for_multiversion_replset, - REPL_MIXED_VERSION_CONFIGS) + version_configs = REPL_MIXED_VERSION_CONFIGS if self.options.is_jstestfuzz: - return self._generate_fuzzer_tasks(config) + return self._generate_fuzzer_tasks(version_configs, is_sharded) # Divide tests into suites based on run-time statistics for the last # LOOKBACK_DURATION_DAYS. Tests without enough run-time statistics will be placed @@ -280,37 +248,32 @@ class EvergreenConfigGenerator(object): end_date = datetime.datetime.utcnow().replace(microsecond=0) start_date = end_date - datetime.timedelta(days=generate_resmoke.LOOKBACK_DURATION_DAYS) suites = gen_suites.calculate_suites(start_date, end_date) - # Update the base suite names to the multiversion task names. - for suite in suites: - suite.source_name = self.task # Render the given suites into yml files that can be used by resmoke.py. - config_file_dict = generate_resmoke.render_suite_files( - suites, self.options.suite, gen_suites.test_list, TEST_SUITE_DIR, config.update_yaml) - # Update the base misc suite name to the multiversion name. - base_misc_file = f"{self.options.suite}_misc.yml" - misc_suite_name = f"{self.task}_misc.yml" - misc_suite = os.path.join(CONFIG_DIR, misc_suite_name) - config_file_dict[misc_suite_name] = config_file_dict.pop(base_misc_file) + config_file_dict = generate_resmoke.render_suite_files(suites, self.options.suite, + gen_suites.test_list, TEST_SUITE_DIR) generate_resmoke.write_file_dict(CONFIG_DIR, config_file_dict) if burn_in_test is not None: # Generate the subtasks to run burn_in_test against the appropriate mixed version # configurations. The display task is defined later as part of generating the burn # in tests. - self._generate_burn_in_execution_tasks(config, suites, burn_in_test, burn_in_idx) + self._generate_burn_in_execution_tasks(version_configs, suites, burn_in_test, + burn_in_idx, is_sharded) return self.evg_config - for version_config in config.version_configs: + for version_config in version_configs: idx = 0 for suite in suites: # Generate the newly divided test suites source_suite = os.path.join(CONFIG_DIR, suite.name + ".yml") - self._generate_sub_task(version_config, self.task, idx, source_suite, len(suites)) + self._generate_sub_task(version_config, self.task, idx, source_suite, len(suites), + is_sharded) idx += 1 # Also generate the misc task. misc_suite_name = "{0}_misc".format(self.options.suite) - self._generate_sub_task(version_config, self.task, idx, misc_suite, 1) + misc_suite = os.path.join(CONFIG_DIR, misc_suite_name + ".yml") + self._generate_sub_task(version_config, self.task, idx, misc_suite, 1, is_sharded) idx += 1 self.create_display_task(self.task, self.task_specs, self.task_names) return self.evg_config diff --git a/buildscripts/evergreen_generate_resmoke_tasks.py b/buildscripts/evergreen_generate_resmoke_tasks.py index ea9cbb4ed1d..5736dcdb49e 100755 --- a/buildscripts/evergreen_generate_resmoke_tasks.py +++ b/buildscripts/evergreen_generate_resmoke_tasks.py @@ -375,8 +375,7 @@ def generate_resmoke_suite_config(source_config, source_file, roots=None, exclud return contents -def render_suite_files(suites: List, suite_name: str, test_list: List[str], suite_dir, - update_source_config_cb=None): +def render_suite_files(suites: List, suite_name: str, test_list: List[str], suite_dir): """ Render the given list of suites. @@ -391,8 +390,6 @@ def render_suite_files(suites: List, suite_name: str, test_list: List[str], suit :return: Dictionary of rendered resmoke config files. """ source_config = read_yaml(suite_dir, suite_name + ".yml") - if update_source_config_cb is not None: - update_source_config_cb(source_config) suite_configs = { f"{os.path.basename(suite.name)}.yml": suite.generate_resmoke_config(source_config) for suite in suites diff --git a/buildscripts/resmokelib/config.py b/buildscripts/resmokelib/config.py index c1566dd6a02..33f00f48d19 100644 --- a/buildscripts/resmokelib/config.py +++ b/buildscripts/resmokelib/config.py @@ -95,6 +95,9 @@ DEFAULTS = { "tag_file": None, "transport_layer": None, "mixed_bin_versions": None, + "linear_chain": None, + "num_replset_nodes": None, + "num_shards": None, # Evergreen options. "build_id": None, @@ -386,6 +389,15 @@ MAJORITY_READ_CONCERN = None # Specifies the binary versions of each node we should run for a replica set. MIXED_BIN_VERSIONS = None +# Specifies the number of replica set members in a ReplicaSetFixture. +NUM_REPLSET_NODES = None + +# Specifies the number of shards in a ShardedClusterFixture. +NUM_SHARDS = None + +# If true, run ReplicaSetFixture with linear chaining. +LINEAR_CHAIN = None + # If set to "on", it enables flow control. If set to "off", it disables flow control. If left as # None, the server's default will determine whether flow control is enabled. FLOW_CONTROL = None diff --git a/buildscripts/resmokelib/parser.py b/buildscripts/resmokelib/parser.py index ef57ab66af7..f6ed3417e82 100644 --- a/buildscripts/resmokelib/parser.py +++ b/buildscripts/resmokelib/parser.py @@ -267,6 +267,15 @@ def _make_parser(): # pylint: disable=too-many-statements help="Sets the storage engine cache size configuration" " setting for all mongod's.") + parser.add_option( + "--numReplSetNodes", type="int", dest="num_replset_nodes", metavar="N", + help="The number of nodes to initialize per ReplicaSetFixture. This is also " + "used to indicate the number of replica set members per shard in a " + "ShardedClusterFixture.") + + parser.add_option("--numShards", type="int", dest="num_shards", metavar="N", + help="The number of shards to use in a ShardedClusterFixture.") + parser.add_option("--tagFile", dest="tag_file", metavar="OPTIONS", help="A YAML file that associates tests and tags.") @@ -291,6 +300,11 @@ def _make_parser(): # pylint: disable=too-many-statements " 'last-stable' version primary and 'latest' version secondary. For a sharded cluster" " with two shards and two replica set nodes each, specify 'old-new-old-new'.") + parser.add_option( + "--linearChain", type="choice", action="store", dest="linear_chain", choices=("on", "off"), + metavar="ON|OFF", help="Enable or disable linear chaining for tests using " + "ReplicaSetFixture.") + evergreen_options = optparse.OptionGroup( parser, title=_EVERGREEN_OPTIONS_TITLE, description=("Options used to propagate information about the Evergreen task running this" @@ -594,6 +608,7 @@ def _update_config_vars(values): # pylint: disable=too-many-statements,too-many _config.INCLUDE_WITH_ANY_TAGS = _tags_from_list(config.pop("include_with_any_tags")) _config.GENNY_EXECUTABLE = _expand_user(config.pop("genny_executable")) _config.JOBS = config.pop("jobs") + _config.LINEAR_CHAIN = config.pop("linear_chain") == "on" _config.MAJORITY_READ_CONCERN = config.pop("majority_read_concern") == "on" _config.MIXED_BIN_VERSIONS = config.pop("mixed_bin_versions") if _config.MIXED_BIN_VERSIONS is not None: @@ -606,6 +621,8 @@ def _update_config_vars(values): # pylint: disable=too-many-statements,too-many _config.MONGOS_SET_PARAMETERS = config.pop("mongos_set_parameters") _config.NO_JOURNAL = config.pop("no_journal") _config.NUM_CLIENTS_PER_FIXTURE = config.pop("num_clients_per_fixture") + _config.NUM_REPLSET_NODES = config.pop("num_replset_nodes") + _config.NUM_SHARDS = config.pop("num_shards") _config.PERF_REPORT_FILE = config.pop("perf_report_file") _config.RANDOM_SEED = config.pop("seed") _config.REPEAT_SUITES = config.pop("repeat_suites") diff --git a/buildscripts/resmokelib/testing/fixtures/replicaset.py b/buildscripts/resmokelib/testing/fixtures/replicaset.py index efa4c7bea6a..22e2d1e1614 100644 --- a/buildscripts/resmokelib/testing/fixtures/replicaset.py +++ b/buildscripts/resmokelib/testing/fixtures/replicaset.py @@ -34,7 +34,6 @@ class ReplicaSetFixture(interface.ReplFixture): # pylint: disable=too-many-inst 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 @@ -42,9 +41,15 @@ class ReplicaSetFixture(interface.ReplFixture): # pylint: disable=too-many-inst self.voting_secondaries = voting_secondaries self.all_nodes_electable = all_nodes_electable self.use_replica_set_connection_string = use_replica_set_connection_string - self.linear_chain = linear_chain self.mixed_bin_versions = utils.default_if_none(mixed_bin_versions, config.MIXED_BIN_VERSIONS) + + # Use the values given from the command line if they exist for linear_chain and num_nodes. + linear_chain_option = utils.default_if_none(config.LINEAR_CHAIN, linear_chain) + self.linear_chain = linear_chain_option if linear_chain_option else linear_chain + num_replset_nodes = config.NUM_REPLSET_NODES + self.num_nodes = num_replset_nodes if num_replset_nodes else num_nodes + if self.mixed_bin_versions is not None: mongod_executable = utils.default_if_none(config.MONGOD_EXECUTABLE, config.DEFAULT_MONGOD_EXECUTABLE) @@ -63,9 +68,9 @@ class ReplicaSetFixture(interface.ReplFixture): # pylint: disable=too-many-inst # server nodes will always be fully upgraded before shard nodes. self.mixed_bin_versions = [latest_mongod, latest_mongod] num_versions = len(self.mixed_bin_versions) - if num_versions != num_nodes and not is_config_svr: + if num_versions != self.num_nodes and not is_config_svr: msg = (("The number of binary versions specified: {} do not match the number of"\ - " nodes in the replica set: {}.")).format(num_versions, num_nodes) + " nodes in the replica set: {}.")).format(num_versions, self.num_nodes) raise errors.ServerFailure(msg) # By default, we only use a replica set connection string if all nodes are capable of being diff --git a/buildscripts/resmokelib/testing/fixtures/shardedcluster.py b/buildscripts/resmokelib/testing/fixtures/shardedcluster.py index 5b808f9b458..edefdf11f9f 100644 --- a/buildscripts/resmokelib/testing/fixtures/shardedcluster.py +++ b/buildscripts/resmokelib/testing/fixtures/shardedcluster.py @@ -41,8 +41,11 @@ class ShardedClusterFixture(interface.Fixture): # pylint: disable=too-many-inst self.mongod_options["set_parameters"]["migrationLockAcquisitionMaxWaitMS"] = \ mongod_options["set_parameters"].get("migrationLockAcquisitionMaxWaitMS", 30000) self.preserve_dbpath = preserve_dbpath - self.num_shards = num_shards - self.num_rs_nodes_per_shard = num_rs_nodes_per_shard + # Use 'num_shards' and 'num_rs_nodes_per_shard' values from the command line if they exist. + num_shards_option = config.NUM_SHARDS + self.num_shards = num_shards if not num_shards_option else num_shards_option + num_rs_nodes_per_shard_option = config.NUM_REPLSET_NODES + self.num_rs_nodes_per_shard = num_rs_nodes_per_shard if not num_rs_nodes_per_shard_option else num_rs_nodes_per_shard_option self.num_mongos = num_mongos self.enable_sharding = utils.default_if_none(enable_sharding, []) self.enable_balancer = enable_balancer |