diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index d0a262f48..92cebd38c 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -44,12 +44,10 @@ import ( "github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger/message/log" "github.com/minio/minio/pkg/auth" - "github.com/minio/minio/pkg/cpu" "github.com/minio/minio/pkg/event/target" "github.com/minio/minio/pkg/handlers" iampolicy "github.com/minio/minio/pkg/iam/policy" "github.com/minio/minio/pkg/madmin" - "github.com/minio/minio/pkg/mem" xnet "github.com/minio/minio/pkg/net" trace "github.com/minio/minio/pkg/trace" ) @@ -378,155 +376,6 @@ func (a adminAPIHandlers) AccountingUsageInfoHandler(w http.ResponseWriter, r *h writeSuccessResponseJSON(w, usageInfoJSON) } -// ServerCPULoadInfo holds informantion about cpu utilization -// of one minio node. It also reports any errors if encountered -// while trying to reach this server. -type ServerCPULoadInfo struct { - Addr string `json:"addr"` - Error string `json:"error,omitempty"` - Load []cpu.Load `json:"load"` - HistoricLoad []cpu.Load `json:"historicLoad"` -} - -// ServerMemUsageInfo holds informantion about memory utilization -// of one minio node. It also reports any errors if encountered -// while trying to reach this server. -type ServerMemUsageInfo struct { - Addr string `json:"addr"` - Error string `json:"error,omitempty"` - Usage []mem.Usage `json:"usage"` - HistoricUsage []mem.Usage `json:"historicUsage"` -} - -// ServerNetReadPerfInfo network read performance information. -type ServerNetReadPerfInfo struct { - Addr string `json:"addr"` - ReadThroughput uint64 `json:"readThroughput"` - Error string `json:"error,omitempty"` -} - -// PerfInfoHandler - GET /minio/admin/v3/performance?perfType={perfType} -// ---------- -// Get all performance information based on input type -// Supported types = drive -func (a adminAPIHandlers) PerfInfoHandler(w http.ResponseWriter, r *http.Request) { - ctx := newContext(r, w, "PerfInfo") - - objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.PerfInfoAdminAction) - if objectAPI == nil { - return - } - - vars := mux.Vars(r) - switch perfType := vars["perfType"]; perfType { - case "net": - var size int64 = defaultNetPerfSize - if sizeStr, found := vars["size"]; found { - var err error - if size, err = strconv.ParseInt(sizeStr, 10, 64); err != nil || size < 0 { - writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL) - return - } - } - - if !globalIsDistXL { - writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) - return - } - - addr := r.Host - if globalIsDistXL { - addr = GetLocalPeer(globalEndpoints) - } - - infos := map[string][]ServerNetReadPerfInfo{} - infos[addr] = globalNotificationSys.NetReadPerfInfo(size) - for peer, info := range globalNotificationSys.CollectNetPerfInfo(size) { - infos[peer] = info - } - - // Marshal API response - jsonBytes, err := json.Marshal(infos) - if err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return - } - - // Reply with performance information (across nodes in a - // distributed setup) as json. - writeSuccessResponseJSON(w, jsonBytes) - - case "drive": - // Drive Perf is only implemented for Erasure coded backends - if !globalIsXL { - writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) - return - } - - var size int64 = madmin.DefaultDrivePerfSize - if sizeStr, found := vars["size"]; found { - var err error - if size, err = strconv.ParseInt(sizeStr, 10, 64); err != nil || size <= 0 { - writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL) - return - } - } - // Get drive performance details from local server's drive(s) - dp := getLocalDrivesPerf(globalEndpoints, size, r) - - // Notify all other MinIO peers to report drive performance numbers - dps := globalNotificationSys.DrivePerfInfo(size) - dps = append(dps, dp) - - // Marshal API response - jsonBytes, err := json.Marshal(dps) - if err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return - } - - // Reply with performance information (across nodes in a - // distributed setup) as json. - writeSuccessResponseJSON(w, jsonBytes) - case "cpu": - // Get CPU load details from local server's cpu(s) - cpu := getLocalCPULoad(globalEndpoints, r) - // Notify all other MinIO peers to report cpu load numbers - cpus := globalNotificationSys.CPULoadInfo() - cpus = append(cpus, cpu) - - // Marshal API response - jsonBytes, err := json.Marshal(cpus) - if err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return - } - - // Reply with cpu load information (across nodes in a - // distributed setup) as json. - writeSuccessResponseJSON(w, jsonBytes) - case "mem": - // Get mem usage details from local server(s) - m := getLocalMemUsage(globalEndpoints, r) - // Notify all other MinIO peers to report mem usage numbers - mems := globalNotificationSys.MemUsageInfo() - mems = append(mems, m) - - // Marshal API response - jsonBytes, err := json.Marshal(mems) - if err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return - } - - // Reply with mem usage information (across nodes in a - // distributed setup) as json. - writeSuccessResponseJSON(w, jsonBytes) - default: - writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) - } -} - func newLockEntry(l lockRequesterInfo, resource, server string) *madmin.LockEntry { entry := &madmin.LockEntry{ Timestamp: l.Timestamp, @@ -1315,63 +1164,6 @@ func (a adminAPIHandlers) KMSKeyStatusHandler(w http.ResponseWriter, r *http.Req writeSuccessResponseJSON(w, resp) } -// ServerHardwareInfoHandler - GET /minio/admin/v3/hardwareinfo?Type={hwType} -// ---------- -// Get all hardware information based on input type -// Supported types = cpu -func (a adminAPIHandlers) ServerHardwareInfoHandler(w http.ResponseWriter, r *http.Request) { - ctx := newContext(r, w, "HardwareInfo") - - objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.ServerHardwareInfoAdminAction) - if objectAPI == nil { - return - } - - vars := mux.Vars(r) - hardware := vars[madmin.HARDWARE] - - switch madmin.HardwareType(hardware) { - case madmin.CPU: - // Get CPU hardware details from local server's cpu(s) - cpu := getLocalCPUInfo(globalEndpoints, r) - // Notify all other MinIO peers to report cpu hardware - cpus := globalNotificationSys.CPUInfo() - cpus = append(cpus, cpu) - - // Marshal API response - jsonBytes, err := json.Marshal(cpus) - if err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return - } - - // Reply with cpu hardware information (across nodes in a - // distributed setup) as json. - writeSuccessResponseJSON(w, jsonBytes) - - case madmin.NETWORK: - // Get Network hardware details from local server's network(s) - network := getLocalNetworkInfo(globalEndpoints, r) - // Notify all other MinIO peers to report network hardware - networks := globalNotificationSys.NetworkInfo() - networks = append(networks, network) - - // Marshal API response - jsonBytes, err := json.Marshal(networks) - if err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return - } - - // Reply with cpu network information (across nodes in a - // distributed setup) as json. - writeSuccessResponseJSON(w, jsonBytes) - - default: - writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL) - } -} - // OBDInfoHandler - GET /minio/admin/v3/obdinfo // ---------- // Get server on-board diagnostics diff --git a/cmd/admin-router.go b/cmd/admin-router.go index f26290d8e..2918fcc1a 100644 --- a/cmd/admin-router.go +++ b/cmd/admin-router.go @@ -56,8 +56,6 @@ func registerAdminRouter(router *mux.Router, enableConfigOps, enableIAMOps bool) // Info operations adminRouter.Methods(http.MethodGet).Path(adminVersion + "/info").HandlerFunc(httpTraceAll(adminAPI.ServerInfoHandler)) - // Harware Info operations - adminRouter.Methods(http.MethodGet).Path(adminVersion+"/hardware").HandlerFunc(httpTraceAll(adminAPI.ServerHardwareInfoHandler)).Queries("hwType", "{hwType:.*}") // StorageInfo operations adminRouter.Methods(http.MethodGet).Path(adminVersion + "/storageinfo").HandlerFunc(httpTraceAll(adminAPI.StorageInfoHandler)) @@ -79,8 +77,6 @@ func registerAdminRouter(router *mux.Router, enableConfigOps, enableIAMOps bool) /// Health operations } - // Performance command - return performance details based on input type - adminRouter.Methods(http.MethodGet).Path(adminVersion+"/performance").HandlerFunc(httpTraceAll(adminAPI.PerfInfoHandler)).Queries("perfType", "{perfType:.*}") // Profiling operations adminRouter.Methods(http.MethodPost).Path(adminVersion+"/profiling/start").HandlerFunc(httpTraceAll(adminAPI.StartProfilingHandler)). diff --git a/cmd/admin-server-info.go b/cmd/admin-server-info.go index e6ccaf6e7..d6f562658 100644 --- a/cmd/admin-server-info.go +++ b/cmd/admin-server-info.go @@ -17,176 +17,14 @@ package cmd import ( - "net" "net/http" "os" - "github.com/minio/minio-go/v6/pkg/set" - "github.com/minio/minio/pkg/cpu" "github.com/minio/minio/pkg/disk" "github.com/minio/minio/pkg/madmin" - "github.com/minio/minio/pkg/mem" - - cpuhw "github.com/shirou/gopsutil/cpu" ) -// getLocalMemUsage - returns ServerMemUsageInfo for all zones, endpoints. -func getLocalMemUsage(endpointZones EndpointZones, r *http.Request) ServerMemUsageInfo { - var memUsages []mem.Usage - var historicUsages []mem.Usage - seenHosts := set.NewStringSet() - for _, ep := range endpointZones { - for _, endpoint := range ep.Endpoints { - if seenHosts.Contains(endpoint.Host) { - continue - } - seenHosts.Add(endpoint.Host) - - // Only proceed for local endpoints - if endpoint.IsLocal { - memUsages = append(memUsages, mem.GetUsage()) - historicUsages = append(historicUsages, mem.GetHistoricUsage()) - } - } - } - addr := r.Host - if globalIsDistXL { - addr = GetLocalPeer(endpointZones) - } - return ServerMemUsageInfo{ - Addr: addr, - Usage: memUsages, - HistoricUsage: historicUsages, - } -} - -// getLocalCPULoad - returns ServerCPULoadInfo for all zones, endpoints. -func getLocalCPULoad(endpointZones EndpointZones, r *http.Request) ServerCPULoadInfo { - var cpuLoads []cpu.Load - var historicLoads []cpu.Load - seenHosts := set.NewStringSet() - for _, ep := range endpointZones { - for _, endpoint := range ep.Endpoints { - if seenHosts.Contains(endpoint.Host) { - continue - } - seenHosts.Add(endpoint.Host) - - // Only proceed for local endpoints - if endpoint.IsLocal { - cpuLoads = append(cpuLoads, cpu.GetLoad()) - historicLoads = append(historicLoads, cpu.GetHistoricLoad()) - } - } - } - addr := r.Host - if globalIsDistXL { - addr = GetLocalPeer(endpointZones) - } - return ServerCPULoadInfo{ - Addr: addr, - Load: cpuLoads, - HistoricLoad: historicLoads, - } -} - -// getLocalDrivesPerf - returns ServerDrivesPerfInfo for all zones, endpoints. -func getLocalDrivesPerf(endpointZones EndpointZones, size int64, r *http.Request) madmin.ServerDrivesPerfInfo { - var dps []disk.Performance - for _, ep := range endpointZones { - for _, endpoint := range ep.Endpoints { - // Only proceed for local endpoints - if endpoint.IsLocal { - if _, err := os.Stat(endpoint.Path); err != nil { - // Since this drive is not available, add relevant details and proceed - dps = append(dps, disk.Performance{Path: endpoint.Path, Error: err.Error()}) - continue - } - dp := disk.GetPerformance(pathJoin(endpoint.Path, minioMetaTmpBucket, mustGetUUID()), size) - dp.Path = endpoint.Path - dps = append(dps, dp) - } - } - } - addr := r.Host - if globalIsDistXL { - addr = GetLocalPeer(endpointZones) - } - return madmin.ServerDrivesPerfInfo{ - Addr: addr, - Perf: dps, - } -} - -// getLocalCPUInfo - returns ServerCPUHardwareInfo for all zones, endpoints. -func getLocalCPUInfo(endpointZones EndpointZones, r *http.Request) madmin.ServerCPUHardwareInfo { - var cpuHardwares []cpuhw.InfoStat - seenHosts := set.NewStringSet() - for _, ep := range endpointZones { - for _, endpoint := range ep.Endpoints { - if seenHosts.Contains(endpoint.Host) { - continue - } - // Add to the list of visited hosts - seenHosts.Add(endpoint.Host) - // Only proceed for local endpoints - if endpoint.IsLocal { - cpuHardware, err := cpuhw.Info() - if err != nil { - return madmin.ServerCPUHardwareInfo{ - Error: err.Error(), - } - } - cpuHardwares = append(cpuHardwares, cpuHardware...) - } - } - } - addr := r.Host - if globalIsDistXL { - addr = GetLocalPeer(endpointZones) - } - - return madmin.ServerCPUHardwareInfo{ - Addr: addr, - CPUInfo: cpuHardwares, - } -} - -// getLocalNetworkInfo - returns ServerNetworkHardwareInfo for all zones, endpoints. -func getLocalNetworkInfo(endpointZones EndpointZones, r *http.Request) madmin.ServerNetworkHardwareInfo { - var networkHardwares []net.Interface - seenHosts := set.NewStringSet() - for _, ep := range endpointZones { - for _, endpoint := range ep.Endpoints { - if seenHosts.Contains(endpoint.Host) { - continue - } - // Add to the list of visited hosts - seenHosts.Add(endpoint.Host) - // Only proceed for local endpoints - if endpoint.IsLocal { - networkHardware, err := net.Interfaces() - if err != nil { - return madmin.ServerNetworkHardwareInfo{ - Error: err.Error(), - } - } - networkHardwares = append(networkHardwares, networkHardware...) - } - } - } - addr := r.Host - if globalIsDistXL { - addr = GetLocalPeer(endpointZones) - } - - return madmin.ServerNetworkHardwareInfo{ - Addr: addr, - NetworkInfo: networkHardwares, - } -} - -// getLocalServerProperty - returns ServerDrivesPerfInfo for only the +// getLocalServerProperty - returns madmin.ServerProperties for only the // local endpoints from given list of endpoints func getLocalServerProperty(endpointZones EndpointZones, r *http.Request) madmin.ServerProperties { var disks []madmin.Disk diff --git a/cmd/notification.go b/cmd/notification.go index 6d426dd20..caaf6b24d 100644 --- a/cmd/notification.go +++ b/cmd/notification.go @@ -830,55 +830,6 @@ func (sys *NotificationSys) PutBucketObjectLockConfig(ctx context.Context, bucke } } -// NetReadPerfInfo - Network read performance information. -func (sys *NotificationSys) NetReadPerfInfo(size int64) []ServerNetReadPerfInfo { - reply := make([]ServerNetReadPerfInfo, len(sys.peerClients)) - - // Execution is done serially. - for i, client := range sys.peerClients { - if client == nil { - continue - } - - info, err := client.NetReadPerfInfo(size) - if err != nil { - reqInfo := (&logger.ReqInfo{}).AppendTags("remotePeer", client.host.String()) - ctx := logger.SetReqInfo(GlobalContext, reqInfo) - logger.LogIf(ctx, err) - - info.Addr = client.host.String() - info.Error = err.Error() - } - - reply[i] = info - } - - return reply -} - -// CollectNetPerfInfo - Collect network performance information of all peers. -func (sys *NotificationSys) CollectNetPerfInfo(size int64) map[string][]ServerNetReadPerfInfo { - reply := map[string][]ServerNetReadPerfInfo{} - - // Execution is done serially. - for _, client := range sys.peerClients { - if client == nil { - continue - } - - info, err := client.CollectNetPerfInfo(size) - if err != nil { - reqInfo := (&logger.ReqInfo{}).AppendTags("remotePeer", client.host.String()) - ctx := logger.SetReqInfo(GlobalContext, reqInfo) - logger.LogIf(ctx, err) - } - - reply[client.host.String()] = info - } - - return reply -} - // NetOBDInfo - Net OBD information func (sys *NotificationSys) NetOBDInfo(ctx context.Context) madmin.ServerNetOBDInfo { var sortedGlobalEndpoints []string @@ -1188,142 +1139,6 @@ func (sys *NotificationSys) ProcOBDInfo(ctx context.Context) []madmin.ServerProc return reply } -// DrivePerfInfo - Drive speed (read and write) information -func (sys *NotificationSys) DrivePerfInfo(size int64) []madmin.ServerDrivesPerfInfo { - reply := make([]madmin.ServerDrivesPerfInfo, len(sys.peerClients)) - - g := errgroup.WithNErrs(len(sys.peerClients)) - for index, client := range sys.peerClients { - if client == nil { - continue - } - index := index - g.Go(func() error { - var err error - reply[index], err = sys.peerClients[index].DrivePerfInfo(size) - return err - }, index) - } - - for index, err := range g.Wait() { - if err != nil { - addr := sys.peerClients[index].host.String() - reqInfo := (&logger.ReqInfo{}).AppendTags("remotePeer", addr) - ctx := logger.SetReqInfo(GlobalContext, reqInfo) - logger.LogIf(ctx, err) - reply[index].Addr = addr - reply[index].Error = err.Error() - } - } - return reply -} - -// MemUsageInfo - Mem utilization information -func (sys *NotificationSys) MemUsageInfo() []ServerMemUsageInfo { - reply := make([]ServerMemUsageInfo, len(sys.peerClients)) - - g := errgroup.WithNErrs(len(sys.peerClients)) - for index, client := range sys.peerClients { - if client == nil { - continue - } - index := index - g.Go(func() error { - var err error - reply[index], err = sys.peerClients[index].MemUsageInfo() - return err - }, index) - } - - for index, err := range g.Wait() { - if err != nil { - addr := sys.peerClients[index].host.String() - reqInfo := (&logger.ReqInfo{}).AppendTags("remotePeer", addr) - ctx := logger.SetReqInfo(GlobalContext, reqInfo) - logger.LogIf(ctx, err) - reply[index].Addr = addr - reply[index].Error = err.Error() - } - } - return reply -} - -// CPULoadInfo - CPU utilization information -func (sys *NotificationSys) CPULoadInfo() []ServerCPULoadInfo { - reply := make([]ServerCPULoadInfo, len(sys.peerClients)) - - g := errgroup.WithNErrs(len(sys.peerClients)) - for index, client := range sys.peerClients { - if client == nil { - continue - } - index := index - g.Go(func() error { - var err error - reply[index], err = sys.peerClients[index].CPULoadInfo() - return err - }, index) - } - - for index, err := range g.Wait() { - if err != nil { - addr := sys.peerClients[index].host.String() - reqInfo := (&logger.ReqInfo{}).AppendTags("remotePeer", addr) - ctx := logger.SetReqInfo(GlobalContext, reqInfo) - logger.LogIf(ctx, err) - reply[index].Addr = addr - reply[index].Error = err.Error() - } - } - return reply -} - -// CPUInfo - CPU Hardware info -func (sys *NotificationSys) CPUInfo() []madmin.ServerCPUHardwareInfo { - reply := make([]madmin.ServerCPUHardwareInfo, len(sys.peerClients)) - var wg sync.WaitGroup - for i, client := range sys.peerClients { - if client == nil { - continue - } - wg.Add(1) - go func(client *peerRESTClient, idx int) { - defer wg.Done() - cpui, err := client.CPUInfo() - if err != nil { - cpui.Addr = client.host.String() - cpui.Error = err.Error() - } - reply[idx] = cpui - }(client, i) - } - wg.Wait() - return reply -} - -// NetworkInfo - Network Hardware info -func (sys *NotificationSys) NetworkInfo() []madmin.ServerNetworkHardwareInfo { - reply := make([]madmin.ServerNetworkHardwareInfo, len(sys.peerClients)) - var wg sync.WaitGroup - for i, client := range sys.peerClients { - if client == nil { - continue - } - wg.Add(1) - go func(client *peerRESTClient, idx int) { - defer wg.Done() - netinfo, err := client.NetworkInfo() - if err != nil { - netinfo.Addr = client.host.String() - netinfo.Error = err.Error() - } - reply[idx] = netinfo - }(client, i) - } - wg.Wait() - return reply -} - // ServerInfo - calls ServerInfo RPC call on all peers. func (sys *NotificationSys) ServerInfo() []madmin.ServerProperties { reply := make([]madmin.ServerProperties, len(sys.peerClients)) diff --git a/cmd/obdinfo.go b/cmd/obdinfo.go index 91ede483b..3f22c6d4a 100644 --- a/cmd/obdinfo.go +++ b/cmd/obdinfo.go @@ -80,16 +80,16 @@ func getLocalDrivesOBD(ctx context.Context, parallel bool, endpointZones Endpoin }) continue } + measurePath := pathJoin(minioMetaTmpBucket, mustGetUUID()) measure := func(index int, path string) { - latency, throughput, err := disk.GetOBDInfo(ctx, pathJoin(endpoint.Path, minioMetaTmpBucket, mustGetUUID())) - driveOBDInfo := madmin.DriveOBDInfo{ - Path: path, - Latency: latency, - Throughput: throughput, - } + var driveOBDInfo madmin.DriveOBDInfo + latency, throughput, err := disk.GetOBDInfo(ctx, path, pathJoin(path, measurePath)) if err != nil { driveOBDInfo.Error = err.Error() } + driveOBDInfo.Path = path + driveOBDInfo.Latency = latency + driveOBDInfo.Throughput = throughput drivesOBDInfo = append(drivesOBDInfo, driveOBDInfo) wg.Done() } diff --git a/cmd/peer-rest-client.go b/cmd/peer-rest-client.go index c1fcabdc0..33cf7607d 100644 --- a/cmd/peer-rest-client.go +++ b/cmd/peer-rest-client.go @@ -24,13 +24,13 @@ import ( "io" "io/ioutil" "math" - "math/rand" "net/url" "strconv" "sync" "sync/atomic" "time" + "github.com/dustin/go-humanize" "github.com/minio/minio/cmd/http" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/rest" @@ -44,12 +44,6 @@ import ( trace "github.com/minio/minio/pkg/trace" ) -const ( - kiB int64 = 1 << 10 - miB int64 = kiB << 10 - giB int64 = miB << 10 -) - // client to talk to peer Nodes. type peerRESTClient struct { host *xnet.Host @@ -113,37 +107,6 @@ func (client *peerRESTClient) Close() error { // GetLocksResp stores various info from the client for each lock that is requested. type GetLocksResp []map[string][]lockRequesterInfo -// NetReadPerfInfo - fetch network read performance information for a remote node. -func (client *peerRESTClient) NetReadPerfInfo(size int64) (info ServerNetReadPerfInfo, err error) { - params := make(url.Values) - params.Set(peerRESTNetPerfSize, strconv.FormatInt(size, 10)) - respBody, err := client.call( - peerRESTMethodNetReadPerfInfo, - params, - rand.New(rand.NewSource(time.Now().UnixNano())), - size, - ) - if err != nil { - return - } - defer http.DrainBody(respBody) - err = gob.NewDecoder(respBody).Decode(&info) - return info, err -} - -// CollectNetPerfInfo - collect network performance information of other peers. -func (client *peerRESTClient) CollectNetPerfInfo(size int64) (info []ServerNetReadPerfInfo, err error) { - params := make(url.Values) - params.Set(peerRESTNetPerfSize, strconv.FormatInt(size, 10)) - respBody, err := client.call(peerRESTMethodCollectNetPerfInfo, params, nil, -1) - if err != nil { - return - } - defer http.DrainBody(respBody) - err = gob.NewDecoder(respBody).Decode(&info) - return info, err -} - // GetLocks - fetch older locks for a remote node. func (client *peerRESTClient) GetLocks() (locks GetLocksResp, err error) { respBody, err := client.call(peerRESTMethodGetLocks, nil, nil, -1) @@ -166,39 +129,6 @@ func (client *peerRESTClient) ServerInfo() (info madmin.ServerProperties, err er return info, err } -// CPULoadInfo - fetch CPU information for a remote node. -func (client *peerRESTClient) CPULoadInfo() (info ServerCPULoadInfo, err error) { - respBody, err := client.call(peerRESTMethodCPULoadInfo, nil, nil, -1) - if err != nil { - return - } - defer http.DrainBody(respBody) - err = gob.NewDecoder(respBody).Decode(&info) - return info, err -} - -// CPUInfo - fetch CPU hardware information for a remote node. -func (client *peerRESTClient) CPUInfo() (info madmin.ServerCPUHardwareInfo, err error) { - respBody, err := client.call(peerRESTMethodHardwareCPUInfo, nil, nil, -1) - if err != nil { - return - } - defer http.DrainBody(respBody) - err = gob.NewDecoder(respBody).Decode(&info) - return info, err -} - -// NetworkInfo - fetch network hardware information for a remote node. -func (client *peerRESTClient) NetworkInfo() (info madmin.ServerNetworkHardwareInfo, err error) { - respBody, err := client.call(peerRESTMethodHardwareNetworkInfo, nil, nil, -1) - if err != nil { - return - } - defer http.DrainBody(respBody) - err = gob.NewDecoder(respBody).Decode(&info) - return info, err -} - type networkOverloadedErr struct{} var networkOverloaded networkOverloadedErr @@ -338,11 +268,11 @@ func (client *peerRESTClient) doNetOBDTest(ctx context.Context, dataSize int64, } func maxLatencyForSizeThreads(size int64, threadCount uint) float64 { - Gbit100 := 12.5 * float64(giB) - Gbit40 := 5.00 * float64(giB) - Gbit25 := 3.25 * float64(giB) - Gbit10 := 1.25 * float64(giB) - // Gbit1 := 0.25 * float64(giB) + Gbit100 := 12.5 * float64(humanize.GiByte) + Gbit40 := 5.00 * float64(humanize.GiByte) + Gbit25 := 3.25 * float64(humanize.GiByte) + Gbit10 := 1.25 * float64(humanize.GiByte) + // Gbit1 := 0.25 * float64(humanize.GiByte) // Given the current defaults, each combination of size/thread // is supposed to fully saturate the intended pipe when all threads are active @@ -391,23 +321,23 @@ func (client *peerRESTClient) NetOBDInfo(ctx context.Context) (info madmin.NetOB } steps := []step{ { // 100 Gbit - size: 256 * miB, + size: 256 * humanize.MiByte, threads: 50, }, { // 40 Gbit - size: 256 * miB, + size: 256 * humanize.MiByte, threads: 20, }, { // 25 Gbit - size: 128 * miB, + size: 128 * humanize.MiByte, threads: 25, }, { // 10 Gbit - size: 128 * miB, + size: 128 * humanize.MiByte, threads: 10, }, { // 1 Gbit - size: 64 * miB, + size: 64 * humanize.MiByte, threads: 2, }, } @@ -514,30 +444,6 @@ func (client *peerRESTClient) ProcOBDInfo(ctx context.Context) (info madmin.Serv return info, err } -// DrivePerfInfo - fetch Drive performance information for a remote node. -func (client *peerRESTClient) DrivePerfInfo(size int64) (info madmin.ServerDrivesPerfInfo, err error) { - params := make(url.Values) - params.Set(peerRESTDrivePerfSize, strconv.FormatInt(size, 10)) - respBody, err := client.call(peerRESTMethodDrivePerfInfo, params, nil, -1) - if err != nil { - return - } - defer http.DrainBody(respBody) - err = gob.NewDecoder(respBody).Decode(&info) - return info, err -} - -// MemUsageInfo - fetch memory usage information for a remote node. -func (client *peerRESTClient) MemUsageInfo() (info ServerMemUsageInfo, err error) { - respBody, err := client.call(peerRESTMethodMemUsageInfo, nil, nil, -1) - if err != nil { - return - } - defer http.DrainBody(respBody) - err = gob.NewDecoder(respBody).Decode(&info) - return info, err -} - // StartProfiling - Issues profiling command on the peer node. func (client *peerRESTClient) StartProfiling(profiler string) error { values := make(url.Values) diff --git a/cmd/peer-rest-common.go b/cmd/peer-rest-common.go index e7e8bb40a..077b6dec5 100644 --- a/cmd/peer-rest-common.go +++ b/cmd/peer-rest-common.go @@ -24,12 +24,7 @@ const ( ) const ( - peerRESTMethodNetReadPerfInfo = "/netreadperfinfo" - peerRESTMethodCollectNetPerfInfo = "/collectnetperfinfo" peerRESTMethodServerInfo = "/serverinfo" - peerRESTMethodCPULoadInfo = "/cpuloadinfo" - peerRESTMethodMemUsageInfo = "/memusageinfo" - peerRESTMethodDrivePerfInfo = "/driveperfinfo" peerRESTMethodDriveOBDInfo = "/driveobdinfo" peerRESTMethodNetOBDInfo = "/netobdinfo" peerRESTMethodCPUOBDInfo = "/cpuobdinfo" @@ -66,8 +61,6 @@ const ( peerRESTMethodBucketEncryptionSet = "/setbucketencryption" peerRESTMethodBucketEncryptionRemove = "/removebucketencryption" peerRESTMethodLog = "/log" - peerRESTMethodHardwareCPUInfo = "/cpuhardwareinfo" - peerRESTMethodHardwareNetworkInfo = "/networkhardwareinfo" peerRESTMethodPutBucketObjectLockConfig = "/putbucketobjectlockconfig" peerRESTMethodBucketObjectLockConfigRemove = "/removebucketobjectlockconfig" ) diff --git a/cmd/peer-rest-server.go b/cmd/peer-rest-server.go index 84845577f..f971ad8f9 100644 --- a/cmd/peer-rest-server.go +++ b/cmd/peer-rest-server.go @@ -65,84 +65,6 @@ func getServerInfo() (*ServerInfoData, error) { }, nil } -// NetReadPerfInfoHandler - returns network read performance information. -func (s *peerRESTServer) NetReadPerfInfoHandler(w http.ResponseWriter, r *http.Request) { - if !s.IsValid(w, r) { - s.writeErrorResponse(w, errors.New("Invalid request")) - return - } - - params := mux.Vars(r) - - sizeStr, found := params[peerRESTNetPerfSize] - if !found { - s.writeErrorResponse(w, errors.New("size is missing")) - return - } - - size, err := strconv.ParseInt(sizeStr, 10, 64) - if err != nil || size < 0 { - s.writeErrorResponse(w, errInvalidArgument) - return - } - - start := time.Now() - n, err := io.CopyN(ioutil.Discard, r.Body, size) - end := time.Now() - - if err != nil { - s.writeErrorResponse(w, err) - return - } - - if n != size { - s.writeErrorResponse(w, fmt.Errorf("short read; expected: %v, got: %v", size, n)) - return - } - - addr := r.Host - if globalIsDistXL { - addr = GetLocalPeer(globalEndpoints) - } - - d := end.Sub(start) - info := ServerNetReadPerfInfo{ - Addr: addr, - ReadThroughput: uint64(int64(time.Second) * size / int64(d)), - } - - ctx := newContext(r, w, "NetReadPerfInfo") - logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) - w.(http.Flusher).Flush() -} - -// CollectNetPerfInfoHandler - returns network performance information collected from other peers. -func (s *peerRESTServer) CollectNetPerfInfoHandler(w http.ResponseWriter, r *http.Request) { - if !s.IsValid(w, r) { - s.writeErrorResponse(w, errors.New("Invalid request")) - return - } - - params := mux.Vars(r) - sizeStr, found := params[peerRESTNetPerfSize] - if !found { - s.writeErrorResponse(w, errors.New("size is missing")) - return - } - - size, err := strconv.ParseInt(sizeStr, 10, 64) - if err != nil || size < 0 { - s.writeErrorResponse(w, errInvalidArgument) - return - } - - info := globalNotificationSys.NetReadPerfInfo(size) - - ctx := newContext(r, w, "CollectNetPerfInfo") - logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) - w.(http.Flusher).Flush() -} - // GetLocksHandler - returns list of older lock from the server. func (s *peerRESTServer) GetLocksHandler(w http.ResponseWriter, r *http.Request) { if !s.IsValid(w, r) { @@ -427,48 +349,6 @@ func (s *peerRESTServer) DownloadProfilingDataHandler(w http.ResponseWriter, r * logger.LogIf(ctx, gob.NewEncoder(w).Encode(profileData)) } -// CPULoadInfoHandler - returns CPU Load info. -func (s *peerRESTServer) CPULoadInfoHandler(w http.ResponseWriter, r *http.Request) { - if !s.IsValid(w, r) { - s.writeErrorResponse(w, errors.New("Invalid request")) - return - } - - ctx := newContext(r, w, "CPULoadInfo") - info := getLocalCPULoad(globalEndpoints, r) - - defer w.(http.Flusher).Flush() - logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) -} - -// CPUInfoHandler - returns CPU Hardware info. -func (s *peerRESTServer) CPUInfoHandler(w http.ResponseWriter, r *http.Request) { - if !s.IsValid(w, r) { - s.writeErrorResponse(w, errors.New("Invalid request")) - return - } - - ctx := newContext(r, w, "CPUInfo") - info := getLocalCPUInfo(globalEndpoints, r) - - defer w.(http.Flusher).Flush() - logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) -} - -// NetworkInfoHandler - returns Network Hardware info. -func (s *peerRESTServer) NetworkInfoHandler(w http.ResponseWriter, r *http.Request) { - if !s.IsValid(w, r) { - s.writeErrorResponse(w, errors.New("Invalid request")) - return - } - - ctx := newContext(r, w, "NetworkInfo") - info := getLocalNetworkInfo(globalEndpoints, r) - - defer w.(http.Flusher).Flush() - logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) -} - // ServerInfoHandler - returns Server Info func (s *peerRESTServer) ServerInfoHandler(w http.ResponseWriter, r *http.Request) { if !s.IsValid(w, r) { @@ -634,48 +514,6 @@ func (s *peerRESTServer) MemOBDInfoHandler(w http.ResponseWriter, r *http.Reques logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) } -// DrivePerfInfoHandler - returns Drive Performance info. -func (s *peerRESTServer) DrivePerfInfoHandler(w http.ResponseWriter, r *http.Request) { - if !s.IsValid(w, r) { - s.writeErrorResponse(w, errors.New("Invalid request")) - return - } - - params := mux.Vars(r) - - sizeStr, found := params[peerRESTDrivePerfSize] - if !found { - s.writeErrorResponse(w, errors.New("size is missing")) - return - } - - size, err := strconv.ParseInt(sizeStr, 10, 64) - if err != nil || size < 0 { - s.writeErrorResponse(w, errInvalidArgument) - return - } - - ctx := newContext(r, w, "DrivePerfInfo") - - info := getLocalDrivesPerf(globalEndpoints, size, r) - - defer w.(http.Flusher).Flush() - logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) -} - -// MemUsageInfoHandler - returns Memory Usage info. -func (s *peerRESTServer) MemUsageInfoHandler(w http.ResponseWriter, r *http.Request) { - if !s.IsValid(w, r) { - s.writeErrorResponse(w, errors.New("Invalid request")) - return - } - ctx := newContext(r, w, "MemUsageInfo") - info := getLocalMemUsage(globalEndpoints, r) - - defer w.(http.Flusher).Flush() - logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) -} - // DeleteBucketHandler - Delete notification and policies related to the bucket. func (s *peerRESTServer) DeleteBucketHandler(w http.ResponseWriter, r *http.Request) { if !s.IsValid(w, r) { @@ -1303,12 +1141,8 @@ func (s *peerRESTServer) IsValid(w http.ResponseWriter, r *http.Request) bool { func registerPeerRESTHandlers(router *mux.Router) { server := &peerRESTServer{} subrouter := router.PathPrefix(peerRESTPrefix).Subrouter() - subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodNetReadPerfInfo).HandlerFunc(httpTraceHdrs(server.NetReadPerfInfoHandler)).Queries(restQueries(peerRESTNetPerfSize)...) - subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodCollectNetPerfInfo).HandlerFunc(httpTraceHdrs(server.CollectNetPerfInfoHandler)).Queries(restQueries(peerRESTNetPerfSize)...) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetLocks).HandlerFunc(httpTraceHdrs(server.GetLocksHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodServerInfo).HandlerFunc(httpTraceHdrs(server.ServerInfoHandler)) - subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodCPULoadInfo).HandlerFunc(httpTraceHdrs(server.CPULoadInfoHandler)) - subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodMemUsageInfo).HandlerFunc(httpTraceHdrs(server.MemUsageInfoHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodProcOBDInfo).HandlerFunc(httpTraceHdrs(server.ProcOBDInfoHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodMemOBDInfo).HandlerFunc(httpTraceHdrs(server.MemOBDInfoHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodOsInfoOBDInfo).HandlerFunc(httpTraceHdrs(server.OsOBDInfoHandler)) @@ -1317,9 +1151,6 @@ func registerPeerRESTHandlers(router *mux.Router) { subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDriveOBDInfo).HandlerFunc(httpTraceHdrs(server.DriveOBDInfoHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodNetOBDInfo).HandlerFunc(httpTraceHdrs(server.NetOBDInfoHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDispatchNetOBDInfo).HandlerFunc(httpTraceHdrs(server.DispatchNetOBDInfoHandler)) - subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDrivePerfInfo).HandlerFunc(httpTraceHdrs(server.DrivePerfInfoHandler)).Queries(restQueries(peerRESTDrivePerfSize)...) - subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodHardwareCPUInfo).HandlerFunc(httpTraceHdrs(server.CPUInfoHandler)) - subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodHardwareNetworkInfo).HandlerFunc(httpTraceHdrs(server.NetworkInfoHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeleteBucket).HandlerFunc(httpTraceHdrs(server.DeleteBucketHandler)).Queries(restQueries(peerRESTBucket)...) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSignalService).HandlerFunc(httpTraceHdrs(server.SignalServiceHandler)).Queries(restQueries(peerRESTSignal)...) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodServerUpdate).HandlerFunc(httpTraceHdrs(server.ServerUpdateHandler)).Queries(restQueries(peerRESTUpdateURL, peerRESTSha256Hex, peerRESTLatestRelease)...) diff --git a/docs/multi-user/admin/README.md b/docs/multi-user/admin/README.md index 79a0a0b45..6b89aebc0 100644 --- a/docs/multi-user/admin/README.md +++ b/docs/multi-user/admin/README.md @@ -84,15 +84,14 @@ mc admin policy set myminio-admin1 user1policy user=user1 #### Service management permissions - admin:ServerInfo - admin:ServerUpdate -- admin:StorageInfo -- admin:DataUsageInfo -- admin:PerfInfo +- admin:StorageInfo +- admin:DataUsageInfo - admin:TopLocks -- admin:Profiling, -- admin:ServerTrace, -- admin:ConsoleLog, -- admin:KMSKeyStatus -- admin:ServerHardwareInfo +- admin:OBDInfo +- admin:Profiling, +- admin:ServerTrace +- admin:ConsoleLog +- admin:KMSKeyStatus #### User/Group management permissions - admin:AddUserToGroup diff --git a/pkg/cpu/counter_linux.go b/pkg/cpu/counter_linux.go deleted file mode 100644 index 71e8e02c5..000000000 --- a/pkg/cpu/counter_linux.go +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 cpu - -import ( - "syscall" - "time" - "unsafe" - - "golang.org/x/sys/unix" -) - -func newCounter() (counter, error) { - return counter{}, nil -} - -func (c counter) now() time.Time { - var ts syscall.Timespec - // Retrieve Per-process CPU-time clock - syscall.Syscall(syscall.SYS_CLOCK_GETTIME, unix.CLOCK_PROCESS_CPUTIME_ID, uintptr(unsafe.Pointer(&ts)), 0) - sec, nsec := ts.Unix() - return time.Unix(sec, nsec) -} diff --git a/pkg/cpu/counter_other.go b/pkg/cpu/counter_other.go deleted file mode 100644 index 1cf1c1c73..000000000 --- a/pkg/cpu/counter_other.go +++ /dev/null @@ -1,33 +0,0 @@ -// +build !linux - -/* - * MinIO Cloud Storage, (C) 2019-2020 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 cpu - -import ( - "fmt" - "runtime" - "time" -) - -func newCounter() (counter, error) { - return counter{}, fmt.Errorf("cpu metrics not implemented for %s platform", runtime.GOOS) -} - -func (c counter) now() time.Time { - return time.Time{} -} diff --git a/pkg/cpu/cpu.go b/pkg/cpu/cpu.go deleted file mode 100644 index b46717030..000000000 --- a/pkg/cpu/cpu.go +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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 cpu - -import ( - "sync" - "time" -) - -// rollingAvg holds the rolling average of the cpu load on the minio -// server over its lifetime -var rollingAvg *Load - -// cpuMeasureInterval is the interval of time between two -// measurements of CPU load -const cpuLoadMeasureInterval = 5 * time.Second - -// triggers the average load computation at server spawn -func init() { - rollingAvg = &Load{ - Min: float64(0), - Max: float64(0), - Avg: float64(0), - } - var rollingSum float64 - var cycles float64 - go func() { - for { - time.Sleep(cpuLoadMeasureInterval) - cycles = cycles + 1 - currLoad := GetLoad() - if rollingAvg.Max < currLoad.Max || rollingAvg.Max == 0 { - rollingAvg.Max = currLoad.Max - } - if rollingAvg.Min > currLoad.Min || rollingAvg.Min == 0 { - rollingAvg.Min = currLoad.Min - } - rollingSum = rollingSum + currLoad.Avg - rollingAvg.Avg = rollingSum / cycles - } - }() -} - -const ( - // cpuLoadWindow is the interval of time for which the - // cpu utilization is measured - cpuLoadWindow = 200 * time.Millisecond - - // cpuLoadSampleSize is the number of samples measured - // for calculating cpu utilization - cpuLoadSampleSize = 3 - - // endOfTime represents the end of time - endOfTime = time.Duration(1<<63 - 1) -) - -// Load holds CPU utilization % measured in three intervals of 200ms each -type Load struct { - Avg float64 `json:"avg"` - Max float64 `json:"max"` - Min float64 `json:"min"` - Error string `json:"error,omitempty"` -} - -type counter struct{} - -// GetHistoricLoad returns the historic CPU utilization of the current process -func GetHistoricLoad() Load { - return *rollingAvg -} - -// GetLoad returns the CPU utilization of the current process -// This function works by calcualating the amount of cpu clock -// cycles the current process used in a given time window -// -// This corresponds to the CPU utilization calculation done by -// tools like top. Here, we use the getclocktime with the -// CLOCK_PROCESS_CPUTIME_ID parameter to obtain the total number of -// clock ticks used by the process so far. Then we sleep for -// 200ms and obtain the the total number of clock ticks again. The -// difference between the two counts provides us the number of -// clock ticks used by the process in the 200ms interval. -// -// The ratio of clock ticks used (measured in nanoseconds) to number -// of nanoseconds in 200 milliseconds provides us the CPU usage -// for the process currently -func GetLoad() Load { - vals := make(chan time.Duration, 3) - var wg sync.WaitGroup - for i := 0; i < cpuLoadSampleSize; i++ { - cpuCounter, err := newCounter() - if err != nil { - return Load{ - Error: err.Error(), - } - } - wg.Add(1) - go func() { - start := cpuCounter.now() - time.Sleep(cpuLoadWindow) - end := cpuCounter.now() - vals <- end.Sub(start) - wg.Done() - }() - } - wg.Wait() - - sum := time.Duration(0) - max := time.Duration(0) - min := (endOfTime) - for i := 0; i < cpuLoadSampleSize; i++ { - val := <-vals - sum = sum + val - if val > max { - max = val - } - if val < min { - min = val - } - } - close(vals) - avg := sum / 3 - return Load{ - Avg: toFixed4(float64(avg)/float64(200*time.Millisecond)) * 100, - Max: toFixed4(float64(max)/float64(200*time.Millisecond)) * 100, - Min: toFixed4(float64(min)/float64(200*time.Millisecond)) * 100, - Error: "", - } -} diff --git a/pkg/cpu/helpers.go b/pkg/cpu/helpers.go deleted file mode 100644 index eb2ca289b..000000000 --- a/pkg/cpu/helpers.go +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 cpu - -import ( - "math" -) - -func round(num float64) int { - return int(num + math.Copysign(0.5, num)) -} - -func toFixed4(num float64) float64 { - output := math.Pow(10, float64(4)) - return float64(round(num*output)) / output -} diff --git a/pkg/disk/disk.go b/pkg/disk/disk.go index b6857e35f..504b5fd64 100644 --- a/pkg/disk/disk.go +++ b/pkg/disk/disk.go @@ -16,10 +16,6 @@ package disk -import ( - "os" -) - // Info stat fs struct is container which holds following values // Total - total size of the volume / disk // Free - free size of the volume / disk @@ -36,60 +32,3 @@ type Info struct { // Usage is calculated per tenant. Usage uint64 } - -// Performance holds informantion about read and write speed of a disk -type Performance struct { - Path string `json:"path"` - Error string `json:"error,omitempty"` - WriteSpeed float64 `json:"writeSpeed"` - ReadSpeed float64 `json:"readSpeed"` -} - -// GetPerformance returns given disk's read and write performance -func GetPerformance(path string, size int64) Performance { - perf := Performance{} - write, read, err := doPerfMeasure(path, size) - if err != nil { - perf.Error = err.Error() - return perf - } - perf.WriteSpeed = write - perf.ReadSpeed = read - return perf -} - -// Calculate the write and read performance - write and read 10 tmp (1 MiB) -// files and find the average time taken (Bytes / Sec) -func doPerfMeasure(fsPath string, size int64) (writeSpeed, readSpeed float64, err error) { - // Remove the file created for speed test purposes - defer os.RemoveAll(fsPath) - - // Create a file with O_DIRECT flag - w, err := OpenFileDirectIO(fsPath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0666) - if err != nil { - return 0, 0, err - } - - // Fetch aligned buf for direct-io - buf := AlignedBlock(speedTestBlockSize) - - writeSpeed, err = speedTestWrite(w, buf, size) - w.Close() - if err != nil { - return 0, 0, err - } - - // Open file to compute read speed - r, err := OpenFileDirectIO(fsPath, os.O_RDONLY, 0666) - if err != nil { - return 0, 0, err - } - defer r.Close() - - readSpeed, err = speedTestRead(r, buf, size) - if err != nil { - return 0, 0, err - } - - return writeSpeed, readSpeed, nil -} diff --git a/pkg/disk/obd.go b/pkg/disk/obd.go index c8ee2c7fe..344af7a42 100644 --- a/pkg/disk/obd.go +++ b/pkg/disk/obd.go @@ -21,19 +21,13 @@ import ( "context" "fmt" "os" - "path/filepath" "runtime" "time" + "github.com/dustin/go-humanize" "github.com/montanaflynn/stats" ) -const ( - kb = uint64(1 << 10) - mb = uint64(kb << 10) - gb = uint64(mb << 10) -) - var globalLatency = map[string]Latency{} var globalThroughput = map[string]Throughput{} @@ -58,19 +52,20 @@ type Throughput struct { } // GetOBDInfo about the drive -func GetOBDInfo(ctx context.Context, endpoint string) (Latency, Throughput, error) { +func GetOBDInfo(ctx context.Context, drive string, fsPath string) (Latency, Throughput, error) { runtime.LockOSThread() - f, err := OpenFileDirectIO(endpoint, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0755) + // Create a file with O_DIRECT flag, choose default umask and also make sure + // we are exclusively writing to a new file using O_EXCL. + w, err := OpenFileDirectIO(fsPath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0666) if err != nil { return Latency{}, Throughput{}, err } - defer func() { - f.Close() - os.Remove(f.Name()) - }() - drive := filepath.Dir(endpoint) + defer func() { + w.Close() + os.Remove(fsPath) + }() // going to leave this here incase we decide to go back to caching again // if gl, ok := globalLatency[drive]; ok { @@ -79,27 +74,26 @@ func GetOBDInfo(ctx context.Context, endpoint string) (Latency, Throughput, erro // } // } - blockSize := 4 * mb - fileSize := 256 * mb + blockSize := 4 * humanize.MiByte + fileSize := 256 * humanize.MiByte latencies := make([]float64, fileSize/blockSize) throughputs := make([]float64, fileSize/blockSize) - dioFile := os.NewFile(uintptr(f.Fd()), endpoint) - data := make([]byte, blockSize) + data := AlignedBlock(blockSize) - for i := uint64(0); i < (fileSize / blockSize); i++ { + for i := 0; i < (fileSize / blockSize); i++ { if ctx.Err() != nil { return Latency{}, Throughput{}, ctx.Err() } startTime := time.Now() - if n, err := dioFile.Write(data); err != nil { + if n, err := w.Write(data); err != nil { return Latency{}, Throughput{}, err - } else if uint64(n) != blockSize { + } else if n != blockSize { return Latency{}, Throughput{}, fmt.Errorf("Expected to write %d, but only wrote %d", blockSize, n) } - latency := time.Since(startTime) - latencies[i] = float64(latency.Seconds()) + latencyInSecs := time.Since(startTime).Seconds() + latencies[i] = float64(latencyInSecs) } runtime.UnlockOSThread() diff --git a/pkg/disk/speedtest.go b/pkg/disk/speedtest.go deleted file mode 100644 index a38d949df..000000000 --- a/pkg/disk/speedtest.go +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 disk - -import ( - "io" - "math" - "time" - - humanize "github.com/dustin/go-humanize" -) - -var speedTestBlockSize = 4 * humanize.MiByte - -// speedTestWrite computes the write speed by writing -// `speedTestFileSize` bytes of data to `w` in 4MiB direct-aligned -// blocks present in `buf` -func speedTestWrite(w io.Writer, buf []byte, size int64) (float64, error) { - // Write speedTestFileSize of data and record write speed - startTime := time.Now() - remaining := size - for remaining > 0 { - var toWrite int - // there's more remaining to write than the buffer can hold - if int64(len(buf)) < remaining { - toWrite = len(buf) - } else { // buffer can hold all there is to write - toWrite = int(remaining) - } - - written, err := w.Write(buf[:toWrite]) - if err != nil { - return 0, err - } - - remaining = remaining - int64(written) - } - - elapsedTime := time.Since(startTime).Seconds() - totalWriteMBs := float64(size) / humanize.MiByte - writeSpeed := totalWriteMBs / elapsedTime - - return roundToTwoDecimals(writeSpeed), nil -} - -// speedTestRead computes the read speed by reading -// `speedTestFileSize` bytes from the reader `r` using 4MiB size `buf` -func speedTestRead(r io.Reader, buf []byte, size int64) (float64, error) { - // Read speedTestFileSize and record read speed - startTime := time.Now() - remaining := size - for remaining > 0 { - // reads `speedTestBlockSize` on every read - n, err := io.ReadFull(r, buf) - if err == io.ErrUnexpectedEOF || err == nil { - remaining = remaining - int64(n) - continue - } - - // Nothing more left to read from the Reader - if err == io.EOF { - break - } - // Error while reading from the underlying Reader - if err != nil { - return 0, err - } - } - - if remaining > 0 { - return 0, io.ErrUnexpectedEOF - } - - elapsedTime := time.Since(startTime).Seconds() - totalReadMBs := float64(size) / humanize.MiByte - readSpeed := totalReadMBs / elapsedTime - - return roundToTwoDecimals(readSpeed), nil -} - -func roundToTwoDecimals(num float64) float64 { - return math.Round(num*100) / 100 -} diff --git a/pkg/iam/policy/admin-action.go b/pkg/iam/policy/admin-action.go index e9e954102..33e11a8f4 100644 --- a/pkg/iam/policy/admin-action.go +++ b/pkg/iam/policy/admin-action.go @@ -35,8 +35,6 @@ const ( AccountingUsageInfoAdminAction = "admin:AccountingUsageInfo" // DataUsageInfoAdminAction - allow listing data usage info DataUsageInfoAdminAction = "admin:DataUsageInfo" - // PerfInfoAdminAction - allow listing performance info - PerfInfoAdminAction = "admin:PerfInfo" // TopLocksAdminAction - allow listing top locks TopLocksAdminAction = "admin:TopLocksInfo" // ProfilingAdminAction - allow profiling @@ -47,8 +45,6 @@ const ( ConsoleLogAdminAction = "admin:ConsoleLog" // KMSKeyStatusAdminAction - allow getting KMS key status KMSKeyStatusAdminAction = "admin:KMSKeyStatus" - // ServerHardwareInfoAdminAction - allow listing server hardware info - ServerHardwareInfoAdminAction = "admin:HardwareInfo" // ServerInfoAdminAction - allow listing server info ServerInfoAdminAction = "admin:ServerInfo" // OBDInfoAdminAction - allow obtaining cluster on-board diagnostics @@ -115,13 +111,11 @@ var supportedAdminActions = map[AdminAction]struct{}{ ServerInfoAdminAction: {}, StorageInfoAdminAction: {}, DataUsageInfoAdminAction: {}, - PerfInfoAdminAction: {}, TopLocksAdminAction: {}, ProfilingAdminAction: {}, TraceAdminAction: {}, ConsoleLogAdminAction: {}, KMSKeyStatusAdminAction: {}, - ServerHardwareInfoAdminAction: {}, ServerUpdateAdminAction: {}, ConfigUpdateAdminAction: {}, CreateUserAdminAction: {}, @@ -164,13 +158,11 @@ var adminActionConditionKeyMap = map[Action]condition.KeySet{ StorageInfoAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), ServerInfoAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), DataUsageInfoAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), - PerfInfoAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), TopLocksAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), ProfilingAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), TraceAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), ConsoleLogAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), KMSKeyStatusAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), - ServerHardwareInfoAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), ServerUpdateAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), ConfigUpdateAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), CreateUserAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...), diff --git a/pkg/iam/policy/constants.go b/pkg/iam/policy/constants.go index 795e7278b..bf7876b8e 100644 --- a/pkg/iam/policy/constants.go +++ b/pkg/iam/policy/constants.go @@ -70,9 +70,11 @@ var AdminDiagnostics = Policy{ Version: DefaultVersion, Statements: []Statement{ { - SID: policy.ID(""), - Effect: policy.Allow, - Actions: NewActionSet(PerfInfoAdminAction, ProfilingAdminAction, TraceAdminAction, ConsoleLogAdminAction, ServerInfoAdminAction, ServerHardwareInfoAdminAction, TopLocksAdminAction), + SID: policy.ID(""), + Effect: policy.Allow, + Actions: NewActionSet(ProfilingAdminAction, TraceAdminAction, + ConsoleLogAdminAction, ServerInfoAdminAction, + TopLocksAdminAction, OBDInfoAdminAction), Resources: NewResourceSet(NewResource("*", "")), }, }, diff --git a/pkg/madmin/README.md b/pkg/madmin/README.md index 86c72ddfb..614270af3 100644 --- a/pkg/madmin/README.md +++ b/pkg/madmin/README.md @@ -45,12 +45,12 @@ func main() { | Service operations | Info operations | Healing operations | Config operations | Top operations | IAM operations | Misc | KMS | |:------------------------------------|:--------------------------------------------------|:-------------------|:--------------------------|:------------------------|:--------------------------------------|:--------------------------------------------------|:--------------------------------| | [`ServiceRestart`](#ServiceRestart) | [`ServerInfo`](#ServerInfo) | [`Heal`](#Heal) | [`GetConfig`](#GetConfig) | [`TopLocks`](#TopLocks) | [`AddUser`](#AddUser) | | [`GetKeyStatus`](#GetKeyStatus) | -| [`ServiceStop`](#ServiceStop) | [`ServerCPULoadInfo`](#ServerCPULoadInfo) | | [`SetConfig`](#SetConfig) | | [`SetUserPolicy`](#SetUserPolicy) | [`StartProfiling`](#StartProfiling) | | -| | [`ServerMemUsageInfo`](#ServerMemUsageInfo) | | | | [`ListUsers`](#ListUsers) | [`DownloadProfilingData`](#DownloadProfilingData) | | -| [`ServiceTrace`](#ServiceTrace) | [`ServerDrivesPerfInfo`](#ServerDrivesPerfInfo) | | | | [`AddCannedPolicy`](#AddCannedPolicy) | [`ServerUpdate`](#ServerUpdate) | | -| | [`NetPerfInfo`](#NetPerfInfo) | | | | | | | -| | [`ServerCPUHardwareInfo`](#ServerCPUHardwareInfo) | | | | | | | -| | [`ServerNetworkHardwareInfo`](#ServerNetworkHardwareInfo) | | | | | | | +| [`ServiceStop`](#ServiceStop) | | | [`SetConfig`](#SetConfig) | | [`SetUserPolicy`](#SetUserPolicy) | [`StartProfiling`](#StartProfiling) | | +| | | | | | [`ListUsers`](#ListUsers) | [`DownloadProfilingData`](#DownloadProfilingData) | | +| [`ServiceTrace`](#ServiceTrace) | | | | | [`AddCannedPolicy`](#AddCannedPolicy) | [`ServerUpdate`](#ServerUpdate) | | +| | | | | | | | | +| | | | | | | | | +| | | | | | | | | | | [`StorageInfo`](#StorageInfo) | | | | | | | ## 1. Constructor @@ -210,116 +210,6 @@ Fetches information for all cluster nodes, such as server properties, storage in ``` - -### ServerDrivesPerfInfo(ctx context.Context) ([]ServerDrivesPerfInfo, error) - -Fetches drive performance information for all cluster nodes. - -| Param | Type | Description | -|-----------------|--------------------|--------------------------------------------------------------------| -| `di.Addr` | _string_ | Address of the server the following information is retrieved from. | -| `di.Error` | _string_ | Errors (if any) encountered while reaching this node | -| `di.DrivesPerf` | _disk.Performance_ | Path of the drive mount on above server and read, write speed. | - -| Param | Type | Description | -|-------------------------------|-----------|--------------------------------------------------------| -| `disk.Performance.Path` | _string_ | Path of drive mount. | -| `disk.Performance.Error` | _string_ | Error (if any) encountered while accessing this drive. | -| `disk.Performance.WriteSpeed` | _float64_ | Write speed on above path in Bytes/s. | -| `disk.Performance.ReadSpeed` | _float64_ | Read speed on above path in Bytes/s. | - - -### ServerCPULoadInfo(ctx context.Context) ([]ServerCPULoadInfo, error) - -Fetches CPU utilization for all cluster nodes. - -| Param | Type | Description | -|----------------|------------|---------------------------------------------------------------------| -| `cpui.Addr` | _string_ | Address of the server the following information is retrieved from. | -| `cpui.Error` | _string_ | Errors (if any) encountered while reaching this node | -| `cpui.CPULoad` | _cpu.Load_ | The load on the CPU. | - -| Param | Type | Description | -|------------------|-----------|-----------------------------------------------------------------| -| `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 accessing the CPU info | - - -### ServerMemUsageInfo(ctx context.Context) ([]ServerMemUsageInfo, error) - -Fetches Mem utilization for all cluster nodes. - -| Param | Type | Description | -|-----------------|-------------|---------------------------------------------------------------------| -| `memi.Addr` | _string_ | Address of the server the following information is retrieved from. | -| `memi.Error` | _string_ | Errors (if any) encountered while reaching this node | -| `memi.MemUsage` | _mem.Usage_ | The utilitzation of Memory | - -| 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 accessing the CPU info | - - -### NetPerfInfo(ctx context.Context, 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 | -| `ReadThroughput` | _uint64_ | Network read throughput of the server in bytes per second | - - - -### ServerCPUHardwareInfo(ctx context.Context) ([]ServerCPUHardwareInfo, error) - -Fetches hardware information of CPU. - -| Param | Type | Description | -|-------------------|---------------------|---------------------------------------------------------------------| -| `hwi.Addr` | _string_ | Address of the server the following information is retrieved from. | -| `hwi.Error` | _string_ | Errors (if any) encountered while reaching this node | -| `hwi.CPUInfo` | _[]cpu.InfoStat_ | The CPU hardware info. | - -| Param | Type | Description | -|----------------------------|----------|--------------------------------------------------------| -| `CPUInfo.CPU` | _int32_ | CPU | -| `CPUInfo.VendorID` | _string_ | Vendor Id | -| `CPUInfo.Family` | _string_ | CPU Family | -| `CPUInfo.Model` | _string_ | Model | -| `CPUInfo.Stepping` | _int32_ | Stepping | -| `CPUInfo.PhysicalId` | _string_ | Physical Id | -| `CPUInfo.CoreId` | _string_ | Core Id | -| `CPUInfo.Cores` | _int32_ | Cores | -| `CPUInfo.ModelName` | _string_ | Model Name | -| `CPUInfo.Mhz` | _float64_| Mhz | -| `CPUInfo.CacheZSize` | _int32_ | cache sizes | -| `CPUInfo.Flags` |_[]string_| Flags | -| `CPUInfo.Microcode` | _string_ | Micro codes | - - -### ServerNetworkHardwareInfo(ctx context.Context) ([]ServerNetworkHardwareInfo, error) - -Fetches hardware information of CPU. - -| Param | Type | Description | -|-------------------|---------------------|---------------------------------------------------------------------| -| `hwi.Addr` | _string_ | Address of the server the following information is retrieved from. | -| `hwi.Error` | _string_ | Errors (if any) encountered while reaching this node | -| `hwi.NetworkInfo` | _[]net.Interface_ | The network hardware info | - -| Param | Type | Description | -|----------------------------|----------|-----------------------------------------------------------| -| `NetworkInfo.Index` | _int32_ | positive integer that starts at one, zero is never used. | -| `NetworkInfo.MTU` | _int32_ | maximum transmission unit | -| `NetworkInfo.Name` | _string_ | e.g., "en0", "lo0", "eth0.100" | -| `NetworkInfo.HardwareAddr` | _[]byte_ | IEEE MAC-48, EUI-48 and EUI-64 form | -| `NetworkInfo.Flags` | _uint32_ | e.g., FlagUp, FlagLoopback, FlagMulticast | - ### StorageInfo(ctx context.Context) (StorageInfo, error) diff --git a/pkg/madmin/examples/cpu-load-info.go b/pkg/madmin/examples/cpu-load-info.go deleted file mode 100644 index d05c925b4..000000000 --- a/pkg/madmin/examples/cpu-load-info.go +++ /dev/null @@ -1,45 +0,0 @@ -// +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 ( - "context" - "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.ServerCPULoadInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Println(st) -} diff --git a/pkg/madmin/examples/drives-perf-info.go b/pkg/madmin/examples/drives-perf-info.go deleted file mode 100644 index d8003cdb8..000000000 --- a/pkg/madmin/examples/drives-perf-info.go +++ /dev/null @@ -1,45 +0,0 @@ -// +build ignore - -/* - * MinIO Cloud Storage, (C) 2018 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 ( - "context" - "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.ServerDrivesPerfInfo(context.Background(), madmin.DefaultDrivePerfSize) - if err != nil { - log.Fatalln(err) - } - log.Println(st) -} diff --git a/pkg/madmin/examples/hw-cpu-info.go b/pkg/madmin/examples/hw-cpu-info.go deleted file mode 100644 index 88b242c6b..000000000 --- a/pkg/madmin/examples/hw-cpu-info.go +++ /dev/null @@ -1,45 +0,0 @@ -// +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 ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are - // dummy values, please replace them with correct 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.ServerCPUHardwareInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Println(st) - -} diff --git a/pkg/madmin/examples/hw-network-info.go b/pkg/madmin/examples/hw-network-info.go deleted file mode 100644 index 63ca845a0..000000000 --- a/pkg/madmin/examples/hw-network-info.go +++ /dev/null @@ -1,45 +0,0 @@ -// +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 ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are - // dummy values, please replace them with correct 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.ServerNetworkHardwareInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Println(st) - -} diff --git a/pkg/madmin/examples/mem-usage-info.go b/pkg/madmin/examples/mem-usage-info.go deleted file mode 100644 index 2fc2f59f4..000000000 --- a/pkg/madmin/examples/mem-usage-info.go +++ /dev/null @@ -1,45 +0,0 @@ -// +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 ( - "context" - "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.ServerMemUsageInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Println(st) -} diff --git a/pkg/madmin/examples/net-perf-info.go b/pkg/madmin/examples/net-perf-info.go deleted file mode 100644 index 887ed0ed1..000000000 --- a/pkg/madmin/examples/net-perf-info.go +++ /dev/null @@ -1,45 +0,0 @@ -// +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 ( - "context" - "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(context.Background(), madmin.DefaultNetPerfSize) - if err != nil { - log.Fatalln(err) - } - log.Println(st) -} diff --git a/pkg/madmin/hardware-commands.go b/pkg/madmin/hardware-commands.go deleted file mode 100644 index ccbea08f6..000000000 --- a/pkg/madmin/hardware-commands.go +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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 madmin - -import ( - "context" - "encoding/json" - "io/ioutil" - "net" - "net/http" - "net/url" - - "github.com/shirou/gopsutil/cpu" -) - -// HardwareType - type to hardware -type HardwareType string - -const ( - // HARDWARE represents hardware type - HARDWARE = "hwType" - // CPU represents hardware as cpu - CPU HardwareType = "cpu" - // NETWORK hardware Info - NETWORK HardwareType = "network" -) - -// ServerCPUHardwareInfo holds informantion about cpu hardware -type ServerCPUHardwareInfo struct { - Addr string `json:"addr"` - Error string `json:"error,omitempty"` - CPUInfo []cpu.InfoStat `json:"cpu"` -} - -// ServerCPUHardwareInfo - Returns cpu hardware information -func (adm *AdminClient) ServerCPUHardwareInfo(ctx context.Context) ([]ServerCPUHardwareInfo, error) { - v := url.Values{} - v.Set(HARDWARE, string(CPU)) - resp, err := adm.executeMethod(ctx, - http.MethodGet, requestData{ - relPath: adminAPIPrefix + "/hardware", - queryValues: v, - }, - ) - - defer closeResponse(resp) - if err != nil { - return nil, err - } - - // Check response http status code - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - // Unmarshal the server's json response - var cpuInfo []ServerCPUHardwareInfo - - respBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - err = json.Unmarshal(respBytes, &cpuInfo) - if err != nil { - return nil, err - } - return cpuInfo, nil -} - -// ServerNetworkHardwareInfo holds informantion about cpu hardware -type ServerNetworkHardwareInfo struct { - Addr string `json:"addr"` - Error string `json:"error,omitempty"` - NetworkInfo []net.Interface `json:"network"` -} - -// ServerNetworkHardwareInfo - Returns network hardware information -func (adm *AdminClient) ServerNetworkHardwareInfo(ctx context.Context) ([]ServerNetworkHardwareInfo, error) { - v := url.Values{} - v.Set(HARDWARE, string(NETWORK)) - resp, err := adm.executeMethod(ctx, - http.MethodGet, requestData{ - relPath: "/v1/hardware", - queryValues: v, - }, - ) - - defer closeResponse(resp) - if err != nil { - return nil, err - } - - // Check response http status code - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - // Unmarshal the server's json response - var networkInfo []ServerNetworkHardwareInfo - - respBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - err = json.Unmarshal(respBytes, &networkInfo) - if err != nil { - return nil, err - } - return networkInfo, nil -} diff --git a/pkg/madmin/info-commands.go b/pkg/madmin/info-commands.go index 67b5bd9c5..0a049f89b 100644 --- a/pkg/madmin/info-commands.go +++ b/pkg/madmin/info-commands.go @@ -20,25 +20,10 @@ package madmin import ( "context" "encoding/json" - "errors" "io/ioutil" "math" "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 - // DefaultDrivePerfSize - default file size for testing drive performance - DefaultDrivePerfSize = 100 * humanize.MiByte ) // BackendType - represents different backend types. @@ -251,200 +236,6 @@ func (adm *AdminClient) AccountingUsageInfo(ctx context.Context) (map[string]Buc return accountingUsageInfo, nil } -// ServerDrivesPerfInfo holds informantion about address and write speed of -// all drives in a single server node -type ServerDrivesPerfInfo struct { - Addr string `json:"addr"` - Error string `json:"error,omitempty"` - Perf []disk.Performance `json:"perf"` - Size int64 `json:"size,omitempty"` -} - -// ServerDrivesPerfInfo - Returns drive's read and write performance information -func (adm *AdminClient) ServerDrivesPerfInfo(ctx context.Context, size int64) ([]ServerDrivesPerfInfo, error) { - v := url.Values{} - v.Set("perfType", string("drive")) - - v.Set("size", strconv.FormatInt(size, 10)) - - resp, err := adm.executeMethod(ctx, http.MethodGet, - requestData{ - relPath: adminAPIPrefix + "/performance", - queryValues: v, - }, - ) - - defer closeResponse(resp) - if err != nil { - return nil, err - } - - // Check response http status code - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - // Unmarshal the server's json response - var info []ServerDrivesPerfInfo - - 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 -} - -// ServerCPULoadInfo holds information about address and cpu load of -// a single server node -type ServerCPULoadInfo struct { - Addr string `json:"addr"` - Error string `json:"error,omitempty"` - Load []cpu.Load `json:"load"` - HistoricLoad []cpu.Load `json:"historicLoad"` -} - -// ServerCPULoadInfo - Returns cpu utilization information -func (adm *AdminClient) ServerCPULoadInfo(ctx context.Context) ([]ServerCPULoadInfo, error) { - v := url.Values{} - v.Set("perfType", string("cpu")) - resp, err := adm.executeMethod(ctx, - http.MethodGet, requestData{ - relPath: adminAPIPrefix + "/performance", - queryValues: v, - }, - ) - - defer closeResponse(resp) - if err != nil { - return nil, err - } - - // Check response http status code - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - // Unmarshal the server's json response - var info []ServerCPULoadInfo - - 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 -} - -// ServerMemUsageInfo holds information about address and memory utilization of -// a single server node -type ServerMemUsageInfo struct { - Addr string `json:"addr"` - Error string `json:"error,omitempty"` - Usage []mem.Usage `json:"usage"` - HistoricUsage []mem.Usage `json:"historicUsage"` -} - -// ServerMemUsageInfo - Returns mem utilization information -func (adm *AdminClient) ServerMemUsageInfo(ctx context.Context) ([]ServerMemUsageInfo, error) { - v := url.Values{} - v.Set("perfType", string("mem")) - resp, err := adm.executeMethod(ctx, - http.MethodGet, - requestData{ - relPath: adminAPIPrefix + "/performance", - queryValues: v, - }, - ) - - defer closeResponse(resp) - if err != nil { - return nil, err - } - - // Check response http status code - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - // Unmarshal the server's json response - var info []ServerMemUsageInfo - - 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 -} - -// NetPerfInfo network performance information. -type NetPerfInfo struct { - Addr string `json:"addr"` - ReadThroughput uint64 `json:"readThroughput"` - Error string `json:"error,omitempty"` -} - -// NetPerfInfo - Returns network performance information of all cluster nodes. -func (adm *AdminClient) NetPerfInfo(ctx context.Context, 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(ctx, - http.MethodGet, - requestData{ - relPath: adminAPIPrefix + "/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 -} - // InfoMessage container to hold server admin related information. type InfoMessage struct { Mode string `json:"mode,omitempty"` diff --git a/pkg/mem/mem.go b/pkg/mem/mem.go deleted file mode 100644 index 0bb012301..000000000 --- a/pkg/mem/mem.go +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 mem - -import ( - "runtime" - "time" -) - -// historicUsage holds the rolling average of memory used by -// minio server -var historicUsage *Usage - -// memUsageMeasureInterval is the window of time between -// two measurements of memory usage -const memUsageMeasureInterval = 5 * time.Second - -// triggers the collection of historic stats about the memory -// utilized by minio server -func init() { - historicUsage = &Usage{} - var cycles uint64 - go func() { - for { - time.Sleep(memUsageMeasureInterval) - currUsage := GetUsage() - currSum := cycles * historicUsage.Mem - cycles = cycles + 1 - historicUsage.Mem = (currSum + currUsage.Mem) / cycles - } - }() -} - -// Usage holds memory utilization information in human readable format -type Usage struct { - Mem uint64 `json:"mem"` - Error string `json:"error,omitempty"` -} - -// GetHistoricUsage measures the historic average of memory utilized by -// current process -func GetHistoricUsage() Usage { - return *historicUsage -} - -// GetUsage measures the total memory provisioned for the current process -// from the OS -func GetUsage() Usage { - memStats := new(runtime.MemStats) - runtime.ReadMemStats(memStats) - return Usage{ - Mem: memStats.Sys, - } -}