From ee5153c5451a3850b788a14d3dba34a953582cad Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Tue, 7 May 2024 13:44:36 -0400 Subject: [PATCH] machine: Add LibKrun provider detection Adds provider detection for LibKrun in `pkg/provider/platform_darwin.go`. Changes the macOS version check to 13 instead of 11, and now uses the `semver` package to verify current version. Signed-off-by: Jake Correnti --- pkg/machine/provider/platform_darwin.go | 74 ++++++++++++++++++------- pkg/machine/provider/platform_test.go | 13 ++++- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/pkg/machine/provider/platform_darwin.go b/pkg/machine/provider/platform_darwin.go index 51e697f39a..c868957b24 100644 --- a/pkg/machine/provider/platform_darwin.go +++ b/pkg/machine/provider/platform_darwin.go @@ -2,13 +2,13 @@ package provider import ( "bytes" - "errors" "fmt" "os" "os/exec" - "strconv" + "runtime" "strings" + "github.com/blang/semver/v4" "github.com/containers/common/pkg/config" "github.com/containers/podman/v5/pkg/machine/applehv" "github.com/containers/podman/v5/pkg/machine/define" @@ -44,42 +44,78 @@ func Get() (vmconfigs.VMProvider, error) { // SupportedProviders returns the providers that are supported on the host operating system func SupportedProviders() []define.VMType { - return []define.VMType{define.AppleHvVirt} + supported := []define.VMType{define.AppleHvVirt} + if runtime.GOARCH == "arm64" { + return append(supported, define.LibKrun) + } + return supported } // InstalledProviders returns the supported providers that are installed on the host func InstalledProviders() ([]define.VMType, error) { + installed := []define.VMType{} + + appleHvInstalled, err := appleHvInstalled() + if err != nil { + return nil, err + } + if appleHvInstalled { + installed = append(installed, define.AppleHvVirt) + } + + libKrunInstalled, err := libKrunInstalled() + if err != nil { + return nil, err + } + if libKrunInstalled { + installed = append(installed, define.LibKrun) + } + + return installed, nil +} + +func appleHvInstalled() (bool, error) { var outBuf bytes.Buffer - // Apple's Virtualization.Framework is only supported on MacOS 11.0+ - const SupportedMacOSVersion = 11 + // Apple's Virtualization.Framework is only supported on MacOS 11.0+, + // but to use EFI MacOS 13.0+ is required + expectedVer, err := semver.Make("13.0.0") + if err != nil { + return false, err + } cmd := exec.Command("sw_vers", "--productVersion") cmd.Stdout = &outBuf if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("unable to check current macOS version using `sw_vers --productVersion`: %s", err) + return false, fmt.Errorf("unable to check current macOS version using `sw_vers --productVersion`: %s", err) } // the output will be in the format of MAJOR.MINOR.PATCH - output := outBuf.String() - idx := strings.Index(output, ".") - if idx < 0 { - return nil, errors.New("invalid output provided by sw_vers --productVersion") - } - majorString := output[:idx] - majorInt, err := strconv.Atoi(majorString) + output := strings.TrimSuffix(outBuf.String(), "\n") + currentVer, err := semver.Make(output) if err != nil { - return nil, err + return false, err } - if majorInt >= SupportedMacOSVersion { - return []define.VMType{define.AppleHvVirt}, nil + return currentVer.GTE(expectedVer), nil +} + +func libKrunInstalled() (bool, error) { + if runtime.GOARCH != "arm64" { + return false, nil + } + + // need to verify that krunkit, virglrenderer, and libkrun-efi are installed + cfg, err := config.Default() + if err != nil { + return false, err } - return []define.VMType{}, nil + _, err = cfg.FindHelperBinary("krunkit", false) + return err == nil, nil } // HasPermsForProvider returns whether the host operating system has the proper permissions to use the given provider func HasPermsForProvider(provider define.VMType) bool { - // there are no permissions required for AppleHV - return provider == define.AppleHvVirt + // there are no permissions required for AppleHV or LibKrun + return provider == define.AppleHvVirt || provider == define.LibKrun } diff --git a/pkg/machine/provider/platform_test.go b/pkg/machine/provider/platform_test.go index 36621a2446..241aa322b2 100644 --- a/pkg/machine/provider/platform_test.go +++ b/pkg/machine/provider/platform_test.go @@ -11,7 +11,11 @@ import ( func TestSupportedProviders(t *testing.T) { switch runtime.GOOS { case "darwin": - assert.Equal(t, []define.VMType{define.AppleHvVirt}, SupportedProviders()) + if runtime.GOARCH == "arm64" { + assert.Equal(t, []define.VMType{define.AppleHvVirt, define.LibKrun}, SupportedProviders()) + } else { + assert.Equal(t, []define.VMType{define.AppleHvVirt}, SupportedProviders()) + } case "windows": assert.Equal(t, []define.VMType{define.WSLVirt, define.HyperVVirt}, SupportedProviders()) case "linux": @@ -24,6 +28,7 @@ func TestInstalledProviders(t *testing.T) { assert.Nil(t, err) switch runtime.GOOS { case "darwin": + // TODO: need to verify if an arm64 machine reports {applehv, libkrun} assert.Equal(t, []define.VMType{define.AppleHvVirt}, installed) case "windows": provider, err := Get() @@ -55,6 +60,9 @@ func TestBadSupportedProviders(t *testing.T) { switch runtime.GOOS { case "darwin": assert.NotEqual(t, []define.VMType{define.QemuVirt}, SupportedProviders()) + if runtime.GOARCH != "arm64" { + assert.NotEqual(t, []define.VMType{define.AppleHvVirt, define.LibKrun}, SupportedProviders()) + } case "windows": assert.NotEqual(t, []define.VMType{define.QemuVirt}, SupportedProviders()) case "linux": @@ -68,6 +76,9 @@ func TestBadInstalledProviders(t *testing.T) { switch runtime.GOOS { case "darwin": assert.NotEqual(t, []define.VMType{define.QemuVirt}, installed) + if runtime.GOARCH != "arm64" { + assert.NotEqual(t, []define.VMType{define.AppleHvVirt, define.LibKrun}, installed) + } case "windows": assert.NotContains(t, installed, define.QemuVirt) case "linux":