diff --git a/pkg/machine/qemu.go b/pkg/machine/qemu.go index ee3bb74..45eba78 100644 --- a/pkg/machine/qemu.go +++ b/pkg/machine/qemu.go @@ -25,29 +25,34 @@ type QEMU struct { func (q *QEMU) Create(ctx context.Context) (context.Context, error) { log.Info("Create qemu machine") - driveSize := q.driveSize() - drive := q.machineConfig.Drive - if q.machineConfig.AutoDriveSetup && q.machineConfig.Drive == "" { - err := q.CreateDisk(fmt.Sprintf("%s.img", q.machineConfig.ID), driveSize) - if err != nil { - return ctx, fmt.Errorf("creating disk with size %s: %w", driveSize, err) + driveSizes := q.driveSizes() + userDrives := q.machineConfig.Drives + if q.machineConfig.AutoDriveSetup && len(userDrives) == 0 { + for i, s := range driveSizes { + filename := fmt.Sprintf("%s-%d.img", q.machineConfig.ID, i) + err := q.CreateDisk(filename, s) + if err != nil { + return ctx, fmt.Errorf("creating disk with size %s: %w", s, err) + } + userDrives = append(userDrives, filepath.Join(q.machineConfig.StateDir, filename)) } - drive = filepath.Join(q.machineConfig.StateDir, fmt.Sprintf("%s.img", q.machineConfig.ID)) } genDrives := func(m types.MachineConfig) []string { - drives := []string{} + allDrives := []string{} if m.ISO != "" { - drives = append(drives, "-drive", fmt.Sprintf("if=ide,media=cdrom,file=%s", m.ISO)) + allDrives = append(allDrives, "-drive", fmt.Sprintf("if=ide,media=cdrom,file=%s", m.ISO)) } if m.DataSource != "" { - drives = append(drives, "-drive", fmt.Sprintf("if=ide,media=cdrom,file=%s", m.DataSource)) + allDrives = append(allDrives, "-drive", fmt.Sprintf("if=ide,media=cdrom,file=%s", m.DataSource)) } - if drive != "" { - drives = append(drives, "-drive", fmt.Sprintf("if=virtio,media=disk,file=%s", drive)) + if len(userDrives) != 0 { + for _, d := range userDrives { + allDrives = append(allDrives, "-drive", fmt.Sprintf("if=virtio,media=disk,file=%s", d)) + } } - return drives + return allDrives } processName := "/usr/bin/qemu-system-x86_64" @@ -56,7 +61,9 @@ func (q *QEMU) Create(ctx context.Context) (context.Context, error) { } log.Infof("Starting VM with %s [ Memory: %s, CPU: %s ]", processName, q.machineConfig.Memory, q.machineConfig.CPU) - log.Infof("HD at %s, state directory at %s", drive, q.machineConfig.StateDir) + for _, d := range userDrives { + log.Infof("HD at %s, state directory at %s", d, q.machineConfig.StateDir) + } if q.machineConfig.ISO != "" { log.Infof("ISO at %s", q.machineConfig.ISO) } @@ -258,13 +265,18 @@ func (q *QEMU) monitorSockFile() string { return path.Join(q.machineConfig.StateDir, "qemu-monitor.sock") } -// Converts the user's drive size (which is Mb as a string) to the qemu format. +// Converts the user's drive sizes (which are Mb as strings) to the qemu format. // https://qemu.readthedocs.io/en/latest/tools/qemu-img.html#cmdoption-qemu-img-arg-create -func (q *QEMU) driveSize() string { - driveSize := types.DefaultDriveSize - if q.machineConfig.Drive != "" { - driveSize = q.machineConfig.Drive +func (q *QEMU) driveSizes() []string { + sizes := []string{} + + for _, s := range q.machineConfig.DriveSizes { + sizes = append(sizes, fmt.Sprintf("%sM", s)) + } + + if len(sizes) == 0 { + sizes = append(sizes, fmt.Sprintf("%sM", types.DefaultDriveSize)) } - return fmt.Sprintf("%sM", driveSize) + return sizes } diff --git a/pkg/machine/types/config.go b/pkg/machine/types/config.go index d08c856..d4fb3b3 100644 --- a/pkg/machine/types/config.go +++ b/pkg/machine/types/config.go @@ -25,8 +25,8 @@ type MachineConfig struct { ISOChecksum string `yaml:"isoChecksum,omitempty"` DataSource string `yaml:"datasource,omitempty"` - Drive string `yaml:"drive,omitempty"` - DriveSize string `yaml:"drivesize,omitempty"` + Drives []string `yaml:"drives,omitempty"` + DriveSizes []string `yaml:"driveSizes,omitempty"` AutoDriveSetup bool `yaml:"auto_drive,omitempty"` ID string `yaml:"id,omitempty"` Memory string `yaml:"memory,omitempty"` @@ -166,7 +166,7 @@ func WithISO(iso string) MachineOption { func WithDrive(drive string) MachineOption { return func(mc *MachineConfig) error { if drive != "" { - mc.Drive = drive + mc.Drives = append(mc.Drives, drive) } return nil @@ -176,7 +176,7 @@ func WithDrive(drive string) MachineOption { func WithDriveSize(drivesize string) MachineOption { return func(mc *MachineConfig) error { if drivesize != "" { - mc.DriveSize = drivesize + mc.DriveSizes = append(mc.DriveSizes, drivesize) } return nil diff --git a/pkg/machine/vbox.go b/pkg/machine/vbox.go index 164f50e..ad8219d 100644 --- a/pkg/machine/vbox.go +++ b/pkg/machine/vbox.go @@ -65,35 +65,38 @@ func (v *VBox) Create(ctx context.Context) (context.Context, error) { return ctx, fmt.Errorf("while set VM: %w - %s", err, out) } - driveSize := types.DefaultDriveSize - if v.machineConfig.Drive != "" { - driveSize = v.machineConfig.Drive - } - drive := v.machineConfig.Drive - if v.machineConfig.AutoDriveSetup && v.machineConfig.Drive == "" { - err := v.CreateDisk(fmt.Sprintf("%s.vdi", v.machineConfig.ID), driveSize) - if err != nil { - return ctx, err + driveSizes := v.driveSizes() + userDrives := v.machineConfig.Drives + if v.machineConfig.AutoDriveSetup && len(userDrives) == 0 { + for i, s := range driveSizes { + err := v.CreateDisk(fmt.Sprintf("%s-%d.vdi", v.machineConfig.ID, i), s) + if err != nil { + return ctx, err + } + userDrives = append(userDrives, filepath.Join(v.machineConfig.StateDir, fmt.Sprintf("%s-%d.vdi", v.machineConfig.ID, i))) } - drive = filepath.Join(v.machineConfig.StateDir, fmt.Sprintf("%s.vdi", v.machineConfig.ID)) } - if drive != "" { - out, err = utils.SH(fmt.Sprintf(`VBoxManage storageattach "%s" --storagectl "sata controller" --port 0 --device 0 --type hdd --medium %s`, v.machineConfig.ID, drive)) + totalDrives := 0 + for _, d := range userDrives { + totalDrives++ + out, err = utils.SH(fmt.Sprintf(`VBoxManage storageattach "%s-%d" --storagectl "sata controller" --port %d --device 0 --type hdd --medium %s`, v.machineConfig.ID, totalDrives-1, totalDrives, d)) if err != nil { return ctx, fmt.Errorf("while set VM: %w - %s", err, out) } } if v.machineConfig.ISO != "" { - out, err = utils.SH(fmt.Sprintf(`VBoxManage storageattach "%s" --storagectl "sata controller" --port 1 --device 0 --type dvddrive --medium %s`, v.machineConfig.ID, v.machineConfig.ISO)) + totalDrives++ + out, err = utils.SH(fmt.Sprintf(`VBoxManage storageattach "%s" --storagectl "sata controller" --port %d --device 0 --type dvddrive --medium %s`, v.machineConfig.ID, totalDrives-1, v.machineConfig.ISO)) if err != nil { return ctx, fmt.Errorf("while set VM: %w - %s", err, out) } } if v.machineConfig.DataSource != "" { - out, err = utils.SH(fmt.Sprintf(`VBoxManage storageattach "%s" --storagectl "sata controller" --port 2 --device 0 --type dvddrive --medium %s`, v.machineConfig.ID, v.machineConfig.DataSource)) + totalDrives++ + out, err = utils.SH(fmt.Sprintf(`VBoxManage storageattach "%s" --storagectl "sata controller" --port %d --device 0 --type dvddrive --medium %s`, v.machineConfig.ID, totalDrives-1, v.machineConfig.DataSource)) if err != nil { return ctx, fmt.Errorf("while set VM: %w - %s", err, out) } @@ -140,3 +143,11 @@ func (v *VBox) ReceiveFile(src, dst string) error { func (v *VBox) SendFile(src, dst, permissions string) error { return controller.SendFile(v, src, dst, permissions) } + +func (v *VBox) driveSizes() []string { + if len(v.machineConfig.DriveSizes) != 0 { + return v.machineConfig.DriveSizes + } + + return []string{types.DefaultDriveSize} +}