@@ -3,6 +3,7 @@ package limayaml
33import (
44 "bytes"
55 "crypto/sha256"
6+ "errors"
67 "fmt"
78 "net"
89 "os"
@@ -13,6 +14,7 @@ import (
1314 "strings"
1415 "text/template"
1516
17+ "github.com/coreos/go-semver/semver"
1618 "github.com/docker/go-units"
1719 "github.com/pbnjay/memory"
1820 "github.com/sirupsen/logrus"
@@ -178,7 +180,7 @@ func FillDefault(y, d, o *LimaYAML, filePath string) {
178180 if o .VMType != nil {
179181 y .VMType = o .VMType
180182 }
181- y .VMType = ptr .Of (ResolveVMType (y . VMType ))
183+ y .VMType = ptr .Of (ResolveVMType (y , d , o , filePath ))
182184 if y .OS == nil {
183185 y .OS = d .OS
184186 }
@@ -905,11 +907,97 @@ func NewVMType(driver string) VMType {
905907 }
906908}
907909
908- func ResolveVMType (s * string ) VMType {
909- if s == nil || * s == "" || * s == "default" {
910+ func isExistingInstanceDir (dir string ) bool {
911+ // existence of "lima.yaml" does not signify existence of the instance,
912+ // because the file is created during the initialization of the instance.
913+ for _ , f := range []string {
914+ filenames .HostAgentStdoutLog , filenames .HostAgentStderrLog ,
915+ filenames .VzIdentifier , filenames .BaseDisk , filenames .DiffDisk , filenames .CIDataISO ,
916+ } {
917+ file := filepath .Join (dir , f )
918+ if _ , err := os .Lstat (file ); ! errors .Is (err , os .ErrNotExist ) {
919+ return true
920+ }
921+ }
922+ return false
923+ }
924+
925+ func ResolveVMType (y , d , o * LimaYAML , filePath string ) VMType {
926+ // Check if the VMType is explicitly specified
927+ for i , f := range []* LimaYAML {o , y , d } {
928+ if f .VMType != nil && * f .VMType != "" && * f .VMType != "default" {
929+ logrus .Debugf ("ResolveVMType: resolved VMType %q (explicitly specified in []*LimaYAML{o,y,d}[%d])" , * f .VMType , i )
930+ return NewVMType (* f .VMType )
931+ }
932+ }
933+
934+ // If this is an existing instance, guess the VMType from the contents of the instance directory.
935+ // Note that the instance directory may be created by a previous version of Lima.
936+ if dir , basename := filepath .Split (filePath ); dir != "" && basename == filenames .LimaYAML && isExistingInstanceDir (dir ) {
937+ vzIdentifier := filepath .Join (dir , filenames .VzIdentifier ) // since Lima v0.14
938+ if _ , err := os .Lstat (vzIdentifier ); ! errors .Is (err , os .ErrNotExist ) {
939+ logrus .Debugf ("ResolveVMType: resolved VMType %q (existing instance, with %q)" , VZ , vzIdentifier )
940+ return VZ
941+ }
942+ logrus .Debugf ("ResolveVMType: resolved VMType %q (existing instance, without %q)" , QEMU , vzIdentifier )
943+ return QEMU
944+ }
945+
946+ // Resolve the best type, depending on GOOS
947+ switch runtime .GOOS {
948+ case "darwin" :
949+ macOSProductVersion , err := osutil .ProductVersion ()
950+ if err != nil {
951+ logrus .WithError (err ).Warn ("Failed to get macOS product version" )
952+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for unknown version of macOS)" , QEMU )
953+ return QEMU
954+ }
955+ // Virtualization.framework in macOS prior to 13.5 could not boot Linux kernel v6.2 on Intel
956+ // https://github.com/lima-vm/lima/issues/1577
957+ if macOSProductVersion .LessThan (* semver .New ("13.5.0" )) {
958+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for macOS prior to 13.5)" , QEMU )
959+ return QEMU
960+ }
961+ // Use QEMU if the config depends on QEMU
962+ for i , f := range []* LimaYAML {o , y , d } {
963+ if f .Arch != nil && ! IsNativeArch (* f .Arch ) {
964+ logrus .Debugf ("ResolveVMType: resolved VMType %q (non-native arch=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , * f .Arch , i )
965+ return QEMU
966+ }
967+ if f .Firmware .LegacyBIOS != nil && * f .Firmware .LegacyBIOS {
968+ logrus .Debugf ("ResolveVMType: resolved VMType %q (firmware.legacyBIOS is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , i )
969+ return QEMU
970+ }
971+ if f .MountType != nil && * f .MountType == NINEP {
972+ logrus .Debugf ("ResolveVMType: resolved VMType %q (mountType=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , NINEP , i )
973+ return QEMU
974+ }
975+ if f .Audio .Device != nil {
976+ switch * f .Audio .Device {
977+ case "" , "none" , "default" , "vz" :
978+ // NOP
979+ default :
980+ logrus .Debugf ("ResolveVMType: resolved VMType %q (audio.device=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , * f .Audio .Device , i )
981+ return QEMU
982+ }
983+ }
984+ if f .Video .Display != nil {
985+ switch * f .Video .Display {
986+ case "" , "none" , "default" , "vz" :
987+ // NOP
988+ default :
989+ logrus .Debugf ("ResolveVMType: resolved VMType %q (video.display=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , * f .Video .Display , i )
990+ return QEMU
991+ }
992+ }
993+ }
994+ // Use VZ if the config is compatible with VZ
995+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for macOS 13.5 and later)" , VZ )
996+ return VZ
997+ default :
998+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for GOOS=%q)" , QEMU , runtime .GOOS )
910999 return QEMU
9111000 }
912- return NewVMType (* s )
9131001}
9141002
9151003func ResolveOS (s * string ) OS {
0 commit comments