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  }