github.com/vmware/govmomi@v0.51.0/ovf/configspec_test.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 ovf
     6  
     7  import (
     8  	"bytes"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  
    13  	"github.com/vmware/govmomi/vim25/types"
    14  )
    15  
    16  func TestEnvelopeToConfigSpec(t *testing.T) {
    17  
    18  	t.Run("Strict", func(t *testing.T) {
    19  		t.Run("Unsupported ResourceType", func(t *testing.T) {
    20  			e := testEnvelope(t, "fixtures/unsupported-resourcetype.ovf")
    21  			_, err := e.ToConfigSpecWithOptions(ToConfigSpecOptions{Strict: true})
    22  			if assert.Error(t, err) {
    23  				assert.Contains(t, err.Error(), "unsupported resource type")
    24  				if ovfErr, ok := AsErrUnsupportedItem(err); assert.True(t, ok) {
    25  					assert.Equal(t, ovfErr.Index, 2)
    26  					assert.Equal(t, ovfErr.InstanceID, "3")
    27  					assert.Equal(t, ovfErr.Name, "invalidResourceType")
    28  					assert.Equal(t, ovfErr.ResourceType, CIMResourceType(35))
    29  					assert.Equal(t, ovfErr.ResourceSubType, "")
    30  				}
    31  			}
    32  		})
    33  		t.Run("Unsupported ResourceSubType", func(t *testing.T) {
    34  			e := testEnvelope(t, "fixtures/unsupported-resourcesubtype.ovf")
    35  			_, err := e.ToConfigSpecWithOptions(ToConfigSpecOptions{Strict: true})
    36  			if assert.Error(t, err) {
    37  				assert.Contains(t, err.Error(), "unsupported resource subtype")
    38  				if ovfErr, ok := AsErrUnsupportedItem(err); assert.True(t, ok) {
    39  					assert.Equal(t, ovfErr.Index, 2)
    40  					assert.Equal(t, ovfErr.InstanceID, "3")
    41  					assert.Equal(t, ovfErr.Name, "invalidResourceSubType")
    42  					assert.Equal(t, ovfErr.ResourceType, CIMResourceType(1))
    43  					assert.Equal(t, ovfErr.ResourceSubType, "invalidresourcesubtype")
    44  				}
    45  			}
    46  		})
    47  	})
    48  
    49  	t.Run("Photon 5", func(t *testing.T) {
    50  		e := testEnvelope(t, "fixtures/photon5.ovf")
    51  		cs, err := e.ToConfigSpec()
    52  		assert.NoError(t, err)
    53  		assert.NotEmpty(t, cs)
    54  
    55  		if testing.Verbose() {
    56  			var w bytes.Buffer
    57  			enc := types.NewJSONEncoder(&w)
    58  			enc.SetIndent("", "    ")
    59  			assert.NoError(t, enc.Encode(cs))
    60  			t.Logf("\n\nconfigSpec=%s\n\n", w.String())
    61  		}
    62  	})
    63  
    64  	t.Run("Ubuntu 24.10", func(t *testing.T) {
    65  		e := testEnvelope(t, "fixtures/ubuntu24.10.ovf")
    66  		cs, err := e.ToConfigSpec()
    67  		assert.NoError(t, err)
    68  		assert.NotEmpty(t, cs)
    69  
    70  		if testing.Verbose() {
    71  			var w bytes.Buffer
    72  			enc := types.NewJSONEncoder(&w)
    73  			enc.SetIndent("", "    ")
    74  			assert.NoError(t, enc.Encode(cs))
    75  			t.Logf("\n\nconfigSpec=%s\n\n", w.String())
    76  		}
    77  	})
    78  
    79  	t.Run("Large", func(t *testing.T) {
    80  		e := testEnvelope(t, "fixtures/configspec.ovf")
    81  		cs, err := e.ToConfigSpec()
    82  		assert.NoError(t, err)
    83  		assert.NotEmpty(t, cs)
    84  
    85  		if testing.Verbose() {
    86  			var w bytes.Buffer
    87  			enc := types.NewJSONEncoder(&w)
    88  			enc.SetIndent("", "    ")
    89  			assert.NoError(t, enc.Encode(cs))
    90  			t.Logf("\n\nconfigSpec=%s\n\n", w.String())
    91  		}
    92  
    93  		assert.Equal(t, "haproxy", cs.Name)
    94  		assert.Equal(t, int32(2), cs.NumCPUs)
    95  		assert.Equal(t, int32(2), cs.NumCoresPerSocket)
    96  		assert.Equal(t, int64(4096), cs.MemoryMB)
    97  		assert.Equal(t, "vmx-13", cs.Version)
    98  
    99  		if assert.Len(t, cs.DeviceChange, 21) {
   100  
   101  			var scsiController1Key int32
   102  			if d, ok := cs.DeviceChange[0].GetVirtualDeviceConfigSpec().Device.(*types.VirtualLsiLogicController); assert.True(t, ok) {
   103  				scsiController1Key = d.Key
   104  				assert.Equal(t, int32(0), d.BusNumber)
   105  				if assert.NotNil(t, d.SlotInfo) {
   106  					si, ok := d.SlotInfo.(*types.VirtualDevicePciBusSlotInfo)
   107  					assert.True(t, ok)
   108  					assert.Equal(t, int32(128), si.PciSlotNumber)
   109  				}
   110  			}
   111  
   112  			if d, ok := cs.DeviceChange[1].GetVirtualDeviceConfigSpec().Device.(*types.VirtualDisk); assert.True(t, ok) {
   113  				assert.Equal(t, scsiController1Key, d.ControllerKey)
   114  				if assert.NotNil(t, d.UnitNumber) {
   115  					assert.Equal(t, int32(0), *d.UnitNumber)
   116  				}
   117  				db, ok := d.Backing.(*types.VirtualDiskFlatVer2BackingInfo)
   118  				assert.True(t, ok)
   119  				assert.Equal(t, string(types.VirtualDiskModePersistent), db.DiskMode)
   120  				if assert.NotNil(t, db.ThinProvisioned) {
   121  					assert.True(t, *db.ThinProvisioned)
   122  				}
   123  				assert.Equal(t, int64(20*1024*1024*1024), d.CapacityInBytes)
   124  			}
   125  
   126  			if bd, ok := cs.DeviceChange[2].GetVirtualDeviceConfigSpec().Device.(types.BaseVirtualEthernetCard); assert.True(t, ok) {
   127  				d := bd.GetVirtualEthernetCard()
   128  				if assert.NotNil(t, d.UnitNumber) {
   129  					assert.Equal(t, int32(2), *d.UnitNumber)
   130  				}
   131  				if assert.NotNil(t, d.Connectable) {
   132  					assert.True(t, d.Connectable.AllowGuestControl)
   133  				}
   134  				if assert.NotNil(t, d.WakeOnLanEnabled) {
   135  					assert.False(t, *d.WakeOnLanEnabled)
   136  				}
   137  				if assert.NotNil(t, d.SlotInfo) {
   138  					si, ok := d.SlotInfo.(*types.VirtualDevicePciBusSlotInfo)
   139  					assert.True(t, ok)
   140  					assert.Equal(t, int32(160), si.PciSlotNumber)
   141  				}
   142  			}
   143  
   144  			if bd, ok := cs.DeviceChange[3].GetVirtualDeviceConfigSpec().Device.(types.BaseVirtualEthernetCard); assert.True(t, ok) {
   145  				d := bd.GetVirtualEthernetCard()
   146  				if assert.NotNil(t, d.UnitNumber) {
   147  					assert.Equal(t, int32(3), *d.UnitNumber)
   148  				}
   149  				if assert.NotNil(t, d.Connectable) {
   150  					assert.True(t, d.Connectable.AllowGuestControl)
   151  				}
   152  				if assert.NotNil(t, d.WakeOnLanEnabled) {
   153  					assert.False(t, *d.WakeOnLanEnabled)
   154  				}
   155  				if assert.NotNil(t, d.SlotInfo) {
   156  					si, ok := d.SlotInfo.(*types.VirtualDevicePciBusSlotInfo)
   157  					assert.True(t, ok)
   158  					assert.Equal(t, int32(192), si.PciSlotNumber)
   159  				}
   160  				if assert.NotNil(t, d.UptCompatibilityEnabled) {
   161  					assert.False(t, *d.UptCompatibilityEnabled)
   162  				}
   163  			}
   164  
   165  			if d, ok := cs.DeviceChange[4].GetVirtualDeviceConfigSpec().Device.(*types.VirtualMachineVideoCard); assert.True(t, ok) {
   166  				if assert.NotNil(t, d.Enable3DSupport) {
   167  					assert.False(t, *d.Enable3DSupport)
   168  				}
   169  				assert.Equal(t, int64(262144), d.GraphicsMemorySizeInKB)
   170  				if assert.NotNil(t, d.UseAutoDetect) {
   171  					assert.False(t, *d.UseAutoDetect)
   172  				}
   173  				assert.Equal(t, int64(4096), d.VideoRamSizeInKB)
   174  				assert.Equal(t, int32(1), d.NumDisplays)
   175  				assert.Equal(t, "automatic", d.Use3dRenderer)
   176  			}
   177  
   178  			var ideControllerKey int32
   179  			if d, ok := cs.DeviceChange[5].GetVirtualDeviceConfigSpec().Device.(*types.VirtualIDEController); assert.True(t, ok) {
   180  				ideControllerKey = d.Key
   181  				assert.Equal(t, int32(1), d.BusNumber)
   182  			}
   183  
   184  			if d, ok := cs.DeviceChange[6].GetVirtualDeviceConfigSpec().Device.(*types.VirtualIDEController); assert.True(t, ok) {
   185  				assert.Equal(t, int32(0), d.BusNumber)
   186  			}
   187  
   188  			if d, ok := cs.DeviceChange[7].GetVirtualDeviceConfigSpec().Device.(*types.VirtualCdrom); assert.True(t, ok) {
   189  				if assert.NotNil(t, d.UnitNumber) {
   190  					assert.Equal(t, int32(0), *d.UnitNumber)
   191  				}
   192  				assert.Equal(t, ideControllerKey, d.ControllerKey)
   193  			}
   194  
   195  			var sioControllerKey int32
   196  			if d, ok := cs.DeviceChange[8].GetVirtualDeviceConfigSpec().Device.(*types.VirtualSIOController); assert.True(t, ok) {
   197  				sioControllerKey = d.Key
   198  			}
   199  
   200  			if d, ok := cs.DeviceChange[9].GetVirtualDeviceConfigSpec().Device.(*types.VirtualFloppy); assert.True(t, ok) {
   201  				if assert.NotNil(t, d.UnitNumber) {
   202  					assert.Equal(t, int32(0), *d.UnitNumber)
   203  				}
   204  				assert.Equal(t, sioControllerKey, d.ControllerKey)
   205  			}
   206  
   207  			if d, ok := cs.DeviceChange[10].GetVirtualDeviceConfigSpec().Device.(*types.VirtualMachineVMCIDevice); assert.True(t, ok) {
   208  				if assert.NotNil(t, d.AllowUnrestrictedCommunication) {
   209  					assert.False(t, *d.AllowUnrestrictedCommunication)
   210  				}
   211  			}
   212  
   213  			var scsiController2Key int32
   214  			if d, ok := cs.DeviceChange[11].GetVirtualDeviceConfigSpec().Device.(*types.ParaVirtualSCSIController); assert.True(t, ok) {
   215  				scsiController2Key = d.Key
   216  				assert.Equal(t, int32(1), d.BusNumber)
   217  				assert.Nil(t, d.SlotInfo)
   218  				assert.Len(t, d.Device, 1)
   219  			}
   220  
   221  			if d, ok := cs.DeviceChange[12].GetVirtualDeviceConfigSpec().Device.(*types.VirtualDisk); assert.True(t, ok) {
   222  				assert.Equal(t, scsiController2Key, d.ControllerKey)
   223  				if assert.NotNil(t, d.UnitNumber) {
   224  					assert.Equal(t, int32(0), *d.UnitNumber)
   225  				}
   226  				db, ok := d.Backing.(*types.VirtualDiskFlatVer2BackingInfo)
   227  				assert.True(t, ok)
   228  				assert.Equal(t, string(types.VirtualDiskModePersistent), db.DiskMode)
   229  				if assert.NotNil(t, db.ThinProvisioned) {
   230  					assert.True(t, *db.ThinProvisioned)
   231  				}
   232  				assert.Equal(t, int64(10*1024*1024*1024), d.CapacityInBytes)
   233  			}
   234  
   235  			var sataController1Key int32
   236  			if d, ok := cs.DeviceChange[13].GetVirtualDeviceConfigSpec().Device.(*types.VirtualAHCIController); assert.True(t, ok) {
   237  				sataController1Key = d.Key
   238  				assert.Equal(t, int32(0), d.BusNumber)
   239  				assert.Nil(t, d.SlotInfo)
   240  			}
   241  
   242  			if d, ok := cs.DeviceChange[14].GetVirtualDeviceConfigSpec().Device.(*types.VirtualDisk); assert.True(t, ok) {
   243  				assert.Equal(t, sataController1Key, d.ControllerKey)
   244  				if assert.NotNil(t, d.UnitNumber) {
   245  					assert.Equal(t, int32(0), *d.UnitNumber)
   246  				}
   247  				db, ok := d.Backing.(*types.VirtualDiskFlatVer2BackingInfo)
   248  				assert.True(t, ok)
   249  				assert.Equal(t, string(types.VirtualDiskModePersistent), db.DiskMode)
   250  				if assert.NotNil(t, db.ThinProvisioned) {
   251  					assert.True(t, *db.ThinProvisioned)
   252  				}
   253  				assert.Equal(t, int64(10*1024*1024*1024), d.CapacityInBytes)
   254  			}
   255  
   256  			var sataController2Key int32
   257  			if d, ok := cs.DeviceChange[15].GetVirtualDeviceConfigSpec().Device.(*types.VirtualAHCIController); assert.True(t, ok) {
   258  				sataController2Key = d.Key
   259  				assert.Equal(t, int32(1), d.BusNumber)
   260  				assert.Nil(t, d.SlotInfo)
   261  			}
   262  
   263  			if d, ok := cs.DeviceChange[16].GetVirtualDeviceConfigSpec().Device.(*types.VirtualDisk); assert.True(t, ok) {
   264  				assert.Equal(t, sataController2Key, d.ControllerKey)
   265  				if assert.NotNil(t, d.UnitNumber) {
   266  					assert.Equal(t, int32(0), *d.UnitNumber)
   267  				}
   268  				db, ok := d.Backing.(*types.VirtualDiskFlatVer2BackingInfo)
   269  				assert.True(t, ok)
   270  				assert.Equal(t, string(types.VirtualDiskModePersistent), db.DiskMode)
   271  				if assert.NotNil(t, db.ThinProvisioned) {
   272  					assert.True(t, *db.ThinProvisioned)
   273  				}
   274  				assert.Equal(t, int64(10*1024*1024*1024), d.CapacityInBytes)
   275  			}
   276  
   277  			var nvmeController1Key int32
   278  			if d, ok := cs.DeviceChange[17].GetVirtualDeviceConfigSpec().Device.(*types.VirtualNVMEController); assert.True(t, ok) {
   279  				nvmeController1Key = d.Key
   280  				assert.Equal(t, int32(0), d.BusNumber)
   281  				assert.Nil(t, d.SlotInfo)
   282  			}
   283  
   284  			if d, ok := cs.DeviceChange[18].GetVirtualDeviceConfigSpec().Device.(*types.VirtualDisk); assert.True(t, ok) {
   285  				assert.Equal(t, nvmeController1Key, d.ControllerKey)
   286  				if assert.NotNil(t, d.UnitNumber) {
   287  					assert.Equal(t, int32(0), *d.UnitNumber)
   288  				}
   289  				db, ok := d.Backing.(*types.VirtualDiskFlatVer2BackingInfo)
   290  				assert.True(t, ok)
   291  				assert.Equal(t, string(types.VirtualDiskModePersistent), db.DiskMode)
   292  				if assert.NotNil(t, db.ThinProvisioned) {
   293  					assert.True(t, *db.ThinProvisioned)
   294  				}
   295  				assert.Equal(t, int64(10*1024*1024*1024), d.CapacityInBytes)
   296  			}
   297  
   298  			if d, ok := cs.DeviceChange[19].GetVirtualDeviceConfigSpec().Device.(*types.VirtualUSBController); assert.True(t, ok) {
   299  				if assert.NotNil(t, d.AutoConnectDevices) {
   300  					assert.True(t, *d.AutoConnectDevices)
   301  				}
   302  				if assert.NotNil(t, d.EhciEnabled) {
   303  					assert.False(t, *d.EhciEnabled)
   304  				}
   305  			}
   306  
   307  			if d, ok := cs.DeviceChange[20].GetVirtualDeviceConfigSpec().Device.(*types.VirtualUSBXHCIController); assert.True(t, ok) {
   308  				if assert.NotNil(t, d.AutoConnectDevices) {
   309  					assert.True(t, *d.AutoConnectDevices)
   310  				}
   311  			}
   312  		}
   313  
   314  		assert.ElementsMatch(t, cs.ExtraConfig, []types.BaseOptionValue{
   315  			&types.OptionValue{
   316  				Key:   "guest_rpc.auth.cloud-init.set",
   317  				Value: "FALSE",
   318  			},
   319  		})
   320  
   321  		if assert.NotNil(t, cs.Flags) {
   322  			if assert.NotNil(t, cs.Flags.VbsEnabled) {
   323  				assert.False(t, *cs.Flags.VbsEnabled)
   324  			}
   325  			if assert.NotNil(t, cs.Flags.VvtdEnabled) {
   326  				assert.False(t, *cs.Flags.VvtdEnabled)
   327  			}
   328  		}
   329  
   330  		assert.Equal(t, "bios", cs.Firmware)
   331  
   332  		if assert.NotNil(t, cs.BootOptions) {
   333  			if assert.NotNil(t, cs.BootOptions.EfiSecureBootEnabled) {
   334  				assert.False(t, *cs.BootOptions.EfiSecureBootEnabled)
   335  			}
   336  		}
   337  
   338  		if assert.NotNil(t, cs.CpuHotAddEnabled) {
   339  			assert.False(t, *cs.CpuHotAddEnabled)
   340  		}
   341  		if assert.NotNil(t, cs.CpuHotRemoveEnabled) {
   342  			assert.False(t, *cs.CpuHotRemoveEnabled)
   343  		}
   344  		if assert.NotNil(t, cs.MemoryHotAddEnabled) {
   345  			assert.False(t, *cs.MemoryHotAddEnabled)
   346  		}
   347  		if assert.NotNil(t, cs.NestedHVEnabled) {
   348  			assert.False(t, *cs.NestedHVEnabled)
   349  		}
   350  		if assert.NotNil(t, cs.VirtualICH7MPresent) {
   351  			assert.False(t, *cs.VirtualICH7MPresent)
   352  		}
   353  
   354  		assert.Equal(t, int32(1), cs.SimultaneousThreads)
   355  
   356  		if assert.NotNil(t, cs.VPMCEnabled) {
   357  			assert.False(t, *cs.VPMCEnabled)
   358  		}
   359  
   360  		if assert.NotNil(t, cs.CpuAllocation) {
   361  			if assert.NotNil(t, cs.CpuAllocation.Shares) {
   362  				assert.Equal(t, &types.SharesInfo{
   363  					Shares: 2000,
   364  					Level:  types.SharesLevelNormal,
   365  				}, cs.CpuAllocation.Shares)
   366  			}
   367  		}
   368  
   369  		if assert.NotNil(t, cs.PowerOpInfo) {
   370  			assert.Equal(t, &types.VirtualMachineDefaultPowerOpInfo{
   371  				PowerOffType:  "soft",
   372  				ResetType:     "soft",
   373  				SuspendType:   "hard",
   374  				StandbyAction: "checkpoint",
   375  			}, cs.PowerOpInfo)
   376  		}
   377  
   378  		if assert.NotNil(t, cs.Tools) {
   379  			assert.Equal(t, &types.ToolsConfigInfo{
   380  				SyncTimeWithHost:        types.NewBool(false),
   381  				SyncTimeWithHostAllowed: types.NewBool(true),
   382  				AfterPowerOn:            types.NewBool(true),
   383  				AfterResume:             types.NewBool(true),
   384  				BeforeGuestShutdown:     types.NewBool(true),
   385  				BeforeGuestStandby:      types.NewBool(true),
   386  				ToolsUpgradePolicy:      "manual",
   387  			}, cs.Tools)
   388  		}
   389  
   390  		if va, ok := cs.VAppConfig.(*types.VAppConfigSpec); assert.True(t, ok) {
   391  			if assert.Len(t, va.Product, 4) {
   392  				assert.ElementsMatch(t,
   393  					[]types.VAppProductSpec{
   394  						{
   395  							ArrayUpdateSpec: types.ArrayUpdateSpec{
   396  								Operation: types.ArrayUpdateOperationAdd,
   397  							},
   398  							Info: &types.VAppProductInfo{
   399  								Key:         0,
   400  								Name:        "HAProxy for the Load Balancer API v0.2.0",
   401  								Vendor:      "VMware Inc.",
   402  								Version:     "v0.2.0",
   403  								FullVersion: "v0.2.0",
   404  								ProductUrl:  "https://vmware.com",
   405  								VendorUrl:   "https://vmware.com",
   406  							},
   407  						},
   408  						{
   409  							ArrayUpdateSpec: types.ArrayUpdateSpec{
   410  								Operation: types.ArrayUpdateOperationAdd,
   411  							},
   412  							Info: &types.VAppProductInfo{
   413  								Key:     1,
   414  								ClassId: "appliance",
   415  							},
   416  						},
   417  						{
   418  							ArrayUpdateSpec: types.ArrayUpdateSpec{
   419  								Operation: types.ArrayUpdateOperationAdd,
   420  							},
   421  							Info: &types.VAppProductInfo{
   422  								Key:     2,
   423  								ClassId: "network",
   424  							},
   425  						},
   426  						{
   427  							ArrayUpdateSpec: types.ArrayUpdateSpec{
   428  								Operation: types.ArrayUpdateOperationAdd,
   429  							},
   430  							Info: &types.VAppProductInfo{
   431  								Key:     3,
   432  								ClassId: "loadbalance",
   433  							},
   434  						},
   435  					},
   436  					va.Product,
   437  				)
   438  			}
   439  			if assert.Len(t, va.Property, 6) {
   440  				assert.ElementsMatch(t,
   441  					[]types.VAppPropertySpec{
   442  
   443  						// default
   444  						{
   445  							ArrayUpdateSpec: types.ArrayUpdateSpec{
   446  								Operation: types.ArrayUpdateOperationAdd,
   447  							},
   448  							Info: &types.VAppPropertyInfo{
   449  								Key:              0,
   450  								Category:         "Load Balancer API",
   451  								Id:               "BUILD_TIMESTAMP",
   452  								Type:             "string",
   453  								UserConfigurable: types.NewBool(false),
   454  								DefaultValue:     "1615488399",
   455  							},
   456  						},
   457  						{
   458  							ArrayUpdateSpec: types.ArrayUpdateSpec{
   459  								Operation: types.ArrayUpdateOperationAdd,
   460  							},
   461  							Info: &types.VAppPropertyInfo{
   462  								Key:              1,
   463  								Category:         "Load Balancer API",
   464  								Id:               "BUILD_DATE",
   465  								Type:             "string",
   466  								UserConfigurable: types.NewBool(false),
   467  								DefaultValue:     "2021-03-11T18:46:39Z",
   468  							},
   469  						},
   470  
   471  						// appliance
   472  						{
   473  							ArrayUpdateSpec: types.ArrayUpdateSpec{
   474  								Operation: types.ArrayUpdateOperationAdd,
   475  							},
   476  							Info: &types.VAppPropertyInfo{
   477  								Key:              2,
   478  								Category:         "1. Appliance Configuration",
   479  								ClassId:          "appliance",
   480  								Id:               "root_pwd",
   481  								Label:            "1.1. Root Password",
   482  								Type:             "string",
   483  								UserConfigurable: types.NewBool(true),
   484  								Description:      "The initial password of the root user. Subsequent changes of password should be performed in operating system. (6-128 characters)",
   485  							},
   486  						},
   487  
   488  						// network
   489  						{
   490  							ArrayUpdateSpec: types.ArrayUpdateSpec{
   491  								Operation: types.ArrayUpdateOperationAdd,
   492  							},
   493  							Info: &types.VAppPropertyInfo{
   494  								Key:              3,
   495  								Category:         "2. Network Config",
   496  								ClassId:          "network",
   497  								Id:               "hostname",
   498  								Label:            "2.1. Host Name",
   499  								Type:             "string",
   500  								UserConfigurable: types.NewBool(true),
   501  								DefaultValue:     "haproxy.local",
   502  								Description:      "The host name. A fully-qualified domain name is also supported.",
   503  							},
   504  						},
   505  
   506  						// loadbalance
   507  						{
   508  							ArrayUpdateSpec: types.ArrayUpdateSpec{
   509  								Operation: types.ArrayUpdateOperationAdd,
   510  							},
   511  							Info: &types.VAppPropertyInfo{
   512  								Key:              4,
   513  								Category:         "3. Load Balancing",
   514  								ClassId:          "loadbalance",
   515  								Id:               "service_ip_range",
   516  								Label:            "3.1. Load Balancer IP Ranges, comma-separated in CIDR format (Eg 1.2.3.4/28,5.6.7.8/28)",
   517  								Type:             "string",
   518  								UserConfigurable: types.NewBool(true),
   519  								Description:      "The IP ranges the load balancer will use for Kubernetes Services and Control Planes. The Appliance will currently respond to ALL the IPs in these ranges whether they're assigned or not. As such, these ranges must not overlap with the IPs assigned for the appliance or any other VMs on the network.",
   520  							},
   521  						},
   522  						{
   523  							ArrayUpdateSpec: types.ArrayUpdateSpec{
   524  								Operation: types.ArrayUpdateOperationAdd,
   525  							},
   526  							Info: &types.VAppPropertyInfo{
   527  								Key:              5,
   528  								Category:         "3. Load Balancing",
   529  								ClassId:          "loadbalance",
   530  								Id:               "dataplane_port",
   531  								Label:            "3.2. Dataplane API Management Port",
   532  								Type:             "int",
   533  								UserConfigurable: types.NewBool(true),
   534  								DefaultValue:     "5556",
   535  								Description:      "Specifies the port on which the Dataplane API will be advertized on the Management Network.",
   536  							},
   537  						},
   538  					},
   539  					va.Property,
   540  				)
   541  			}
   542  		}
   543  	})
   544  }