Skip to content

Issue #4881 Add Rosetta 2 support for Apple Silicon#5181

Open
cpepper96 wants to merge 11 commits intocrc-org:mainfrom
cpepper96:main
Open

Issue #4881 Add Rosetta 2 support for Apple Silicon#5181
cpepper96 wants to merge 11 commits intocrc-org:mainfrom
cpepper96:main

Conversation

@cpepper96
Copy link
Copy Markdown

@cpepper96 cpepper96 commented Mar 16, 2026

Description

Fixes: #4881

Hi folks! This PR adds support for enabling Rosetta 2 on MacOS. The issue linked above does a great a job of describing the problem and solution.

TLDR: CRC currently uses QEMU on ARM64 MacOS to emulate x86 instructions. This has known limitations and some x86 containers are unable to run on CRC on Mac. Swapping Rosetta for QEMU should result in faster and more stable performance when trying to run x86 containers with CRC on Mac.

My team has been using this solution for the last couple of weeks with no issues except for one edge case. x86 binaries that use reexec() (e.g., buildah) have a known limitation under Rosetta due to kernel-level binfmt_misc + memfd interactions.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change
  • Chore (non-breaking change which doesn't affect codebase;
    test, version modification, documentation, etc.)

Proposed changes

  • Added new use-rosetta config field to enable this feature
  • Added preflight check to validate host os has rosetta
  • Updated Darwin vfkit driver to expose Rosetta virtiofs share
  • During CRC start configureRosetta will use sshRunner to:
  1. Mount the Rosetta virtiofs share into the CRC VM
  2. Create an additional shared bindmount at var/lib/rosetta/rosetta to be accessible across namespace boundaries (helpful for stuff like buildah which uses unshare()).
  3. Mask QEMU binfmt config and register Rosetta as the x86_64 binfmt handler with CFP flags

Testing

  1. Setup and start crc with crc config set use-rosetta true
  2. SSH into running CRC VM and confirm that Rosetta binfmt is registered and Rosetta is mounted
[core@crc ~]$ cat /proc/sys/fs/binfmt_misc/rosetta
enabled
interpreter /var/lib/rosetta/rosetta
flags: POCF
offset 0
magic 7f454c4602010100000000000000000002003e00
mask fffffffffffefe00fffffffffffffffffeffffff
[core@crc ~]$ mount | grep rosetta
rosetta on /run/media/rosetta type virtiofs (rw,relatime,context=system_u:object_r:bin_t:s0)
  1. Run a container on the VM that is known to fail on CRC with QEMU
sudo podman run --rm --platform linux/amd64 quay.io/coreos/etcd:v3.5.9 etcd

Contribution Checklist

  • I Keep It Small and Simple: The smaller the PR is, the easier it is to review and have it merged
  • I have performed a self-review of my code
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Which platform have you tested the code changes on?
    • Linux
    • Windows
    • MacOS

Summary by CodeRabbit

  • New Features
    • Added Rosetta emulation support on Apple Silicon Macs
    • New use-rosetta configuration option to enable x86-64 application compatibility
    • Introduced validation restricting Rosetta enablement to Apple Silicon platforms only
    • Added preflight checks to verify Rosetta runtime installation
    • Rosetta setup configured during virtual machine initialization when enabled

Jerod Culpepper and others added 11 commits February 11, 2026 07:12
Enable Apple's Rosetta 2 translation layer as an alternative to QEMU
for running x86_64/amd64 containers in the CRC VM on Apple Silicon Macs.
This resolves crashes (e.g. Go lfstack.push panics) caused by QEMU
user-mode emulation incompatibilities.

Adds `use-rosetta` config setting that attaches a Rosetta virtiofs share
to the vfkit VM and configures binfmt_misc inside the VM at each start.
Includes preflight check to ensure Rosetta is installed on the host.

Closes: crc-org#4881

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…roc writes

Replace direct writes to /proc/sys/fs/binfmt_misc with /etc/binfmt.d/
config files managed by systemd-binfmt. This follows the same patterns
used elsewhere in the codebase (tee for config files, systemctl for
services). Also changes the Rosetta mount SELinux context from
container_file_t to bin_t so systemd-binfmt (running as init_t) can
execute the interpreter when the binfmt F flag is set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… errors

Rosetta's virtiofs drops file connections across namespace boundaries
created by buildah/podman unshare, causing "No such file or directory"
during container builds. Bind mount the binary to /var/lib/rosetta with
shared propagation so it survives namespace transitions while preserving
the virtiofs transport Rosetta requires.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…check

