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  }