demo: read the recovered content instead of a path

zerto_recover_file no longer writes the file to this host and hands back a
path, because a path here means nothing to a caller elsewhere and letting
the caller choose it was an arbitrary write. Both drivers still read
rec["path"], so they broke.

They now use the returned content. A small recovered_bytes() helper in each
driver decodes the text or base64 form, so the Windows copy-back keeps
shipping exact bytes rather than letting PowerShell rewrite line endings,
which is the bug that put a stray CR in an earlier take.

The Linux driver writes the bytes to a local file before scp, since scp
needs something on disk to send.

Verified against a live recovery: the helper returns 164 bytes whose sha256
matches the one the server reported, and the keys the on-screen show()
filter uses are all still present.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016yVfC5nvZowoLFnEGWhLGn
This commit is contained in:
2026-09-22 19:41:52 -04:00
co-authored by Claude Opus 5
parent e802d86196
commit 3e7b777e53
2 changed files with 30 additions and 6 deletions
+13 -2
View File
@@ -22,6 +22,17 @@ T0 = time.time()
STEP = [0]
def recovered_bytes(rec: dict) -> bytes:
"""zerto_recover_file returns the content now, not a path on the MCP host.
The server may be on another machine, so a path there is of no use here.
"""
import base64
if rec.get("encoding") == "base64":
return base64.b64decode(rec["content"])
return rec["content"].encode()
def w(s=""):
sys.stdout.write(s + "\n"); sys.stdout.flush()
@@ -155,7 +166,7 @@ async def main():
show(rec, keep=["ok", "bytes", "flr_path", "unmount"])
if not rec.get("ok"):
w(f"{RED} FLR failed{RST}"); return 1
body = Path(rec["path"]).read_text()
body = recovered_bytes(rec).decode()
w(f"{YEL} recovered file:{RST}")
for line in body.splitlines():
w(f"{GREEN}{BOLD} | {line}{RST}")
@@ -166,7 +177,7 @@ async def main():
# endings and appends one, which makes the restored file differ
# from what Zerto handed back. WriteAllBytes does not.
import base64
blob = Path(rec["path"]).read_bytes()
blob = recovered_bytes(rec)
b64 = base64.b64encode(blob).decode()
guest_ps(
f"[IO.File]::WriteAllBytes('{CFG['guest_path']}',"