Avoid silently accepting Apple's Rosetta license on behalf of the user.
The preflight now errors with instructions to install Rosetta manually.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add support for Rosetta 2 on MacOS
Add the preserve-argv[0] (P) flag to the Rosetta binfmt_misc
registration so /proc/self/exe resolves to the original binary
path instead of the Rosetta interpreter. This fixes reexec patterns
used by Go-based container tools (buildah, podman).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@openshift-ci openshift-ci bot requested review from cfergeau and gbraad March 16, 2026 23:16
@openshift-ci
Copy link
Copy Markdown

openshift-ci bot commented Mar 16, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign praveenkumar for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci
Copy link
Copy Markdown

openshift-ci bot commented Mar 16, 2026

Hi @cpepper96. Thanks for your PR.

I'm waiting for a crc-org member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 16, 2026

Walkthrough

This PR introduces Rosetta 2 emulation support for CRC on Apple Silicon macOS. It adds a new configuration setting with platform-specific validation, updates data structures to propagate the flag, implements Rosetta device setup in the VFKit driver, and adds corresponding preflight checks for Rosetta installation verification.

Changes

Cohort / File(s) Summary
Configuration & Validation
pkg/crc/config/settings.go, pkg/crc/config/validations.go
Added new UseRosetta config setting with platform-constrained validation that only permits Rosetta on Darwin/arm64 architecture.
Data Structures
pkg/crc/machine/types/types.go, pkg/crc/machine/config/config.go, cmd/crc/cmd/start.go
Added EnableRosetta boolean field to StartConfig and MachineConfig structs, with propagation through startup flow.
VFKit Driver & VM Setup
pkg/crc/machine/vfkit/driver_darwin.go, pkg/drivers/vfkit/driver_darwin.go, pkg/crc/machine/start.go
Introduced Rosetta device creation in VFKit driver and new configureRosetta() function that mounts Rosetta via virtiofs, creates bind mounts, and configures binfmt to route x86_64 binaries through Rosetta instead of QEMU emulation.
Preflight Checks
pkg/crc/preflight/preflight.go, pkg/crc/preflight/preflight_darwin.go, pkg/crc/preflight/preflight_checks_darwin.go, pkg/crc/preflight/preflight_linux.go, pkg/crc/preflight/preflight_windows.go
Updated function signatures across platforms to accept enableRosetta parameter; added checkRosettaInstalled() verification and conditional rosettaPreflightCheck in Darwin implementation.
Tests
pkg/crc/preflight/preflight_darwin_test.go, pkg/crc/preflight/preflight_windows_test.go
Updated test cases to accommodate additional enableRosetta parameter; adjusted expected check counts for Rosetta-enabled scenarios (21/20 vs. 20/19 for SystemNetworking/UserNetworking modes).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Config as Config System
    participant Start as Start Flow
    participant VFKit as VFKit Driver
    participant VM as QEMU/VFKit VM
    participant SSH as SSH Handler

    User->>Config: crc config set use-rosetta true
    Config->>Config: Validate (Darwin/arm64 only)
    
    User->>Start: crc start
    Start->>Config: Read EnableRosetta setting
    Start->>VFKit: CreateHost(machineConfig with EnableRosetta=true)
    
    VFKit->>VM: Create VM with Rosetta device via config.RosettaShareNew()
    VM-->>VFKit: VM Created
    
    Start->>SSH: Wait for SSH Ready
    SSH-->>Start: Connected
    
    Start->>VM: configureRosetta()
    VM->>VM: Mount Rosetta via virtiofs to /media/rosetta
    VM->>VM: Create /var/lib/rosetta bind mount target
    VM->>VM: Bind mount /media/rosetta/rosetta to /var/lib/rosetta
    VM->>VM: Mask qemu-x86_64-static binfmt config
    VM->>VM: Write rosetta-x86_64 binfmt config
    VM->>VM: Restart systemd-binfmt service
    VM-->>Start: Rosetta configured
    
    Start-->>User: Start complete (Rosetta enabled)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

kind/task, lgtm

Suggested reviewers

  • evidolob
  • anjannath

Poem

