Skip to content

Commit 2c30cb1

Browse files
committed
Added multi disk support tests
1 parent 4af6c63 commit 2c30cb1

File tree

6 files changed

+319
-17
lines changed

6 files changed

+319
-17
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ generate-e2e-templates-main: $(KUSTOMIZE) ## Generate test templates for the mai
374374
cp "$(RELEASE_DIR)/main/cluster-template-ignition.yaml" "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/base/cluster-template-ignition.yaml"
375375
"$(KUSTOMIZE)" --load-restrictor LoadRestrictionsNone build "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/base" > "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/cluster-template.yaml"
376376
"$(KUSTOMIZE)" --load-restrictor LoadRestrictionsNone build "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/hw-upgrade" > "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/cluster-template-hw-upgrade.yaml"
377+
"$(KUSTOMIZE)" --load-restrictor LoadRestrictionsNone build "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/multi-disk" > "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/cluster-template-multi-disk.yaml"
377378
"$(KUSTOMIZE)" --load-restrictor LoadRestrictionsNone build "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/storage-policy" > "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/cluster-template-storage-policy.yaml"
378379
"$(KUSTOMIZE)" --load-restrictor LoadRestrictionsNone build "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/conformance" > "$(E2E_GOVMOMI_TEMPLATE_DIR)/main/cluster-template-conformance.yaml"
379380
# Since CAPI uses different flavor names for KCP and MD remediation using MHC

pkg/services/govmomi/vcenter/clone_test.go

Lines changed: 186 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package vcenter
1919
import (
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+
143312
func validateDiskSpec(t *testing.T, device types.BaseVirtualDeviceConfigSpec, cloneDiskSize int32) {
144313
t.Helper()
145314
disk := device.GetVirtualDeviceConfigSpec().Device.(*types.VirtualDisk)

test/e2e/config/vsphere.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ providers:
173173
- sourcePath: "../../../test/e2e/data/infrastructure-vsphere-govmomi/main/cluster-template-ipam.yaml"
174174
- sourcePath: "../../../test/e2e/data/infrastructure-vsphere-govmomi/main/cluster-template-kcp-remediation.yaml"
175175
- sourcePath: "../../../test/e2e/data/infrastructure-vsphere-govmomi/main/cluster-template-md-remediation.yaml"
176+
- sourcePath: "../../../test/e2e/data/infrastructure-vsphere-govmomi/main/cluster-template-multi-disk.yaml"
176177
- sourcePath: "../../../test/e2e/data/infrastructure-vsphere-govmomi/main/cluster-template-node-drain.yaml"
177178
- sourcePath: "../../../test/e2e/data/infrastructure-vsphere-govmomi/main/cluster-template-ownerrefs-finalizers.yaml"
178179
- sourcePath: "../../../test/e2e/data/infrastructure-vsphere-govmomi/main/cluster-template-pci.yaml"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
2+
kind: VSphereMachineTemplate
3+
metadata:
4+
name: '${CLUSTER_NAME}'
5+
namespace: '${NAMESPACE}'
6+
spec:
7+
template:
8+
spec:
9+
dataDisks:
10+
- name: "disk_1"
11+
sizeGiB: 10
12+
- name: "disk_2"
13+
sizeGiB: 20
14+
---
15+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
16+
kind: VSphereMachineTemplate
17+
metadata:
18+
name: '${CLUSTER_NAME}-worker'
19+
namespace: '${NAMESPACE}'
20+
spec:
21+
template:
22+
spec:
23+
dataDisks:
24+
- name: "disk_1"
25+
sizeGiB: 20
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: kustomize.config.k8s.io/v1beta1
2+
kind: Kustomization
3+
resources:
4+
- ../base
5+
patchesStrategicMerge:
6+
- data-disks-patch.yaml

0 commit comments

Comments
 (0)