diff --git a/config.go b/config.go index be7203d36..43274a41d 100644 --- a/config.go +++ b/config.go @@ -86,3 +86,26 @@ func getConfigFile() (string, error) { } return filepath.Join(configPath, globalMinioConfigFile), nil } + +// isFormatConfigFileExists - returns true if format config file exists. +func isFormatConfigFileExists() bool { + st, err := os.Stat(mustGetFormatConfigFile()) + return (err == nil && st.Mode().IsRegular()) +} + +// mustGetFormatConfigFile must get format config file. +func mustGetFormatConfigFile() string { + configFile, err := getFormatConfigFile() + fatalIf(err, "Unable to get format config file.", nil) + + return configFile +} + +// getFormatConfigFile get format config file. +func getFormatConfigFile() (string, error) { + configPath, err := getConfigPath() + if err != nil { + return "", err + } + return filepath.Join(configPath, globalMinioFormatConfigFile), nil +} diff --git a/format-config-v1.go b/format-config-v1.go new file mode 100644 index 000000000..dabb75b0e --- /dev/null +++ b/format-config-v1.go @@ -0,0 +1,111 @@ +/* + * Minio Cloud Storage, (C) 2016 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 main + +import "github.com/minio/minio/pkg/quick" + +type fsFormat struct { + Version string `json:"version"` +} + +type xlFormat struct { + Version string `json:"version"` + Disks []string `json:"disks"` +} + +type formatConfigV1 struct { + // must have "Version" to "quick" to work + Version string `json:"version"` + Format string `json:"format"` + FS fsFormat `json:"fs,omitempty"` + XL xlFormat `json:"xl,omitempty"` +} + +func (f formatConfigV1) Save() error { + configFile, err := getFormatConfigFile() + if err != nil { + return err + } + + // initialize quick. + qc, err := quick.New(&f) + if err != nil { + return err + } + + // Save config file. + return qc.Save(configFile) +} + +func (f *formatConfigV1) Load() error { + configFile, err := getFormatConfigFile() + if err != nil { + return err + } + + f.Version = globalMinioConfigVersion + qc, err := quick.New(f) + if err != nil { + return err + } + if err := qc.Load(configFile); err != nil { + return err + } + + return nil +} + +// saveFormatFS - save FS format configuration +func saveFormatFS(fs fsFormat) error { + config := formatConfigV1{Version: globalMinioConfigVersion, Format: "fs", FS: fs} + return config.Save() +} + +// saveFormatXL - save XL format configuration +func saveFormatXL(xl xlFormat) error { + config := formatConfigV1{Version: globalMinioConfigVersion, Format: "xl", XL: xl} + return config.Save() +} + +// getSavedFormatConfig - get saved format configuration +func getSavedFormatConfig() (formatConfigV1, error) { + config := formatConfigV1{Version: globalMinioConfigVersion} + + if err := config.Load(); err != nil { + return config, err + } + + return config, nil +} + +// getFormatFS - get saved FS format configuration +func getFormatFS() (fsFormat, error) { + config, err := getSavedFormatConfig() + if err != nil { + return fsFormat{}, err + } + return config.FS, nil +} + +// getFormatXL - get saved XL format configuration +func getFormatXL() (xlFormat, error) { + config, err := getSavedFormatConfig() + if err != nil { + return xlFormat{}, err + } + return config.XL, nil +} diff --git a/globals.go b/globals.go index bb65c27bc..ad3b147f7 100644 --- a/globals.go +++ b/globals.go @@ -29,12 +29,13 @@ const ( // minio configuration related constants. const ( - globalMinioConfigVersion = "4" - globalMinioConfigDir = ".minio" - globalMinioCertsDir = ".minio/certs" - globalMinioCertFile = "public.crt" - globalMinioKeyFile = "private.key" - globalMinioConfigFile = "config.json" + globalMinioConfigVersion = "4" + globalMinioConfigDir = ".minio" + globalMinioCertsDir = ".minio/certs" + globalMinioCertFile = "public.crt" + globalMinioKeyFile = "private.key" + globalMinioConfigFile = "config.json" + globalMinioFormatConfigFile = "format.json" ) var ( diff --git a/routers.go b/routers.go index 39afda7f7..5f5d9a7f3 100644 --- a/routers.go +++ b/routers.go @@ -17,7 +17,9 @@ package main import ( + "fmt" "net/http" + "reflect" router "github.com/gorilla/mux" ) @@ -36,6 +38,26 @@ func newObjectLayer(exportPaths ...string) (ObjectLayer, error) { // configureServer handler returns final handler for the http server. func configureServerHandler(srvCmdConfig serverCmdConfig) http.Handler { + // FIXME: currently we don't check single exportPath which uses FS layer. + if len(srvCmdConfig.exportPaths) > 1 { + if isFormatConfigFileExists() { + format, err := getFormatXL() + if err != nil { + fatalIf(err, "Failed to read format.json", nil) + } + + if !reflect.DeepEqual(format.Disks, srvCmdConfig.exportPaths) { + err = fmt.Errorf("Number of export paths from command-line did not match the backend configuration. Backend is configured with [%s] exports.", format.Disks) + fatalIf(err, "", nil) + } + } else { + // First run: save disk configuration + if err := saveFormatXL(xlFormat{Version: "1", Disks: srvCmdConfig.exportPaths}); err != nil { + fatalIf(err, "Unable to save 'format.json'", nil) + } + } + } + objAPI, err := newObjectLayer(srvCmdConfig.exportPaths...) fatalIf(err, "Initializing object layer failed.", nil)