Skip to content

Commit 98a2170

Browse files
committed
multiple disks support feature
1 parent 39ad710 commit 98a2170

File tree

5 files changed

+92
-45
lines changed

5 files changed

+92
-45
lines changed

.github/workflows/ci.yaml

Lines changed: 0 additions & 38 deletions
This file was deleted.

api/v1beta1/type.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ type Image struct {
5656
ChecksumType *string `json:"checksumType,omitempty"`
5757
}
5858

59+
// ExtraDisk represents an additional virtual disk
60+
type ExtraDisk struct {
61+
Size string `json:"size,omitempty"` // e.g., "100Gi"
62+
Storage string `json:"storage,omitempty"` // e.g., "local-lvm"
63+
Type string `json:"type,omitempty"` // e.g., "scsi", "virtio"
64+
Format string `json:"format,omitempty"` //
65+
}
66+
5967
// Hardware
6068
type Hardware struct {
6169
// amount of RAM for the VM in MiB : 16 ~
@@ -94,7 +102,8 @@ type Hardware struct {
94102
// hard disk size
95103
// +kubebuilder:validation:Pattern:=\+?\d+(\.\d+)?[KMGT]?
96104
// +kubebuilder:default:="50G"
97-
Disk string `json:"disk,omitempty"`
105+
RootDisk string `json:"rootDisk,omitempty"`
106+
ExtraDisks []ExtraDisk `json:"extraDisks,omitempty"` // Add support for multiple disks
98107

99108
// network devices
100109
// to do: multiple devices

cloud/services/compute/instance/image.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (s *Service) reconcileBootDevice(ctx context.Context, vm *proxmox.VirtualMa
2424

2525
// boot disk
2626
log.Info("resizing boot disk")
27-
if err := vm.ResizeVolume(ctx, bootDvice, s.scope.GetHardware().Disk); err != nil {
27+
if err := vm.ResizeVolume(ctx, bootDvice, s.scope.GetHardware().RootDisk); err != nil {
2828
return err
2929
}
3030

cloud/services/compute/instance/qemu.go

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package instance
33
import (
44
"context"
55
"fmt"
6+
"reflect"
67

78
"github.com/k8s-proxmox/cluster-api-provider-proxmox/cloud/scheduler/framework"
89
"github.com/k8s-proxmox/proxmox-go/api"
@@ -13,6 +14,7 @@ import (
1314

1415
const (
1516
bootDvice = "scsi0"
17+
1618
)
1719

1820
// reconciles QEMU instance
@@ -96,9 +98,39 @@ func (s *Service) createQEMU(ctx context.Context) (*proxmox.VirtualMachine, erro
9698
return nil, err
9799
}
98100

101+
// Resize disks immediately after creation
102+
if err := s.resizeExtraDisks(ctx, vm); err != nil {
103+
log.Error(err, "Failed to resize extra disks")
104+
}
105+
99106
return vm, nil
100107
}
101108

109+
func (s *Service) resizeExtraDisks(ctx context.Context, vm *proxmox.VirtualMachine) error {
110+
log := log.FromContext(ctx)
111+
log.Info("Resizing additional disks for VM", "vmid", vm.VM.VMID)
112+
113+
extraDisks := s.scope.GetHardware().ExtraDisks
114+
if len(extraDisks) == 0 {
115+
return nil // No extra disks, nothing to do
116+
}
117+
118+
for i, disk := range extraDisks {
119+
diskName := fmt.Sprintf("scsi%d", i+1) // scsi1, scsi2, scsi3...
120+
log.Info("Resizing disk", "vmid", vm.VM.VMID, "disk", diskName, "size", disk.Size)
121+
122+
// Use `ResizeVolume` to resize the disk
123+
err := vm.ResizeVolume(ctx, diskName, disk.Size)
124+
if err != nil {
125+
log.Error(err, "Failed to resize disk", "disk", diskName)
126+
return err
127+
}
128+
}
129+
130+
log.Info("Successfully resized all extra disks", "vmid", vm.VM.VMID)
131+
return nil
132+
}
133+
102134
func (s *Service) generateVMOptions() api.VirtualMachineCreateOptions {
103135
vmName := s.scope.Name()
104136
snippetStorageName := s.scope.GetClusterStorage().Name
@@ -108,8 +140,29 @@ func (s *Service) generateVMOptions() api.VirtualMachineCreateOptions {
108140
options := s.scope.GetOptions()
109141
cicustom := fmt.Sprintf("user=%s:%s", snippetStorageName, userSnippetPath(vmName))
110142
ide2 := fmt.Sprintf("file=%s:cloudinit,media=cdrom", imageStorageName)
111-
scsi0 := fmt.Sprintf("%s:0,import-from=%s", imageStorageName, rawImageFilePath(s.scope.GetImage()))
112143
net0 := hardware.NetworkDevice.String()
144+
// Assign primary SCSI disk
145+
scsiDisks := api.Scsi{}
146+
scsiDisks.Scsi0 = fmt.Sprintf("%s:0,import-from=%s", imageStorageName, rawImageFilePath(s.scope.GetImage()))
147+
// Assign additional disks manually
148+
extraDisks := s.scope.GetHardware().ExtraDisks
149+
if len(extraDisks) > 5 {
150+
log.FromContext(context.TODO()).Error(fmt.Errorf("too many extra disks"), "Only 6 extra disks are supported, ignoring extra disks")
151+
extraDisks = extraDisks[:5] // Trim to max 5 extra disks
152+
}
153+
154+
// Assign extra disks
155+
scsiStruct := reflect.ValueOf(&scsiDisks).Elem()
156+
for i, disk := range extraDisks {
157+
fieldName := fmt.Sprintf("Scsi%d", i+1) // Scsi1, Scsi2, ...
158+
field := scsiStruct.FieldByName(fieldName)
159+
if field.IsValid() && field.CanSet() {
160+
field.SetString(fmt.Sprintf("%s:%d,format=%s,size=%s", disk.Storage, i+1, disk.Format, disk.Size))
161+
// field.SetString(fmt.Sprintf("%s:%d,size=%s", disk.Storage, i+1, disk.Size))
162+
} else {
163+
log.FromContext(context.TODO()).Error(fmt.Errorf("invalid SCSI field"), "Failed to set extra disk", "field", fieldName)
164+
}
165+
}
113166

114167
vmoptions := api.VirtualMachineCreateOptions{
115168
ACPI: boolToInt8(options.ACPI),
@@ -140,7 +193,7 @@ func (s *Service) generateVMOptions() api.VirtualMachineCreateOptions {
140193
OSType: api.OSType(options.OSType),
141194
Protection: boolToInt8(options.Protection),
142195
Reboot: int(boolToInt8(options.Reboot)),
143-
Scsi: api.Scsi{Scsi0: scsi0},
196+
Scsi: scsiDisks,
144197
ScsiHw: api.VirtioScsiPci,
145198
SearchDomain: network.SearchDomain,
146199
Serial: api.Serial{Serial0: "socket"},
@@ -168,10 +221,33 @@ func boolToInt8(b bool) int8 {
168221
func (s *Service) injectVMOption(vmOption *api.VirtualMachineCreateOptions, storage string) *api.VirtualMachineCreateOptions {
169222
// storage is finalized after node scheduling so we need to inject storage name here
170223
ide2 := fmt.Sprintf("file=%s:cloudinit,media=cdrom", storage)
171-
scsi0 := fmt.Sprintf("%s:0,import-from=%s", storage, rawImageFilePath(s.scope.GetImage()))
172-
vmOption.Scsi.Scsi0 = scsi0
173224
vmOption.Ide.Ide2 = ide2
174225
vmOption.Storage = storage
226+
// Assign primary root disk
227+
vmOption.Scsi.Scsi0 = fmt.Sprintf("%s:0,import-from=%s", storage, rawImageFilePath(s.scope.GetImage()))
228+
229+
// Assign Extra Disks (Scsi1, Scsi2, ... up to Scsi5)
230+
extraDisks := s.scope.GetHardware().ExtraDisks
231+
if len(extraDisks) > 5 {
232+
log.FromContext(context.TODO()).Error(fmt.Errorf("too many extra disks"), "Only 5 extra disks are supported, ignoring excess")
233+
extraDisks = extraDisks[:5] // Limit to 5 extra disks
234+
}
175235

236+
// Set each disk explicitly
237+
if len(extraDisks) > 0 {
238+
vmOption.Scsi.Scsi1 = fmt.Sprintf("%s:1,size=%s", extraDisks[0].Storage, extraDisks[0].Size)
239+
}
240+
if len(extraDisks) > 1 {
241+
vmOption.Scsi.Scsi2 = fmt.Sprintf("%s:2,size=%s", extraDisks[1].Storage, extraDisks[1].Size)
242+
}
243+
if len(extraDisks) > 2 {
244+
vmOption.Scsi.Scsi3 = fmt.Sprintf("%s:3,size=%s", extraDisks[2].Storage, extraDisks[2].Size)
245+
}
246+
if len(extraDisks) > 3 {
247+
vmOption.Scsi.Scsi4 = fmt.Sprintf("%s:4,size=%s", extraDisks[3].Storage, extraDisks[3].Size)
248+
}
249+
if len(extraDisks) > 4 {
250+
vmOption.Scsi.Scsi5 = fmt.Sprintf("%s:5,size=%s", extraDisks[4].Storage, extraDisks[4].Size)
251+
}
176252
return vmOption
177253
}

clusterctl.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
providers:
22
- name: proxmox
3-
url: https://github.com/k8s-proxmox/cluster-api-provider-proxmox/releases/latest/infrastructure-components.yaml
3+
url: https://github.com/mojaloop/cluster-api-provider-proxmox/releases/latest/infrastructure-components.yaml
44
type: InfrastructureProvider

0 commit comments

Comments
 (0)