github.com/minio/console@v1.4.1/api/admin_speedtest.go (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2021 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 package api 18 19 import ( 20 "context" 21 "encoding/json" 22 "fmt" 23 "net/http" 24 "strconv" 25 "time" 26 27 "github.com/dustin/go-humanize" 28 "github.com/minio/madmin-go/v3" 29 "github.com/minio/websocket" 30 ) 31 32 // getSpeedtesthOptionsFromReq gets duration, size & concurrent requests from a websocket 33 // path come as : `/speedtest?duration=2h&size=12MiB&concurrent=10` 34 func getSpeedtestOptionsFromReq(req *http.Request) (*madmin.SpeedtestOpts, error) { 35 optionsSet := madmin.SpeedtestOpts{} 36 37 queryPairs := req.URL.Query() 38 39 paramDuration := queryPairs.Get("duration") 40 41 if paramDuration == "" { 42 paramDuration = "10s" 43 } 44 45 duration, err := time.ParseDuration(paramDuration) 46 if err != nil { 47 return nil, fmt.Errorf("unable to parse duration: %s", paramDuration) 48 } 49 50 if duration <= 0 { 51 return nil, fmt.Errorf("duration cannot be 0 or negative") 52 } 53 54 optionsSet.Duration = duration 55 56 paramSize := queryPairs.Get("size") 57 58 if paramSize == "" { 59 paramSize = "64MiB" 60 } 61 62 size, err := humanize.ParseBytes(paramSize) 63 if err != nil { 64 return nil, fmt.Errorf("unable to parse object size") 65 } 66 67 optionsSet.Size = int(size) 68 69 paramConcurrent := queryPairs.Get("concurrent") 70 71 if paramConcurrent == "" { 72 paramConcurrent = "32" 73 } 74 75 concurrent, err := strconv.Atoi(paramConcurrent) 76 if err != nil { 77 return nil, fmt.Errorf("invalid concurrent value: %s", paramConcurrent) 78 } 79 80 if concurrent <= 0 { 81 return nil, fmt.Errorf("concurrency cannot be '0' or negative") 82 } 83 84 optionsSet.Concurrency = concurrent 85 86 autotune := queryPairs.Get("autotune") 87 88 if autotune == "true" { 89 optionsSet.Autotune = true 90 } 91 92 return &optionsSet, nil 93 } 94 95 func startSpeedtest(ctx context.Context, conn WSConn, client MinioAdmin, speedtestOpts *madmin.SpeedtestOpts) error { 96 speedtestRes, err := client.speedtest(ctx, *speedtestOpts) 97 if err != nil { 98 LogError("error initializing speedtest: %v", err) 99 return err 100 } 101 102 for result := range speedtestRes { 103 // Serializing message 104 bytes, err := json.Marshal(result) 105 if err != nil { 106 LogError("error serializing json: %v", err) 107 return err 108 } 109 // Send Message through websocket connection 110 err = conn.writeMessage(websocket.TextMessage, bytes) 111 if err != nil { 112 LogError("error writing speedtest response: %v", err) 113 return err 114 } 115 } 116 117 return nil 118 }