@@ -19,6 +19,7 @@ package vcenter
1919import (
2020 ctx "context"
2121 "crypto/tls"
22+ "fmt"
2223 "testing"
2324
2425 "github.com/vmware/govmomi/object"
@@ -60,25 +61,30 @@ func TestGetDiskSpec(t *testing.T) {
6061 additionalCloneDiskSizes []int32
6162 name string
6263 disks object.VirtualDeviceList
64+ dataDisks []infrav1.VSphereDisk
65+ expectedDiskCount int
6366 err string
6467 }{
6568 {
66- name : "Successfully clone template with correct disk requirements" ,
67- disks : defaultDisks ,
68- cloneDiskSize : defaultSizeGiB ,
69- expectDevice : true ,
69+ name : "Successfully clone template with correct disk requirements" ,
70+ disks : defaultDisks ,
71+ cloneDiskSize : defaultSizeGiB ,
72+ expectDevice : true ,
73+ expectedDiskCount : 1 ,
7074 },
7175 {
72- name : "Successfully clone template and increase disk requirements" ,
73- disks : defaultDisks ,
74- cloneDiskSize : defaultSizeGiB + 1 ,
75- expectDevice : true ,
76+ name : "Successfully clone template and increase disk requirements" ,
77+ disks : defaultDisks ,
78+ cloneDiskSize : defaultSizeGiB + 1 ,
79+ expectDevice : true ,
80+ expectedDiskCount : 1 ,
7681 },
7782 {
78- name : "Successfully clone template with no explicit disk requirements" ,
79- disks : defaultDisks ,
80- cloneDiskSize : 0 ,
81- expectDevice : true ,
83+ name : "Successfully clone template with no explicit disk requirements" ,
84+ disks : defaultDisks ,
85+ cloneDiskSize : 0 ,
86+ expectDevice : true ,
87+ expectedDiskCount : 1 ,
8288 },
8389 {
8490 name : "Fail to clone template with lower disk requirements then on template" ,
@@ -98,6 +104,7 @@ func TestGetDiskSpec(t *testing.T) {
98104 cloneDiskSize : defaultSizeGiB + 1 ,
99105 additionalCloneDiskSizes : []int32 {defaultSizeGiB + 1 },
100106 expectDevice : true ,
107+ expectedDiskCount : 2 ,
101108 },
102109 {
103110 name : "Fails to clone template and decrease second disk size" ,
@@ -121,25 +128,187 @@ func TestGetDiskSpec(t *testing.T) {
121128 },
122129 }
123130 vmContext := & capvcontext.VMContext {VSphereVM : vsphereVM }
124- devices , err := getDiskSpec (vmContext , tc .disks )
131+ deviceResults , err := getDiskSpec (vmContext , tc .disks )
125132 if (tc .err != "" && err == nil ) || (tc .err == "" && err != nil ) || (err != nil && tc .err != err .Error ()) {
126133 t .Fatalf ("Expected to get '%v' error from getDiskSpec, got: '%v'" , tc .err , err )
127134 }
128- if deviceFound := len (devices ) != 0 ; tc .expectDevice != deviceFound {
129- t .Fatalf ("Expected to get a device: %v, but got: '%#v'" , tc .expectDevice , devices )
135+ if deviceFound := len (deviceResults ) != 0 ; tc .expectDevice != deviceFound {
136+ t .Fatalf ("Expected to get a device: %v, but got: '%#v'" , tc .expectDevice , deviceResults )
130137 }
131138 if tc .expectDevice {
132- primaryDevice := devices [0 ]
139+ primaryDevice := deviceResults [0 ]
133140 validateDiskSpec (t , primaryDevice , tc .cloneDiskSize )
134141 if len (tc .additionalCloneDiskSizes ) != 0 {
135- secondaryDevice := devices [1 ]
142+ secondaryDevice := deviceResults [1 ]
136143 validateDiskSpec (t , secondaryDevice , tc .additionalCloneDiskSizes [0 ])
137144 }
145+
146+ // Check number of disks present
147+ if len (deviceResults ) != tc .expectedDiskCount {
148+ t .Fatalf ("Expected device count to be %v, but found %v" , tc .expectedDiskCount , len (deviceResults ))
149+ }
138150 }
139151 })
140152 }
141153}
142154
155+ func TestCreateDataDisks (t * testing.T ) {
156+ model , session , server := initSimulator (t )
157+ t .Cleanup (model .Remove )
158+ t .Cleanup (server .Close )
159+ vm := simulator .Map .Any ("VirtualMachine" ).(* simulator.VirtualMachine )
160+ machine := object .NewVirtualMachine (session .Client .Client , vm .Reference ())
161+
162+ deviceList , err := machine .Device (ctx .TODO ())
163+ if err != nil {
164+ t .Fatalf ("Failed to obtain vm devices: %v" , err )
165+ }
166+
167+ // Find primary disk and get controller
168+ disks := deviceList .SelectByType ((* types .VirtualDisk )(nil ))
169+ primaryDisk := disks [0 ].(* types.VirtualDisk )
170+ controller , ok := deviceList .FindByKey (primaryDisk .ControllerKey ).(types.BaseVirtualController )
171+ if ! ok {
172+ t .Fatalf ("unable to get controller for test" )
173+ }
174+
175+ testCases := []struct {
176+ name string
177+ devices object.VirtualDeviceList
178+ controller types.BaseVirtualController
179+ dataDisks []infrav1.VSphereDisk
180+ expectedUnitNumber []int
181+ err string
182+ }{
183+ {
184+ name : "Add data disk with 1 ova disk" ,
185+ devices : deviceList ,
186+ controller : controller ,
187+ dataDisks : createDataDiskDefinitions (1 ),
188+ expectedUnitNumber : []int {1 },
189+ },
190+ {
191+ name : "Add data disk with 2 ova disk" ,
192+ devices : createAdditionalDisks (deviceList , controller , 1 ),
193+ controller : controller ,
194+ dataDisks : createDataDiskDefinitions (1 ),
195+ expectedUnitNumber : []int {2 },
196+ },
197+ {
198+ name : "Add multiple data disk with 1 ova disk" ,
199+ devices : deviceList ,
200+ controller : controller ,
201+ dataDisks : createDataDiskDefinitions (2 ),
202+ expectedUnitNumber : []int {1 , 2 },
203+ },
204+ {
205+ name : "Add too many data disks with 1 ova disk" ,
206+ devices : deviceList ,
207+ controller : controller ,
208+ dataDisks : createDataDiskDefinitions (30 ),
209+ err : "all unit numbers are already in-use" ,
210+ },
211+ {
212+ name : "Add data disk with no ova disk" ,
213+ devices : nil ,
214+ controller : nil ,
215+ dataDisks : createDataDiskDefinitions (1 ),
216+ err : "Invalid disk count: 0" ,
217+ },
218+ {
219+ name : "Add too many data disks with 1 ova disk" ,
220+ devices : deviceList ,
221+ controller : controller ,
222+ dataDisks : createDataDiskDefinitions (40 ),
223+ err : "all unit numbers are already in-use" ,
224+ },
225+ }
226+
227+ for _ , test := range testCases {
228+ tc := test
229+ t .Run (tc .name , func (t * testing.T ) {
230+ var funcError error
231+
232+ // Create the data disks
233+ newDisks , funcError := createDataDisks (ctx .TODO (), tc .dataDisks , tc .devices )
234+ if (tc .err != "" && funcError == nil ) || (tc .err == "" && funcError != nil ) || (funcError != nil && tc .err != funcError .Error ()) {
235+ t .Fatalf ("Expected to get '%v' error from assignUnitNumber, got: '%v'" , tc .err , funcError )
236+ }
237+
238+ if tc .err == "" && funcError == nil {
239+ // Check number of disks present
240+ if len (newDisks ) != len (tc .dataDisks ) {
241+ t .Fatalf ("Expected device count to be %v, but found %v" , len (tc .dataDisks ), len (newDisks ))
242+ }
243+
244+ // Validate the configs of new data disks
245+ for index , disk := range newDisks {
246+ // Check disk size matches original request
247+ vd := disk .GetVirtualDeviceConfigSpec ().Device .(* types.VirtualDisk )
248+ expectedSize := int64 (tc .dataDisks [index ].SizeGiB * 1024 * 1024 )
249+ if vd .CapacityInKB != expectedSize {
250+ t .Fatalf ("Expected disk size (KB) %d to match %d" , vd .CapacityInKB , expectedSize )
251+ }
252+
253+ // Check unit number
254+ unitNumber := * disk .GetVirtualDeviceConfigSpec ().Device .GetVirtualDevice ().UnitNumber
255+ if tc .err == "" && unitNumber != int32 (tc .expectedUnitNumber [index ]) {
256+ t .Fatalf ("Expected to get unitNumber '%d' error from assignUnitNumber, got: '%d'" , tc .expectedUnitNumber [index ], unitNumber )
257+ }
258+ }
259+ }
260+ })
261+ }
262+ }
263+
264+ func createAdditionalDisks (devices object.VirtualDeviceList , controller types.BaseVirtualController , numOfDisks int ) object.VirtualDeviceList {
265+ deviceList := devices
266+ disks := devices .SelectByType ((* types .VirtualDisk )(nil ))
267+ primaryDisk := disks [0 ].(* types.VirtualDisk )
268+
269+ for i := 0 ; i < numOfDisks ; i ++ {
270+ newDevice := createVirtualDisk (primaryDisk .ControllerKey + 1 , controller , 10 )
271+ newUnitNumber := * primaryDisk .UnitNumber + int32 (i + 1 )
272+ newDevice .UnitNumber = & newUnitNumber
273+ deviceList = append (deviceList , newDevice )
274+ }
275+ return deviceList
276+ }
277+
278+ func createVirtualDisk (key int32 , controller types.BaseVirtualController , diskSize int32 ) * types.VirtualDisk {
279+ dev := & types.VirtualDisk {
280+ VirtualDevice : types.VirtualDevice {
281+ Key : key ,
282+ Backing : & types.VirtualDiskFlatVer2BackingInfo {
283+ DiskMode : string (types .VirtualDiskModePersistent ),
284+ ThinProvisioned : types .NewBool (true ),
285+ VirtualDeviceFileBackingInfo : types.VirtualDeviceFileBackingInfo {
286+ FileName : "" ,
287+ },
288+ },
289+ },
290+ CapacityInKB : int64 (diskSize ) * 1024 * 1024 ,
291+ }
292+
293+ if controller != nil {
294+ dev .VirtualDevice .ControllerKey = controller .GetVirtualController ().Key
295+ }
296+ return dev
297+ }
298+
299+ func createDataDiskDefinitions (numOfDataDisks int ) []infrav1.VSphereDisk {
300+ disks := []infrav1.VSphereDisk {}
301+
302+ for i := 0 ; i < numOfDataDisks ; i ++ {
303+ disk := infrav1.VSphereDisk {
304+ Name : fmt .Sprintf ("disk_%d" , i ),
305+ SizeGiB : 10 * int32 (i ),
306+ }
307+ disks = append (disks , disk )
308+ }
309+ return disks
310+ }
311+
143312func validateDiskSpec (t * testing.T , device types.BaseVirtualDeviceConfigSpec , cloneDiskSize int32 ) {
144313 t .Helper ()
145314 disk := device .GetVirtualDeviceConfigSpec ().Device .(* types.VirtualDisk )
0 commit comments