github.com/vmware/govmomi@v0.51.0/cli/host/esxcli/model.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 esxcli
     6  
     7  import (
     8  	"context"
     9  	"encoding/json"
    10  	"flag"
    11  	"fmt"
    12  	"io"
    13  	"strings"
    14  	"text/tabwriter"
    15  
    16  	"github.com/vmware/govmomi/cli"
    17  	"github.com/vmware/govmomi/cli/esx"
    18  	"github.com/vmware/govmomi/cli/flags"
    19  	"github.com/vmware/govmomi/internal"
    20  )
    21  
    22  type model struct {
    23  	*flags.HostSystemFlag
    24  
    25  	types     bool
    26  	commands  bool
    27  	instances bool
    28  }
    29  
    30  func init() {
    31  	cli.Register("host.esxcli.model", &model{}, true)
    32  }
    33  
    34  func (cmd *model) Usage() string {
    35  	return "[NAMESPACE]..."
    36  }
    37  
    38  func (cmd *model) Description() string {
    39  	return `Print esxcli model for HOST.
    40  
    41  Examples:
    42    govc host.esxcli.model # prints type model supported by vcsim
    43    govc host.esxcli.model network.vm network.ip.connection # specific namespaces
    44    govc host.esxcli.model -dump # generate simulator/esx/type_info.go
    45    govc host.esxcli.model -c # prints commands supported by vcsim
    46    govc host.esxcli.model -c network.vm`
    47  }
    48  
    49  func (cmd *model) Register(ctx context.Context, f *flag.FlagSet) {
    50  	cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
    51  	cmd.HostSystemFlag.Register(ctx, f)
    52  
    53  	f.BoolVar(&cmd.types, "t", true, "Print type info")
    54  	f.BoolVar(&cmd.commands, "c", false, "Print command info")
    55  	f.BoolVar(&cmd.instances, "i", false, "Print instances")
    56  }
    57  
    58  var namespaces = []string{
    59  	"hardware.clock",
    60  	"hardware.platform",
    61  	"iscsi.software",
    62  	"network.firewall",
    63  	"network.ip.connection",
    64  	"network.nic.ring.current",
    65  	"network.nic.ring.preset",
    66  	"network.vm",
    67  	"software.vib",
    68  	"system.hostname",
    69  	"system.settings.advanced",
    70  	"system.stats.uptime",
    71  	"vm.process",
    72  }
    73  
    74  type modelInfo struct {
    75  	CommandInfo []esx.CommandInfo
    76  	TypeInfo    internal.DynamicTypeMgrAllTypeInfo
    77  	Instances   []internal.DynamicTypeMgrMoInstance
    78  }
    79  
    80  func (r modelInfo) Dump() any {
    81  	if len(r.CommandInfo) != 0 {
    82  		return r.CommandInfo
    83  	}
    84  	if len(r.Instances) != 0 {
    85  		return r.Instances
    86  	}
    87  	return r.TypeInfo
    88  }
    89  
    90  func (r modelInfo) MarshalJSON() ([]byte, error) {
    91  	return json.Marshal(r.Dump())
    92  }
    93  
    94  func (r modelInfo) Write(w io.Writer) error {
    95  	for _, item := range r.CommandInfo {
    96  		ns := strings.ReplaceAll(item.Name, ".", " ")
    97  
    98  		for _, m := range item.Method {
    99  			tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
   100  			fmt.Fprintf(tw, "%s %s\n", ns, m.Name)
   101  
   102  			for _, p := range m.Param {
   103  				fmt.Fprintf(tw, "  %s\t%s\n", p.Name, p.Aliases)
   104  			}
   105  
   106  			_ = tw.Flush()
   107  		}
   108  	}
   109  
   110  	for _, obj := range r.TypeInfo.ManagedTypeInfo {
   111  		for _, m := range obj.Method {
   112  			if m.ReturnTypeInfo == nil {
   113  				continue
   114  			}
   115  
   116  			var param []string
   117  			for _, p := range m.ParamTypeInfo {
   118  				param = append(param, p.Name+" "+p.Type)
   119  			}
   120  
   121  			fmt.Fprintf(w, "func %s.%s(%s) %s\n",
   122  				obj.Name, m.Name,
   123  				strings.Join(param, ", "),
   124  				m.ReturnTypeInfo.Type)
   125  		}
   126  	}
   127  
   128  	tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
   129  	for _, obj := range r.TypeInfo.DataTypeInfo {
   130  		fmt.Fprintf(tw, "type %s struct = {\n", obj.Name)
   131  		for _, p := range obj.Property {
   132  			fmt.Fprintf(tw, "    %s\t%s\n", p.Name, p.Type)
   133  		}
   134  		fmt.Fprintln(tw, "}")
   135  	}
   136  	_ = tw.Flush()
   137  
   138  	return nil
   139  }
   140  
   141  func (cmd *model) typeInfo(ctx context.Context, e *esx.Executor, args []string) (internal.DynamicTypeMgrAllTypeInfo, error) {
   142  	var info internal.DynamicTypeMgrAllTypeInfo
   143  
   144  	for _, ns := range args {
   145  		req := internal.DynamicTypeMgrQueryTypeInfoRequest{
   146  			This: e.DynamicTypeManager(),
   147  			FilterSpec: &internal.DynamicTypeMgrTypeFilterSpec{
   148  				TypeSubstr: ns,
   149  			},
   150  		}
   151  
   152  		res, err := internal.DynamicTypeMgrQueryTypeInfo(ctx, e.Client(), &req)
   153  		if err != nil {
   154  			return info, err
   155  		}
   156  
   157  		info.DataTypeInfo = append(info.DataTypeInfo, res.Returnval.DataTypeInfo...)
   158  		info.EnumTypeInfo = append(info.EnumTypeInfo, res.Returnval.EnumTypeInfo...)
   159  		info.ManagedTypeInfo = append(info.ManagedTypeInfo, res.Returnval.ManagedTypeInfo...)
   160  	}
   161  
   162  	return info, nil
   163  }
   164  
   165  func (cmd *model) commandInfo(ctx context.Context, e *esx.Executor, args []string) ([]esx.CommandInfo, error) {
   166  	var info []esx.CommandInfo
   167  
   168  	for _, ns := range args {
   169  		c, err := e.CommandInfo(ctx, ns)
   170  		if err != nil {
   171  			return nil, err
   172  		}
   173  
   174  		info = append(info, *c)
   175  	}
   176  
   177  	return info, nil
   178  }
   179  
   180  func (cmd *model) instanceInfo(ctx context.Context, e *esx.Executor, args []string) ([]internal.DynamicTypeMgrMoInstance, error) {
   181  	var info []internal.DynamicTypeMgrMoInstance
   182  
   183  	req := internal.DynamicTypeMgrQueryMoInstancesRequest{
   184  		This: e.DynamicTypeManager(),
   185  	}
   186  
   187  	res, err := internal.DynamicTypeMgrQueryMoInstances(ctx, e.Client(), &req)
   188  	if err != nil {
   189  		return nil, err
   190  	}
   191  
   192  	for _, i := range res.Returnval {
   193  		for _, ns := range args {
   194  			if !strings.HasPrefix(ns, "vim.") {
   195  				ns = "vim.EsxCLI." + ns
   196  			}
   197  
   198  			if ns == i.MoType {
   199  				info = append(info, i)
   200  				break
   201  			}
   202  		}
   203  	}
   204  
   205  	return info, nil
   206  }
   207  
   208  func (cmd *model) Run(ctx context.Context, f *flag.FlagSet) error {
   209  	args := f.Args()
   210  	if len(args) == 0 {
   211  		args = namespaces
   212  	}
   213  
   214  	c, err := cmd.Client()
   215  	if err != nil {
   216  		return err
   217  	}
   218  
   219  	host, err := cmd.HostSystem()
   220  	if err != nil {
   221  		return err
   222  	}
   223  
   224  	e, err := esx.NewExecutor(ctx, c, host)
   225  	if err != nil {
   226  		return err
   227  	}
   228  
   229  	if cmd.commands || cmd.instances {
   230  		cmd.types = false
   231  	}
   232  
   233  	var res modelInfo
   234  
   235  	if cmd.commands {
   236  		res.CommandInfo, err = cmd.commandInfo(ctx, e, args)
   237  		if err != nil {
   238  			return err
   239  		}
   240  	}
   241  
   242  	if cmd.types {
   243  		res.TypeInfo, err = cmd.typeInfo(ctx, e, args)
   244  		if err != nil {
   245  			return err
   246  		}
   247  	}
   248  
   249  	if cmd.instances {
   250  		res.Instances, err = cmd.instanceInfo(ctx, e, args)
   251  		if err != nil {
   252  			return err
   253  		}
   254  		if !cmd.All() {
   255  			cmd.JSON = true
   256  		}
   257  	}
   258  
   259  	return cmd.WriteResult(&res)
   260  }