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 <jakecorrenti+github@proton.me>
This commit is contained in:
Jake Correnti
2024-05-07 13:44:36 -04:00
parent 97f3f9c34e
commit ee5153c545
2 changed files with 67 additions and 20 deletions

View File

@ -2,13 +2,13 @@ package provider
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"strconv" "runtime"
"strings" "strings"
"github.com/blang/semver/v4"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
"github.com/containers/podman/v5/pkg/machine/applehv" "github.com/containers/podman/v5/pkg/machine/applehv"
"github.com/containers/podman/v5/pkg/machine/define" "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 // SupportedProviders returns the providers that are supported on the host operating system
func SupportedProviders() []define.VMType { 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 // InstalledProviders returns the supported providers that are installed on the host
func InstalledProviders() ([]define.VMType, error) { 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 var outBuf bytes.Buffer
// Apple's Virtualization.Framework is only supported on MacOS 11.0+ // Apple's Virtualization.Framework is only supported on MacOS 11.0+,
const SupportedMacOSVersion = 11 // 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 := exec.Command("sw_vers", "--productVersion")
cmd.Stdout = &outBuf cmd.Stdout = &outBuf
if err := cmd.Run(); err != nil { 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 // the output will be in the format of MAJOR.MINOR.PATCH
output := outBuf.String() output := strings.TrimSuffix(outBuf.String(), "\n")
idx := strings.Index(output, ".") currentVer, err := semver.Make(output)
if idx < 0 {
return nil, errors.New("invalid output provided by sw_vers --productVersion")
}
majorString := output[:idx]
majorInt, err := strconv.Atoi(majorString)
if err != nil { if err != nil {
return nil, err return false, err
} }
if majorInt >= SupportedMacOSVersion { return currentVer.GTE(expectedVer), nil
return []define.VMType{define.AppleHvVirt}, nil }
func libKrunInstalled() (bool, error) {
if runtime.GOARCH != "arm64" {
return false, nil
} }
return []define.VMType{}, nil // need to verify that krunkit, virglrenderer, and libkrun-efi are installed
cfg, err := config.Default()
if err != nil {
return false, err
}
_, 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 // HasPermsForProvider returns whether the host operating system has the proper permissions to use the given provider
func HasPermsForProvider(provider define.VMType) bool { func HasPermsForProvider(provider define.VMType) bool {
// there are no permissions required for AppleHV // there are no permissions required for AppleHV or LibKrun
return provider == define.AppleHvVirt return provider == define.AppleHvVirt || provider == define.LibKrun
} }

View File

@ -11,7 +11,11 @@ import (
func TestSupportedProviders(t *testing.T) { func TestSupportedProviders(t *testing.T) {
switch runtime.GOOS { switch runtime.GOOS {
case "darwin": 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": case "windows":
assert.Equal(t, []define.VMType{define.WSLVirt, define.HyperVVirt}, SupportedProviders()) assert.Equal(t, []define.VMType{define.WSLVirt, define.HyperVVirt}, SupportedProviders())
case "linux": case "linux":
@ -24,6 +28,7 @@ func TestInstalledProviders(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
switch runtime.GOOS { switch runtime.GOOS {
case "darwin": case "darwin":
// TODO: need to verify if an arm64 machine reports {applehv, libkrun}
assert.Equal(t, []define.VMType{define.AppleHvVirt}, installed) assert.Equal(t, []define.VMType{define.AppleHvVirt}, installed)
case "windows": case "windows":
provider, err := Get() provider, err := Get()
@ -55,6 +60,9 @@ func TestBadSupportedProviders(t *testing.T) {
switch runtime.GOOS { switch runtime.GOOS {
case "darwin": case "darwin":
assert.NotEqual(t, []define.VMType{define.QemuVirt}, SupportedProviders()) assert.NotEqual(t, []define.VMType{define.QemuVirt}, SupportedProviders())
if runtime.GOARCH != "arm64" {
assert.NotEqual(t, []define.VMType{define.AppleHvVirt, define.LibKrun}, SupportedProviders())
}
case "windows": case "windows":
assert.NotEqual(t, []define.VMType{define.QemuVirt}, SupportedProviders()) assert.NotEqual(t, []define.VMType{define.QemuVirt}, SupportedProviders())
case "linux": case "linux":
@ -68,6 +76,9 @@ func TestBadInstalledProviders(t *testing.T) {
switch runtime.GOOS { switch runtime.GOOS {
case "darwin": case "darwin":
assert.NotEqual(t, []define.VMType{define.QemuVirt}, installed) assert.NotEqual(t, []define.VMType{define.QemuVirt}, installed)
if runtime.GOARCH != "arm64" {
assert.NotEqual(t, []define.VMType{define.AppleHvVirt, define.LibKrun}, installed)
}
case "windows": case "windows":
assert.NotContains(t, installed, define.QemuVirt) assert.NotContains(t, installed, define.QemuVirt)
case "linux": case "linux":