summaryrefslogtreecommitdiff
path: root/buildscripts
diff options
context:
space:
mode:
authorJason Chan <jason.chan@mongodb.com>2019-11-25 19:48:23 +0000
committerevergreen <evergreen@mongodb.com>2019-11-25 19:48:23 +0000
commit5c86d41207c3a8aba3adffc1c992561599d2aaa5 (patch)
tree1fdae50c0c78817276e7089d70708b8d73d2335c /buildscripts
parent96be927c235887791941fe9cffc57c9d3e66df57 (diff)
downloadmongo-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-xbuildscripts/evergreen_gen_fuzzer_tests.py13
-rwxr-xr-xbuildscripts/evergreen_gen_multiversion_tests.py113
-rwxr-xr-xbuildscripts/evergreen_generate_resmoke_tasks.py5
-rw-r--r--buildscripts/resmokelib/config.py12
-rw-r--r--buildscripts/resmokelib/parser.py17
-rw-r--r--buildscripts/resmokelib/testing/fixtures/replicaset.py13
-rw-r--r--buildscripts/resmokelib/testing/fixtures/shardedcluster.py7
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