diff --git a/backlog.md b/backlog.md index b09c679..0c16050 100644 --- a/backlog.md +++ b/backlog.md @@ -27,6 +27,11 @@ ## Quick Wins (low effort, high value) +### Per-VM/LXC IP Addresses +- Fetches guest IPs from `/status/guest` for running VMs/LXCs (requires guest agent). +- Displays IPs below the name in the table. +- **Status: done (merged to main)** + ### Search / Filter - Client-side text input filtering table rows by name/node/status - Uses `useMemo` for performant filtering, auto-expands single node and filter-matched nodes diff --git a/src/app/api/lxc/route.js b/src/app/api/lxc/route.js index fd65095..3c7eb41 100644 --- a/src/app/api/lxc/route.js +++ b/src/app/api/lxc/route.js @@ -1,8 +1,7 @@ import { NextResponse } from 'next/server'; -import { getNodes, getLXC } from '@/lib/proxmox'; +import { getNodes, getLXC, getGuestIPs } from '@/lib/proxmox'; const PROXMOX_WEB_URL = process.env.PROXMOX_WEB_URL || process.env.PROXMOX_API_URL?.replace('/api2/json', ''); -const PROXMOX_CONSOLE_TOKEN = process.env.PROXMOX_CONSOLE_TOKEN || process.env.PROXMOX_TOKEN_ID; /** @param {import('next').Request} _req */ export async function GET(_req) { @@ -13,13 +12,20 @@ export async function GET(_req) { for (const node of nodes) { try { const lxcs = await getLXC(node.name); - allLXC.push( - ...lxcs.map((lxc) => ({ + for (const lxc of lxcs) { + let ips = []; + if (lxc.status === 'running') { + try { + ips = await getGuestIPs(node.name, lxc.vmid, 'lxc'); + } catch { /* guest agent not available */ } + } + allLXC.push({ ...lxc, node: node.name, consoleUrl: `${PROXMOX_WEB_URL}/?console=lxc&vmid=${lxc.vmid}&node=${encodeURIComponent(node.name)}&resize=scale&xtermjs=1`, - })), - ); + ips, + }); + } } catch { /* skip node */ } } diff --git a/src/app/api/vms/route.js b/src/app/api/vms/route.js index 8acabb7..6ffe359 100644 --- a/src/app/api/vms/route.js +++ b/src/app/api/vms/route.js @@ -1,8 +1,7 @@ import { NextResponse } from 'next/server'; -import { getNodes, getVMs } from '@/lib/proxmox'; +import { getNodes, getVMs, getGuestIPs } from '@/lib/proxmox'; const PROXMOX_WEB_URL = process.env.PROXMOX_WEB_URL || process.env.PROXMOX_API_URL?.replace('/api2/json', ''); -const PROXMOX_CONSOLE_TOKEN = process.env.PROXMOX_CONSOLE_TOKEN || process.env.PROXMOX_TOKEN_ID; /** @param {import('next').Request} _req */ export async function GET(_req) { @@ -13,13 +12,20 @@ export async function GET(_req) { for (const node of nodes) { try { const vms = await getVMs(node.name); - allVMs.push( - ...vms.map((vm) => ({ + for (const vm of vms) { + let ips = []; + if (vm.status === 'running') { + try { + ips = await getGuestIPs(node.name, vm.vmid, 'qemu'); + } catch { /* guest agent not available */ } + } + allVMs.push({ ...vm, node: node.name, consoleUrl: `${PROXMOX_WEB_URL}/?console=qemu&vmid=${vm.vmid}&node=${encodeURIComponent(node.name)}&resize=scale&novnc=1`, - })), - ); + ips, + }); + } } catch { /* skip node */ } } diff --git a/src/components/LXCList.js b/src/components/LXCList.js index 1e6400e..50005e8 100644 --- a/src/components/LXCList.js +++ b/src/components/LXCList.js @@ -90,7 +90,14 @@ export default function LXCList({ lxc, onPowerAction, onOpenConsole }) { {running.map((item) => (