From 51624461161d7c785043f7c3bb175678829e9864 Mon Sep 17 00:00:00 2001 From: Chance Zibolski Date: Mon, 14 Nov 2022 11:52:09 -0800 Subject: [PATCH] Add support for Rosetta with vmType: vz Signed-off-by: Chance Zibolski --- examples/experimental/vz.yaml | 6 ++- .../boot/05-rosetta-volume.sh | 16 ++++++++ pkg/cidata/cidata.TEMPLATE.d/lima.env | 2 + pkg/cidata/cidata.go | 2 + pkg/cidata/template.go | 2 + pkg/limayaml/limayaml.go | 6 +++ pkg/vz/errors.go | 8 ++++ pkg/vz/rosetta_directory_share.go | 12 ++++++ pkg/vz/rosseta_directory_share_arm64.go | 39 +++++++++++++++++++ pkg/vz/vm_darwin.go | 13 +++++++ 10 files changed, 105 insertions(+), 1 deletion(-) create mode 100755 pkg/cidata/cidata.TEMPLATE.d/boot/05-rosetta-volume.sh create mode 100644 pkg/vz/errors.go create mode 100644 pkg/vz/rosetta_directory_share.go create mode 100644 pkg/vz/rosseta_directory_share_arm64.go diff --git a/examples/experimental/vz.yaml b/examples/experimental/vz.yaml index d584f6244113..44625596d465 100644 --- a/examples/experimental/vz.yaml +++ b/examples/experimental/vz.yaml @@ -1,6 +1,10 @@ # Example to run ubuntu using vmType: vz instead of qemu (Default) -# This example requires Lima v0.14.0 or later. +# This example requires Lima v0.14.0 or later and MacOS Ventura. vmType: "vz" +rosetta: + enabled: true + binfmt: true + images: - location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img" arch: "x86_64" diff --git a/pkg/cidata/cidata.TEMPLATE.d/boot/05-rosetta-volume.sh b/pkg/cidata/cidata.TEMPLATE.d/boot/05-rosetta-volume.sh new file mode 100755 index 000000000000..6e8e3489b830 --- /dev/null +++ b/pkg/cidata/cidata.TEMPLATE.d/boot/05-rosetta-volume.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -eu + +if [ "$LIMA_CIDATA_ROSETTA_ENABLED" != "true" ]; then + exit 0 +fi + +mkdir -p /mnt/lima-rosetta +mount -t virtiofs vz-rosetta /mnt/lima-rosetta + +if [ "$LIMA_CIDATA_ROSETTA_BINFMT" = "true" ]; then + echo \ + ':rosetta:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00:\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/mnt/lima-rosetta/rosetta:OCF' \ + >/proc/sys/fs/binfmt_misc/register +fi diff --git a/pkg/cidata/cidata.TEMPLATE.d/lima.env b/pkg/cidata/cidata.TEMPLATE.d/lima.env index a688ff09b377..941286c85192 100644 --- a/pkg/cidata/cidata.TEMPLATE.d/lima.env +++ b/pkg/cidata/cidata.TEMPLATE.d/lima.env @@ -27,3 +27,5 @@ LIMA_CIDATA_SLIRP_GATEWAY={{.SlirpGateway}} LIMA_CIDATA_SLIRP_IP_ADDRESS={{.SlirpIPAddress}} LIMA_CIDATA_UDP_DNS_LOCAL_PORT={{.UDPDNSLocalPort}} LIMA_CIDATA_TCP_DNS_LOCAL_PORT={{.TCPDNSLocalPort}} +LIMA_CIDATA_ROSETTA_ENABLED={{.RosettaEnabled}} +LIMA_CIDATA_ROSETTA_BINFMT={{.RosettaBinFmt}} diff --git a/pkg/cidata/cidata.go b/pkg/cidata/cidata.go index 5ea42aefcf3b..a25ab6aba22c 100644 --- a/pkg/cidata/cidata.go +++ b/pkg/cidata/cidata.go @@ -126,6 +126,8 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort SlirpGateway: networks.SlirpGateway, SlirpDNS: networks.SlirpDNS, SlirpIPAddress: networks.SlirpIPAddress, + RosettaEnabled: y.Rosetta.Enabled, + RosettaBinFmt: y.Rosetta.BinFmt, } // change instance id on every boot so network config will be processed again diff --git a/pkg/cidata/template.go b/pkg/cidata/template.go index ce6de21e4ffa..dff7a0a3ebe1 100644 --- a/pkg/cidata/template.go +++ b/pkg/cidata/template.go @@ -71,6 +71,8 @@ type TemplateArgs struct { CACerts CACerts HostHomeMountPoint string BootCmds []BootCmds + RosettaEnabled bool + RosettaBinFmt bool } func ValidateTemplateArgs(args TemplateArgs) error { diff --git a/pkg/limayaml/limayaml.go b/pkg/limayaml/limayaml.go index ecff11629c58..3cacdf7f77ec 100644 --- a/pkg/limayaml/limayaml.go +++ b/pkg/limayaml/limayaml.go @@ -33,6 +33,7 @@ type LimaYAML struct { // `useHostResolver` was deprecated in Lima v0.8.1, removed in Lima v0.14.0. Use `hostResolver.enabled` instead. PropagateProxyEnv *bool `yaml:"propagateProxyEnv,omitempty" json:"propagateProxyEnv,omitempty"` CACertificates CACertificates `yaml:"caCerts,omitempty" json:"caCerts,omitempty"` + Rosetta Rosetta `yaml:"rosetta,omitempty" json:"rosetta,omitempty"` } type Arch = string @@ -52,6 +53,11 @@ const ( VZ VMType = "vz" ) +type Rosetta struct { + Enabled bool `yaml:"enabled" json:"enabled"` + BinFmt bool `yaml:"binfmt" json:"binfmt"` +} + type File struct { Location string `yaml:"location" json:"location"` // REQUIRED Arch Arch `yaml:"arch,omitempty" json:"arch,omitempty"` diff --git a/pkg/vz/errors.go b/pkg/vz/errors.go new file mode 100644 index 000000000000..080ef640c882 --- /dev/null +++ b/pkg/vz/errors.go @@ -0,0 +1,8 @@ +//go:build darwin +// +build darwin + +package vz + +import "errors" + +var errRosettaUnsupported = errors.New("Rosetta is unsupported on non-ARM64 hosts") diff --git a/pkg/vz/rosetta_directory_share.go b/pkg/vz/rosetta_directory_share.go new file mode 100644 index 000000000000..30e0ef487603 --- /dev/null +++ b/pkg/vz/rosetta_directory_share.go @@ -0,0 +1,12 @@ +//go:build darwin && !arm64 +// +build darwin,!arm64 + +package vz + +import ( + "github.com/Code-Hex/vz/v3" +) + +func createRosettaDirectoryShareConfiguration() (*vz.VirtioFileSystemDeviceConfiguration, error) { + return nil, errRosettaUnsupported +} diff --git a/pkg/vz/rosseta_directory_share_arm64.go b/pkg/vz/rosseta_directory_share_arm64.go new file mode 100644 index 000000000000..c56b91e8ff3d --- /dev/null +++ b/pkg/vz/rosseta_directory_share_arm64.go @@ -0,0 +1,39 @@ +//go:build darwin && arm64 +// +build darwin,arm64 + +package vz + +import ( + "fmt" + + "github.com/Code-Hex/vz/v3" + "github.com/sirupsen/logrus" +) + +func createRosettaDirectoryShareConfiguration() (*vz.VirtioFileSystemDeviceConfiguration, error) { + config, err := vz.NewVirtioFileSystemDeviceConfiguration("vz-rosetta") + if err != nil { + return nil, fmt.Errorf("failed to create a new virtio file system configuration: %w", err) + } + availability := vz.LinuxRosettaDirectoryShareAvailability() + switch availability { + case vz.LinuxRosettaAvailabilityNotSupported: + return nil, errRosettaUnsupported + case vz.LinuxRosettaAvailabilityNotInstalled: + logrus.Info("Installing rosetta...") + if err := vz.LinuxRosettaDirectoryShareInstallRosetta(); err != nil { + return nil, fmt.Errorf("failed to install rosetta: %w", err) + } + logrus.Info("Rosetta installation complete.") + case vz.LinuxRosettaAvailabilityInstalled: + // nothing to do + } + + rosettaShare, err := vz.NewLinuxRosettaDirectoryShare() + if err != nil { + return nil, fmt.Errorf("failed to create a new rosetta directory share: %w", err) + } + config.SetDirectoryShare(rosettaShare) + + return config, nil +} diff --git a/pkg/vz/vm_darwin.go b/pkg/vz/vm_darwin.go index aef6707a7888..e60987741fbf 100644 --- a/pkg/vz/vm_darwin.go +++ b/pkg/vz/vm_darwin.go @@ -345,6 +345,19 @@ func attachFolderMounts(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineCo config.SetDirectoryShare(share) mounts[i] = config } + + if driver.Yaml.Rosetta.Enabled { + logrus.Info("Setting up Rosetta share") + directorySharingDeviceConfig, err := createRosettaDirectoryShareConfiguration() + if errors.Is(err, errRosettaUnsupported) { + logrus.Warnf("Unable to configure Rosetta: %s", err) + } else if err != nil { + return err + } else { + mounts = append(mounts, directorySharingDeviceConfig) + } + } + vmConfig.SetDirectorySharingDevicesVirtualMachineConfiguration(mounts) return nil }