Fix dashboard timeout by making disk stats non-blocking

virsh guestinfo calls (one per VM) took ~4s on cold cache, exceeding
the dashboard's 3s fetch timeout. Disk stats now refresh in a background
thread and return stale/empty data immediately. Also raised dashboard
fetch timeout to 8s for cold-cache dominfo calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 22:19:21 -06:00
parent f421fe5a77
commit e10a57bb6c

33
app.py
View File

@@ -240,13 +240,8 @@ def get_vm_live_stats():
return live
def get_vm_disk_stats(running_names):
"""Get filesystem usage for running VMs via virsh guestinfo. Cached for VM_DISK_TTL seconds."""
with _vm_disk_lock:
now = time.time()
if now - _vm_disk_cache["ts"] < VM_DISK_TTL:
return _vm_disk_cache["data"]
def _fetch_disk_stats(running_names):
"""Background worker: fetch filesystem stats for all running VMs."""
disks = {}
for name in running_names:
try:
@@ -256,16 +251,12 @@ def get_vm_disk_stats(running_names):
)
if result.returncode != 0:
continue
# Parse filesystem entries, find root mountpoint
fs = {}
for line in result.stdout.split("\n"):
if ":" not in line:
continue
key, val = line.split(":", 1)
key = key.strip()
val = val.strip()
fs[key] = val
# Collect all filesystems
fs[key.strip()] = val.strip()
count = int(fs.get("fs.count", 0))
vm_disks = []
for i in range(count):
@@ -282,11 +273,23 @@ def get_vm_disk_stats(running_names):
disks[name] = vm_disks
except Exception:
continue
with _vm_disk_lock:
_vm_disk_cache["data"] = disks
_vm_disk_cache["ts"] = time.time()
return disks
_vm_disk_cache["refreshing"] = False
def get_vm_disk_stats(running_names):
"""Get filesystem usage. Returns cached data immediately; refreshes in background."""
with _vm_disk_lock:
now = time.time()
stale = now - _vm_disk_cache["ts"] >= VM_DISK_TTL
refreshing = _vm_disk_cache.get("refreshing", False)
if stale and not refreshing:
_vm_disk_cache["refreshing"] = True
t = threading.Thread(target=_fetch_disk_stats, args=(running_names,), daemon=True)
t.start()
return _vm_disk_cache["data"]
def get_vm_base_info():
@@ -380,7 +383,7 @@ def get_local_stats():
}
def fetch_remote_stats(url, timeout=3):
def fetch_remote_stats(url, timeout=8):
try:
req = urllib.request.Request(url.rstrip("/") + "/api/stats")
with urllib.request.urlopen(req, timeout=timeout) as resp: