diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 2decb52cb..d57f7cebc 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -376,8 +376,7 @@ func (a adminAPIHandlers) PerfInfoHandler(w http.ResponseWriter, r *http.Request } } - storage := objectAPI.StorageInfo(ctx) - if !(storage.Backend.Type == BackendFS || storage.Backend.Type == BackendErasure) { + if !globalIsDistXL { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) return } diff --git a/cmd/peer-rest-server.go b/cmd/peer-rest-server.go index a35555dcc..5f437d281 100644 --- a/cmd/peer-rest-server.go +++ b/cmd/peer-rest-server.go @@ -921,8 +921,8 @@ func (s *peerRESTServer) IsValid(w http.ResponseWriter, r *http.Request) bool { func registerPeerRESTHandlers(router *mux.Router) { server := &peerRESTServer{} subrouter := router.PathPrefix(peerRESTPath).Subrouter() - subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodNetReadPerfInfo).HandlerFunc(httpTraceHdrs(server.NetReadPerfInfoHandler)) - subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodCollectNetPerfInfo).HandlerFunc(httpTraceHdrs(server.CollectNetPerfInfoHandler)) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodNetReadPerfInfo).HandlerFunc(httpTraceHdrs(server.NetReadPerfInfoHandler)).Queries(restQueries(peerRESTNetPerfSize)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodCollectNetPerfInfo).HandlerFunc(httpTraceHdrs(server.CollectNetPerfInfoHandler)).Queries(restQueries(peerRESTNetPerfSize)...) subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodGetLocks).HandlerFunc(httpTraceHdrs(server.GetLocksHandler)) subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodServerInfo).HandlerFunc(httpTraceHdrs(server.ServerInfoHandler)) subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodCPULoadInfo).HandlerFunc(httpTraceHdrs(server.CPULoadInfoHandler)) diff --git a/pkg/madmin/README.md b/pkg/madmin/README.md index 5b0dc9756..79879efa3 100644 --- a/pkg/madmin/README.md +++ b/pkg/madmin/README.md @@ -49,6 +49,7 @@ func main() { | [`ServiceStop`](#ServiceStop) | [`ServerCPULoadInfo`](#ServerCPULoadInfo) | | [`SetConfig`](#SetConfig) | | [`SetUserPolicy`](#SetUserPolicy) | [`StartProfiling`](#StartProfiling) | | | [`ServerMemUsageInfo`](#ServerMemUsageInfo) | | [`GetConfigKeys`](#GetConfigKeys) | | [`ListUsers`](#ListUsers) | [`DownloadProfilingData`](#DownloadProfilingData) | | [`ServiceTrace`](#ServiceTrace) | [`ServerDrivesPerfInfo`](#ServerDrivesPerfInfo) | | [`SetConfigKeys`](#SetConfigKeys) | | [`AddCannedPolicy`](#AddCannedPolicy) | [`ServerUpdate`](#ServerUpdate) | +| | [`NetPerfInfo`](#NetPerfInfo) | | | | | | ## 1. Constructor @@ -257,7 +258,7 @@ Fetches CPU utilization for all cluster nodes. | `cpu.Load.Avg` | _float64_ | The average utilization of the CPU measured in a 200ms interval | | `cpu.Load.Min` | _float64_ | The minimum utilization of the CPU measured in a 200ms interval | | `cpu.Load.Max` | _float64_ | The maximum utilization of the CPU measured in a 200ms interval | -| `cpu.Load.Error` | _string_ | Error (if any) encountered while accesing the CPU info | +| `cpu.Load.Error` | _string_ | Error (if any) encountered while accessing the CPU info | ### ServerMemUsageInfo() ([]ServerMemUsageInfo, error) @@ -273,7 +274,18 @@ Fetches Mem utilization for all cluster nodes. | Param | Type | Description | |-------------------|----------|--------------------------------------------------------| | `mem.Usage.Mem` | _uint64_ | The total number of bytes obtained from the OS | -| `mem.Usage.Error` | _string_ | Error (if any) encountered while accesing the CPU info | +| `mem.Usage.Error` | _string_ | Error (if any) encountered while accessing the CPU info | + + +### NetPerfInfo(int size) (map[string][]NetPerfInfo, error) + +Fetches network performance of all cluster nodes using given sized payload. Returned value is a map containing each node indexed list of performance of other nodes. + +| Param | Type | Description | +|------------|------------------|--------------------------------------------------------------------| +| `Addr` | _string_ | Address of the server the following information is retrieved from. | +| `Error` | _string_ | Errors (if any) encountered while reaching this node | +| `ReadPerf` | _time.Duration_ | Network read performance of the server | ## 5. Heal operations diff --git a/pkg/madmin/examples/net-perf-info.go b/pkg/madmin/examples/net-perf-info.go new file mode 100644 index 000000000..85da2ffcd --- /dev/null +++ b/pkg/madmin/examples/net-perf-info.go @@ -0,0 +1,44 @@ +// +build ignore + +/* + * MinIO Cloud Storage, (C) 2019 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 (HTTP) 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.NetPerfInfo(madmin.DefaultNetPerfSize) + if err != nil { + log.Fatalln(err) + } + log.Println(st) +} diff --git a/pkg/madmin/info-commands.go b/pkg/madmin/info-commands.go index 43ec3b4f2..920fe6422 100644 --- a/pkg/madmin/info-commands.go +++ b/pkg/madmin/info-commands.go @@ -19,16 +19,24 @@ package madmin import ( "encoding/json" + "errors" "io/ioutil" "net/http" "net/url" + "strconv" "time" + humanize "github.com/dustin/go-humanize" "github.com/minio/minio/pkg/cpu" "github.com/minio/minio/pkg/disk" "github.com/minio/minio/pkg/mem" ) +const ( + // DefaultNetPerfSize - default payload size used for network performance. + DefaultNetPerfSize = 100 * humanize.MiByte +) + // BackendType - represents different backend types. type BackendType int @@ -288,3 +296,52 @@ func (adm *AdminClient) ServerMemUsageInfo() ([]ServerMemUsageInfo, error) { return info, nil } + +// NetPerfInfo network performance information. +type NetPerfInfo struct { + Addr string `json:"addr"` + ReadPerf time.Duration `json:"readPerf"` + Error string `json:"error,omitempty"` +} + +// NetPerfInfo - Returns network performance information of all cluster nodes. +func (adm *AdminClient) NetPerfInfo(size int) (map[string][]NetPerfInfo, error) { + v := url.Values{} + v.Set("perfType", "net") + if size > 0 { + v.Set("size", strconv.Itoa(size)) + } + resp, err := adm.executeMethod("GET", requestData{ + relPath: "/v1/performance", + queryValues: v, + }) + + defer closeResponse(resp) + if err != nil { + return nil, err + } + + // Check response http status code + if resp.StatusCode == http.StatusMethodNotAllowed { + return nil, errors.New("NetPerfInfo is meant for multi-node MinIO deployments") + } + + if resp.StatusCode != http.StatusOK { + return nil, httpRespToErrorResponse(resp) + } + + // Unmarshal the server's json response + info := map[string][]NetPerfInfo{} + + respBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + err = json.Unmarshal(respBytes, &info) + if err != nil { + return nil, err + } + + return info, nil +}