diff options
Diffstat (limited to 'vm-manager/README.md')
| -rw-r--r-- | vm-manager/README.md | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/vm-manager/README.md b/vm-manager/README.md new file mode 100644 index 0000000..e11b7f2 --- /dev/null +++ b/vm-manager/README.md @@ -0,0 +1,97 @@ +# vm-manager + +A drawer for libvirt virtual machines: state, live statistics, the actions +that make sense in the current state, and the snapshot list. It replaces the +menu half of `rofi-qemu.sh`, which could only ever show a list of strings. + + ┌─ buildsystem ───────────────── ● running ─┐ + │ CPU 4% RAM 0.7/16 GB Disk 60/130 GB │ + │ 172.16.34.20 │ + │ [Shutdown] [Reboot] [Suspend] [Reset] │ + │ snapshots │ + │ working 2026-03-06 10:27 │ + └───────────────────────────────────────────┘ + +## Running it + + qs -p . + +`SUPER+v` toggles it, through an IPC call, so the shell has to be running +first. Both are wired in the Hyprland config: + + -- autostart.lua + hl.exec_cmd("qs -p ~/Programming/GIT/quickshell/vm-manager") + + -- keybindings.lua + hl.bind(mainMod .. " + v", hl.dsp.exec_cmd( + "qs -p ~/Programming/GIT/quickshell/vm-manager ipc call panel toggle")) + +Write those two paths out in full in the real config: `exec_cmd` runs the +command directly, with no shell to expand `~`. + +The drawer opens on the monitor named by the `monitor` property at the top of +`VmPanel.qml`, defaulting to `DP-3`, and falls back to the first screen when +that one is not connected. It dims the rest of that monitor, because the +secondary screen usually has a real window on it, and takes keyboard focus so +Escape closes it and a delete can be confirmed by typing. + +## Where the numbers come from + +Everything shells out to `virsh`, the same commands the rofi script used. No +libvirt bindings, no new dependency. + +| Row | Source | +| ---------- | ------------------------------------------------- | +| state | `virsh domstats --state` | +| CPU | `cpu.time` sampled twice, divided by vCPU count | +| RAM | `virsh dommemstat`: `actual - usable` | +| Disk | guest agent `guest-get-fsinfo`, the `/` mount | +| address | `virsh domifaddr --source agent` | +| snapshots | `virsh snapshot-list` | + +Three of those need **qemu-guest-agent running inside the guest**. It is not +up for the first few seconds after boot, and another VM might not have it at +all, so those rows show `—` and the header says `agent starting` rather than +substituting a host-side figure. That distinction matters: libvirt's own +`balloon.current` is memory *allocated* to the VM, which on a VM that has +booted reads as 100% forever, and `block.0.allocation` is qcow2 growth on the +host, not usage inside the guest. Showing either in place of the real number +would be quietly wrong, so they are not used as a fallback. + +## Live without polling + +`virsh event --all --loop` streams lifecycle changes, and that process runs +for the whole session, panel open or not. Starting a VM from `virsh` or +virt-manager updates the drawer, and opening it shows current state rather +than whatever was true last time. + +Statistics do need sampling, on a 2 second timer, but only while the drawer +is open: `Virsh.sampling` follows the panel's `open`. A closed panel costs one +idle process waiting on an event socket. + +## Destructive actions + +`Reset`, `Force stop`, snapshot `Revert` and snapshot `Delete` each take one +confirmation click. `Delete VM` requires the machine's name to be typed, +because it runs `virsh undefine --remove-all-storage`, which erases the disk +image with no undo. The rofi script ran exactly that from a single menu +selection with no confirmation at all. + +Failures are reported with `notify-send`, since a `virsh` error otherwise has +nowhere to go: the process output is not attached to a terminal. + +## Theme + +`Theme.qml` is the copy from `volume-osd` with three colours added for state +dots (green running, yellow transitional, red crashed). The accent still comes +from `~/.cache/wal/udt-accent.rasi` and still tracks the wallpaper. + +The frosting is Hyprland's, matched on this window's namespace: + + hl.layer_rule({ + name = "blur-vm-manager", + match = { namespace = "^(quickshell-vm-manager)$" }, + blur = true, + xray = false, + ignore_alpha = 0.1, + }) |
