Skip to content

Support for VBox driver - for converting to external #3623

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions pkg/cidata/cidata.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,15 @@ func templateArgs(bootScripts bool, instDir, name string, instConfig *limayaml.L
args.MountType = "virtiofs"
}

switch *instConfig.VMType {
case limayaml.QEMU:
args.DiskType = "virtio"
case limayaml.VZ:
args.DiskType = "virtio"
case limayaml.VBOX:
args.DiskType = "sata"
}

for i, d := range instConfig.AdditionalDisks {
format := true
if d.Format != nil {
Expand All @@ -246,7 +255,7 @@ func templateArgs(bootScripts bool, instDir, name string, instConfig *limayaml.L
}
args.Disks = append(args.Disks, Disk{
Name: d.Name,
Device: diskDeviceNameFromOrder(i),
Device: diskDeviceNameFromOrder(args.DiskType, i),
Format: format,
FSType: fstype,
FSArgs: d.FSArgs,
Expand Down Expand Up @@ -472,7 +481,10 @@ func getBootCmds(p []limayaml.Provision) []BootCmds {
return bootCmds
}

func diskDeviceNameFromOrder(order int) string {
func diskDeviceNameFromOrder(diskType string, order int) string {
if diskType == "sata" {
return fmt.Sprintf("sd%c", int('b')+order)
} // diskType == "virtio"
return fmt.Sprintf("vd%c", int('b')+order)
}

Expand Down
1 change: 1 addition & 0 deletions pkg/cidata/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ type TemplateArgs struct {
Mounts []Mount
MountType string
Disks []Disk
DiskType string
GuestInstallPrefix string
UpgradePackages bool
Containerd Containerd
Expand Down
4 changes: 4 additions & 0 deletions pkg/driverutil/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import (
"github.com/lima-vm/lima/pkg/driver"
"github.com/lima-vm/lima/pkg/limayaml"
"github.com/lima-vm/lima/pkg/qemu"
"github.com/lima-vm/lima/pkg/vbox"
"github.com/lima-vm/lima/pkg/vz"
"github.com/lima-vm/lima/pkg/wsl2"
)

func CreateTargetDriverInstance(base *driver.BaseDriver) driver.Driver {
limaDriver := base.Instance.Config.VMType
if *limaDriver == limayaml.VBOX {
return vbox.New(base)
}
if *limaDriver == limayaml.VZ {
return vz.New(base)
}
Expand Down
34 changes: 23 additions & 11 deletions pkg/instance/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,19 +402,31 @@ func prepareDiffDisk(inst *store.Instance) error {
return err
}

f, err := os.Open(diffDisk)
if err != nil {
return err
}
defer f.Close()
var diskSize int64
var format string
if *inst.Config.VMType != limayaml.VBOX {
f, err := os.Open(diffDisk)
if err != nil {
return err
}
defer f.Close()

img, err := qcow2reader.Open(f)
if err != nil {
return err
}
img, err := qcow2reader.Open(f)
if err != nil {
return err
}

diskSize := img.Size()
format := string(img.Type())
diskSize = img.Size()
format = string(img.Type())
} else {
info, err := imgutil.GetInfo(diffDisk)
if err != nil {
return err
}

diskSize = info.VSize
format = info.Format
}

if inst.Disk == diskSize {
return nil
Expand Down
2 changes: 2 additions & 0 deletions pkg/limayaml/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,8 @@ func NewArch(arch string) Arch {

func NewVMType(driver string) VMType {
switch driver {
case "vbox":
return VBOX
case "vz":
return VZ
case "qemu":
Expand Down
1 change: 1 addition & 0 deletions pkg/limayaml/limayaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const (
WSLMount MountType = "wsl2"

QEMU VMType = "qemu"
VBOX VMType = "vbox"
VZ VMType = "vz"
WSL2 VMType = "wsl2"
)
Expand Down
6 changes: 5 additions & 1 deletion pkg/limayaml/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,16 @@ func Validate(y *LimaYAML, warn bool) error {
// NOP
case WSL2:
// NOP
case VBOX:
if *y.Arch != X8664 {
return fmt.Errorf("field `arch` must be %q for VBox; got %q", X8664, *y.Arch)
}
case VZ:
if !IsNativeArch(*y.Arch) {
return fmt.Errorf("field `arch` must be %q for VZ; got %q", NewArch(runtime.GOARCH), *y.Arch)
}
default:
return fmt.Errorf("field `vmType` must be %q, %q, %q; got %q", QEMU, VZ, WSL2, *y.VMType)
return fmt.Errorf("field `vmType` must be %q, %q, %q, or %q; got %q", QEMU, VBOX, VZ, WSL2, *y.VMType)
}

if len(y.Images) == 0 {
Expand Down
20 changes: 20 additions & 0 deletions pkg/qemu/imgutil/imgutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
return &x
}

func (sp *InfoFormatSpecific) Vdi() *InfoFormatSpecificDataVdi {
var x InfoFormatSpecificDataVdi
return &x
}

type InfoFormatSpecificDataQcow2 struct {
Compat string `json:"compat,omitempty"` // since QEMU 1.7
LazyRefcounts bool `json:"lazy-refcounts,omitempty"` // since QEMU 1.7
Expand All @@ -94,6 +99,9 @@
ClusterSize int `json:"cluster-size,omitempty"` // since QEMU 1.7
}

type InfoFormatSpecificDataVdi struct {

Check failure on line 102 in pkg/qemu/imgutil/imgutil.go

View workflow job for this annotation

GitHub Actions / Lint Go (macos-15)

File is not properly formatted (gofumpt)
}

// Info corresponds to the output of `qemu-img info --output=json FILE`.
type Info struct {
Filename string `json:"filename,omitempty"` // since QEMU 1.3
Expand Down Expand Up @@ -121,6 +129,18 @@
return nil
}

func ConvertToVDI(source string, dest string) error {

Check failure on line 132 in pkg/qemu/imgutil/imgutil.go

View workflow job for this annotation

GitHub Actions / Lint Go (macos-15)

paramTypeCombine: func(source string, dest string) error could be replaced with func(source, dest string) error (gocritic)
var stdout, stderr bytes.Buffer
cmd := exec.Command("qemu-img", "convert", "-O", "vdi", source, dest)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to run %v: stdout=%q, stderr=%q: %w",
cmd.Args, stdout.String(), stderr.String(), err)
}
return nil
}

func ParseInfo(b []byte) (*Info, error) {
var imgInfo Info
if err := json.Unmarshal(b, &imgInfo); err != nil {
Expand Down
93 changes: 93 additions & 0 deletions pkg/vbox/disk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package vbox

import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"

"github.com/docker/go-units"

Check failure on line 12 in pkg/vbox/disk.go

View workflow job for this annotation

GitHub Actions / Lint Go (macos-15)

File is not properly formatted (gci)
"github.com/lima-vm/lima/pkg/driver"
"github.com/lima-vm/lima/pkg/fileutils"
"github.com/lima-vm/lima/pkg/iso9660util"
"github.com/lima-vm/lima/pkg/qemu/imgutil"
"github.com/lima-vm/lima/pkg/store/filenames"
)

func EnsureDisk(ctx context.Context, driver *driver.BaseDriver) error {
diffDisk := filepath.Join(driver.Instance.Dir, filenames.DiffDisk)
if _, err := os.Stat(diffDisk); err == nil || !errors.Is(err, os.ErrNotExist) {
// disk is already ensured
return err
}

baseDisk := filepath.Join(driver.Instance.Dir, filenames.BaseDisk)
if _, err := os.Stat(baseDisk); errors.Is(err, os.ErrNotExist) {
var ensuredBaseDisk bool
errs := make([]error, len(driver.Instance.Config.Images))
for i, f := range driver.Instance.Config.Images {
if _, err := fileutils.DownloadFile(ctx, baseDisk, f.File, true, "the image", *driver.Instance.Config.Arch); err != nil {
errs[i] = err
continue
}
ensuredBaseDisk = true
break
}
if !ensuredBaseDisk {
return fileutils.Errors(errs)
}
}
diskSize, _ := units.RAMInBytes(*driver.Instance.Config.Disk)
if diskSize == 0 {
return nil
}
// TODO - Break qemu dependency
isBaseDiskISO, err := iso9660util.IsISO9660(baseDisk)
if err != nil {
return err
}
baseDiskInfo, err := imgutil.GetInfo(baseDisk)
if err != nil {
return fmt.Errorf("failed to get the information of base disk %q: %w", baseDisk, err)
}
if err = imgutil.AcceptableAsBasedisk(baseDiskInfo); err != nil {
return fmt.Errorf("file %q is not acceptable as the base disk: %w", baseDisk, err)
}
if baseDiskInfo.Format == "" {
return fmt.Errorf("failed to inspect the format of %q", baseDisk)
}
args := []string{"create", "-f", "qcow2"}
if !isBaseDiskISO {
args = append(args, "-F", baseDiskInfo.Format, "-b", baseDisk)
}
args = append(args, diffDisk, strconv.Itoa(int(diskSize)))
cmd := exec.Command("qemu-img", args...)
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("failed to run %v: %q: %w", cmd.Args, string(out), err)
}
if isBaseDiskISO {
if err = os.Rename(baseDisk, baseDisk+".iso"); err != nil {
return err
}
if err = os.Symlink(filenames.BaseDisk+".iso", baseDisk); err != nil {
return err
}
} else {
if err = os.Rename(baseDisk, baseDisk+".img"); err != nil {
return err
}
if err = os.Symlink(filenames.BaseDisk+".img", baseDisk); err != nil {
return err
}
}
if err = imgutil.ConvertToVDI(diffDisk, diffDisk+".vdi"); err != nil {
return errors.New("cannot convert qcow2 to vdi for vbox driver")
}
if err = os.Remove(diffDisk); err != nil {
return err
}
return os.Symlink(filenames.DiffDisk+".vdi", diffDisk)
}
Loading
Loading