Status storeServerOptions(const moe::Environment& params, const std::vector<std::string>& args) { Status ret = setupBinaryName(args); if (!ret.isOK()) { return ret; } ret = setupCwd(); if (!ret.isOK()) { return ret; } ret = setArgvArray(args); if (!ret.isOK()) { return ret; } ret = setParsedOpts(params); if (!ret.isOK()) { return ret; } if (params.count("verbose")) { std::string verbosity = params["verbose"].as<std::string>(); for (std::string::iterator iterator = verbosity.begin(); iterator != verbosity.end(); iterator++) { if (*iterator != 'v') { return Status(ErrorCodes::BadValue, "The \"verbose\" option string cannot contain any characters " "other than \"v\""); } } } // Handle both the "--verbose" string argument and the "-vvvv" arguments at the same time so // that we ensure that we set the log level to the maximum of the options provided for (string s = ""; s.length() <= 14; s.append("v")) { if (!s.empty() && params.count(s)) { logger::globalLogDomain()->setMinimumLoggedSeverity( logger::LogSeverity::Debug(s.length())); } if (params.count("verbose")) { std::string verbosity = params["verbose"].as<std::string>(); if (s == verbosity) { logger::globalLogDomain()->setMinimumLoggedSeverity( logger::LogSeverity::Debug(s.length())); } } } if (params.count("enableExperimentalIndexStatsCmd")) { serverGlobalParams.experimental.indexStatsCmdEnabled = true; } if (params.count("enableExperimentalStorageDetailsCmd")) { serverGlobalParams.experimental.storageDetailsCmdEnabled = true; } if (params.count("port")) { serverGlobalParams.port = params["port"].as<int>(); } if (params.count("bind_ip")) { serverGlobalParams.bind_ip = params["bind_ip"].as<std::string>(); } if (params.count("clusterAuthMode")) { serverGlobalParams.clusterAuthMode = params["clusterAuthMode"].as<std::string>(); } if (params.count("quiet")) { serverGlobalParams.quiet = true; } if (params.count("traceExceptions")) { DBException::traceExceptions = true; } if (params.count("maxConns")) { serverGlobalParams.maxConns = params["maxConns"].as<int>(); if (serverGlobalParams.maxConns < 5) { return Status(ErrorCodes::BadValue, "maxConns has to be at least 5"); } } if (params.count("objcheck")) { serverGlobalParams.objcheck = true; } if (params.count("noobjcheck")) { if (params.count("objcheck")) { return Status(ErrorCodes::BadValue, "can't have both --objcheck and --noobjcheck"); } serverGlobalParams.objcheck = false; } if (params.count("bind_ip")) { // passing in wildcard is the same as default behavior; remove and warn if (serverGlobalParams.bind_ip == "0.0.0.0") { std::cout << "warning: bind_ip of 0.0.0.0 is unnecessary; " << "listens on all ips by default" << endl; serverGlobalParams.bind_ip = ""; } } #ifndef _WIN32 if (params.count("unixSocketPrefix")) { serverGlobalParams.socket = params["unixSocketPrefix"].as<string>(); } if (params.count("nounixsocket")) { serverGlobalParams.noUnixSocket = true; } if (params.count("fork") && !params.count("shutdown")) { serverGlobalParams.doFork = true; } #endif // _WIN32 if (params.count("logTimestampFormat")) { using logger::MessageEventDetailsEncoder; std::string formatterName = params["logTimestampFormat"].as<string>(); if (formatterName == "ctime") { MessageEventDetailsEncoder::setDateFormatter(dateToCtimeString); } else if (formatterName == "iso8601-utc") { MessageEventDetailsEncoder::setDateFormatter(dateToISOStringUTC); } else if (formatterName == "iso8601-local") { MessageEventDetailsEncoder::setDateFormatter(dateToISOStringLocal); } else { StringBuilder sb; sb << "Value of logTimestampFormat must be one of ctime, iso8601-utc " << "or iso8601-local; not \"" << formatterName << "\"."; return Status(ErrorCodes::BadValue, sb.str()); } } if (params.count("logpath")) { serverGlobalParams.logpath = params["logpath"].as<string>(); if (serverGlobalParams.logpath.empty()) { return Status(ErrorCodes::BadValue, "logpath cannot be empty if supplied"); } } serverGlobalParams.logWithSyslog = params.count("syslog"); #ifndef _WIN32 if (params.count("syslogFacility")) { std::string facility = params["syslogFacility"].as<string>(); bool set = false; // match facility string to facility value for (unsigned long i = 0; i < sizeof(facilitynames)/sizeof(facilitynames[0]); i++) { if (!facility.compare(facilitynames[i].c_name)) { serverGlobalParams.syslogFacility = facilitynames[i].c_val; set = true; } } if (!set) { StringBuilder sb; sb << "ERROR: syslogFacility must be set to a string representing one of the " << "possible syslog facilities"; return Status(ErrorCodes::BadValue, sb.str()); } } else { serverGlobalParams.syslogFacility = LOG_USER; } #endif // _WIN32 serverGlobalParams.logAppend = params.count("logappend"); if (!serverGlobalParams.logpath.empty() && serverGlobalParams.logWithSyslog) { return Status(ErrorCodes::BadValue, "Cant use both a logpath and syslog "); } if (serverGlobalParams.doFork && serverGlobalParams.logpath.empty() && !serverGlobalParams.logWithSyslog) { return Status(ErrorCodes::BadValue, "--fork has to be used with --logpath or --syslog"); } if (params.count("keyFile")) { serverGlobalParams.keyFile = boost::filesystem::absolute( params["keyFile"].as<string>()).generic_string(); } if ( params.count("pidfilepath")) { serverGlobalParams.pidFile = params["pidfilepath"].as<string>(); } if (params.count("setParameter")) { std::vector<std::string> parameters = params["setParameter"].as<std::vector<std::string> >(); for (size_t i = 0, length = parameters.size(); i < length; ++i) { std::string name; std::string value; if (!mongoutils::str::splitOn(parameters[i], '=', name, value)) { StringBuilder sb; sb << "Illegal option assignment: \"" << parameters[i] << "\""; return Status(ErrorCodes::BadValue, sb.str()); } ServerParameter* parameter = mapFindWithDefault( ServerParameterSet::getGlobal()->getMap(), name, static_cast<ServerParameter*>(NULL)); if (NULL == parameter) { StringBuilder sb; sb << "Illegal --setParameter parameter: \"" << name << "\""; return Status(ErrorCodes::BadValue, sb.str()); } if (!parameter->allowedToChangeAtStartup()) { StringBuilder sb; sb << "Cannot use --setParameter to set \"" << name << "\" at startup"; return Status(ErrorCodes::BadValue, sb.str()); } Status status = parameter->setFromString(value); if (!status.isOK()) { StringBuilder sb; sb << "Bad value for parameter \"" << name << "\": " << status.reason(); return Status(ErrorCodes::BadValue, sb.str()); } } } if (!params.count("clusterAuthMode") && params.count("keyFile")){ serverGlobalParams.clusterAuthMode = "keyFile"; } #ifdef MONGO_SSL ret = storeSSLServerOptions(params); if (!ret.isOK()) { return ret; } #else // ifdef MONGO_SSL // keyFile is currently the only supported value if not using SSL if (params.count("clusterAuthMode") && serverGlobalParams.clusterAuthMode != "keyFile") { StringBuilder sb; sb << "unsupported value for clusterAuthMode " << serverGlobalParams.clusterAuthMode; return Status(ErrorCodes::BadValue, sb.str()); } #endif return Status::OK(); }
Status storeServerOptions(const moe::Environment& params, const std::vector<std::string>& args) { Status ret = setupBinaryName(args); if (!ret.isOK()) { return ret; } ret = setupCwd(); if (!ret.isOK()) { return ret; } ret = setArgvArray(args); if (!ret.isOK()) { return ret; } ret = setParsedOpts(params); if (!ret.isOK()) { return ret; } // Check options that are not yet supported if (params.count("net.http.port")) { return Status(ErrorCodes::BadValue, "The net.http.port option is not currently supported"); } if (params.count("systemLog.verbosity")) { int verbosity = params["systemLog.verbosity"].as<int>(); if (verbosity < 0) { // This can only happen in YAML config return Status(ErrorCodes::BadValue, "systemLog.verbosity YAML Config cannot be negative"); } logger::globalLogDomain()->setMinimumLoggedSeverity( logger::LogSeverity::Debug(verbosity)); } if (params.count("enableExperimentalIndexStatsCmd")) { serverGlobalParams.experimental.indexStatsCmdEnabled = true; } if (params.count("enableExperimentalStorageDetailsCmd")) { serverGlobalParams.experimental.storageDetailsCmdEnabled = true; } if (params.count("net.port")) { serverGlobalParams.port = params["net.port"].as<int>(); } if (params.count("net.bindIp")) { serverGlobalParams.bind_ip = params["net.bindIp"].as<std::string>(); } if (params.count("net.http.enabled")) { serverGlobalParams.isHttpInterfaceEnabled = params["net.http.enabled"].as<bool>(); } if (params.count("security.clusterAuthMode")) { std::string clusterAuthMode = params["security.clusterAuthMode"].as<std::string>(); if (clusterAuthMode == "keyFile") { serverGlobalParams.clusterAuthMode.store (ServerGlobalParams::ClusterAuthMode_keyFile); } else if (clusterAuthMode == "sendKeyFile") { serverGlobalParams.clusterAuthMode.store (ServerGlobalParams::ClusterAuthMode_sendKeyFile); } else if (clusterAuthMode == "sendX509") { serverGlobalParams.clusterAuthMode.store (ServerGlobalParams::ClusterAuthMode_sendX509); } else if (clusterAuthMode == "x509") { serverGlobalParams.clusterAuthMode.store(ServerGlobalParams::ClusterAuthMode_x509); } else { return Status(ErrorCodes::BadValue, "unsupported value for clusterAuthMode " + clusterAuthMode ); } } else { serverGlobalParams.clusterAuthMode.store(ServerGlobalParams::ClusterAuthMode_undefined); } if (params.count("systemLog.quiet")) { serverGlobalParams.quiet = true; } if (params.count("systemLog.traceAllExceptions")) { DBException::traceExceptions = true; } if (params.count("net.maxIncomingConnections")) { serverGlobalParams.maxConns = params["net.maxIncomingConnections"].as<int>(); if (serverGlobalParams.maxConns < 5) { return Status(ErrorCodes::BadValue, "maxConns has to be at least 5"); } } if (params.count("net.wireObjectCheck")) { serverGlobalParams.objcheck = params["net.wireObjectCheck"].as<bool>(); } if (params.count("net.bindIp")) { // passing in wildcard is the same as default behavior; remove and warn if (serverGlobalParams.bind_ip == "0.0.0.0") { std::cout << "warning: bind_ip of 0.0.0.0 is unnecessary; " << "listens on all ips by default" << endl; serverGlobalParams.bind_ip = ""; } } #ifndef _WIN32 if (params.count("net.unixDomainSocket.pathPrefix")) { serverGlobalParams.socket = params["net.unixDomainSocket.pathPrefix"].as<string>(); } if (params.count("net.unixDomainSocket.enabled")) { serverGlobalParams.noUnixSocket = !params["net.unixDomainSocket.enabled"].as<bool>(); } if (params.count("processManagement.fork") && !params.count("shutdown")) { serverGlobalParams.doFork = true; } #endif // _WIN32 if (params.count("systemLog.timeStampFormat")) { using logger::MessageEventDetailsEncoder; std::string formatterName = params["systemLog.timeStampFormat"].as<string>(); if (formatterName == "ctime") { MessageEventDetailsEncoder::setDateFormatter(outputDateAsCtime); } else if (formatterName == "iso8601-utc") { MessageEventDetailsEncoder::setDateFormatter(outputDateAsISOStringUTC); } else if (formatterName == "iso8601-local") { MessageEventDetailsEncoder::setDateFormatter(outputDateAsISOStringLocal); } else { StringBuilder sb; sb << "Value of logTimestampFormat must be one of ctime, iso8601-utc " << "or iso8601-local; not \"" << formatterName << "\"."; return Status(ErrorCodes::BadValue, sb.str()); } } if (params.count("systemLog.destination")) { std::string systemLogDestination = params["systemLog.destination"].as<std::string>(); if (systemLogDestination == "file") { if (params.count("systemLog.path")) { serverGlobalParams.logpath = params["systemLog.path"].as<std::string>(); } else { return Status(ErrorCodes::BadValue, "systemLog.path is required if systemLog.destination is to a " "file"); } } else if (systemLogDestination == "syslog") { if (params.count("systemLog.path")) { return Status(ErrorCodes::BadValue, "Can only use systemLog.path if systemLog.destination is to a " "file"); } serverGlobalParams.logWithSyslog = true; } else { StringBuilder sb; sb << "Bad value for systemLog.destination: " << systemLogDestination << ". Supported targets are: (syslog|file)"; return Status(ErrorCodes::BadValue, sb.str()); } } else { if (params.count("systemLog.path")) { return Status(ErrorCodes::BadValue, "Can only use systemLog.path if systemLog.destination is to a file"); } } #ifndef _WIN32 if (params.count("systemLog.syslogFacility")) { std::string facility = params["systemLog.syslogFacility"].as<string>(); bool set = false; // match facility string to facility value size_t facilitynamesLength = sizeof(facilitynames)/sizeof(facilitynames[0]); for (unsigned long i = 0; i < facilitynamesLength && facilitynames[i].c_name != NULL; i++) { if (!facility.compare(facilitynames[i].c_name)) { serverGlobalParams.syslogFacility = facilitynames[i].c_val; set = true; } } if (!set) { StringBuilder sb; sb << "ERROR: syslogFacility must be set to a string representing one of the " << "possible syslog facilities"; return Status(ErrorCodes::BadValue, sb.str()); } } else { serverGlobalParams.syslogFacility = LOG_USER; } #endif // _WIN32 serverGlobalParams.logAppend = params.count("systemLog.logAppend"); if (!serverGlobalParams.logpath.empty() && serverGlobalParams.logWithSyslog) { return Status(ErrorCodes::BadValue, "Cant use both a logpath and syslog "); } if (serverGlobalParams.doFork && serverGlobalParams.logpath.empty() && !serverGlobalParams.logWithSyslog) { return Status(ErrorCodes::BadValue, "--fork has to be used with --logpath or --syslog"); } if (params.count("security.keyFile")) { serverGlobalParams.keyFile = boost::filesystem::absolute( params["security.keyFile"].as<string>()).generic_string(); } if ( params.count("processManagement.pidFilePath")) { serverGlobalParams.pidFile = params["processManagement.pidFilePath"].as<string>(); } if (params.count("setParameter")) { std::map<std::string, std::string> parameters = params["setParameter"].as<std::map<std::string, std::string> >(); for (std::map<std::string, std::string>::iterator parametersIt = parameters.begin(); parametersIt != parameters.end(); parametersIt++) { ServerParameter* parameter = mapFindWithDefault( ServerParameterSet::getGlobal()->getMap(), parametersIt->first, static_cast<ServerParameter*>(NULL)); if (NULL == parameter) { StringBuilder sb; sb << "Illegal --setParameter parameter: \"" << parametersIt->first << "\""; return Status(ErrorCodes::BadValue, sb.str()); } if (!parameter->allowedToChangeAtStartup()) { StringBuilder sb; sb << "Cannot use --setParameter to set \"" << parametersIt->first << "\" at startup"; return Status(ErrorCodes::BadValue, sb.str()); } Status status = parameter->setFromString(parametersIt->second); if (!status.isOK()) { StringBuilder sb; sb << "Bad value for parameter \"" << parametersIt->first << "\": " << status.reason(); return Status(ErrorCodes::BadValue, sb.str()); } } } if (!params.count("security.clusterAuthMode") && params.count("security.keyFile")){ serverGlobalParams.clusterAuthMode.store (ServerGlobalParams::ClusterAuthMode_keyFile); } #ifdef MONGO_SSL ret = storeSSLServerOptions(params); if (!ret.isOK()) { return ret; } #endif return Status::OK(); }
bool CmdLine::store( const std::vector<std::string>& argv, boost::program_options::options_description& visible, boost::program_options::options_description& hidden, boost::program_options::positional_options_description& positional, boost::program_options::variables_map ¶ms ) { if (argv.empty()) return false; { // setup binary name cmdLine.binaryName = argv[0]; size_t i = cmdLine.binaryName.rfind( '/' ); if ( i != string::npos ) cmdLine.binaryName = cmdLine.binaryName.substr( i + 1 ); // setup cwd char buffer[1024]; #ifdef _WIN32 verify( _getcwd( buffer , 1000 ) ); #else verify( getcwd( buffer , 1000 ) ); #endif cmdLine.cwd = buffer; } /* don't allow guessing - creates ambiguities when some options are * prefixes of others. allow long disguises and don't allow guessing * to get away with our vvvvvvv trick. */ int style = (((po::command_line_style::unix_style ^ po::command_line_style::allow_guessing) | po::command_line_style::allow_long_disguise) ^ po::command_line_style::allow_sticky); try { po::options_description all; all.add( visible ); all.add( hidden ); po::store( po::command_line_parser(std::vector<std::string>(argv.begin() + 1, argv.end())) .options( all ) .positional( positional ) .style( style ) .run(), params ); if ( params.count("config") ) { ifstream f( params["config"].as<string>().c_str() ); if ( ! f.is_open() ) { cout << "ERROR: could not read from config file" << endl << endl; cout << visible << endl; return false; } stringstream ss; CmdLine::parseConfigFile( f, ss ); po::store( po::parse_config_file( ss , all ) , params ); f.close(); } po::notify(params); } catch (po::error &e) { cout << "error command line: " << e.what() << endl; cout << "use --help for help" << endl; //cout << visible << endl; return false; } { BSONArrayBuilder b; std::vector<std::string> censoredArgv = argv; censor(&censoredArgv); for (size_t i=0; i < censoredArgv.size(); i++) { b << censoredArgv[i]; } argvArray = b.arr(); } { BSONObjBuilder b; for (po::variables_map::const_iterator it(params.begin()), end(params.end()); it != end; it++){ if (!it->second.defaulted()){ const string& key = it->first; const po::variable_value& value = it->second; const type_info& type = value.value().type(); if (type == typeid(string)){ if (value.as<string>().empty()) b.appendBool(key, true); // boost po uses empty string for flags like --quiet else { if ( _isPasswordArgument(key.c_str()) ) { b.append( key, "<password>" ); } else { b.append( key, value.as<string>() ); } } } else if (type == typeid(int)) b.append(key, value.as<int>()); else if (type == typeid(double)) b.append(key, value.as<double>()); else if (type == typeid(bool)) b.appendBool(key, value.as<bool>()); else if (type == typeid(long)) b.appendNumber(key, (long long)value.as<long>()); else if (type == typeid(unsigned)) b.appendNumber(key, (long long)value.as<unsigned>()); else if (type == typeid(unsigned long long)) b.appendNumber(key, (long long)value.as<unsigned long long>()); else if (type == typeid(vector<string>)) b.append(key, value.as<vector<string> >()); else b.append(key, "UNKNOWN TYPE: " + demangleName(type)); } } parsedOpts = b.obj(); } if (params.count("verbose")) { logLevel = 1; } for (string s = "vv"; s.length() <= 12; s.append("v")) { if (params.count(s)) { logLevel = s.length(); } } if (params.count("quiet")) { cmdLine.quiet = true; } if (params.count("traceExceptions")) { DBException::traceExceptions = true; } if (params.count("maxConns")) { cmdLine.maxConns = params["maxConns"].as<int>(); if ( cmdLine.maxConns < 5 ) { out() << "maxConns has to be at least 5" << endl; return false; } else if ( cmdLine.maxConns > MAX_MAX_CONN ) { out() << "maxConns can't be greater than " << MAX_MAX_CONN << endl; return false; } } if (params.count("objcheck")) { cmdLine.objcheck = true; } if (params.count("noobjcheck")) { if (params.count("objcheck")) { out() << "can't have both --objcheck and --noobjcheck" << endl; return false; } cmdLine.objcheck = false; } if (params.count("bind_ip")) { // passing in wildcard is the same as default behavior; remove and warn if ( cmdLine.bind_ip == "0.0.0.0" ) { cout << "warning: bind_ip of 0.0.0.0 is unnecessary; listens on all ips by default" << endl; cmdLine.bind_ip = ""; } } #ifndef _WIN32 if (params.count("unixSocketPrefix")) { cmdLine.socket = params["unixSocketPrefix"].as<string>(); } if (params.count("nounixsocket")) { cmdLine.noUnixSocket = true; } if (params.count("fork") && !params.count("shutdown")) { cmdLine.doFork = true; } #endif // _WIN32 if (params.count("logpath")) { cmdLine.logpath = params["logpath"].as<string>(); if (cmdLine.logpath.empty()) { cout << "logpath cannot be empty if supplied" << endl; return false; } } cmdLine.logWithSyslog = params.count("syslog"); cmdLine.logAppend = params.count("logappend"); if (!cmdLine.logpath.empty() && cmdLine.logWithSyslog) { cout << "Cant use both a logpath and syslog " << endl; return false; } if (cmdLine.doFork && cmdLine.logpath.empty() && !cmdLine.logWithSyslog) { cout << "--fork has to be used with --logpath or --syslog" << endl; return false; } if (params.count("keyFile")) { cmdLine.keyFile = params["keyFile"].as<string>(); } if ( params.count("pidfilepath")) { cmdLine.pidFile = params["pidfilepath"].as<string>(); } if (params.count("setParameter")) { std::vector<std::string> parameters = params["setParameter"].as<std::vector<std::string> >(); for (size_t i = 0, length = parameters.size(); i < length; ++i) { std::string name; std::string value; if (!mongoutils::str::splitOn(parameters[i], '=', name, value)) { cout << "Illegal option assignment: \"" << parameters[i] << "\"" << endl; return false; } ServerParameter* parameter = mapFindWithDefault( ServerParameterSet::getGlobal()->getMap(), name, static_cast<ServerParameter*>(NULL)); if (NULL == parameter) { cout << "Illegal --option parameter: \"" << name << "\"" << endl; return false; } Status status = parameter->setFromString(value); if (!status.isOK()) { cout << "Bad value for parameter \"" << name << "\": " << status.reason() << endl; return false; } } } #ifdef MONGO_SSL if (params.count("sslWeakCertificateValidation")) { cmdLine.sslWeakCertificateValidation = true; } if (params.count("sslOnNormalPorts")) { cmdLine.sslOnNormalPorts = true; if ( cmdLine.sslPEMKeyFile.size() == 0 ) { log() << "need sslPEMKeyFile" << endl; return false; } if (cmdLine.sslWeakCertificateValidation && cmdLine.sslCAFile.empty()) { log() << "need sslCAFile with sslWeakCertificateValidation" << endl; return false; } } else if (cmdLine.sslPEMKeyFile.size() || cmdLine.sslPEMKeyPassword.size() || cmdLine.sslCAFile.size() || cmdLine.sslCRLFile.size() || cmdLine.sslWeakCertificateValidation) { log() << "need to enable sslOnNormalPorts" << endl; return false; } #endif return true; }