summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/qga_snip.py
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-28 13:10:58 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-28 13:10:58 -0400
commit375d627a7abd0c07b95d70395ce89b2f4c42d106 (patch)
tree228ff83fcfa9c7316e545c2af921c69186cb72c7 /tools/guest-diag/qga_snip.py
parent701346522d9e152049ec6a4fdb99448937803e60 (diff)
downloadopen-iov-375d627a7abd0c07b95d70395ce89b2f4c42d106.tar.gz
open-iov-375d627a7abd0c07b95d70395ce89b2f4c42d106.zip
tools/guest-diag: guest frame capture + input driving for the two-VM GZDoom video (Xvfb XGetImage capture, SDL present shim, window resize, XTEST input, QGA range fetch)
Diffstat (limited to 'tools/guest-diag/qga_snip.py')
-rw-r--r--tools/guest-diag/qga_snip.py41
1 files changed, 41 insertions, 0 deletions
diff --git a/tools/guest-diag/qga_snip.py b/tools/guest-diag/qga_snip.py
new file mode 100644
index 0000000..cd3b992
--- /dev/null
+++ b/tools/guest-diag/qga_snip.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+# Fetch a byte range from a guest file via the QEMU guest agent.
+# Usage: qga_snip.py <guest_path> <offset> <length> <host_out>
+import base64
+import json
+import socket
+import sys
+
+GUEST, OFF, LEN, HOST = sys.argv[1], int(sys.argv[2]), int(sys.argv[3]), sys.argv[4]
+import os
+SOCK = os.environ.get("QGA_SOCK", "/tmp/qemu-guest-agent.sock")
+
+
+def recv_line(s):
+ buf = b""
+ while b"\n" not in buf:
+ c = s.recv(65536)
+ if not c:
+ break
+ buf += c
+ return buf.split(b"\n", 1)[0]
+
+
+def cmd(s, obj):
+ s.sendall((json.dumps(obj) + "\r\n").encode())
+ return json.loads(recv_line(s))
+
+
+s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+s.settimeout(30.0)
+s.connect(SOCK)
+h = cmd(s, {"execute": "guest-file-open",
+ "arguments": {"path": GUEST, "mode": "r"}})["return"]
+cmd(s, {"execute": "guest-file-seek",
+ "arguments": {"handle": h, "offset": OFF, "whence": 0}})
+r = cmd(s, {"execute": "guest-file-read",
+ "arguments": {"handle": h, "count": LEN}})
+data = base64.b64decode(r["return"].get("buf-b64", ""))
+open(HOST, "wb").write(data)
+cmd(s, {"execute": "guest-file-close", "arguments": {"handle": h}})
+print(f"GOT {len(data)} bytes @ {OFF} -> {HOST}")