Show configured resources on the info screen

A new "Resources" section at the top of the info screen shows CPU
cores (with sockets for VMs), memory, swap for containers, and each
disk with its size. The disks are the same ones the edit dialog
offers, so cloud-init and CD drives are left out. A container without
a cores limit shows "unlimited".

The open info screen reloads after any guest job, so values edited
with e show up straight away.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit was merged in pull request #7.
This commit is contained in:
DuckbootandClaude Opus 5.5 committed 2026-11-02 22:42:38 +01:00
1 parent 0c3669271c
commit 5a3ca5a216
3 files changed
+107 -4

No files matched your search

+74
View File
@@ -2034,3 +2034,77 @@ async def test_footer_on_main_screen_shows_enter_for_info(fake):
await settle(app, pilot)
shown = [ab.binding for ab in app.active_bindings.values() if ab.binding.show]
assert any(b.key == "enter" and b.description == "Info" for b in shown)
# --- info screen: resources (CPU, RAM, disk) ------------------------------------------
def resource_rows(app):
t = app.screen.query_one("#resources", DataTable)
return {cells(t, i)[0]: cells(t, i)[1] for i in range(t.row_count)}
async def test_info_shows_vm_resources(fake):
fake.net_configs[108] = {"sockets": 2, "memory": 8192,
"scsi0": "local-lvm:vm-108-disk-0,discard=on,size=10G,ssd=1",
"ide2": "local-lvm:vm-108-cloudinit,media=cdrom"} # fmt: skip
app = make_app()
async with app.run_test(size=SIZE) as pilot:
await open_info(app, pilot) # VM 108, cores 4 in the fake config
assert "Resources" in str(
app.screen.query_one("#resources_section").border_title
)
rows = resource_rows(app)
assert rows["CPU"] == "4 cores × 2 sockets"
assert rows["Memory"] == "8192 MiB"
assert rows["Disk scsi0"] == "10G"
assert not any(
"ide2" in k for k in rows
) # cloud-init drive is not a disk to show
async def test_info_shows_ct_resources_with_swap_and_mount_points(fake):
fake.net_configs[100] = {"memory": 512, "swap": 256,
"rootfs": "local-lvm:vm-100-disk-0,size=8G",
"mp0": "local-lvm:vm-100-disk-1,mp=/data,size=32G"} # fmt: skip
fake.disk_map = {
"rootfs": "8G",
"mp0": "32G",
} # cli.disks is faked; its parsing has cli tests
app = make_app()
async with app.run_test(size=SIZE) as pilot:
await open_info(app, pilot, down=1) # CT 100, cores 1
rows = resource_rows(app)
assert rows["CPU"] == "1 core"
assert rows["Memory"] == "512 MiB"
assert rows["Swap"] == "256 MiB"
assert rows["Disk rootfs"] == "8G" and rows["Disk mp0"] == "32G"
async def test_info_ct_without_cores_is_unlimited(fake, monkeypatch):
monkeypatch.setattr(cli, "guest_config", lambda guest: {"memory": 512})
app = make_app()
async with app.run_test(size=SIZE) as pilot:
await open_info(app, pilot, down=1)
assert resource_rows(app)["CPU"] == "unlimited"
async def test_info_resources_reload_after_edit(fake, monkeypatch):
config = {
"cores": 4,
"memory": 8192,
} # what Proxmox stores; set_resources changes it
monkeypatch.setattr(cli, "guest_config", lambda guest: dict(config))
monkeypatch.setattr(
cli,
"set_resources",
lambda guest, cores=None, memory_mb=None: config.update(cores=cores),
)
app = make_app()
async with app.run_test(size=SIZE) as pilot:
await open_edit(app, pilot) # Enter, then e on VM 108
fill(app, cores="8")
await press_button(app, pilot, "#apply")
await settle(app, pilot)
assert isinstance(app.screen, appmod.InfoScreen)
assert resource_rows(app)["CPU"].startswith("8 cores")