github.com/vmware/govmomi@v0.51.0/cli/datacenter/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 datacenter
     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/view"
    20  	"github.com/vmware/govmomi/vim25"
    21  	"github.com/vmware/govmomi/vim25/mo"
    22  	"github.com/vmware/govmomi/vim25/types"
    23  )
    24  
    25  type info struct {
    26  	*flags.ClientFlag
    27  	*flags.OutputFlag
    28  	*flags.DatacenterFlag
    29  }
    30  
    31  func init() {
    32  	cli.Register("datacenter.info", &info{})
    33  }
    34  
    35  func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
    36  	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
    37  	cmd.ClientFlag.Register(ctx, f)
    38  
    39  	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
    40  	cmd.OutputFlag.Register(ctx, f)
    41  
    42  	cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
    43  	cmd.DatacenterFlag.Register(ctx, f)
    44  }
    45  
    46  func (cmd *info) Process(ctx context.Context) error {
    47  	if err := cmd.ClientFlag.Process(ctx); err != nil {
    48  		return err
    49  	}
    50  	if err := cmd.OutputFlag.Process(ctx); err != nil {
    51  		return err
    52  	}
    53  	if err := cmd.DatacenterFlag.Process(ctx); err != nil {
    54  		return err
    55  	}
    56  	return nil
    57  }
    58  
    59  func (cmd *info) Usage() string {
    60  	return "[PATH]..."
    61  }
    62  
    63  func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
    64  	c, err := cmd.Client()
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	finder, err := cmd.Finder()
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	args := f.Args()
    75  	if len(args) == 0 {
    76  		args = []string{"*"}
    77  	}
    78  
    79  	var props []string
    80  	res := infoResult{
    81  		finder: finder,
    82  		ctx:    ctx,
    83  		client: c,
    84  	}
    85  
    86  	if !cmd.OutputFlag.All() {
    87  		props = []string{
    88  			"name",
    89  			"vmFolder",
    90  			"hostFolder",
    91  			"datastoreFolder",
    92  			"networkFolder",
    93  			"datastore",
    94  			"network",
    95  		}
    96  	}
    97  
    98  	for _, arg := range args {
    99  		objects, err := finder.DatacenterList(ctx, arg)
   100  		if err != nil {
   101  			return err
   102  		}
   103  		res.objects = append(res.objects, objects...)
   104  	}
   105  
   106  	if len(res.objects) != 0 {
   107  		refs := make([]types.ManagedObjectReference, 0, len(res.objects))
   108  		for _, o := range res.objects {
   109  			refs = append(refs, o.Reference())
   110  		}
   111  
   112  		pc := property.DefaultCollector(c)
   113  		err = pc.Retrieve(ctx, refs, props, &res.Datacenters)
   114  		if err != nil {
   115  			return err
   116  		}
   117  	}
   118  
   119  	return cmd.WriteResult(&res)
   120  }
   121  
   122  type infoResult struct {
   123  	Datacenters []mo.Datacenter `json:"datacenters"`
   124  	objects     []*object.Datacenter
   125  	finder      *find.Finder
   126  	ctx         context.Context
   127  	client      *vim25.Client
   128  }
   129  
   130  func (r *infoResult) Write(w io.Writer) error {
   131  	// Maintain order via r.objects as Property collector does not always return results in order.
   132  	objects := make(map[types.ManagedObjectReference]mo.Datacenter, len(r.Datacenters))
   133  	for _, o := range r.Datacenters {
   134  		objects[o.Reference()] = o
   135  	}
   136  
   137  	tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
   138  
   139  	for _, o := range r.objects {
   140  		dc := objects[o.Reference()]
   141  		fmt.Fprintf(tw, "Name:\t%s\n", dc.Name)
   142  		fmt.Fprintf(tw, "  Path:\t%s\n", o.InventoryPath)
   143  
   144  		r.finder.SetDatacenter(o)
   145  
   146  		hosts, _ := r.finder.HostSystemList(r.ctx, "*")
   147  		fmt.Fprintf(tw, "  Hosts:\t%d\n", len(hosts))
   148  
   149  		clusters, _ := r.finder.ClusterComputeResourceList(r.ctx, "*")
   150  		fmt.Fprintf(tw, "  Clusters:\t%d\n", len(clusters))
   151  
   152  		manager := view.NewManager(r.client)
   153  
   154  		v, err := manager.CreateContainerView(r.ctx, o.Reference(), []string{"VirtualMachine"}, true)
   155  		if err != nil {
   156  			return err
   157  		}
   158  
   159  		var vms []mo.VirtualMachine
   160  		err = v.Retrieve(r.ctx, []string{"VirtualMachine"}, []string{"summary.config.template"}, &vms)
   161  		if err != nil {
   162  			return err
   163  		}
   164  
   165  		defer func() {
   166  			_ = v.Destroy(r.ctx)
   167  		}()
   168  
   169  		totalVms := 0
   170  		for _, vm := range vms {
   171  			if vm.Summary.Config.Template {
   172  				continue
   173  			}
   174  			totalVms++
   175  		}
   176  
   177  		fmt.Fprintf(tw, "  Virtual Machines:\t%d\n", totalVms)
   178  
   179  		fmt.Fprintf(tw, "  Networks:\t%d\n", len(dc.Network))
   180  		fmt.Fprintf(tw, "  Datastores:\t%d\n", len(dc.Datastore))
   181  	}
   182  
   183  	return tw.Flush()
   184  }