@@ -3,6 +3,7 @@ package limayaml
3
3
import (
4
4
"bytes"
5
5
"crypto/sha256"
6
+ "errors"
6
7
"fmt"
7
8
"net"
8
9
"os"
@@ -13,6 +14,7 @@ import (
13
14
"strings"
14
15
"text/template"
15
16
17
+ "github.com/coreos/go-semver/semver"
16
18
"github.com/docker/go-units"
17
19
"github.com/pbnjay/memory"
18
20
"github.com/sirupsen/logrus"
@@ -178,7 +180,7 @@ func FillDefault(y, d, o *LimaYAML, filePath string) {
178
180
if o .VMType != nil {
179
181
y .VMType = o .VMType
180
182
}
181
- y .VMType = ptr .Of (ResolveVMType (y . VMType ))
183
+ y .VMType = ptr .Of (ResolveVMType (y , d , o , filePath ))
182
184
if y .OS == nil {
183
185
y .OS = d .OS
184
186
}
@@ -905,11 +907,97 @@ func NewVMType(driver string) VMType {
905
907
}
906
908
}
907
909
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 )
910
999
return QEMU
911
1000
}
912
- return NewVMType (* s )
913
1001
}
914
1002
915
1003
func ResolveOS (s * string ) OS {
0 commit comments