Repository navigation
Health: read through the share and ask Samba before saying "Ready" - #46
Merged
Merged
Conversation
Every check of the SMB layout asked whether units are `active`, whether rclone's rc answers and where tmutil points - all over limactl's own network. A hung or dead punchfs/rclone FUSE chain, a cut vzNAT, a silent smbd and an inactive tm-bands-bind after vm-prepare-bundle all showed green "Ready" for up to 3 h. - ShareReadProbe: the status script reads 1 byte (read-only) of the image's band 0 through the share's path; detached reader, 10 s wait, single-flight lock, survives sudo use_pty's hangup, dead locks taken over. dead / failed / no answer / readable / no image yet. - SMBProbe: SMB2 NEGOTIATE from the Mac to <machine>:445 with a deadline; no route is "unknown" (Local Network privacy), answers reused for 60 s. - backup-health, vm-status, the menu bar and the machine card: "unknown" and "dead" are never green. - servicesHealthy takes bundlePrepared: an inactive bind is fine only before vm-prepare-bundle. - Status script limit 60 -> 90 s; NSLocalNetworkUsageDescription. No self-repair (separate decision); nothing in vm/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AU1Mhxpy65J75YYTkmt7NF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In the SMB layout every health check asked the machine whether its units are
active(systemctl is-active), whether rclone's rc answers, and wheretmutilpoints — all throughlimactl shell, i.e. ssh over Lima's own user network. Nothing read through the path Time Machine actually uses (Mac →vzNAT→ smbd →tm-bands-bind→ punchfs FUSE → rclone FUSE → Drive), and nothing talked SMB from the Mac.So these states showed "Ready" / green in the panel and a clean
vm-statusfor up to 3 h, until the age of the last backup crossed the threshold:active; rc still answers);Restart=alwaysrestarts rclone alone);activebut not answering;tm-bands-bindinactiveaftervm-prepare-bundle—servicesHealthypassed it as fine, and the bands then land on the machine's local disk instead of Drive.The Mac does not keep the share mounted (Time Machine mounts it per backup), so there is no "remount" on the Mac side; this PR is detection only.
What changes (mac-app only — nothing in
vm/)ShareReadProbe— part of the existing status script (limactl shell+sudo bash; onlyhead,sed,ls,sh, all in the Ubuntu 24.04 image, nothing installed). Reads 1 byte, read-only (head -c1) of/srv/tm-local/<image>/bands/0— through the bind, punchfs and rclone once the image is prepared. Band 0 is read on every mount, so it is in rclone's cache: a local read, not a download.hung <age>. A lock dir in/runkeeps it to one reader (a stuck reader is reported at once by every later run, not multiplied per panel refresh).use_ptyhangs up the script's process group when bash exits orlimactlis killed) and removes its own lock; a lock whose reader is gone (pid not alive, or no pid and older than 60 s) is taken over.vm-prepare-bundlean image directory without band 0 yet (Time Machine creating it) is "no image yet", not dead.SMBProbe— an SMB2 NEGOTIATE from the Mac to<machine address>:445(a TCP connect alone would be answered by the kernel even with smbd hung). Non-blocking socket +pollwith a 5 s deadline, off the main actor, EINTR retried. Never logs in. Verdicts: answers / refused / not SMB / no answer / unreachable (EHOSTUNREACH/ENETUNREACH) / no address. The panel reuses an answer for 60 s (smbd forks a child per connection); a failure is asked again at every refresh.BackupHealth(backup-health alarm),vm-status(two new lines, exit code), the menu-bar headline/badge/tone and the machine card in the window ("Services" row was "All running" in green; also fixes "Not running: " with an empty list).servicesHealthy(_:bundlePrepared:)— an inactivetm-bands-bindis fine only beforevm-prepare-bundle; prepared → failure; not known → unknown. Also used byvm-update's final check.VMStatus.reportTimeout60 → 90 s: probe 11 s + twocurl -m 20+limactlstart must fit, or a hung rclone turned the whole report into "no answer".NSLocalNetworkUsageDescriptionin Info.plist (see failure modes).Probe state → behaviour
Share read: readableshare-unreadable(from the first second)share-read-no-answer(never deferred)Samba from Mac: answerssmb-no-connection(deferred in the 20 min startup grace)smb-no-answer/smb-no-addresssmb-unreachable, names Local Network privacymachine-service-downThe probe alarms are raised only while every service is
active; with a service down the existing harder message speaks alone. Nothing is restarted or unmounted by this PR.Failure modes and limits
unreachable), not red, and the message says where to allow it. Could not be verified on a real Mac in this PR (no running of anything on the owner's Mac); see the checks below.headprocess in D state inside the machine (one, not one per run) — it also holds the FUSE mount busy, so a laterumount/restart of punchfs may get EBUSY until the read returns or the machine reboots.log level = 1should not log these.Tests
swift-format lint --strictclean.bundle.env/image dirs.BackupHealth.currentReport()and the panel controller (they call limactl/tmutil), EINTR inpoll.Release
mac-app/Sources/**andmac-app/Resources/**are inrelease.yml's push paths: merging this releases a new patch version (cask in the tap). Nothing invm/, so the machine template is unchanged andvm-updateis not needed.For the owner after merging
brew upgrade --cask renacode/tap/cloudmachine(and restart the app).cloudmachine-agent vm-status— expectShare read: readableandSamba from Mac: <address>:445 - answers.vm-statusfrom Terminal says "answers": allow CloudMachine in System Settings › Privacy & Security › Local Network (the app should ask once; the launchd agent may not be able to).Proposed next step (separate PR, needs the owner's decision): self-repair
Not in this PR. A draft was written and tested, then taken out on purpose — it restarts services on the only copy of the backup, possibly during a Time Machine run.
vm-guard(every 60 s) runs the same probe; on a confirmed dead read it queuessystemctl restart --no-block punchfs, which throughRequires=also restartstm-bands-bindandsmbdand leaves rclone (the upload and its 120 GB cache) alone..dead, never "no answer" (a hung read may be a write still going; a restart under it loses it); only with every serviceactive(a down service is systemd's, and right after boot the bind is not there yet); two dead reads in a row, a minute apart.fusermount -uzis lazy, so punchfs comes back, but the stuck reader stays until the machine reboots.🤖 Generated with Claude Code
https://claude.ai/code/session_01AU1Mhxpy65J75YYTkmt7NF