@@ -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 }
@@ -924,11 +926,96 @@ func NewVMType(driver string) VMType {
924926 }
925927}
926928
927- func ResolveVMType (s * string ) VMType {
928- if s == nil || * s == "" || * s == "default" {
929+ func isExistingInstanceDir (dir string ) bool {
930+ // existence of "lima.yaml" does not signify existence of the instance,
931+ // because the file is created during the initialization of the instance.
932+ for _ , f := range []string {
933+ filenames .HostAgentStdoutLog , filenames .HostAgentStderrLog ,
934+ filenames .VzIdentifier , filenames .BaseDisk , filenames .DiffDisk , filenames .CIDataISO ,
935+ } {
936+ file := filepath .Join (dir , f )
937+ if _ , err := os .Lstat (file ); ! errors .Is (err , os .ErrNotExist ) {
938+ return true
939+ }
940+ }
941+ return false
942+ }
943+
944+ func ResolveVMType (y , d , o * LimaYAML , filePath string ) VMType {
945+ // Check if the VMType is explicitly specified
946+ for i , f := range []* LimaYAML {o , y , d } {
947+ if f .VMType != nil && * f .VMType != "" && * f .VMType != "default" {
948+ logrus .Debugf ("ResolveVMType: resolved VMType %q (explicitly specified in []*LimaYAML{o,y,d}[%d])" , * f .VMType , i )
949+ return NewVMType (* f .VMType )
950+ }
951+ }
952+
953+ // If this is an existing instance, guess the VMType from the contents of the instance directory.
954+ if dir , basename := filepath .Split (filePath ); dir != "" && basename == filenames .LimaYAML && isExistingInstanceDir (dir ) {
955+ vzIdentifier := filepath .Join (dir , filenames .VzIdentifier ) // since Lima v0.14
956+ if _ , err := os .Lstat (vzIdentifier ); ! errors .Is (err , os .ErrNotExist ) {
957+ logrus .Debugf ("ResolveVMType: resolved VMType %q (existing instance, with %q)" , VZ , vzIdentifier )
958+ return VZ
959+ }
960+ logrus .Debugf ("ResolveVMType: resolved VMType %q (existing instance, without %q)" , QEMU , vzIdentifier )
961+ return QEMU
962+ }
963+
964+ // Resolve the best type, depending on GOOS
965+ switch runtime .GOOS {
966+ case "darwin" :
967+ macOSProductVersion , err := osutil .ProductVersion ()
968+ if err != nil {
969+ logrus .WithError (err ).Warn ("Failed to get macOS product version" )
970+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for unknown version of macOS)" , QEMU )
971+ return QEMU
972+ }
973+ // Virtualization.framework in macOS prior to 13.5 could not boot Linux kernel v6.2 on Intel
974+ // https://github.com/lima-vm/lima/issues/1577
975+ if macOSProductVersion .LessThan (* semver .New ("13.5.0" )) {
976+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for macOS prior to 13.5)" , QEMU )
977+ return QEMU
978+ }
979+ // Use QEMU if the config depends on QEMU
980+ for i , f := range []* LimaYAML {o , y , d } {
981+ if f .Arch != nil && ! IsNativeArch (* f .Arch ) {
982+ logrus .Debugf ("ResolveVMType: resolved VMType %q (non-native arch=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , * f .Arch , i )
983+ return QEMU
984+ }
985+ if f .Firmware .LegacyBIOS != nil && * f .Firmware .LegacyBIOS {
986+ logrus .Debugf ("ResolveVMType: resolved VMType %q (firmware.legacyBIOS is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , i )
987+ return QEMU
988+ }
989+ if f .MountType != nil && * f .MountType == NINEP {
990+ logrus .Debugf ("ResolveVMType: resolved VMType %q (mountType=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , NINEP , i )
991+ return QEMU
992+ }
993+ if f .Audio .Device != nil {
994+ switch * f .Audio .Device {
995+ case "" , "none" , "default" , "vz" :
996+ // NOP
997+ default :
998+ logrus .Debugf ("ResolveVMType: resolved VMType %q (audio.device=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , * f .Audio .Device , i )
999+ return QEMU
1000+ }
1001+ }
1002+ if f .Video .Display != nil {
1003+ switch * f .Video .Display {
1004+ case "" , "none" , "default" , "vz" :
1005+ // NOP
1006+ default :
1007+ logrus .Debugf ("ResolveVMType: resolved VMType %q (video.display=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , * f .Video .Display , i )
1008+ return QEMU
1009+ }
1010+ }
1011+ }
1012+ // Use VZ if the config is compatible with VZ
1013+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for macOS 13.5 and later)" , VZ )
1014+ return VZ
1015+ default :
1016+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for GOOS=%q)" , QEMU , runtime .GOOS )
9291017 return QEMU
9301018 }
931- return NewVMType (* s )
9321019}
9331020
9341021func ResolveOS (s * string ) OS {
0 commit comments