Skip to content

Commit 7906bf1

Browse files
committed
Fixed logic to handle vSphere image template w/ multiple disks
1 parent 8c5f0b5 commit 7906bf1

File tree

4 files changed

+90
-43
lines changed

4 files changed

+90
-43
lines changed

config/default/crd/bases/infrastructure.cluster.x-k8s.io_vspheremachines.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -995,12 +995,6 @@ spec:
995995
description: VSphereDisk describes additional disks for vSphere
996996
to be added to VM that are not part of the VM OVA template.
997997
properties:
998-
deviceName:
999-
description: |-
1000-
DeviceName is a name to be used to identify the disk definition. If deviceName is not specified,
1001-
the disk will still be created. The deviceName should be unique so that it can be used to clearly
1002-
identify purpose of the disk, but is not required to be unique.
1003-
type: string
1004998
sizeGiB:
1005999
description: SizeGiB is the size of the disk (in GiB).
10061000
format: int64

config/default/crd/bases/infrastructure.cluster.x-k8s.io_vspheremachinetemplates.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -865,12 +865,6 @@ spec:
865865
vSphere to be added to VM that are not part of the VM
866866
OVA template.
867867
properties:
868-
deviceName:
869-
description: |-
870-
DeviceName is a name to be used to identify the disk definition. If deviceName is not specified,
871-
the disk will still be created. The deviceName should be unique so that it can be used to clearly
872-
identify purpose of the disk, but is not required to be unique.
873-
type: string
874868
sizeGiB:
875869
description: SizeGiB is the size of the disk (in GiB).
876870
format: int64

config/default/crd/bases/infrastructure.cluster.x-k8s.io_vspherevms.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,12 +1088,6 @@ spec:
10881088
description: VSphereDisk describes additional disks for vSphere
10891089
to be added to VM that are not part of the VM OVA template.
10901090
properties:
1091-
deviceName:
1092-
description: |-
1093-
DeviceName is a name to be used to identify the disk definition. If deviceName is not specified,
1094-
the disk will still be created. The deviceName should be unique so that it can be used to clearly
1095-
identify purpose of the disk, but is not required to be unique.
1096-
type: string
10971091
sizeGiB:
10981092
description: SizeGiB is the size of the disk (in GiB).
10991093
format: int64

pkg/services/govmomi/vcenter/clone.go

Lines changed: 90 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -374,18 +374,50 @@ func getDiskSpec(vmCtx *capvcontext.VMContext, devices object.VirtualDeviceList)
374374

375375
// Now if we have increased the disk size of any additional disks that were in the template, we can now add new disks
376376
// that are present in the additionalDisks list.
377-
for i, dataDisk := range vmCtx.VSphereVM.Spec.DataDisks {
377+
if len(vmCtx.VSphereVM.Spec.DataDisks) > 0 {
378+
additionalDisks, diskErr := createAdditionalDisks(vmCtx.VSphereVM.Spec.DataDisks, primaryDisk, devices)
379+
if diskErr != nil {
380+
klog.Errorf("Unable to add additional disks: %v", diskErr)
381+
return nil, diskErr
382+
}
383+
diskSpecs = append(diskSpecs, additionalDisks...)
384+
}
385+
386+
return diskSpecs, nil
387+
}
388+
389+
func getDiskConfigSpec(disk *types.VirtualDisk, diskCloneCapacityKB int64) (types.BaseVirtualDeviceConfigSpec, error) {
390+
switch {
391+
case diskCloneCapacityKB == 0:
392+
// No disk size specified for the clone. Default to the template disk capacity.
393+
case diskCloneCapacityKB > 0 && diskCloneCapacityKB >= disk.CapacityInKB:
394+
disk.CapacityInKB = diskCloneCapacityKB
395+
case diskCloneCapacityKB > 0 && diskCloneCapacityKB < disk.CapacityInKB:
396+
return nil, errors.Errorf(
397+
"can't resize template disk down, initial capacity is larger: %dKiB > %dKiB",
398+
disk.CapacityInKB, diskCloneCapacityKB)
399+
}
400+
401+
return &types.VirtualDeviceConfigSpec{
402+
Operation: types.VirtualDeviceConfigSpecOperationEdit,
403+
Device: disk,
404+
}, nil
405+
}
406+
407+
func createAdditionalDisks(disks []infrav1.VSphereDisk, primaryDisk *types.VirtualDisk, devices object.VirtualDeviceList) ([]types.BaseVirtualDeviceConfigSpec, error) {
408+
additionalDisks := []types.BaseVirtualDeviceConfigSpec{}
409+
unit := int32(1)
410+
411+
for i, dataDisk := range disks {
378412
klog.InfoS("Adding disk", "spec", dataDisk)
379413

380-
// Need storage policy
381-
// Need scsi controller
382-
controller, err := devices.FindDiskController("scsi")
383-
if err != nil {
414+
// Get controller. Only supporting using same controller as primary disk at this time
415+
controller, ok := devices.FindByKey(primaryDisk.ControllerKey).(types.BaseVirtualController) // TODO: Do this
416+
if !ok {
384417
klog.Infof("Unable to get scsi controller")
418+
return nil, errors.Errorf("unable to find controller with key=%v", primaryDisk.ControllerKey)
385419
}
386420

387-
unit := int32(i + 1)
388-
389421
dev := &types.VirtualDisk{
390422
VirtualDevice: types.VirtualDevice{
391423
Key: devices.NewKey() - int32(i),
@@ -394,15 +426,17 @@ func getDiskSpec(vmCtx *capvcontext.VMContext, devices object.VirtualDeviceList)
394426
ThinProvisioned: types.NewBool(true),
395427
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
396428
FileName: "",
397-
//Datastore: types.NewReference(datastore.Reference()),
398429
},
399430
},
400-
UnitNumber: &unit,
401431
ControllerKey: controller.GetVirtualController().Key,
402432
},
403433
CapacityInKB: dataDisk.SizeGiB * 1024 * 1024,
404434
}
405435

436+
// Assign unit number to next slot on controller
437+
assignUnitNumber(dev, devices, additionalDisks, controller, unit)
438+
unit = *dev.UnitNumber
439+
406440
diskConfigSpec := types.VirtualDeviceConfigSpec{
407441
Device: dev,
408442
Operation: types.VirtualDeviceConfigSpecOperationAdd,
@@ -411,28 +445,59 @@ func getDiskSpec(vmCtx *capvcontext.VMContext, devices object.VirtualDeviceList)
411445

412446
klog.InfoS("Generated device", "dev", dev)
413447

414-
diskSpecs = append(diskSpecs, &diskConfigSpec)
448+
additionalDisks = append(additionalDisks, &diskConfigSpec)
415449
}
416450

417-
return diskSpecs, nil
451+
return additionalDisks, nil
418452
}
419453

