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