github.com/vmware/govmomi@v0.43.0/govc/cluster/usage.go (about) 1 /* 2 Copyright (c) 2020-2023 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package cluster 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 "io" 24 "text/tabwriter" 25 26 "github.com/vmware/govmomi/govc/cli" 27 "github.com/vmware/govmomi/govc/flags" 28 "github.com/vmware/govmomi/property" 29 "github.com/vmware/govmomi/units" 30 "github.com/vmware/govmomi/vim25/mo" 31 ) 32 33 type usage struct { 34 *flags.DatacenterFlag 35 36 shared bool 37 } 38 39 func init() { 40 cli.Register("cluster.usage", &usage{}) 41 } 42 43 func (cmd *usage) Register(ctx context.Context, f *flag.FlagSet) { 44 cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx) 45 cmd.DatacenterFlag.Register(ctx, f) 46 47 f.BoolVar(&cmd.shared, "S", false, "Exclude host local storage") 48 } 49 50 func (cmd *usage) Usage() string { 51 return "CLUSTER" 52 } 53 54 func (cmd *usage) Description() string { 55 return `Cluster resource usage summary. 56 57 Examples: 58 govc cluster.usage ClusterName 59 govc cluster.usage -S ClusterName # summarize shared storage only 60 govc cluster.usage -json ClusterName | jq -r .cpu.summary.usage` 61 } 62 63 func (cmd *usage) Run(ctx context.Context, f *flag.FlagSet) error { 64 finder, err := cmd.Finder() 65 if err != nil { 66 return err 67 } 68 69 obj, err := finder.ClusterComputeResource(ctx, f.Arg(0)) 70 if err != nil { 71 return err 72 } 73 74 var res Usage 75 var cluster mo.ClusterComputeResource 76 var hosts []mo.HostSystem 77 var datastores []mo.Datastore 78 79 pc := property.DefaultCollector(obj.Client()) 80 81 err = pc.RetrieveOne(ctx, obj.Reference(), []string{"datastore", "host"}, &cluster) 82 if err != nil { 83 return err 84 } 85 86 err = pc.Retrieve(ctx, cluster.Host, []string{"summary"}, &hosts) 87 if err != nil { 88 return err 89 } 90 91 for _, host := range hosts { 92 res.CPU.Capacity += int64(int32(host.Summary.Hardware.NumCpuCores) * host.Summary.Hardware.CpuMhz) 93 res.CPU.Used += int64(host.Summary.QuickStats.OverallCpuUsage) 94 95 res.Memory.Capacity += host.Summary.Hardware.MemorySize 96 res.Memory.Used += int64(host.Summary.QuickStats.OverallMemoryUsage) << 20 97 } 98 99 err = pc.Retrieve(ctx, cluster.Datastore, []string{"summary"}, &datastores) 100 if err != nil { 101 return err 102 } 103 104 for _, datastore := range datastores { 105 shared := datastore.Summary.MultipleHostAccess 106 if cmd.shared && shared != nil && *shared == false { 107 continue 108 } 109 110 res.Storage.Capacity += datastore.Summary.Capacity 111 res.Storage.Free += datastore.Summary.FreeSpace 112 } 113 114 res.CPU.Free = res.CPU.Capacity - res.CPU.Used 115 res.CPU.summarize(ghz) 116 117 res.Memory.Free = res.Memory.Capacity - res.Memory.Used 118 res.Memory.summarize(size) 119 120 res.Storage.Used = res.Storage.Capacity - res.Storage.Free 121 res.Storage.summarize(size) 122 123 return cmd.WriteResult(&res) 124 } 125 126 type ResourceUsageSummary struct { 127 Used string `json:"used"` 128 Free string `json:"free"` 129 Capacity string `json:"capacity"` 130 Usage string `json:"usage"` 131 } 132 133 type ResourceUsage struct { 134 Used int64 `json:"used"` 135 Free int64 `json:"free"` 136 Capacity int64 `json:"capacity"` 137 Usage float64 `json:"usage"` 138 Summary ResourceUsageSummary `json:"summary"` 139 } 140 141 func (r *ResourceUsage) summarize(f func(int64) string) { 142 r.Usage = 100 * float64(r.Used) / float64(r.Capacity) 143 144 r.Summary.Usage = fmt.Sprintf("%.1f", r.Usage) 145 r.Summary.Capacity = f(r.Capacity) 146 r.Summary.Used = f(r.Used) 147 r.Summary.Free = f(r.Free) 148 } 149 150 func (r *ResourceUsage) write(w io.Writer, label string) { 151 fmt.Fprintf(w, "%s usage:\t%s%%\n", label, r.Summary.Usage) 152 fmt.Fprintf(w, "%s capacity:\t%s\n", label, r.Summary.Capacity) 153 fmt.Fprintf(w, "%s used:\t%s\n", label, r.Summary.Used) 154 fmt.Fprintf(w, "%s free:\t%s\n", label, r.Summary.Free) 155 } 156 157 func ghz(val int64) string { 158 return fmt.Sprintf("%.1fGHz", float64(val)/1000) 159 } 160 161 func size(val int64) string { 162 return units.ByteSize(val).String() 163 } 164 165 type Usage struct { 166 Memory ResourceUsage `json:"memory"` 167 CPU ResourceUsage `json:"cpu"` 168 Storage ResourceUsage `json:"storage"` 169 } 170 171 func (r *Usage) Write(w io.Writer) error { 172 tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) 173 174 r.CPU.write(tw, "CPU") 175 fmt.Fprintf(tw, "\t\n") 176 177 r.Memory.write(tw, "Memory") 178 fmt.Fprintf(tw, "\t\n") 179 180 r.Storage.write(tw, "Storage") 181 182 return tw.Flush() 183 }