Run fstrim in a VM via the guest agent #31

Merged
Duckboot merged 1 commits from feat/vm-fstrim-19 into main 2026-11-03 01:33:20 +01:00
Owner

What

f on the info screen runs fstrim in a running VM that has the guest agent enabled.

  • Not eligible: a container gets an info note (containers have no guest agent, so use pct fstrim on the node). A stopped VM, or one without the agent, gets a warning, and nothing runs.
  • Eligible VM: a confirm comes first, then agent ping, then fstrim. The result reports the trimmed total in GiB or MiB, the number of paths, and any per-path errors.

Review fixes

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

Verification

  • 608 tests pass.
  • ruff check and ruff format --check report no issues.
  • betterleaks found no secrets.
  • Not run live, because the issue asks for approval before running fstrim on VM 108. Only the harmless agent ping was run there, and it answered {"result": "{}"}.

This PR is stacked on #30 → #29 → #28 → #27.

Closes #19

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com

## What `f` on the info screen runs fstrim in a running VM that has the guest agent enabled. - **Not eligible:** a container gets an info note (containers have no guest agent, so use `pct fstrim` on the node). A stopped VM, or one without the agent, gets a warning, and nothing runs. - **Eligible VM:** a confirm comes first, then `agent ping`, then `fstrim`. The result reports the trimmed total in GiB or MiB, the number of paths, and any per-path errors. ## Review fixes - **Odd agent output:** it no longer turns a finished trim into "fstrim failed". - Unreadable output gives "no results". - Odd entries are repaired: entries that are not dicts are dropped, a non-integer `trimmed` becomes 0, and a missing `path` becomes "?". - Well-formed entries are returned unchanged. - **Timeout:** fstrim gets a 30-minute CLI timeout instead of 330 s, because a large disk can take longer. - **Markup in notifications:** notifications are never parsed as markup (`GuestApp.notify` defaults to `markup=False`). Guest names, paths and CLI or agent errors are untrusted text, and a `[/b]` in them could break the toast. - **Before load:** pressing `f` before the info screen has loaded says "still loading" instead of a wrong "not running". - **Wording:** "1 path" in the singular. ## Verification - 608 tests pass. - `ruff check` and `ruff format --check` report no issues. - `betterleaks` found no secrets. - Not run live, because the issue asks for approval before running fstrim on VM 108. Only the harmless `agent ping` was run there, and it answered `{"result": "{}"}`. This PR is stacked on #30 → #29 → #28 → #27. Closes #19 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Duckboot added 5 commits 2026-11-03 01:08:40 +01:00
Warn on an untested cv4pve-cli version at startup
CI / pytest and ruff (pull_request) Successful in 4m42s
CI / pytest and ruff (push) Has been cancelled
e7569a7bf7
At startup the app runs `cv4pve-cli --version`. If it differs from
cli.TESTED_VERSION (2.4.0), a warning says which version was found
and which one was tested. The app parses output formats that are not
a stable API: the config list text, prune-backups as a JSON string,
the CT ip-addresses JSON string and the exit codes with --wait. A
newer cv4pve-cli could break them in confusing ways.

If cv4pve-cli cannot be run at all, an error says so once, instead of
every later call failing without explanation. The README notes the
tested version.

Closes #14

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Document installing cv4pve-tui as a uv tool
CI / pytest and ruff (pull_request) Successful in 4m40s
CI / pytest and ruff (push) Has been cancelled
ff6345c80f
The README gets an "Install" section: install with uv tool from the
Gitea repo or from a local checkout, then upgrade and uninstall. The
"Run" section says to use `cv4pve-tui` when installed and
`uv run cv4pve-tui` from a checkout.

Verified by installing into throwaway tool dirs (UV_TOOL_DIR and
UV_TOOL_BIN_DIR under /tmp): `uv tool install .` gave a cv4pve-tui
binary. Started from /tmp in a pseudo-terminal, it drew the guest
frame and ran until it was stopped. The pyproject metadata (entry
point, readme, requires-python) was already enough.

Closes #17

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add search and filter to the guest table
CI / pytest and ruff (pull_request) Successful in 4m48s
CI / pytest and ruff (push) Has been cancelled
d97ad22c78
/ opens a filter box under the guest table, and the table filters as
you type. Terms are separated by spaces, all must match, and case is
ignored:

- a plain term matches part of the name, the VMID or a tag
- is:running and is:stopped match the status
- type:lxc/ct and type:vm/qemu match the guest type

Enter keeps the filter and goes back to the table. Escape clears it,
from the box or from the table. The frame shows
"· filter: <text> · N of M". Actions only ever see the visible rows,
and the filter survives reloads and context switches.

Review fixes:
- Typing "[/b]" or "[/]" crashed the app, because the filter text went
  into the border subtitle, which Textual parses as markup. The
  subtitle is now plain text, so "[red]" is also shown literally.
- Escape on the table now clears a filter that was applied with Enter.
- guest_matches tolerates a None status or type.

Read-only live check on mainframe: "debian" gives 104, "type:vm" gives
108, "community-script is:running" gives 14 of 19, and "is:stopped"
gives 0 of 19.

Closes #16

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Edit autostart, startup order and tags from the info screen
CI / pytest and ruff (pull_request) Successful in 5m31s
CI / pytest and ruff (push) Has been cancelled
f5f3effce5
The info screen's Resources table shows Autostart (yes/no), Startup
(order, up and down delays) and Tags. o opens a dialog to change them.
Only keys that differ are sent, in one `set <kind> config` call
through the existing set_net. A confirm lists the old and new value
of each key.

Tags are removed with `--delete tags` on set config. The CLI also has
a `delete ct|vm ... tags` command, but it shares the form that
destroys the whole guest, so the app never uses it; nothing in the
code builds a delete ct|vm argv. Inputs are validated before sending:
startup values must be ints >= 0, and tags must match
[A-Za-z0-9_][A-Za-z0-9_+.-]*. They are split on ; , or whitespace and
deduplicated.

Live test on CT 104: onboot 1 -> 0, startup order=5,up=10, tag
tui-test added, then all set back through the dialog. The config
ended identical to the baseline.

Closes #18

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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
262441916c
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>
Duckboot merged commit 262441916c into main 2026-11-03 01:33:20 +01:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Duckboot/cv4pve-cli-tui#31