diff --git a/src/app/api/lxc/route.js b/src/app/api/lxc/route.js index 4e10751..0811d4e 100644 --- a/src/app/api/lxc/route.js +++ b/src/app/api/lxc/route.js @@ -1,6 +1,9 @@ import { NextResponse } from 'next/server'; import { getNodes, getLXC } from '@/lib/proxmox'; +const PROXMOX_API_URL = process.env.PROXMOX_API_URL || 'https://proxmox:8006/api2/json'; +const PROXMOX_WEBUI = PROXMOX_API_URL.replace('/api2/json', ''); + /** @param {import('next').Request} _req */ export async function GET(_req) { try { @@ -10,7 +13,13 @@ export async function GET(_req) { for (const node of nodes) { try { const lxcs = await getLXC(node.name); - allLXC.push(...lxcs.map((lxc) => ({ ...lxc, node: node.name }))); + allLXC.push( + ...lxcs.map((lxc) => ({ + ...lxc, + node: node.name, + consoleUrl: `${PROXMOX_WEBUI}/pve/console?node=${encodeURIComponent(node.name)}&vmid=${lxc.vmid}`, + })), + ); } catch { /* skip node */ } } diff --git a/src/app/api/vms/route.js b/src/app/api/vms/route.js index d4c787d..d5f3256 100644 --- a/src/app/api/vms/route.js +++ b/src/app/api/vms/route.js @@ -1,6 +1,9 @@ import { NextResponse } from 'next/server'; import { getNodes, getVMs } from '@/lib/proxmox'; +const PROXMOX_API_URL = process.env.PROXMOX_API_URL || 'https://proxmox:8006/api2/json'; +const PROXMOX_WEBUI = PROXMOX_API_URL.replace('/api2/json', ''); + /** @param {import('next').Request} _req */ export async function GET(_req) { try { @@ -10,7 +13,13 @@ export async function GET(_req) { for (const node of nodes) { try { const vms = await getVMs(node.name); - allVMs.push(...vms.map((vm) => ({ ...vm, node: node.name }))); + allVMs.push( + ...vms.map((vm) => ({ + ...vm, + node: node.name, + consoleUrl: `${PROXMOX_WEBUI}/pve/console?node=${encodeURIComponent(node.name)}&vmid=${vm.vmid}`, + })), + ); } catch { /* skip node */ } } diff --git a/src/components/LXCList.js b/src/components/LXCList.js index 8d76b04..78fbf1c 100644 --- a/src/components/LXCList.js +++ b/src/components/LXCList.js @@ -36,7 +36,21 @@ export default function LXCList({ lxc, onPowerAction }) { {running.map((item) => ( {item.vmid} - {item.name} + + {item.consoleUrl ? ( + + {item.name} + [⟶] + + ) : ( + {item.name} + )} + {item.node} {(item.cpu * 100).toFixed(1)}% {formatBytes(item.memory?.used || 0)} / {formatBytes(item.memory?.total || 0)} @@ -82,7 +96,21 @@ export default function LXCList({ lxc, onPowerAction }) { {stopped.map((item) => ( {item.vmid} - {item.name} + + {item.consoleUrl ? ( + + {item.name} + [⟶] + + ) : ( + {item.name} + )} + {item.node} {formatBytes(item.disk?.used || 0)} diff --git a/src/components/VMList.js b/src/components/VMList.js index a76dffe..3dcf8db 100644 --- a/src/components/VMList.js +++ b/src/components/VMList.js @@ -37,7 +37,21 @@ export default function VMList({ vms, onPowerAction }) { {running.map((vm) => ( {vm.vmid} - {vm.name} + + {vm.consoleUrl ? ( + + {vm.name} + [⟶] + + ) : ( + {vm.name} + )} + {vm.node} {(vm.cpu * 100).toFixed(1)}% {formatBytes(vm.memory?.used || 0)} / {formatBytes(vm.memory?.total || 0)} @@ -83,7 +97,21 @@ export default function VMList({ vms, onPowerAction }) { {stopped.map((vm) => ( {vm.vmid} - {vm.name} + + {vm.consoleUrl ? ( + + {vm.name} + [⟶] + + ) : ( + {vm.name} + )} + {vm.node} {formatBytes(vm.disk?.used || 0)}