scripts/ci-qa-macos-dev.py
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env python3
"""Reject read-only guest mounts without changing the management VM's mounts.
Requires a healthy, installed macOS management VM and its root SSH access.
Each failure is injected in a private Linux mount namespace. Running services
and the host namespace retain their writable mounts.
"""
import argparse
from pathlib import Path
import shlex
import subprocess
import urllib.request
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--cli", type=Path, default=Path("target/debug/firecrab"))
args = parser.parse_args()
cli = str(args.cli.resolve())
script = (Path(__file__).parent / "micromanager/dev-macos-guest.sh").read_bytes()
def guest(*command, data=None):
return subprocess.run([cli, "service", "shell", *command], input=data,
capture_output=True, timeout=30)
def api():
with urllib.request.urlopen("http://127.0.0.1:5523/api/host", timeout=5) as response:
assert response.status == 200
def snapshot():
result = guest("sh", "-c", 'set -e; helper=firecrab-helper; '
'if [ "$(systemctl show -p LoadState --value firecrab-helper)" = not-found ]; '
'then helper=firecrab-net-helper; fi; '
'systemctl show -p MainPID firecrab-api "$helper"; '
"findmnt -n -o TARGET,OPTIONS --target /; "
"findmnt -n -o TARGET,OPTIONS --target /var/lib/firecrab")
if result.returncode:
raise RuntimeError(result.stderr.decode())
return result.stdout
api()
before = snapshot()
for mount in ["/", "/var/lib/firecrab", "/usr/local/lib"]:
for action in ["start", "debug"]:
target = shlex.quote(mount)
command = (f"mount --make-rprivate / && mount --bind {target} {target} && "
f"mount -o remount,bind,ro {target} && "
f"exec bash -s -- {action} 1.97.1 incoming-qa.tar")
result = guest("unshare", "--mount", "--", "sh", "-c", command, data=script)
if (result.returncode != 74 or b"not writable" not in result.stderr
or b"[PASS]" in result.stdout):
raise RuntimeError(f"{mount} {action}: exit={result.returncode}\n"
+ result.stdout.decode() + result.stderr.decode())
api()
if snapshot() != before:
raise RuntimeError("failure injection changed running services or host mounts")
print(f"[PASS] read-only {mount}: {action} rejected; API and mounts preserved")
if __name__ == "__main__":
main()