github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/support-perf-drive.go (about) 1 // Copyright (c) 2015-2022 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "context" 22 "os" 23 24 tea "github.com/charmbracelet/bubbletea" 25 "github.com/dustin/go-humanize" 26 "github.com/minio/cli" 27 "github.com/minio/madmin-go/v3" 28 "github.com/minio/mc/pkg/probe" 29 ) 30 31 func mainAdminSpeedTestDrive(ctx *cli.Context, aliasedURL string, outCh chan<- PerfTestResult) error { 32 client, perr := newAdminClient(aliasedURL) 33 if perr != nil { 34 fatalIf(perr.Trace(aliasedURL), "Unable to initialize admin client.") 35 return nil 36 } 37 38 ctxt, cancel := context.WithCancel(globalContext) 39 defer cancel() 40 41 blocksize, e := humanize.ParseBytes(ctx.String("blocksize")) 42 if e != nil { 43 fatalIf(probe.NewError(e), "Unable to parse blocksize") 44 return nil 45 } 46 if blocksize <= 0 { 47 fatalIf(errInvalidArgument(), "blocksize cannot be <= 0") 48 return nil 49 } 50 51 filesize, e := humanize.ParseBytes(ctx.String("filesize")) 52 if e != nil { 53 fatalIf(probe.NewError(e), "Unable to parse filesize") 54 return nil 55 } 56 if filesize <= 0 { 57 fatalIf(errInvalidArgument(), "filesize cannot be <= 0") 58 return nil 59 } 60 61 serial := ctx.Bool("serial") 62 63 resultCh, e := client.DriveSpeedtest(ctxt, madmin.DriveSpeedTestOpts{ 64 Serial: serial, 65 BlockSize: blocksize, 66 FileSize: filesize, 67 }) 68 69 if globalJSON { 70 if e != nil { 71 printMsg(convertPerfResult(PerfTestResult{ 72 Type: DrivePerfTest, 73 Err: e.Error(), 74 Final: true, 75 })) 76 77 return nil 78 } 79 80 var results []madmin.DriveSpeedTestResult 81 for result := range resultCh { 82 if result.Version != "" { 83 results = append(results, result) 84 } 85 } 86 printMsg(convertPerfResult(PerfTestResult{ 87 Type: DrivePerfTest, 88 DriveResult: results, 89 Final: true, 90 })) 91 92 return nil 93 } 94 95 done := make(chan struct{}) 96 97 p := tea.NewProgram(initSpeedTestUI()) 98 go func() { 99 if _, e := p.Run(); e != nil { 100 os.Exit(1) 101 } 102 close(done) 103 }() 104 105 go func() { 106 if e != nil { 107 r := PerfTestResult{ 108 Type: DrivePerfTest, 109 Err: e.Error(), 110 Final: true, 111 } 112 p.Send(r) 113 if outCh != nil { 114 outCh <- r 115 } 116 return 117 } 118 119 var results []madmin.DriveSpeedTestResult 120 for result := range resultCh { 121 if result.Version != "" { 122 results = append(results, result) 123 } else { 124 p.Send(PerfTestResult{ 125 Type: DrivePerfTest, 126 DriveResult: []madmin.DriveSpeedTestResult{}, 127 }) 128 } 129 } 130 r := PerfTestResult{ 131 Type: DrivePerfTest, 132 DriveResult: results, 133 Final: true, 134 } 135 p.Send(r) 136 if outCh != nil { 137 outCh <- r 138 } 139 }() 140 141 <-done 142 143 return nil 144 }