Skip to content
Open
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
13 changes: 13 additions & 0 deletions pkg/driver/qemu/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,14 @@ func resolveCPUType(y *limatype.LimaYAML) string {
return cpuType[*y.Arch]
}

func qemuExtraArgs(y *limatype.LimaYAML) ([]string, error) {
var qemuOpts limatype.QEMUOpts
if err := limayaml.Convert(y.VMOpts[limatype.QEMU], &qemuOpts, "vmOpts.qemu"); err != nil {
return nil, fmt.Errorf("failed to convert `vmOpts.qemu`: %w", err)
}
return qemuOpts.ExtraArgs, nil
}

func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err error) {
y := cfg.LimaYAML
exe, args, err = Exe(*y.Arch)
Expand Down Expand Up @@ -975,6 +983,11 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er
// QEMU process
args = append(args, "-name", "lima-"+cfg.Name)
args = append(args, "-pidfile", filepath.Join(cfg.InstanceDir, filenames.PIDFile(*y.VMType)))
extraArgs, err := qemuExtraArgs(y)
if err != nil {
return "", nil, err
}
args = append(args, extraArgs...)

return exe, args, nil
}
Expand Down
72 changes: 72 additions & 0 deletions pkg/driver/qemu/qemu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import (
"testing"

"gotest.tools/v3/assert"

"github.com/lima-vm/lima/v2/pkg/limatype"
"github.com/lima-vm/lima/v2/pkg/limayaml"
)

func TestArgValue(t *testing.T) {
Expand Down Expand Up @@ -89,3 +92,72 @@ func TestParseQemuVersion(t *testing.T) {
assert.Equal(t, tc.expectedValue, v.String())
}
}

func TestQemuExtraArgs(t *testing.T) {
type testCase struct {
name string
inputYAML string
expected []string
expectedError string
}
testCases := []testCase{
{
name: "no vmOpts",
inputYAML: `
vmType: "qemu"
`,
expected: nil,
},
{
name: "qemu opts without extra args",
inputYAML: `
vmType: "qemu"
vmOpts:
qemu:
minimumVersion: "8.2.1"
`,
expected: nil,
},
{
name: "extra args set",
inputYAML: `
vmType: "qemu"
vmOpts:
qemu:
extraArgs:
- "-device"
- "virtio-balloon"
- "-overcommit"
- "mem-lock=off"
`,
expected: []string{"-device", "virtio-balloon", "-overcommit", "mem-lock=off"},
},
{
name: "structurally wrong extra args",
inputYAML: `
vmType: "qemu"
vmOpts:
qemu:
extraArgs:
- "-device"
- {bad: "shape"}
`,
expectedError: "failed to convert `vmOpts.qemu`",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var y limatype.LimaYAML
err := limayaml.Unmarshal([]byte(tc.inputYAML), &y, "lima.yaml")
assert.NilError(t, err)

got, err := qemuExtraArgs(&y)
if tc.expectedError == "" {
assert.NilError(t, err)
assert.DeepEqual(t, got, tc.expected)
} else {
assert.ErrorContains(t, err, tc.expectedError)
}
})
}
}
5 changes: 3 additions & 2 deletions pkg/limatype/lima_yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ type User struct {
type VMOpts map[VMType]any

type QEMUOpts struct {
MinimumVersion *string `yaml:"minimumVersion,omitempty" json:"minimumVersion,omitempty" jsonschema:"nullable"`
CPUType CPUType `yaml:"cpuType,omitempty" json:"cpuType,omitempty" jsonschema:"nullable"`
MinimumVersion *string `yaml:"minimumVersion,omitempty" json:"minimumVersion,omitempty" jsonschema:"nullable"`
CPUType CPUType `yaml:"cpuType,omitempty" json:"cpuType,omitempty" jsonschema:"nullable"`
ExtraArgs []string `yaml:"extraArgs,omitempty" json:"extraArgs,omitempty" jsonschema:"nullable"`
}

type VZOpts struct {
Expand Down
4 changes: 4 additions & 0 deletions pkg/limayaml/marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,17 @@ vmOpts:
qemu:
minimumVersion: null
cpuType:
extraArgs:
- "-device"
- "virtio-balloon"
`
var y limatype.LimaYAML
err := Unmarshal([]byte(text), &y, "lima.yaml")
assert.NilError(t, err)
var o limatype.QEMUOpts
err = Convert(y.VMOpts[limatype.QEMU], &o, "vmOpts.qemu")
assert.NilError(t, err)
assert.DeepEqual(t, o.ExtraArgs, []string{"-device", "virtio-balloon"})
t.Log(dumpYAML(t, o))
}

Expand Down
6 changes: 6 additions & 0 deletions templates/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,12 @@ vmOpts:
# armv7l: "max" # (or "host" when running on armv7l host)
# riscv64: "max" # (or "host" when running on riscv64 host)
# x86_64: "max" # (or "host" when running on x86_64 host; additional options are appended on Intel Mac)

# Extra arguments to pass to QEMU.
# Each list entry is one CLI token (no shell parsing).
# 🟢 Builtin default: []
# extraArgs:
# - "-usb"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to use existing env vars? (QEMU_SYSTEM_AARCH64, QEMU_SYSTEM_X86_64, etc.)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly because I missed the fact that it gets parsed for shell arguments. :)

Though looking at

logrus.Warnf("Specifying args (%v) via $%s is supported only for debugging!", args, envK)
, looks like it would log a warning when args are present. And it would be nicer to have it in one place in template file.

Feel free to close the PR if you don't think it would be helpful to others.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to use existing env vars? (QEMU_SYSTEM_AARCH64, QEMU_SYSTEM_X86_64, etc.)

I think we used to say that this is just a debugging feature, but it seems like the fact that you can add additional arguments is not documented at all.

If this is supposed to be a regular (driver) feature, then adding it to the template makes sense.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I have a use case that this would be incredibly helpful for - I need to add a pflash device for OVMF vars, so that the variables don't get written to the esp of the guest. Right now, the only workaround I'm seeing is to write a wrapper script that I call via QEMU_SYSTEM_X86_64 and QEMU_SYSTEM_AARCH64, but that feels really hacky. Being able to append args via the YAML would eliminate the need for a wrapper script entirely.

vz:
# Specify the disk image format: "raw" or "asif".
# Currently only applies to the primary disk image.
Expand Down
Loading