github.com/vmware/govmomi@v0.51.0/simulator/esxcli.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 simulator 6 7 import ( 8 "bytes" 9 "fmt" 10 "reflect" 11 "strconv" 12 "strings" 13 "time" 14 15 esxcli "github.com/vmware/govmomi/cli/esx" 16 "github.com/vmware/govmomi/internal" 17 "github.com/vmware/govmomi/simulator/esx" 18 "github.com/vmware/govmomi/vim25/mo" 19 "github.com/vmware/govmomi/vim25/soap" 20 "github.com/vmware/govmomi/vim25/types" 21 "github.com/vmware/govmomi/vim25/xml" 22 ) 23 24 type DynamicTypeManager struct { 25 types.ManagedObjectReference 26 } 27 28 type ManagedMethodExecuter struct { 29 types.ManagedObjectReference 30 31 h *HostSystem 32 } 33 34 var esxcliNotFound = &types.LocalizedMethodFault{ 35 Fault: new(types.NotFound), 36 LocalizedMessage: "The object or item referred to could not be found.", 37 } 38 39 func esxcliFault(msg ...string) *types.LocalizedMethodFault { 40 return &types.LocalizedMethodFault{ 41 Fault: &internal.VimEsxCLICLIFault{ErrMsg: msg}, 42 LocalizedMessage: "EsxCLI.CLIFault.summary", 43 } 44 } 45 46 func (h *HostSystem) RetrieveManagedMethodExecuter(ctx *Context, req *internal.RetrieveManagedMethodExecuterRequest) soap.HasFault { 47 if h.mme == nil { 48 h.mme = &ManagedMethodExecuter{ 49 types.ManagedObjectReference{Type: "ManagedMethodExecuter", Value: h.Self.Value}, 50 h, 51 } 52 ctx.Map.Put(h.mme) 53 } 54 55 return &internal.RetrieveManagedMethodExecuterBody{ 56 Res: &internal.RetrieveManagedMethodExecuterResponse{ 57 Returnval: &internal.ReflectManagedMethodExecuter{ 58 ManagedObjectReference: h.mme.Reference(), 59 }, 60 }, 61 } 62 } 63 64 func (h *HostSystem) RetrieveDynamicTypeManager(ctx *Context, req *internal.RetrieveDynamicTypeManagerRequest) soap.HasFault { 65 if h.dtm == nil { 66 h.dtm = &DynamicTypeManager{ 67 types.ManagedObjectReference{Type: "DynamicTypeManager", Value: h.Self.Value}, 68 } 69 ctx.Map.Put(h.dtm) 70 } 71 72 return &internal.RetrieveDynamicTypeManagerBody{ 73 Res: &internal.RetrieveDynamicTypeManagerResponse{ 74 Returnval: &internal.InternalDynamicTypeManager{ 75 ManagedObjectReference: h.dtm.Reference(), 76 }, 77 }, 78 } 79 } 80 81 func (*DynamicTypeManager) DynamicTypeMgrQueryTypeInfo(ctx *Context, req *internal.DynamicTypeMgrQueryTypeInfoRequest) soap.HasFault { 82 all := esx.TypeInfo 83 84 if spec, ok := req.FilterSpec.(*internal.DynamicTypeMgrTypeFilterSpec); ok { 85 all = internal.DynamicTypeMgrAllTypeInfo{} 86 87 for _, info := range esx.TypeInfo.DataTypeInfo { 88 if strings.Contains(info.Name, spec.TypeSubstr) { 89 all.DataTypeInfo = append(all.DataTypeInfo, info) 90 } 91 } 92 93 for _, info := range esx.TypeInfo.EnumTypeInfo { 94 if strings.Contains(info.Name, spec.TypeSubstr) { 95 all.EnumTypeInfo = append(all.EnumTypeInfo, info) 96 } 97 } 98 99 for _, info := range esx.TypeInfo.ManagedTypeInfo { 100 if strings.Contains(info.Name, spec.TypeSubstr) { 101 all.ManagedTypeInfo = append(all.ManagedTypeInfo, info) 102 } 103 } 104 } 105 106 body := &internal.DynamicTypeMgrQueryTypeInfoBody{ 107 Res: &internal.DynamicTypeMgrQueryTypeInfoResponse{ 108 Returnval: all, 109 }, 110 } 111 112 return body 113 } 114 115 func (m *DynamicTypeManager) DynamicTypeMgrQueryMoInstances(ctx *Context, req *internal.DynamicTypeMgrQueryMoInstancesRequest) soap.HasFault { 116 body := &internal.DynamicTypeMgrQueryMoInstancesBody{ 117 Res: &internal.DynamicTypeMgrQueryMoInstancesResponse{ 118 Returnval: nil, 119 }, 120 } 121 122 return body 123 } 124 125 func (m *ManagedMethodExecuter) VimCLIInfoFetchCLIInfo(_ *Context, args esxcli.Values) (*esxcli.CommandInfo, *types.LocalizedMethodFault) { 126 kind := args.Value("typeName") 127 kind = strings.TrimPrefix(kind, "vim.EsxCLI.") 128 129 for _, info := range esx.CommandInfo { 130 if info.CommandInfoItem.Name == kind { 131 return &info, nil 132 } 133 } 134 135 return nil, esxcliNotFound 136 } 137 138 // sample from: govc host.esxcli -dump software vib get 139 var softwareVib = []esxcli.Values{ 140 { 141 "AcceptanceLevel": []string{"VMwareCertified"}, 142 "CreationDate": []string{"2023-03-22"}, 143 "Depends": []string{"esx-version >= 5.0.0"}, 144 "Description": []string{"An embedded web UI for ESXi"}, 145 "ID": []string{"VMware_bootbank_esx-ui_2.12.0-21482143"}, 146 "InstallDate": []string{"2023-03-28"}, 147 "LiveInstallAllowed": []string{"True"}, 148 "LiveRemoveAllowed": []string{"True"}, 149 "MaintenanceModeRequired": []string{"False"}, 150 "Name": []string{"esx-ui"}, 151 "Overlay": []string{"False"}, 152 "Payloads": []string{"esx-ui"}, 153 "Platforms": []string{"host"}, 154 "StatelessReady": []string{"True"}, 155 "Status": []string{""}, 156 "Summary": []string{"VMware Host Client"}, 157 "Type": []string{"bootbank"}, 158 "Vendor": []string{"VMware"}, 159 "Version": []string{"2.12.0-21482143"}, 160 }, 161 { 162 "AcceptanceLevel": []string{"VMwareCertified"}, 163 "CreationDate": []string{"2023-03-25"}, 164 "Depends": []string{"vmkapi_2_11_0_0", "vmkapi_incompat_2_11_0_0"}, 165 "Description": []string{"Intel DW GPIO controller driver"}, 166 "ID": []string{"VMW_bootbank_intelgpio_0.1-1vmw.801.0.0.21495797"}, 167 "InstallDate": []string{"2023-03-28"}, 168 "LiveInstallAllowed": []string{"False"}, 169 "LiveRemoveAllowed": []string{"False"}, 170 "MaintenanceModeRequired": []string{"True"}, 171 "Name": []string{"intelgpio"}, 172 "Overlay": []string{"False"}, 173 "Payloads": []string{"intelgpi"}, 174 "Platforms": []string{"host"}, 175 "StatelessReady": []string{"True"}, 176 "Status": []string{""}, 177 "Summary": []string{"VMware Esx VIB"}, 178 "Tags": []string{"RestrictStickyFiles", "module", "driver", "sdkname:esx", "sdkversion:8.0.1-21495797"}, 179 "Type": []string{"bootbank"}, 180 "Vendor": []string{"VMW"}, 181 "Version": []string{"0.1-1vmw.801.0.0.21495797"}, 182 }, 183 } 184 185 func (m *ManagedMethodExecuter) VimEsxCLISoftwareVibGet(_ *Context, args esxcli.Values) (*esxcli.Response, *types.LocalizedMethodFault) { 186 r := esxcli.Response{Kind: "VIBExt"} 187 188 name := args.Value("vibname") 189 190 if name != "" { 191 for _, vib := range softwareVib { 192 if vib.Value("Name") == name { 193 r.Values = append(r.Values, vib) 194 return &r, nil 195 } 196 } 197 return nil, esxcliFault("[NoMatchError]", "id="+name) 198 } 199 200 r.Values = softwareVib 201 202 return &r, nil 203 } 204 205 func (m *ManagedMethodExecuter) VimEsxCLISoftwareVibList(_ *Context, args esxcli.Values) (*esxcli.Response, *types.LocalizedMethodFault) { 206 r := esxcli.Response{Kind: "SummaryExt"} 207 208 r.Values = softwareVib // TODO: subset of VibGet fields 209 210 return &r, nil 211 } 212 213 func (m *ManagedMethodExecuter) VimEsxCLIHardwareClockGet(_ *Context, _ esxcli.Values) (*esxcli.Response, *types.LocalizedMethodFault) { 214 return &esxcli.Response{ 215 Kind: "string", 216 String: time.Now().UTC().Format(time.RFC3339), 217 }, nil 218 } 219 220 func (m *ManagedMethodExecuter) VimEsxCLINetworkFirewallGet(ctx *Context, args esxcli.Values) (*esxcli.Response, *types.LocalizedMethodFault) { 221 r := esxcli.Response{ 222 Kind: "Firewall", 223 Values: []esxcli.Values{{ 224 "DefaultAction": []string{"DROP"}, 225 "Enabled": []string{"false"}, 226 "Loaded": []string{"true"}, 227 }}, 228 } 229 230 return &r, nil 231 } 232 233 func (m *ManagedMethodExecuter) VimEsxCLINetworkVmList(ctx *Context, _ esxcli.Values) (*esxcli.Response, *types.LocalizedMethodFault) { 234 r := esxcli.Response{Kind: "VM"} 235 236 for _, ref := range m.h.Vm { 237 vm := ctx.Map.Get(ref).(*VirtualMachine) 238 239 var networks []string 240 for _, ref := range vm.Network { 241 name := entityName(ctx.Map.Get(ref).(mo.Entity)) 242 networks = append(networks, name) 243 } 244 245 r.Values = append(r.Values, esxcli.Values{ 246 "Name": []string{vm.Name}, 247 "Networks": networks, 248 "NumPorts": []string{strconv.Itoa(len(networks))}, 249 "WorldID": []string{strconv.Itoa(vm.worldID())}, 250 }) 251 } 252 253 return &r, nil 254 } 255 256 // sample from: govc host.esxcli -dump network ip connection list 257 var networkIpConnectionList = []esxcli.Values{ 258 { 259 "CCAlgo": []string{"newreno"}, 260 "ForeignAddress": []string{"0.0.0.0:0"}, 261 "LocalAddress": []string{"0.0.0.0:443"}, 262 "Proto": []string{"tcp"}, 263 "RecvQ": []string{"0"}, 264 "SendQ": []string{"0"}, 265 "State": []string{"LISTEN"}, 266 "WorldID": []string{"525276"}, 267 "WorldName": []string{"envoy"}, 268 }, 269 { 270 "CCAlgo": []string{""}, 271 "ForeignAddress": []string{"0.0.0.0:0"}, 272 "LocalAddress": []string{"127.0.0.1:123"}, 273 "Proto": []string{"udp"}, 274 "RecvQ": []string{"0"}, 275 "SendQ": []string{"0"}, 276 "State": []string{""}, 277 "WorldID": []string{"530726"}, 278 "WorldName": []string{"ntpd"}, 279 }, 280 } 281 282 func (m *ManagedMethodExecuter) VimEsxCLINetworkIpConnectionList(_ *Context, args esxcli.Values) (*esxcli.Response, *types.LocalizedMethodFault) { 283 r := esxcli.Response{Kind: "IpConnection"} 284 285 kind := args.Value("type") 286 if kind != "" && kind != "tcp" { // ip, tcp, udp, all 287 return nil, esxcliFault("Invalid data constraint for parameter 'type'.") 288 } 289 290 r.Values = networkIpConnectionList 291 292 return &r, nil 293 } 294 295 // sample from: govc host.esxcli -dump system settings advanced list 296 var systemSettingsAdvancedList = []esxcli.Values{ 297 { 298 "DefaultIntValue": []string{"2"}, 299 "Description": []string{"PShare salting allows for sharing isolation between multiple VM"}, 300 "HostSpecific": []string{"false"}, 301 "Impact": []string{"none"}, 302 "IntValue": []string{"2"}, 303 "MaxValue": []string{"2"}, 304 "MinValue": []string{"0"}, 305 "Path": []string{"/Mem/ShareForceSalting"}, 306 "Type": []string{"integer"}, 307 }, 308 { 309 "DefaultIntValue": []string{"0"}, 310 "Description": []string{"Enable guest arp inspection IOChain to get IP"}, 311 "HostSpecific": []string{"false"}, 312 "Impact": []string{"none"}, 313 "IntValue": []string{"1"}, 314 "MaxValue": []string{"1"}, 315 "MinValue": []string{"0"}, 316 "Path": []string{"/Net/GuestIPHack"}, 317 "Type": []string{"integer"}, 318 }, 319 } 320 321 func (m *ManagedMethodExecuter) VimEsxCLISystemSettingsAdvancedList(_ *Context, args esxcli.Values) (*esxcli.Response, *types.LocalizedMethodFault) { 322 r := esxcli.Response{Kind: "SettingsAdvancedOption"} 323 324 option := args.Value("option") 325 if option != "" { 326 for _, s := range systemSettingsAdvancedList { 327 if s.Value("Path") == option { 328 r.Values = append(r.Values, s) 329 return &r, nil 330 } 331 } 332 return nil, esxcliFault("Unable to find option") 333 } 334 335 r.Values = systemSettingsAdvancedList 336 337 return &r, nil 338 } 339 340 func (m *ManagedMethodExecuter) VimEsxCLIVmProcessList(ctx *Context, _ esxcli.Values) (*esxcli.Response, *types.LocalizedMethodFault) { 341 r := esxcli.Response{Kind: "VirtualMachine"} 342 343 for _, ref := range m.h.Vm { 344 vm := ctx.Map.Get(ref).(*VirtualMachine) 345 346 r.Values = append(r.Values, esxcli.Values{ 347 "ConfigFile": []string{vm.Config.Files.VmPathName}, 348 "DisplayName": []string{vm.Name}, 349 "ProcessID": []string{"0"}, 350 "UUID": []string{vm.uid.String()}, 351 "VMXCartelID": []string{strconv.Itoa(vm.worldID() + 1)}, 352 "WorldID": []string{strconv.Itoa(vm.worldID())}, 353 }) 354 } 355 356 return &r, nil 357 } 358 359 func (m *ManagedMethodExecuter) VimEsxCLIIscsiSoftwareGet(_ *Context, _ esxcli.Values) (*esxcli.Response, *types.LocalizedMethodFault) { 360 return &esxcli.Response{Kind: "boolean", String: "false"}, nil 361 } 362 363 var boot = time.Now() 364 365 func (m *ManagedMethodExecuter) VimEsxCLISystemStatsUptimeGet(_ *Context, _ esxcli.Values) (*esxcli.Response, *types.LocalizedMethodFault) { 366 uptime := fmt.Sprintf("%d", time.Since(boot)) 367 return &esxcli.Response{Kind: "long", String: uptime}, nil 368 } 369 370 func (_ *ManagedMethodExecuter) toXML(v any) string { 371 var out bytes.Buffer 372 373 err := xml.NewEncoder(&out).Encode(v) 374 if err != nil { 375 panic(err) 376 } 377 378 return out.String() 379 } 380 381 func (m *ManagedMethodExecuter) ExecuteSoap(ctx *Context, req *internal.ExecuteSoapRequest) soap.HasFault { 382 res := new(internal.ReflectManagedMethodExecuterSoapResult) 383 384 args := esxcli.Values{} 385 for _, arg := range req.Argument { 386 args[arg.Name] = arg.Value() 387 } 388 389 name := internal.EsxcliName(req.Method) 390 method := reflect.ValueOf(m).MethodByName(name) 391 392 var val types.AnyType 393 err := esxcliNotFound 394 395 if method.IsValid() { 396 ret := method.Call([]reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(args)}) 397 val = ret[0].Interface() 398 err = ret[1].Interface().(*types.LocalizedMethodFault) 399 } 400 401 if err == nil { 402 if r, ok := val.(*esxcli.Response); ok { 403 if r.String == "" { 404 // DataObject xsi:type has method name prefix 405 r.Kind = strings.ReplaceAll(ucFirst(req.Method), ".", "") + r.Kind 406 } 407 } 408 res.Response = m.toXML(val) 409 } else { 410 res.Fault = &internal.ReflectManagedMethodExecuterSoapFault{ 411 FaultMsg: err.LocalizedMessage, 412 FaultDetail: m.toXML(err), 413 } 414 } 415 416 return &internal.ExecuteSoapBody{ 417 Res: &internal.ExecuteSoapResponse{ 418 Returnval: res, 419 }, 420 } 421 }