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 }