Run fstrim in a VM via the guest agent
CI / pytest and ruff (pull_request) Successful in 5m56s
CI / pytest and ruff (push) Successful in 6m14s

f on the info screen runs fstrim in a running VM with the guest agent
enabled. A container gets an info note (no guest agent; use pct
fstrim on the node). A stopped VM or one without an agent gets a
warning, and nothing runs. Otherwise a confirm comes first, then
agent ping and fstrim. The result reports the trimmed total
(GiB/MiB), the number of paths and any per-path errors.

Review fixes:
- Odd agent output no longer turns a finished trim into "fstrim
  failed". Unreadable output gives "no results". Odd entries are
  repaired: non-dict entries are dropped, a non-int trimmed becomes 0
  and a missing path becomes "?". Well-formed entries are returned
  unchanged.
- fstrim gets a 30-minute CLI timeout instead of 330 s, because a big
  disk can take longer.
- Notifications are never parsed as markup (GuestApp.notify defaults
  to markup=False). Guest names, paths and CLI or agent errors are
  untrusted text, so a "[/b]" in them could break the toast.
- f before the info screen has loaded says "still loading" instead of
  a wrong "not running".
- "1 path" in the singular.

Not run live: the issue asks for approval before fstrim on VM 108.
Only the harmless agent ping was run there, and it answered.

Closes #19

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit was merged in pull request #31.
This commit is contained in:
DuckbootandClaude Opus 5.5 committed 2026-11-03 01:08:30 +01:00
1 parent f5f3effce5
commit 262441916c
6 files changed
+540 -2

No files matched your search

+38
View File
@@ -697,3 +697,41 @@ CLI facts (read-only probes, PVE 9.2):
or None, `tags` string or None); invalid -> error notify, dialog stays, no call; no
change -> info notify; else `ConfirmScreen` titled "Boot and tags" listing old -> new
per key; yes -> busy guard, `cli.set_net(guest, changes)` via start_job, info reloads.
---
# fstrim in a VM via the guest agent (issue #19)
## Decision
Key `f` on the info screen, VMs only. Not run live (the issue asks for approval first);
tested with mocks.
CLI facts:
- `do vm agent ping <node> <vmid> -o json` -> `[{"key": "result", "value": "{}"}]` when the
agent answers (verified read-only on VM 108); non-zero exit when it does not.
- `do vm agent fstrim <node> <vmid> -o json` -> the same key/value shape; QEMU guest
agent's result is `{"paths": [{"path": "/", "trimmed": <bytes>, "minimum": 0}, ...]}`
(a path may carry `"error"` instead of `trimmed`). Not verified live.
- VM config `agent` = `enabled=1` (or `1`) when the agent is enabled.
### `cli.py`
- `agent_enabled(config) -> bool` - `agent` is `1` or starts with `1` / has `enabled=1`.
- `agent_ping(guest)` -> `do vm agent ping <node> <vmid> -o json`; CliError if the agent
does not answer.
- `fstrim(guest) -> list[dict]` -> `do vm agent fstrim <node> <vmid> -o json`; returns
the `paths` list parsed from the `result` value (`[]` if missing or unparseable).
### `app.py` (UI contract)
- `f` on the info screen:
- container -> info notify that containers have no guest agent (`pct fstrim` on the
node instead); nothing runs;
- VM not running, or `agent_enabled` false -> warning notify saying why; nothing runs;
- otherwise `ConfirmScreen` titled "fstrim" naming the VM and saying it frees unused
blocks on thin-provisioned storage and adds I/O load while it runs;
- yes -> busy guard, worker: `cli.agent_ping` then `cli.fstrim`; done notify with the
trimmed total in GiB/MiB and the number of paths (errors per path mentioned);
CliError -> error notify (ping failure says the agent did not answer).