Add server hardware/network detail view with Proxmox sync and agent reporting
Servers & Tasks only tracked scheduled tasks — there was no overview of the servers themselves and no way to see CPU/RAM/disk/IP info. Add a clickable server overview (visible to every role, not just admins) that opens a per-server detail page. - servers table gains an agent-reported hardware/network snapshot (IPs, CPU model/cores/load, memory, disks) and an optional link to a Proxmox VM/LXC (integration + node + guest type + vmid). - Proxmox adapter gains getGuestDetail(): live cores/memory/disk from /config, live cpu/mem/uptime from /status/current, and IPs (LXC net config directly, QEMU via a best-effort guest-agent call that degrades gracefully when the agent isn't installed). - New GET /api/servers/:id/detail combines whichever hardware source applies (live Proxmox vs. last agent report) with a DNS reverse-lookup against the DNS module's own record cache, so matching hostnames show up next to each IP. New PATCH /api/servers/:id manages the Proxmox link. - agent/linux/report-tasks.sh now also collects and reports IPs, CPU/memory/disk info on every check-in (load-average-based CPU number, not instantaneous, to keep the agent a cheap oneshot). - Extracted the per-server task table into a shared ServerTaskTable component so the all-servers view and the new detail page render tasks identically. Verified server-side end-to-end against the real dev server (agent report -> detail endpoint -> DNS match) and the Proxmox adapter against a mock HTTPS server covering LXC/QEMU config parsing and the guest-agent-unavailable fallback. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1f0e6a9d4c
commit
b9409d3095
15 files changed
+2206
-140
No files matched your search
@@ -13,8 +13,16 @@ export interface IncomingTask {
|
||||
metadata?: unknown;
|
||||
}
|
||||
|
||||
export interface IncomingSystemInfo {
|
||||
ip_addresses?: string[];
|
||||
cpu?: { model?: string; cores?: number; load_percent?: number | null };
|
||||
memory?: { total_bytes?: number; used_bytes?: number };
|
||||
disks?: { mount: string; size_bytes: number; used_bytes: number }[];
|
||||
}
|
||||
|
||||
export interface AgentReport {
|
||||
hostname?: string;
|
||||
system?: IncomingSystemInfo;
|
||||
tasks: IncomingTask[];
|
||||
}
|
||||
|
||||
@@ -85,8 +93,25 @@ export async function syncServerTasks(serverId: number, report: AgentReport) {
|
||||
await db.update(scheduledTasks).set({ isStale: true }).where(agentScope);
|
||||
}
|
||||
|
||||
const system = report.system;
|
||||
await db
|
||||
.update(servers)
|
||||
.set({ lastSeenAt: now, ...(report.hostname ? { hostname: report.hostname } : {}) })
|
||||
.set({
|
||||
lastSeenAt: now,
|
||||
...(report.hostname ? { hostname: report.hostname } : {}),
|
||||
...(system?.ip_addresses ? { ipAddresses: JSON.stringify(system.ip_addresses) } : {}),
|
||||
...(system?.cpu?.model !== undefined ? { cpuModel: system.cpu.model } : {}),
|
||||
...(system?.cpu?.cores !== undefined ? { cpuCores: system.cpu.cores } : {}),
|
||||
...(system?.cpu?.load_percent !== undefined ? { cpuLoadPercent: system.cpu.load_percent } : {}),
|
||||
...(system?.memory?.total_bytes !== undefined ? { memTotalBytes: system.memory.total_bytes } : {}),
|
||||
...(system?.memory?.used_bytes !== undefined ? { memUsedBytes: system.memory.used_bytes } : {}),
|
||||
...(system?.disks
|
||||
? {
|
||||
disks: JSON.stringify(
|
||||
system.disks.map((d) => ({ mount: d.mount, sizeBytes: d.size_bytes, usedBytes: d.used_bytes })),
|
||||
),
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
.where(eq(servers.id, serverId));
|
||||
}
|
||||
Reference in new issue
Block a user