🐰 Hop, skip, and hop through Apple's Silicon land,
Rosetta now translates x86 as planned,
No more QEMU quirks to bear,
With binfmt magic in the air,
Container binaries run swift and fair! 🍎✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Issue #4881 Add Rosetta 2 support for Apple Silicon' clearly and concisely summarizes the main feature addition in the changeset.
Description check ✅ Passed The PR description covers all required template sections including problem statement, solution, type of change (feature), proposed changes, testing steps, and contribution checklist completion.
Linked Issues check ✅ Passed All coding requirements from issue #4881 are met: configuration toggle, Rosetta virtiofs device exposure, binfmt registration, and namespace preservation via bind-mount.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing Rosetta 2 support as specified in issue #4881; no extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use Trivy to scan for security misconfigurations and secrets in Infrastructure as Code files.

Add a .trivyignore file to your project to customize which findings Trivy reports.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/crc/preflight/preflight_windows.go (1)

214-216: ⚠️ Potential issue | 🔴 Critical

Compilation error: Missing argument in getAllPreflightChecks.

The call to getPreflightChecks on line 215 passes only 5 arguments, but the function signature on line 234 requires 6 parameters. This will fail to compile.

🐛 Proposed fix
 func getAllPreflightChecks() []Check {
-	return getPreflightChecks(true, network.UserNetworkingMode, constants.GetDefaultBundlePath(crcpreset.OpenShift), crcpreset.OpenShift, false)
+	return getPreflightChecks(true, network.UserNetworkingMode, constants.GetDefaultBundlePath(crcpreset.OpenShift), crcpreset.OpenShift, false, false)
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/crc/preflight/preflight_windows.go` around lines 214 - 216,
getAllPreflightChecks calls getPreflightChecks with only five arguments but the
getPreflightChecks signature expects six; update the call in
getAllPreflightChecks to pass the missing sixth parameter (match the exact type
and semantics required by getPreflightChecks) so the argument list and types
align with the function signature — locate getPreflightChecks and add the
appropriate value (constant, variable, or literal) to the call in
getAllPreflightChecks to fix the compilation error.
🧹 Nitpick comments (3)
pkg/crc/preflight/preflight_darwin_test.go (1)

26-28: Consider adding the Rosetta case for the alternate first-flag path too.

You now cover Rosetta-enabled counts for getPreflightChecks(false, ...). Adding the corresponding getPreflightChecks(true, ..., true) assertion would make this regression-proof if behavior diverges by that first flag later.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/crc/preflight/preflight_darwin_test.go` around lines 26 - 28, The test
currently asserts Rosetta-enabled preflight check counts only for
getPreflightChecks(false, ...); add the matching assertions for the alternate
first-flag path by calling getPreflightChecks(true,
network.SystemNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift),
preset.OpenShift, false, true) and getPreflightChecks(true,
network.UserNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift),
preset.OpenShift, false, true) and assert their lengths match the expected 21
and 20 respectively so both code paths are covered.
pkg/drivers/vfkit/driver_darwin.go (1)

236-236: Use a shared constant for the Rosetta mount tag.

Line 236 hardcodes "rosetta". Since guest-side mount/config must match this tag exactly, a shared constant helps avoid drift across files.

