mirror of
https://github.com/minio/minio.git
synced 2025-11-09 21:49:46 -05:00
server: handle command line and env variables at one place. (#3975)
This commit is contained in:
@@ -94,20 +94,6 @@ func checkUpdate(mode string) {
|
||||
}
|
||||
}
|
||||
|
||||
// envParams holds all env parameters
|
||||
type envParams struct {
|
||||
creds credential
|
||||
browser BrowserFlag
|
||||
}
|
||||
|
||||
func migrate() {
|
||||
// Migrate config file
|
||||
err := migrateConfig()
|
||||
fatalIf(err, "Config migration failed.")
|
||||
|
||||
// Migrate other configs here.
|
||||
}
|
||||
|
||||
func enableLoggers() {
|
||||
fileLogTarget := serverConfig.Logger.GetFile()
|
||||
if fileLogTarget.Enable {
|
||||
@@ -124,77 +110,6 @@ func enableLoggers() {
|
||||
log.SetConsoleTarget(consoleLogTarget)
|
||||
}
|
||||
|
||||
// Initializes a new config if it doesn't exist, else migrates any old config
|
||||
// to newer config and finally loads the config to memory.
|
||||
func initConfig() {
|
||||
accessKey := os.Getenv("MINIO_ACCESS_KEY")
|
||||
secretKey := os.Getenv("MINIO_SECRET_KEY")
|
||||
|
||||
var cred credential
|
||||
var err error
|
||||
if accessKey != "" && secretKey != "" {
|
||||
cred, err = createCredential(accessKey, secretKey)
|
||||
fatalIf(err, "Invalid access/secret Key set in environment.")
|
||||
|
||||
// credential Envs are set globally.
|
||||
globalIsEnvCreds = true
|
||||
}
|
||||
|
||||
envs := envParams{
|
||||
creds: cred,
|
||||
browser: BrowserFlag(true),
|
||||
}
|
||||
|
||||
if browser := os.Getenv("MINIO_BROWSER"); browser != "" {
|
||||
browserFlag, err := ParseBrowserFlag(browser)
|
||||
if err != nil {
|
||||
fatalIf(errors.New("invalid value"), "Unknown value ‘%s’ in MINIO_BROWSER environment variable.", browser)
|
||||
}
|
||||
|
||||
// browser Envs are set globally, this does not represent
|
||||
// if browser is turned off or on.
|
||||
globalIsEnvBrowser = true
|
||||
envs.browser = browserFlag
|
||||
}
|
||||
|
||||
// Config file does not exist, we create it fresh and return upon success.
|
||||
if !isConfigFileExists() {
|
||||
err := newConfig(envs)
|
||||
fatalIf(err, "Unable to initialize minio config for the first time.")
|
||||
log.Println("Created minio configuration file successfully at " + getConfigDir())
|
||||
return
|
||||
}
|
||||
|
||||
// Migrate any old version of config / state files to newer format.
|
||||
migrate()
|
||||
|
||||
// Validate config file
|
||||
err = validateConfig()
|
||||
fatalIf(err, "Unable to validate configuration file")
|
||||
|
||||
// Once we have migrated all the old config, now load them.
|
||||
err = loadConfig(envs)
|
||||
fatalIf(err, "Unable to initialize minio config")
|
||||
}
|
||||
|
||||
// Generic Minio initialization to create/load config, prepare loggers, etc..
|
||||
func minioInit(ctx *cli.Context) {
|
||||
// Create certs path.
|
||||
fatalIf(createConfigDir(), "Unable to create \"certs\" directory.")
|
||||
|
||||
// Is TLS configured?.
|
||||
globalIsSSL = isSSL()
|
||||
|
||||
// Initialize minio server config.
|
||||
initConfig()
|
||||
|
||||
// Enable all loggers by now so we can use errorIf() and fatalIf()
|
||||
enableLoggers()
|
||||
|
||||
// Init the error tracing module.
|
||||
initError()
|
||||
}
|
||||
|
||||
type serverCmdConfig struct {
|
||||
serverAddr string
|
||||
endpoints []*url.URL
|
||||
@@ -240,18 +155,6 @@ func parseStorageEndpoints(eps []string) (endpoints []*url.URL, err error) {
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
// initServer initialize server config.
|
||||
func initServerConfig(c *cli.Context) {
|
||||
// Initialization such as config generating/loading config, enable logging, ..
|
||||
minioInit(c)
|
||||
|
||||
// Load user supplied root CAs
|
||||
fatalIf(loadRootCAs(), "Unable to load a CA files")
|
||||
|
||||
// Set system resources to maximum.
|
||||
errorIf(setMaxResources(), "Unable to change resource limit")
|
||||
}
|
||||
|
||||
// Validate if input disks are sufficient for initializing XL.
|
||||
func checkSufficientDisks(eps []*url.URL) error {
|
||||
// Verify total number of disks.
|
||||
@@ -344,21 +247,9 @@ func checkEndpointsSyntax(eps []*url.URL, disks []string) error {
|
||||
}
|
||||
|
||||
// Make sure all the command line parameters are OK and exit in case of invalid parameters.
|
||||
func checkServerSyntax(c *cli.Context) {
|
||||
serverAddr := c.String("address")
|
||||
|
||||
host, portStr, err := net.SplitHostPort(serverAddr)
|
||||
fatalIf(err, "Unable to parse %s.", serverAddr)
|
||||
|
||||
// Verify syntax for all the XL disks.
|
||||
disks := c.Args()
|
||||
|
||||
// Parse disks check if they comply with expected URI style.
|
||||
endpoints, err := parseStorageEndpoints(disks)
|
||||
fatalIf(err, "Unable to parse storage endpoints %s", strings.Join(disks, " "))
|
||||
|
||||
func checkServerSyntax(endpoints []*url.URL, disks []string) {
|
||||
// Validate if endpoints follow the expected syntax.
|
||||
err = checkEndpointsSyntax(endpoints, disks)
|
||||
err := checkEndpointsSyntax(endpoints, disks)
|
||||
fatalIf(err, "Invalid endpoints found %s", strings.Join(disks, " "))
|
||||
|
||||
// Validate for duplicate endpoints are supplied.
|
||||
@@ -382,25 +273,25 @@ func checkServerSyntax(c *cli.Context) {
|
||||
}
|
||||
|
||||
// Rest of the checks applies only to distributed XL setup.
|
||||
if host != "" {
|
||||
if globalMinioHost != "" {
|
||||
// We are here implies --address host:port is passed, hence the user is trying
|
||||
// to run one minio process per export disk.
|
||||
if portStr == "" {
|
||||
if globalMinioPort == "" {
|
||||
fatalIf(errInvalidArgument, "Port missing, Host:Port should be specified for --address")
|
||||
}
|
||||
foundCnt := 0
|
||||
for _, ep := range endpoints {
|
||||
if ep.Host == serverAddr {
|
||||
if ep.Host == globalMinioAddr {
|
||||
foundCnt++
|
||||
}
|
||||
}
|
||||
if foundCnt == 0 {
|
||||
// --address host:port should be available in the XL disk list.
|
||||
fatalIf(errInvalidArgument, "%s is not available in %s", serverAddr, strings.Join(disks, " "))
|
||||
fatalIf(errInvalidArgument, "%s is not available in %s", globalMinioAddr, strings.Join(disks, " "))
|
||||
}
|
||||
if foundCnt > 1 {
|
||||
// --address host:port should match exactly one entry in the XL disk list.
|
||||
fatalIf(errInvalidArgument, "%s matches % entries in %s", serverAddr, foundCnt, strings.Join(disks, " "))
|
||||
fatalIf(errInvalidArgument, "%s matches % entries in %s", globalMinioAddr, foundCnt, strings.Join(disks, " "))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,22 +353,23 @@ func getHostPort(address string) (host, port string, err error) {
|
||||
return host, port, nil
|
||||
}
|
||||
|
||||
// serverMain handler called for 'minio server' command.
|
||||
func serverMain(c *cli.Context) {
|
||||
if !c.Args().Present() || c.Args().First() == "help" {
|
||||
cli.ShowCommandHelpAndExit(c, "server", 1)
|
||||
}
|
||||
|
||||
// Get quiet flag from command line argument.
|
||||
quietFlag := c.Bool("quiet") || c.GlobalBool("quiet")
|
||||
if quietFlag {
|
||||
log.EnableQuiet()
|
||||
func initConfig() {
|
||||
// Config file does not exist, we create it fresh and return upon success.
|
||||
if isFile(getConfigFile()) {
|
||||
fatalIf(migrateConfig(), "Config migration failed.")
|
||||
fatalIf(validateConfig(), "Unable to validate configuration file")
|
||||
fatalIf(loadConfig(), "Unable to initialize minio config")
|
||||
} else {
|
||||
fatalIf(newConfig(), "Unable to initialize minio config for the first time.")
|
||||
log.Println("Created minio configuration file successfully at " + getConfigDir())
|
||||
}
|
||||
}
|
||||
|
||||
func serverHandleCmdArgs(ctx *cli.Context) {
|
||||
// Get configuration directory from command line argument.
|
||||
configDir := c.String("config-dir")
|
||||
if !c.IsSet("config-dir") && c.GlobalIsSet("config-dir") {
|
||||
configDir = c.GlobalString("config-dir")
|
||||
configDir := ctx.String("config-dir")
|
||||
if !ctx.IsSet("config-dir") && ctx.GlobalIsSet("config-dir") {
|
||||
configDir = ctx.GlobalString("config-dir")
|
||||
}
|
||||
if configDir == "" {
|
||||
fatalIf(errors.New("empty directory"), "Configuration directory cannot be empty.")
|
||||
@@ -494,35 +386,16 @@ func serverMain(c *cli.Context) {
|
||||
// Set configuration directory.
|
||||
setConfigDir(configDir)
|
||||
|
||||
// Start profiler if env is set.
|
||||
if profiler := os.Getenv("_MINIO_PROFILER"); profiler != "" {
|
||||
globalProfiler = startProfiler(profiler)
|
||||
}
|
||||
|
||||
// Initializes server config, certs, logging and system settings.
|
||||
initServerConfig(c)
|
||||
|
||||
// Server address.
|
||||
serverAddr := c.String("address")
|
||||
globalMinioAddr = ctx.String("address")
|
||||
|
||||
var err error
|
||||
globalMinioHost, globalMinioPort, err = getHostPort(serverAddr)
|
||||
fatalIf(err, "Unable to extract host and port %s", serverAddr)
|
||||
|
||||
// Check server syntax and exit in case of errors.
|
||||
// Done after globalMinioHost and globalMinioPort is set
|
||||
// as parseStorageEndpoints() depends on it.
|
||||
checkServerSyntax(c)
|
||||
globalMinioHost, globalMinioPort, err = getHostPort(globalMinioAddr)
|
||||
fatalIf(err, "Unable to extract host and port %s", globalMinioAddr)
|
||||
|
||||
// Disks to be used in server init.
|
||||
endpoints, err := parseStorageEndpoints(c.Args())
|
||||
fatalIf(err, "Unable to parse storage endpoints %s", c.Args())
|
||||
|
||||
// Should exit gracefully if none of the endpoints passed
|
||||
// as command line args are local to this server.
|
||||
if !isAnyEndpointLocal(endpoints) {
|
||||
fatalIf(errInvalidArgument, "None of the disks passed as command line args are local to this server.")
|
||||
}
|
||||
endpoints, err := parseStorageEndpoints(ctx.Args())
|
||||
fatalIf(err, "Unable to parse storage endpoints %s", ctx.Args())
|
||||
|
||||
// Sort endpoints for consistent ordering across multiple
|
||||
// nodes in a distributed setup. This is to avoid format.json
|
||||
@@ -530,26 +403,91 @@ func serverMain(c *cli.Context) {
|
||||
// on all nodes.
|
||||
sort.Sort(byHostPath(endpoints))
|
||||
|
||||
// Configure server.
|
||||
srvConfig := serverCmdConfig{
|
||||
serverAddr: serverAddr,
|
||||
endpoints: endpoints,
|
||||
checkServerSyntax(endpoints, ctx.Args())
|
||||
|
||||
// Should exit gracefully if none of the endpoints passed
|
||||
// as command line args are local to this server.
|
||||
if !isAnyEndpointLocal(endpoints) {
|
||||
fatalIf(errInvalidArgument, "None of the disks passed as command line args are local to this server.")
|
||||
}
|
||||
|
||||
// Check if endpoints are part of distributed setup.
|
||||
globalIsDistXL = isDistributedSetup(endpoints)
|
||||
|
||||
// Set nodes for dsync for distributed setup.
|
||||
if globalIsDistXL {
|
||||
fatalIf(initDsyncNodes(endpoints), "Unable to initialize distributed locking clients")
|
||||
}
|
||||
|
||||
// Set globalIsXL if erasure code backend is about to be
|
||||
// initialized for the given endpoints.
|
||||
if len(endpoints) > 1 {
|
||||
globalIsXL = true
|
||||
}
|
||||
|
||||
// Set endpoints of []*url.URL type to globalEndpoints.
|
||||
globalEndpoints = endpoints
|
||||
}
|
||||
|
||||
func serverHandleEnvVars() {
|
||||
// Start profiler if env is set.
|
||||
if profiler := os.Getenv("_MINIO_PROFILER"); profiler != "" {
|
||||
globalProfiler = startProfiler(profiler)
|
||||
}
|
||||
|
||||
// Check if object cache is disabled.
|
||||
globalXLObjCacheDisabled = strings.EqualFold(os.Getenv("_MINIO_CACHE"), "off")
|
||||
|
||||
accessKey := os.Getenv("MINIO_ACCESS_KEY")
|
||||
secretKey := os.Getenv("MINIO_SECRET_KEY")
|
||||
if accessKey != "" && secretKey != "" {
|
||||
cred, err := createCredential(accessKey, secretKey)
|
||||
fatalIf(err, "Invalid access/secret Key set in environment.")
|
||||
|
||||
// credential Envs are set globally.
|
||||
globalIsEnvCreds = true
|
||||
globalActiveCred = cred
|
||||
}
|
||||
|
||||
if browser := os.Getenv("MINIO_BROWSER"); browser != "" {
|
||||
browserFlag, err := ParseBrowserFlag(browser)
|
||||
if err != nil {
|
||||
fatalIf(errors.New("invalid value"), "Unknown value ‘%s’ in MINIO_BROWSER environment variable.", browser)
|
||||
}
|
||||
|
||||
// browser Envs are set globally, this does not represent
|
||||
// if browser is turned off or on.
|
||||
globalIsEnvBrowser = true
|
||||
globalIsBrowserEnabled = bool(browserFlag)
|
||||
}
|
||||
}
|
||||
|
||||
// serverMain handler called for 'minio server' command.
|
||||
func serverMain(ctx *cli.Context) {
|
||||
if !ctx.Args().Present() || ctx.Args().First() == "help" {
|
||||
cli.ShowCommandHelpAndExit(ctx, "server", 1)
|
||||
}
|
||||
|
||||
// Get quiet flag from command line argument.
|
||||
quietFlag := ctx.Bool("quiet") || ctx.GlobalBool("quiet")
|
||||
if quietFlag {
|
||||
log.EnableQuiet()
|
||||
}
|
||||
|
||||
serverHandleCmdArgs(ctx)
|
||||
serverHandleEnvVars()
|
||||
|
||||
// Create certs path.
|
||||
fatalIf(createConfigDir(), "Unable to create configuration directories.")
|
||||
|
||||
initConfig()
|
||||
|
||||
// Enable loggers as per configuration file.
|
||||
enableLoggers()
|
||||
|
||||
// Init the error tracing module.
|
||||
initError()
|
||||
|
||||
// Check and load SSL certificates.
|
||||
var err error
|
||||
globalPublicCerts, globalRootCAs, globalIsSSL, err = getSSLConfig()
|
||||
fatalIf(err, "Invalid SSL key file")
|
||||
|
||||
if !quietFlag {
|
||||
// Check for new updates from dl.minio.io.
|
||||
mode := globalMinioModeFS
|
||||
@@ -562,32 +500,43 @@ func serverMain(c *cli.Context) {
|
||||
checkUpdate(mode)
|
||||
}
|
||||
|
||||
// Set system resources to maximum.
|
||||
errorIf(setMaxResources(), "Unable to change resource limit")
|
||||
|
||||
// Set nodes for dsync for distributed setup.
|
||||
if globalIsDistXL {
|
||||
fatalIf(initDsyncNodes(), "Unable to initialize distributed locking clients")
|
||||
}
|
||||
|
||||
// Initialize name space lock.
|
||||
initNSLock(globalIsDistXL)
|
||||
|
||||
// Configure server.
|
||||
srvConfig := serverCmdConfig{
|
||||
serverAddr: globalMinioAddr,
|
||||
endpoints: globalEndpoints,
|
||||
}
|
||||
|
||||
// Configure server.
|
||||
handler, err := configureServerHandler(srvConfig)
|
||||
fatalIf(err, "Unable to configure one of server's RPC services.")
|
||||
|
||||
// Initialize a new HTTP server.
|
||||
apiServer := NewServerMux(serverAddr, handler)
|
||||
apiServer := NewServerMux(globalMinioAddr, handler)
|
||||
|
||||
// Set the global minio addr for this server.
|
||||
globalMinioAddr = getLocalAddress(srvConfig)
|
||||
|
||||
// Initialize S3 Peers inter-node communication only in distributed setup.
|
||||
initGlobalS3Peers(endpoints)
|
||||
initGlobalS3Peers(globalEndpoints)
|
||||
|
||||
// Initialize Admin Peers inter-node communication only in distributed setup.
|
||||
initGlobalAdminPeers(endpoints)
|
||||
initGlobalAdminPeers(globalEndpoints)
|
||||
|
||||
// Determine API endpoints where we are going to serve the S3 API from.
|
||||
apiEndPoints, err := finalizeAPIEndpoints(apiServer.Addr)
|
||||
globalAPIEndpoints, err = finalizeAPIEndpoints(apiServer.Addr)
|
||||
fatalIf(err, "Unable to finalize API endpoints for %s", apiServer.Addr)
|
||||
|
||||
// Set the global API endpoints value.
|
||||
globalAPIEndpoints = apiEndPoints
|
||||
|
||||
// Start server, automatically configures TLS if certs are available.
|
||||
go func() {
|
||||
cert, key := "", ""
|
||||
@@ -597,9 +546,6 @@ func serverMain(c *cli.Context) {
|
||||
fatalIf(apiServer.ListenAndServe(cert, key), "Failed to start minio server.")
|
||||
}()
|
||||
|
||||
// Set endpoints of []*url.URL type to globalEndpoints.
|
||||
globalEndpoints = endpoints
|
||||
|
||||
newObject, err := newObjectLayer(srvConfig)
|
||||
fatalIf(err, "Initializing object layer failed")
|
||||
|
||||
@@ -608,9 +554,7 @@ func serverMain(c *cli.Context) {
|
||||
globalObjLayerMutex.Unlock()
|
||||
|
||||
// Prints the formatted startup message once object layer is initialized.
|
||||
if !quietFlag {
|
||||
printStartupMessage(apiEndPoints)
|
||||
}
|
||||
printStartupMessage(globalAPIEndpoints)
|
||||
|
||||
// Set uptime time after object layer has initialized.
|
||||
globalBootTime = UTCNow()
|
||||
|
||||
Reference in New Issue
Block a user