github.com/vmware/govmomi@v0.43.0/govc/vm/check/flag.go (about)

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