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  }