forked from minio/minio
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrate config.json from config-dir to backend
This PR is a first set of changes to move the config to the backend, the changes uses the existing `config.json` allows it to be migrated such that we can save it in on backend disks. In future releases we will slowly migrate out of the current architecture. Fixes minio#6182
- Loading branch information
1 parent
157ed65
commit a971361
Showing
12 changed files
with
360 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,281 @@ | ||
/* | ||
* Minio Cloud Storage, (C) 2018 Minio, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"errors" | ||
"io/ioutil" | ||
"path" | ||
|
||
"github.com/minio/minio/cmd/logger" | ||
"github.com/minio/minio/pkg/hash" | ||
"github.com/minio/minio/pkg/quick" | ||
) | ||
|
||
const ( | ||
minioConfigPrefix = "config" | ||
|
||
// Minio configuration file. | ||
minioConfigFile = "config.json" | ||
) | ||
|
||
func saveServerConfig(objAPI ObjectLayer, config *serverConfig) error { | ||
if err := quick.CheckData(config); err != nil { | ||
return err | ||
} | ||
|
||
data, err := json.Marshal(config) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
configFile := path.Join(minioConfigPrefix, minioConfigFile) | ||
return saveConfig(objAPI, configFile, data) | ||
} | ||
|
||
func readServerConfig(ctx context.Context, objAPI ObjectLayer) (*serverConfig, error) { | ||
configFile := path.Join(minioConfigPrefix, minioConfigFile) | ||
reader, err := readConfig(ctx, objAPI, configFile) | ||
if err != nil { | ||
return nil, err | ||
} | ||
var config = &serverConfig{} | ||
d := json.NewDecoder(reader) | ||
if err = d.Decode(config); err != nil { | ||
return nil, err | ||
} | ||
if err = quick.CheckData(config); err != nil { | ||
return nil, err | ||
} | ||
return config, nil | ||
} | ||
|
||
func checkServerConfig(ctx context.Context, objAPI ObjectLayer) error { | ||
configFile := path.Join(minioConfigPrefix, minioConfigFile) | ||
if _, err := objAPI.GetObjectInfo(ctx, minioMetaBucket, configFile); err != nil { | ||
if isErrObjectNotFound(err) { | ||
return errConfigNotFound | ||
} | ||
logger.GetReqInfo(ctx).AppendTags("configFile", configFile) | ||
logger.LogIf(ctx, err) | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func saveConfig(objAPI ObjectLayer, configFile string, data []byte) error { | ||
hashReader, err := hash.NewReader(bytes.NewReader(data), int64(len(data)), "", getSHA256Hash(data)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = objAPI.PutObject(context.Background(), minioMetaBucket, configFile, hashReader, nil) | ||
return err | ||
} | ||
|
||
var errConfigNotFound = errors.New("config file not found") | ||
|
||
func readConfig(ctx context.Context, objAPI ObjectLayer, configFile string) (*bytes.Buffer, error) { | ||
var buffer bytes.Buffer | ||
// Read entire content by setting size to -1 | ||
if err := objAPI.GetObject(ctx, minioMetaBucket, configFile, 0, -1, &buffer, ""); err != nil { | ||
// Ignore if err is ObjectNotFound or IncompleteBody when bucket is not configured with notification | ||
if isErrObjectNotFound(err) || isErrIncompleteBody(err) { | ||
return nil, errConfigNotFound | ||
} | ||
|
||
logger.GetReqInfo(ctx).AppendTags("configFile", configFile) | ||
logger.LogIf(ctx, err) | ||
return nil, err | ||
} | ||
|
||
// Return config not found on empty content. | ||
if buffer.Len() == 0 { | ||
return nil, errConfigNotFound | ||
} | ||
|
||
return &buffer, nil | ||
} | ||
|
||
// ConfigSys - config system. | ||
type ConfigSys struct{} | ||
|
||
// Load - load config.json. | ||
func (sys *ConfigSys) Load(objAPI ObjectLayer) error { | ||
if objAPI == nil { | ||
return errInvalidArgument | ||
} | ||
srvCfg, err := readServerConfig(context.Background(), objAPI) | ||
if err != nil { | ||
return err | ||
} | ||
if err = srvCfg.Validate(); err != nil { | ||
return err | ||
} | ||
|
||
// If env is set override the credentials from config file. | ||
if globalIsEnvCreds { | ||
srvCfg.SetCredential(globalActiveCred) | ||
} | ||
|
||
if globalIsEnvBrowser { | ||
srvCfg.SetBrowser(globalIsBrowserEnabled) | ||
} | ||
|
||
if globalIsEnvRegion { | ||
srvCfg.SetRegion(globalServerRegion) | ||
} | ||
|
||
if globalIsEnvDomainName { | ||
srvCfg.Domain = globalDomainName | ||
} | ||
|
||
if globalIsStorageClass { | ||
srvCfg.SetStorageClass(globalStandardStorageClass, globalRRStorageClass) | ||
} | ||
|
||
if globalIsDiskCacheEnabled { | ||
srvCfg.SetCacheConfig(globalCacheDrives, globalCacheExcludes, globalCacheExpiry, globalCacheMaxUse) | ||
} | ||
|
||
globalServerConfigMu.Lock() | ||
globalServerConfig = srvCfg | ||
globalServerConfigMu.Unlock() | ||
|
||
if !globalIsEnvCreds { | ||
globalActiveCred = globalServerConfig.GetCredential() | ||
} | ||
if !globalIsEnvBrowser { | ||
globalIsBrowserEnabled = globalServerConfig.GetBrowser() | ||
} | ||
if !globalIsEnvWORM { | ||
globalWORMEnabled = globalServerConfig.GetWorm() | ||
} | ||
if !globalIsEnvRegion { | ||
globalServerRegion = globalServerConfig.GetRegion() | ||
} | ||
if !globalIsEnvDomainName { | ||
globalDomainName = globalServerConfig.Domain | ||
} | ||
if !globalIsStorageClass { | ||
globalStandardStorageClass, globalRRStorageClass = globalServerConfig.GetStorageClass() | ||
} | ||
if !globalIsDiskCacheEnabled { | ||
cacheConf := globalServerConfig.GetCacheConfig() | ||
globalCacheDrives = cacheConf.Drives | ||
globalCacheExcludes = cacheConf.Exclude | ||
globalCacheExpiry = cacheConf.Expiry | ||
globalCacheMaxUse = cacheConf.MaxUse | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Init - initializes config system from config.json. | ||
func (sys *ConfigSys) Init(objAPI ObjectLayer) error { | ||
if objAPI == nil { | ||
return errInvalidArgument | ||
} | ||
|
||
srvCfg, err := readServerConfig(context.Background(), objAPI) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err = srvCfg.Validate(); err != nil { | ||
return err | ||
} | ||
|
||
// If env is set override the credentials from config file. | ||
if globalIsEnvCreds { | ||
srvCfg.SetCredential(globalActiveCred) | ||
} | ||
|
||
if globalIsEnvBrowser { | ||
srvCfg.SetBrowser(globalIsBrowserEnabled) | ||
} | ||
|
||
if globalIsEnvWORM { | ||
srvCfg.SetWorm(globalWORMEnabled) | ||
} | ||
|
||
if globalIsEnvRegion { | ||
srvCfg.SetRegion(globalServerRegion) | ||
} | ||
|
||
if globalIsEnvDomainName { | ||
srvCfg.Domain = globalDomainName | ||
} | ||
|
||
if globalIsStorageClass { | ||
srvCfg.SetStorageClass(globalStandardStorageClass, globalRRStorageClass) | ||
} | ||
|
||
if globalIsDiskCacheEnabled { | ||
srvCfg.SetCacheConfig(globalCacheDrives, globalCacheExcludes, globalCacheExpiry, globalCacheMaxUse) | ||
} | ||
|
||
globalServerConfigMu.Lock() | ||
defer globalServerConfigMu.Unlock() | ||
globalServerConfig = srvCfg | ||
return nil | ||
} | ||
|
||
// NewConfigSys - creates new config system object. | ||
func NewConfigSys() *ConfigSys { | ||
return &ConfigSys{} | ||
} | ||
|
||
// Migrates ${HOME}/.minio/config.json to '<export_path>/.minio.sys/config/minio.json' | ||
func migrateConfigToMinioSys() error { | ||
// Construct path to config.json for the given bucket. | ||
configFile := path.Join(bucketConfigPrefix, minioConfigFile) | ||
transactionConfigFile := configFile + ".transaction" | ||
|
||
// As object layer's GetObject() and PutObject() take respective lock on minioMetaBucket | ||
// and configFile, take a transaction lock to avoid race. | ||
objLock := globalNSMutex.NewNSLock(minioMetaBucket, transactionConfigFile) | ||
if err := objLock.GetLock(globalOperationTimeout); err != nil { | ||
return err | ||
} | ||
defer objLock.Unlock() | ||
|
||
// Verify if backend already has the file. | ||
if err := checkServerConfig(context.Background(), newObjectLayerFn()); err != errConfigNotFound { | ||
return err | ||
} // if errConfigNotFound proceed to migrate.. | ||
|
||
data, err := ioutil.ReadFile(getConfigFile()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var config = &serverConfig{} | ||
d := json.NewDecoder(bytes.NewReader(data)) | ||
if err = d.Decode(config); err != nil { | ||
return err | ||
} | ||
|
||
if err = quick.CheckData(config); err != nil { | ||
return err | ||
} | ||
|
||
return saveServerConfig(newObjectLayerFn(), config) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.