diff --git a/examples/default.yaml b/examples/default.yaml index da6f06ede79..13c7a2aef66 100644 --- a/examples/default.yaml +++ b/examples/default.yaml @@ -5,12 +5,24 @@ # Default values in this YAML file are specified by `null` instead of Lima's "builtin default" values, # so they can be overridden by the $LIMA_HOME/_config/default.yaml mechanism documented at the end of this file. +# A template should specify the minimum Lima version required to parse this template correctly. +# It should not be set if the minimum version is less than 1.0.0 +# 🟢 Builtin default: not set +minimumLimaVersion: null + # VM type: "qemu", "vz" (on macOS 13 and later), or "default". # The vmType can be specified only on creating the instance. # The vmType of existing instances cannot be changed. # 🟢 Builtin default: "vz" (on macOS 13.5 and later), "qemu" (on others) vmType: null +vmOpts: + qemu: + # Minimum version of QEMU required to create an instance of this template. + # Will be ignored if the vmType is not "qemu" + # 🟢 Builtin default: not set + minimumVersion: null + # OS: "Linux". # 🟢 Builtin default: "Linux" os: null diff --git a/pkg/limayaml/limayaml.go b/pkg/limayaml/limayaml.go index 24e9b3c783d..ee02018e3ff 100644 --- a/pkg/limayaml/limayaml.go +++ b/pkg/limayaml/limayaml.go @@ -7,7 +7,9 @@ import ( ) type LimaYAML struct { + MinimumLimaVersion *string `yaml:"minimumLimaVersion,omitempty" json:"minimumLimaVersion,omitempty"` VMType *VMType `yaml:"vmType,omitempty" json:"vmType,omitempty"` + VMOpts VMOpts `yaml:"vmOpts,omitempty" json:"vmOpts,omitempty"` OS *OS `yaml:"os,omitempty" json:"os,omitempty"` Arch *Arch `yaml:"arch,omitempty" json:"arch,omitempty"` Images []Image `yaml:"images" json:"images"` // REQUIRED @@ -72,6 +74,14 @@ const ( WSL2 VMType = "wsl2" ) +type VMOpts struct { + QEMU QEMUOpts `yaml:"qemu,omitempty" json:"qemu,omitempty"` +} + +type QEMUOpts struct { + MinimumVersion *string `yaml:"minimumVersion,omitempty" json:"minimumVersion,omitempty"` +} + type Rosetta struct { Enabled *bool `yaml:"enabled,omitempty" json:"enabled,omitempty"` BinFmt *bool `yaml:"binfmt,omitempty" json:"binfmt,omitempty"` diff --git a/pkg/limayaml/validate.go b/pkg/limayaml/validate.go index b746535e877..a647f146c20 100644 --- a/pkg/limayaml/validate.go +++ b/pkg/limayaml/validate.go @@ -12,10 +12,13 @@ import ( "strings" "unicode" + "github.com/coreos/go-semver/semver" "github.com/docker/go-units" "github.com/lima-vm/lima/pkg/localpathutil" "github.com/lima-vm/lima/pkg/networks" "github.com/lima-vm/lima/pkg/osutil" + "github.com/lima-vm/lima/pkg/version" + "github.com/lima-vm/lima/pkg/version/versionutil" "github.com/sirupsen/logrus" ) @@ -43,6 +46,23 @@ func validateFileObject(f File, fieldName string) error { } func Validate(y *LimaYAML, warn bool) error { + if y.MinimumLimaVersion != nil { + if _, err := versionutil.Parse(*y.MinimumLimaVersion); err != nil { + return fmt.Errorf("field `minimumLimaVersion` must be a semvar value, got %q: %w", *y.MinimumLimaVersion, err) + } + limaVersion, err := versionutil.Parse(version.Version) + if err != nil { + return fmt.Errorf("can't parse builtin Lima version %q: %w", version.Version, err) + } + if versionutil.GreaterThan(*y.MinimumLimaVersion, limaVersion.String()) { + return fmt.Errorf("template requires Lima version %q; this is only %q", *y.MinimumLimaVersion, limaVersion.String()) + } + } + if y.VMOpts.QEMU.MinimumVersion != nil { + if _, err := semver.NewVersion(*y.VMOpts.QEMU.MinimumVersion); err != nil { + return fmt.Errorf("field `vmOpts.qemu.minimumVersion` must be a semvar value, got %q: %w", *y.VMOpts.QEMU.MinimumVersion, err) + } + } switch *y.OS { case LINUX: default: diff --git a/pkg/qemu/qemu.go b/pkg/qemu/qemu.go index dc779cb498d..27624034551 100644 --- a/pkg/qemu/qemu.go +++ b/pkg/qemu/qemu.go @@ -496,6 +496,9 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er if version.LessThan(*semver.New(MinimumQemuVersion)) { logrus.Fatalf("QEMU %v is too old, %v or later required", version, MinimumQemuVersion) } + if y.VMOpts.QEMU.MinimumVersion != nil && version.LessThan(*semver.New(*y.VMOpts.QEMU.MinimumVersion)) { + logrus.Fatalf("QEMU %v is too old, template requires %q or later", version, *y.VMOpts.QEMU.MinimumVersion) + } if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" && version.Equal(*semver.New("8.2.0")) { logrus.Fatal("QEMU 8.2.0 is no longer supported on ARM Mac due to . " + "Please upgrade QEMU to v8.2.1 (or downgrade to v8.1.x).")