feat(metrics): real-time VM disk fill, IOPS and network I/O
Add live per-disk usage, disk read/write and network in/out rates to the instance Overview tab, the instances list and the dashboard top-loaded list. Backend: - get_vm_fsinfo() pulls per-filesystem usage via QEMU guest agent - metrics_broadcaster computes I/O rates (bytes/sec) from cumulative counters - instances-list loop now refreshes each running VM via status/current (1s-granular) instead of cluster/resources (10s pvestatd), with bounded concurrency, and paces both realtime loops to a 1s cadence Frontend: - OverviewTab: per-disk cards, Network I/O and I/O-rate cards via WS - InstancesPage: Net and Disk I/O columns; Disk% shown for LXC only - DashboardPage: top-loaded list overlaid with realtime metrics Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -168,6 +168,37 @@ class VmMixin:
|
||||
"""Получить статистику VM (CPU, память, диск)"""
|
||||
return self.get_vm_status(node, vmid)
|
||||
|
||||
def get_vm_fsinfo(self, node: str, vmid: int) -> list:
|
||||
"""Return per-filesystem info via QEMU guest agent (get-fsinfo).
|
||||
Returns [] if agent is not installed or unreachable."""
|
||||
if not self.proxmox:
|
||||
return []
|
||||
try:
|
||||
result = self.proxmox.nodes(node).qemu(vmid).agent('get-fsinfo').get()
|
||||
fslist = result if isinstance(result, list) else result.get('result', [])
|
||||
disks = []
|
||||
seen_disks: set = set()
|
||||
for fs in fslist:
|
||||
if not isinstance(fs, dict):
|
||||
continue
|
||||
total = fs.get('total-bytes', 0) or 0
|
||||
if total == 0:
|
||||
continue
|
||||
# Deduplicate by disk+partition key to avoid pseudo-filesystems
|
||||
disk_key = fs.get('name', '') or fs.get('mountpoint', '')
|
||||
if disk_key in seen_disks:
|
||||
continue
|
||||
seen_disks.add(disk_key)
|
||||
disks.append({
|
||||
'name': fs.get('name', ''),
|
||||
'mountpoint': fs.get('mountpoint', '/'),
|
||||
'used': fs.get('used-bytes', 0) or 0,
|
||||
'total': total,
|
||||
})
|
||||
return disks
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
def get_vm_rrddata(self, node: str, vmid: int, timeframe: str = "hour") -> Dict:
|
||||
"""
|
||||
Получить исторические данные VM для графиков (CPU, Memory, Network, Disk IO)
|
||||
|
||||
Reference in New Issue
Block a user