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 }