@@ -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"
@@ -11,6 +12,7 @@ import (
11
12
"strconv"
12
13
"text/template"
13
14
15
+ "github.com/coreos/go-semver/semver"
14
16
"github.com/docker/go-units"
15
17
"github.com/lima-vm/lima/pkg/networks"
16
18
"github.com/pbnjay/memory"
@@ -127,13 +129,7 @@ func defaultGuestInstallPrefix() string {
127
129
// - DNS are picked from the highest priority where DNS is not empty.
128
130
// - CACertificates Files and Certs are uniquely appended in d, y, o order
129
131
func FillDefault (y , d , o * LimaYAML , filePath string ) {
130
- if y .VMType == nil {
131
- y .VMType = d .VMType
132
- }
133
- if o .VMType != nil {
134
- y .VMType = o .VMType
135
- }
136
- y .VMType = pointer .String (ResolveVMType (y .VMType ))
132
+ y .VMType = pointer .String (ResolveVMType (y , d , o , filePath ))
137
133
if y .OS == nil {
138
134
y .OS = d .OS
139
135
}
@@ -860,11 +856,95 @@ func NewVMType(driver string) VMType {
860
856
}
861
857
}
862
858
863
- func ResolveVMType (s * string ) VMType {
864
- if s == nil || * s == "" || * s == "default" {
859
+ func isExistingInstanceDir (dir string ) bool {
860
+ // existence of "lima.yaml" does not signify existence of the instance,
861
+ // because the file is created during the initialization of the instance.
862
+ for _ , f := range []string {filenames .HostAgentStdoutLog , filenames .HostAgentStderrLog ,
863
+ filenames .VzIdentifier , filenames .BaseDisk , filenames .DiffDisk , filenames .CIDataISO } {
864
+ file := filepath .Join (dir , f )
865
+ if _ , err := os .Lstat (file ); ! errors .Is (err , os .ErrNotExist ) {
866
+ return true
867
+ }
868
+ }
869
+ return false
870
+ }
871
+
872
+ func ResolveVMType (y , d , o * LimaYAML , filePath string ) VMType {
873
+ // Check if the VMType is explicitly specified
874
+ for i , f := range []* LimaYAML {o , y , d } {
875
+ if f .VMType != nil && * f .VMType != "" && * f .VMType != "default" {
876
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (explicitly specified in []*LimaYAML{o,y,d}[%d])" , * f .VMType , i )
877
+ return NewVMType (* f .VMType )
878
+ }
879
+ }
880
+
881
+ // If this is an existing instance, guess the VMType from the contents of the instance directory.
882
+ // Note that the instance directory may be created by a previous version of Lima.
883
+ if dir , basename := filepath .Split (filePath ); dir != "" && basename == filenames .LimaYAML && isExistingInstanceDir (dir ) {
884
+ vzIdentifier := filepath .Join (dir , filenames .VzIdentifier )
885
+ if _ , err := os .Lstat (vzIdentifier ); ! errors .Is (err , os .ErrNotExist ) {
886
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (existing instance, with %q)" , VZ , vzIdentifier )
887
+ return VZ
888
+ }
889
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (existing instance, without %q)" , QEMU , vzIdentifier )
890
+ return QEMU
891
+ }
892
+
893
+ // Resolve the best type, depending on GOOS
894
+ switch runtime .GOOS {
895
+ case "darwin" :
896
+ macOSProductVersion , err := osutil .MacOSProductVersion ()
897
+ if err != nil {
898
+ logrus .WithError (err ).Warn ("Failed to get macOS product version" )
899
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for unknown version of macOS)" , QEMU )
900
+ return QEMU
901
+ }
902
+ // Virtualization.framework in macOS prior to 13.5 could not boot Linux kernel v6.2 on Intel
903
+ // https://github.com/lima-vm/lima/issues/1577
904
+ if macOSProductVersion .LessThan (* semver .New ("13.5.0" )) {
905
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for macOS prior to 13.5)" , QEMU )
906
+ return QEMU
907
+ }
908
+ // Use QEMU if the config depends on QEMU
909
+ for i , f := range []* LimaYAML {o , y , d } {
910
+ if f .Arch != nil && ! IsNativeArch (* f .Arch ) {
911
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (non-native arch=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , * f .Arch , i )
912
+ return QEMU
913
+ }
914
+ if f .Firmware .LegacyBIOS != nil && * f .Firmware .LegacyBIOS {
915
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (firmware.legacyBIOS is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , i )
916
+ return QEMU
917
+ }
918
+ if f .MountType != nil && * f .MountType == NINEP {
919
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (mountType=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , NINEP , i )
920
+ return QEMU
921
+ }
922
+ if f .Audio .Device != nil {
923
+ switch * f .Audio .Device {
924
+ case "" , "none" , "default" , "vz" :
925
+ // NOP
926
+ default :
927
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (audio.device=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , * f .Audio .Device , i )
928
+ return QEMU
929
+ }
930
+ }
931
+ if f .Video .Display != nil {
932
+ switch * f .Video .Display {
933
+ case "" , "none" , "default" , "vz" :
934
+ // NOP
935
+ default :
936
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (video.display=%q is specified in []*LimaYAML{o,y,d}[%d])" , QEMU , * f .Video .Display , i )
937
+ return QEMU
938
+ }
939
+ }
940
+ }
941
+ // Use VZ if the config is compatible with VZ
942
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for macOS 13.5 and later)" , VZ )
943
+ return VZ
944
+ default :
945
+ logrus .Debugf ("ResolveVMType: resolved VMType %q (default for GOOS=%q)" , QEMU , runtime .GOOS )
865
946
return QEMU
866
947
}
867
- return NewVMType (* s )
868
948
}
869
949
870
950
func ResolveOS (s * string ) OS {
0 commit comments