github.com/vmware/govmomi@v0.51.0/cli/cluster/usage.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package cluster
     6  
     7  import (
     8  	"context"
     9  	"flag"
    10  	"fmt"
    11  	"io"
    12  	"text/tabwriter"
    13  
    14  	"github.com/vmware/govmomi/cli"
    15  	"github.com/vmware/govmomi/cli/flags"
    16  	"github.com/vmware/govmomi/property"
    17  	"github.com/vmware/govmomi/units"
    18  	"github.com/vmware/govmomi/vim25/mo"
    19  )
    20  
    21  type usage struct {
    22  	*flags.DatacenterFlag
    23  
    24  	shared bool
    25  }
    26  
    27  func init() {
    28  	cli.Register("cluster.usage", &usage{})
    29  }
    30  
    31  func (cmd *usage) Register(ctx context.Context, f *flag.FlagSet) {
    32  	cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
    33  	cmd.DatacenterFlag.Register(ctx, f)
    34  
    35  	f.BoolVar(&cmd.shared, "S", false, "Exclude host local storage")
    36  }
    37  
    38  func (cmd *usage) Usage() string {
    39  	return "CLUSTER"
    40  }
    41  
    42  func (cmd *usage) Description() string {
    43  	return `Cluster resource usage summary.
    44  
    45  Examples:
    46    govc cluster.usage ClusterName
    47    govc cluster.usage -S ClusterName # summarize shared storage only
    48    govc cluster.usage -json ClusterName | jq -r .cpu.summary.usage`
    49  }
    50  
    51  func (cmd *usage) Run(ctx context.Context, f *flag.FlagSet) error {
    52  	finder, err := cmd.Finder()
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	obj, err := finder.ClusterComputeResource(ctx, f.Arg(0))
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	var res Usage
    63  	var cluster mo.ClusterComputeResource
    64  	var hosts []mo.HostSystem
    65  	var datastores []mo.Datastore
    66  
    67  	pc := property.DefaultCollector(obj.Client())
    68  
    69  	err = pc.RetrieveOne(ctx, obj.Reference(), []string{"datastore", "host"}, &cluster)
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	err = pc.Retrieve(ctx, cluster.Host, []string{"summary"}, &hosts)
    75  	if err != nil {
    76  		return err
    77  	}
    78  
    79  	for _, host := range hosts {
    80  		res.CPU.Capacity += int64(int32(host.Summary.Hardware.NumCpuCores) * host.Summary.Hardware.CpuMhz)
    81  		res.CPU.Used += int64(host.Summary.QuickStats.OverallCpuUsage)
    82  
    83  		res.Memory.Capacity += host.Summary.Hardware.MemorySize
    84  		res.Memory.Used += int64(host.Summary.QuickStats.OverallMemoryUsage) << 20
    85  	}
    86  
    87  	err = pc.Retrieve(ctx, cluster.Datastore, []string{"summary"}, &datastores)
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	for _, datastore := range datastores {
    93  		shared := datastore.Summary.MultipleHostAccess
    94  		if cmd.shared && shared != nil && *shared == false {
    95  			continue
    96  		}
    97  
    98  		res.Storage.Capacity += datastore.Summary.Capacity
    99  		res.Storage.Free += datastore.Summary.FreeSpace
   100  	}
   101  
   102  	res.CPU.Free = res.CPU.Capacity - res.CPU.Used
   103  	res.CPU.summarize(ghz)
   104  
   105  	res.Memory.Free = res.Memory.Capacity - res.Memory.Used
   106  	res.Memory.summarize(size)
   107  
   108  	res.Storage.Used = res.Storage.Capacity - res.Storage.Free
   109  	res.Storage.summarize(size)
   110  
   111  	return cmd.WriteResult(&res)
   112  }
   113  
   114  type ResourceUsageSummary struct {
   115  	Used     string `json:"used"`
   116  	Free     string `json:"free"`
   117  	Capacity string `json:"capacity"`
   118  	Usage    string `json:"usage"`
   119  }
   120  
   121  type ResourceUsage struct {
   122  	Used     int64                `json:"used"`
   123  	Free     int64                `json:"free"`
   124  	Capacity int64                `json:"capacity"`
   125  	Usage    float64              `json:"usage"`
   126  	Summary  ResourceUsageSummary `json:"summary"`
   127  }
   128  
   129  func (r *ResourceUsage) summarize(f func(int64) string) {
   130  	r.Usage = 100 * float64(r.Used) / float64(r.Capacity)
   131  
   132  	r.Summary.Usage = fmt.Sprintf("%.1f", r.Usage)
   133  	r.Summary.Capacity = f(r.Capacity)
   134  	r.Summary.Used = f(r.Used)
   135  	r.Summary.Free = f(r.Free)
   136  }
   137  
   138  func (r *ResourceUsage) write(w io.Writer, label string) {
   139  	fmt.Fprintf(w, "%s usage:\t%s%%\n", label, r.Summary.Usage)
   140  	fmt.Fprintf(w, "%s capacity:\t%s\n", label, r.Summary.Capacity)
   141  	fmt.Fprintf(w, "%s used:\t%s\n", label, r.Summary.Used)
   142  	fmt.Fprintf(w, "%s free:\t%s\n", label, r.Summary.Free)
   143  }
   144  
   145  func ghz(val int64) string {
   146  	return fmt.Sprintf("%.1fGHz", float64(val)/1000)
   147  }
   148  
   149  func size(val int64) string {
   150  	return units.ByteSize(val).String()
   151  }
   152  
   153  type Usage struct {
   154  	Memory  ResourceUsage `json:"memory"`
   155  	CPU     ResourceUsage `json:"cpu"`
   156  	Storage ResourceUsage `json:"storage"`
   157  }
   158  
   159  func (r *Usage) Write(w io.Writer) error {
   160  	tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
   161  
   162  	r.CPU.write(tw, "CPU")
   163  	fmt.Fprintf(tw, "\t\n")
   164  
   165  	r.Memory.write(tw, "Memory")
   166  	fmt.Fprintf(tw, "\t\n")
   167  
   168  	r.Storage.write(tw, "Storage")
   169  
   170  	return tw.Flush()
   171  }