diff --git a/cmd/bucket-replication-stats.go b/cmd/bucket-replication-stats.go index 51ceaf5b4..f495df8fb 100644 --- a/cmd/bucket-replication-stats.go +++ b/cmd/bucket-replication-stats.go @@ -246,6 +246,9 @@ outer: } func (r *ReplicationStats) getAllCachedLatest() BucketStatsMap { + if r == nil { + return BucketStatsMap{} + } r.dlock.RLock() defer r.dlock.RUnlock() return r.mostRecentStats diff --git a/cmd/config-current.go b/cmd/config-current.go index 00b3354c9..06e59ba8a 100644 --- a/cmd/config-current.go +++ b/cmd/config-current.go @@ -69,7 +69,6 @@ func initHelp() { config.LoggerWebhookSubSys: logger.DefaultLoggerWebhookKVS, config.AuditWebhookSubSys: logger.DefaultAuditWebhookKVS, config.AuditKafkaSubSys: logger.DefaultAuditKafkaKVS, - config.HealSubSys: heal.DefaultKVS, config.ScannerSubSys: scanner.DefaultKVS, config.SubnetSubSys: subnet.DefaultKVS, config.CallhomeSubSys: callhome.DefaultKVS, @@ -79,6 +78,7 @@ func initHelp() { } if globalIsErasure { kvs[config.StorageClassSubSys] = storageclass.DefaultKVS + kvs[config.HealSubSys] = heal.DefaultKVS } config.RegisterDefaultKVS(kvs) @@ -125,10 +125,6 @@ func initHelp() { Key: config.APISubSys, Description: "manage global HTTP API call specific features, such as throttling, authentication types, etc.", }, - config.HelpKV{ - Key: config.HealSubSys, - Description: "manage object healing frequency and bitrot verification checks", - }, config.HelpKV{ Key: config.ScannerSubSys, Description: "manage namespace scanning for usage calculation, lifecycle, healing and more", @@ -213,12 +209,13 @@ func initHelp() { } if globalIsErasure { - helpSubSys = append(helpSubSys, config.HelpKV{}) - copy(helpSubSys[2:], helpSubSys[1:]) - helpSubSys[1] = config.HelpKV{ + helpSubSys = append(helpSubSys, config.HelpKV{ Key: config.StorageClassSubSys, Description: "define object level redundancy", - } + }, config.HelpKV{ + Key: config.HealSubSys, + Description: "manage object healing frequency and bitrot verification checks", + }) } helpMap := map[string]config.HelpKVS{ @@ -289,14 +286,12 @@ func validateSubSysConfig(s config.Config, subSys string, objAPI ObjectLayer) er return err } case config.StorageClassSubSys: - if globalIsErasure { - if objAPI == nil { - return errServerNotInitialized - } - for _, setDriveCount := range objAPI.SetDriveCounts() { - if _, err := storageclass.LookupConfig(s[config.StorageClassSubSys][config.Default], setDriveCount); err != nil { - return err - } + if objAPI == nil { + return errServerNotInitialized + } + for _, setDriveCount := range objAPI.SetDriveCounts() { + if _, err := storageclass.LookupConfig(s[config.StorageClassSubSys][config.Default], setDriveCount); err != nil { + return err } } case config.CacheSubSys: @@ -573,16 +568,18 @@ func lookupConfigs(s config.Config, objAPI ObjectLayer) { } func applyDynamicConfigForSubSys(ctx context.Context, objAPI ObjectLayer, s config.Config, subSys string) error { + if objAPI == nil { + return errServerNotInitialized + } + + setDriveCounts := objAPI.SetDriveCounts() switch subSys { case config.APISubSys: apiConfig, err := api.LookupConfig(s[config.APISubSys][config.Default]) if err != nil { logger.LogIf(ctx, fmt.Errorf("Invalid api configuration: %w", err)) } - var setDriveCounts []int - if objAPI != nil { - setDriveCounts = objAPI.SetDriveCounts() - } + globalAPIConfig.init(apiConfig, setDriveCounts) // Initialize remote instance transport once. @@ -595,10 +592,8 @@ func applyDynamicConfigForSubSys(ctx context.Context, objAPI ObjectLayer, s conf return fmt.Errorf("Unable to setup Compression: %w", err) } // Validate if the object layer supports compression. - if objAPI != nil { - if cmpCfg.Enabled && !objAPI.IsCompressionSupported() { - return fmt.Errorf("Backend does not support compression") - } + if cmpCfg.Enabled && !objAPI.IsCompressionSupported() { + return fmt.Errorf("Backend does not support compression") } globalCompressConfigMu.Lock() globalCompressConfig = cmpCfg @@ -667,19 +662,16 @@ func applyDynamicConfigForSubSys(ctx context.Context, objAPI ObjectLayer, s conf logger.LogIf(ctx, fmt.Errorf("Unable to update audit kafka targets: %w", err)) } case config.StorageClassSubSys: - if globalIsErasure && objAPI != nil { - setDriveCounts := objAPI.SetDriveCounts() - for i, setDriveCount := range setDriveCounts { - sc, err := storageclass.LookupConfig(s[config.StorageClassSubSys][config.Default], setDriveCount) - if err != nil { - logger.LogIf(ctx, fmt.Errorf("Unable to initialize storage class config: %w", err)) - break - } - // if we validated all setDriveCounts and it was successful - // proceed to store the correct storage class globally. - if i == len(setDriveCounts)-1 { - globalStorageClass.Update(sc) - } + for i, setDriveCount := range setDriveCounts { + sc, err := storageclass.LookupConfig(s[config.StorageClassSubSys][config.Default], setDriveCount) + if err != nil { + logger.LogIf(ctx, fmt.Errorf("Unable to initialize storage class config: %w", err)) + break + } + // if we validated all setDriveCounts and it was successful + // proceed to store the correct storage class globally. + if i == len(setDriveCounts)-1 { + globalStorageClass.Update(sc) } } case config.CallhomeSubSys: diff --git a/cmd/erasure-healing_test.go b/cmd/erasure-healing_test.go index 2a01a177a..82387cbaf 100644 --- a/cmd/erasure-healing_test.go +++ b/cmd/erasure-healing_test.go @@ -230,6 +230,13 @@ func TestHealing(t *testing.T) { t.Fatal(err) } defer obj.Shutdown(context.Background()) + + // initialize the server and obtain the credentials and root. + // credentials are necessary to sign the HTTP request. + if err = newTestConfig(globalMinioDefaultRegion, obj); err != nil { + t.Fatalf("Unable to initialize server config. %s", err) + } + defer removeRoots(fsDirs) z := obj.(*erasureServerPools) diff --git a/cmd/gateway-main.go b/cmd/gateway-main.go index 5f62d058e..0bbdb18a5 100644 --- a/cmd/gateway-main.go +++ b/cmd/gateway-main.go @@ -220,17 +220,6 @@ func StartGateway(ctx *cli.Context, gw Gateway) { // Set when gateway is enabled globalIsGateway = true - // Initialize server config. - srvCfg := newServerConfig() - - // Override any values from ENVs. - lookupConfigs(srvCfg, nil) - - // hold the mutex lock before a new config is assigned. - globalServerConfigMu.Lock() - globalServerConfig = srvCfg - globalServerConfigMu.Unlock() - // Initialize router. `SkipClean(true)` stops gorilla/mux from // normalizing URL path minio/minio#3256 // avoid URL path encoding minio/minio#8950 @@ -252,11 +241,6 @@ func StartGateway(ctx *cli.Context, gw Gateway) { // Add API router. registerAPIRouter(router) - // Enable bucket forwarding handler only if bucket federation is enabled. - if globalDNSConfig != nil && globalBucketFederation { - globalHandlers = append(globalHandlers, setBucketForwardingHandler) - } - // Use all the middlewares router.Use(globalHandlers...) @@ -307,6 +291,17 @@ func StartGateway(ctx *cli.Context, gw Gateway) { globalObjectAPI = newObject globalObjLayerMutex.Unlock() + // Initialize server config. + srvCfg := newServerConfig() + + // Override any values from ENVs. + lookupConfigs(srvCfg, newObject) + + // hold the mutex lock before a new config is assigned. + globalServerConfigMu.Lock() + globalServerConfig = srvCfg + globalServerConfigMu.Unlock() + go globalIAMSys.Init(GlobalContext, newObject, globalEtcdClient, globalRefreshIAMInterval) if gatewayName == NASBackendGateway { diff --git a/cmd/signals.go b/cmd/signals.go index 14beb900c..d8db1e436 100644 --- a/cmd/signals.go +++ b/cmd/signals.go @@ -78,11 +78,15 @@ func handleSignals() { case <-globalHTTPServerErrorCh: exit(stopProcess()) case osSignal := <-globalOSSignalCh: - globalReplicationPool.SaveState(context.Background()) + if !globalIsGateway { + globalReplicationPool.SaveState(context.Background()) + } logger.Info("Exiting on signal: %s", strings.ToUpper(osSignal.String())) exit(stopProcess()) case signal := <-globalServiceSignalCh: - globalReplicationPool.SaveState(context.Background()) + if !globalIsGateway { + globalReplicationPool.SaveState(context.Background()) + } switch signal { case serviceRestart: logger.Info("Restarting on service signal") diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index 329da75c1..dccffaba2 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -215,6 +215,7 @@ func prepareErasure(ctx context.Context, nDisks int) (ObjectLayer, []string, err removeRoots(fsDirs) return nil, nil, err } + return obj, fsDirs, nil } @@ -502,6 +503,8 @@ func newTestConfig(bucketLocation string, obj ObjectLayer) (err error) { // Set a default region. config.SetRegion(globalServerConfig, bucketLocation) + applyDynamicConfigForSubSys(context.Background(), obj, globalServerConfig, config.StorageClassSubSys) + // Save config. return saveServerConfig(context.Background(), obj, globalServerConfig) } @@ -1742,6 +1745,10 @@ func ExecObjectLayerAPITest(t *testing.T, objAPITest objAPITestType, endpoints [ // Executing the object layer tests for single node setup. objAPITest(objLayer, ErasureSDStr, bucketFS, fsAPIRouter, credentials, t) + // reset globals. + // this is to make sure that the tests are not affected by modified value. + resetTestGlobals() + objLayer, erasureDisks, err := prepareErasure16(ctx) if err != nil { t.Fatalf("Initialization of object layer failed for Erasure setup: %s", err) @@ -1752,6 +1759,13 @@ func ExecObjectLayerAPITest(t *testing.T, objAPITest objAPITestType, endpoints [ if err != nil { t.Fatalf("Initialzation of API handler tests failed: %s", err) } + + // initialize the server and obtain the credentials and root. + // credentials are necessary to sign the HTTP request. + if err = newTestConfig(globalMinioDefaultRegion, objLayer); err != nil { + t.Fatalf("Unable to initialize server config. %s", err) + } + // Executing the object layer tests for Erasure. objAPITest(objLayer, ErasureTestStr, bucketErasure, erAPIRouter, credentials, t) diff --git a/internal/config/storageclass/storage-class.go b/internal/config/storageclass/storage-class.go index 7ada9c923..b833f7754 100644 --- a/internal/config/storageclass/storage-class.go +++ b/internal/config/storageclass/storage-class.go @@ -193,12 +193,14 @@ func validateParity(ssParity, rrsParity, setDriveCount int) (err error) { return fmt.Errorf("Reduced redundancy storage class parity %d should be greater than or equal to %d", rrsParity, minParityDisks) } - if ssParity > setDriveCount/2 { - return fmt.Errorf("Standard storage class parity %d should be less than or equal to %d", ssParity, setDriveCount/2) - } + if setDriveCount > 2 { + if ssParity > setDriveCount/2 { + return fmt.Errorf("Standard storage class parity %d should be less than or equal to %d", ssParity, setDriveCount/2) + } - if rrsParity > setDriveCount/2 { - return fmt.Errorf("Reduced redundancy storage class parity %d should be less than or equal to %d", rrsParity, setDriveCount/2) + if rrsParity > setDriveCount/2 { + return fmt.Errorf("Reduced redundancy storage class parity %d should be less than or equal to %d", rrsParity, setDriveCount/2) + } } if ssParity > 0 && rrsParity > 0 { @@ -283,6 +285,8 @@ func LookupConfig(kvs config.KVS, setDriveCount int) (cfg Config, err error) { if err != nil { return Config{}, err } + } else { + cfg.Standard.Parity = DefaultParityBlocks(setDriveCount) } if rrsc != "" { @@ -290,14 +294,11 @@ func LookupConfig(kvs config.KVS, setDriveCount int) (cfg Config, err error) { if err != nil { return Config{}, err } - } - - if cfg.RRS.Parity == 0 && rrsc == "" { + } else { cfg.RRS.Parity = defaultRRSParity - } - - if cfg.Standard.Parity == 0 && ssc == "" { - cfg.Standard.Parity = DefaultParityBlocks(setDriveCount) + if setDriveCount == 1 { + cfg.RRS.Parity = 0 + } } // Validation is done after parsing both the storage classes. This is needed because we need one