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:
33
app.py
33
app.py
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user