@@ -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" ,
@@ -114,32 +121,268 @@ func TestGetDiskSpec(t *testing.T) {
114121 cloneSpec := infrav1.VirtualMachineCloneSpec {
115122 DiskGiB : tc .cloneDiskSize ,
116123 AdditionalDisksGiB : tc .additionalCloneDiskSizes ,
124+ DataDisks : tc .dataDisks ,
117125 }
118126 vsphereVM := & infrav1.VSphereVM {
119127 Spec : infrav1.VSphereVMSpec {
120128 VirtualMachineCloneSpec : cloneSpec ,
121129 },
122130 }
123131 vmContext := & capvcontext.VMContext {VSphereVM : vsphereVM }
124- devices , err := getDiskSpec (vmContext , tc .disks )
132+ deviceResults , err := getDiskSpec (vmContext , tc .disks )
125133 if (tc .err != "" && err == nil ) || (tc .err == "" && err != nil ) || (err != nil && tc .err != err .Error ()) {
126134 t .Fatalf ("Expected to get '%v' error from getDiskSpec, got: '%v'" , tc .err , err )
127135 }
128- if deviceFound := len (devices ) != 0 ; tc .expectDevice != deviceFound {
129- t .Fatalf ("Expected to get a device: %v, but got: '%#v'" , tc .expectDevice , devices )
136+ if deviceFound := len (deviceResults ) != 0 ; tc .expectDevice != deviceFound {
137+ t .Fatalf ("Expected to get a device: %v, but got: '%#v'" , tc .expectDevice , deviceResults )
130138 }
131139 if tc .expectDevice {
132- primaryDevice := devices [0 ]
140+ primaryDevice := deviceResults [0 ]
133141 validateDiskSpec (t , primaryDevice , tc .cloneDiskSize )
134142 if len (tc .additionalCloneDiskSizes ) != 0 {
135- secondaryDevice := devices [1 ]
143+ secondaryDevice := deviceResults [1 ]
136144 validateDiskSpec (t , secondaryDevice , tc .additionalCloneDiskSizes [0 ])
137145 }
146+
147+ // Check number of disks present
148+ if len (deviceResults ) != tc .expectedDiskCount {
149+ t .Fatalf ("Expected device count to be %v, but found %v" , tc .expectedDiskCount , len (deviceResults ))
150+ }
151+ }
152+ })
153+ }
154+ }
155+
156+ func TestCreateDiskSpec (t * testing.T ) {
157+ model , session , server := initSimulator (t )
158+ t .Cleanup (model .Remove )
159+ t .Cleanup (server .Close )
160+ vm := simulator .Map .Any ("VirtualMachine" ).(* simulator.VirtualMachine )
161+ machine := object .NewVirtualMachine (session .Client .Client , vm .Reference ())
162+
163+ devices , err := machine .Device (ctx .TODO ())
164+ if err != nil {
165+ t .Fatalf ("Failed to obtain vm devices: %v" , err )
166+ }
167+ defaultDisks := devices .SelectByType ((* types .VirtualDisk )(nil ))
168+ if len (defaultDisks ) < 1 {
169+ t .Fatal ("Unable to find attached disk for data disk testing" )
170+ }
171+
172+ testCases := []struct {
173+ expectDevice bool
174+ cloneDiskSize int32
175+ additionalCloneDiskSizes []int32
176+ name string
177+ disks object.VirtualDeviceList
178+ dataDisks []infrav1.VSphereDisk
179+ expectedDiskCount int
180+ err string
181+ }{
182+ {
183+ name : "Successfully add data disk" ,
184+ disks : devices ,
185+ dataDisks : []infrav1.VSphereDisk {
186+ {
187+ SizeGiB : 10 ,
188+ },
189+ },
190+ expectDevice : true ,
191+ },
192+ {
193+ name : "Successfully add multiple data disks" ,
194+ disks : devices ,
195+ dataDisks : []infrav1.VSphereDisk {
196+ {
197+ SizeGiB : 10 ,
198+ },
199+ {
200+ SizeGiB : 20 ,
201+ },
202+ },
203+ expectDevice : true ,
204+ },
205+ {
206+ name : "Successfully add multiple data disks when template has multiple disks" ,
207+ disks : append (devices , defaultDisks ... ),
208+ dataDisks : []infrav1.VSphereDisk {
209+ {
210+ SizeGiB : 10 ,
211+ },
212+ {
213+ SizeGiB : 20 ,
214+ },
215+ },
216+ expectDevice : true ,
217+ },
218+ }
219+
220+ for _ , test := range testCases {
221+ tc := test
222+ t .Run (tc .name , func (t * testing.T ) {
223+ deviceResults , err := createDataDisks (ctx .TODO (), tc .dataDisks , tc .disks )
224+ if (tc .err != "" && err == nil ) || (tc .err == "" && err != nil ) || (err != nil && tc .err != err .Error ()) {
225+ t .Fatalf ("Expected to get '%v' error from createDataDisks, got: '%v'" , tc .err , err )
226+ }
227+ if deviceFound := len (deviceResults ) != 0 ; tc .expectDevice != deviceFound {
228+ t .Fatalf ("Expected to get a device: %v, but got: '%#v'" , tc .expectDevice , deviceResults )
229+ }
230+ if tc .expectDevice {
231+ // Check number of disks present
232+ if len (deviceResults ) != len (tc .dataDisks ) {
233+ t .Fatalf ("Expected device count to be %v, but found %v" , tc .expectedDiskCount , len (deviceResults ))
234+ }
235+ }
236+ })
237+ }
238+ }
239+
240+ func TestAddingDataDisks (t * testing.T ) {
241+ model , session , server := initSimulator (t )
242+ t .Cleanup (model .Remove )
243+ t .Cleanup (server .Close )
244+ vm := simulator .Map .Any ("VirtualMachine" ).(* simulator.VirtualMachine )
245+ machine := object .NewVirtualMachine (session .Client .Client , vm .Reference ())
246+
247+ deviceList , err := machine .Device (ctx .TODO ())
248+ if err != nil {
249+ t .Fatalf ("Failed to obtain vm devices: %v" , err )
250+ }
251+
252+ // Find primary disk and get controller
253+ disks := deviceList .SelectByType ((* types .VirtualDisk )(nil ))
254+ primaryDisk := disks [0 ].(* types.VirtualDisk )
255+ controller , ok := deviceList .FindByKey (primaryDisk .ControllerKey ).(types.BaseVirtualController )
256+ if ! ok {
257+ t .Fatalf ("unable to get controller for test" )
258+ }
259+
260+ testCases := []struct {
261+ name string
262+ devices object.VirtualDeviceList
263+ controller types.BaseVirtualController
264+ dataDisks []infrav1.VSphereDisk
265+ expectedUnitNumber []int
266+ err string
267+ }{
268+ {
269+ name : "Add data disk with 1 ova disk" ,
270+ devices : deviceList ,
271+ controller : controller ,
272+ dataDisks : createDataDiskDefinitions (1 ),
273+ expectedUnitNumber : []int {1 },
274+ },
275+ {
276+ name : "Add data disk with 2 ova disk" ,
277+ devices : createAdditionalDisks (deviceList , controller , 1 ),
278+ controller : controller ,
279+ dataDisks : createDataDiskDefinitions (1 ),
280+ expectedUnitNumber : []int {2 },
281+ },
282+ {
283+ name : "Add multiple data disk with 1 ova disk" ,
284+ devices : deviceList ,
285+ controller : controller ,
286+ dataDisks : createDataDiskDefinitions (2 ),
287+ expectedUnitNumber : []int {1 , 2 },
288+ },
289+ {
290+ name : "Add too many data disks with 1 ova disk" ,
291+ devices : deviceList ,
292+ controller : controller ,
293+ dataDisks : createDataDiskDefinitions (30 ),
294+ err : "all unit numbers are already in-use" ,
295+ },
296+ {
297+ name : "Add data disk with no ova disk" ,
298+ devices : nil ,
299+ controller : nil ,
300+ dataDisks : createDataDiskDefinitions (1 ),
301+ err : "Invalid disk count: 0" ,
302+ },
303+ {
304+ name : "Add too many data disks with 1 ova disk" ,
305+ devices : deviceList ,
306+ controller : controller ,
307+ dataDisks : createDataDiskDefinitions (40 ),
308+ err : "all unit numbers are already in-use" ,
309+ },
310+ }
311+
312+ for _ , test := range testCases {
313+ tc := test
314+ t .Run (tc .name , func (t * testing.T ) {
315+ var funcError error
316+
317+ // Create the data disks
318+ newDisks , funcError := createDataDisks (ctx .TODO (), tc .dataDisks , tc .devices )
319+ if (tc .err != "" && funcError == nil ) || (tc .err == "" && funcError != nil ) || (funcError != nil && tc .err != funcError .Error ()) {
320+ t .Fatalf ("Expected to get '%v' error from assignUnitNumber, got: '%v'" , tc .err , funcError )
321+ }
322+
323+ // Validate the configs of new data disks
324+ for index , disk := range newDisks {
325+ if funcError != nil {
326+ break
327+ }
328+
329+ unitNumber := * disk .GetVirtualDeviceConfigSpec ().Device .GetVirtualDevice ().UnitNumber
330+ if tc .err == "" && unitNumber != int32 (tc .expectedUnitNumber [index ]) {
331+ t .Fatalf ("Expected to get unitNumber '%d' error from assignUnitNumber, got: '%d'" , tc .expectedUnitNumber [index ], unitNumber )
332+ }
138333 }
139334 })
140335 }
141336}
142337
338+ func createAdditionalDisks (devices object.VirtualDeviceList , controller types.BaseVirtualController , numOfDisks int ) object.VirtualDeviceList {
339+ deviceList := devices
340+ disks := devices .SelectByType ((* types .VirtualDisk )(nil ))
341+ primaryDisk := disks [0 ].(* types.VirtualDisk )
342+
343+ for i := 0 ; i < numOfDisks ; i ++ {
344+ newDevice := createVirtualDisk (primaryDisk .ControllerKey + 1 , controller , 10 )
345+ newUnitNumber := * primaryDisk .UnitNumber + int32 (i + 1 )
346+ newDevice .UnitNumber = & newUnitNumber
347+ deviceList = append (deviceList , newDevice )
348+ }
349+ return deviceList
350+ }
351+
352+ func createVirtualDisk (key int32 , controller types.BaseVirtualController , diskSize int32 ) * types.VirtualDisk {
353+ dev := & types.VirtualDisk {
354+ VirtualDevice : types.VirtualDevice {
355+ Key : key ,
356+ Backing : & types.VirtualDiskFlatVer2BackingInfo {
357+ DiskMode : string (types .VirtualDiskModePersistent ),
358+ ThinProvisioned : types .NewBool (true ),
359+ VirtualDeviceFileBackingInfo : types.VirtualDeviceFileBackingInfo {
360+ FileName : "" ,
361+ },
362+ },
363+ },
364+ CapacityInKB : int64 (diskSize ) * 1024 * 1024 ,
365+ }
366+
367+ if controller != nil {
368+ dev .VirtualDevice .ControllerKey = controller .GetVirtualController ().Key
369+ }
370+ return dev
371+ }
372+
373+ func createDataDiskDefinitions (numOfDataDisks int ) []infrav1.VSphereDisk {
374+ disks := []infrav1.VSphereDisk {}
375+
376+ for i := 0 ; i < numOfDataDisks ; i ++ {
377+ disk := infrav1.VSphereDisk {
378+ Name : fmt .Sprintf ("disk_%d" , i ),
379+ SizeGiB : 10 * int32 (i ),
380+ }
381+ disks = append (disks , disk )
382+ }
383+ return disks
384+ }
385+
143386func validateDiskSpec (t * testing.T , device types.BaseVirtualDeviceConfigSpec , cloneDiskSize int32 ) {
144387 t .Helper ()
145388 disk := device .GetVirtualDeviceConfigSpec ().Device .(* types.VirtualDisk )
0 commit comments