mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
Merge cmd/donut into minio cmd, deprecate controller RPC request
This commit is contained in:
parent
6be5a2fb7e
commit
aabfd541e1
1
Makefile
1
Makefile
@ -34,7 +34,6 @@ cyclo:
|
|||||||
gomake-all: getdeps verifiers
|
gomake-all: getdeps verifiers
|
||||||
@echo "Installing minio:"
|
@echo "Installing minio:"
|
||||||
@go run make.go -install
|
@go run make.go -install
|
||||||
@go run cmd/donut/make.go -install
|
|
||||||
|
|
||||||
release: getdeps verifiers
|
release: getdeps verifiers
|
||||||
@echo "Installing minio:"
|
@echo "Installing minio:"
|
||||||
|
1
cmd/donut/.gitignore
vendored
1
cmd/donut/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
donut
|
|
@ -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()+": <DEBUG> ")
|
|
||||||
fmt.Fprint(os.Stderr, a...)
|
|
||||||
mutex.Unlock()
|
|
||||||
case levelInfo:
|
|
||||||
mutex.Lock()
|
|
||||||
fmt.Print(ProgramName() + ": <INFO> ")
|
|
||||||
fmt.Print(a...)
|
|
||||||
mutex.Unlock()
|
|
||||||
case levelError:
|
|
||||||
mutex.Lock()
|
|
||||||
fmt.Fprint(os.Stderr, ProgramName()+": <ERROR> ")
|
|
||||||
fmt.Fprint(os.Stderr, a...)
|
|
||||||
mutex.Unlock()
|
|
||||||
case levelFatal:
|
|
||||||
mutex.Lock()
|
|
||||||
fmt.Fprint(os.Stderr, ProgramName()+": <FATAL> ")
|
|
||||||
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()+": <DEBUG> ")
|
|
||||||
fmt.Fprintln(os.Stderr, a...)
|
|
||||||
mutex.Unlock()
|
|
||||||
case levelInfo:
|
|
||||||
mutex.Lock()
|
|
||||||
fmt.Print(ProgramName() + ": <INFO> ")
|
|
||||||
fmt.Println(a...)
|
|
||||||
mutex.Unlock()
|
|
||||||
case levelError:
|
|
||||||
mutex.Lock()
|
|
||||||
fmt.Fprint(os.Stderr, ProgramName()+": <ERROR> ")
|
|
||||||
fmt.Fprintln(os.Stderr, a...)
|
|
||||||
mutex.Unlock()
|
|
||||||
case levelFatal:
|
|
||||||
mutex.Lock()
|
|
||||||
fmt.Fprint(os.Stderr, ProgramName()+": <FATAL> ")
|
|
||||||
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()+": <DEBUG> ")
|
|
||||||
fmt.Fprintf(os.Stderr, f, a...)
|
|
||||||
mutex.Unlock()
|
|
||||||
case levelInfo:
|
|
||||||
mutex.Lock()
|
|
||||||
fmt.Print(ProgramName() + ": <INFO> ")
|
|
||||||
fmt.Printf(f, a...)
|
|
||||||
mutex.Unlock()
|
|
||||||
case levelError:
|
|
||||||
mutex.Lock()
|
|
||||||
fmt.Fprint(os.Stderr, ProgramName()+": <ERROR> ")
|
|
||||||
fmt.Fprintf(os.Stderr, f, a...)
|
|
||||||
mutex.Unlock()
|
|
||||||
|
|
||||||
case levelFatal:
|
|
||||||
mutex.Lock()
|
|
||||||
fmt.Fprint(os.Stderr, ProgramName()+": <FATAL> ")
|
|
||||||
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
|
|
||||||
}
|
|
@ -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()
|
|
||||||
}
|
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)
|
|
||||||
}
|
|
84
commands.go
84
commands.go
@ -19,9 +19,11 @@ package main
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/minio/cli"
|
"github.com/minio/cli"
|
||||||
"github.com/minio/minio/pkg/controller"
|
"github.com/minio/minio/pkg/controller"
|
||||||
|
"github.com/minio/minio/pkg/donut"
|
||||||
"github.com/minio/minio/pkg/server"
|
"github.com/minio/minio/pkg/server"
|
||||||
"github.com/minio/minio/pkg/server/api"
|
"github.com/minio/minio/pkg/server/api"
|
||||||
)
|
)
|
||||||
@ -29,6 +31,7 @@ import (
|
|||||||
var commands = []cli.Command{
|
var commands = []cli.Command{
|
||||||
serverCmd,
|
serverCmd,
|
||||||
controllerCmd,
|
controllerCmd,
|
||||||
|
donutCmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
var serverCmd = cli.Command{
|
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 {
|
func getServerConfig(c *cli.Context) api.Config {
|
||||||
certFile := c.GlobalString("cert")
|
certFile := c.GlobalString("cert")
|
||||||
keyFile := c.GlobalString("key")
|
keyFile := c.GlobalString("key")
|
||||||
@ -126,14 +201,5 @@ func runController(c *cli.Context) {
|
|||||||
Fatalln(err)
|
Fatalln(err)
|
||||||
}
|
}
|
||||||
Println(string(keys))
|
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,31 +109,4 @@ func GetAuthKeys(url string) ([]byte, error) {
|
|||||||
return json.MarshalIndent(reply, "", "\t")
|
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
|
// Add more functions here for other RPC messages
|
||||||
|
Loading…
Reference in New Issue
Block a user