Suggested refactor
+const rosettaMountTag = "rosetta"
...
-		rosettaDev, err := config.RosettaShareNew("rosetta")
+		rosettaDev, err := config.RosettaShareNew(rosettaMountTag)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/drivers/vfkit/driver_darwin.go` at line 236, Replace the hardcoded
"rosetta" string in the call rosettaDev, err :=
config.RosettaShareNew("rosetta") with a shared constant (e.g.,
config.RosettaTag) so guest-side mount/config matches the same identifier
everywhere; update this call to use the constant from the config package and, if
the constant does not yet exist, add it in the config package (name it clearly
like RosettaTag or RosettaMountTag) and update any other callers to use that
constant to prevent drift.
pkg/crc/machine/start.go (1)

270-325: Consider using POSIX-compatible shell syntax for binfmt configuration.

The code uses here-string syntax (<<<) on line 314, which is a bash-specific feature and will fail on systems using only POSIX sh. While RHEL/Fedora-based systems typically include bash, this reduces portability.

♻️ Suggested improvement for broader shell compatibility
 	// Write Rosetta binfmt config pointing to the bind mount path
 	rosettaBinfmt := `: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:/var/lib/rosetta/rosetta:CFP`
 	if _, _, err := sshRunner.RunPrivileged("Writing Rosetta binfmt config",
-		fmt.Sprintf("tee /etc/binfmt.d/rosetta.conf <<< '%s'", rosettaBinfmt)); err != nil {
+		"sh", "-c", fmt.Sprintf("echo '%s' > /etc/binfmt.d/rosetta.conf", rosettaBinfmt)); err != nil {
 		return err
 	}

Note: Similar bash-ism appears at line 509 for chrony config; consider applying the same fix there.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/crc/machine/start.go` around lines 270 - 325, The use of a bash-only
here-string in configureRosetta should be replaced with a POSIX-compatible write
(e.g., use a heredoc or printf piped to tee) so that rosettaBinfmt is written to
/etc/binfmt.d/rosetta.conf without relying on <<<; update the RunPrivileged call
that currently uses fmt.Sprintf("tee /etc/binfmt.d/rosetta.conf <<< '%s'",
rosettaBinfmt) to instead pipe the content via a POSIX-safe form (for example:
printf '%s\n' '<content>' | tee /etc/binfmt.d/rosetta.conf or tee
/etc/binfmt.d/rosetta.conf <<'EOF' ... EOF) and apply the same change to the
similar chrony config write elsewhere in the code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/crc/config/validations.go`:
- Around line 159-162: The current platform check blocks any setting of the
rosetta flag on non-Apple-Silicon hosts; instead first validate the boolean
using ValidateBool(value), and only block when the validated value is true on
unsupported platforms. Concretely: call ValidateBool(value) (same symbol) to get
the parsed boolean and message, if parsing failed return that failure; if parsed
value is false return success (allow explicit false); if parsed value is true
then check runtime.GOOS and runtime.GOARCH and, if not darwin/arm64, return the
existing error message "Rosetta is only supported on Apple Silicon Macs",
otherwise return success.

In `@pkg/crc/preflight/preflight_checks_darwin.go`:
- Around line 232-234: The os.Stat(rosettaPath) error is currently always
reported as "Rosetta is not installed", which hides other failures; change the
handling so that if os.IsNotExist(err) you return the existing "Rosetta is not
installed" error, otherwise return a distinct error that includes the underlying
error (e.g., "failed to stat rosettaPath: <err>") so permission/I/O errors are
preserved; locate the os.Stat(rosettaPath) call in preflight_checks_darwin.go
and update the conditional to use os.IsNotExist(err) and return the
wrapped/original error for non-ENOENT cases.

---

Outside diff comments:
In `@pkg/crc/preflight/preflight_windows.go`:
- Around line 214-216: getAllPreflightChecks calls getPreflightChecks with only
five arguments but the getPreflightChecks signature expects six; update the call
in getAllPreflightChecks to pass the missing sixth parameter (match the exact
type and semantics required by getPreflightChecks) so the argument list and
types align with the function signature — locate getPreflightChecks and add the
appropriate value (constant, variable, or literal) to the call in
getAllPreflightChecks to fix the compilation error.

---

Nitpick comments:
In `@pkg/crc/machine/start.go`:
- Around line 270-325: The use of a bash-only here-string in configureRosetta
should be replaced with a POSIX-compatible write (e.g., use a heredoc or printf
piped to tee) so that rosettaBinfmt is written to /etc/binfmt.d/rosetta.conf
without relying on <<<; update the RunPrivileged call that currently uses
fmt.Sprintf("tee /etc/binfmt.d/rosetta.conf <<< '%s'", rosettaBinfmt) to instead
pipe the content via a POSIX-safe form (for example: printf '%s\n' '<content>' |
tee /etc/binfmt.d/rosetta.conf or tee /etc/binfmt.d/rosetta.conf <<'EOF' ...
EOF) and apply the same change to the similar chrony config write elsewhere in
the code.

In `@pkg/crc/preflight/preflight_darwin_test.go`:
- Around line 26-28: The test currently asserts Rosetta-enabled preflight check
counts only for getPreflightChecks(false, ...); add the matching assertions for
the alternate first-flag path by calling getPreflightChecks(true,
network.SystemNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift),
preset.OpenShift, false, true) and getPreflightChecks(true,
network.UserNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift),
preset.OpenShift, false, true) and assert their lengths match the expected 21
and 20 respectively so both code paths are covered.

In `@pkg/drivers/vfkit/driver_darwin.go`:
- Line 236: Replace the hardcoded "rosetta" string in the call rosettaDev, err
:= config.RosettaShareNew("rosetta") with a shared constant (e.g.,
config.RosettaTag) so guest-side mount/config matches the same identifier
everywhere; update this call to use the constant from the config package and, if
the constant does not yet exist, add it in the config package (name it clearly
like RosettaTag or RosettaMountTag) and update any other callers to use that
constant to prevent drift.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 07a9fe6e-c8bf-475b-b0b9-71d0f1971f16

📥 Commits

Reviewing files that changed from the base of the PR and between 26e31d0 and 4964fef.

📒 Files selected for processing (15)
  • cmd/crc/cmd/start.go
  • pkg/crc/config/settings.go
  • pkg/crc/config/validations.go
  • pkg/crc/machine/config/config.go
  • pkg/crc/machine/start.go
  • pkg/crc/machine/types/types.go
  • pkg/crc/machine/vfkit/driver_darwin.go
  • pkg/crc/preflight/preflight.go
  • pkg/crc/preflight/preflight_checks_darwin.go
  • pkg/crc/preflight/preflight_darwin.go
  • pkg/crc/preflight/preflight_darwin_test.go
  • pkg/crc/preflight/preflight_linux.go
  • pkg/crc/preflight/preflight_windows.go
  • pkg/crc/preflight/preflight_windows_test.go
  • pkg/drivers/vfkit/driver_darwin.go

Comment on lines +159 to +162
if runtime.GOOS != "darwin" || runtime.GOARCH != "arm64" {
return false, "Rosetta is only supported on Apple Silicon Macs"
}
return ValidateBool(value)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Allow explicit false for unsupported platforms.

Line 159 currently rejects the setting regardless of value on non-Apple-Silicon hosts. This prevents users from explicitly setting use-rosetta=false (useful for config portability/reset flows).

Suggested fix
 func validateRosetta(value interface{}) (bool, string) {
-	if runtime.GOOS != "darwin" || runtime.GOARCH != "arm64" {
-		return false, "Rosetta is only supported on Apple Silicon Macs"
-	}
-	return ValidateBool(value)
+	enabled, err := cast.ToBoolE(value)
+	if err != nil {
+		return false, "must be true or false"
+	}
+	if !enabled {
+		return true, ""
+	}
+	if runtime.GOOS != "darwin" || runtime.GOARCH != "arm64" {
+		return false, "Rosetta is only supported on Apple Silicon Macs"
+	}
+	return true, ""
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/crc/config/validations.go` around lines 159 - 162, The current platform
check blocks any setting of the rosetta flag on non-Apple-Silicon hosts; instead
first validate the boolean using ValidateBool(value), and only block when the
validated value is true on unsupported platforms. Concretely: call
ValidateBool(value) (same symbol) to get the parsed boolean and message, if
parsing failed return that failure; if parsed value is false return success
(allow explicit false); if parsed value is true then check runtime.GOOS and
runtime.GOARCH and, if not darwin/arm64, return the existing error message
"Rosetta is only supported on Apple Silicon Macs", otherwise return success.

