github.com/vmware/govmomi@v0.43.0/vim25/types/configspec_test.go (about)

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