mirror of
https://github.com/minio/minio.git
synced 2025-11-07 04:42:56 -05:00
remove safeMode behavior in startup (#10645)
In almost all scenarios MinIO now is mostly ready for all sub-systems independently, safe-mode is not useful anymore and do not serve its original intended purpose. allow server to be fully functional even with config partially configured, this is to cater for availability of actual I/O v/s manually fixing the server. In k8s like environments it will never make sense to take pod into safe-mode state, because there is no real access to perform any remote operation on them.
This commit is contained in:
@@ -186,7 +186,7 @@ func newAllSubsystems() {
|
||||
globalBucketTargetSys = NewBucketTargetSys()
|
||||
}
|
||||
|
||||
func initSafeMode(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
func initServer(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
// Create cancel context to control 'newRetryTimer' go routine.
|
||||
retryCtx, cancel := context.WithCancel(ctx)
|
||||
|
||||
@@ -199,33 +199,33 @@ func initSafeMode(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
// appropriately. This is also true for rotation of encrypted
|
||||
// content.
|
||||
txnLk := newObject.NewNSLock(retryCtx, minioMetaBucket, minioConfigPrefix+"/transaction.lock")
|
||||
var locked bool
|
||||
defer func(txnLk RWLocker) {
|
||||
if locked {
|
||||
txnLk.Unlock()
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
var cerr config.Err
|
||||
// For any config error, we don't need to drop into safe-mode
|
||||
// instead its a user error and should be fixed by user.
|
||||
if errors.As(err, &cerr) {
|
||||
logger.FatalIf(err, "Unable to initialize the server")
|
||||
return
|
||||
}
|
||||
|
||||
// If context was canceled
|
||||
if errors.Is(err, context.Canceled) {
|
||||
logger.FatalIf(err, "Server startup canceled upon user request")
|
||||
return
|
||||
}
|
||||
|
||||
// Prints the formatted startup message in safe mode operation.
|
||||
// Drops-into safe mode where users need to now manually recover
|
||||
// the server.
|
||||
printStartupSafeModeMessage(getAPIEndpoints(), err)
|
||||
|
||||
<-globalOSSignalCh
|
||||
}
|
||||
}(txnLk)
|
||||
|
||||
// Prints the formatted startup message, if err is not nil then it prints additional information as well.
|
||||
printStartupMessage(getAPIEndpoints(), err)
|
||||
|
||||
if globalActiveCred.Equal(auth.DefaultCredentials) {
|
||||
msg := fmt.Sprintf("Detected default credentials '%s', please change the credentials immediately using 'MINIO_ACCESS_KEY' and 'MINIO_SECRET_KEY'", globalActiveCred)
|
||||
logger.StartupMessage(color.RedBold(msg))
|
||||
}
|
||||
|
||||
<-globalOSSignalCh
|
||||
}()
|
||||
|
||||
// Enable background operations for erasure coding
|
||||
if globalIsErasure {
|
||||
@@ -256,9 +256,6 @@ func initSafeMode(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
continue
|
||||
}
|
||||
|
||||
// locked successful
|
||||
locked = true
|
||||
|
||||
// These messages only meant primarily for distributed setup, so only log during distributed setup.
|
||||
if globalIsDistErasure {
|
||||
logger.Info("Waiting for all MinIO sub-systems to be initialized.. lock acquired")
|
||||
@@ -270,7 +267,8 @@ func initSafeMode(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
if err = handleEncryptedConfigBackend(newObject); err == nil {
|
||||
// Upon success migrating the config, initialize all sub-systems
|
||||
// if all sub-systems initialized successfully return right away
|
||||
if err = initAllSubsystems(retryCtx, newObject); err == nil {
|
||||
if err = initAllSubsystems(ctx, newObject); err == nil {
|
||||
txnLk.Unlock()
|
||||
// All successful return.
|
||||
if globalIsDistErasure {
|
||||
// These messages only meant primarily for distributed setup, so only log during distributed setup.
|
||||
@@ -280,6 +278,8 @@ func initSafeMode(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
txnLk.Unlock() // Unlock the transaction lock and allow other nodes to acquire the lock if possible.
|
||||
|
||||
// One of these retriable errors shall be retried.
|
||||
if errors.Is(err, errDiskNotFound) ||
|
||||
errors.Is(err, errConfigNotFound) ||
|
||||
@@ -288,8 +288,6 @@ func initSafeMode(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
errors.As(err, &wquorum) ||
|
||||
isErrBucketNotFound(err) {
|
||||
logger.Info("Waiting for all MinIO sub-systems to be initialized.. possible cause (%v)", err)
|
||||
txnLk.Unlock() // Unlock the transaction lock and allow other nodes to acquire the lock if possible.
|
||||
locked = false
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -299,7 +297,7 @@ func initSafeMode(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
|
||||
// Return an error when retry is canceled or deadlined
|
||||
if err = retryCtx.Err(); err != nil {
|
||||
return fmt.Errorf("Unable to initialize sub-systems: %w", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Retry was canceled successfully.
|
||||
@@ -314,13 +312,13 @@ func initAllSubsystems(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
// ensures top level retry works accordingly.
|
||||
// List buckets to heal, and be re-used for loading configs.
|
||||
var buckets []BucketInfo
|
||||
rquorum := InsufficientReadQuorum{}
|
||||
wquorum := InsufficientWriteQuorum{}
|
||||
if globalIsErasure {
|
||||
buckets, err = newObject.ListBucketsHeal(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to list buckets to heal: %w", err)
|
||||
}
|
||||
rquorum := InsufficientReadQuorum{}
|
||||
wquorum := InsufficientWriteQuorum{}
|
||||
for _, bucket := range buckets {
|
||||
if err = newObject.MakeBucketWithLocation(ctx, bucket.Name, BucketOptions{}); err != nil {
|
||||
if errors.As(err, &wquorum) || errors.As(err, &rquorum) {
|
||||
@@ -344,7 +342,16 @@ func initAllSubsystems(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
|
||||
// Initialize config system.
|
||||
if err = globalConfigSys.Init(newObject); err != nil {
|
||||
return fmt.Errorf("Unable to initialize config system: %w", err)
|
||||
if errors.Is(err, errDiskNotFound) ||
|
||||
errors.Is(err, errConfigNotFound) ||
|
||||
errors.Is(err, context.DeadlineExceeded) ||
|
||||
errors.As(err, &rquorum) ||
|
||||
errors.As(err, &wquorum) ||
|
||||
isErrBucketNotFound(err) {
|
||||
return fmt.Errorf("Unable to initialize config system: %w", err)
|
||||
}
|
||||
// Any other config errors we simply print a message and proceed forward.
|
||||
logger.LogIf(ctx, err)
|
||||
}
|
||||
|
||||
// Populate existing buckets to the etcd backend
|
||||
@@ -353,20 +360,25 @@ func initAllSubsystems(ctx context.Context, newObject ObjectLayer) (err error) {
|
||||
go initFederatorBackend(buckets, newObject)
|
||||
}
|
||||
|
||||
// Initialize bucket metadata sub-system.
|
||||
if err = globalBucketMetadataSys.Init(ctx, buckets, newObject); err != nil {
|
||||
return fmt.Errorf("Unable to initialize bucket metadata sub-system: %w", err)
|
||||
if globalCacheConfig.Enabled {
|
||||
// initialize the new disk cache objects.
|
||||
var cacheAPI CacheObjectLayer
|
||||
cacheAPI, err = newServerCacheObjects(ctx, globalCacheConfig)
|
||||
logger.FatalIf(err, "Unable to initialize disk caching")
|
||||
|
||||
globalObjLayerMutex.Lock()
|
||||
globalCacheObjectAPI = cacheAPI
|
||||
globalObjLayerMutex.Unlock()
|
||||
}
|
||||
|
||||
// Initialize bucket metadata sub-system.
|
||||
globalBucketMetadataSys.Init(ctx, buckets, newObject)
|
||||
|
||||
// Initialize notification system.
|
||||
if err = globalNotificationSys.Init(ctx, buckets, newObject); err != nil {
|
||||
return fmt.Errorf("Unable to initialize notification system: %w", err)
|
||||
}
|
||||
globalNotificationSys.Init(ctx, buckets, newObject)
|
||||
|
||||
// Initialize bucket targets sub-system.
|
||||
if err = globalBucketTargetSys.Init(ctx, buckets, newObject); err != nil {
|
||||
return fmt.Errorf("Unable to initialize bucket target sub-system: %w", err)
|
||||
}
|
||||
globalBucketTargetSys.Init(ctx, buckets, newObject)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -488,42 +500,15 @@ func serverMain(ctx *cli.Context) {
|
||||
|
||||
// Once endpoints are finalized, initialize the new object api in safe mode.
|
||||
globalObjLayerMutex.Lock()
|
||||
globalSafeMode = true
|
||||
globalObjectAPI = newObject
|
||||
globalObjLayerMutex.Unlock()
|
||||
|
||||
go initDataCrawler(GlobalContext, newObject)
|
||||
|
||||
logger.FatalIf(initSafeMode(GlobalContext, newObject), "Unable to initialize server switching into safe-mode")
|
||||
|
||||
// Initialize users credentials and policies in background.
|
||||
go startBackgroundIAMLoad(GlobalContext)
|
||||
go startBackgroundIAMLoad(GlobalContext, newObject)
|
||||
|
||||
if globalCacheConfig.Enabled {
|
||||
// initialize the new disk cache objects.
|
||||
var cacheAPI CacheObjectLayer
|
||||
cacheAPI, err = newServerCacheObjects(GlobalContext, globalCacheConfig)
|
||||
logger.FatalIf(err, "Unable to initialize disk caching")
|
||||
|
||||
globalObjLayerMutex.Lock()
|
||||
globalCacheObjectAPI = cacheAPI
|
||||
globalObjLayerMutex.Unlock()
|
||||
}
|
||||
|
||||
// Disable safe mode operation, after all initialization is over.
|
||||
globalObjLayerMutex.Lock()
|
||||
globalSafeMode = false
|
||||
globalObjLayerMutex.Unlock()
|
||||
|
||||
// Prints the formatted startup message once object layer is initialized.
|
||||
printStartupMessage(getAPIEndpoints())
|
||||
|
||||
if globalActiveCred.Equal(auth.DefaultCredentials) {
|
||||
msg := fmt.Sprintf("Detected default credentials '%s', please change the credentials immediately using 'MINIO_ACCESS_KEY' and 'MINIO_SECRET_KEY'", globalActiveCred)
|
||||
logger.StartupMessage(color.RedBold(msg))
|
||||
}
|
||||
|
||||
<-globalOSSignalCh
|
||||
initServer(GlobalContext, newObject)
|
||||
}
|
||||
|
||||
// Initialize object layer with the supplied disks, objectLayer is nil upon any error.
|
||||
|
||||
Reference in New Issue
Block a user