github.com/vmware/govmomi@v0.51.0/vim25/types/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 types
     6  
     7  import (
     8  	"fmt"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  
    13  	"github.com/vmware/govmomi/vim25/xml"
    14  )
    15  
    16  func TestVirtualMachineConfigSpec(t *testing.T) {
    17  
    18  	t.Run("marshal to xml", func(t *testing.T) {
    19  		spec := VirtualMachineConfigSpec{
    20  			Name:     "vm-001",
    21  			GuestId:  "otherGuest",
    22  			Files:    &VirtualMachineFileInfo{VmPathName: "[datastore1]"},
    23  			NumCPUs:  1,
    24  			MemoryMB: 128,
    25  			DeviceChange: []BaseVirtualDeviceConfigSpec{
    26  				&VirtualDeviceConfigSpec{
    27  					Operation: VirtualDeviceConfigSpecOperationAdd,
    28  					Device: &VirtualLsiLogicController{VirtualSCSIController{
    29  						SharedBus: VirtualSCSISharingNoSharing,
    30  						VirtualController: VirtualController{
    31  							BusNumber: 0,
    32  							VirtualDevice: VirtualDevice{
    33  								Key: 1000,
    34  							},
    35  						},
    36  					}},
    37  				},
    38  				&VirtualDeviceConfigSpec{
    39  					Operation:     VirtualDeviceConfigSpecOperationAdd,
    40  					FileOperation: VirtualDeviceConfigSpecFileOperationCreate,
    41  					Device: &VirtualDisk{
    42  						VirtualDevice: VirtualDevice{
    43  							Key:           0,
    44  							ControllerKey: 1000,
    45  							UnitNumber:    new(int32), // zero default value
    46  							Backing: &VirtualDiskFlatVer2BackingInfo{
    47  								DiskMode:        string(VirtualDiskModePersistent),
    48  								ThinProvisioned: NewBool(true),
    49  								VirtualDeviceFileBackingInfo: VirtualDeviceFileBackingInfo{
    50  									FileName: "[datastore1]",
    51  								},
    52  							},
    53  						},
    54  						CapacityInKB: 4000000,
    55  					},
    56  				},
    57  				&VirtualDeviceConfigSpec{
    58  					Operation: VirtualDeviceConfigSpecOperationAdd,
    59  					Device: &VirtualE1000{VirtualEthernetCard{
    60  						VirtualDevice: VirtualDevice{
    61  							Key: 0,
    62  							DeviceInfo: &Description{
    63  								Label:   "Network Adapter 1",
    64  								Summary: "VM Network",
    65  							},
    66  							Backing: &VirtualEthernetCardNetworkBackingInfo{
    67  								VirtualDeviceDeviceBackingInfo: VirtualDeviceDeviceBackingInfo{
    68  									DeviceName: "VM Network",
    69  								},
    70  							},
    71  						},
    72  						AddressType: string(VirtualEthernetCardMacTypeGenerated),
    73  					}},
    74  				},
    75  			},
    76  			ExtraConfig: []BaseOptionValue{
    77  				&OptionValue{Key: "bios.bootOrder", Value: "ethernet0"},
    78  			},
    79  		}
    80  
    81  		_, err := xml.MarshalIndent(spec, "", " ")
    82  		assert.NoError(t, err)
    83  	})
    84  
    85  	t.Run("EnsureDisksHaveControllers", func(t *testing.T) {
    86  
    87  		const vmx20 = "vmx-20"
    88  
    89  		testCases := []struct {
    90  			name               string
    91  			configSpec         *VirtualMachineConfigSpec
    92  			existingDevices    []BaseVirtualDevice
    93  			err                error
    94  			expectedConfigSpec *VirtualMachineConfigSpec
    95  			panicMsg           string
    96  		}{
    97  			{
    98  				name:               "nil configSpec arg should panic",
    99  				configSpec:         nil,
   100  				existingDevices:    nil,
   101  				err:                nil,
   102  				expectedConfigSpec: nil,
   103  				panicMsg:           "configSpec is nil",
   104  			},
   105  			{
   106  				name: "do nothing if configSpec has no disks",
   107  				configSpec: &VirtualMachineConfigSpec{
   108  					Version: vmx20,
   109  				},
   110  				existingDevices: nil,
   111  				err:             nil,
   112  				expectedConfigSpec: &VirtualMachineConfigSpec{
   113  					Version: vmx20,
   114  				},
   115  			},
   116  			{
   117  				name: "do nothing if configSpec has a disk, but it is being removed",
   118  				configSpec: &VirtualMachineConfigSpec{
   119  					Version: vmx20,
   120  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   121  						&VirtualDeviceConfigSpec{
   122  							Operation: VirtualDeviceConfigSpecOperationRemove,
   123  							Device:    &VirtualDisk{},
   124  						},
   125  					},
   126  				},
   127  				existingDevices: nil,
   128  				err:             nil,
   129  				expectedConfigSpec: &VirtualMachineConfigSpec{
   130  					Version: vmx20,
   131  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   132  						&VirtualDeviceConfigSpec{
   133  							Operation: VirtualDeviceConfigSpecOperationRemove,
   134  							Device:    &VirtualDisk{},
   135  						},
   136  					},
   137  				},
   138  			},
   139  			{
   140  				name: "do nothing if configSpec has a disk, but it is already attached to a controller from existing devices",
   141  				configSpec: &VirtualMachineConfigSpec{
   142  					Version: vmx20,
   143  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   144  						&VirtualDeviceConfigSpec{
   145  							Operation: VirtualDeviceConfigSpecOperationAdd,
   146  							Device: &VirtualDisk{
   147  								VirtualDevice: VirtualDevice{
   148  									ControllerKey: 1000,
   149  								},
   150  							},
   151  						},
   152  					},
   153  				},
   154  				existingDevices: []BaseVirtualDevice{
   155  					&VirtualPCIController{
   156  						VirtualController: VirtualController{
   157  							VirtualDevice: VirtualDevice{
   158  								Key: 100,
   159  							},
   160  						},
   161  					},
   162  					&ParaVirtualSCSIController{
   163  						VirtualSCSIController: VirtualSCSIController{
   164  							VirtualController: VirtualController{
   165  								VirtualDevice: VirtualDevice{
   166  									ControllerKey: 100,
   167  									Key:           1000,
   168  								},
   169  							},
   170  						},
   171  					},
   172  				},
   173  				err: nil,
   174  				expectedConfigSpec: &VirtualMachineConfigSpec{
   175  					Version: vmx20,
   176  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   177  						&VirtualDeviceConfigSpec{
   178  							Operation: VirtualDeviceConfigSpecOperationAdd,
   179  							Device: &VirtualDisk{
   180  								VirtualDevice: VirtualDevice{
   181  									ControllerKey: 1000,
   182  								},
   183  							},
   184  						},
   185  					},
   186  				},
   187  			},
   188  			{
   189  				name: "attach disk to new PVSCSI controller when adding disk and there is a nil base device change in ConfigSpec and existing device includes only PCI controller",
   190  				configSpec: &VirtualMachineConfigSpec{
   191  					Version: vmx20,
   192  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   193  						BaseVirtualDeviceConfigSpec(nil),
   194  						&VirtualDeviceConfigSpec{
   195  							Operation: VirtualDeviceConfigSpecOperationAdd,
   196  							Device:    &VirtualDisk{},
   197  						},
   198  					},
   199  				},
   200  				existingDevices: []BaseVirtualDevice{
   201  					&VirtualPCIController{
   202  						VirtualController: VirtualController{
   203  							VirtualDevice: VirtualDevice{
   204  								Key: 100,
   205  							},
   206  						},
   207  					},
   208  				},
   209  				err: nil,
   210  				expectedConfigSpec: &VirtualMachineConfigSpec{
   211  					Version: vmx20,
   212  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   213  						BaseVirtualDeviceConfigSpec(nil),
   214  						&VirtualDeviceConfigSpec{
   215  							Operation: VirtualDeviceConfigSpecOperationAdd,
   216  							Device: &VirtualDisk{
   217  								VirtualDevice: VirtualDevice{
   218  									ControllerKey: -1,
   219  								},
   220  							},
   221  						},
   222  						&VirtualDeviceConfigSpec{
   223  							Operation: VirtualDeviceConfigSpecOperationAdd,
   224  							Device: &ParaVirtualSCSIController{
   225  								VirtualSCSIController: VirtualSCSIController{
   226  									VirtualController: VirtualController{
   227  										VirtualDevice: VirtualDevice{
   228  											ControllerKey: 100,
   229  											Key:           -1,
   230  										},
   231  										BusNumber: 0,
   232  									},
   233  									HotAddRemove: NewBool(true),
   234  									SharedBus:    VirtualSCSISharingNoSharing,
   235  								},
   236  							},
   237  						},
   238  					},
   239  				},
   240  			},
   241  			{
   242  				name: "attach disk to new PVSCSI controller when adding disk and there is a nil device change in ConfigSpec and existing device includes only PCI controller",
   243  				configSpec: &VirtualMachineConfigSpec{
   244  					Version: vmx20,
   245  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   246  						nilVirtualDeviceConfigSpec{},
   247  						&VirtualDeviceConfigSpec{
   248  							Operation: VirtualDeviceConfigSpecOperationAdd,
   249  							Device:    &VirtualDisk{},
   250  						},
   251  					},
   252  				},
   253  				existingDevices: []BaseVirtualDevice{
   254  					&VirtualPCIController{
   255  						VirtualController: VirtualController{
   256  							VirtualDevice: VirtualDevice{
   257  								Key: 100,
   258  							},
   259  						},
   260  					},
   261  				},
   262  				err: nil,
   263  				expectedConfigSpec: &VirtualMachineConfigSpec{
   264  					Version: vmx20,
   265  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   266  						nilVirtualDeviceConfigSpec{},
   267  						&VirtualDeviceConfigSpec{
   268  							Operation: VirtualDeviceConfigSpecOperationAdd,
   269  							Device: &VirtualDisk{
   270  								VirtualDevice: VirtualDevice{
   271  									ControllerKey: -1,
   272  								},
   273  							},
   274  						},
   275  						&VirtualDeviceConfigSpec{
   276  							Operation: VirtualDeviceConfigSpecOperationAdd,
   277  							Device: &ParaVirtualSCSIController{
   278  								VirtualSCSIController: VirtualSCSIController{
   279  									VirtualController: VirtualController{
   280  										VirtualDevice: VirtualDevice{
   281  											ControllerKey: 100,
   282  											Key:           -1,
   283  										},
   284  										BusNumber: 0,
   285  									},
   286  									HotAddRemove: NewBool(true),
   287  									SharedBus:    VirtualSCSISharingNoSharing,
   288  								},
   289  							},
   290  						},
   291  					},
   292  				},
   293  			},
   294  
   295  			{
   296  				name: "attach disk to new PVSCSI controller when adding disk and there is a nil base device in ConfigSpec and existing device includes only PCI controller",
   297  				configSpec: &VirtualMachineConfigSpec{
   298  					Version: vmx20,
   299  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   300  						&VirtualDeviceConfigSpec{
   301  							Device: BaseVirtualDevice(nil),
   302  						},
   303  						&VirtualDeviceConfigSpec{
   304  							Operation: VirtualDeviceConfigSpecOperationAdd,
   305  							Device:    &VirtualDisk{},
   306  						},
   307  					},
   308  				},
   309  				existingDevices: []BaseVirtualDevice{
   310  					&VirtualPCIController{
   311  						VirtualController: VirtualController{
   312  							VirtualDevice: VirtualDevice{
   313  								Key: 100,
   314  							},
   315  						},
   316  					},
   317  				},
   318  				err: nil,
   319  				expectedConfigSpec: &VirtualMachineConfigSpec{
   320  					Version: vmx20,
   321  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   322  						&VirtualDeviceConfigSpec{
   323  							Device: BaseVirtualDevice(nil),
   324  						},
   325  						&VirtualDeviceConfigSpec{
   326  							Operation: VirtualDeviceConfigSpecOperationAdd,
   327  							Device: &VirtualDisk{
   328  								VirtualDevice: VirtualDevice{
   329  									ControllerKey: -1,
   330  								},
   331  							},
   332  						},
   333  						&VirtualDeviceConfigSpec{
   334  							Operation: VirtualDeviceConfigSpecOperationAdd,
   335  							Device: &ParaVirtualSCSIController{
   336  								VirtualSCSIController: VirtualSCSIController{
   337  									VirtualController: VirtualController{
   338  										VirtualDevice: VirtualDevice{
   339  											ControllerKey: 100,
   340  											Key:           -1,
   341  										},
   342  										BusNumber: 0,
   343  									},
   344  									HotAddRemove: NewBool(true),
   345  									SharedBus:    VirtualSCSISharingNoSharing,
   346  								},
   347  							},
   348  						},
   349  					},
   350  				},
   351  			},
   352  			{
   353  				name: "attach disk to new PVSCSI controller when adding disk and there is a nil device in ConfigSpec and existing device includes only PCI controller",
   354  				configSpec: &VirtualMachineConfigSpec{
   355  					Version: vmx20,
   356  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   357  						&VirtualDeviceConfigSpec{
   358  							Device: nilVirtualDevice{},
   359  						},
   360  						&VirtualDeviceConfigSpec{
   361  							Operation: VirtualDeviceConfigSpecOperationAdd,
   362  							Device:    &VirtualDisk{},
   363  						},
   364  					},
   365  				},
   366  				existingDevices: []BaseVirtualDevice{
   367  					&VirtualPCIController{
   368  						VirtualController: VirtualController{
   369  							VirtualDevice: VirtualDevice{
   370  								Key: 100,
   371  							},
   372  						},
   373  					},
   374  				},
   375  				err: nil,
   376  				expectedConfigSpec: &VirtualMachineConfigSpec{
   377  					Version: vmx20,
   378  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   379  						&VirtualDeviceConfigSpec{
   380  							Device: nilVirtualDevice{},
   381  						},
   382  						&VirtualDeviceConfigSpec{
   383  							Operation: VirtualDeviceConfigSpecOperationAdd,
   384  							Device: &VirtualDisk{
   385  								VirtualDevice: VirtualDevice{
   386  									ControllerKey: -1,
   387  								},
   388  							},
   389  						},
   390  						&VirtualDeviceConfigSpec{
   391  							Operation: VirtualDeviceConfigSpecOperationAdd,
   392  							Device: &ParaVirtualSCSIController{
   393  								VirtualSCSIController: VirtualSCSIController{
   394  									VirtualController: VirtualController{
   395  										VirtualDevice: VirtualDevice{
   396  											ControllerKey: 100,
   397  											Key:           -1,
   398  										},
   399  										BusNumber: 0,
   400  									},
   401  									HotAddRemove: NewBool(true),
   402  									SharedBus:    VirtualSCSISharingNoSharing,
   403  								},
   404  							},
   405  						},
   406  					},
   407  				},
   408  			},
   409  			{
   410  				name: "attach disk to new PVSCSI controller when adding disk and existing device includes PCI controller and nil base device",
   411  				configSpec: &VirtualMachineConfigSpec{
   412  					Version: vmx20,
   413  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   414  						&VirtualDeviceConfigSpec{
   415  							Operation: VirtualDeviceConfigSpecOperationAdd,
   416  							Device:    &VirtualDisk{},
   417  						},
   418  					},
   419  				},
   420  				existingDevices: []BaseVirtualDevice{
   421  					&VirtualPCIController{
   422  						VirtualController: VirtualController{
   423  							VirtualDevice: VirtualDevice{
   424  								Key: 100,
   425  							},
   426  						},
   427  					},
   428  					BaseVirtualDevice(nil),
   429  				},
   430  				err: nil,
   431  				expectedConfigSpec: &VirtualMachineConfigSpec{
   432  					Version: vmx20,
   433  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   434  						&VirtualDeviceConfigSpec{
   435  							Operation: VirtualDeviceConfigSpecOperationAdd,
   436  							Device: &VirtualDisk{
   437  								VirtualDevice: VirtualDevice{
   438  									ControllerKey: -1,
   439  								},
   440  							},
   441  						},
   442  						&VirtualDeviceConfigSpec{
   443  							Operation: VirtualDeviceConfigSpecOperationAdd,
   444  							Device: &ParaVirtualSCSIController{
   445  								VirtualSCSIController: VirtualSCSIController{
   446  									VirtualController: VirtualController{
   447  										VirtualDevice: VirtualDevice{
   448  											ControllerKey: 100,
   449  											Key:           -1,
   450  										},
   451  										BusNumber: 0,
   452  									},
   453  									HotAddRemove: NewBool(true),
   454  									SharedBus:    VirtualSCSISharingNoSharing,
   455  								},
   456  							},
   457  						},
   458  					},
   459  				},
   460  			},
   461  			{
   462  				name: "attach disk to new PVSCSI controller when adding disk and existing device includes PCI controller and nil device",
   463  				configSpec: &VirtualMachineConfigSpec{
   464  					Version: vmx20,
   465  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   466  						&VirtualDeviceConfigSpec{
   467  							Operation: VirtualDeviceConfigSpecOperationAdd,
   468  							Device:    &VirtualDisk{},
   469  						},
   470  					},
   471  				},
   472  				existingDevices: []BaseVirtualDevice{
   473  					&VirtualPCIController{
   474  						VirtualController: VirtualController{
   475  							VirtualDevice: VirtualDevice{
   476  								Key: 100,
   477  							},
   478  						},
   479  					},
   480  					nilVirtualDevice{},
   481  				},
   482  				err: nil,
   483  				expectedConfigSpec: &VirtualMachineConfigSpec{
   484  					Version: vmx20,
   485  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   486  						&VirtualDeviceConfigSpec{
   487  							Operation: VirtualDeviceConfigSpecOperationAdd,
   488  							Device: &VirtualDisk{
   489  								VirtualDevice: VirtualDevice{
   490  									ControllerKey: -1,
   491  								},
   492  							},
   493  						},
   494  						&VirtualDeviceConfigSpec{
   495  							Operation: VirtualDeviceConfigSpecOperationAdd,
   496  							Device: &ParaVirtualSCSIController{
   497  								VirtualSCSIController: VirtualSCSIController{
   498  									VirtualController: VirtualController{
   499  										VirtualDevice: VirtualDevice{
   500  											ControllerKey: 100,
   501  											Key:           -1,
   502  										},
   503  										BusNumber: 0,
   504  									},
   505  									HotAddRemove: NewBool(true),
   506  									SharedBus:    VirtualSCSISharingNoSharing,
   507  								},
   508  							},
   509  						},
   510  					},
   511  				},
   512  			},
   513  			{
   514  				name: "attach disk to new PVSCSI controller when adding disk while removing SATA controller and existing device includes only PCI controller",
   515  				configSpec: &VirtualMachineConfigSpec{
   516  					Version: vmx20,
   517  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   518  						&VirtualDeviceConfigSpec{
   519  							Operation: VirtualDeviceConfigSpecOperationRemove,
   520  							Device: &VirtualAHCIController{
   521  								VirtualSATAController: VirtualSATAController{
   522  									VirtualController: VirtualController{
   523  										VirtualDevice: VirtualDevice{
   524  											ControllerKey: 100,
   525  											Key:           15000,
   526  										},
   527  									},
   528  								},
   529  							},
   530  						},
   531  						&VirtualDeviceConfigSpec{
   532  							Operation: VirtualDeviceConfigSpecOperationAdd,
   533  							Device:    &VirtualDisk{},
   534  						},
   535  					},
   536  				},
   537  				existingDevices: []BaseVirtualDevice{
   538  					&VirtualPCIController{
   539  						VirtualController: VirtualController{
   540  							VirtualDevice: VirtualDevice{
   541  								Key: 100,
   542  							},
   543  						},
   544  					},
   545  				},
   546  				err: nil,
   547  				expectedConfigSpec: &VirtualMachineConfigSpec{
   548  					Version: vmx20,
   549  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   550  						&VirtualDeviceConfigSpec{
   551  							Operation: VirtualDeviceConfigSpecOperationRemove,
   552  							Device: &VirtualAHCIController{
   553  								VirtualSATAController: VirtualSATAController{
   554  									VirtualController: VirtualController{
   555  										VirtualDevice: VirtualDevice{
   556  											ControllerKey: 100,
   557  											Key:           15000,
   558  										},
   559  									},
   560  								},
   561  							},
   562  						},
   563  						&VirtualDeviceConfigSpec{
   564  							Operation: VirtualDeviceConfigSpecOperationAdd,
   565  							Device: &VirtualDisk{
   566  								VirtualDevice: VirtualDevice{
   567  									ControllerKey: -1,
   568  								},
   569  							},
   570  						},
   571  						&VirtualDeviceConfigSpec{
   572  							Operation: VirtualDeviceConfigSpecOperationAdd,
   573  							Device: &ParaVirtualSCSIController{
   574  								VirtualSCSIController: VirtualSCSIController{
   575  									VirtualController: VirtualController{
   576  										VirtualDevice: VirtualDevice{
   577  											ControllerKey: 100,
   578  											Key:           -1,
   579  										},
   580  										BusNumber: 0,
   581  									},
   582  									HotAddRemove: NewBool(true),
   583  									SharedBus:    VirtualSCSISharingNoSharing,
   584  								},
   585  							},
   586  						},
   587  					},
   588  				},
   589  			},
   590  			{
   591  				name: "attach disk to new PVSCSI controller when adding disk that references SATA controller being removed and existing device includes only PCI controller",
   592  				configSpec: &VirtualMachineConfigSpec{
   593  					Version: vmx20,
   594  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   595  						&VirtualDeviceConfigSpec{
   596  							Operation: VirtualDeviceConfigSpecOperationRemove,
   597  							Device: &VirtualAHCIController{
   598  								VirtualSATAController: VirtualSATAController{
   599  									VirtualController: VirtualController{
   600  										VirtualDevice: VirtualDevice{
   601  											ControllerKey: 100,
   602  											Key:           15000,
   603  										},
   604  									},
   605  								},
   606  							},
   607  						},
   608  						&VirtualDeviceConfigSpec{
   609  							Operation: VirtualDeviceConfigSpecOperationAdd,
   610  							Device: &VirtualDisk{
   611  								VirtualDevice: VirtualDevice{
   612  									ControllerKey: 15000,
   613  								},
   614  							},
   615  						},
   616  					},
   617  				},
   618  				existingDevices: []BaseVirtualDevice{
   619  					&VirtualPCIController{
   620  						VirtualController: VirtualController{
   621  							VirtualDevice: VirtualDevice{
   622  								Key: 100,
   623  							},
   624  						},
   625  					},
   626  				},
   627  				err: nil,
   628  				expectedConfigSpec: &VirtualMachineConfigSpec{
   629  					Version: vmx20,
   630  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   631  						&VirtualDeviceConfigSpec{
   632  							Operation: VirtualDeviceConfigSpecOperationRemove,
   633  							Device: &VirtualAHCIController{
   634  								VirtualSATAController: VirtualSATAController{
   635  									VirtualController: VirtualController{
   636  										VirtualDevice: VirtualDevice{
   637  											ControllerKey: 100,
   638  											Key:           15000,
   639  										},
   640  									},
   641  								},
   642  							},
   643  						},
   644  						&VirtualDeviceConfigSpec{
   645  							Operation: VirtualDeviceConfigSpecOperationAdd,
   646  							Device: &VirtualDisk{
   647  								VirtualDevice: VirtualDevice{
   648  									ControllerKey: -1,
   649  								},
   650  							},
   651  						},
   652  						&VirtualDeviceConfigSpec{
   653  							Operation: VirtualDeviceConfigSpecOperationAdd,
   654  							Device: &ParaVirtualSCSIController{
   655  								VirtualSCSIController: VirtualSCSIController{
   656  									VirtualController: VirtualController{
   657  										VirtualDevice: VirtualDevice{
   658  											ControllerKey: 100,
   659  											Key:           -1,
   660  										},
   661  										BusNumber: 0,
   662  									},
   663  									HotAddRemove: NewBool(true),
   664  									SharedBus:    VirtualSCSISharingNoSharing,
   665  								},
   666  							},
   667  						},
   668  					},
   669  				},
   670  			},
   671  			{
   672  				name: "attach disk to new PVSCSI controller when adding disk that references non-existent controller and existing device includes only PCI controller",
   673  				configSpec: &VirtualMachineConfigSpec{
   674  					Version: vmx20,
   675  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   676  						&VirtualDeviceConfigSpec{
   677  							Operation: VirtualDeviceConfigSpecOperationAdd,
   678  							Device: &VirtualDisk{
   679  								VirtualDevice: VirtualDevice{
   680  									ControllerKey: -1000,
   681  								},
   682  							},
   683  						},
   684  					},
   685  				},
   686  				existingDevices: []BaseVirtualDevice{
   687  					&VirtualPCIController{
   688  						VirtualController: VirtualController{
   689  							VirtualDevice: VirtualDevice{
   690  								Key: 100,
   691  							},
   692  						},
   693  					},
   694  				},
   695  				err: nil,
   696  				expectedConfigSpec: &VirtualMachineConfigSpec{
   697  					Version: vmx20,
   698  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   699  						&VirtualDeviceConfigSpec{
   700  							Operation: VirtualDeviceConfigSpecOperationAdd,
   701  							Device: &VirtualDisk{
   702  								VirtualDevice: VirtualDevice{
   703  									ControllerKey: -1,
   704  								},
   705  							},
   706  						},
   707  						&VirtualDeviceConfigSpec{
   708  							Operation: VirtualDeviceConfigSpecOperationAdd,
   709  							Device: &ParaVirtualSCSIController{
   710  								VirtualSCSIController: VirtualSCSIController{
   711  									VirtualController: VirtualController{
   712  										VirtualDevice: VirtualDevice{
   713  											ControllerKey: 100,
   714  											Key:           -1,
   715  										},
   716  										BusNumber: 0,
   717  									},
   718  									HotAddRemove: NewBool(true),
   719  									SharedBus:    VirtualSCSISharingNoSharing,
   720  								},
   721  							},
   722  						},
   723  					},
   724  				},
   725  			},
   726  			{
   727  				name: "attach disk to new PVSCSI controller when adding disk sans controller and no existing devices",
   728  				configSpec: &VirtualMachineConfigSpec{
   729  					Version: vmx20,
   730  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   731  						&VirtualDeviceConfigSpec{
   732  							Operation: VirtualDeviceConfigSpecOperationAdd,
   733  							Device:    &VirtualDisk{},
   734  						},
   735  					},
   736  				},
   737  				existingDevices: nil,
   738  				err:             nil,
   739  				expectedConfigSpec: &VirtualMachineConfigSpec{
   740  					Version: vmx20,
   741  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   742  						&VirtualDeviceConfigSpec{
   743  							Operation: VirtualDeviceConfigSpecOperationAdd,
   744  							Device: &VirtualDisk{
   745  								VirtualDevice: VirtualDevice{
   746  									ControllerKey: -2,
   747  								},
   748  							},
   749  						},
   750  						&VirtualDeviceConfigSpec{
   751  							Operation: VirtualDeviceConfigSpecOperationAdd,
   752  							Device: &VirtualPCIController{
   753  								VirtualController: VirtualController{
   754  									VirtualDevice: VirtualDevice{
   755  										Key: -1,
   756  									},
   757  								},
   758  							},
   759  						},
   760  						&VirtualDeviceConfigSpec{
   761  							Operation: VirtualDeviceConfigSpecOperationAdd,
   762  							Device: &ParaVirtualSCSIController{
   763  								VirtualSCSIController: VirtualSCSIController{
   764  									VirtualController: VirtualController{
   765  										VirtualDevice: VirtualDevice{
   766  											ControllerKey: -1,
   767  											Key:           -2,
   768  										},
   769  										BusNumber: 0,
   770  									},
   771  									HotAddRemove: NewBool(true),
   772  									SharedBus:    VirtualSCSISharingNoSharing,
   773  								},
   774  							},
   775  						},
   776  					},
   777  				},
   778  			},
   779  			{
   780  				name: "attach disk to new PVSCSI controller when adding PCI controller and disk sans controller and no existing devices",
   781  				configSpec: &VirtualMachineConfigSpec{
   782  					Version: vmx20,
   783  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   784  						&VirtualDeviceConfigSpec{
   785  							Operation: VirtualDeviceConfigSpecOperationAdd,
   786  							Device: &VirtualPCIController{
   787  								VirtualController: VirtualController{
   788  									VirtualDevice: VirtualDevice{
   789  										Key: -50,
   790  									},
   791  								},
   792  							},
   793  						},
   794  						&VirtualDeviceConfigSpec{
   795  							Operation: VirtualDeviceConfigSpecOperationAdd,
   796  							Device:    &VirtualDisk{},
   797  						},
   798  					},
   799  				},
   800  				existingDevices: nil,
   801  				err:             nil,
   802  				expectedConfigSpec: &VirtualMachineConfigSpec{
   803  					Version: vmx20,
   804  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   805  						&VirtualDeviceConfigSpec{
   806  							Operation: VirtualDeviceConfigSpecOperationAdd,
   807  							Device: &VirtualPCIController{
   808  								VirtualController: VirtualController{
   809  									VirtualDevice: VirtualDevice{
   810  										Key: -50,
   811  									},
   812  								},
   813  							},
   814  						},
   815  						&VirtualDeviceConfigSpec{
   816  							Operation: VirtualDeviceConfigSpecOperationAdd,
   817  							Device: &VirtualDisk{
   818  								VirtualDevice: VirtualDevice{
   819  									ControllerKey: -51,
   820  								},
   821  							},
   822  						},
   823  						&VirtualDeviceConfigSpec{
   824  							Operation: VirtualDeviceConfigSpecOperationAdd,
   825  							Device: &ParaVirtualSCSIController{
   826  								VirtualSCSIController: VirtualSCSIController{
   827  									VirtualController: VirtualController{
   828  										VirtualDevice: VirtualDevice{
   829  											ControllerKey: -50,
   830  											Key:           -51,
   831  										},
   832  										BusNumber: 0,
   833  									},
   834  									HotAddRemove: NewBool(true),
   835  									SharedBus:    VirtualSCSISharingNoSharing,
   836  								},
   837  							},
   838  						},
   839  					},
   840  				},
   841  			},
   842  			{
   843  				name: "attach disk to new PVSCSI controller when adding disk sans controller and existing devices only includes PCI controller",
   844  				configSpec: &VirtualMachineConfigSpec{
   845  					Version: vmx20,
   846  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   847  						&VirtualDeviceConfigSpec{
   848  							Operation: VirtualDeviceConfigSpecOperationAdd,
   849  							Device:    &VirtualDisk{},
   850  						},
   851  					},
   852  				},
   853  				existingDevices: []BaseVirtualDevice{
   854  					&VirtualPCIController{
   855  						VirtualController: VirtualController{
   856  							VirtualDevice: VirtualDevice{
   857  								Key: 100,
   858  							},
   859  						},
   860  					},
   861  				},
   862  				err: nil,
   863  				expectedConfigSpec: &VirtualMachineConfigSpec{
   864  					Version: vmx20,
   865  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   866  						&VirtualDeviceConfigSpec{
   867  							Operation: VirtualDeviceConfigSpecOperationAdd,
   868  							Device: &VirtualDisk{
   869  								VirtualDevice: VirtualDevice{
   870  									ControllerKey: -1,
   871  								},
   872  							},
   873  						},
   874  						&VirtualDeviceConfigSpec{
   875  							Operation: VirtualDeviceConfigSpecOperationAdd,
   876  							Device: &ParaVirtualSCSIController{
   877  								VirtualSCSIController: VirtualSCSIController{
   878  									VirtualController: VirtualController{
   879  										VirtualDevice: VirtualDevice{
   880  											ControllerKey: 100,
   881  											Key:           -1,
   882  										},
   883  										BusNumber: 0,
   884  									},
   885  									HotAddRemove: NewBool(true),
   886  									SharedBus:    VirtualSCSISharingNoSharing,
   887  								},
   888  							},
   889  						},
   890  					},
   891  				},
   892  			},
   893  
   894  			//
   895  			// SCSI (in existing devices)
   896  			//
   897  			{
   898  				name: "attach disk to existing controller when adding disk and existing devices includes PCI and PVSCSI controllers",
   899  				configSpec: &VirtualMachineConfigSpec{
   900  					Version: vmx20,
   901  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   902  						&VirtualDeviceConfigSpec{
   903  							Operation: VirtualDeviceConfigSpecOperationAdd,
   904  							Device:    &VirtualDisk{},
   905  						},
   906  					},
   907  				},
   908  				existingDevices: []BaseVirtualDevice{
   909  					&VirtualPCIController{
   910  						VirtualController: VirtualController{
   911  							VirtualDevice: VirtualDevice{
   912  								Key: 100,
   913  							},
   914  						},
   915  					},
   916  					&ParaVirtualSCSIController{
   917  						VirtualSCSIController: VirtualSCSIController{
   918  							VirtualController: VirtualController{
   919  								VirtualDevice: VirtualDevice{
   920  									ControllerKey: 100,
   921  									Key:           1000,
   922  								},
   923  							},
   924  						},
   925  					},
   926  				},
   927  				err: nil,
   928  				expectedConfigSpec: &VirtualMachineConfigSpec{
   929  					Version: vmx20,
   930  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   931  						&VirtualDeviceConfigSpec{
   932  							Operation: VirtualDeviceConfigSpecOperationAdd,
   933  							Device: &VirtualDisk{
   934  								VirtualDevice: VirtualDevice{
   935  									ControllerKey: 1000,
   936  								},
   937  							},
   938  						},
   939  					},
   940  				},
   941  			},
   942  			{
   943  				name: "attach disk to existing controller when adding disk and existing devices includes PCI and Bus Logic controllers",
   944  				configSpec: &VirtualMachineConfigSpec{
   945  					Version: vmx20,
   946  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   947  						&VirtualDeviceConfigSpec{
   948  							Operation: VirtualDeviceConfigSpecOperationAdd,
   949  							Device:    &VirtualDisk{},
   950  						},
   951  					},
   952  				},
   953  				existingDevices: []BaseVirtualDevice{
   954  					&VirtualPCIController{
   955  						VirtualController: VirtualController{
   956  							VirtualDevice: VirtualDevice{
   957  								Key: 100,
   958  							},
   959  						},
   960  					},
   961  					&VirtualBusLogicController{
   962  						VirtualSCSIController: VirtualSCSIController{
   963  							VirtualController: VirtualController{
   964  								VirtualDevice: VirtualDevice{
   965  									ControllerKey: 100,
   966  									Key:           1000,
   967  								},
   968  							},
   969  						},
   970  					},
   971  				},
   972  				err: nil,
   973  				expectedConfigSpec: &VirtualMachineConfigSpec{
   974  					Version: vmx20,
   975  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   976  						&VirtualDeviceConfigSpec{
   977  							Operation: VirtualDeviceConfigSpecOperationAdd,
   978  							Device: &VirtualDisk{
   979  								VirtualDevice: VirtualDevice{
   980  									ControllerKey: 1000,
   981  								},
   982  							},
   983  						},
   984  					},
   985  				},
   986  			},
   987  			{
   988  				name: "attach disk to existing controller when adding disk and existing devices includes PCI and LSI Logic controllers",
   989  				configSpec: &VirtualMachineConfigSpec{
   990  					Version: vmx20,
   991  					DeviceChange: []BaseVirtualDeviceConfigSpec{
   992  						&VirtualDeviceConfigSpec{
   993  							Operation: VirtualDeviceConfigSpecOperationAdd,
   994  							Device:    &VirtualDisk{},
   995  						},
   996  					},
   997  				},
   998  				existingDevices: []BaseVirtualDevice{
   999  					&VirtualPCIController{
  1000  						VirtualController: VirtualController{
  1001  							VirtualDevice: VirtualDevice{
  1002  								Key: 100,
  1003  							},
  1004  						},
  1005  					},
  1006  					&VirtualLsiLogicController{
  1007  						VirtualSCSIController: VirtualSCSIController{
  1008  							VirtualController: VirtualController{
  1009  								VirtualDevice: VirtualDevice{
  1010  									ControllerKey: 100,
  1011  									Key:           1000,
  1012  								},
  1013  							},
  1014  						},
  1015  					},
  1016  				},
  1017  				err: nil,
  1018  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1019  					Version: vmx20,
  1020  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1021  						&VirtualDeviceConfigSpec{
  1022  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1023  							Device: &VirtualDisk{
  1024  								VirtualDevice: VirtualDevice{
  1025  									ControllerKey: 1000,
  1026  								},
  1027  							},
  1028  						},
  1029  					},
  1030  				},
  1031  			},
  1032  			{
  1033  				name: "attach disk to existing controller when adding disk and existing devices includes PCI and LSI Logic SAS controllers",
  1034  				configSpec: &VirtualMachineConfigSpec{
  1035  					Version: vmx20,
  1036  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1037  						&VirtualDeviceConfigSpec{
  1038  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1039  							Device:    &VirtualDisk{},
  1040  						},
  1041  					},
  1042  				},
  1043  				existingDevices: []BaseVirtualDevice{
  1044  					&VirtualPCIController{
  1045  						VirtualController: VirtualController{
  1046  							VirtualDevice: VirtualDevice{
  1047  								Key: 100,
  1048  							},
  1049  						},
  1050  					},
  1051  					&VirtualLsiLogicSASController{
  1052  						VirtualSCSIController: VirtualSCSIController{
  1053  							VirtualController: VirtualController{
  1054  								VirtualDevice: VirtualDevice{
  1055  									ControllerKey: 100,
  1056  									Key:           1000,
  1057  								},
  1058  							},
  1059  						},
  1060  					},
  1061  				},
  1062  				err: nil,
  1063  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1064  					Version: vmx20,
  1065  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1066  						&VirtualDeviceConfigSpec{
  1067  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1068  							Device: &VirtualDisk{
  1069  								VirtualDevice: VirtualDevice{
  1070  									ControllerKey: 1000,
  1071  								},
  1072  							},
  1073  						},
  1074  					},
  1075  				},
  1076  			},
  1077  			{
  1078  				name: "attach disk to existing controller when adding disk and existing devices includes PCI and SCSI controllers",
  1079  				configSpec: &VirtualMachineConfigSpec{
  1080  					Version: vmx20,
  1081  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1082  						&VirtualDeviceConfigSpec{
  1083  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1084  							Device:    &VirtualDisk{},
  1085  						},
  1086  					},
  1087  				},
  1088  				existingDevices: []BaseVirtualDevice{
  1089  					&VirtualPCIController{
  1090  						VirtualController: VirtualController{
  1091  							VirtualDevice: VirtualDevice{
  1092  								Key: 100,
  1093  							},
  1094  						},
  1095  					},
  1096  					&VirtualSCSIController{
  1097  						VirtualController: VirtualController{
  1098  							VirtualDevice: VirtualDevice{
  1099  								ControllerKey: 100,
  1100  								Key:           1000,
  1101  							},
  1102  						},
  1103  					},
  1104  				},
  1105  				err: nil,
  1106  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1107  					Version: vmx20,
  1108  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1109  						&VirtualDeviceConfigSpec{
  1110  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1111  							Device: &VirtualDisk{
  1112  								VirtualDevice: VirtualDevice{
  1113  									ControllerKey: 1000,
  1114  								},
  1115  							},
  1116  						},
  1117  					},
  1118  				},
  1119  			},
  1120  
  1121  			//
  1122  			// SATA (in existing devices)
  1123  			//
  1124  			{
  1125  				name: "attach disk to existing controller when adding disk and existing devices includes PCI and SATA controllers",
  1126  				configSpec: &VirtualMachineConfigSpec{
  1127  					Version: vmx20,
  1128  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1129  						&VirtualDeviceConfigSpec{
  1130  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1131  							Device:    &VirtualDisk{},
  1132  						},
  1133  					},
  1134  				},
  1135  				existingDevices: []BaseVirtualDevice{
  1136  					&VirtualPCIController{
  1137  						VirtualController: VirtualController{
  1138  							VirtualDevice: VirtualDevice{
  1139  								Key: 100,
  1140  							},
  1141  						},
  1142  					},
  1143  					&VirtualAHCIController{
  1144  						VirtualSATAController: VirtualSATAController{
  1145  							VirtualController: VirtualController{
  1146  								VirtualDevice: VirtualDevice{
  1147  									ControllerKey: 100,
  1148  									Key:           15000,
  1149  								},
  1150  							},
  1151  						},
  1152  					},
  1153  				},
  1154  				err: nil,
  1155  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1156  					Version: vmx20,
  1157  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1158  						&VirtualDeviceConfigSpec{
  1159  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1160  							Device: &VirtualDisk{
  1161  								VirtualDevice: VirtualDevice{
  1162  									ControllerKey: 15000,
  1163  								},
  1164  							},
  1165  						},
  1166  					},
  1167  				},
  1168  			},
  1169  			{
  1170  				name: "attach disk to existing controller when adding disk and existing devices includes PCI and AHCI controllers",
  1171  				configSpec: &VirtualMachineConfigSpec{
  1172  					Version: vmx20,
  1173  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1174  						&VirtualDeviceConfigSpec{
  1175  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1176  							Device:    &VirtualDisk{},
  1177  						},
  1178  					},
  1179  				},
  1180  				existingDevices: []BaseVirtualDevice{
  1181  					&VirtualPCIController{
  1182  						VirtualController: VirtualController{
  1183  							VirtualDevice: VirtualDevice{
  1184  								Key: 100,
  1185  							},
  1186  						},
  1187  					},
  1188  					&VirtualAHCIController{
  1189  						VirtualSATAController: VirtualSATAController{
  1190  							VirtualController: VirtualController{
  1191  								VirtualDevice: VirtualDevice{
  1192  									ControllerKey: 100,
  1193  									Key:           15000,
  1194  								},
  1195  							},
  1196  						},
  1197  					},
  1198  				},
  1199  				err: nil,
  1200  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1201  					Version: vmx20,
  1202  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1203  						&VirtualDeviceConfigSpec{
  1204  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1205  							Device: &VirtualDisk{
  1206  								VirtualDevice: VirtualDevice{
  1207  									ControllerKey: 15000,
  1208  								},
  1209  							},
  1210  						},
  1211  					},
  1212  				},
  1213  			},
  1214  
  1215  			//
  1216  			// NVME (in existing devices)
  1217  			//
  1218  			{
  1219  				name: "attach disk to existing controller when adding disk and existing devices includes PCI and NVME controllers",
  1220  				configSpec: &VirtualMachineConfigSpec{
  1221  					Version: vmx20,
  1222  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1223  						&VirtualDeviceConfigSpec{
  1224  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1225  							Device:    &VirtualDisk{},
  1226  						},
  1227  					},
  1228  				},
  1229  				existingDevices: []BaseVirtualDevice{
  1230  					&VirtualPCIController{
  1231  						VirtualController: VirtualController{
  1232  							VirtualDevice: VirtualDevice{
  1233  								Key: 100,
  1234  							},
  1235  						},
  1236  					},
  1237  					&VirtualNVMEController{
  1238  						VirtualController: VirtualController{
  1239  							VirtualDevice: VirtualDevice{
  1240  								ControllerKey: 100,
  1241  								Key:           31000,
  1242  							},
  1243  						},
  1244  					},
  1245  				},
  1246  				err: nil,
  1247  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1248  					Version: vmx20,
  1249  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1250  						&VirtualDeviceConfigSpec{
  1251  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1252  							Device: &VirtualDisk{
  1253  								VirtualDevice: VirtualDevice{
  1254  									ControllerKey: 31000,
  1255  								},
  1256  							},
  1257  						},
  1258  					},
  1259  				},
  1260  			},
  1261  
  1262  			//
  1263  			// SCSI (in ConfigSpec)
  1264  			//
  1265  			{
  1266  				name: "attach disk to PVSCSI controller in ConfigSpec when adding disk and existing devices includes only PCI controller",
  1267  				configSpec: &VirtualMachineConfigSpec{
  1268  					Version: vmx20,
  1269  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1270  						&VirtualDeviceConfigSpec{
  1271  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1272  							Device: &ParaVirtualSCSIController{
  1273  								VirtualSCSIController: VirtualSCSIController{
  1274  									VirtualController: VirtualController{
  1275  										VirtualDevice: VirtualDevice{
  1276  											ControllerKey: 100,
  1277  											Key:           -10,
  1278  										},
  1279  									},
  1280  								},
  1281  							},
  1282  						},
  1283  						&VirtualDeviceConfigSpec{
  1284  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1285  							Device:    &VirtualDisk{},
  1286  						},
  1287  					},
  1288  				},
  1289  				existingDevices: []BaseVirtualDevice{
  1290  					&VirtualPCIController{
  1291  						VirtualController: VirtualController{
  1292  							VirtualDevice: VirtualDevice{
  1293  								Key: 100,
  1294  							},
  1295  						},
  1296  					},
  1297  				},
  1298  				err: nil,
  1299  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1300  					Version: vmx20,
  1301  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1302  						&VirtualDeviceConfigSpec{
  1303  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1304  							Device: &ParaVirtualSCSIController{
  1305  								VirtualSCSIController: VirtualSCSIController{
  1306  									VirtualController: VirtualController{
  1307  										VirtualDevice: VirtualDevice{
  1308  											ControllerKey: 100,
  1309  											Key:           -10,
  1310  										},
  1311  									},
  1312  								},
  1313  							},
  1314  						},
  1315  						&VirtualDeviceConfigSpec{
  1316  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1317  							Device: &VirtualDisk{
  1318  								VirtualDevice: VirtualDevice{
  1319  									ControllerKey: -10,
  1320  								},
  1321  							},
  1322  						},
  1323  					},
  1324  				},
  1325  			},
  1326  			{
  1327  				name: "attach disk to Bus Logic controller in ConfigSpec when adding disk and existing devices includes only PCI controller",
  1328  				configSpec: &VirtualMachineConfigSpec{
  1329  					Version: vmx20,
  1330  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1331  						&VirtualDeviceConfigSpec{
  1332  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1333  							Device: &VirtualBusLogicController{
  1334  								VirtualSCSIController: VirtualSCSIController{
  1335  									VirtualController: VirtualController{
  1336  										VirtualDevice: VirtualDevice{
  1337  											ControllerKey: 100,
  1338  											Key:           -10,
  1339  										},
  1340  									},
  1341  								},
  1342  							},
  1343  						},
  1344  						&VirtualDeviceConfigSpec{
  1345  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1346  							Device:    &VirtualDisk{},
  1347  						},
  1348  					},
  1349  				},
  1350  				existingDevices: []BaseVirtualDevice{
  1351  					&VirtualPCIController{
  1352  						VirtualController: VirtualController{
  1353  							VirtualDevice: VirtualDevice{
  1354  								Key: 100,
  1355  							},
  1356  						},
  1357  					},
  1358  				},
  1359  				err: nil,
  1360  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1361  					Version: vmx20,
  1362  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1363  						&VirtualDeviceConfigSpec{
  1364  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1365  							Device: &VirtualBusLogicController{
  1366  								VirtualSCSIController: VirtualSCSIController{
  1367  									VirtualController: VirtualController{
  1368  										VirtualDevice: VirtualDevice{
  1369  											ControllerKey: 100,
  1370  											Key:           -10,
  1371  										},
  1372  									},
  1373  								},
  1374  							},
  1375  						},
  1376  						&VirtualDeviceConfigSpec{
  1377  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1378  							Device: &VirtualDisk{
  1379  								VirtualDevice: VirtualDevice{
  1380  									ControllerKey: -10,
  1381  								},
  1382  							},
  1383  						},
  1384  					},
  1385  				},
  1386  			},
  1387  			{
  1388  				name: "attach disk to LSI Logic controller in ConfigSpec when adding disk and existing devices includes only PCI controller",
  1389  				configSpec: &VirtualMachineConfigSpec{
  1390  					Version: vmx20,
  1391  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1392  						&VirtualDeviceConfigSpec{
  1393  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1394  							Device: &VirtualLsiLogicController{
  1395  								VirtualSCSIController: VirtualSCSIController{
  1396  									VirtualController: VirtualController{
  1397  										VirtualDevice: VirtualDevice{
  1398  											ControllerKey: 100,
  1399  											Key:           -10,
  1400  										},
  1401  									},
  1402  								},
  1403  							},
  1404  						},
  1405  						&VirtualDeviceConfigSpec{
  1406  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1407  							Device:    &VirtualDisk{},
  1408  						},
  1409  					},
  1410  				},
  1411  				existingDevices: []BaseVirtualDevice{
  1412  					&VirtualPCIController{
  1413  						VirtualController: VirtualController{
  1414  							VirtualDevice: VirtualDevice{
  1415  								Key: 100,
  1416  							},
  1417  						},
  1418  					},
  1419  				},
  1420  				err: nil,
  1421  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1422  					Version: vmx20,
  1423  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1424  						&VirtualDeviceConfigSpec{
  1425  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1426  							Device: &VirtualLsiLogicController{
  1427  								VirtualSCSIController: VirtualSCSIController{
  1428  									VirtualController: VirtualController{
  1429  										VirtualDevice: VirtualDevice{
  1430  											ControllerKey: 100,
  1431  											Key:           -10,
  1432  										},
  1433  									},
  1434  								},
  1435  							},
  1436  						},
  1437  						&VirtualDeviceConfigSpec{
  1438  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1439  							Device: &VirtualDisk{
  1440  								VirtualDevice: VirtualDevice{
  1441  									ControllerKey: -10,
  1442  								},
  1443  							},
  1444  						},
  1445  					},
  1446  				},
  1447  			},
  1448  			{
  1449  				name: "attach disk to LSI Logic SAS controller in ConfigSpec when adding disk and existing devices includes only PCI controller",
  1450  				configSpec: &VirtualMachineConfigSpec{
  1451  					Version: vmx20,
  1452  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1453  						&VirtualDeviceConfigSpec{
  1454  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1455  							Device: &VirtualLsiLogicSASController{
  1456  								VirtualSCSIController: VirtualSCSIController{
  1457  									VirtualController: VirtualController{
  1458  										VirtualDevice: VirtualDevice{
  1459  											ControllerKey: 100,
  1460  											Key:           -10,
  1461  										},
  1462  									},
  1463  								},
  1464  							},
  1465  						},
  1466  						&VirtualDeviceConfigSpec{
  1467  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1468  							Device:    &VirtualDisk{},
  1469  						},
  1470  					},
  1471  				},
  1472  				existingDevices: []BaseVirtualDevice{
  1473  					&VirtualPCIController{
  1474  						VirtualController: VirtualController{
  1475  							VirtualDevice: VirtualDevice{
  1476  								Key: 100,
  1477  							},
  1478  						},
  1479  					},
  1480  				},
  1481  				err: nil,
  1482  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1483  					Version: vmx20,
  1484  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1485  						&VirtualDeviceConfigSpec{
  1486  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1487  							Device: &VirtualLsiLogicSASController{
  1488  								VirtualSCSIController: VirtualSCSIController{
  1489  									VirtualController: VirtualController{
  1490  										VirtualDevice: VirtualDevice{
  1491  											ControllerKey: 100,
  1492  											Key:           -10,
  1493  										},
  1494  									},
  1495  								},
  1496  							},
  1497  						},
  1498  						&VirtualDeviceConfigSpec{
  1499  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1500  							Device: &VirtualDisk{
  1501  								VirtualDevice: VirtualDevice{
  1502  									ControllerKey: -10,
  1503  								},
  1504  							},
  1505  						},
  1506  					},
  1507  				},
  1508  			},
  1509  			{
  1510  				name: "attach disk to SCSI controller in ConfigSpec when adding disk and existing devices includes only PCI controller",
  1511  				configSpec: &VirtualMachineConfigSpec{
  1512  					Version: vmx20,
  1513  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1514  						&VirtualDeviceConfigSpec{
  1515  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1516  							Device: &VirtualSCSIController{
  1517  								VirtualController: VirtualController{
  1518  									VirtualDevice: VirtualDevice{
  1519  										ControllerKey: 100,
  1520  										Key:           -10,
  1521  									},
  1522  								},
  1523  							},
  1524  						},
  1525  						&VirtualDeviceConfigSpec{
  1526  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1527  							Device:    &VirtualDisk{},
  1528  						},
  1529  					},
  1530  				},
  1531  				existingDevices: []BaseVirtualDevice{
  1532  					&VirtualPCIController{
  1533  						VirtualController: VirtualController{
  1534  							VirtualDevice: VirtualDevice{
  1535  								Key: 100,
  1536  							},
  1537  						},
  1538  					},
  1539  				},
  1540  				err: nil,
  1541  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1542  					Version: vmx20,
  1543  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1544  						&VirtualDeviceConfigSpec{
  1545  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1546  							Device: &VirtualSCSIController{
  1547  								VirtualController: VirtualController{
  1548  									VirtualDevice: VirtualDevice{
  1549  										ControllerKey: 100,
  1550  										Key:           -10,
  1551  									},
  1552  								},
  1553  							},
  1554  						},
  1555  						&VirtualDeviceConfigSpec{
  1556  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1557  							Device: &VirtualDisk{
  1558  								VirtualDevice: VirtualDevice{
  1559  									ControllerKey: -10,
  1560  								},
  1561  							},
  1562  						},
  1563  					},
  1564  				},
  1565  			},
  1566  
  1567  			//
  1568  			// SATA (in ConfigSpec)
  1569  			//
  1570  			{
  1571  				name: "attach disk to SATA controller in ConfigSpec when adding disk and existing devices includes only PCI controller",
  1572  				configSpec: &VirtualMachineConfigSpec{
  1573  					Version: vmx20,
  1574  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1575  						&VirtualDeviceConfigSpec{
  1576  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1577  							Device: &VirtualAHCIController{
  1578  								VirtualSATAController: VirtualSATAController{
  1579  									VirtualController: VirtualController{
  1580  										VirtualDevice: VirtualDevice{
  1581  											ControllerKey: 100,
  1582  											Key:           -10,
  1583  										},
  1584  									},
  1585  								},
  1586  							},
  1587  						},
  1588  						&VirtualDeviceConfigSpec{
  1589  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1590  							Device:    &VirtualDisk{},
  1591  						},
  1592  					},
  1593  				},
  1594  				existingDevices: []BaseVirtualDevice{
  1595  					&VirtualPCIController{
  1596  						VirtualController: VirtualController{
  1597  							VirtualDevice: VirtualDevice{
  1598  								Key: 100,
  1599  							},
  1600  						},
  1601  					},
  1602  				},
  1603  				err: nil,
  1604  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1605  					Version: vmx20,
  1606  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1607  						&VirtualDeviceConfigSpec{
  1608  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1609  							Device: &VirtualAHCIController{
  1610  								VirtualSATAController: VirtualSATAController{
  1611  									VirtualController: VirtualController{
  1612  										VirtualDevice: VirtualDevice{
  1613  											ControllerKey: 100,
  1614  											Key:           -10,
  1615  										},
  1616  									},
  1617  								},
  1618  							},
  1619  						},
  1620  						&VirtualDeviceConfigSpec{
  1621  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1622  							Device: &VirtualDisk{
  1623  								VirtualDevice: VirtualDevice{
  1624  									ControllerKey: -10,
  1625  								},
  1626  							},
  1627  						},
  1628  					},
  1629  				},
  1630  			},
  1631  			{
  1632  				name: "attach disk to AHCI controller in ConfigSpec when adding disk and existing devices includes only PCI controller",
  1633  				configSpec: &VirtualMachineConfigSpec{
  1634  					Version: vmx20,
  1635  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1636  						&VirtualDeviceConfigSpec{
  1637  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1638  							Device: &VirtualAHCIController{
  1639  								VirtualSATAController: VirtualSATAController{
  1640  									VirtualController: VirtualController{
  1641  										VirtualDevice: VirtualDevice{
  1642  											ControllerKey: 100,
  1643  											Key:           -10,
  1644  										},
  1645  									},
  1646  								},
  1647  							},
  1648  						},
  1649  						&VirtualDeviceConfigSpec{
  1650  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1651  							Device:    &VirtualDisk{},
  1652  						},
  1653  					},
  1654  				},
  1655  				existingDevices: []BaseVirtualDevice{
  1656  					&VirtualPCIController{
  1657  						VirtualController: VirtualController{
  1658  							VirtualDevice: VirtualDevice{
  1659  								Key: 100,
  1660  							},
  1661  						},
  1662  					},
  1663  				},
  1664  				err: nil,
  1665  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1666  					Version: vmx20,
  1667  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1668  						&VirtualDeviceConfigSpec{
  1669  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1670  							Device: &VirtualAHCIController{
  1671  								VirtualSATAController: VirtualSATAController{
  1672  									VirtualController: VirtualController{
  1673  										VirtualDevice: VirtualDevice{
  1674  											ControllerKey: 100,
  1675  											Key:           -10,
  1676  										},
  1677  									},
  1678  								},
  1679  							},
  1680  						},
  1681  						&VirtualDeviceConfigSpec{
  1682  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1683  							Device: &VirtualDisk{
  1684  								VirtualDevice: VirtualDevice{
  1685  									ControllerKey: -10,
  1686  								},
  1687  							},
  1688  						},
  1689  					},
  1690  				},
  1691  			},
  1692  
  1693  			//
  1694  			// NVME (in ConfigSpec)
  1695  			//
  1696  			{
  1697  				name: "attach disk to NVME controller in ConfigSpec when adding disk and existing devices includes only PCI controller",
  1698  				configSpec: &VirtualMachineConfigSpec{
  1699  					Version: vmx20,
  1700  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1701  						&VirtualDeviceConfigSpec{
  1702  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1703  							Device: &VirtualNVMEController{
  1704  								VirtualController: VirtualController{
  1705  									VirtualDevice: VirtualDevice{
  1706  										ControllerKey: 100,
  1707  										Key:           -10,
  1708  									},
  1709  								},
  1710  							},
  1711  						},
  1712  						&VirtualDeviceConfigSpec{
  1713  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1714  							Device:    &VirtualDisk{},
  1715  						},
  1716  					},
  1717  				},
  1718  				existingDevices: []BaseVirtualDevice{
  1719  					&VirtualPCIController{
  1720  						VirtualController: VirtualController{
  1721  							VirtualDevice: VirtualDevice{
  1722  								Key: 100,
  1723  							},
  1724  						},
  1725  					},
  1726  				},
  1727  				err: nil,
  1728  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1729  					Version: vmx20,
  1730  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1731  						&VirtualDeviceConfigSpec{
  1732  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1733  							Device: &VirtualNVMEController{
  1734  								VirtualController: VirtualController{
  1735  									VirtualDevice: VirtualDevice{
  1736  										ControllerKey: 100,
  1737  										Key:           -10,
  1738  									},
  1739  								},
  1740  							},
  1741  						},
  1742  						&VirtualDeviceConfigSpec{
  1743  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1744  							Device: &VirtualDisk{
  1745  								VirtualDevice: VirtualDevice{
  1746  									ControllerKey: -10,
  1747  								},
  1748  							},
  1749  						},
  1750  					},
  1751  				},
  1752  			},
  1753  
  1754  			//
  1755  			// First SCSI HBA is full
  1756  			//
  1757  			{
  1758  				name: "attach disk to new PVSCSI controller when adding disk and existing devices includes PCI controller and LSI Logic controller with no free slots",
  1759  				configSpec: &VirtualMachineConfigSpec{
  1760  					Version: vmx20,
  1761  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1762  						&VirtualDeviceConfigSpec{
  1763  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1764  							Device:    &VirtualDisk{},
  1765  						},
  1766  					},
  1767  				},
  1768  				existingDevices: ensureDiskControllerJoinSlices(
  1769  					[]BaseVirtualDevice{
  1770  						&VirtualPCIController{
  1771  							VirtualController: VirtualController{
  1772  								VirtualDevice: VirtualDevice{
  1773  									Key: 100,
  1774  								},
  1775  							},
  1776  						},
  1777  					},
  1778  
  1779  					//
  1780  					// SCSI HBA 1 / 16 disks
  1781  					//
  1782  					append(
  1783  						[]BaseVirtualDevice{
  1784  							&VirtualLsiLogicController{
  1785  								VirtualSCSIController: VirtualSCSIController{
  1786  									VirtualController: VirtualController{
  1787  										VirtualDevice: VirtualDevice{
  1788  											ControllerKey: 100,
  1789  											Key:           1000,
  1790  										},
  1791  										BusNumber: 1,
  1792  									},
  1793  								},
  1794  							},
  1795  						},
  1796  						ensureDiskControllerGenerateVirtualDisks(16, 1000)...,
  1797  					),
  1798  				),
  1799  				err: nil,
  1800  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1801  					Version: vmx20,
  1802  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1803  						&VirtualDeviceConfigSpec{
  1804  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1805  							Device: &VirtualDisk{
  1806  								VirtualDevice: VirtualDevice{
  1807  									ControllerKey: -1,
  1808  								},
  1809  							},
  1810  						},
  1811  						&VirtualDeviceConfigSpec{
  1812  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1813  							Device: &ParaVirtualSCSIController{
  1814  								VirtualSCSIController: VirtualSCSIController{
  1815  									VirtualController: VirtualController{
  1816  										VirtualDevice: VirtualDevice{
  1817  											ControllerKey: 100,
  1818  											Key:           -1,
  1819  										},
  1820  										BusNumber: 0,
  1821  									},
  1822  									HotAddRemove: NewBool(true),
  1823  									SharedBus:    VirtualSCSISharingNoSharing,
  1824  								},
  1825  							},
  1826  						},
  1827  					},
  1828  				},
  1829  			},
  1830  
  1831  			//
  1832  			// First and second SCSI HBAs are full
  1833  			//
  1834  			{
  1835  				name: "attach disk to new PVSCSI controller when adding disk and existing devices includes PCI controller and two existing SCSI controllers have no free slots",
  1836  				configSpec: &VirtualMachineConfigSpec{
  1837  					Version: vmx20,
  1838  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1839  						&VirtualDeviceConfigSpec{
  1840  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1841  							Device:    &VirtualDisk{},
  1842  						},
  1843  					},
  1844  				},
  1845  				existingDevices: ensureDiskControllerJoinSlices(
  1846  					[]BaseVirtualDevice{
  1847  						&VirtualPCIController{
  1848  							VirtualController: VirtualController{
  1849  								VirtualDevice: VirtualDevice{
  1850  									Key: 100,
  1851  								},
  1852  							},
  1853  						},
  1854  					},
  1855  
  1856  					//
  1857  					// SCSI HBA 1 / 16 disks
  1858  					//
  1859  					append(
  1860  						[]BaseVirtualDevice{
  1861  							&VirtualLsiLogicController{
  1862  								VirtualSCSIController: VirtualSCSIController{
  1863  									VirtualController: VirtualController{
  1864  										VirtualDevice: VirtualDevice{
  1865  											ControllerKey: 100,
  1866  											Key:           1000,
  1867  										},
  1868  										BusNumber: 0,
  1869  									},
  1870  								},
  1871  							},
  1872  						},
  1873  						ensureDiskControllerGenerateVirtualDisks(16, 1000)...,
  1874  					),
  1875  
  1876  					//
  1877  					// SCSI HBA 2 / 16 disks
  1878  					//
  1879  					append(
  1880  						[]BaseVirtualDevice{
  1881  							&VirtualBusLogicController{
  1882  								VirtualSCSIController: VirtualSCSIController{
  1883  									VirtualController: VirtualController{
  1884  										VirtualDevice: VirtualDevice{
  1885  											ControllerKey: 100,
  1886  											Key:           1001,
  1887  										},
  1888  										BusNumber: 3,
  1889  									},
  1890  								},
  1891  							},
  1892  						},
  1893  						ensureDiskControllerGenerateVirtualDisks(16, 1001)...,
  1894  					),
  1895  				),
  1896  				err: nil,
  1897  				expectedConfigSpec: &VirtualMachineConfigSpec{
  1898  					Version: vmx20,
  1899  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1900  						&VirtualDeviceConfigSpec{
  1901  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1902  							Device: &VirtualDisk{
  1903  								VirtualDevice: VirtualDevice{
  1904  									ControllerKey: -1,
  1905  								},
  1906  							},
  1907  						},
  1908  						&VirtualDeviceConfigSpec{
  1909  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1910  							Device: &ParaVirtualSCSIController{
  1911  								VirtualSCSIController: VirtualSCSIController{
  1912  									VirtualController: VirtualController{
  1913  										VirtualDevice: VirtualDevice{
  1914  											ControllerKey: 100,
  1915  											Key:           -1,
  1916  										},
  1917  										BusNumber: 1,
  1918  									},
  1919  									HotAddRemove: NewBool(true),
  1920  									SharedBus:    VirtualSCSISharingNoSharing,
  1921  								},
  1922  							},
  1923  						},
  1924  					},
  1925  				},
  1926  			},
  1927  
  1928  			//
  1929  			// First, second, and third SCSI HBAs are full
  1930  			//
  1931  			{
  1932  				name: "attach disk to new PVSCSI controller when adding disk and existing devices includes PCI controller and three existing SCSI controllers have no free slots",
  1933  				configSpec: &VirtualMachineConfigSpec{
  1934  					Version: vmx20,
  1935  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  1936  						&VirtualDeviceConfigSpec{
  1937  							Operation: VirtualDeviceConfigSpecOperationAdd,
  1938  							Device:    &VirtualDisk{},
  1939  						},
  1940  					},
  1941  				},
  1942  				existingDevices: ensureDiskControllerJoinSlices(
  1943  					[]BaseVirtualDevice{
  1944  						&VirtualPCIController{
  1945  							VirtualController: VirtualController{
  1946  								VirtualDevice: VirtualDevice{
  1947  									Key: 100,
  1948  								},
  1949  							},
  1950  						},
  1951  					},
  1952  
  1953  					//
  1954  					// SCSI HBA 1 / 16 disks
  1955  					//
  1956  					append(
  1957  						[]BaseVirtualDevice{
  1958  							&VirtualLsiLogicController{
  1959  								VirtualSCSIController: VirtualSCSIController{
  1960  									VirtualController: VirtualController{
  1961  										VirtualDevice: VirtualDevice{
  1962  											ControllerKey: 100,
  1963  											Key:           1000,
  1964  										},
  1965  										BusNumber: 3,
  1966  									},
  1967  								},
  1968  							},
  1969  						},
  1970  						ensureDiskControllerGenerateVirtualDisks(16, 1000)...,
  1971  					),
  1972  
  1973  					//
  1974  					// SCSI HBA 2 / 16 disks
  1975  					//
  1976  					append(
  1977  						[]BaseVirtualDevice{
  1978  							&VirtualBusLogicController{
  1979  								VirtualSCSIController: VirtualSCSIController{
  1980  									VirtualController: VirtualController{
  1981  										VirtualDevice: VirtualDevice{
  1982  											ControllerKey: 100,
  1983  											Key:           1001,
  1984  										},
  1985  										BusNumber: 0,
  1986  									},
  1987  								},
  1988  							},
  1989  						},
  1990  						ensureDiskControllerGenerateVirtualDisks(16, 1001)...,
  1991  					),
  1992  
  1993  					//
  1994  					// SCSI HBA 3 / 16 disks
  1995  					//
  1996  					append(
  1997  						[]BaseVirtualDevice{
  1998  							&VirtualBusLogicController{
  1999  								VirtualSCSIController: VirtualSCSIController{
  2000  									VirtualController: VirtualController{
  2001  										VirtualDevice: VirtualDevice{
  2002  											ControllerKey: 100,
  2003  											Key:           1002,
  2004  										},
  2005  										BusNumber: 1,
  2006  									},
  2007  								},
  2008  							},
  2009  						},
  2010  						ensureDiskControllerGenerateVirtualDisks(16, 1002)...,
  2011  					),
  2012  				),
  2013  				err: nil,
  2014  				expectedConfigSpec: &VirtualMachineConfigSpec{
  2015  					Version: vmx20,
  2016  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  2017  						&VirtualDeviceConfigSpec{
  2018  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2019  							Device: &VirtualDisk{
  2020  								VirtualDevice: VirtualDevice{
  2021  									ControllerKey: -1,
  2022  								},
  2023  							},
  2024  						},
  2025  						&VirtualDeviceConfigSpec{
  2026  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2027  							Device: &ParaVirtualSCSIController{
  2028  								VirtualSCSIController: VirtualSCSIController{
  2029  									VirtualController: VirtualController{
  2030  										VirtualDevice: VirtualDevice{
  2031  											ControllerKey: 100,
  2032  											Key:           -1,
  2033  										},
  2034  										BusNumber: 2,
  2035  									},
  2036  									HotAddRemove: NewBool(true),
  2037  									SharedBus:    VirtualSCSISharingNoSharing,
  2038  								},
  2039  							},
  2040  						},
  2041  					},
  2042  				},
  2043  			},
  2044  
  2045  			//
  2046  			// First, second, and third SCSI HBAs are full (different bus number)
  2047  			//
  2048  			{
  2049  				name: "attach disk to new PVSCSI controller (bus number three) when adding disk and existing devices includes PCI controller and three existing SCSI controllers have no free slots",
  2050  				configSpec: &VirtualMachineConfigSpec{
  2051  					Version: vmx20,
  2052  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  2053  						&VirtualDeviceConfigSpec{
  2054  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2055  							Device:    &VirtualDisk{},
  2056  						},
  2057  					},
  2058  				},
  2059  				existingDevices: ensureDiskControllerJoinSlices(
  2060  					[]BaseVirtualDevice{
  2061  						&VirtualPCIController{
  2062  							VirtualController: VirtualController{
  2063  								VirtualDevice: VirtualDevice{
  2064  									Key: 100,
  2065  								},
  2066  							},
  2067  						},
  2068  					},
  2069  
  2070  					//
  2071  					// SCSI HBA 1 / 16 disks
  2072  					//
  2073  					append(
  2074  						[]BaseVirtualDevice{
  2075  							&VirtualLsiLogicController{
  2076  								VirtualSCSIController: VirtualSCSIController{
  2077  									VirtualController: VirtualController{
  2078  										VirtualDevice: VirtualDevice{
  2079  											ControllerKey: 100,
  2080  											Key:           1000,
  2081  										},
  2082  										BusNumber: 2,
  2083  									},
  2084  								},
  2085  							},
  2086  						},
  2087  						ensureDiskControllerGenerateVirtualDisks(16, 1000)...,
  2088  					),
  2089  
  2090  					//
  2091  					// SCSI HBA 2 / 16 disks
  2092  					//
  2093  					append(
  2094  						[]BaseVirtualDevice{
  2095  							&VirtualBusLogicController{
  2096  								VirtualSCSIController: VirtualSCSIController{
  2097  									VirtualController: VirtualController{
  2098  										VirtualDevice: VirtualDevice{
  2099  											ControllerKey: 100,
  2100  											Key:           1001,
  2101  										},
  2102  										BusNumber: 0,
  2103  									},
  2104  								},
  2105  							},
  2106  						},
  2107  						ensureDiskControllerGenerateVirtualDisks(16, 1001)...,
  2108  					),
  2109  
  2110  					//
  2111  					// SCSI HBA 3 / 16 disks
  2112  					//
  2113  					append(
  2114  						[]BaseVirtualDevice{
  2115  							&VirtualBusLogicController{
  2116  								VirtualSCSIController: VirtualSCSIController{
  2117  									VirtualController: VirtualController{
  2118  										VirtualDevice: VirtualDevice{
  2119  											ControllerKey: 100,
  2120  											Key:           1002,
  2121  										},
  2122  										BusNumber: 1,
  2123  									},
  2124  								},
  2125  							},
  2126  						},
  2127  						ensureDiskControllerGenerateVirtualDisks(16, 1002)...,
  2128  					),
  2129  				),
  2130  				err: nil,
  2131  				expectedConfigSpec: &VirtualMachineConfigSpec{
  2132  					Version: vmx20,
  2133  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  2134  						&VirtualDeviceConfigSpec{
  2135  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2136  							Device: &VirtualDisk{
  2137  								VirtualDevice: VirtualDevice{
  2138  									ControllerKey: -1,
  2139  								},
  2140  							},
  2141  						},
  2142  						&VirtualDeviceConfigSpec{
  2143  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2144  							Device: &ParaVirtualSCSIController{
  2145  								VirtualSCSIController: VirtualSCSIController{
  2146  									VirtualController: VirtualController{
  2147  										VirtualDevice: VirtualDevice{
  2148  											ControllerKey: 100,
  2149  											Key:           -1,
  2150  										},
  2151  										BusNumber: 3,
  2152  									},
  2153  									HotAddRemove: NewBool(true),
  2154  									SharedBus:    VirtualSCSISharingNoSharing,
  2155  								},
  2156  							},
  2157  						},
  2158  					},
  2159  				},
  2160  			},
  2161  
  2162  			//
  2163  			// All SCSI HBAs are full
  2164  			//
  2165  			{
  2166  				name: "attach disk to new SATA controller when adding disk and existing devices includes PCI controller and there are already four SCSI controllers with no free slots",
  2167  				configSpec: &VirtualMachineConfigSpec{
  2168  					Version: vmx20,
  2169  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  2170  						&VirtualDeviceConfigSpec{
  2171  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2172  							Device:    &VirtualDisk{},
  2173  						},
  2174  					},
  2175  				},
  2176  				existingDevices: ensureDiskControllerJoinSlices(
  2177  					[]BaseVirtualDevice{
  2178  						&VirtualPCIController{
  2179  							VirtualController: VirtualController{
  2180  								VirtualDevice: VirtualDevice{
  2181  									Key: 100,
  2182  								},
  2183  							},
  2184  						},
  2185  					},
  2186  
  2187  					//
  2188  					// SCSI HBA 1 / 16 disks
  2189  					//
  2190  					append(
  2191  						[]BaseVirtualDevice{
  2192  							&ParaVirtualSCSIController{
  2193  								VirtualSCSIController: VirtualSCSIController{
  2194  									VirtualController: VirtualController{
  2195  										VirtualDevice: VirtualDevice{
  2196  											ControllerKey: 100,
  2197  											Key:           1000,
  2198  										},
  2199  									},
  2200  								},
  2201  							},
  2202  						},
  2203  						ensureDiskControllerGenerateVirtualDisks(16, 1000)...,
  2204  					),
  2205  					//
  2206  					// SCSI HBA 2 / 16 disks
  2207  					//
  2208  					append(
  2209  						[]BaseVirtualDevice{
  2210  							&VirtualLsiLogicController{
  2211  								VirtualSCSIController: VirtualSCSIController{
  2212  									VirtualController: VirtualController{
  2213  										VirtualDevice: VirtualDevice{
  2214  											ControllerKey: 100,
  2215  											Key:           1001,
  2216  										},
  2217  									},
  2218  								},
  2219  							},
  2220  						},
  2221  						ensureDiskControllerGenerateVirtualDisks(16, 1001)...,
  2222  					),
  2223  					//
  2224  					// SCSI HBA 3 / 16 disks
  2225  					//
  2226  					append(
  2227  						[]BaseVirtualDevice{
  2228  							&VirtualSCSIController{
  2229  								VirtualController: VirtualController{
  2230  									VirtualDevice: VirtualDevice{
  2231  										ControllerKey: 100,
  2232  										Key:           1002,
  2233  									},
  2234  								},
  2235  							},
  2236  						},
  2237  						ensureDiskControllerGenerateVirtualDisks(16, 1002)...,
  2238  					),
  2239  					//
  2240  					// SCSI HBA 4 / 16 disks
  2241  					//
  2242  					append(
  2243  						[]BaseVirtualDevice{
  2244  							&VirtualLsiLogicSASController{
  2245  								VirtualSCSIController: VirtualSCSIController{
  2246  									VirtualController: VirtualController{
  2247  										VirtualDevice: VirtualDevice{
  2248  											ControllerKey: 100,
  2249  											Key:           1003,
  2250  										},
  2251  									},
  2252  								},
  2253  							},
  2254  						},
  2255  						ensureDiskControllerGenerateVirtualDisks(16, 1003)...,
  2256  					),
  2257  				),
  2258  				err: nil,
  2259  				expectedConfigSpec: &VirtualMachineConfigSpec{
  2260  					Version: vmx20,
  2261  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  2262  						&VirtualDeviceConfigSpec{
  2263  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2264  							Device: &VirtualDisk{
  2265  								VirtualDevice: VirtualDevice{
  2266  									ControllerKey: -1,
  2267  								},
  2268  							},
  2269  						},
  2270  						&VirtualDeviceConfigSpec{
  2271  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2272  							Device: &VirtualAHCIController{
  2273  								VirtualSATAController: VirtualSATAController{
  2274  									VirtualController: VirtualController{
  2275  										VirtualDevice: VirtualDevice{
  2276  											ControllerKey: 100,
  2277  											Key:           -1,
  2278  										},
  2279  										BusNumber: 0,
  2280  									},
  2281  								},
  2282  							},
  2283  						},
  2284  					},
  2285  				},
  2286  			},
  2287  
  2288  			{
  2289  				name: "attach disk to new NVME controller when adding disk and existing devices includes PCI controller and there are already four SCSI and SATA controllers with no free slots",
  2290  				configSpec: &VirtualMachineConfigSpec{
  2291  					Version: vmx20,
  2292  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  2293  						&VirtualDeviceConfigSpec{
  2294  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2295  							Device:    &VirtualDisk{},
  2296  						},
  2297  					},
  2298  				},
  2299  				existingDevices: ensureDiskControllerJoinSlices(
  2300  					[]BaseVirtualDevice{
  2301  						&VirtualPCIController{
  2302  							VirtualController: VirtualController{
  2303  								VirtualDevice: VirtualDevice{
  2304  									Key: 100,
  2305  								},
  2306  							},
  2307  						},
  2308  					},
  2309  
  2310  					//
  2311  					// SCSI HBA 1 / 16 disks
  2312  					//
  2313  					append(
  2314  						[]BaseVirtualDevice{
  2315  							&ParaVirtualSCSIController{
  2316  								VirtualSCSIController: VirtualSCSIController{
  2317  									VirtualController: VirtualController{
  2318  										VirtualDevice: VirtualDevice{
  2319  											ControllerKey: 100,
  2320  											Key:           1000,
  2321  										},
  2322  									},
  2323  								},
  2324  							},
  2325  						},
  2326  						ensureDiskControllerGenerateVirtualDisks(16, 1000)...,
  2327  					),
  2328  					//
  2329  					// SCSI HBA 2 / 16 disks
  2330  					//
  2331  					append(
  2332  						[]BaseVirtualDevice{
  2333  							&VirtualLsiLogicController{
  2334  								VirtualSCSIController: VirtualSCSIController{
  2335  									VirtualController: VirtualController{
  2336  										VirtualDevice: VirtualDevice{
  2337  											ControllerKey: 100,
  2338  											Key:           1001,
  2339  										},
  2340  									},
  2341  								},
  2342  							},
  2343  						},
  2344  						ensureDiskControllerGenerateVirtualDisks(16, 1001)...,
  2345  					),
  2346  					//
  2347  					// SCSI HBA 3 / 16 disks
  2348  					//
  2349  					append(
  2350  						[]BaseVirtualDevice{
  2351  							&VirtualSCSIController{
  2352  								VirtualController: VirtualController{
  2353  									VirtualDevice: VirtualDevice{
  2354  										ControllerKey: 100,
  2355  										Key:           1002,
  2356  									},
  2357  								},
  2358  							},
  2359  						},
  2360  						ensureDiskControllerGenerateVirtualDisks(16, 1002)...,
  2361  					),
  2362  					//
  2363  					// SCSI HBA 4 / 16 disks
  2364  					//
  2365  					append(
  2366  						[]BaseVirtualDevice{
  2367  							&VirtualLsiLogicSASController{
  2368  								VirtualSCSIController: VirtualSCSIController{
  2369  									VirtualController: VirtualController{
  2370  										VirtualDevice: VirtualDevice{
  2371  											ControllerKey: 100,
  2372  											Key:           1003,
  2373  										},
  2374  									},
  2375  								},
  2376  							},
  2377  						},
  2378  						ensureDiskControllerGenerateVirtualDisks(16, 1003)...,
  2379  					),
  2380  
  2381  					//
  2382  					// SATA HBA 1 / 30 disks
  2383  					//
  2384  					append(
  2385  						[]BaseVirtualDevice{
  2386  							&VirtualAHCIController{
  2387  								VirtualSATAController: VirtualSATAController{
  2388  									VirtualController: VirtualController{
  2389  										VirtualDevice: VirtualDevice{
  2390  											ControllerKey: 100,
  2391  											Key:           15000,
  2392  										},
  2393  									},
  2394  								},
  2395  							},
  2396  						},
  2397  						ensureDiskControllerGenerateVirtualDisks(30, 15000)...,
  2398  					),
  2399  					//
  2400  					// SATA HBA 2 / 30 disks
  2401  					//
  2402  					append(
  2403  						[]BaseVirtualDevice{
  2404  							&VirtualAHCIController{
  2405  								VirtualSATAController: VirtualSATAController{
  2406  									VirtualController: VirtualController{
  2407  										VirtualDevice: VirtualDevice{
  2408  											ControllerKey: 100,
  2409  											Key:           15001,
  2410  										},
  2411  									},
  2412  								},
  2413  							},
  2414  						},
  2415  						ensureDiskControllerGenerateVirtualDisks(30, 15001)...,
  2416  					),
  2417  					//
  2418  					// SATA HBA 3 / 30 disks
  2419  					//
  2420  					append(
  2421  						[]BaseVirtualDevice{
  2422  							&VirtualAHCIController{
  2423  								VirtualSATAController: VirtualSATAController{
  2424  									VirtualController: VirtualController{
  2425  										VirtualDevice: VirtualDevice{
  2426  											ControllerKey: 100,
  2427  											Key:           15002,
  2428  										},
  2429  									},
  2430  								},
  2431  							},
  2432  						},
  2433  						ensureDiskControllerGenerateVirtualDisks(30, 15002)...,
  2434  					),
  2435  					//
  2436  					// SATA HBA 4 / 30 disks
  2437  					//
  2438  					append(
  2439  						[]BaseVirtualDevice{
  2440  							&VirtualAHCIController{
  2441  								VirtualSATAController: VirtualSATAController{
  2442  									VirtualController: VirtualController{
  2443  										VirtualDevice: VirtualDevice{
  2444  											ControllerKey: 100,
  2445  											Key:           15003,
  2446  										},
  2447  									},
  2448  								},
  2449  							},
  2450  						},
  2451  						ensureDiskControllerGenerateVirtualDisks(30, 15003)...,
  2452  					),
  2453  				),
  2454  				err: nil,
  2455  				expectedConfigSpec: &VirtualMachineConfigSpec{
  2456  					Version: vmx20,
  2457  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  2458  						&VirtualDeviceConfigSpec{
  2459  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2460  							Device: &VirtualDisk{
  2461  								VirtualDevice: VirtualDevice{
  2462  									ControllerKey: -1,
  2463  								},
  2464  							},
  2465  						},
  2466  						&VirtualDeviceConfigSpec{
  2467  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2468  							Device: &VirtualNVMEController{
  2469  								VirtualController: VirtualController{
  2470  									VirtualDevice: VirtualDevice{
  2471  										ControllerKey: 100,
  2472  										Key:           -1,
  2473  									},
  2474  									BusNumber: 0,
  2475  								},
  2476  								SharedBus: string(VirtualNVMEControllerSharingNoSharing),
  2477  							},
  2478  						},
  2479  					},
  2480  				},
  2481  			},
  2482  			{
  2483  				name: "return an error that there are no available controllers when adding a disk and existing devices includes PCI controller and there are already four SCSI, SATA, and NVME controllers with no free slots",
  2484  				configSpec: &VirtualMachineConfigSpec{
  2485  					Version: vmx20,
  2486  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  2487  						&VirtualDeviceConfigSpec{
  2488  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2489  							Device:    &VirtualDisk{},
  2490  						},
  2491  					},
  2492  				},
  2493  				existingDevices: ensureDiskControllerJoinSlices(
  2494  					[]BaseVirtualDevice{
  2495  						&VirtualPCIController{
  2496  							VirtualController: VirtualController{
  2497  								VirtualDevice: VirtualDevice{
  2498  									Key: 100,
  2499  								},
  2500  							},
  2501  						},
  2502  					},
  2503  
  2504  					//
  2505  					// SCSI HBA 1 / 16 disks
  2506  					//
  2507  					append(
  2508  						[]BaseVirtualDevice{
  2509  							&ParaVirtualSCSIController{
  2510  								VirtualSCSIController: VirtualSCSIController{
  2511  									VirtualController: VirtualController{
  2512  										VirtualDevice: VirtualDevice{
  2513  											ControllerKey: 100,
  2514  											Key:           1000,
  2515  										},
  2516  									},
  2517  								},
  2518  							},
  2519  						},
  2520  						ensureDiskControllerGenerateVirtualDisks(16, 1000)...,
  2521  					),
  2522  					//
  2523  					// SCSI HBA 2 / 16 disks
  2524  					//
  2525  					append(
  2526  						[]BaseVirtualDevice{
  2527  							&VirtualLsiLogicController{
  2528  								VirtualSCSIController: VirtualSCSIController{
  2529  									VirtualController: VirtualController{
  2530  										VirtualDevice: VirtualDevice{
  2531  											ControllerKey: 100,
  2532  											Key:           1001,
  2533  										},
  2534  									},
  2535  								},
  2536  							},
  2537  						},
  2538  						ensureDiskControllerGenerateVirtualDisks(16, 1001)...,
  2539  					),
  2540  					//
  2541  					// SCSI HBA 3 / 16 disks
  2542  					//
  2543  					append(
  2544  						[]BaseVirtualDevice{
  2545  							&VirtualSCSIController{
  2546  								VirtualController: VirtualController{
  2547  									VirtualDevice: VirtualDevice{
  2548  										ControllerKey: 100,
  2549  										Key:           1002,
  2550  									},
  2551  								},
  2552  							},
  2553  						},
  2554  						ensureDiskControllerGenerateVirtualDisks(16, 1002)...,
  2555  					),
  2556  					//
  2557  					// SCSI HBA 4 / 16 disks
  2558  					//
  2559  					append(
  2560  						[]BaseVirtualDevice{
  2561  							&VirtualLsiLogicSASController{
  2562  								VirtualSCSIController: VirtualSCSIController{
  2563  									VirtualController: VirtualController{
  2564  										VirtualDevice: VirtualDevice{
  2565  											ControllerKey: 100,
  2566  											Key:           1003,
  2567  										},
  2568  									},
  2569  								},
  2570  							},
  2571  						},
  2572  						ensureDiskControllerGenerateVirtualDisks(16, 1003)...,
  2573  					),
  2574  
  2575  					//
  2576  					// SATA HBA 1 / 30 disks
  2577  					//
  2578  					append(
  2579  						[]BaseVirtualDevice{
  2580  							&VirtualAHCIController{
  2581  								VirtualSATAController: VirtualSATAController{
  2582  									VirtualController: VirtualController{
  2583  										VirtualDevice: VirtualDevice{
  2584  											ControllerKey: 100,
  2585  											Key:           15000,
  2586  										},
  2587  									},
  2588  								},
  2589  							},
  2590  						},
  2591  						ensureDiskControllerGenerateVirtualDisks(30, 15000)...,
  2592  					),
  2593  					//
  2594  					// SATA HBA 2 / 30 disks
  2595  					//
  2596  					append(
  2597  						[]BaseVirtualDevice{
  2598  							&VirtualAHCIController{
  2599  								VirtualSATAController: VirtualSATAController{
  2600  									VirtualController: VirtualController{
  2601  										VirtualDevice: VirtualDevice{
  2602  											ControllerKey: 100,
  2603  											Key:           15001,
  2604  										},
  2605  									},
  2606  								},
  2607  							},
  2608  						},
  2609  						ensureDiskControllerGenerateVirtualDisks(30, 15001)...,
  2610  					),
  2611  					//
  2612  					// SATA HBA 3 / 30 disks
  2613  					//
  2614  					append(
  2615  						[]BaseVirtualDevice{
  2616  							&VirtualSATAController{
  2617  								VirtualController: VirtualController{
  2618  									VirtualDevice: VirtualDevice{
  2619  										ControllerKey: 100,
  2620  										Key:           15002,
  2621  									},
  2622  								},
  2623  							},
  2624  						},
  2625  						ensureDiskControllerGenerateVirtualDisks(30, 15002)...,
  2626  					),
  2627  					//
  2628  					// SATA HBA 4 / 30 disks
  2629  					//
  2630  					append(
  2631  						[]BaseVirtualDevice{
  2632  							&VirtualAHCIController{
  2633  								VirtualSATAController: VirtualSATAController{
  2634  									VirtualController: VirtualController{
  2635  										VirtualDevice: VirtualDevice{
  2636  											ControllerKey: 100,
  2637  											Key:           15003,
  2638  										},
  2639  									},
  2640  								},
  2641  							},
  2642  						},
  2643  						ensureDiskControllerGenerateVirtualDisks(30, 15003)...,
  2644  					),
  2645  
  2646  					//
  2647  					// NVME HBA 1 / 15 disks
  2648  					//
  2649  					append(
  2650  						[]BaseVirtualDevice{
  2651  							&VirtualNVMEController{
  2652  								VirtualController: VirtualController{
  2653  									VirtualDevice: VirtualDevice{
  2654  										ControllerKey: 100,
  2655  										Key:           31000,
  2656  									},
  2657  								},
  2658  							},
  2659  						},
  2660  						ensureDiskControllerGenerateVirtualDisks(15, 31000)...,
  2661  					),
  2662  					//
  2663  					// NVME HBA 2 / 15 disks
  2664  					//
  2665  					append(
  2666  						[]BaseVirtualDevice{
  2667  							&VirtualNVMEController{
  2668  								VirtualController: VirtualController{
  2669  									VirtualDevice: VirtualDevice{
  2670  										ControllerKey: 100,
  2671  										Key:           31001,
  2672  									},
  2673  								},
  2674  							},
  2675  						},
  2676  						ensureDiskControllerGenerateVirtualDisks(15, 31001)...,
  2677  					),
  2678  					//
  2679  					// NVME HBA 3 / 15 disks
  2680  					//
  2681  					append(
  2682  						[]BaseVirtualDevice{
  2683  							&VirtualNVMEController{
  2684  								VirtualController: VirtualController{
  2685  									VirtualDevice: VirtualDevice{
  2686  										ControllerKey: 100,
  2687  										Key:           31002,
  2688  									},
  2689  								},
  2690  							},
  2691  						},
  2692  						ensureDiskControllerGenerateVirtualDisks(15, 31002)...,
  2693  					),
  2694  					//
  2695  					// NVME HBA 4 / 15 disks
  2696  					//
  2697  					append(
  2698  						[]BaseVirtualDevice{
  2699  							&VirtualNVMEController{
  2700  								VirtualController: VirtualController{
  2701  									VirtualDevice: VirtualDevice{
  2702  										ControllerKey: 100,
  2703  										Key:           31003,
  2704  									},
  2705  								},
  2706  							},
  2707  						},
  2708  						ensureDiskControllerGenerateVirtualDisks(15, 31003)...,
  2709  					),
  2710  				),
  2711  				err: fmt.Errorf("no controllers available"),
  2712  				expectedConfigSpec: &VirtualMachineConfigSpec{
  2713  					Version: vmx20,
  2714  					DeviceChange: []BaseVirtualDeviceConfigSpec{
  2715  						&VirtualDeviceConfigSpec{
  2716  							Operation: VirtualDeviceConfigSpecOperationAdd,
  2717  							Device:    &VirtualDisk{},
  2718  						},
  2719  					},
  2720  				},
  2721  			},
  2722  		}
  2723  
  2724  		for i := range testCases {
  2725  			tc := testCases[i]
  2726  			t.Run(tc.name, func(t *testing.T) {
  2727  				if tc.panicMsg != "" {
  2728  					assert.PanicsWithValue(t, tc.panicMsg, func() { _ = tc.configSpec.EnsureDisksHaveControllers(tc.existingDevices...) })
  2729  				} else {
  2730  					var err error
  2731  					assert.NotPanics(t, func() { err = tc.configSpec.EnsureDisksHaveControllers(tc.existingDevices...) })
  2732  					assert.Equal(t, tc.err, err)
  2733  					assert.Equal(t, tc.expectedConfigSpec, tc.configSpec)
  2734  				}
  2735  			})
  2736  		}
  2737  	})
  2738  }
  2739  
  2740  type nilVirtualDeviceConfigSpec struct{}
  2741  
  2742  func (n nilVirtualDeviceConfigSpec) GetVirtualDeviceConfigSpec() *VirtualDeviceConfigSpec {
  2743  	return nil
  2744  }
  2745  
  2746  type nilVirtualDevice struct{}
  2747  
  2748  func (n nilVirtualDevice) GetVirtualDevice() *VirtualDevice {
  2749  	return nil
  2750  }
  2751  
  2752  func ensureDiskControllerJoinSlices[T any](a []T, b ...[]T) []T {
  2753  	for i := range b {
  2754  		a = append(a, b[i]...)
  2755  	}
  2756  	return a
  2757  }
  2758  
  2759  func ensureDiskControllerGenerateVirtualDisks(
  2760  	numDisks int, controllerKey int32) []BaseVirtualDevice {
  2761  
  2762  	devices := make([]BaseVirtualDevice, numDisks)
  2763  	for i := range devices {
  2764  		devices[i] = &VirtualDisk{
  2765  			VirtualDevice: VirtualDevice{
  2766  				ControllerKey: controllerKey,
  2767  			},
  2768  		}
  2769  	}
  2770  	return devices
  2771  }