github.com/vmware/govmomi@v0.43.0/vim25/types/helpers.go (about) 1 /* 2 Copyright (c) 2015-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 types 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "fmt" 23 "net/url" 24 "reflect" 25 "strings" 26 "time" 27 ) 28 29 func EnumValuesAsStrings[T ~string](enumValues []T) []string { 30 stringValues := make([]string, len(enumValues)) 31 for i := range enumValues { 32 stringValues[i] = string(enumValues[i]) 33 } 34 return stringValues 35 } 36 37 func NewBool(v bool) *bool { 38 return &v 39 } 40 41 func NewInt32(v int32) *int32 { 42 return &v 43 } 44 45 func NewInt64(v int64) *int64 { 46 return &v 47 } 48 49 func NewTime(v time.Time) *time.Time { 50 return &v 51 } 52 53 func NewReference(r ManagedObjectReference) *ManagedObjectReference { 54 return &r 55 } 56 57 func (r ManagedObjectReference) Reference() ManagedObjectReference { 58 return r 59 } 60 61 func (r ManagedObjectReference) String() string { 62 return strings.Join([]string{r.Type, r.Value}, ":") 63 } 64 65 func (r *ManagedObjectReference) FromString(o string) bool { 66 s := strings.SplitN(o, ":", 2) 67 68 if len(s) != 2 { 69 return false 70 } 71 72 r.Type = s[0] 73 r.Value = s[1] 74 75 return true 76 } 77 78 // Encode ManagedObjectReference for use with URL and File paths 79 func (r ManagedObjectReference) Encode() string { 80 return strings.Join([]string{r.Type, url.QueryEscape(r.Value)}, "-") 81 } 82 83 func (c *PerfCounterInfo) Name() string { 84 return c.GroupInfo.GetElementDescription().Key + "." + c.NameInfo.GetElementDescription().Key + "." + string(c.RollupType) 85 } 86 87 func defaultResourceAllocationInfo() ResourceAllocationInfo { 88 return ResourceAllocationInfo{ 89 Reservation: NewInt64(0), 90 ExpandableReservation: NewBool(true), 91 Limit: NewInt64(-1), 92 Shares: &SharesInfo{ 93 Level: SharesLevelNormal, 94 }, 95 } 96 } 97 98 // DefaultResourceConfigSpec returns a ResourceConfigSpec populated with the same default field values as vCenter. 99 // Note that the wsdl marks these fields as optional, but they are required to be set when creating a resource pool. 100 // They are only optional when updating a resource pool. 101 func DefaultResourceConfigSpec() ResourceConfigSpec { 102 return ResourceConfigSpec{ 103 CpuAllocation: defaultResourceAllocationInfo(), 104 MemoryAllocation: defaultResourceAllocationInfo(), 105 } 106 } 107 108 // ToConfigSpec returns a VirtualMachineConfigSpec based on the 109 // VirtualMachineConfigInfo. 110 func (ci VirtualMachineConfigInfo) ToConfigSpec() VirtualMachineConfigSpec { 111 cs := VirtualMachineConfigSpec{ 112 ChangeVersion: ci.ChangeVersion, 113 Name: ci.Name, 114 Version: ci.Version, 115 CreateDate: ci.CreateDate, 116 Uuid: ci.Uuid, 117 InstanceUuid: ci.InstanceUuid, 118 NpivNodeWorldWideName: ci.NpivNodeWorldWideName, 119 NpivPortWorldWideName: ci.NpivPortWorldWideName, 120 NpivWorldWideNameType: ci.NpivWorldWideNameType, 121 NpivDesiredNodeWwns: ci.NpivDesiredNodeWwns, 122 NpivDesiredPortWwns: ci.NpivDesiredPortWwns, 123 NpivTemporaryDisabled: ci.NpivTemporaryDisabled, 124 NpivOnNonRdmDisks: ci.NpivOnNonRdmDisks, 125 LocationId: ci.LocationId, 126 GuestId: ci.GuestId, 127 AlternateGuestName: ci.AlternateGuestName, 128 Annotation: ci.Annotation, 129 Files: &ci.Files, 130 Tools: ci.Tools, 131 Flags: &ci.Flags, 132 ConsolePreferences: ci.ConsolePreferences, 133 PowerOpInfo: &ci.DefaultPowerOps, 134 RebootPowerOff: ci.RebootPowerOff, 135 NumCPUs: ci.Hardware.NumCPU, 136 VcpuConfig: ci.VcpuConfig, 137 NumCoresPerSocket: ci.Hardware.NumCoresPerSocket, 138 MemoryMB: int64(ci.Hardware.MemoryMB), 139 MemoryHotAddEnabled: ci.MemoryHotAddEnabled, 140 CpuHotAddEnabled: ci.CpuHotAddEnabled, 141 CpuHotRemoveEnabled: ci.CpuHotRemoveEnabled, 142 VirtualICH7MPresent: ci.Hardware.VirtualICH7MPresent, 143 VirtualSMCPresent: ci.Hardware.VirtualSMCPresent, 144 DeviceChange: nil, // See below 145 CpuAllocation: ci.CpuAllocation, 146 MemoryAllocation: ci.MemoryAllocation, 147 LatencySensitivity: ci.LatencySensitivity, 148 CpuAffinity: ci.CpuAffinity, 149 MemoryAffinity: ci.MemoryAffinity, 150 NetworkShaper: ci.NetworkShaper, 151 CpuFeatureMask: nil, // See below 152 ExtraConfig: ci.ExtraConfig, 153 SwapPlacement: ci.SwapPlacement, 154 BootOptions: ci.BootOptions, 155 FtInfo: ci.FtInfo, 156 RepConfig: ci.RepConfig, 157 VAssertsEnabled: ci.VAssertsEnabled, 158 ChangeTrackingEnabled: ci.ChangeTrackingEnabled, 159 Firmware: ci.Firmware, 160 MaxMksConnections: ci.MaxMksConnections, 161 GuestAutoLockEnabled: ci.GuestAutoLockEnabled, 162 ManagedBy: ci.ManagedBy, 163 MemoryReservationLockedToMax: ci.MemoryReservationLockedToMax, 164 NestedHVEnabled: ci.NestedHVEnabled, 165 VPMCEnabled: ci.VPMCEnabled, 166 MessageBusTunnelEnabled: ci.MessageBusTunnelEnabled, 167 MigrateEncryption: ci.MigrateEncryption, 168 FtEncryptionMode: ci.FtEncryptionMode, 169 SevEnabled: ci.SevEnabled, 170 MotherboardLayout: ci.Hardware.MotherboardLayout, 171 ScheduledHardwareUpgradeInfo: ci.ScheduledHardwareUpgradeInfo, 172 SgxInfo: ci.SgxInfo, 173 GuestMonitoringModeInfo: ci.GuestMonitoringModeInfo, 174 PmemFailoverEnabled: ci.PmemFailoverEnabled, 175 VmxStatsCollectionEnabled: ci.VmxStatsCollectionEnabled, 176 VmOpNotificationToAppEnabled: ci.VmOpNotificationToAppEnabled, 177 VmOpNotificationTimeout: ci.VmOpNotificationTimeout, 178 DeviceSwap: ci.DeviceSwap, 179 SimultaneousThreads: ci.Hardware.SimultaneousThreads, 180 Pmem: ci.Pmem, 181 DeviceGroups: ci.DeviceGroups, 182 FixedPassthruHotPlugEnabled: ci.FixedPassthruHotPlugEnabled, 183 MetroFtEnabled: ci.MetroFtEnabled, 184 MetroFtHostGroup: ci.MetroFtHostGroup, 185 } 186 187 // Unassign the Files field if all of its fields are empty. 188 if ci.Files.FtMetadataDirectory == "" && ci.Files.LogDirectory == "" && 189 ci.Files.SnapshotDirectory == "" && ci.Files.SuspendDirectory == "" && 190 ci.Files.VmPathName == "" { 191 cs.Files = nil 192 } 193 194 // Unassign the Flags field if all of its fields are empty. 195 if ci.Flags.CbrcCacheEnabled == nil && 196 ci.Flags.DisableAcceleration == nil && 197 ci.Flags.DiskUuidEnabled == nil && 198 ci.Flags.EnableLogging == nil && 199 ci.Flags.FaultToleranceType == "" && 200 ci.Flags.HtSharing == "" && 201 ci.Flags.MonitorType == "" && 202 ci.Flags.RecordReplayEnabled == nil && 203 ci.Flags.RunWithDebugInfo == nil && 204 ci.Flags.SnapshotDisabled == nil && 205 ci.Flags.SnapshotLocked == nil && 206 ci.Flags.SnapshotPowerOffBehavior == "" && 207 ci.Flags.UseToe == nil && 208 ci.Flags.VbsEnabled == nil && 209 ci.Flags.VirtualExecUsage == "" && 210 ci.Flags.VirtualMmuUsage == "" && 211 ci.Flags.VvtdEnabled == nil { 212 cs.Flags = nil 213 } 214 215 // Unassign the PowerOps field if all of its fields are empty. 216 if ci.DefaultPowerOps.DefaultPowerOffType == "" && 217 ci.DefaultPowerOps.DefaultResetType == "" && 218 ci.DefaultPowerOps.DefaultSuspendType == "" && 219 ci.DefaultPowerOps.PowerOffType == "" && 220 ci.DefaultPowerOps.ResetType == "" && 221 ci.DefaultPowerOps.StandbyAction == "" && 222 ci.DefaultPowerOps.SuspendType == "" { 223 cs.PowerOpInfo = nil 224 } 225 226 if l := len(ci.CpuFeatureMask); l > 0 { 227 cs.CpuFeatureMask = make([]VirtualMachineCpuIdInfoSpec, l) 228 for i := 0; i < l; i++ { 229 cs.CpuFeatureMask[i] = VirtualMachineCpuIdInfoSpec{ 230 ArrayUpdateSpec: ArrayUpdateSpec{ 231 Operation: ArrayUpdateOperationAdd, 232 }, 233 Info: &HostCpuIdInfo{ 234 Level: ci.CpuFeatureMask[i].Level, 235 Vendor: ci.CpuFeatureMask[i].Vendor, 236 Eax: ci.CpuFeatureMask[i].Eax, 237 Ebx: ci.CpuFeatureMask[i].Ebx, 238 Ecx: ci.CpuFeatureMask[i].Ecx, 239 Edx: ci.CpuFeatureMask[i].Edx, 240 }, 241 } 242 } 243 } 244 245 if l := len(ci.Hardware.Device); l > 0 { 246 cs.DeviceChange = make([]BaseVirtualDeviceConfigSpec, l) 247 for i := 0; i < l; i++ { 248 cs.DeviceChange[i] = &VirtualDeviceConfigSpec{ 249 Operation: VirtualDeviceConfigSpecOperationAdd, 250 FileOperation: VirtualDeviceConfigSpecFileOperationCreate, 251 Device: ci.Hardware.Device[i], 252 Profile: nil, 253 Backing: nil, 254 FilterSpec: nil, 255 } 256 } 257 } 258 259 if ni := ci.NumaInfo; ni != nil { 260 cs.VirtualNuma = &VirtualMachineVirtualNuma{ 261 CoresPerNumaNode: ni.CoresPerNumaNode, 262 ExposeVnumaOnCpuHotadd: ni.VnumaOnCpuHotaddExposed, 263 } 264 } 265 266 if civa, ok := ci.VAppConfig.(*VmConfigInfo); ok { 267 var csva VmConfigSpec 268 269 csva.Eula = civa.Eula 270 csva.InstallBootRequired = &civa.InstallBootRequired 271 csva.InstallBootStopDelay = civa.InstallBootStopDelay 272 273 ipAssignment := civa.IpAssignment 274 csva.IpAssignment = &ipAssignment 275 276 csva.OvfEnvironmentTransport = civa.OvfEnvironmentTransport 277 for i := range civa.OvfSection { 278 s := civa.OvfSection[i] 279 csva.OvfSection = append( 280 csva.OvfSection, 281 VAppOvfSectionSpec{ 282 ArrayUpdateSpec: ArrayUpdateSpec{ 283 Operation: ArrayUpdateOperationAdd, 284 }, 285 Info: &s, 286 }, 287 ) 288 } 289 290 for i := range civa.Product { 291 p := civa.Product[i] 292 csva.Product = append( 293 csva.Product, 294 VAppProductSpec{ 295 ArrayUpdateSpec: ArrayUpdateSpec{ 296 Operation: ArrayUpdateOperationAdd, 297 }, 298 Info: &p, 299 }, 300 ) 301 } 302 303 for i := range civa.Property { 304 p := civa.Property[i] 305 csva.Property = append( 306 csva.Property, 307 VAppPropertySpec{ 308 ArrayUpdateSpec: ArrayUpdateSpec{ 309 Operation: ArrayUpdateOperationAdd, 310 }, 311 Info: &p, 312 }, 313 ) 314 } 315 316 cs.VAppConfig = &csva 317 } 318 319 return cs 320 } 321 322 // ToString returns the string-ified version of the provided input value by 323 // first attempting to encode the value to JSON using the vimtype JSON encoder, 324 // and if that should fail, using the standard JSON encoder, and if that fails, 325 // returning the value formatted with Sprintf("%v"). 326 // 327 // Please note, this function is not intended to replace marshaling the data 328 // to JSON using the normal workflows. This function is for when a string-ified 329 // version of the data is needed for things like logging. 330 func ToString(in AnyType) (s string) { 331 if in == nil { 332 return "null" 333 } 334 335 marshalWithSprintf := func() string { 336 return fmt.Sprintf("%v", in) 337 } 338 339 defer func() { 340 if err := recover(); err != nil { 341 s = marshalWithSprintf() 342 } 343 }() 344 345 rv := reflect.ValueOf(in) 346 switch rv.Kind() { 347 348 case reflect.Bool, 349 reflect.Complex64, reflect.Complex128, 350 reflect.Float32, reflect.Float64: 351 352 return fmt.Sprintf("%v", in) 353 354 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 355 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 356 reflect.Uintptr: 357 358 return fmt.Sprintf("%d", in) 359 360 case reflect.String: 361 return in.(string) 362 363 case reflect.Interface, reflect.Pointer: 364 if rv.IsZero() { 365 return "null" 366 } 367 return ToString(rv.Elem().Interface()) 368 } 369 370 marshalWithStdlibJSONEncoder := func() string { 371 data, err := json.Marshal(in) 372 if err != nil { 373 return marshalWithSprintf() 374 } 375 return string(data) 376 } 377 378 defer func() { 379 if err := recover(); err != nil { 380 s = marshalWithStdlibJSONEncoder() 381 } 382 }() 383 384 var w bytes.Buffer 385 enc := NewJSONEncoder(&w) 386 if err := enc.Encode(in); err != nil { 387 return marshalWithStdlibJSONEncoder() 388 } 389 390 // Do not include the newline character added by the vimtype JSON encoder. 391 return strings.TrimSuffix(w.String(), "\n") 392 } 393 394 func init() { 395 // Known 6.5 issue where this event type is sent even though it is internal. 396 // This workaround allows us to unmarshal and avoid NPEs. 397 t["HostSubSpecificationUpdateEvent"] = reflect.TypeOf((*HostEvent)(nil)).Elem() 398 }