420-
func getDiskConfigSpec(disk *types.VirtualDisk, diskCloneCapacityKB int64) (types.BaseVirtualDeviceConfigSpec, error) {
421-
switch {
422-
case diskCloneCapacityKB == 0:
423-
// No disk size specified for the clone. Default to the template disk capacity.
424-
case diskCloneCapacityKB > 0 && diskCloneCapacityKB >= disk.CapacityInKB:
425-
disk.CapacityInKB = diskCloneCapacityKB
426-
case diskCloneCapacityKB > 0 && diskCloneCapacityKB < disk.CapacityInKB:
427-
return nil, errors.Errorf(
428-
"can't resize template disk down, initial capacity is larger: %dKiB > %dKiB",
429-
disk.CapacityInKB, diskCloneCapacityKB)
454+
// assignController assigns a device to a controller.
455+
func assignUnitNumber(device types.BaseVirtualDevice, existingDevices object.VirtualDeviceList, newDevices []types.BaseVirtualDeviceConfigSpec, controller types.BaseVirtualController, offset int32) {
456+
vd := device.GetVirtualDevice()
457+
vd.ControllerKey = controller.GetVirtualController().Key
458+
vd.UnitNumber = &offset
459+
460+
units := make([]bool, 30)
461+
462+
for i := 0; i < int(offset); i++ {
463+
units[i] = true
430464
}
431465

432-
return &types.VirtualDeviceConfigSpec{
433-
Operation: types.VirtualDeviceConfigSpecOperationEdit,
434-
Device: disk,
435-
}, nil
466+
sc, ok := controller.(types.BaseVirtualSCSIController)
467+
if ok {
468+
// The SCSI controller sits on its own bus
469+
klog.Infof("Marking SCSI Controller's unit number: %d", sc.GetVirtualSCSIController().ScsiCtlrUnitNumber)
470+
units[sc.GetVirtualSCSIController().ScsiCtlrUnitNumber] = true
471+
}
472+
473+
key := controller.GetVirtualController().Key
474+
475+
// Check all existing devices
476+
for _, device := range existingDevices {
477+
d := device.GetVirtualDevice()
478+
479+
if d.ControllerKey == key && d.UnitNumber != nil {
480+
units[int(*d.UnitNumber)] = true
481+
}
482+
}
483+
484+
// Check new devices
485+
for _, device := range newDevices {
486+
d := device.GetVirtualDeviceConfigSpec().Device.GetVirtualDevice()
487+
488+
if d.ControllerKey == key && d.UnitNumber != nil {
489+
units[int(*d.UnitNumber)] = true
490+
}
491+
}
492+
493+
// Assign first unused unit number
494+
for unit, used := range units {
495+
if !used {
496+
unit32 := int32(unit)
497+
vd.UnitNumber = &unit32
498+
break
499+
}
500+
}
436501
}
437502

438503
const ethCardType = "vmxnet3"

0 commit comments

Comments
 (0)