Comment on lines +232 to +234
if _, err := os.Stat(rosettaPath); err != nil {
return fmt.Errorf("Rosetta is not installed, which is required for x86_64 emulation")
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Handle non-ENOENT errors separately in Rosetta preflight.

Line 232 currently treats every os.Stat failure as “not installed”. That can mask permission/I/O errors and mislead remediation.

Suggested fix
 func checkRosettaInstalled() error {
-	if _, err := os.Stat(rosettaPath); err != nil {
-		return fmt.Errorf("Rosetta is not installed, which is required for x86_64 emulation")
+	if _, err := os.Stat(rosettaPath); err != nil {
+		if os.IsNotExist(err) {
+			return fmt.Errorf("Rosetta is not installed, which is required for x86_64 emulation")
+		}
+		return fmt.Errorf("failed to verify Rosetta installation at %s: %w", rosettaPath, err)
 	}
 	return nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if _, err := os.Stat(rosettaPath); err != nil {
return fmt.Errorf("Rosetta is not installed, which is required for x86_64 emulation")
}
func checkRosettaInstalled() error {
if _, err := os.Stat(rosettaPath); err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("Rosetta is not installed, which is required for x86_64 emulation")
}
return fmt.Errorf("failed to verify Rosetta installation at %s: %w", rosettaPath, err)
}
return nil
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/crc/preflight/preflight_checks_darwin.go` around lines 232 - 234, The
os.Stat(rosettaPath) error is currently always reported as "Rosetta is not
installed", which hides other failures; change the handling so that if
os.IsNotExist(err) you return the existing "Rosetta is not installed" error,
otherwise return a distinct error that includes the underlying error (e.g.,
"failed to stat rosettaPath: <err>") so permission/I/O errors are preserved;
locate the os.Stat(rosettaPath) call in preflight_checks_darwin.go and update
the conditional to use os.IsNotExist(err) and return the wrapped/original error
for non-ENOENT cases.

@cfergeau
Copy link
Copy Markdown
Contributor

My team has been using this solution for the last couple of weeks

Could you share more details about your usecase for this? Last time we checked, running amd64 images in an openshift/microshift arm64 cluster was not supported, and there were complications with running images from other arches

@cpepper96
Copy link
Copy Markdown
Author

My team has been using this solution for the last couple of weeks

Could you share more details about your usecase for this? Last time we checked, running amd64 images in an openshift/microshift arm64 cluster was not supported, and there were complications with running images from other arches

We have arm64 macs as our dev laptops but our target environment is an amd64 openshift cluster. We are receiving amd64 container images from an upstream vendor (we don't control the build process). So our use case is local development and testing of these amd64 images on our arm64 macs prior to deploying to our amd64 openshift cluster.

@cfergeau
Copy link
Copy Markdown
Contributor

our use case is local development and testing of these amd64 images on our arm64 macs

can you be more specific about how you pull these images in the cluster and then run them? is this done using oc? The previous discussion around this was in #3483

@cpepper96
Copy link
Copy Markdown
Author

our use case is local development and testing of these amd64 images on our arm64 macs

can you be more specific about how you pull these images in the cluster and then run them? is this done using oc? The previous discussion around this was in #3483

sure! we push the x86 images to the internal image registry in the openshift local cluster and configure the deployments to pull from there. oc cli isn't used in the process, we use podman to push the images to the cluster.

@praveenkumar
Copy link
Copy Markdown
Member

We have arm64 macs as our dev laptops but our target environment is an amd64 openshift cluster.

@cpepper96 This target environment is not the mac-M1

testing of these amd64 images on our arm64 macs prior to deploying to our amd64 openshift cluster.

So when you testing those amd64 images before pushing/deploying to your amd64 cluster, does it really required the OCP cluster locally or you just need podman to test those on M1? I am thinking you might just need podman desktop on your dev machine to test the images locally before push to cluster which does support running the amd64 images.

@cpepper96
Copy link
Copy Markdown
Author

We have arm64 macs as our dev laptops but our target environment is an amd64 openshift cluster.

@cpepper96 This target environment is not the mac-M1

testing of these amd64 images on our arm64 macs prior to deploying to our amd64 openshift cluster.

So when you testing those amd64 images before pushing/deploying to your amd64 cluster, does it really required the OCP cluster locally or you just need podman to test those on M1? I am thinking you might just need podman desktop on your dev machine to test the images locally before push to cluster which does support running the amd64 images.

Hi @praveenkumar! We currently use podman/podman desktop and have used the workaround you suggested. There is no hard requirement to testing using OCP local but we have found it quite helpful to be able to do so and these changes enabled us to do that.

@praveenkumar
Copy link
Copy Markdown
Member

There is no hard requirement to testing using OCP local but we have found it quite helpful to be able to do so and these changes enabled us to do that.

@cpepper96 Happy to hear that you find OCP local helpful. I am just trying to understand the usecase which you described with OCP local because to me that is really just running a different arch container for which you really don't need a cluster but container runtime which podman desktop provides. Are you using this OCP local for podman operations also and not consuming the podman-machine?

@cpepper96
Copy link
Copy Markdown
Author

@cpepper96 Happy to hear that you find OCP local helpful. I am just trying to understand the usecase which you described with OCP local because to me that is really just running a different arch container for which you really don't need a cluster but container runtime which podman desktop provides. Are you using this OCP local for podman operations also and not consuming the podman-machine?

Yeah let me try to be more specific here. We are building applications to integrate with an existing platform that gets delivered to us as a Helm chart + images. Can't get too specific but its about 10 different microservices. So our two big use cases are:

  1. Platform engineers receive a new update of this platform. Typically they'll try to install/upgrade/test the new platform locally using OCP local prior to promoting update to our cloud environment.
  2. SWE are developing applications to integrate with this platform. They have OCP local + platform deployed for development prior to promoting changes to our cloud environment.

So the use case is not just running a different arch container on mac but being able to develop/test against a OCP based platform locally that is comprised of different arch containers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Rosetta 2 on macOS

4 participants