From a0d0645128a989a4bbced177109d952900a71df6 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 9 Oct 2020 09:59:52 -0700 Subject: [PATCH] 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. --- cmd/admin-handlers-config-kv.go | 2 +- cmd/admin-handlers-users.go | 10 +-- cmd/admin-handlers.go | 8 +-- cmd/admin-heal-ops.go | 10 +-- cmd/api-response.go | 8 --- cmd/api-router.go | 13 ---- cmd/bucket-encryption.go | 2 +- cmd/bucket-lifecycle.go | 2 +- cmd/bucket-metadata-sys.go | 8 +-- cmd/bucket-object-lock.go | 2 +- cmd/bucket-quota.go | 2 +- cmd/bucket-replication.go | 2 +- cmd/data-crawler.go | 2 +- cmd/gateway-main.go | 8 +-- cmd/globals.go | 5 -- cmd/iam.go | 54 ++++++++-------- cmd/lock-rest-server.go | 6 +- cmd/metrics.go | 6 +- cmd/notification.go | 10 +-- cmd/peer-rest-server.go | 22 +++---- cmd/server-main.go | 107 ++++++++++++++------------------ cmd/server-startup-msg.go | 94 ++++------------------------ cmd/server-startup-msg_test.go | 2 +- cmd/signals.go | 2 +- cmd/test-utils_test.go | 10 +-- cmd/xl-storage.go | 2 +- pkg/event/targetlist.go | 4 ++ 27 files changed, 137 insertions(+), 266 deletions(-) diff --git a/cmd/admin-handlers-config-kv.go b/cmd/admin-handlers-config-kv.go index 653c165c4..30eb8e5ab 100644 --- a/cmd/admin-handlers-config-kv.go +++ b/cmd/admin-handlers-config-kv.go @@ -42,7 +42,7 @@ import ( func validateAdminReqConfigKV(ctx context.Context, w http.ResponseWriter, r *http.Request) (auth.Credentials, ObjectLayer) { // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return auth.Credentials{}, nil diff --git a/cmd/admin-handlers-users.go b/cmd/admin-handlers-users.go index 0f2f29bca..cd9c9343c 100644 --- a/cmd/admin-handlers-users.go +++ b/cmd/admin-handlers-users.go @@ -35,7 +35,7 @@ func validateAdminUsersReq(ctx context.Context, w http.ResponseWriter, r *http.R var adminAPIErr APIErrorCode // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return nil, cred @@ -386,7 +386,7 @@ func (a adminAPIHandlers) AddServiceAccount(w http.ResponseWriter, r *http.Reque defer logger.AuditLog(w, r, "AddServiceAccount", mustGetClaimsFromToken(r)) // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return @@ -465,7 +465,7 @@ func (a adminAPIHandlers) ListServiceAccounts(w http.ResponseWriter, r *http.Req defer logger.AuditLog(w, r, "ListServiceAccounts", mustGetClaimsFromToken(r)) // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return @@ -520,7 +520,7 @@ func (a adminAPIHandlers) DeleteServiceAccount(w http.ResponseWriter, r *http.Re defer logger.AuditLog(w, r, "DeleteServiceAccount", mustGetClaimsFromToken(r)) // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return @@ -579,7 +579,7 @@ func (a adminAPIHandlers) AccountUsageInfoHandler(w http.ResponseWriter, r *http defer logger.AuditLog(w, r, "AccountUsageInfo", mustGetClaimsFromToken(r)) // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 72d1a6717..0dc9100c2 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -899,7 +899,7 @@ func validateAdminReq(ctx context.Context, w http.ResponseWriter, r *http.Reques var cred auth.Credentials var adminAPIErr APIErrorCode // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || globalNotificationSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return nil, cred @@ -1490,11 +1490,7 @@ func (a adminAPIHandlers) ServerInfoHandler(w http.ResponseWriter, r *http.Reque } } - mode := "safemode" - if newObjectLayerFn() != nil { - mode = "online" - } - + mode := "online" server := getLocalServerProperty(globalEndpoints, r) servers := globalNotificationSys.ServerInfo() servers = append(servers, server) diff --git a/cmd/admin-heal-ops.go b/cmd/admin-heal-ops.go index ce7a3665d..b7d71d2e1 100644 --- a/cmd/admin-heal-ops.go +++ b/cmd/admin-heal-ops.go @@ -808,7 +808,7 @@ func (h *healSequence) traverseAndHeal() { func (h *healSequence) healMinioSysMeta(metaPrefix string) func() error { return func() error { // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil { return errServerNotInitialized } @@ -844,7 +844,7 @@ func (h *healSequence) healDiskFormat() error { } // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil { return errServerNotInitialized } @@ -864,7 +864,7 @@ func (h *healSequence) healBuckets(bucketsOnly bool) error { } // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil { return errServerNotInitialized } @@ -886,7 +886,7 @@ func (h *healSequence) healBuckets(bucketsOnly bool) error { // healBucket - traverses and heals given bucket func (h *healSequence) healBucket(bucket string, bucketsOnly bool) error { // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil { return errServerNotInitialized } @@ -932,7 +932,7 @@ func (h *healSequence) healBucket(bucket string, bucketsOnly bool) error { // healObject - heal the given object and record result func (h *healSequence) healObject(bucket, object, versionID string) error { // Get current object layer instance. - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil { return errServerNotInitialized } diff --git a/cmd/api-response.go b/cmd/api-response.go index 4d6c0e689..968a46b8d 100644 --- a/cmd/api-response.go +++ b/cmd/api-response.go @@ -703,10 +703,6 @@ func generateMultiDeleteResponse(quiet bool, deletedObjects []DeletedObject, err } func writeResponse(w http.ResponseWriter, statusCode int, response []byte, mType mimeType) { - if newObjectLayerFn() == nil { - // Server still in safe mode. - w.Header().Set(xhttp.MinIOServerStatus, "safemode") - } setCommonHeaders(w) if mType != mimeNone { w.Header().Set(xhttp.ContentType, string(mType)) @@ -773,10 +769,6 @@ func writeErrorResponse(ctx context.Context, w http.ResponseWriter, err APIError // The request is from browser and also if browser // is enabled we need to redirect. if browser && globalBrowserEnabled { - if newObjectLayerFn() == nil { - // server still in safe mode. - w.Header().Set(xhttp.MinIOServerStatus, "safemode") - } w.Header().Set(xhttp.Location, minioReservedBucketPath+reqURL.Path) w.WriteHeader(http.StatusTemporaryRedirect) return diff --git a/cmd/api-router.go b/cmd/api-router.go index 3bdd166e4..f69945dc9 100644 --- a/cmd/api-router.go +++ b/cmd/api-router.go @@ -32,28 +32,15 @@ func newHTTPServerFn() *xhttp.Server { return globalHTTPServer } -func newObjectLayerWithoutSafeModeFn() ObjectLayer { - globalObjLayerMutex.Lock() - defer globalObjLayerMutex.Unlock() - return globalObjectAPI -} - func newObjectLayerFn() ObjectLayer { globalObjLayerMutex.Lock() defer globalObjLayerMutex.Unlock() - if globalSafeMode { - return nil - } return globalObjectAPI } func newCachedObjectLayerFn() CacheObjectLayer { globalObjLayerMutex.Lock() defer globalObjLayerMutex.Unlock() - - if globalSafeMode { - return nil - } return globalCacheObjectAPI } diff --git a/cmd/bucket-encryption.go b/cmd/bucket-encryption.go index 2c2ab1606..5c1040b18 100644 --- a/cmd/bucket-encryption.go +++ b/cmd/bucket-encryption.go @@ -34,7 +34,7 @@ func NewBucketSSEConfigSys() *BucketSSEConfigSys { // Get - gets bucket encryption config for the given bucket. func (sys *BucketSSEConfigSys) Get(bucket string) (*bucketsse.BucketSSEConfig, error) { if globalIsGateway { - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return nil, errServerNotInitialized } diff --git a/cmd/bucket-lifecycle.go b/cmd/bucket-lifecycle.go index 01d69978e..520bf04d0 100644 --- a/cmd/bucket-lifecycle.go +++ b/cmd/bucket-lifecycle.go @@ -31,7 +31,7 @@ type LifecycleSys struct{} // Get - gets lifecycle config associated to a given bucket name. func (sys *LifecycleSys) Get(bucketName string) (lc *lifecycle.Lifecycle, err error) { if globalIsGateway { - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return nil, errServerNotInitialized } diff --git a/cmd/bucket-metadata-sys.go b/cmd/bucket-metadata-sys.go index 56a471d03..2e1011d00 100644 --- a/cmd/bucket-metadata-sys.go +++ b/cmd/bucket-metadata-sys.go @@ -72,7 +72,7 @@ func (sys *BucketMetadataSys) Set(bucket string, meta BucketMetadata) { // Update update bucket metadata for the specified config file. // The configData data should not be modified after being sent here. func (sys *BucketMetadataSys) Update(bucket string, configFile string, configData []byte) error { - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return errServerNotInitialized } @@ -275,7 +275,7 @@ func (sys *BucketMetadataSys) GetLifecycleConfig(bucket string) (*lifecycle.Life func (sys *BucketMetadataSys) GetNotificationConfig(bucket string) (*event.Config, error) { if globalIsGateway && globalGatewayName == NASBackendGateway { // Only needed in case of NAS gateway. - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return nil, errServerNotInitialized } @@ -313,7 +313,7 @@ func (sys *BucketMetadataSys) GetSSEConfig(bucket string) (*bucketsse.BucketSSEC // The returned object may not be modified. func (sys *BucketMetadataSys) GetPolicyConfig(bucket string) (*policy.Policy, error) { if globalIsGateway { - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return nil, errServerNotInitialized } @@ -376,7 +376,7 @@ func (sys *BucketMetadataSys) GetBucketTargetsConfig(bucket string) (*madmin.Buc // GetConfig returns a specific configuration from the bucket metadata. // The returned object may not be modified. func (sys *BucketMetadataSys) GetConfig(bucket string) (BucketMetadata, error) { - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return newBucketMetadata(bucket), errServerNotInitialized } diff --git a/cmd/bucket-object-lock.go b/cmd/bucket-object-lock.go index f8c7931be..0eb83b0ad 100644 --- a/cmd/bucket-object-lock.go +++ b/cmd/bucket-object-lock.go @@ -33,7 +33,7 @@ type BucketObjectLockSys struct{} // Get - Get retention configuration. func (sys *BucketObjectLockSys) Get(bucketName string) (r objectlock.Retention, err error) { if globalIsGateway { - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return r, errServerNotInitialized } diff --git a/cmd/bucket-quota.go b/cmd/bucket-quota.go index 6a9307f83..b9f7273bf 100644 --- a/cmd/bucket-quota.go +++ b/cmd/bucket-quota.go @@ -63,7 +63,7 @@ func parseBucketQuota(bucket string, data []byte) (quotaCfg *madmin.BucketQuota, } func (sys *BucketQuotaSys) check(ctx context.Context, bucket string, size int64) error { - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return errServerNotInitialized } diff --git a/cmd/bucket-replication.go b/cmd/bucket-replication.go index b94288f92..571c168d1 100644 --- a/cmd/bucket-replication.go +++ b/cmd/bucket-replication.go @@ -38,7 +38,7 @@ import ( // gets replication config associated to a given bucket name. func getReplicationConfig(ctx context.Context, bucketName string) (rc *replication.Config, err error) { if globalIsGateway { - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return nil, errServerNotInitialized } diff --git a/cmd/data-crawler.go b/cmd/data-crawler.go index 2f9a21d59..a25d92752 100644 --- a/cmd/data-crawler.go +++ b/cmd/data-crawler.go @@ -462,7 +462,7 @@ func (f *folderScanner) scanQueuedLevels(ctx context.Context, folders []cachedFo continue } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { continue } diff --git a/cmd/gateway-main.go b/cmd/gateway-main.go index b116e3694..9c911e804 100644 --- a/cmd/gateway-main.go +++ b/cmd/gateway-main.go @@ -300,7 +300,6 @@ func StartGateway(ctx *cli.Context, gw Gateway) { // Once endpoints are finalized, initialize the new object api in safe mode. globalObjLayerMutex.Lock() - globalSafeMode = true globalObjectAPI = newObject globalObjLayerMutex.Unlock() @@ -325,7 +324,7 @@ func StartGateway(ctx *cli.Context, gw Gateway) { if enableIAMOps { // Initialize IAM sys. - startBackgroundIAMLoad(GlobalContext) + startBackgroundIAMLoad(GlobalContext, newObject) } if globalCacheConfig.Enabled { @@ -353,11 +352,6 @@ func StartGateway(ctx *cli.Context, gw Gateway) { // - compression verifyObjectLayerFeatures("gateway "+gatewayName, newObject) - // 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. if !globalCLIContext.Quiet { mode := globalMinioModeGatewayPrefix + gatewayName diff --git a/cmd/globals.go b/cmd/globals.go index a439f8eb4..cedd01ff8 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -268,11 +268,6 @@ var ( globalBackgroundHealRoutine *healRoutine globalBackgroundHealState *allHealState - // Only enabled when one of the sub-systems fail - // to initialize, this allows for administrators to - // fix the system. - globalSafeMode bool - // If writes to FS backend should be O_SYNC. globalFSOSync bool diff --git a/cmd/iam.go b/cmd/iam.go index e16e2b8fe..38c26e5b6 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -411,8 +411,8 @@ func (sys *IAMSys) doIAMConfigMigration(ctx context.Context) error { // Loads IAM users and policies in background, any un-handled // error means this code can potentially crash the server // in such a situation manual intervention is necessary. -func startBackgroundIAMLoad(ctx context.Context) { - go globalIAMSys.Init(ctx, newObjectLayerWithoutSafeModeFn()) +func startBackgroundIAMLoad(ctx context.Context, objAPI ObjectLayer) { + go globalIAMSys.Init(ctx, objAPI) } // Init - initializes config system by reading entries from config/iam @@ -514,7 +514,7 @@ func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer) { // DeletePolicy - deletes a canned policy from backend or etcd. func (sys *IAMSys) DeletePolicy(policyName string) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -567,7 +567,7 @@ func (sys *IAMSys) DeletePolicy(policyName string) error { // InfoPolicy - expands the canned policy into its JSON structure. func (sys *IAMSys) InfoPolicy(policyName string) (iampolicy.Policy, error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return iampolicy.Policy{}, errServerNotInitialized } @@ -585,7 +585,7 @@ func (sys *IAMSys) InfoPolicy(policyName string) (iampolicy.Policy, error) { // ListPolicies - lists all canned policies. func (sys *IAMSys) ListPolicies() (map[string]iampolicy.Policy, error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return nil, errServerNotInitialized } @@ -607,7 +607,7 @@ func (sys *IAMSys) ListPolicies() (map[string]iampolicy.Policy, error) { // SetPolicy - sets a new name policy. func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -629,7 +629,7 @@ func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error { // DeleteUser - delete user (only for long-term users not STS users). func (sys *IAMSys) DeleteUser(accessKey string) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -699,7 +699,7 @@ func (sys *IAMSys) currentPolicies(policyName string) string { // SetTempUser - set temporary user credentials, these credentials have an expiry. func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyName string) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -749,7 +749,7 @@ func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyNa // ListUsers - list all users. func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return nil, errServerNotInitialized } @@ -786,7 +786,7 @@ func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) { // IsTempUser - returns if given key is a temporary user. func (sys *IAMSys) IsTempUser(name string) (bool, error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return false, errServerNotInitialized } @@ -804,7 +804,7 @@ func (sys *IAMSys) IsTempUser(name string) (bool, error) { // IsServiceAccount - returns if given key is a service account func (sys *IAMSys) IsServiceAccount(name string) (bool, string, error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return false, "", errServerNotInitialized } @@ -826,7 +826,7 @@ func (sys *IAMSys) IsServiceAccount(name string) (bool, string, error) { // GetUserInfo - get info on a user. func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return u, errServerNotInitialized } @@ -872,7 +872,7 @@ func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) { // SetUserStatus - sets current user status, supports disabled or enabled. func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -918,7 +918,7 @@ func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) // NewServiceAccount - create a new service account func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, sessionPolicy *iampolicy.Policy) (auth.Credentials, error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return auth.Credentials{}, errServerNotInitialized } @@ -985,7 +985,7 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, ses // ListServiceAccounts - lists all services accounts associated to a specific user func (sys *IAMSys) ListServiceAccounts(ctx context.Context, accessKey string) ([]string, error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return nil, errServerNotInitialized } @@ -1010,7 +1010,7 @@ func (sys *IAMSys) ListServiceAccounts(ctx context.Context, accessKey string) ([ // GetServiceAccountParent - gets information about a service account func (sys *IAMSys) GetServiceAccountParent(ctx context.Context, accessKey string) (string, error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return "", errServerNotInitialized } @@ -1027,7 +1027,7 @@ func (sys *IAMSys) GetServiceAccountParent(ctx context.Context, accessKey string // DeleteServiceAccount - delete a service account func (sys *IAMSys) DeleteServiceAccount(ctx context.Context, accessKey string) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -1056,7 +1056,7 @@ func (sys *IAMSys) DeleteServiceAccount(ctx context.Context, accessKey string) e // SetUser - set user credentials and policy. func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -1094,7 +1094,7 @@ func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error { // SetUserSecretKey - sets user secret key func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -1123,7 +1123,7 @@ func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error { // GetUser - get user credentials func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return cred, false } @@ -1187,7 +1187,7 @@ func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) { // AddUsersToGroup - adds users to a group, creating the group if // needed. No error if user(s) already are in the group. func (sys *IAMSys) AddUsersToGroup(group string, members []string) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -1248,7 +1248,7 @@ func (sys *IAMSys) AddUsersToGroup(group string, members []string) error { // RemoveUsersFromGroup - remove users from group. If no users are // given, and the group is empty, deletes the group as well. func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -1329,7 +1329,7 @@ func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error { // SetGroupStatus - enable/disabled a group func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -1365,7 +1365,7 @@ func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error { // GetGroupDescription - builds up group description func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return gd, errServerNotInitialized } @@ -1406,7 +1406,7 @@ func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err e // ListGroups - lists groups. func (sys *IAMSys) ListGroups() (r []string, err error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return r, errServerNotInitialized } @@ -1430,7 +1430,7 @@ func (sys *IAMSys) ListGroups() (r []string, err error) { // PolicyDBSet - sets a policy for a user or group in the PolicyDB. func (sys *IAMSys) PolicyDBSet(name, policy string, isGroup bool) error { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return errServerNotInitialized } @@ -1497,7 +1497,7 @@ func (sys *IAMSys) policyDBSet(name, policyName string, userType IAMUserType, is // be a member of multiple groups, this function returns an array of // applicable policies (each group is mapped to at most one policy). func (sys *IAMSys) PolicyDBGet(name string, isGroup bool) ([]string, error) { - objectAPI := newObjectLayerWithoutSafeModeFn() + objectAPI := newObjectLayerFn() if objectAPI == nil || sys == nil || sys.store == nil { return nil, errServerNotInitialized } diff --git a/cmd/lock-rest-server.go b/cmd/lock-rest-server.go index 68b6a9203..d130af540 100644 --- a/cmd/lock-rest-server.go +++ b/cmd/lock-rest-server.go @@ -35,7 +35,7 @@ const ( lockMaintenanceInterval = 30 * time.Second // Lock validity check interval. - lockValidityCheckInterval = 2 * time.Minute + lockValidityCheckInterval = 30 * time.Second ) // To abstract a node over network. @@ -242,7 +242,7 @@ func getLongLivedLocks(interval time.Duration) map[Endpoint][]nameLockRequesterI // // We will ignore the error, and we will retry later to get a resolve on this lock func lockMaintenance(ctx context.Context, interval time.Duration) error { - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return nil } @@ -332,7 +332,7 @@ func startLockMaintenance(ctx context.Context) { // no need to start the lock maintenance // if ObjectAPI is not initialized. for { - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { time.Sleep(time.Second) continue diff --git a/cmd/metrics.go b/cmd/metrics.go index 46e08611a..a5e0682ae 100644 --- a/cmd/metrics.go +++ b/cmd/metrics.go @@ -161,7 +161,7 @@ func gatewayMetricsPrometheus(ch chan<- prometheus.Metric) { return } - objLayer := newObjectLayerWithoutSafeModeFn() + objLayer := newObjectLayerFn() // Service not initialized yet if objLayer == nil { return @@ -372,7 +372,7 @@ func networkMetricsPrometheus(ch chan<- prometheus.Metric) { // Populates prometheus with bucket usage metrics, this metrics // is only enabled if crawler is enabled. func bucketUsageMetricsPrometheus(ch chan<- prometheus.Metric) { - objLayer := newObjectLayerWithoutSafeModeFn() + objLayer := newObjectLayerFn() // Service not initialized yet if objLayer == nil { return @@ -435,7 +435,7 @@ func bucketUsageMetricsPrometheus(ch chan<- prometheus.Metric) { // collects storage metrics for MinIO server in Prometheus specific format // and sends to given channel func storageMetricsPrometheus(ch chan<- prometheus.Metric) { - objLayer := newObjectLayerWithoutSafeModeFn() + objLayer := newObjectLayerFn() // Service not initialized yet if objLayer == nil { return diff --git a/cmd/notification.go b/cmd/notification.go index 8aaea5669..f5cfe44d9 100644 --- a/cmd/notification.go +++ b/cmd/notification.go @@ -613,18 +613,12 @@ func (sys *NotificationSys) Init(ctx context.Context, buckets []BucketInfo, objA return errServerNotInitialized } - // In gateway mode, notifications are not supported. + // In gateway mode, notifications are not supported - except NAS gateway. if globalIsGateway && !objAPI.IsNotificationSupported() { return nil } - if globalConfigTargetList != nil { - for _, target := range globalConfigTargetList.Targets() { - if err := sys.targetList.Add(target); err != nil { - return err - } - } - } + logger.LogIf(ctx, sys.targetList.Add(globalConfigTargetList.Targets()...)) go func() { for res := range sys.targetResCh { diff --git a/cmd/peer-rest-server.go b/cmd/peer-rest-server.go index 6193d4957..e4bca01a8 100644 --- a/cmd/peer-rest-server.go +++ b/cmd/peer-rest-server.go @@ -64,7 +64,7 @@ func (s *peerRESTServer) DeletePolicyHandler(w http.ResponseWriter, r *http.Requ return } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { s.writeErrorResponse(w, errServerNotInitialized) return @@ -97,7 +97,7 @@ func (s *peerRESTServer) LoadPolicyHandler(w http.ResponseWriter, r *http.Reques return } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { s.writeErrorResponse(w, errServerNotInitialized) return @@ -130,7 +130,7 @@ func (s *peerRESTServer) LoadPolicyMappingHandler(w http.ResponseWriter, r *http return } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { s.writeErrorResponse(w, errServerNotInitialized) return @@ -164,7 +164,7 @@ func (s *peerRESTServer) DeleteServiceAccountHandler(w http.ResponseWriter, r *h return } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { s.writeErrorResponse(w, errServerNotInitialized) return @@ -197,7 +197,7 @@ func (s *peerRESTServer) LoadServiceAccountHandler(w http.ResponseWriter, r *htt return } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { s.writeErrorResponse(w, errServerNotInitialized) return @@ -230,7 +230,7 @@ func (s *peerRESTServer) DeleteUserHandler(w http.ResponseWriter, r *http.Reques return } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { s.writeErrorResponse(w, errServerNotInitialized) return @@ -263,7 +263,7 @@ func (s *peerRESTServer) LoadUserHandler(w http.ResponseWriter, r *http.Request) return } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { s.writeErrorResponse(w, errServerNotInitialized) return @@ -307,7 +307,7 @@ func (s *peerRESTServer) LoadGroupHandler(w http.ResponseWriter, r *http.Request return } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { s.writeErrorResponse(w, errServerNotInitialized) return @@ -609,7 +609,7 @@ func (s *peerRESTServer) LoadBucketMetadataHandler(w http.ResponseWriter, r *htt return } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { s.writeErrorResponse(w, errServerNotInitialized) return @@ -657,7 +657,7 @@ func (s *peerRESTServer) ReloadFormatHandler(w http.ResponseWriter, r *http.Requ return } - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { s.writeErrorResponse(w, errServerNotInitialized) return @@ -767,7 +767,7 @@ func (s *peerRESTServer) GetLocalDiskIDs(w http.ResponseWriter, r *http.Request) ctx := newContext(r, w, "GetLocalDiskIDs") - objLayer := newObjectLayerWithoutSafeModeFn() + objLayer := newObjectLayerFn() // Service not initialized yet if objLayer == nil { diff --git a/cmd/server-main.go b/cmd/server-main.go index ca03716bf..797bf96dd 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -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) + // Prints the formatted startup message, if err is not nil then it prints additional information as well. + printStartupMessage(getAPIEndpoints(), err) - <-globalOSSignalCh + 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)) } - }(txnLk) + + <-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) - - 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)) - } + go startBackgroundIAMLoad(GlobalContext, newObject) - <-globalOSSignalCh + initServer(GlobalContext, newObject) } // Initialize object layer with the supplied disks, objectLayer is nil upon any error. diff --git a/cmd/server-startup-msg.go b/cmd/server-startup-msg.go index fe8ed50c8..3f0adb9de 100644 --- a/cmd/server-startup-msg.go +++ b/cmd/server-startup-msg.go @@ -32,13 +32,12 @@ import ( // Documentation links, these are part of message printing code. const ( - mcQuickStartGuide = "https://docs.min.io/docs/minio-client-quickstart-guide" - mcAdminQuickStartGuide = "https://docs.min.io/docs/minio-admin-complete-guide.html" - goQuickStartGuide = "https://docs.min.io/docs/golang-client-quickstart-guide" - jsQuickStartGuide = "https://docs.min.io/docs/javascript-client-quickstart-guide" - javaQuickStartGuide = "https://docs.min.io/docs/java-client-quickstart-guide" - pyQuickStartGuide = "https://docs.min.io/docs/python-client-quickstart-guide" - dotnetQuickStartGuide = "https://docs.min.io/docs/dotnet-client-quickstart-guide" + mcQuickStartGuide = "https://docs.min.io/docs/minio-client-quickstart-guide" + goQuickStartGuide = "https://docs.min.io/docs/golang-client-quickstart-guide" + jsQuickStartGuide = "https://docs.min.io/docs/javascript-client-quickstart-guide" + javaQuickStartGuide = "https://docs.min.io/docs/java-client-quickstart-guide" + pyQuickStartGuide = "https://docs.min.io/docs/python-client-quickstart-guide" + dotnetQuickStartGuide = "https://docs.min.io/docs/dotnet-client-quickstart-guide" ) // generates format string depending on the string length and padding. @@ -52,65 +51,13 @@ func mustGetStorageInfo(objAPI ObjectLayer) StorageInfo { return storageInfo } -func printStartupSafeModeMessage(apiEndpoints []string, err error) { - logStartupMessage(color.RedBold("Server startup failed with '%v'", err)) - logStartupMessage(color.RedBold("Server switching to safe mode")) - logStartupMessage(color.RedBold("Please use 'mc admin config' commands fix this issue")) - - // Object layer is initialized then print StorageInfo in safe mode. - objAPI := newObjectLayerWithoutSafeModeFn() - if objAPI != nil { - if msg := getStorageInfoMsgSafeMode(mustGetStorageInfo(objAPI)); msg != "" { - logStartupMessage(msg) - } - } - - // Get saved credentials. - cred := globalActiveCred - - // Get saved region. - region := globalServerRegion - - strippedAPIEndpoints := stripStandardPorts(apiEndpoints) - - apiEndpointStr := strings.Join(strippedAPIEndpoints, " ") - - // Colorize the message and print. - logStartupMessage(color.Red("Endpoint: ") + color.Bold(fmt.Sprintf(getFormatStr(len(apiEndpointStr), 1), apiEndpointStr))) - if color.IsTerminal() && !globalCLIContext.Anonymous { - logStartupMessage(color.Red("AccessKey: ") + color.Bold(fmt.Sprintf("%s ", cred.AccessKey))) - logStartupMessage(color.Red("SecretKey: ") + color.Bold(fmt.Sprintf("%s ", cred.SecretKey))) - if region != "" { - logStartupMessage(color.Red("Region: ") + color.Bold(fmt.Sprintf(getFormatStr(len(region), 3), region))) - } - } - - // Prints `mc` cli configuration message chooses - // first endpoint as default. - alias := "myminio" - endPoint := strippedAPIEndpoints[0] - - // Configure 'mc', following block prints platform specific information for minio client admin commands. - if color.IsTerminal() && !globalCLIContext.Anonymous { - logStartupMessage(color.RedBold("\nCommand-line Access: ") + mcAdminQuickStartGuide) - if runtime.GOOS == globalWindowsOSName { - mcMessage := fmt.Sprintf("> mc.exe alias set %s %s %s %s --api s3v4", alias, - endPoint, cred.AccessKey, cred.SecretKey) - logStartupMessage(fmt.Sprintf(getFormatStr(len(mcMessage), 3), mcMessage)) - mcMessage = "> mc.exe admin config --help" - logStartupMessage(fmt.Sprintf(getFormatStr(len(mcMessage), 3), mcMessage)) - } else { - mcMessage := fmt.Sprintf("$ mc alias set %s %s %s %s --api s3v4", alias, - endPoint, cred.AccessKey, cred.SecretKey) - logStartupMessage(fmt.Sprintf(getFormatStr(len(mcMessage), 3), mcMessage)) - mcMessage = "$ mc admin config --help" - logStartupMessage(fmt.Sprintf(getFormatStr(len(mcMessage), 3), mcMessage)) - } - } -} - // Prints the formatted startup message. -func printStartupMessage(apiEndpoints []string) { +func printStartupMessage(apiEndpoints []string, err error) { + if err != nil { + logStartupMessage(color.RedBold("Server startup failed with '%v'", err)) + logStartupMessage(color.RedBold("Not all features may be available on this server")) + logStartupMessage(color.RedBold("Please use 'mc admin' commands to further investigate this issue")) + } strippedAPIEndpoints := stripStandardPorts(apiEndpoints) // If cache layer is enabled, print cache capacity. @@ -254,23 +201,6 @@ func printObjectAPIMsg() { logStartupMessage(color.Blue(" .NET: ") + fmt.Sprintf(getFormatStr(len(dotnetQuickStartGuide), 6), dotnetQuickStartGuide)) } -// Get formatted disk/storage info message. -func getStorageInfoMsgSafeMode(storageInfo StorageInfo) string { - var msg string - var mcMessage string - if storageInfo.Backend.Type == BackendErasure { - if storageInfo.Backend.OfflineDisks.Sum() > 0 { - mcMessage = "Use `mc admin info` to look for latest server/disk info\n" - } - diskInfo := fmt.Sprintf(" %d Online, %d Offline. ", storageInfo.Backend.OnlineDisks.Sum(), storageInfo.Backend.OfflineDisks.Sum()) - msg += color.Red("Status:") + fmt.Sprintf(getFormatStr(len(diskInfo), 8), diskInfo) - } - if len(mcMessage) > 0 { - msg = fmt.Sprintf("%s %s", mcMessage, msg) - } - return msg -} - // Get formatted disk/storage info message. func getStorageInfoMsg(storageInfo StorageInfo) string { var msg string diff --git a/cmd/server-startup-msg_test.go b/cmd/server-startup-msg_test.go index d0eb14f62..e085b39cc 100644 --- a/cmd/server-startup-msg_test.go +++ b/cmd/server-startup-msg_test.go @@ -102,5 +102,5 @@ func TestPrintStartupMessage(t *testing.T) { } apiEndpoints := []string{"http://127.0.0.1:9000"} - printStartupMessage(apiEndpoints) + printStartupMessage(apiEndpoints, nil) } diff --git a/cmd/signals.go b/cmd/signals.go index fb8ff8549..00182c903 100644 --- a/cmd/signals.go +++ b/cmd/signals.go @@ -60,7 +60,7 @@ func handleSignals() { } } - if objAPI := newObjectLayerWithoutSafeModeFn(); objAPI != nil { + if objAPI := newObjectLayerFn(); objAPI != nil { oerr = objAPI.Shutdown(context.Background()) logger.LogIf(context.Background(), oerr) } diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index bc70f9f8f..6f706c3a9 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -2077,16 +2077,10 @@ func registerAPIFunctions(muxRouter *mux.Router, objLayer ObjectLayer, apiFuncti // operation api := objectAPIHandlers{ ObjectAPI: func() ObjectLayer { - if !globalSafeMode { - return globalObjectAPI - } - return nil + return globalObjectAPI }, CacheAPI: func() CacheObjectLayer { - if !globalSafeMode { - return globalCacheObjectAPI - } - return nil + return globalCacheObjectAPI }, } diff --git a/cmd/xl-storage.go b/cmd/xl-storage.go index b4652074b..57fb4af83 100644 --- a/cmd/xl-storage.go +++ b/cmd/xl-storage.go @@ -366,7 +366,7 @@ func (s *xlStorage) CrawlAndGetDataUsage(ctx context.Context, cache dataUsageCac } // Get object api - objAPI := newObjectLayerWithoutSafeModeFn() + objAPI := newObjectLayerFn() if objAPI == nil { return cache, errServerNotInitialized } diff --git a/pkg/event/targetlist.go b/pkg/event/targetlist.go index 4b97e4729..214c2ac5c 100644 --- a/pkg/event/targetlist.go +++ b/pkg/event/targetlist.go @@ -86,6 +86,10 @@ func (list *TargetList) Remove(targetIDSet TargetIDSet) { // Targets - list all targets func (list *TargetList) Targets() []Target { + if list == nil { + return []Target{} + } + list.RLock() defer list.RUnlock()