/* * Copyright (C) 2013 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects for * all of the code used other than as permitted herein. If you modify file(s) * with this exception, you may extend this exception to your version of the * file(s), but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. */ #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kControl #include "mongo/db/mongod_options.h" #include #include #include #include #include "mongo/base/status.h" #include "mongo/bson/json.h" #include "mongo/bson/util/builder.h" #include "mongo/config.h" #include "mongo/db/db.h" #include "mongo/db/diag_log.h" #include "mongo/db/repl/repl_settings.h" #include "mongo/db/server_options.h" #include "mongo/db/server_options_helpers.h" #include "mongo/db/storage/mmap_v1/mmap_v1_options.h" #include "mongo/s/catalog/sharding_catalog_client.h" #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" #include "mongo/util/net/ssl_options.h" #include "mongo/util/options_parser/startup_options.h" #include "mongo/util/stringutils.h" #include "mongo/util/version.h" namespace mongo { using std::cout; using std::endl; using std::string; MongodGlobalParams mongodGlobalParams; Status addMongodOptions(moe::OptionSection* options) { moe::OptionSection general_options("General options"); Status ret = addGeneralServerOptions(&general_options); if (!ret.isOK()) { return ret; } #if defined(_WIN32) moe::OptionSection windows_scm_options("Windows Service Control Manager options"); ret = addWindowsServerOptions(&windows_scm_options); if (!ret.isOK()) { return ret; } #endif #ifdef MONGO_CONFIG_SSL moe::OptionSection ssl_options("SSL options"); ret = addSSLServerOptions(&ssl_options); if (!ret.isOK()) { return ret; } #endif moe::OptionSection ms_options("Master/slave options (old; use replica sets instead)"); moe::OptionSection rs_options("Replica set options"); moe::OptionSection replication_options("Replication options"); moe::OptionSection sharding_options("Sharding options"); moe::OptionSection storage_options("Storage options"); // Authentication Options // Way to enable or disable auth on command line and in Legacy config file general_options.addOptionChaining("auth", "auth", moe::Switch, "run with security") .setSources(moe::SourceAllLegacy) .incompatibleWith("noauth"); // IP Whitelisting Options general_options .addOptionChaining("security.clusterIpSourceWhitelist", "clusterIpSourceWhitelist", moe::StringVector, "Network CIDR specification of permitted origin for `__system` access.") .composing(); // Way to enable or disable auth in JSON Config general_options .addOptionChaining( "security.authorization", "", moe::String, "How the database behaves with respect to authorization of clients. " "Options are \"disabled\", which means that authorization checks are not " "performed, and \"enabled\" which means that a client cannot perform actions it is " "not authorized to do.") .setSources(moe::SourceYAMLConfig) .format("(:?disabled)|(:?enabled)", "(disabled/enabled)"); // setParameter parameters that we want as config file options // TODO: Actually read these into our environment. Currently they have no effect general_options.addOptionChaining("security.authSchemaVersion", "", moe::String, "TODO") .setSources(moe::SourceYAMLConfig); general_options.addOptionChaining("security.enableLocalhostAuthBypass", "", moe::String, "TODO") .setSources(moe::SourceYAMLConfig); // Diagnostic Options general_options .addOptionChaining( "diaglog", "diaglog", moe::Int, "DEPRECATED: 0=off 1=W 2=R 3=both 7=W+some reads") .hidden() .setSources(moe::SourceAllLegacy); general_options .addOptionChaining("operationProfiling.slowOpThresholdMs", "slowms", moe::Int, "value of slow for profile and console log") .setDefault(moe::Value(100)); general_options .addOptionChaining("operationProfiling.slowOpSampleRate", "slowOpSampleRate", moe::Double, "fraction of slow ops to include in the profile and console log") .setDefault(moe::Value(1.0)); general_options.addOptionChaining("profile", "profile", moe::Int, "0=off 1=slow, 2=all") .setSources(moe::SourceAllLegacy); general_options .addOptionChaining("operationProfiling.mode", "", moe::String, "(off/slowOp/all)") .setSources(moe::SourceYAMLConfig) .format("(:?off)|(:?slowOp)|(:?all)", "(off/slowOp/all)"); general_options .addOptionChaining( "cpu", "cpu", moe::Switch, "periodically show cpu and iowait utilization") .setSources(moe::SourceAllLegacy); general_options .addOptionChaining( "sysinfo", "sysinfo", moe::Switch, "print some diagnostic system information") .setSources(moe::SourceAllLegacy); // Storage Options storage_options.addOptionChaining( "storage.engine", "storageEngine", moe::String, "what storage engine to use - defaults to wiredTiger if no data files present"); #ifdef _WIN32 boost::filesystem::path currentPath = boost::filesystem::current_path(); std::string defaultPath = currentPath.root_name().string() + storageGlobalParams.kDefaultDbPath; storage_options.addOptionChaining("storage.dbPath", "dbpath", moe::String, std::string("directory for datafiles - defaults to ") + storageGlobalParams.kDefaultDbPath + " which is " + defaultPath + " based on the current working drive"); #else storage_options.addOptionChaining("storage.dbPath", "dbpath", moe::String, std::string("directory for datafiles - defaults to ") + storageGlobalParams.kDefaultDbPath); #endif storage_options.addOptionChaining("storage.directoryPerDB", "directoryperdb", moe::Switch, "each database will be stored in a separate directory"); storage_options .addOptionChaining("storage.queryableBackupMode", "queryableBackupMode", moe::Switch, "enable read-only mode - if true the server will not accept writes.") .setSources(moe::SourceAll) .hidden(); storage_options .addOptionChaining("storage.groupCollections", "groupCollections", moe::Switch, "group collections - if true the storage engine may group " "collections within a database into a shared record store.") .hidden(); general_options .addOptionChaining("noIndexBuildRetry", "noIndexBuildRetry", moe::Switch, "don't retry any index builds that were interrupted by shutdown") .setSources(moe::SourceAllLegacy); general_options .addOptionChaining("storage.indexBuildRetry", "", moe::Bool, "don't retry any index builds that were interrupted by shutdown") .setSources(moe::SourceYAMLConfig); storage_options .addOptionChaining("noprealloc", "noprealloc", moe::Switch, "disable data file preallocation - will often hurt performance") .setSources(moe::SourceAllLegacy); storage_options .addOptionChaining("storage.mmapv1.preallocDataFiles", "", moe::Bool, "disable data file preallocation - will often hurt performance", "storage.preallocDataFiles") .setSources(moe::SourceYAMLConfig); storage_options .addOptionChaining("storage.mmapv1.nsSize", "nssize", moe::Int, ".ns file size (in MB) for new databases", "storage.nsSize") .setDefault(moe::Value(16)); storage_options .addOptionChaining("storage.mmapv1.quota.enforced", "quota", moe::Switch, "limits each database to a certain number of files (8 default)", "storage.quota.enforced") .incompatibleWith("keyFile"); storage_options.addOptionChaining("storage.mmapv1.quota.maxFilesPerDB", "quotaFiles", moe::Int, "number of files allowed per db, implies --quota", "storage.quota.maxFilesPerDB"); storage_options.addOptionChaining("storage.mmapv1.smallFiles", "smallfiles", moe::Switch, "use a smaller default file size", "storage.smallFiles"); storage_options .addOptionChaining("storage.syncPeriodSecs", "syncdelay", moe::Double, "seconds between disk syncs (0=never, but not recommended)") .setDefault(moe::Value(60.0)); // Upgrade and repair are disallowed in JSON configs since they trigger very heavyweight // actions rather than specify configuration data storage_options.addOptionChaining("upgrade", "upgrade", moe::Switch, "upgrade db if needed") .setSources(moe::SourceAllLegacy); storage_options.addOptionChaining("repair", "repair", moe::Switch, "run repair on all dbs") .setSources(moe::SourceAllLegacy); storage_options.addOptionChaining("storage.repairPath", "repairpath", moe::String, "root directory for repair files - defaults to dbpath"); // Javascript Options general_options .addOptionChaining("noscripting", "noscripting", moe::Switch, "disable scripting engine") .setSources(moe::SourceAllLegacy); general_options .addOptionChaining( "security.javascriptEnabled", "", moe::Bool, "Enable javascript execution") .setSources(moe::SourceYAMLConfig); // Query Options general_options .addOptionChaining("notablescan", "notablescan", moe::Switch, "do not allow table scans") .setSources(moe::SourceAllLegacy); // Journaling Options // Way to enable or disable journaling on command line and in Legacy config file storage_options.addOptionChaining("journal", "journal", moe::Switch, "enable journaling") .setSources(moe::SourceAllLegacy); storage_options .addOptionChaining("nojournal", "nojournal", moe::Switch, "disable journaling (journaling is on by default for 64 bit)") .setSources(moe::SourceAllLegacy); storage_options.addOptionChaining("dur", "dur", moe::Switch, "enable journaling") .hidden() .setSources(moe::SourceAllLegacy); storage_options.addOptionChaining("nodur", "nodur", moe::Switch, "disable journaling") .hidden() .setSources(moe::SourceAllLegacy); // Way to enable or disable journaling in JSON Config general_options.addOptionChaining("storage.journal.enabled", "", moe::Bool, "enable journaling") .setSources(moe::SourceYAMLConfig); // Two ways to set durability diagnostic options. durOptions is deprecated storage_options .addOptionChaining("storage.mmapv1.journal.debugFlags", "journalOptions", moe::Int, "journal diagnostic options", "storage.journal.debugFlags") .incompatibleWith("durOptions"); storage_options .addOptionChaining("durOptions", "durOptions", moe::Int, "durability diagnostic options") .hidden() .setSources(moe::SourceAllLegacy) .incompatibleWith("storage.mmapv1.journal.debugFlags"); storage_options.addOptionChaining("storage.journal.commitIntervalMs", "journalCommitInterval", moe::Int, "how often to group/batch commit (ms)", "storage.mmapv1.journal.commitIntervalMs"); // Deprecated option that we don't want people to use for performance reasons storage_options .addOptionChaining("storage.mmapv1.journal.nopreallocj", "nopreallocj", moe::Switch, "don't preallocate journal files") .hidden() .setSources(moe::SourceAll); #if defined(__linux__) general_options.addOptionChaining( "shutdown", "shutdown", moe::Switch, "kill a running server (for init scripts)"); #endif // Master Slave Options ms_options.addOptionChaining("master", "master", moe::Switch, "master mode") .incompatibleWith("replication.replSet") .incompatibleWith("replication.replSetName") .setSources(moe::SourceAllLegacy); ms_options.addOptionChaining("slave", "slave", moe::Switch, "slave mode") .incompatibleWith("replication.replSet") .incompatibleWith("replication.replSetName") .setSources(moe::SourceAllLegacy); ms_options .addOptionChaining( "source", "source", moe::String, "when slave: specify master as ") .incompatibleWith("replication.replSet") .incompatibleWith("replication.replSetName") .setSources(moe::SourceAllLegacy); ms_options .addOptionChaining( "only", "only", moe::String, "when slave: specify a single database to replicate") .incompatibleWith("replication.replSet") .incompatibleWith("replication.replSetName") .setSources(moe::SourceAllLegacy); ms_options .addOptionChaining( "slavedelay", "slavedelay", moe::Int, "specify delay (in seconds) to be used when applying master ops to slave") .incompatibleWith("replication.replSet") .incompatibleWith("replication.replSetName") .setSources(moe::SourceAllLegacy); ms_options .addOptionChaining( "autoresync", "autoresync", moe::Switch, "automatically resync if slave data is stale") .incompatibleWith("replication.replSet") .incompatibleWith("replication.replSetName") .setSources(moe::SourceAllLegacy); // Replication Options replication_options.addOptionChaining( "replication.oplogSizeMB", "oplogSize", moe::Int, "size to use (in MB) for replication op log. default is 5% of disk space " "(i.e. large is good)"); rs_options .addOptionChaining("replication.replSet", "replSet", moe::String, "arg is [/]") .setSources(moe::SourceAllLegacy); rs_options.addOptionChaining("replication.replSetName", "", moe::String, "arg is ") .setSources(moe::SourceYAMLConfig) .format("[^/]+", "[replica set name with no \"/\"]"); rs_options .addOptionChaining("replication.secondaryIndexPrefetch", "replIndexPrefetch", moe::String, "specify index prefetching behavior (if secondary) [none|_id_only|all]") .format("(:?none)|(:?_id_only)|(:?all)", "(none/_id_only/all)"); rs_options.addOptionChaining("replication.enableMajorityReadConcern", "enableMajorityReadConcern", moe::Switch, "enables majority readConcern"); // Sharding Options sharding_options .addOptionChaining("configsvr", "configsvr", moe::Switch, "declare this is a config db of a cluster; default port 27019; " "default dir /data/configdb") .setSources(moe::SourceAllLegacy) .incompatibleWith("shardsvr") .incompatibleWith("nojournal"); sharding_options .addOptionChaining("shardsvr", "shardsvr", moe::Switch, "declare this is a shard db of a cluster; default port 27018") .setSources(moe::SourceAllLegacy) .incompatibleWith("configsvr") .incompatibleWith("master") .incompatibleWith("slave"); sharding_options .addOptionChaining( "sharding.clusterRole", "", moe::String, "Choose what role this mongod has in a sharded cluster. Possible values are:\n" " \"configsvr\": Start this node as a config server. Starts on port 27019 by " "default." " \"shardsvr\": Start this node as a shard server. Starts on port 27018 by " "default.") .setSources(moe::SourceYAMLConfig) .format("(:?configsvr)|(:?shardsvr)", "(configsvr/shardsvr)"); sharding_options .addOptionChaining( "sharding._overrideShardIdentity", "", moe::String, "overrides the shardIdentity document settings stored in the local storage with " "a MongoDB Extended JSON document in string format") .setSources(moe::SourceYAMLConfig) .incompatibleWith("configsvr") .requires("storage.queryableBackupMode"); sharding_options .addOptionChaining("noMoveParanoia", "noMoveParanoia", moe::Switch, "turn off paranoid saving of data for the moveChunk command; default") .hidden() .setSources(moe::SourceAllLegacy) .incompatibleWith("moveParanoia"); sharding_options .addOptionChaining("moveParanoia", "moveParanoia", moe::Switch, "turn on paranoid saving of data during the moveChunk command " "(used for internal system diagnostics)") .hidden() .setSources(moe::SourceAllLegacy) .incompatibleWith("noMoveParanoia"); sharding_options .addOptionChaining("sharding.archiveMovedChunks", "", moe::Bool, "config file option to turn on paranoid saving of data during the " "moveChunk command (used for internal system diagnostics)") .hidden() .setSources(moe::SourceYAMLConfig); options->addSection(general_options).transitional_ignore(); #if defined(_WIN32) options->addSection(windows_scm_options).transitional_ignore(); #endif options->addSection(replication_options).transitional_ignore(); options->addSection(ms_options).transitional_ignore(); options->addSection(rs_options).transitional_ignore(); options->addSection(sharding_options).transitional_ignore(); #ifdef MONGO_CONFIG_SSL options->addSection(ssl_options).transitional_ignore(); #endif options->addSection(storage_options).transitional_ignore(); // The following are legacy options that are disallowed in the JSON config file options ->addOptionChaining( "fastsync", "fastsync", moe::Switch, "indicate that this instance is starting from a dbpath snapshot of the repl peer") .hidden() .setSources(moe::SourceAllLegacy); options ->addOptionChaining("pretouch", "pretouch", moe::Int, "n pretouch threads for applying master/slave operations") .hidden() .setSources(moe::SourceAllLegacy); // This is a deprecated option that we are supporting for backwards compatibility // The first value for this option can be either 'dbpath' or 'run'. // If it is 'dbpath', mongod prints the dbpath and exits. Any extra values are ignored. // If it is 'run', mongod runs normally. Providing extra values is an error. options->addOptionChaining("command", "command", moe::StringVector, "command") .hidden() .positional(1, 3) .setSources(moe::SourceAllLegacy); options ->addOptionChaining("cacheSize", "cacheSize", moe::Long, "cache size (in MB) for rec store") .hidden() .setSources(moe::SourceAllLegacy); // deprecated pairing command line options options->addOptionChaining("pairwith", "pairwith", moe::Switch, "DEPRECATED") .hidden() .setSources(moe::SourceAllLegacy); options->addOptionChaining("arbiter", "arbiter", moe::Switch, "DEPRECATED") .hidden() .setSources(moe::SourceAllLegacy); options->addOptionChaining("opIdMem", "opIdMem", moe::Switch, "DEPRECATED") .hidden() .setSources(moe::SourceAllLegacy); return Status::OK(); } void printMongodHelp(const moe::OptionSection& options) { std::cout << options.helpString() << std::endl; }; namespace { void sysRuntimeInfo() { #if defined(_SC_PAGE_SIZE) log() << " page size: " << (int)sysconf(_SC_PAGE_SIZE); #endif #if defined(_SC_PHYS_PAGES) log() << " _SC_PHYS_PAGES: " << sysconf(_SC_PHYS_PAGES); #endif #if defined(_SC_AVPHYS_PAGES) log() << " _SC_AVPHYS_PAGES: " << sysconf(_SC_AVPHYS_PAGES); #endif } } // namespace bool handlePreValidationMongodOptions(const moe::Environment& params, const std::vector& args) { if (params.count("help") && params["help"].as() == true) { printMongodHelp(moe::startupOptions); return false; } if (params.count("version") && params["version"].as() == true) { setPlainConsoleLogger(); auto&& vii = VersionInfoInterface::instance(); log() << mongodVersion(vii); vii.logBuildInfo(); return false; } if (params.count("sysinfo") && params["sysinfo"].as() == true) { setPlainConsoleLogger(); sysRuntimeInfo(); return false; } return true; } Status validateMongodOptions(const moe::Environment& params) { Status ret = validateServerOptions(params); if (!ret.isOK()) { return ret; } if ((params.count("nodur") || params.count("nojournal")) && (params.count("dur") || params.count("journal"))) { return Status(ErrorCodes::BadValue, "Can't specify both --journal and --nojournal options."); } #ifdef _WIN32 if (params.count("install") || params.count("reinstall")) { if (params.count("storage.dbPath") && !boost::filesystem::path(params["storage.dbPath"].as()).is_absolute()) { return Status(ErrorCodes::BadValue, "dbPath requires an absolute file path with Windows services"); } } #endif if (params.count("storage.queryableBackupMode")) { // Command line options that are disallowed when --queryableBackupMode is specified. for (const auto& disallowedOption : {"replication.replSet", "configsvr", "upgrade", "repair", "profile", "master", "slave", "source", "only", "slavedelay", "autoresync", "fastsync"}) { if (params.count(disallowedOption)) { return Status(ErrorCodes::BadValue, str::stream() << "Cannot specify both queryable backup mode and " << disallowedOption); } } bool isClusterRoleShard = false; if (params.count("sharding.clusterRole")) { auto clusterRole = params["sharding.clusterRole"].as(); isClusterRoleShard = (clusterRole == "shardsvr"); } if ((isClusterRoleShard || params.count("shardsvr")) && !params.count("sharding._overrideShardIdentity")) { return Status( ErrorCodes::BadValue, "shardsvr cluster role with queryableBackupMode requires _overrideShardIdentity"); } } return Status::OK(); } Status canonicalizeMongodOptions(moe::Environment* params) { Status ret = canonicalizeServerOptions(params); if (!ret.isOK()) { return ret; } #ifdef MONGO_CONFIG_SSL ret = canonicalizeSSLServerOptions(params); if (!ret.isOK()) { return ret; } #endif // "storage.journal.enabled" comes from the config file, so override it if any of "journal", // "nojournal", "dur", and "nodur" are set, since those come from the command line. if (params->count("journal")) { Status ret = params->set("storage.journal.enabled", moe::Value((*params)["journal"].as())); if (!ret.isOK()) { return ret; } ret = params->remove("journal"); if (!ret.isOK()) { return ret; } } if (params->count("nojournal")) { Status ret = params->set("storage.journal.enabled", moe::Value(!(*params)["nojournal"].as())); if (!ret.isOK()) { return ret; } ret = params->remove("nojournal"); if (!ret.isOK()) { return ret; } } if (params->count("dur")) { Status ret = params->set("storage.journal.enabled", moe::Value((*params)["dur"].as())); if (!ret.isOK()) { return ret; } ret = params->remove("dur"); if (!ret.isOK()) { return ret; } } if (params->count("nodur")) { Status ret = params->set("storage.journal.enabled", moe::Value(!(*params)["nodur"].as())); if (!ret.isOK()) { return ret; } ret = params->remove("nodur"); if (!ret.isOK()) { return ret; } } // "storage.mmapv1.journal.durOptions" comes from the config file, so override it // if "durOptions" is set since that comes from the command line. if (params->count("durOptions")) { int durOptions; Status ret = params->get("durOptions", &durOptions); if (!ret.isOK()) { return ret; } ret = params->remove("durOptions"); if (!ret.isOK()) { return ret; } ret = params->set("storage.mmapv1.journal.debugFlags", moe::Value(durOptions)); if (!ret.isOK()) { return ret; } } // "security.authorization" comes from the config file, so override it if "auth" is // set since those come from the command line. if (params->count("auth")) { Status ret = params->set("security.authorization", (*params)["auth"].as() ? moe::Value(std::string("enabled")) : moe::Value(std::string("disabled"))); if (!ret.isOK()) { return ret; } ret = params->remove("auth"); if (!ret.isOK()) { return ret; } } // "storage.mmapv1.preallocDataFiles" comes from the config file, so override it if "noprealloc" // is set since that comes from the command line. if (params->count("noprealloc")) { Status ret = params->set("storage.mmapv1.preallocDataFiles", moe::Value(!(*params)["noprealloc"].as())); if (!ret.isOK()) { return ret; } ret = params->remove("noprealloc"); if (!ret.isOK()) { return ret; } } // "sharding.archiveMovedChunks" comes from the config file, so override it if // "noMoveParanoia" or "moveParanoia" are set since those come from the command line. if (params->count("noMoveParanoia")) { Status ret = params->set("sharding.archiveMovedChunks", moe::Value(!(*params)["noMoveParanoia"].as())); if (!ret.isOK()) { return ret; } ret = params->remove("noMoveParanoia"); if (!ret.isOK()) { return ret; } } if (params->count("moveParanoia")) { Status ret = params->set("sharding.archiveMovedChunks", moe::Value((*params)["moveParanoia"].as())); if (!ret.isOK()) { return ret; } ret = params->remove("moveParanoia"); if (!ret.isOK()) { return ret; } } // "sharding.clusterRole" comes from the config file, so override it if "configsvr" or // "shardsvr" are set since those come from the command line. if (params->count("configsvr")) { if ((*params)["configsvr"].as() == false) { // Handle the case where "configsvr" comes from the legacy config file and is set to // false. This option is not allowed in the YAML config. return Status(ErrorCodes::BadValue, "configsvr option cannot be set to false in config file"); } Status ret = params->set("sharding.clusterRole", moe::Value(std::string("configsvr"))); if (!ret.isOK()) { return ret; } ret = params->remove("configsvr"); if (!ret.isOK()) { return ret; } } if (params->count("shardsvr")) { if ((*params)["shardsvr"].as() == false) { // Handle the case where "shardsvr" comes from the legacy config file and is set to // false. This option is not allowed in the YAML config. return Status(ErrorCodes::BadValue, "shardsvr option cannot be set to false in config file"); } Status ret = params->set("sharding.clusterRole", moe::Value(std::string("shardsvr"))); if (!ret.isOK()) { return ret; } ret = params->remove("shardsvr"); if (!ret.isOK()) { return ret; } } if (params->count("profile")) { int profilingMode; Status ret = params->get("profile", &profilingMode); if (!ret.isOK()) { return ret; } std::string profilingModeString; if (profilingMode == 0) { profilingModeString = "off"; } else if (profilingMode == 1) { profilingModeString = "slowOp"; } else if (profilingMode == 2) { profilingModeString = "all"; } else { StringBuilder sb; sb << "Bad value for profile: " << profilingMode << ". Supported modes are: (0=off|1=slowOp|2=all)"; return Status(ErrorCodes::BadValue, sb.str()); } ret = params->set("operationProfiling.mode", moe::Value(profilingModeString)); if (!ret.isOK()) { return ret; } ret = params->remove("profile"); if (!ret.isOK()) { return ret; } } // "storage.indexBuildRetry" comes from the config file, so override it if // "noIndexBuildRetry" is set since that comes from the command line. if (params->count("noIndexBuildRetry")) { Status ret = params->set("storage.indexBuildRetry", moe::Value(!(*params)["noIndexBuildRetry"].as())); if (!ret.isOK()) { return ret; } ret = params->remove("noIndexBuildRetry"); if (!ret.isOK()) { return ret; } } // Ensure that "replication.replSet" logically overrides "replication.replSetName". We // can't canonicalize them as the same option, because they mean slightly different things. // "replication.replSet" can include a seed list, while "replication.replSetName" just has // the replica set name. if (params->count("replication.replSet") && params->count("replication.replSetName")) { ret = params->remove("replication.replSetName"); if (!ret.isOK()) { return ret; } } // "security.javascriptEnabled" comes from the config file, so override it if "noscripting" // is set since that comes from the command line. if (params->count("noscripting")) { Status ret = params->set("security.javascriptEnabled", moe::Value(!(*params)["noscripting"].as())); if (!ret.isOK()) { return ret; } ret = params->remove("noscripting"); if (!ret.isOK()) { return ret; } } return Status::OK(); } Status storeMongodOptions(const moe::Environment& params) { Status ret = storeServerOptions(params); if (!ret.isOK()) { return ret; } // TODO: Integrate these options with their setParameter counterparts if (params.count("security.authSchemaVersion")) { return Status(ErrorCodes::BadValue, "security.authSchemaVersion is currently not supported in config files"); } if (params.count("security.enableLocalhostAuthBypass")) { return Status(ErrorCodes::BadValue, "security.enableLocalhostAuthBypass is currently not supported in config " "files"); } if (params.count("storage.engine")) { storageGlobalParams.engine = params["storage.engine"].as(); storageGlobalParams.engineSetByUser = true; } if (params.count("storage.dbPath")) { storageGlobalParams.dbpath = params["storage.dbPath"].as(); if (params.count("processManagement.fork") && storageGlobalParams.dbpath[0] != '/') { // we need to change dbpath if we fork since we change // cwd to "/" // fork only exists on *nix // so '/' is safe storageGlobalParams.dbpath = serverGlobalParams.cwd + "/" + storageGlobalParams.dbpath; } } #ifdef _WIN32 if (storageGlobalParams.dbpath.size() > 1 && storageGlobalParams.dbpath[storageGlobalParams.dbpath.size() - 1] == '/') { // size() check is for the unlikely possibility of --dbpath "/" storageGlobalParams.dbpath = storageGlobalParams.dbpath.erase(storageGlobalParams.dbpath.size() - 1); } #endif if (params.count("operationProfiling.mode")) { std::string profilingMode = params["operationProfiling.mode"].as(); if (profilingMode == "off") { serverGlobalParams.defaultProfile = 0; } else if (profilingMode == "slowOp") { serverGlobalParams.defaultProfile = 1; } else if (profilingMode == "all") { serverGlobalParams.defaultProfile = 2; } else { StringBuilder sb; sb << "Bad value for operationProfiling.mode: " << profilingMode << ". Supported modes are: (off|slowOp|all)"; return Status(ErrorCodes::BadValue, sb.str()); } } if (params.count("operationProfiling.slowOpThresholdMs")) { serverGlobalParams.slowMS = params["operationProfiling.slowOpThresholdMs"].as(); } if (params.count("operationProfiling.slowOpSampleRate")) { serverGlobalParams.sampleRate = params["operationProfiling.slowOpSampleRate"].as(); } if (params.count("storage.syncPeriodSecs")) { storageGlobalParams.syncdelay = params["storage.syncPeriodSecs"].as(); if (storageGlobalParams.syncdelay < 0 || storageGlobalParams.syncdelay > StorageGlobalParams::kMaxSyncdelaySecs) { return Status(ErrorCodes::BadValue, str::stream() << "syncdelay out of allowed range (0-" << StorageGlobalParams::kMaxSyncdelaySecs << "s)"); } } if (params.count("storage.directoryPerDB")) { storageGlobalParams.directoryperdb = params["storage.directoryPerDB"].as(); } if (params.count("storage.queryableBackupMode") && params["storage.queryableBackupMode"].as()) { storageGlobalParams.readOnly = true; storageGlobalParams.dur = false; } if (params.count("storage.groupCollections")) { storageGlobalParams.groupCollections = params["storage.groupCollections"].as(); } if (params.count("cpu")) { serverGlobalParams.cpu = params["cpu"].as(); } if (params.count("storage.mmapv1.quota.enforced")) { mmapv1GlobalOptions.quota = params["storage.mmapv1.quota.enforced"].as(); } if (params.count("storage.mmapv1.quota.maxFilesPerDB")) { mmapv1GlobalOptions.quota = true; mmapv1GlobalOptions.quotaFiles = params["storage.mmapv1.quota.maxFilesPerDB"].as() - 1; } if (params.count("storage.journal.enabled")) { storageGlobalParams.dur = params["storage.journal.enabled"].as(); } if (params.count("storage.journal.commitIntervalMs")) { // don't check if dur is false here as many will just use the default, and will default // to off on win32. ie no point making life a little more complex by giving an error on // a dev environment. auto journalCommitIntervalMs = params["storage.journal.commitIntervalMs"].as(); storageGlobalParams.journalCommitIntervalMs.store(journalCommitIntervalMs); if (journalCommitIntervalMs < 1 || journalCommitIntervalMs > StorageGlobalParams::kMaxJournalCommitIntervalMs) { return Status(ErrorCodes::BadValue, str::stream() << "--journalCommitInterval out of allowed range (1-" << StorageGlobalParams::kMaxJournalCommitIntervalMs << "ms)"); } } if (params.count("storage.mmapv1.journal.debugFlags")) { mmapv1GlobalOptions.journalOptions = params["storage.mmapv1.journal.debugFlags"].as(); } if (params.count("storage.mmapv1.journal.nopreallocj")) { mmapv1GlobalOptions.preallocj = !params["storage.mmapv1.journal.nopreallocj"].as(); } if (params.count("security.javascriptEnabled")) { mongodGlobalParams.scriptingEnabled = params["security.javascriptEnabled"].as(); } if (params.count("security.clusterIpSourceWhitelist")) { mongodGlobalParams.whitelistedClusterNetwork = std::vector(); for (const std::string& whitelistEntry : params["security.clusterIpSourceWhitelist"].as>()) { std::vector intermediates; splitStringDelim(whitelistEntry, &intermediates, ','); std::copy(intermediates.begin(), intermediates.end(), std::back_inserter(*mongodGlobalParams.whitelistedClusterNetwork)); } } if (params.count("storage.mmapv1.preallocDataFiles")) { mmapv1GlobalOptions.prealloc = params["storage.mmapv1.preallocDataFiles"].as(); cout << "note: noprealloc may hurt performance in many applications" << endl; } if (params.count("storage.mmapv1.smallFiles")) { mmapv1GlobalOptions.smallfiles = params["storage.mmapv1.smallFiles"].as(); } if (params.count("diaglog")) { warning() << "--diaglog is deprecated and will be removed in a future release" << startupWarningsLog; int x = params["diaglog"].as(); if (x < 0 || x > 7) { return Status(ErrorCodes::BadValue, "can't interpret --diaglog setting"); } _diaglog.setLevel(x); } if ((params.count("storage.journal.enabled") && params["storage.journal.enabled"].as() == true) && params.count("repair")) { return Status(ErrorCodes::BadValue, "Can't have journaling enabled when using --repair option."); } if (params.count("repair") && params["repair"].as() == true) { storageGlobalParams.upgrade = 1; // --repair implies --upgrade storageGlobalParams.repair = 1; storageGlobalParams.dur = false; } if (params.count("upgrade") && params["upgrade"].as() == true) { storageGlobalParams.upgrade = 1; } if (params.count("notablescan")) { storageGlobalParams.noTableScan.store(params["notablescan"].as()); } repl::ReplSettings replSettings; if (params.count("master")) { replSettings.setMaster(params["master"].as()); } if (params.count("slave") && params["slave"].as() == true) { replSettings.setSlave(true); } if (params.count("slavedelay")) { replSettings.setSlaveDelaySecs(params["slavedelay"].as()); } if (params.count("fastsync")) { if (!replSettings.isSlave()) { return Status(ErrorCodes::BadValue, str::stream() << "--fastsync must only be used with --slave"); } replSettings.setFastSyncEnabled(params["fastsync"].as()); } if (params.count("autoresync")) { replSettings.setAutoResyncEnabled(params["autoresync"].as()); } if (params.count("source")) { /* specifies what the source in local.sources should be */ replSettings.setSource(params["source"].as().c_str()); } if (params.count("pretouch")) { replSettings.setPretouch(params["pretouch"].as()); } if (params.count("replication.replSetName")) { replSettings.setReplSetString(params["replication.replSetName"].as().c_str()); } if (params.count("replication.replSet")) { /* seed list of hosts for the repl set */ replSettings.setReplSetString(params["replication.replSet"].as().c_str()); } if (params.count("replication.secondaryIndexPrefetch")) { replSettings.setPrefetchIndexMode( params["replication.secondaryIndexPrefetch"].as()); } if (params.count("replication.enableMajorityReadConcern")) { replSettings.setMajorityReadConcernEnabled( params["replication.enableMajorityReadConcern"].as()); } if (params.count("storage.indexBuildRetry")) { serverGlobalParams.indexBuildRetry = params["storage.indexBuildRetry"].as(); } if (params.count("only")) { replSettings.setOnly(params["only"].as().c_str()); } if (params.count("storage.mmapv1.nsSize")) { int x = params["storage.mmapv1.nsSize"].as(); if (x <= 0 || x > (0x7fffffff / 1024 / 1024)) { return Status(ErrorCodes::BadValue, "bad --nssize arg"); } mmapv1GlobalOptions.lenForNewNsFiles = x * 1024 * 1024; verify(mmapv1GlobalOptions.lenForNewNsFiles > 0); } if (params.count("replication.oplogSizeMB")) { long long x = params["replication.oplogSizeMB"].as(); if (x <= 0) { return Status(ErrorCodes::BadValue, str::stream() << "bad --oplogSize, arg must be greater than 0," "found: " << x); } // note a small size such as x==1 is ok for an arbiter. if (x > 1000 && sizeof(void*) == 4) { StringBuilder sb; sb << "--oplogSize of " << x << "MB is too big for 32 bit version. Use 64 bit build instead."; return Status(ErrorCodes::BadValue, sb.str()); } replSettings.setOplogSizeBytes(x * 1024 * 1024); invariant(replSettings.getOplogSizeBytes() > 0); } if (params.count("cacheSize")) { long x = params["cacheSize"].as(); if (x <= 0) { return Status(ErrorCodes::BadValue, "bad --cacheSize arg"); } return Status(ErrorCodes::BadValue, "--cacheSize option not currently supported"); } if (!params.count("net.port")) { if (params.count("sharding.clusterRole")) { std::string clusterRole = params["sharding.clusterRole"].as(); if (clusterRole == "configsvr") { serverGlobalParams.port = ServerGlobalParams::ConfigServerPort; } else if (clusterRole == "shardsvr") { serverGlobalParams.port = ServerGlobalParams::ShardServerPort; } else { StringBuilder sb; sb << "Bad value for sharding.clusterRole: " << clusterRole << ". Supported modes are: (configsvr|shardsvr)"; return Status(ErrorCodes::BadValue, sb.str()); } } } else { if (serverGlobalParams.port < 0 || serverGlobalParams.port > 65535) { return Status(ErrorCodes::BadValue, "bad --port number"); } } if (params.count("sharding.clusterRole")) { auto clusterRoleParam = params["sharding.clusterRole"].as(); if (clusterRoleParam == "configsvr") { serverGlobalParams.clusterRole = ClusterRole::ConfigServer; replSettings.setMajorityReadConcernEnabled(true); // If we haven't explicitly specified a journal option, default journaling to true for // the config server role if (!params.count("storage.journal.enabled")) { storageGlobalParams.dur = true; } if (!params.count("storage.dbPath")) { storageGlobalParams.dbpath = storageGlobalParams.kDefaultConfigDbPath; } } else if (clusterRoleParam == "shardsvr") { serverGlobalParams.clusterRole = ClusterRole::ShardServer; } } if (params.count("sharding.archiveMovedChunks")) { serverGlobalParams.moveParanoia = params["sharding.archiveMovedChunks"].as(); } if (params.count("sharding._overrideShardIdentity")) { auto docAsString = params["sharding._overrideShardIdentity"].as(); try { serverGlobalParams.overrideShardIdentity = fromjson(docAsString); } catch (const DBException& exception) { return exception.toStatus( "Error encountered while parsing _overrideShardIdentity JSON document"); } } if (params.count("pairwith") || params.count("arbiter") || params.count("opIdMem")) { return Status(ErrorCodes::BadValue, "****\n" "Replica Pairs have been deprecated. Invalid options: " "--pairwith, --arbiter, and/or --opIdMem\n" "\n" "****"); } #ifdef _WIN32 // If dbPath is a default value, prepend with drive name so log entries are explicit // We must resolve the dbpath before it stored in repairPath in the default case. if (storageGlobalParams.dbpath == storageGlobalParams.kDefaultDbPath || storageGlobalParams.dbpath == storageGlobalParams.kDefaultConfigDbPath) { boost::filesystem::path currentPath = boost::filesystem::current_path(); storageGlobalParams.dbpath = currentPath.root_name().string() + storageGlobalParams.dbpath; } #endif // needs to be after things like --configsvr parsing, thus here. if (params.count("storage.repairPath")) { storageGlobalParams.repairpath = params["storage.repairPath"].as(); if (!storageGlobalParams.repairpath.size()) { return Status(ErrorCodes::BadValue, "repairpath is empty"); } if (storageGlobalParams.dur && !str::startsWith(storageGlobalParams.repairpath, storageGlobalParams.dbpath)) { return Status(ErrorCodes::BadValue, "You must use a --repairpath that is a subdirectory of --dbpath when " "using journaling"); } } else { storageGlobalParams.repairpath = storageGlobalParams.dbpath; } if (replSettings.getPretouch()) log() << "--pretouch " << replSettings.getPretouch(); // Check if we are 32 bit and have not explicitly specified any journaling options if (sizeof(void*) == 4 && !params.count("storage.journal.enabled")) { // trying to make this stand out more like startup warnings log() << endl; warning() << "32-bit servers don't have journaling enabled by default. " << "Please use --journal if you want durability."; log() << endl; } setGlobalReplSettings(replSettings); return Status::OK(); } namespace { repl::ReplSettings globalReplSettings; } // namespace void setGlobalReplSettings(const repl::ReplSettings& settings) { globalReplSettings = settings; } const repl::ReplSettings& getGlobalReplSettings() { return globalReplSettings; } } // namespace mongo