@@ -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
}
@@ -924,11 +926,96 @@ func NewVMType(driver string) VMType {
924
926
}
925
927
}
926
928
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 )
929
1017
return QEMU
930
1018
}
931
- return NewVMType (* s )
932
1019
}
933
1020
934
1021
func ResolveOS (s * string ) OS {
0 commit comments