github.com/vmware/govmomi@v0.51.0/cli/vm/check/flag.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 check
     6  
     7  import (
     8  	"context"
     9  	"flag"
    10  	"fmt"
    11  	"io"
    12  	"os"
    13  	"slices"
    14  	"strings"
    15  	"text/tabwriter"
    16  
    17  	"github.com/vmware/govmomi/cli/flags"
    18  	"github.com/vmware/govmomi/find"
    19  	"github.com/vmware/govmomi/object"
    20  	"github.com/vmware/govmomi/vim25/types"
    21  	"github.com/vmware/govmomi/vim25/xml"
    22  )
    23  
    24  var checkTestTypesList = []string{
    25  	string(types.CheckTestTypeDatastoreTests),
    26  	string(types.CheckTestTypeHostTests),
    27  	string(types.CheckTestTypeNetworkTests),
    28  	string(types.CheckTestTypeResourcePoolTests),
    29  	string(types.CheckTestTypeSourceTests),
    30  }
    31  
    32  type checkTestTypes []types.CheckTestType
    33  
    34  func (c *checkTestTypes) String() string {
    35  	return fmt.Sprint(*c)
    36  }
    37  
    38  func (c *checkTestTypes) Set(value string) error {
    39  	if !slices.Contains(checkTestTypesList, value) {
    40  		return fmt.Errorf("invalid CheckTestType value %q", value)
    41  	}
    42  	*c = append(*c, types.CheckTestType(value))
    43  	return nil
    44  }
    45  
    46  type checkFlag struct {
    47  	*flags.VirtualMachineFlag
    48  	*flags.HostSystemFlag
    49  	*flags.ResourcePoolFlag
    50  
    51  	Machine, Host, Pool *types.ManagedObjectReference
    52  
    53  	testTypes checkTestTypes
    54  }
    55  
    56  func (cmd *checkFlag) Register(ctx context.Context, f *flag.FlagSet) {
    57  	cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
    58  	cmd.VirtualMachineFlag.Register(ctx, f)
    59  	cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
    60  	cmd.HostSystemFlag.Register(ctx, f)
    61  	cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
    62  	cmd.ResourcePoolFlag.Register(ctx, f)
    63  
    64  	f.Var(&cmd.testTypes, "test", fmt.Sprintf("The set of tests to run (%s)", strings.Join(checkTestTypesList, ",")))
    65  }
    66  
    67  func (cmd *checkFlag) Process(ctx context.Context) error {
    68  	if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
    69  		return err
    70  	}
    71  	if err := cmd.HostSystemFlag.Process(ctx); err != nil {
    72  		return err
    73  	}
    74  	if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
    75  		return err
    76  	}
    77  
    78  	vm, err := cmd.VirtualMachine()
    79  	if err != nil {
    80  		return err
    81  	}
    82  	if vm != nil {
    83  		cmd.Machine = types.NewReference(vm.Reference())
    84  	}
    85  
    86  	host, err := cmd.HostSystemIfSpecified()
    87  	if err != nil {
    88  		return err
    89  	}
    90  	if host != nil {
    91  		cmd.Host = types.NewReference(host.Reference())
    92  	}
    93  
    94  	pool, err := cmd.ResourcePoolIfSpecified()
    95  	if err != nil {
    96  		return err
    97  	}
    98  	if pool != nil {
    99  		cmd.Pool = types.NewReference(pool.Reference())
   100  	}
   101  
   102  	return nil
   103  }
   104  
   105  func (cmd *checkFlag) provChecker() (*object.VmProvisioningChecker, error) {
   106  	c, err := cmd.VirtualMachineFlag.Client()
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  
   111  	return object.NewVmProvisioningChecker(c), nil
   112  }
   113  
   114  func (cmd *checkFlag) compatChecker() (*object.VmCompatibilityChecker, error) {
   115  	c, err := cmd.VirtualMachineFlag.Client()
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  
   120  	return object.NewVmCompatibilityChecker(c), nil
   121  }
   122  
   123  func (cmd *checkFlag) Spec(spec any) error {
   124  	dec := xml.NewDecoder(os.Stdin)
   125  	dec.TypeFunc = types.TypeFunc()
   126  	return dec.Decode(spec)
   127  }
   128  
   129  // return cmd.VirtualMachineFlag.WriteResult(&checkResult{res, ctx, cmd.VirtualMachineFlag})
   130  func (cmd *checkFlag) result(ctx context.Context, res []types.CheckResult) error {
   131  	return cmd.VirtualMachineFlag.WriteResult(&checkResult{res, ctx, cmd.VirtualMachineFlag})
   132  }
   133  
   134  type checkResult struct {
   135  	Result []types.CheckResult `json:"result"`
   136  	ctx    context.Context
   137  	vm     *flags.VirtualMachineFlag
   138  }
   139  
   140  func (res *checkResult) Write(w io.Writer) error {
   141  	tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
   142  
   143  	c, err := res.vm.Client()
   144  	if err != nil {
   145  		return err
   146  	}
   147  
   148  	for _, r := range res.Result {
   149  		fields := []struct {
   150  			name  string
   151  			moid  *types.ManagedObjectReference
   152  			fault []types.LocalizedMethodFault
   153  		}{
   154  			{"VM", r.Vm, nil},
   155  			{"Host", r.Host, nil},
   156  			{"Warning", nil, r.Warning},
   157  			{"Error", nil, r.Error},
   158  		}
   159  
   160  		for _, f := range fields {
   161  			var val string
   162  			if f.moid == nil {
   163  				var msgs []string
   164  				for _, m := range f.fault {
   165  					msgs = append(msgs, m.LocalizedMessage)
   166  				}
   167  				val = strings.Join(slices.Compact(msgs), "\n\t")
   168  			} else {
   169  				val, err = find.InventoryPath(res.ctx, c, *f.moid)
   170  				if err != nil {
   171  					return err
   172  				}
   173  			}
   174  			fmt.Fprintf(tw, "%s:\t%s\n", f.name, val)
   175  		}
   176  	}
   177  
   178  	return tw.Flush()
   179  }