Refactor Heal RPC and add Shutdown RPC (#2488)
parent
975eb31973
commit
07506358ff
@ -0,0 +1,120 @@ |
||||
/* |
||||
* 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 cmd |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net/rpc" |
||||
"net/url" |
||||
"path" |
||||
"strings" |
||||
|
||||
"github.com/minio/cli" |
||||
) |
||||
|
||||
var healCmd = cli.Command{ |
||||
Name: "heal", |
||||
Usage: "To heal objects.", |
||||
Action: healControl, |
||||
CustomHelpTemplate: `NAME: |
||||
minio control {{.Name}} - {{.Usage}} |
||||
|
||||
USAGE: |
||||
minio control {{.Name}} |
||||
|
||||
EAMPLES: |
||||
1. Heal an object. |
||||
$ minio control {{.Name}} http://localhost:9000/songs/classical/western/piano.mp3
|
||||
|
||||
2. Heal all objects in a bucket recursively. |
||||
$ minio control {{.Name}} http://localhost:9000/songs
|
||||
|
||||
3. Heall all objects with a given prefix recursively. |
||||
$ minio control {{.Name}} http://localhost:9000/songs/classical/
|
||||
`, |
||||
} |
||||
|
||||
// "minio control heal" entry point.
|
||||
func healControl(ctx *cli.Context) { |
||||
// Parse bucket and object from url.URL.Path
|
||||
parseBucketObject := func(path string) (bucketName string, objectName string) { |
||||
splits := strings.SplitN(path, string(slashSeparator), 3) |
||||
switch len(splits) { |
||||
case 0, 1: |
||||
bucketName = "" |
||||
objectName = "" |
||||
case 2: |
||||
bucketName = splits[1] |
||||
objectName = "" |
||||
case 3: |
||||
bucketName = splits[1] |
||||
objectName = splits[2] |
||||
|
||||
} |
||||
return bucketName, objectName |
||||
} |
||||
|
||||
if len(ctx.Args()) != 1 { |
||||
cli.ShowCommandHelpAndExit(ctx, "heal", 1) |
||||
} |
||||
|
||||
parsedURL, err := url.Parse(ctx.Args()[0]) |
||||
fatalIf(err, "Unable to parse URL") |
||||
|
||||
bucketName, objectName := parseBucketObject(parsedURL.Path) |
||||
if bucketName == "" { |
||||
cli.ShowCommandHelpAndExit(ctx, "heal", 1) |
||||
} |
||||
|
||||
client, err := rpc.DialHTTPPath("tcp", parsedURL.Host, path.Join(reservedBucket, controlPath)) |
||||
fatalIf(err, "Unable to connect to %s", parsedURL.Host) |
||||
|
||||
// If object does not have trailing "/" then it's an object, hence heal it.
|
||||
if objectName != "" && !strings.HasSuffix(objectName, slashSeparator) { |
||||
fmt.Printf("Healing : /%s/%s", bucketName, objectName) |
||||
args := &HealObjectArgs{bucketName, objectName} |
||||
reply := &HealObjectReply{} |
||||
err = client.Call("Control.HealObject", args, reply) |
||||
fatalIf(err, "RPC Control.HealObject call failed") |
||||
fmt.Println() |
||||
return |
||||
} |
||||
|
||||
// Recursively list and heal the objects.
|
||||
prefix := objectName |
||||
marker := "" |
||||
for { |
||||
args := HealListArgs{bucketName, prefix, marker, "", 1000} |
||||
reply := &HealListReply{} |
||||
err = client.Call("Control.ListObjectsHeal", args, reply) |
||||
fatalIf(err, "RPC Heal.ListObjects call failed") |
||||
|
||||
// Heal the objects returned in the ListObjects reply.
|
||||
for _, obj := range reply.Objects { |
||||
fmt.Printf("Healing : /%s/%s", bucketName, obj) |
||||
reply := &HealObjectReply{} |
||||
err = client.Call("Control.HealObject", HealObjectArgs{bucketName, obj}, reply) |
||||
fatalIf(err, "RPC Heal.HealObject call failed") |
||||
fmt.Println() |
||||
} |
||||
if !reply.IsTruncated { |
||||
// End of listing.
|
||||
break |
||||
} |
||||
marker = reply.NextMarker |
||||
} |
||||
} |
@ -0,0 +1,68 @@ |
||||
/* |
||||
* 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 cmd |
||||
|
||||
import ( |
||||
"net/rpc" |
||||
"net/url" |
||||
"path" |
||||
|
||||
"github.com/minio/cli" |
||||
) |
||||
|
||||
var shutdownCmd = cli.Command{ |
||||
Name: "shutdown", |
||||
Usage: "Shutdown or restart the server.", |
||||
Action: shutdownControl, |
||||
Flags: []cli.Flag{ |
||||
cli.BoolFlag{ |
||||
Name: "restart", |
||||
Usage: "Restart the server.", |
||||
}, |
||||
}, |
||||
CustomHelpTemplate: `NAME: |
||||
minio control {{.Name}} - {{.Usage}} |
||||
|
||||
USAGE: |
||||
minio control {{.Name}} http://localhost:9000/
|
||||
|
||||
EAMPLES: |
||||
1. Shutdown the server: |
||||
$ minio control shutdown http://localhost:9000/
|
||||
|
||||
2. Reboot the server: |
||||
$ minio control shutdown --restart http://localhost:9000/
|
||||
`, |
||||
} |
||||
|
||||
// "minio control shutdown" entry point.
|
||||
func shutdownControl(c *cli.Context) { |
||||
if len(c.Args()) != 1 { |
||||
cli.ShowCommandHelpAndExit(c, "shutdown", 1) |
||||
} |
||||
|
||||
parsedURL, err := url.ParseRequestURI(c.Args()[0]) |
||||
fatalIf(err, "Unable to parse URL") |
||||
|
||||
client, err := rpc.DialHTTPPath("tcp", parsedURL.Host, path.Join(reservedBucket, controlPath)) |
||||
fatalIf(err, "Unable to connect to %s", parsedURL.Host) |
||||
|
||||
args := &ShutdownArgs{Reboot: c.Bool("restart")} |
||||
reply := &ShutdownReply{} |
||||
err = client.Call("Control.Shutdown", args, reply) |
||||
fatalIf(err, "RPC Control.Shutdown call failed") |
||||
} |
@ -0,0 +1,42 @@ |
||||
/* |
||||
* 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 cmd |
||||
|
||||
import ( |
||||
"net/rpc" |
||||
|
||||
router "github.com/gorilla/mux" |
||||
) |
||||
|
||||
// Routes paths for "minio control" commands.
|
||||
const ( |
||||
controlPath = "/controller" |
||||
) |
||||
|
||||
// Register control RPC handlers.
|
||||
func registerControlRPCRouter(mux *router.Router, ctrlHandlers *controllerAPIHandlers) { |
||||
ctrlRPCServer := rpc.NewServer() |
||||
ctrlRPCServer.RegisterName("Control", ctrlHandlers) |
||||
|
||||
ctrlRouter := mux.NewRoute().PathPrefix(reservedBucket).Subrouter() |
||||
ctrlRouter.Path(controlPath).Handler(ctrlRPCServer) |
||||
} |
||||
|
||||
// Handler for object healing.
|
||||
type controllerAPIHandlers struct { |
||||
ObjectAPI ObjectLayer |
||||
} |
Loading…
Reference in new issue