def mongod_program(logger, job_num, executable, process_kwargs, mongod_options): """ Return a Process instance that starts mongod arguments constructed from 'mongod_options'. @param logger - The logger to pass into the process. @param executable - The mongod executable to run. @param process_kwargs - A dict of key-value pairs to pass to the process. @param mongod_options - A HistoryDict describing the various options to pass to the mongod. """ args = [executable] mongod_options = mongod_options.copy() if "port" not in mongod_options: mongod_options["port"] = network.PortAllocator.next_fixture_port( job_num) suite_set_parameters = mongod_options.get("set_parameters", make_historic({})) _apply_set_parameters(args, suite_set_parameters) mongod_options.pop("set_parameters") # Apply the rest of the command line arguments. _apply_kwargs(args, mongod_options) _set_keyfile_permissions(mongod_options) process_kwargs = make_historic(utils.default_if_none(process_kwargs, {})) process_kwargs["job_num"] = job_num if config.EXPORT_MONGOD_CONFIG == "regular": mongod_options.dump_history(f"{logger.name}_config.yml") elif config.EXPORT_MONGOD_CONFIG == "detailed": mongod_options.dump_history(f"{logger.name}_config.yml", include_location=True) return make_process(logger, args, **process_kwargs), mongod_options["port"]
def _new_rs_shard(self, index, num_rs_nodes_per_shard): """Return a replicaset.ReplicaSetFixture configured as a shard in a sharded cluster.""" shard_logging_prefix = f"shard{index}" mongod_logger = logging.loggers.new_fixture_node_logger(self.__class__.__name__, self.job_num, shard_logging_prefix) shard_options = self.shard_options.copy() auth_options = shard_options.pop("auth_options", self.auth_options) preserve_dbpath = shard_options.pop("preserve_dbpath", self.preserve_dbpath) replset_config_options = make_historic(shard_options.pop("replset_config_options", {})) replset_config_options["configsvr"] = False mixed_bin_versions = self.mixed_bin_versions if mixed_bin_versions is not None: start_index = index * num_rs_nodes_per_shard mixed_bin_versions = mixed_bin_versions[start_index:start_index + num_rs_nodes_per_shard] mongod_options = self.mongod_options.copy() mongod_options.update(make_historic(shard_options.pop("mongod_options", {}))) mongod_options["shardsvr"] = "" mongod_options["dbpath"] = os.path.join(self._dbpath_prefix, "shard{}".format(index)) mongod_options["replSet"] = ShardedClusterFixture._SHARD_REPLSET_NAME_PREFIX + str(index) return replicaset.ReplicaSetFixture( mongod_logger, self.job_num, mongod_executable=self.mongod_executable, mongod_options=mongod_options, preserve_dbpath=preserve_dbpath, num_nodes=num_rs_nodes_per_shard, auth_options=auth_options, replset_config_options=replset_config_options, mixed_bin_versions=mixed_bin_versions, shard_logging_prefix=shard_logging_prefix, **shard_options)
def __init__( # pylint: disable=too-many-arguments,too-many-locals self, logger, job_num, mongos_executable=None, mongos_options=None, mongod_executable=None, mongod_options=None, dbpath_prefix=None, preserve_dbpath=False, num_shards=1, num_rs_nodes_per_shard=1, num_mongos=1, enable_sharding=None, enable_balancer=True, enable_autosplit=True, auth_options=None, configsvr_options=None, shard_options=None, mixed_bin_versions=None): """Initialize ShardedClusterFixture with different options for the cluster processes.""" interface.Fixture.__init__(self, logger, job_num, dbpath_prefix=dbpath_prefix) if "dbpath" in mongod_options: raise ValueError("Cannot specify mongod_options.dbpath") self.mongos_executable = mongos_executable self.mongos_options = make_historic(utils.default_if_none(mongos_options, {})) self.mongod_options = make_historic(utils.default_if_none(mongod_options, {})) self.mongod_executable = mongod_executable self.mongod_options["set_parameters"] = make_historic( mongod_options.get("set_parameters", {})).copy() self.mongod_options["set_parameters"]["migrationLockAcquisitionMaxWaitMS"] = \ self.mongod_options["set_parameters"].get("migrationLockAcquisitionMaxWaitMS", 30000) self.preserve_dbpath = preserve_dbpath # 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 self.enable_autosplit = enable_autosplit self.auth_options = auth_options self.configsvr_options = make_historic(utils.default_if_none(configsvr_options, {})) self.shard_options = make_historic(utils.default_if_none(shard_options, {})) self.mixed_bin_versions = utils.default_if_none(mixed_bin_versions, config.MIXED_BIN_VERSIONS) if self.num_rs_nodes_per_shard is None: raise TypeError("num_rs_nodes_per_shard must be an integer but found None") elif isinstance(self.num_rs_nodes_per_shard, int): if self.num_rs_nodes_per_shard <= 0: raise ValueError("num_rs_nodes_per_shard must be a positive integer") if self.mixed_bin_versions is not None: num_mongods = self.num_shards * self.num_rs_nodes_per_shard if len(self.mixed_bin_versions) != num_mongods: msg = (("The number of binary versions specified: {} do not match the number of"\ " nodes in the sharded cluster: {}.")).format(len(self.mixed_bin_versions), num_mongods) raise errors.ServerFailure(msg) self._dbpath_prefix = os.path.join(self._dbpath_prefix, config.FIXTURE_SUBDIR) self.configsvr = None self.mongos = [] self.shards = []
def mongos_program( # pylint: disable=too-many-arguments logger, job_num, test_id=None, executable=None, process_kwargs=None, mongos_options=None): """Return a Process instance that starts a mongos with arguments constructed from 'kwargs'.""" args = [executable] mongos_options = mongos_options.copy() if "port" not in mongos_options: mongos_options["port"] = network.PortAllocator.next_fixture_port( job_num) suite_set_parameters = mongos_options.get("set_parameters", {}) _apply_set_parameters(args, suite_set_parameters) mongos_options.pop("set_parameters") # Apply the rest of the command line arguments. _apply_kwargs(args, mongos_options) _set_keyfile_permissions(mongos_options) process_kwargs = make_historic(utils.default_if_none(process_kwargs, {})) process_kwargs["job_num"] = job_num process_kwargs["test_id"] = test_id return make_process(logger, args, **process_kwargs), mongos_options["port"]
def _new_configsvr(self): """Return a replicaset.ReplicaSetFixture configured as the config server.""" shard_logging_prefix = "configsvr" mongod_logger = logging.loggers.new_fixture_node_logger(self.__class__.__name__, self.job_num, shard_logging_prefix) configsvr_options = self.configsvr_options.copy() auth_options = configsvr_options.pop("auth_options", self.auth_options) preserve_dbpath = configsvr_options.pop("preserve_dbpath", self.preserve_dbpath) num_nodes = configsvr_options.pop("num_nodes", 1) replset_config_options = configsvr_options.pop("replset_config_options", {}) replset_config_options["configsvr"] = True mongod_options = self.mongod_options.copy() mongod_options.update(make_historic(configsvr_options.pop("mongod_options", {}))) mongod_options["configsvr"] = "" mongod_options["dbpath"] = os.path.join(self._dbpath_prefix, "config") mongod_options["replSet"] = ShardedClusterFixture._CONFIGSVR_REPLSET_NAME mongod_options["storageEngine"] = "wiredTiger" return replicaset.ReplicaSetFixture( mongod_logger, self.job_num, mongod_options=mongod_options, mongod_executable=self.mongod_executable, preserve_dbpath=preserve_dbpath, num_nodes=num_nodes, auth_options=auth_options, mixed_bin_versions=None, replset_config_options=replset_config_options, shard_logging_prefix=shard_logging_prefix, **configsvr_options)
def __init__( # pylint: disable=too-many-arguments self, logger, job_num, mongod_executable=None, mongod_options=None, dbpath_prefix=None, preserve_dbpath=False): """Initialize MongoDFixture with different options for the mongod process.""" self.mongod_options = make_historic( utils.default_if_none(mongod_options, {})) interface.Fixture.__init__(self, logger, job_num, dbpath_prefix=dbpath_prefix) if "dbpath" in self.mongod_options and dbpath_prefix is not None: raise ValueError( "Cannot specify both mongod_options.dbpath and dbpath_prefix") # Default to command line options if the YAML configuration is not passed in. self.mongod_executable = utils.default_if_none( mongod_executable, config.MONGOD_EXECUTABLE) self.mongod_options = make_historic( utils.default_if_none(mongod_options, {})).copy() # The dbpath in mongod_options takes precedence over other settings to make it easier for # users to specify a dbpath containing data to test against. if "dbpath" not in self.mongod_options: self.mongod_options["dbpath"] = os.path.join( self._dbpath_prefix, config.FIXTURE_SUBDIR) self._dbpath = self.mongod_options["dbpath"] if config.ALWAYS_USE_LOG_FILES: self.mongod_options["logpath"] = self._dbpath + "/mongod.log" self.mongod_options["logappend"] = "" self.preserve_dbpath = True else: self.preserve_dbpath = preserve_dbpath self.mongod = None self.port = None
def test_make_historic(self): actual_dict = { "foo": "bar", "a": "b", "innerdict": { "innerkey": "innerval" } } test_dict = make_historic(actual_dict) test_dict["a"] = "c" # Updating actual_dict doesn't affect test_dict (it copied). actual_dict["foo"] = "za" # Similarly, updating the inner dict doesn't either. actual_dict["innerdict"]["innerkey"] = "innerval2" # However, updating the inner dict on the test_dict does. test_dict["innerdict"]["innerkey"] = "secondinnerval" expected_test_dict = """SchemaVersion: "0.1" History: a: - time: 1 type: WRITE value_written: b - time: 3 type: WRITE value_written: c foo: - time: 0 type: WRITE value_written: bar innerdict: - time: 2 type: WRITE value_written: object_class: dict object_value: innerkey: innerval - time: 4 type: WRITE value_written: object_class: dict object_value: innerkey: secondinnerval""" self.assertEqual(test_dict.dump_history(), expected_test_dict)
def mongos_program(logger, job_num, test_id=None, executable=None, process_kwargs=None, **kwargs): """Return a Process instance that starts a mongos with arguments constructed from 'kwargs'.""" executable = utils.default_if_none(executable, config.DEFAULT_MONGOS_EXECUTABLE) args = [executable] # Apply the --setParameter command line argument. Command line options to resmoke.py override # the YAML configuration. suite_set_parameters = make_historic(kwargs.pop("set_parameters", {})) if config.MONGOS_SET_PARAMETERS is not None: suite_set_parameters.update( utils.load_yaml(config.MONGOS_SET_PARAMETERS)) # Set default log verbosity levels if none were specified. if "logComponentVerbosity" not in suite_set_parameters: suite_set_parameters[ "logComponentVerbosity"] = default_mongos_log_component_verbosity( ) _add_testing_set_parameters(suite_set_parameters) _apply_set_parameters(args, suite_set_parameters) # Apply the rest of the command line arguments. _apply_kwargs(args, kwargs) _set_keyfile_permissions(kwargs) process_kwargs = make_historic(utils.default_if_none(process_kwargs, {})) process_kwargs["job_num"] = job_num process_kwargs["test_id"] = test_id return make_process(logger, args, **process_kwargs)
def __init__(self, logger, job_num, dbpath_prefix, mongos_executable=None, mongos_options=None): """Initialize _MongoSFixture.""" interface.Fixture.__init__(self, logger, job_num) # Default to command line options if the YAML configuration is not passed in. self.mongos_executable = utils.default_if_none(mongos_executable, config.MONGOS_EXECUTABLE) self.mongos_options = make_historic(utils.default_if_none(mongos_options, {})).copy() self.mongos = None self.port = None self._dbpath_prefix = dbpath_prefix
def test_write_equality(self): test_dict = HistoryDict() test_dict["foo"] = "bar" test_dict["myint"] = 1 test_dict["foo"] = "za" test_dict["innerdict"] = make_historic({"a": "b"}) second_dict = HistoryDict() second_dict["foo"] = "bar" second_dict["myint"] = 1 second_dict["foo"] = "za" second_dict["innerdict"] = make_historic({"a": "b"}) self.assertTrue(test_dict.write_equals(second_dict)) second_dict["another"] = "write" self.assertFalse(test_dict.write_equals(second_dict)) test_dict["another"] = "write" self.assertTrue(test_dict.write_equals(second_dict)) # Reads aren't counted gotten_value = second_dict["foo"] # pylint: disable=unused-variable self.assertTrue(test_dict.write_equals(second_dict))
def mongos_program(logger, job_num, test_id=None, executable=None, process_kwargs=None, **kwargs): """Return a Process instance that starts a mongos with arguments constructed from 'kwargs'.""" args = [executable] suite_set_parameters = kwargs.get("set_parameters", {}) _apply_set_parameters(args, suite_set_parameters) kwargs.pop("set_parameters") # Apply the rest of the command line arguments. _apply_kwargs(args, kwargs) _set_keyfile_permissions(kwargs) process_kwargs = make_historic(utils.default_if_none(process_kwargs, {})) process_kwargs["job_num"] = job_num process_kwargs["test_id"] = test_id return make_process(logger, args, **process_kwargs)
def __init__( # pylint: disable=too-many-arguments, too-many-locals self, logger, job_num, mongod_executable=None, mongod_options=None, 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, voting_secondaries=True, all_nodes_electable=False, use_replica_set_connection_string=None, linear_chain=False, mixed_bin_versions=None, default_read_concern=None, default_write_concern=None, shard_logging_prefix=None, replicaset_logging_prefix=None): """Initialize ReplicaSetFixture.""" interface.ReplFixture.__init__(self, logger, job_num, dbpath_prefix=dbpath_prefix) self.mongod_executable = mongod_executable self.mongod_options = make_historic( utils.default_if_none(mongod_options, {})) self.preserve_dbpath = preserve_dbpath 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 = make_historic( utils.default_if_none(replset_config_options, {})) self.voting_secondaries = voting_secondaries self.all_nodes_electable = all_nodes_electable self.use_replica_set_connection_string = use_replica_set_connection_string self.default_read_concern = default_read_concern self.default_write_concern = default_write_concern self.mixed_bin_versions = utils.default_if_none( mixed_bin_versions, config.MIXED_BIN_VERSIONS) self.mixed_bin_versions_config = self.mixed_bin_versions self.shard_logging_prefix = shard_logging_prefix self.replicaset_logging_prefix = replicaset_logging_prefix # 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( self.mongod_executable, config.MONGOD_EXECUTABLE, config.DEFAULT_MONGOD_EXECUTABLE) latest_mongod = mongod_executable # The last-lts binary is currently expected to live in '/data/multiversion', which is # part of the PATH. is_config_svr = "configsvr" in self.replset_config_options and self.replset_config_options[ "configsvr"] if not is_config_svr: self.mixed_bin_versions = [ latest_mongod if (x == "new") else LAST_LTS_MONGOD_BINARY for x in self.mixed_bin_versions ] else: # Our documented recommended path for upgrading shards lets us assume that config # 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 != 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, self.num_nodes) raise errors.ServerFailure(msg) # By default, we only use a replica set connection string if all nodes are capable of being # elected primary. if self.use_replica_set_connection_string is None: self.use_replica_set_connection_string = self.all_nodes_electable if self.default_write_concern is True: self.default_write_concern = make_historic({ "w": "majority", # Use a "signature" value that won't typically match a value assigned in normal use. # This way the wtimeout set by this override is distinguishable in the server logs. "wtimeout": 5 * 60 * 1000 + 321, # 300321ms }) # Set the default oplogSize to 511MB. self.mongod_options.setdefault("oplogSize", 511) # The dbpath in mongod_options is used as the dbpath prefix for replica set members and # takes precedence over other settings. The ShardedClusterFixture uses this parameter to # create replica sets and assign their dbpath structure explicitly. if "dbpath" in self.mongod_options: self._dbpath_prefix = self.mongod_options.pop("dbpath") else: self._dbpath_prefix = os.path.join(self._dbpath_prefix, config.FIXTURE_SUBDIR) self.nodes = [] self.replset_name = None self.initial_sync_node = None self.initial_sync_node_idx = -1
def setup(self): # pylint: disable=too-many-branches,too-many-statements,too-many-locals """Set up the replica set.""" self.replset_name = self.mongod_options.get("replSet", "rs") if not self.nodes: for i in range(self.num_nodes): node = self._new_mongod(i, self.replset_name) self.nodes.append(node) for i in range(self.num_nodes): steady_state_constraint_param = "oplogApplicationEnforcesSteadyStateConstraints" # TODO (SERVER-52985): Set steady state constraint parameters on last-lts nodes. if (steady_state_constraint_param not in self.nodes[i].mongod_options["set_parameters"] and self.mixed_bin_versions is not None and self.mixed_bin_versions[i] == "new"): self.nodes[i].mongod_options["set_parameters"][ steady_state_constraint_param] = True if self.linear_chain and i > 0: self.nodes[i].mongod_options["set_parameters"][ "failpoint.forceSyncSourceCandidate"] = make_historic({ "mode": "alwaysOn", "data": { "hostAndPort": self.nodes[i - 1].get_internal_connection_string() } }) self.nodes[i].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() if self.mixed_bin_versions: for i in range(self.num_nodes): if self.nodes[i].mongod_executable != self.mixed_bin_versions[ i]: msg = ( f"Executable of node{i}: {self.nodes[i].mongod_executable} does not " f"match the executable assigned by mixedBinVersions: " f"{self.mixed_bin_versions[i]}.") raise errors.ServerFailure(msg) # We need only to wait to connect to the first node of the replica set because we first # initiate it as a single node replica set. self.nodes[0].await_ready() # Initiate the replica set. members = [] for (i, node) in enumerate(self.nodes): member_info = { "_id": i, "host": node.get_internal_connection_string() } if i > 0: if not self.all_nodes_electable: member_info["priority"] = 0 if i >= 7 or not self.voting_secondaries: # Only 7 nodes in a replica set can vote, so the other members must still be # non-voting when this fixture is configured to have voting secondaries. 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_internal_connection_string(), "priority": 0, "hidden": 1, "votes": 0 }) repl_config = {"_id": self.replset_name, "protocolVersion": 1} client = self.nodes[0].mongo_client() self.auth(client, self.auth_options) if client.local.system.replset.count(): # Skip initializing the replset if there is an existing configuration. return if self.write_concern_majority_journal_default is not None: repl_config[ "writeConcernMajorityJournalDefault"] = self.write_concern_majority_journal_default else: server_status = client.admin.command({"serverStatus": 1}) cmd_line_opts = client.admin.command({"getCmdLineOpts": 1}) if not (server_status["storageEngine"]["persistent"] and cmd_line_opts["parsed"].get("storage", {}).get( "journal", {}).get("enabled", True)): repl_config["writeConcernMajorityJournalDefault"] = False if self.replset_config_options.get("configsvr", False): repl_config["configsvr"] = True if self.replset_config_options.get("settings"): replset_settings = self.replset_config_options["settings"] repl_config["settings"] = replset_settings # Increase the election timeout to 24 hours to prevent spurious elections. repl_config.setdefault("settings", {}) if "electionTimeoutMillis" not in repl_config["settings"]: repl_config["settings"][ "electionTimeoutMillis"] = 24 * 60 * 60 * 1000 # Start up a single node replica set then reconfigure to the correct size (if the config # contains more than 1 node), so the primary is elected more quickly. repl_config["members"] = [members[0]] self.logger.info("Issuing replSetInitiate command: %s", repl_config) self._initiate_repl_set(client, repl_config) self._await_primary() if self.mixed_bin_versions is not None: if self.mixed_bin_versions[0] == "new": fcv_response = client.admin.command({ "getParameter": 1, "featureCompatibilityVersion": 1 }) fcv = fcv_response["featureCompatibilityVersion"]["version"] if fcv != ReplicaSetFixture._LATEST_FCV: msg = (("Server returned FCV{} when we expected FCV{}." ).format(fcv, ReplicaSetFixture._LATEST_FCV)) raise errors.ServerFailure(msg) # Initiating a replica set with a single node will use "latest" FCV. This will # cause IncompatibleServerVersion errors if additional "last-lts" binary version # nodes are subsequently added to the set, since such nodes cannot set their FCV to # "latest". Therefore, we make sure the primary is "last-lts" FCV before adding in # nodes of different binary versions to the replica set. client.admin.command({ "setFeatureCompatibilityVersion": ReplicaSetFixture._LAST_LTS_FCV }) if self.nodes[1:]: # Wait to connect to each of the secondaries before running the replSetReconfig # command. for node in self.nodes[1:]: node.await_ready() # Add in the members one at a time, since non force reconfigs can only add/remove a # single voting member at a time. for ind in range(2, len(members) + 1): self._add_node_to_repl_set(client, repl_config, ind, members) self._await_secondaries() self._await_newly_added_removals()
from buildscripts.resmokelib import config from buildscripts.resmokelib import core from buildscripts.resmokelib import errors from buildscripts.resmokelib import logging from buildscripts.resmokelib import utils from buildscripts.resmokelib.utils.history import make_historic from buildscripts.resmokelib.multiversionconstants import LAST_LTS_MONGOS_BINARY from buildscripts.resmokelib.testing.fixtures import interface from buildscripts.resmokelib.testing.fixtures import replicaset from buildscripts.resmokelib.testing.fixtures import standalone from buildscripts.resmokelib.utils import registry # The default verbosity setting for any tests that are not started with an Evergreen task id. This # will apply to any tests run locally. DEFAULT_MONGOS_LOG_COMPONENT_VERBOSITY = make_historic({"transaction": 3}) # The default verbosity setting for any tests running in Evergreen i.e. started with an Evergreen # task id. DEFAULT_EVERGREEN_MONGOS_LOG_COMPONENT_VERBOSITY = make_historic( {"transaction": 3}) class ShardedClusterFixture(interface.Fixture): # pylint: disable=too-many-instance-attributes """Fixture which provides JSTests with a sharded cluster to run against.""" _CONFIGSVR_REPLSET_NAME = "config-rs" _SHARD_REPLSET_NAME_PREFIX = "shard-rs" AWAIT_SHARDING_INITIALIZATION_TIMEOUT_SECS = 60 def __init__( # pylint: disable=too-many-arguments,too-many-locals
def mongod_program( # pylint: disable=too-many-branches,too-many-statements logger, job_num, executable=None, process_kwargs=None, mongod_options=None): """ Return a Process instance that starts mongod arguments constructed from 'mongod_options'. @param logger - The logger to pass into the process. @param executable - The mongod executable to run. @param process_kwargs - A dict of key-value pairs to pass to the process. @param mongod_options - A HistoryDict describing the various options to pass to the mongod. """ executable = utils.default_if_none(executable, config.DEFAULT_MONGOD_EXECUTABLE) mongod_options = utils.default_if_none(mongod_options, make_historic({})).copy() args = [executable] # Apply the --setParameter command line argument. Command line options to resmoke.py override # the YAML configuration. # We leave the parameters attached for now so the top-level dict tracks its history. suite_set_parameters = mongod_options.setdefault("set_parameters", make_historic({})) if config.MONGOD_SET_PARAMETERS is not None: suite_set_parameters.update( make_historic(utils.load_yaml(config.MONGOD_SET_PARAMETERS))) # Set default log verbosity levels if none were specified. if "logComponentVerbosity" not in suite_set_parameters: suite_set_parameters[ "logComponentVerbosity"] = get_default_log_component_verbosity_for_mongod( executable) # minNumChunksForSessionsCollection controls the minimum number of chunks the balancer will # enforce for the sessions collection. If the actual number of chunks is less, the balancer will # issue split commands to create more chunks. As a result, the balancer will also end up moving # chunks for the sessions collection to balance the chunks across shards. Unless the suite is # explicitly prepared to handle these background migrations, set the parameter to 1. if "configsvr" in mongod_options and "minNumChunksForSessionsCollection" not in suite_set_parameters: suite_set_parameters["minNumChunksForSessionsCollection"] = 1 # orphanCleanupDelaySecs controls an artificial delay before cleaning up an orphaned chunk # that has migrated off of a shard, meant to allow most dependent queries on secondaries to # complete first. It defaults to 900, or 15 minutes, which is prohibitively long for tests. # Setting it in the .yml file overrides this. if "shardsvr" in mongod_options and "orphanCleanupDelaySecs" not in suite_set_parameters: suite_set_parameters["orphanCleanupDelaySecs"] = 1 # The LogicalSessionCache does automatic background refreshes in the server. This is # race-y for tests, since tests trigger their own immediate refreshes instead. Turn off # background refreshing for tests. Set in the .yml file to override this. if "disableLogicalSessionCacheRefresh" not in suite_set_parameters: suite_set_parameters["disableLogicalSessionCacheRefresh"] = True # Set coordinateCommitReturnImmediatelyAfterPersistingDecision to false so that tests do # not need to rely on causal consistency or explicitly wait for the transaction to finish # committing. If we are running LAST_LTS mongoD and the test suite has explicitly set the # coordinateCommitReturnImmediatelyAfterPersistingDecision parameter, we remove it from # the setParameter list, since coordinateCommitReturnImmediatelyAfterPersistingDecision # does not exist prior to 4.7. # TODO(SERVER-51682): remove the 'elif' clause on master when 5.0 becomes LAST_LTS. if executable != LAST_LTS_MONGOD_BINARY and \ "coordinateCommitReturnImmediatelyAfterPersistingDecision" not in suite_set_parameters: suite_set_parameters[ "coordinateCommitReturnImmediatelyAfterPersistingDecision"] = False elif executable == LAST_LTS_MONGOD_BINARY and \ "coordinateCommitReturnImmediatelyAfterPersistingDecision" in suite_set_parameters: del suite_set_parameters[ "coordinateCommitReturnImmediatelyAfterPersistingDecision"] # TODO SERVER-54593 to remove the special-case handling when 5.0 becomes LAST_LTS. if "reshardingMinimumOperationDurationMillis" in suite_set_parameters: if executable == LAST_LTS_MONGOD_BINARY: del suite_set_parameters[ "reshardingMinimumOperationDurationMillis"] elif executable != LAST_LTS_MONGOD_BINARY: suite_set_parameters["reshardingMinimumOperationDurationMillis"] = 5000 # There's a periodic background thread that checks for and aborts expired transactions. # "transactionLifetimeLimitSeconds" specifies for how long a transaction can run before expiring # and being aborted by the background thread. It defaults to 60 seconds, which is too short to # be reliable for our tests. Setting it to 24 hours, so that it is longer than the Evergreen # execution timeout. if "transactionLifetimeLimitSeconds" not in suite_set_parameters: suite_set_parameters["transactionLifetimeLimitSeconds"] = 24 * 60 * 60 # Hybrid index builds drain writes received during the build process in batches of 1000 writes # by default. Not all tests perform enough writes to exercise the code path where multiple # batches are applied, which means certain bugs are harder to encounter. Set this level lower # so there are more opportunities to drain writes in multiple batches. if "maxIndexBuildDrainBatchSize" not in suite_set_parameters: suite_set_parameters["maxIndexBuildDrainBatchSize"] = 10 # The periodic no-op writer writes an oplog entry of type='n' once every 10 seconds. This has # the potential to mask issues such as SERVER-31609 because it allows the operationTime of # cluster to advance even if the client is blocked for other reasons. We should disable the # periodic no-op writer. Set in the .yml file to override this. if "replSet" in mongod_options and "writePeriodicNoops" not in suite_set_parameters: suite_set_parameters["writePeriodicNoops"] = False # The default time for stepdown and quiesce mode in response to SIGTERM is 15 seconds. Reduce # this to 100ms for faster shutdown. On branches 4.4 and earlier, there is no quiesce mode, but # the default time for stepdown is 10 seconds. # TODO(SERVER-47797): Remove reference to waitForStepDownOnNonCommandShutdown. if ("replSet" in mongod_options and "waitForStepDownOnNonCommandShutdown" not in suite_set_parameters and "shutdownTimeoutMillisForSignaledShutdown" not in suite_set_parameters): if executable == LAST_LTS_MONGOD_BINARY: suite_set_parameters["waitForStepDownOnNonCommandShutdown"] = False else: suite_set_parameters[ "shutdownTimeoutMillisForSignaledShutdown"] = 100 if "enableFlowControl" not in suite_set_parameters and config.FLOW_CONTROL is not None: suite_set_parameters["enableFlowControl"] = ( config.FLOW_CONTROL == "on") if ("failpoint.flowControlTicketOverride" not in suite_set_parameters and config.FLOW_CONTROL_TICKETS is not None): suite_set_parameters[ "failpoint.flowControlTicketOverride"] = make_historic({ "mode": "alwaysOn", "data": { "numTickets": config.FLOW_CONTROL_TICKETS } }) _add_testing_set_parameters(suite_set_parameters) _apply_set_parameters(args, suite_set_parameters) shortcut_opts = { "enableMajorityReadConcern": config.MAJORITY_READ_CONCERN, "nojournal": config.NO_JOURNAL, "storageEngine": config.STORAGE_ENGINE, "transportLayer": config.TRANSPORT_LAYER, "wiredTigerCollectionConfigString": config.WT_COLL_CONFIG, "wiredTigerEngineConfigString": config.WT_ENGINE_CONFIG, "wiredTigerIndexConfigString": config.WT_INDEX_CONFIG, } if config.STORAGE_ENGINE == "inMemory": shortcut_opts["inMemorySizeGB"] = config.STORAGE_ENGINE_CACHE_SIZE elif config.STORAGE_ENGINE == "rocksdb": shortcut_opts["rocksdbCacheSizeGB"] = config.STORAGE_ENGINE_CACHE_SIZE elif config.STORAGE_ENGINE == "wiredTiger" or config.STORAGE_ENGINE is None: shortcut_opts[ "wiredTigerCacheSizeGB"] = config.STORAGE_ENGINE_CACHE_SIZE # These options are just flags, so they should not take a value. opts_without_vals = ("nojournal", "logappend") # Have the --nojournal command line argument to resmoke.py unset the journal option. if shortcut_opts["nojournal"] and "journal" in mongod_options: del mongod_options["journal"] # Ensure that config servers run with journaling enabled. if "configsvr" in mongod_options: shortcut_opts["nojournal"] = False mongod_options["journal"] = "" # Command line options override the YAML configuration. for opt_name in shortcut_opts: opt_value = shortcut_opts[opt_name] if opt_name in opts_without_vals: # Options that are specified as --flag on the command line are represented by a boolean # value where True indicates that the flag should be included in 'kwargs'. if opt_value: mongod_options[opt_name] = "" else: # Options that are specified as --key=value on the command line are represented by a # value where None indicates that the key-value pair shouldn't be included in 'kwargs'. if opt_value is not None: mongod_options[opt_name] = opt_value # Override the storage engine specified on the command line with "wiredTiger" if running a # config server replica set. if "replSet" in mongod_options and "configsvr" in mongod_options: mongod_options["storageEngine"] = "wiredTiger" # set_parameters has its own logic above mongod_options.pop("set_parameters") # Apply the rest of the command line arguments. _apply_kwargs(args, mongod_options) _set_keyfile_permissions(mongod_options) process_kwargs = make_historic(utils.default_if_none(process_kwargs, {})) process_kwargs["job_num"] = job_num if config.EXPORT_MONGOD_CONFIG == "regular": mongod_options.dump_history(f"{logger.name}_config.yml") elif config.EXPORT_MONGOD_CONFIG == "detailed": mongod_options.dump_history(f"{logger.name}_config.yml", include_location=True) return make_process(logger, args, **process_kwargs)
from buildscripts.resmokelib.multiversionconstants import LAST_LTS_MONGOD_BINARY from buildscripts.resmokelib.multiversionconstants import LAST_LTS_MONGOS_BINARY # The below parameters define the default 'logComponentVerbosity' object passed to mongod processes # started either directly via resmoke or those that will get started by the mongo shell. We allow # this default to be different for tests run locally and tests run in Evergreen. This allows us, for # example, to keep log verbosity high in Evergreen test runs without polluting the logs for # developers running local tests. # The default verbosity setting for any tests that are not started with an Evergreen task id. This # will apply to any tests run locally. DEFAULT_MONGOD_LOG_COMPONENT_VERBOSITY = make_historic({ "replication": { "rollback": 2 }, "sharding": { "migration": 2 }, "transaction": 4, "tenantMigration": 4 }) DEFAULT_LAST_LTS_MONGOD_LOG_COMPONENT_VERBOSITY = make_historic({ "replication": { "rollback": 2 }, "transaction": 4 }) # The default verbosity setting for any mongod processes running in Evergreen i.e. started with an # Evergreen task id.