1
0
mirror of https://github.com/minio/mc.git synced 2025-11-10 13:42:32 +03:00

Add admin lock command (#1942)

This commit is contained in:
Anis Elleuch
2017-01-06 10:29:49 +01:00
committed by Harshavardhana
parent 86777e7863
commit 7cec8f2285
14 changed files with 776 additions and 26 deletions

157
cmd/admin-lock-clear.go Normal file
View File

@@ -0,0 +1,157 @@
/*
* Minio Client (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 (
"encoding/json"
"fmt"
"net/url"
"path/filepath"
"time"
"github.com/minio/cli"
"github.com/minio/minio/pkg/madmin"
"github.com/minio/minio/pkg/probe"
)
var (
adminLockClearFlags = []cli.Flag{
cli.StringFlag{
Name: "older-than, o",
Usage: "Only show locks that are older than a specified time, i.e. 30s",
Value: "0s",
},
}
)
var adminLockClearCmd = cli.Command{
Name: "clear",
Usage: "Clear locks hold in a given Minio server",
Action: mainAdminLockClear,
Flags: append(adminLockClearFlags, globalFlags...),
CustomHelpTemplate: `NAME:
mc admin lock {{.Name}} - {{.Usage}}
USAGE:
mc admin lock {{.Name}} ALIAS/BUCKET/PREFIX
FLAGS:
{{range .Flags}}{{.}}
{{end}}
EXAMPLES:
1. Clear all locks hold by 'testbucket' in a Minio server represented by its alias 'play'.
$ mc admin lock {{.Name}} play/testbucket
2. Clear all 'testbucket' locks that are older than 15 minutes.
$ mc admin lock {{.Name}} --older-than 15m play/testbucket/
3. Clear all locks hold by all objects under 'dir' prefix
$ mc admin lock {{.Name}} play/testbucket/dir/
`,
}
// lockClearMessage container to hold locks information.
type lockClearMessage struct {
Status string `json:"status"`
LockInfo madmin.VolumeLockInfo `json:"volumeLockInfo"`
}
// String colorized service status message.
func (u lockClearMessage) String() string {
msg := fmt.Sprintf("%s/%s (LocksOnObject: %d, locksAcquiredOnObject: %d, totalBlockLocks:%d): ",
u.LockInfo.Bucket,
u.LockInfo.Object,
u.LockInfo.LocksOnObject,
u.LockInfo.LocksAcquiredOnObject,
u.LockInfo.TotalBlockedLocks)
for _, detail := range u.LockInfo.LockDetailsOnObject {
msg += fmt.Sprintf(" %+v", detail)
}
msg += "\n"
return msg
}
// JSON jsonified service status Message message.
func (u lockClearMessage) JSON() string {
u.Status = "success"
statusJSONBytes, e := json.Marshal(u)
fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
return string(statusJSONBytes)
}
// checkAdminLockClearSyntax - validate all the passed arguments
func checkAdminLockClearSyntax(ctx *cli.Context) {
if len(ctx.Args()) == 0 || len(ctx.Args()) > 2 {
cli.ShowCommandHelpAndExit(ctx, "clear", 1) // last argument is exit code
}
}
func mainAdminLockClear(ctx *cli.Context) error {
setGlobalsFromContext(ctx)
checkAdminLockClearSyntax(ctx)
// Get the alias parameter from cli
args := ctx.Args()
aliasedURL := args.Get(0)
// Parse older-than flag
olderThan, e := time.ParseDuration(ctx.String("older-than"))
fatalIf(probe.NewError(e), "Unable to parse the passed older-than flag.")
// Fetch the server's address stored in config
_, _, hostCfg, err := expandAlias(aliasedURL)
if err != nil {
return err.ToGoError()
}
// Check if alias exists
if hostCfg == nil {
fatalIf(errInvalidAliasedURL(aliasedURL).Trace(aliasedURL), "The specified alias is not found.")
}
// Parse the server address
url, e := url.Parse(hostCfg.URL)
if e != nil {
return e
}
isSSL := (url.Scheme == "https")
// Create a new Minio Admin Client
client, e := madmin.New(url.Host, hostCfg.AccessKey, hostCfg.SecretKey, isSSL)
if e != nil {
return e
}
aliasedURL = filepath.ToSlash(aliasedURL)
splits := splitStr(aliasedURL, "/", 3)
// Clear locks related to a specified pair of bucket and prefix
locksInfo, e := client.ClearLocks(splits[1], splits[2], olderThan)
fatalIf(probe.NewError(e), "Cannot clear the specified locks.")
for _, l := range locksInfo {
printMsg(lockClearMessage{LockInfo: l})
}
return nil
}

157
cmd/admin-lock-list.go Normal file
View File

@@ -0,0 +1,157 @@
/*
* Minio Client (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 (
"encoding/json"
"fmt"
"net/url"
"path/filepath"
"time"
"github.com/minio/cli"
"github.com/minio/minio/pkg/madmin"
"github.com/minio/minio/pkg/probe"
)
var (
adminLockListFlags = []cli.Flag{
cli.StringFlag{
Name: "older-than, o",
Usage: "Only show locks that are older than a specified time, i.e. 30s",
Value: "0s",
},
}
)
var adminLockListCmd = cli.Command{
Name: "list",
Usage: "Get the list of locks hold in a given Minio server",
Action: mainAdminLockList,
Flags: append(adminLockListFlags, globalFlags...),
CustomHelpTemplate: `NAME:
mc admin lock {{.Name}} - {{.Usage}}
USAGE:
mc admin lock {{.Name}} ALIAS/BUCKET/PREFIX
FLAGS:
{{range .Flags}}{{.}}
{{end}}
EXAMPLES:
1. List hold locks related to testbucket in a Minio server represented by its alias 'play'.
$ mc admin lock {{.Name}} play/testbucket/
2. List locks that are hold for more than 15 minutes.
$ mc admin lock {{.Name}} --older-than 15m play/testbucket/
3. List locks hold by all objects under dir prefix
$ mc admin lock {{.Name}} play/testbucket/dir/
`,
}
// lockListMessage container to hold locks information.
type lockListMessage struct {
Status string `json:"status"`
LockInfo madmin.VolumeLockInfo `json:"volumeLockInfo"`
}
// String colorized service status message.
func (u lockListMessage) String() string {
msg := fmt.Sprintf("%s/%s (LocksOnObject: %d, locksAcquiredOnObject: %d, totalBlockLocks:%d): ",
u.LockInfo.Bucket,
u.LockInfo.Object,
u.LockInfo.LocksOnObject,
u.LockInfo.LocksAcquiredOnObject,
u.LockInfo.TotalBlockedLocks)
for _, detail := range u.LockInfo.LockDetailsOnObject {
msg += fmt.Sprintf(" %+v", detail)
}
msg += "\n"
return msg
}
// JSON jsonified service status Message message.
func (u lockListMessage) JSON() string {
u.Status = "success"
statusJSONBytes, e := json.Marshal(u)
fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
return string(statusJSONBytes)
}
// checkAdminLockListSyntax - validate all the passed arguments
func checkAdminLockListSyntax(ctx *cli.Context) {
if len(ctx.Args()) == 0 || len(ctx.Args()) > 2 {
cli.ShowCommandHelpAndExit(ctx, "list", 1) // last argument is exit code
}
}
func mainAdminLockList(ctx *cli.Context) error {
setGlobalsFromContext(ctx)
checkAdminLockListSyntax(ctx)
// Get the alias parameter from cli
args := ctx.Args()
aliasedURL := args.Get(0)
// Parse older-than flag
olderThan, e := time.ParseDuration(ctx.String("older-than"))
fatalIf(probe.NewError(e), "Unable to parse the passed older-than flag.")
// Fetch the server's address stored in config
_, _, hostCfg, err := expandAlias(aliasedURL)
if err != nil {
return err.ToGoError()
}
// Check if alias exists
if hostCfg == nil {
fatalIf(errInvalidAliasedURL(aliasedURL).Trace(aliasedURL), "The specified alias is not found.")
}
// Parse the server address
url, e := url.Parse(hostCfg.URL)
if e != nil {
return e
}
isSSL := (url.Scheme == "https")
// Create a new Minio Admin Client
client, e := madmin.New(url.Host, hostCfg.AccessKey, hostCfg.SecretKey, isSSL)
if e != nil {
return e
}
aliasedURL = filepath.ToSlash(aliasedURL)
splits := splitStr(aliasedURL, "/", 3)
// Fetch the lock info related to a specified pair of bucket and prefix
locksInfo, e := client.ListLocks(splits[1], splits[2], olderThan)
fatalIf(probe.NewError(e), "Cannot get lock status.")
for _, l := range locksInfo {
printMsg(lockListMessage{LockInfo: l})
}
return nil
}

63
cmd/admin-lock.go Normal file
View File

@@ -0,0 +1,63 @@
/*
* Minio Client (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 "github.com/minio/cli"
var (
adminLockFlags = []cli.Flag{}
)
var adminLockCmd = cli.Command{
Name: "lock",
Usage: "Control locks in servers.",
Action: mainAdminLock,
Flags: append(adminLockFlags, globalFlags...),
Subcommands: []cli.Command{
adminLockListCmd,
adminLockClearCmd,
},
CustomHelpTemplate: `NAME:
{{.Name}} - {{.Usage}}
USAGE:
{{.Name}} [FLAGS] COMMAND
FLAGS:
{{range .Flags}}{{.}}
{{end}}
COMMANDS:
{{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
{{end}}
`,
}
// mainAdminLock is the handle for "mc admin lock" command.
func mainAdminLock(ctx *cli.Context) error {
// Set global flags from context.
setGlobalsFromContext(ctx)
if ctx.Args().First() != "" { // command help.
cli.ShowCommandHelp(ctx, ctx.Args().First())
} else {
// command with Subcommands is an App.
cli.ShowAppHelp(ctx)
}
return nil
// Sub-commands like "list", "unlock" have their own main.
}

View File

@@ -29,6 +29,7 @@ var adminCmd = cli.Command{
Flags: append(adminFlags, globalFlags...), Flags: append(adminFlags, globalFlags...),
Subcommands: []cli.Command{ Subcommands: []cli.Command{
adminServiceCmd, adminServiceCmd,
adminLockCmd,
}, },
CustomHelpTemplate: `NAME: CustomHelpTemplate: `NAME:
{{.Name}} - {{.Usage}} {{.Name}} - {{.Usage}}

View File

@@ -920,19 +920,8 @@ func (c *s3Client) url2BucketAndObject() (bucketName, objectName string) {
path = string(c.targetURL.Separator) + bucket + c.targetURL.Path path = string(c.targetURL.Separator) + bucket + c.targetURL.Path
} }
} }
splits := strings.SplitN(path, string(c.targetURL.Separator), 3) tokens := splitStr(path, string(c.targetURL.Separator), 3)
switch len(splits) { return tokens[1], tokens[2]
case 0, 1:
bucketName = ""
objectName = ""
case 2:
bucketName = splits[1]
objectName = ""
case 3:
bucketName = splits[1]
objectName = splits[2]
}
return bucketName, objectName
} }
// splitPath split path into bucket and object. // splitPath split path into bucket and object.
@@ -955,13 +944,8 @@ func (c *s3Client) splitPath(path string) (bucketName, objectName string) {
} }
} }
tokens := strings.SplitN(path, string(c.targetURL.Separator), 2) tokens := splitStr(path, string(c.targetURL.Separator), 2)
bucketName = tokens[0] return tokens[0], tokens[1]
if len(tokens) == 2 {
objectName = tokens[1]
}
return bucketName, objectName
} }
/// Bucket API operations. /// Bucket API operations.

View File

@@ -21,6 +21,7 @@ import (
"io" "io"
"math/rand" "math/rand"
"os" "os"
"strings"
"time" "time"
"github.com/minio/mc/pkg/console" "github.com/minio/mc/pkg/console"
@@ -75,3 +76,14 @@ func dumpTLSCertificates(t *tls.ConnectionState) {
func isStdIO(reader io.Reader) bool { func isStdIO(reader io.Reader) bool {
return reader == os.Stdin || reader == os.Stdout || reader == os.Stderr return reader == os.Stdin || reader == os.Stdout || reader == os.Stderr
} }
// splitStr splits a string into n parts, empty strings are added
// if we are not able to reach n elements
func splitStr(path, sep string, n int) []string {
splits := strings.SplitN(path, sep, n)
// Add empty strings if we found elements less than nr
for i := n - len(splits); i > 0; i-- {
splits = append(splits, "")
}
return splits
}

View File

@@ -0,0 +1,47 @@
// +build ignore
/*
* 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 (
"log"
"time"
"github.com/minio/minio/pkg/madmin"
)
func main() {
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are
// dummy values, please replace them with original values.
// API requests are secure (HTTPS) if secure=true and insecure (HTTPS) otherwise.
// New returns an Minio Admin client object.
madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true)
if err != nil {
log.Fatalln(err)
}
// Clear locks held on mybucket/myprefix older than olderThan seconds.
olderThan := time.Duration(30 * time.Second)
locksCleared, err := madmClnt.ClearLocks("mybucket", "myprefix", olderThan)
if err != nil {
log.Fatalln(err)
}
log.Println(locksCleared)
}

View File

@@ -0,0 +1,46 @@
// +build ignore
/*
* 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 (
"log"
"time"
"github.com/minio/minio/pkg/madmin"
)
func main() {
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are
// dummy values, please replace them with original values.
// API requests are secure (HTTPS) if secure=true and insecure (HTTPS) otherwise.
// New returns an Minio Admin client object.
madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true)
if err != nil {
log.Fatalln(err)
}
// List locks held on mybucket/myprefix older than 30s.
locksHeld, err := madmClnt.ListLocks("mybucket", "myprefix", time.Duration(30*time.Second))
if err != nil {
log.Fatalln(err)
}
log.Println(locksHeld)
}

View File

@@ -0,0 +1,44 @@
// +build ignore
/*
* 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 (
"log"
"github.com/minio/minio/pkg/madmin"
)
func main() {
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are
// dummy values, please replace them with original values.
// API requests are secure (HTTPS) if secure=true and insecure (HTTPS) otherwise.
// New returns an Minio Admin client object.
madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true)
if err != nil {
log.Fatalln(err)
}
err = madmClnt.ServiceRestart()
if err != nil {
log.Fatalln(err)
}
log.Println("Success")
}

View File

@@ -0,0 +1,44 @@
// +build ignore
/*
* 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 (
"log"
"github.com/minio/minio/pkg/madmin"
)
func main() {
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
// dummy values, please replace them with original values.
// API requests are secure (HTTPS) if secure=true and insecure (HTTPS) otherwise.
// New returns an Minio Admin client object.
madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true)
if err != nil {
log.Fatalln(err)
}
st, err := madmClnt.ServiceStatus()
if err != nil {
log.Fatalln(err)
}
log.Println(st)
}

View File

@@ -0,0 +1,44 @@
// +build ignore
/*
* 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 (
"log"
"github.com/minio/minio/pkg/madmin"
)
func main() {
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
// dummy values, please replace them with original values.
// API requests are secure (HTTPS) if secure=true and insecure (HTTPS) otherwise.
// New returns an Minio Admin client object.
madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true)
if err != nil {
log.Fatalln(err)
}
err = madmClnt.ServiceStop()
if err != nil {
log.Fatalln(err)
}
log.Println("Success")
}

View File

@@ -0,0 +1,151 @@
/*
* 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 madmin
import (
"encoding/json"
"errors"
"io"
"io/ioutil"
"net/http"
"net/url"
"time"
)
type statusType string
const (
runningStatus statusType = "Running"
blockedStatus statusType = "Blocked"
)
type lockType string
const (
debugRLockStr lockType = "RLock"
debugWLockStr lockType = "WLock"
)
// OpsLockState - represents lock specific details.
type OpsLockState struct {
OperationID string `json:"opsID"` // String containing operation ID.
LockSource string `json:"lockSource"` // Operation type (GetObject, PutObject...)
LockType lockType `json:"lockType"` // Lock type (RLock, WLock)
Status statusType `json:"status"` // Status can be Running/Ready/Blocked.
Since time.Time `json:"statusSince"` // Time when the lock was initially held.
Duration time.Duration `json:"statusDuration"` // Duration since the lock was held.
}
// VolumeLockInfo - represents summary and individual lock details of all
// locks held on a given bucket, object.
type VolumeLockInfo struct {
Bucket string `json:"bucket"`
Object string `json:"object"`
// All locks blocked + running for given <volume,path> pair.
LocksOnObject int64 `json:"locksOnObject"`
// Count of operations which has successfully acquired the lock
// but hasn't unlocked yet( operation in progress).
LocksAcquiredOnObject int64 `json:"locksAcquiredOnObject"`
// Count of operations which are blocked waiting for the lock
// to be released.
TotalBlockedLocks int64 `json:"locksBlockedOnObject"`
// State information containing state of the locks for all operations
// on given <volume,path> pair.
LockDetailsOnObject []OpsLockState `json:"lockDetailsOnObject"`
}
// getLockInfos - unmarshal []VolumeLockInfo from a reader.
func getLockInfos(body io.Reader) ([]VolumeLockInfo, error) {
respBytes, err := ioutil.ReadAll(body)
if err != nil {
return nil, err
}
var lockInfos []VolumeLockInfo
err = json.Unmarshal(respBytes, &lockInfos)
if err != nil {
return nil, err
}
return lockInfos, nil
}
// ListLocks - Calls List Locks Management API to fetch locks matching
// bucket, prefix and held before the duration supplied.
func (adm *AdminClient) ListLocks(bucket, prefix string, olderThan time.Duration) ([]VolumeLockInfo, error) {
queryVal := make(url.Values)
queryVal.Set("lock", "")
queryVal.Set("bucket", bucket)
queryVal.Set("prefix", prefix)
queryVal.Set("older-than", olderThan.String())
hdrs := make(http.Header)
hdrs.Set(minioAdminOpHeader, "list")
reqData := requestData{
queryValues: queryVal,
customHeaders: hdrs,
}
// Execute GET on /?lock to list locks.
resp, err := adm.executeMethod("GET", reqData)
defer closeResponse(resp)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, errors.New("Got HTTP Status: " + resp.Status)
}
return getLockInfos(resp.Body)
}
// ClearLocks - Calls Clear Locks Management API to clear locks held
// on bucket, matching prefix older than duration supplied.
func (adm *AdminClient) ClearLocks(bucket, prefix string, olderThan time.Duration) ([]VolumeLockInfo, error) {
queryVal := make(url.Values)
queryVal.Set("lock", "")
queryVal.Set("bucket", bucket)
queryVal.Set("prefix", prefix)
queryVal.Set("older-than", olderThan.String())
hdrs := make(http.Header)
hdrs.Set(minioAdminOpHeader, "clear")
reqData := requestData{
queryValues: queryVal,
customHeaders: hdrs,
}
// Execute POST on /?lock to clear locks.
resp, err := adm.executeMethod("POST", reqData)
defer closeResponse(resp)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, errors.New("Got HTTP Status: " + resp.Status)
}
return getLockInfos(resp.Body)
}

View File

@@ -77,7 +77,7 @@ func (adm *AdminClient) ServiceStatus() (ServiceStatusMetadata, error) {
} }
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return ServiceStatusMetadata{}, errors.New("Got " + resp.Status) return ServiceStatusMetadata{}, errors.New("Got HTTP Status: " + resp.Status)
} }
respBytes, err := ioutil.ReadAll(resp.Body) respBytes, err := ioutil.ReadAll(resp.Body)
@@ -113,7 +113,7 @@ func (adm *AdminClient) ServiceStop() error {
} }
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return errors.New("Got " + resp.Status) return errors.New("Got HTTP Status: " + resp.Status)
} }
return nil return nil
@@ -137,7 +137,7 @@ func (adm *AdminClient) ServiceRestart() error {
} }
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return errors.New("Got " + resp.Status) return errors.New("Got HTTP Status: " + resp.Status)
} }
return nil return nil
} }

6
vendor/vendor.json vendored
View File

@@ -80,10 +80,10 @@
"revisionTime": "2016-08-18T00:31:20Z" "revisionTime": "2016-08-18T00:31:20Z"
}, },
{ {
"checksumSHA1": "ObCt0PoF41PGfeNCcJS6McmiFNs=", "checksumSHA1": "5+Z11r2dweplJF0rTgmn1gtCsjw=",
"path": "github.com/minio/minio/pkg/madmin", "path": "github.com/minio/minio/pkg/madmin",
"revision": "f57f773189ec9eda37dbf5ffd8eb0372cf0a4b39", "revision": "c8f57133a4384ea98206560b691f50e7520007b9",
"revisionTime": "2016-12-21T02:49:48Z" "revisionTime": "2017-01-04T07:39:22Z"
}, },
{ {
"path": "github.com/minio/minio/pkg/probe", "path": "github.com/minio/minio/pkg/probe",