github.com/vmware/govmomi@v0.43.0/govc/pool/info.go (about) 1 /* 2 Copyright (c) 2015-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 pool 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 "io" 24 "text/tabwriter" 25 26 "github.com/vmware/govmomi/find" 27 "github.com/vmware/govmomi/govc/cli" 28 "github.com/vmware/govmomi/govc/flags" 29 "github.com/vmware/govmomi/object" 30 "github.com/vmware/govmomi/property" 31 "github.com/vmware/govmomi/vim25/mo" 32 "github.com/vmware/govmomi/vim25/types" 33 ) 34 35 type info struct { 36 *flags.DatacenterFlag 37 *flags.OutputFlag 38 39 pools bool 40 apps bool 41 } 42 43 func init() { 44 cli.Register("pool.info", &info{}) 45 } 46 47 func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) { 48 cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx) 49 cmd.DatacenterFlag.Register(ctx, f) 50 cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx) 51 cmd.OutputFlag.Register(ctx, f) 52 53 f.BoolVar(&cmd.pools, "p", true, "List resource pools") 54 f.BoolVar(&cmd.apps, "a", false, "List virtual app resource pools") 55 } 56 57 func (cmd *info) Process(ctx context.Context) error { 58 if err := cmd.DatacenterFlag.Process(ctx); err != nil { 59 return err 60 } 61 if err := cmd.OutputFlag.Process(ctx); err != nil { 62 return err 63 } 64 return nil 65 } 66 67 func (cmd *info) Usage() string { 68 return "POOL..." 69 } 70 71 func (cmd *info) Description() string { 72 return "Retrieve information about one or more resource POOLs.\n" + poolNameHelp 73 } 74 75 func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error { 76 if f.NArg() == 0 { 77 return flag.ErrHelp 78 } 79 80 c, err := cmd.Client() 81 if err != nil { 82 return err 83 } 84 85 finder, err := cmd.Finder() 86 if err != nil { 87 return err 88 } 89 90 var res infoResult 91 var props []string 92 93 if cmd.OutputFlag.All() { 94 props = nil 95 } else { 96 props = []string{ 97 "name", 98 "config.cpuAllocation", 99 "config.memoryAllocation", 100 "runtime.cpu", 101 "runtime.memory", 102 } 103 } 104 105 var vapps []*object.VirtualApp 106 107 for _, arg := range f.Args() { 108 if cmd.pools { 109 objects, err := finder.ResourcePoolList(ctx, arg) 110 if err != nil { 111 if _, ok := err.(*find.NotFoundError); !ok { 112 return err 113 } 114 } 115 res.objects = append(res.objects, objects...) 116 } 117 118 if cmd.apps { 119 apps, err := finder.VirtualAppList(ctx, arg) 120 if err != nil { 121 if _, ok := err.(*find.NotFoundError); !ok { 122 return err 123 } 124 } 125 vapps = append(vapps, apps...) 126 } 127 } 128 129 if len(res.objects) != 0 { 130 refs := make([]types.ManagedObjectReference, 0, len(res.objects)) 131 for _, o := range res.objects { 132 refs = append(refs, o.Reference()) 133 } 134 135 pc := property.DefaultCollector(c) 136 err = pc.Retrieve(ctx, refs, props, &res.ResourcePools) 137 if err != nil { 138 return err 139 } 140 } 141 142 if len(vapps) != 0 { 143 var apps []mo.VirtualApp 144 refs := make([]types.ManagedObjectReference, 0, len(vapps)) 145 for _, o := range vapps { 146 refs = append(refs, o.Reference()) 147 p := object.NewResourcePool(c, o.Reference()) 148 p.InventoryPath = o.InventoryPath 149 res.objects = append(res.objects, p) 150 } 151 152 pc := property.DefaultCollector(c) 153 err = pc.Retrieve(ctx, refs, props, &apps) 154 if err != nil { 155 return err 156 } 157 158 for _, app := range apps { 159 res.ResourcePools = append(res.ResourcePools, app.ResourcePool) 160 } 161 } 162 163 return cmd.WriteResult(&res) 164 } 165 166 type infoResult struct { 167 ResourcePools []mo.ResourcePool `json:"resourcePools"` 168 objects []*object.ResourcePool 169 } 170 171 func (r *infoResult) Write(w io.Writer) error { 172 // Maintain order via r.objects as Property collector does not always return results in order. 173 objects := make(map[types.ManagedObjectReference]mo.ResourcePool, len(r.ResourcePools)) 174 for _, o := range r.ResourcePools { 175 objects[o.Reference()] = o 176 } 177 178 tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) 179 180 for _, o := range r.objects { 181 pool := objects[o.Reference()] 182 fmt.Fprintf(tw, "Name:\t%s\n", pool.Name) 183 fmt.Fprintf(tw, " Path:\t%s\n", o.InventoryPath) 184 185 writeInfo(tw, "CPU", "MHz", &pool.Runtime.Cpu, pool.Config.CpuAllocation) 186 pool.Runtime.Memory.MaxUsage >>= 20 187 pool.Runtime.Memory.OverallUsage >>= 20 188 writeInfo(tw, "Mem", "MB", &pool.Runtime.Memory, pool.Config.MemoryAllocation) 189 } 190 191 return tw.Flush() 192 } 193 194 func writeInfo(w io.Writer, name string, units string, ru *types.ResourcePoolResourceUsage, ra types.ResourceAllocationInfo) { 195 usage := 100.0 * float64(ru.OverallUsage) / float64(ru.MaxUsage) 196 shares := "" 197 limit := "unlimited" 198 199 if ra.Shares.Level == types.SharesLevelCustom { 200 shares = fmt.Sprintf(" (%d)", ra.Shares.Shares) 201 } 202 203 if ra.Limit != nil { 204 limit = fmt.Sprintf("%d%s", *ra.Limit, units) 205 } 206 207 fmt.Fprintf(w, " %s Usage:\t%d%s (%0.1f%%)\n", name, ru.OverallUsage, units, usage) 208 fmt.Fprintf(w, " %s Shares:\t%s%s\n", name, ra.Shares.Level, shares) 209 fmt.Fprintf(w, " %s Reservation:\t%d%s (expandable=%v)\n", name, *ra.Reservation, units, *ra.ExpandableReservation) 210 fmt.Fprintf(w, " %s Limit:\t%s\n", name, limit) 211 }