From aabfd541e15c04c288f649f9f97207fe729aa3d7 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 31 Jul 2015 12:57:06 -0700 Subject: [PATCH] Merge cmd/donut into minio cmd, deprecate controller RPC request --- Makefile | 1 - cmd/donut/.gitignore | 1 - cmd/donut/console.go | 171 ----------------------------- cmd/donut/main.go | 190 --------------------------------- cmd/donut/make.go | 121 --------------------- cmd/donut/version.go | 21 ---- commands.go | 84 +++++++++++++-- cmd/donut/disks.go => disks.go | 0 pkg/controller/client.go | 27 ----- 9 files changed, 75 insertions(+), 541 deletions(-) delete mode 100644 cmd/donut/.gitignore delete mode 100644 cmd/donut/console.go delete mode 100644 cmd/donut/main.go delete mode 100644 cmd/donut/make.go delete mode 100644 cmd/donut/version.go rename cmd/donut/disks.go => disks.go (100%) diff --git a/Makefile b/Makefile index 8e8347f24..c87c79bf8 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,6 @@ cyclo: gomake-all: getdeps verifiers @echo "Installing minio:" @go run make.go -install - @go run cmd/donut/make.go -install release: getdeps verifiers @echo "Installing minio:" diff --git a/cmd/donut/.gitignore b/cmd/donut/.gitignore deleted file mode 100644 index 11abcb130..000000000 --- a/cmd/donut/.gitignore +++ /dev/null @@ -1 +0,0 @@ -donut \ No newline at end of file diff --git a/cmd/donut/console.go b/cmd/donut/console.go deleted file mode 100644 index c3caedddd..000000000 --- a/cmd/donut/console.go +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Minio Cloud Storage, (C) 2015 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 ( - "fmt" - "os" - "sync" - - "path/filepath" -) - -type logLevel int - -const ( - levelUnknown logLevel = iota - levelPrint - levelDebug - levelInfo - levelError - levelFatal -) - -var ( - mutex = &sync.RWMutex{} - - // Fatal prints a error message and exits - Fatal = func(a ...interface{}) { privatePrint(levelFatal, a...) } - // Fatalln prints a error message with a new line and exits - Fatalln = func(a ...interface{}) { privatePrintln(levelFatal, a...) } - // Fatalf prints a error message with formatting and exits - Fatalf = func(f string, a ...interface{}) { privatePrintf(levelFatal, f, a...) } - - // Error prints a error message - Error = func(a ...interface{}) { privatePrint(levelError, a...) } - // Errorln prints a error message with a new line - Errorln = func(a ...interface{}) { privatePrintln(levelError, a...) } - // Errorf prints a error message with formatting - Errorf = func(f string, a ...interface{}) { privatePrintf(levelError, f, a...) } - - // Info prints a informational message - Info = func(a ...interface{}) { privatePrint(levelInfo, a...) } - // Infoln prints a informational message with a new line - Infoln = func(a ...interface{}) { privatePrintln(levelInfo, a...) } - // Infof prints a informational message with formatting - Infof = func(f string, a ...interface{}) { privatePrintf(levelInfo, f, a...) } - - // Debug prints a debug message - Debug = func(a ...interface{}) { privatePrint(levelDebug, a...) } - // Debugln prints a debug message with a new line - Debugln = func(a ...interface{}) { privatePrintln(levelDebug, a...) } - // Debugf prints a debug message with formatting - Debugf = func(f string, a ...interface{}) { privatePrintf(levelDebug, f, a...) } - - // Print prints a debug message - Print = func(a ...interface{}) { privatePrint(levelPrint, a...) } - // Println prints a debug message with a new line - Println = func(a ...interface{}) { privatePrintln(levelPrint, a...) } - // Printf prints a debug message with formatting - Printf = func(f string, a ...interface{}) { privatePrintf(levelPrint, f, a...) } -) - -var ( - // print prints a message prefixed with message type and program name - privatePrint = func(l logLevel, a ...interface{}) { - switch l { - case levelDebug: - mutex.Lock() - fmt.Fprint(os.Stderr, ProgramName()+": ") - fmt.Fprint(os.Stderr, a...) - mutex.Unlock() - case levelInfo: - mutex.Lock() - fmt.Print(ProgramName() + ": ") - fmt.Print(a...) - mutex.Unlock() - case levelError: - mutex.Lock() - fmt.Fprint(os.Stderr, ProgramName()+": ") - fmt.Fprint(os.Stderr, a...) - mutex.Unlock() - case levelFatal: - mutex.Lock() - fmt.Fprint(os.Stderr, ProgramName()+": ") - fmt.Fprint(os.Stderr, a...) - mutex.Unlock() - os.Exit(1) - default: - fmt.Print(a...) - } - } - - // println - same as print with a new line - privatePrintln = func(l logLevel, a ...interface{}) { - switch l { - case levelDebug: - mutex.Lock() - fmt.Fprint(os.Stderr, ProgramName()+": ") - fmt.Fprintln(os.Stderr, a...) - mutex.Unlock() - case levelInfo: - mutex.Lock() - fmt.Print(ProgramName() + ": ") - fmt.Println(a...) - mutex.Unlock() - case levelError: - mutex.Lock() - fmt.Fprint(os.Stderr, ProgramName()+": ") - fmt.Fprintln(os.Stderr, a...) - mutex.Unlock() - case levelFatal: - mutex.Lock() - fmt.Fprint(os.Stderr, ProgramName()+": ") - fmt.Fprintln(os.Stderr, a...) - mutex.Unlock() - os.Exit(1) - default: - fmt.Print(a...) - } - } - - // printf - same as print, but takes a format specifier - privatePrintf = func(l logLevel, f string, a ...interface{}) { - switch l { - case levelDebug: - mutex.Lock() - fmt.Fprint(os.Stderr, ProgramName()+": ") - fmt.Fprintf(os.Stderr, f, a...) - mutex.Unlock() - case levelInfo: - mutex.Lock() - fmt.Print(ProgramName() + ": ") - fmt.Printf(f, a...) - mutex.Unlock() - case levelError: - mutex.Lock() - fmt.Fprint(os.Stderr, ProgramName()+": ") - fmt.Fprintf(os.Stderr, f, a...) - mutex.Unlock() - - case levelFatal: - mutex.Lock() - fmt.Fprint(os.Stderr, ProgramName()+": ") - fmt.Fprintf(os.Stderr, f, a...) - mutex.Unlock() - os.Exit(1) - default: - fmt.Printf(f, a...) - } - } -) - -// ProgramName - return the name of the executable program -func ProgramName() string { - _, progName := filepath.Split(os.Args[0]) - return progName -} diff --git a/cmd/donut/main.go b/cmd/donut/main.go deleted file mode 100644 index 18d4305f6..000000000 --- a/cmd/donut/main.go +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Minio Cloud Storage, (C) 2015 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 ( - "fmt" - "os" - "os/user" - "path/filepath" - "runtime" - "strconv" - "time" - - "github.com/dustin/go-humanize" - "github.com/minio/cli" - "github.com/minio/minio/pkg/donut" - "github.com/minio/minio/pkg/iodine" -) - -var globalDebugFlag = false - -var flags = []cli.Flag{ - cli.BoolFlag{ - Name: "debug", - Usage: "print debug information", - }, -} -var commands = []cli.Command{ - { - Name: "make", - Description: "make a donut", - Action: runMkdonut, - CustomHelpTemplate: `NAME: - donut {{.Name}} - {{.Description}} - -USAGE: - donut {{.Name}} DONUTNAME [DISKS...] - -EXAMPLES: - 1. Make a donut with 4 exports - $ donut {{.Name}} mongodb-backup /mnt/export1 /mnt/export2 /mnt/export3 /mnt/export4 - - 2. Make a donut with 16 exports - $ donut {{.Name}} operational-data /mnt/export1 /mnt/export2 /mnt/export3 /mnt/export4 /mnt/export5 \ - /mnt/export6 /mnt/export7 /mnt/export8 /mnt/export9 /mnt/export10 /mnt/export11 \ - /mnt/export12 /mnt/export13 /mnt/export14 /mnt/export15 /mnt/export16 -`, - }, -} - -func init() { - // Check for the environment early on and gracefuly report. - _, err := user.Current() - if err != nil { - Fatalf("Unable to obtain user's home directory. \nError: %s\n", err) - } -} - -// Tries to get os/arch/platform specific information -// Returns a map of current os/arch/platform/memstats -func getSystemData() map[string]string { - host, err := os.Hostname() - if err != nil { - host = "" - } - memstats := &runtime.MemStats{} - runtime.ReadMemStats(memstats) - mem := fmt.Sprintf("Used: %s | Allocated: %s | Used-Heap: %s | Allocated-Heap: %s", - humanize.Bytes(memstats.Alloc), - humanize.Bytes(memstats.TotalAlloc), - humanize.Bytes(memstats.HeapAlloc), - humanize.Bytes(memstats.HeapSys)) - platform := fmt.Sprintf("Host: %s | OS: %s | Arch: %s", - host, - runtime.GOOS, - runtime.GOARCH) - goruntime := fmt.Sprintf("Version: %s | CPUs: %s", runtime.Version(), strconv.Itoa(runtime.NumCPU())) - return map[string]string{ - "PLATFORM": platform, - "RUNTIME": goruntime, - "MEM": mem, - } -} - -func runMkdonut(c *cli.Context) { - if !c.Args().Present() || c.Args().First() == "help" { - cli.ShowCommandHelpAndExit(c, "make", 1) - } - donutName := c.Args().First() - if c.Args().First() != "" { - if !donut.IsValidDonut(donutName) { - Fatalf("Invalid donutname %s\n", donutName) - } - } - var disks []string - for _, disk := range c.Args().Tail() { - if _, err := isUsable(disk); err != nil { - Fatalln(err) - } - disks = append(disks, disk) - } - for _, disk := range disks { - if err := os.MkdirAll(filepath.Join(disk, donutName), 0700); err != nil { - Fatalln(err) - } - } - - hostname, err := os.Hostname() - if err != nil { - Fatalln(err) - } - donutConfig := &donut.Config{} - donutConfig.Version = "0.0.1" - donutConfig.DonutName = donutName - donutConfig.NodeDiskMap = make(map[string][]string) - // keep it in exact order as it was specified, do not try to sort disks - donutConfig.NodeDiskMap[hostname] = disks - // default cache is unlimited - donutConfig.MaxSize = 512000000 - - if err := donut.SaveConfig(donutConfig); err != nil { - Fatalln(err) - } - - Infoln("Success!") -} - -func main() { - // set up iodine - iodine.SetGlobalState("mkdonut.version", Version) - iodine.SetGlobalState("mkdonut.starttime", time.Now().Format(time.RFC3339)) - - // set up go max processes - runtime.GOMAXPROCS(runtime.NumCPU()) - - // set up app - app := cli.NewApp() - app.Name = "donut" - app.Version = getVersion() - app.Compiled = getVersion() - app.Author = "Minio.io" - app.Usage = "Donut maker" - app.Commands = commands - app.Flags = flags - app.Before = func(c *cli.Context) error { - globalDebugFlag = c.GlobalBool("debug") - return nil - } - app.ExtraInfo = func() map[string]string { - if globalDebugFlag { - return getSystemData() - } - return make(map[string]string) - } - app.CustomAppHelpTemplate = `NAME: - {{.Name}} - {{.Usage}} - -USAGE: - {{.Name}} {{if .Flags}}[global flags] {{end}}command{{if .Flags}} [command flags]{{end}} [arguments...] - -COMMANDS: - {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} - {{end}}{{if .Flags}} -GLOBAL FLAGS: - {{range .Flags}}{{.}} - {{end}}{{end}} -VERSION: - {{if .Compiled}} - {{.Compiled}}{{end}} - {{range $key, $value := ExtraInfo}} -{{$key}}: - {{$value}} -{{end}} -` - app.RunAndExitOnError() -} diff --git a/cmd/donut/make.go b/cmd/donut/make.go deleted file mode 100644 index 7626793a4..000000000 --- a/cmd/donut/make.go +++ /dev/null @@ -1,121 +0,0 @@ -// +build ignore - -/* - * Makefile alternative for Minio Cloud Storage, (C) 2015 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 ( - "bytes" - "flag" - "fmt" - "os" - "os/exec" - "text/template" - "time" -) - -type Version struct { - Date string -} - -func writeVersion(version Version) error { - var versionTemplate = `// -------- DO NOT EDIT -------- -// this is an autogenerated file - -package main - -import ( - "net/http" - "time" -) - -// Version autogenerated -var Version = {{if .Date}}"{{.Date}}"{{else}}""{{end}} - -// getVersion - -func getVersion() string { - t, _ := time.Parse(time.RFC3339Nano, Version) - if t.IsZero() { - return "" - } - return t.Format(http.TimeFormat) -} -` - t := template.Must(template.New("version").Parse(versionTemplate)) - versionFile, err := os.OpenFile("version.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - return err - } - defer versionFile.Close() - err = t.Execute(versionFile, version) - if err != nil { - return err - } - return nil -} - -type command struct { - cmd *exec.Cmd - stderr *bytes.Buffer - stdout *bytes.Buffer -} - -func (c command) runCommand() error { - c.cmd.Stdout = c.stdout - c.cmd.Stderr = c.stderr - return c.cmd.Run() -} -func (c command) String() string { - message := c.stderr.String() - message += c.stdout.String() - return message -} - -func runDonutInstall() { - donutInstall := command{exec.Command("godep", "go", "install", "-a", "github.com/minio/minio/cmd/donut"), &bytes.Buffer{}, &bytes.Buffer{}} - donutInstallErr := donutInstall.runCommand() - if donutInstallErr != nil { - fmt.Println(donutInstall) - os.Exit(1) - } - fmt.Print(donutInstall) -} - -func runDonutRelease() { - t := time.Now().UTC() - date := t.Format(time.RFC3339Nano) - version := Version{Date: date} - err := writeVersion(version) - if err != nil { - fmt.Print(err) - os.Exit(1) - } -} - -func main() { - releaseFlag := flag.Bool("release", false, "make a release") - installFlag := flag.Bool("install", false, "install donut") - - flag.Parse() - - if *releaseFlag { - runDonutRelease() - } - if *installFlag { - runDonutInstall() - } -} diff --git a/cmd/donut/version.go b/cmd/donut/version.go deleted file mode 100644 index 17ca8c3d3..000000000 --- a/cmd/donut/version.go +++ /dev/null @@ -1,21 +0,0 @@ -// -------- DO NOT EDIT -------- -// this is an autogenerated file - -package main - -import ( - "net/http" - "time" -) - -// Version autogenerated -var Version = "2015-07-13T01:59:53.151205631Z" - -// getVersion - -func getVersion() string { - t, _ := time.Parse(time.RFC3339Nano, Version) - if t.IsZero() { - return "" - } - return t.Format(http.TimeFormat) -} diff --git a/commands.go b/commands.go index 7a749c3cf..c59b20e39 100644 --- a/commands.go +++ b/commands.go @@ -19,9 +19,11 @@ package main import ( "os" "os/user" + "path/filepath" "github.com/minio/cli" "github.com/minio/minio/pkg/controller" + "github.com/minio/minio/pkg/donut" "github.com/minio/minio/pkg/server" "github.com/minio/minio/pkg/server/api" ) @@ -29,6 +31,7 @@ import ( var commands = []cli.Command{ serverCmd, controllerCmd, + donutCmd, } var serverCmd = cli.Command{ @@ -68,6 +71,78 @@ EXAMPLES: `, } +var donutSubCommands = []cli.Command{ + { + Name: "make", + Description: "make a donut", + Action: runMkdonut, + CustomHelpTemplate: `NAME: + donut {{.Name}} - {{.Description}} + +USAGE: + donut {{.Name}} DONUTNAME [DISKS...] + +EXAMPLES: + 1. Make a donut with 4 exports + $ donut {{.Name}} mongodb-backup /mnt/export1 /mnt/export2 /mnt/export3 /mnt/export4 + + 2. Make a donut with 16 exports + $ donut {{.Name}} operational-data /mnt/export1 /mnt/export2 /mnt/export3 /mnt/export4 /mnt/export5 \ + /mnt/export6 /mnt/export7 /mnt/export8 /mnt/export9 /mnt/export10 /mnt/export11 \ + /mnt/export12 /mnt/export13 /mnt/export14 /mnt/export15 /mnt/export16 +`, + }, +} + +var donutCmd = cli.Command{ + Name: "donut", + Description: "Donut maker", + Subcommands: donutSubCommands, +} + +func runMkdonut(c *cli.Context) { + if !c.Args().Present() || c.Args().First() == "help" { + cli.ShowCommandHelpAndExit(c, "make", 1) + } + donutName := c.Args().First() + if c.Args().First() != "" { + if !donut.IsValidDonut(donutName) { + Fatalf("Invalid donutname %s\n", donutName) + } + } + var disks []string + for _, disk := range c.Args().Tail() { + if _, err := isUsable(disk); err != nil { + Fatalln(err) + } + disks = append(disks, disk) + } + for _, disk := range disks { + if err := os.MkdirAll(filepath.Join(disk, donutName), 0700); err != nil { + Fatalln(err) + } + } + + hostname, err := os.Hostname() + if err != nil { + Fatalln(err) + } + donutConfig := &donut.Config{} + donutConfig.Version = "0.0.1" + donutConfig.DonutName = donutName + donutConfig.NodeDiskMap = make(map[string][]string) + // keep it in exact order as it was specified, do not try to sort disks + donutConfig.NodeDiskMap[hostname] = disks + // default cache is unlimited + donutConfig.MaxSize = 512000000 + + if err := donut.SaveConfig(donutConfig); err != nil { + Fatalln(err) + } + + Infoln("Success!") +} + func getServerConfig(c *cli.Context) api.Config { certFile := c.GlobalString("cert") keyFile := c.GlobalString("key") @@ -126,14 +201,5 @@ func runController(c *cli.Context) { Fatalln(err) } Println(string(keys)) - case "donut": - if len(c.Args()) <= 2 || c.Args().First() == "help" { - cli.ShowCommandHelpAndExit(c, "controller", 1) // last argument is exit code - } - hostname, _ := os.Hostname() - err := controller.SetDonut(c.Args().Tail().First(), hostname, c.Args().Tail().Tail()) - if err != nil { - Fatalln(err) - } } } diff --git a/cmd/donut/disks.go b/disks.go similarity index 100% rename from cmd/donut/disks.go rename to disks.go diff --git a/pkg/controller/client.go b/pkg/controller/client.go index dc0f2c9b7..ddf106849 100644 --- a/pkg/controller/client.go +++ b/pkg/controller/client.go @@ -109,31 +109,4 @@ func GetAuthKeys(url string) ([]byte, error) { return json.MarshalIndent(reply, "", "\t") } -// SetDonut - set donut config -func SetDonut(url, hostname string, disks []string) error { - op := RPCOps{ - Method: "Donut.Set", - Request: rpc.DonutArgs{ - Hostname: hostname, - Disks: disks, - Name: "default", - MaxSize: 512000000, - }, - } - req, err := NewRequest(url, op, http.DefaultTransport) - if err != nil { - return iodine.New(err, nil) - } - resp, err := req.Do() - defer closeResp(resp) - if err != nil { - return iodine.New(err, nil) - } - var reply rpc.Reply - if err := jsonrpc.DecodeClientResponse(resp.Body, &reply); err != nil { - return iodine.New(err, nil) - } - return reply.Error -} - // Add more functions here for other RPC messages