feat(instances): show saved VM configuration on the Settings tab
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 10s

Read-only card on the instance Settings tab surfacing the panel-stored config
(cores/memory/disk/network/cloud-init) via the saved-config endpoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-15 00:30:44 +05:00
parent bb5d30ab68
commit ed4ff6576a
4 changed files with 70 additions and 1 deletions

View File

@@ -5,7 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useVMConfig, useUpdateConfig, useResizeDisk, useVMOwner, useSetVMOwner, useExecuteScript } from '@/hooks/use-instances';
import { useVMConfig, useUpdateConfig, useResizeDisk, useVMOwner, useSetVMOwner, useExecuteScript, useSavedConfig } from '@/hooks/use-instances';
import { useProfile } from '@/hooks/use-settings';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { toast } from 'sonner';
@@ -137,6 +137,45 @@ function ExecuteScriptCard({ serverId, vmid, node }: { serverId: number; vmid: n
);
}
function SavedConfigCard({ serverId, vmid }: { serverId: number; vmid: number }) {
const { t } = useTranslation();
const { data } = useSavedConfig(serverId, vmid);
if (!data?.found || !data.config) return null;
const c = data.config;
const rows: [string, string | number | undefined][] = [
[t('instances.saved_name'), c.name],
['vCPU', c.cores],
[`${t('nodes.memory')} (MB)`, c.memory],
[`${t('nodes.disk')} (GB)`, c.disk_size],
['IP', c.ip_address ? `${c.ip_address}${c.ip_prefix ? `/${c.ip_prefix}` : ''}` : undefined],
[t('netif.gateway'), c.gateway],
['DNS', c.nameserver],
[t('instances.cloud_user'), c.cloud_init_user],
];
return (
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-semibold flex items-center gap-2">
<Settings className="h-4 w-4" />{t('instances.saved_config')}
</CardTitle>
</CardHeader>
<CardContent>
<p className="mb-3 text-xs text-muted-foreground">{t('instances.saved_config_hint')}</p>
<div className="grid grid-cols-2 gap-x-4 gap-y-1 text-sm">
{rows.filter(([, v]) => v != null && v !== '').map(([label, v]) => (
<div key={label} className="flex justify-between gap-2 border-b py-1">
<span className="text-muted-foreground">{label}</span>
<span className="font-mono">{String(v)}</span>
</div>
))}
</div>
</CardContent>
</Card>
);
}
export default function SettingsTab({ serverId, vmid, type, node }: Props) {
const { t } = useTranslation();
const { data: config } = useVMConfig(serverId, vmid, type, node);
@@ -282,6 +321,8 @@ export default function SettingsTab({ serverId, vmid, type, node }: Props) {
</CardContent>
</Card>
<SavedConfigCard serverId={serverId} vmid={vmid} />
{/* Raw Config */}
{config && (
<Card>

View File

@@ -280,6 +280,26 @@ export function useSnapshotArchiveDetail(archiveId: number | null) {
});
}
// ==================== Saved config (DB) ====================
export interface SavedVMConfig {
found: boolean;
config?: {
cores?: number; memory?: number; disk_size?: number;
ip_address?: string; ip_prefix?: number; gateway?: string; nameserver?: string;
cloud_init_user?: string; cloud_init_password?: string; ssh_keys?: string;
name?: string; template_id?: number;
};
}
export function useSavedConfig(serverId: number, vmid: number, enabled = true) {
return useQuery<SavedVMConfig>({
queryKey: ['vm-saved-config', serverId, vmid],
queryFn: () => apiClient.get(`/proxmox/api/${serverId}/vm/${vmid}/saved-config`),
enabled: enabled && serverId > 0 && vmid > 0,
});
}
// ==================== Execute script (guest agent) ====================
export interface ExecuteScriptResult {

View File

@@ -177,6 +177,10 @@
"no_owner": "No owner",
"owner_saved": "Owner updated",
"owner_hint": "Assign this instance to a user (admin only).",
"saved_config": "Saved configuration",
"saved_config_hint": "Values stored by the panel at creation/reinstall time.",
"saved_name": "Name",
"cloud_user": "Cloud-init user",
"execute_script": "Execute script",
"execute_script_hint": "Runs via the QEMU guest agent (must be installed and running in the VM).",
"interpreter": "Interpreter",

View File

@@ -177,6 +177,10 @@
"no_owner": "Без владельца",
"owner_saved": "Владелец обновлён",
"owner_hint": "Назначить инстанс пользователю (только админ).",
"saved_config": "Сохранённая конфигурация",
"saved_config_hint": "Значения, сохранённые панелью при создании/переустановке.",
"saved_name": "Имя",
"cloud_user": "Cloud-init пользователь",
"execute_script": "Выполнить скрипт",
"execute_script_hint": "Выполняется через QEMU guest agent (должен быть установлен и запущен в VM).",
"interpreter": "Интерпретатор",