11 Commits

Author SHA1 Message Date
f053762c4e Harden failure paths found in the reliability review
The success paths were fine; several failure paths drew a confident
conclusion without checking the thing they waited for.

Registry (was: any parse error killed the whole server, since load() runs
in the lifespan):
- quarantine an unreadable file and start empty instead of raising, so the
  tools that stop runaway VMs keep working when bookkeeping is damaged
- skip malformed or invalidly-named records rather than failing the load;
  report both through list_vms as registry_warnings
- read-modify-write under an exclusive flock so a second instance merges
  instead of clobbering, with a PID-unique temp file
- drop the lifespan shutdown save, which could resurrect deleted records
- version the schema and round-trip unknown record fields

sandbox_destroy (the only tool that deletes files):
- verify the process actually died, escalating to SIGKILL, and refuse to
  delete an overlay QEMU still holds open
- assert the target is inside the VM state tree before rmtree
- report cleanup errors instead of swallowing them; destroyed now reflects
  what happened

Launch races:
- reserve the name before the first await so two concurrent launches cannot
  race over one set of sockets
- refuse to unlink a QMP socket that is still accepting connections
- register the VM with a warning rather than orphaning it when the pidfile
  is unreadable but QEMU is up

Guest agent and QMP:
- bound every guest-agent call, not just the handshake; cap max_bytes and
  stop guest_file_read spinning on a zero-progress agent
- serialize QMP sessions per VM (the monitor is single-client) and say
  "another operation holds it" instead of "the VM has likely exited"
- poll liveness while waiting for SHUTDOWN so a crashed VM is reported as
  exited rather than as a guest ignoring ACPI
- default command timeout, with a longer bound for savevm/loadvm
- stricter snapshot tags; log destructive operations to stderr

Adds tests/test_reliability.py covering the conditions above.
2026-08-17 15:53:09 -06:00
1dbe453731 Add vm_mouse_move: chunked relative PS/2 motion with corner homing and clicks 2026-08-17 10:39:23 -06:00
7020f96fa2 Expand server instructions: sandboxes, see & drive loop, port-forward forms 2026-08-17 00:50:31 -06:00
9319fefc7c Document sandbox tools and port-forward forms in README 2026-08-17 00:37:17 -06:00
ea0deb8e70 Reuse dead VM names in sandbox auto-naming 2026-08-17 00:32:32 -06:00
f3c5e2ce48 Add auto/collision-checked port forwards and one-shot sandbox_vm/sandbox_destroy 2026-08-17 00:31:01 -06:00
9d20f28998 Add see & drive tools: screenshot, keyboard/mouse injection, serial console 2026-08-16 23:47:58 -06:00
08f5e4329e Surface daemonized QEMU launch errors from the -D logfile 2026-08-16 22:10:08 -06:00
0dfee9a589 Add project-scoped MCP config 2026-08-16 22:03:16 -06:00
7377ad5dd8 Add test suite: fake QMP client, launcher table tests, real qemu-img and boot integration 2026-08-16 21:05:02 -06:00
8e7286c474 Initial mcqemu: FastMCP server with lifecycle, image, snapshot, and guest-agent tools 2026-08-16 21:00:01 -06:00