fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
import React, { useState, useEffect } from 'react';
|
|
|
|
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/index';
|
|
|
|
|
import { Button } from '@/components/ui/index';
|
|
|
|
|
import { Input } from '@/components/ui/index';
|
|
|
|
|
import { Label } from '@/components/ui/index';
|
|
|
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/index';
|
2026-06-22 02:41:57 +00:00
|
|
|
import { Upload } from 'lucide-react';
|
|
|
|
|
import { open as openFileDialog } from '@tauri-apps/plugin-dialog';
|
|
|
|
|
import {
|
|
|
|
|
listProxmoxClusters,
|
|
|
|
|
listProxmoxNodes,
|
|
|
|
|
listProxmoxStorages,
|
|
|
|
|
listIsoImages,
|
|
|
|
|
uploadIsoImage,
|
|
|
|
|
createProxmoxVm,
|
|
|
|
|
} from '@/lib/proxmoxClient';
|
|
|
|
|
import type { ClusterInfo } from '@/lib/domain';
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
import { toast } from 'sonner';
|
|
|
|
|
|
|
|
|
|
interface CreateVmDialogProps {
|
|
|
|
|
isOpen: boolean;
|
|
|
|
|
clusterId: string;
|
|
|
|
|
onClose: () => void;
|
|
|
|
|
onCreated: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const OS_TYPES = [
|
|
|
|
|
{ value: 'l26', label: 'Linux 2.6+' },
|
|
|
|
|
{ value: 'l24', label: 'Linux 2.4' },
|
|
|
|
|
{ value: 'win11', label: 'Windows 11' },
|
|
|
|
|
{ value: 'win10', label: 'Windows 10/2016/2019' },
|
|
|
|
|
{ value: 'win8', label: 'Windows 8/2012' },
|
|
|
|
|
{ value: 'win7', label: 'Windows 7/2008' },
|
|
|
|
|
{ value: 'other', label: 'Other' },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export function CreateVmDialog({ isOpen, clusterId, onClose, onCreated }: CreateVmDialogProps) {
|
2026-06-22 02:41:57 +00:00
|
|
|
const [clusters, setClusters] = useState<ClusterInfo[]>([]);
|
|
|
|
|
const [selectedClusterId, setSelectedClusterId] = useState(clusterId);
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
const [nodes, setNodes] = useState<string[]>([]);
|
|
|
|
|
const [storages, setStorages] = useState<string[]>([]);
|
2026-06-22 02:41:57 +00:00
|
|
|
const [isoStorages, setIsoStorages] = useState<string[]>([]);
|
|
|
|
|
const [isoImages, setIsoImages] = useState<{ volid: string; name?: string }[]>([]);
|
|
|
|
|
const [isoStorage, setIsoStorage] = useState('');
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
2026-06-22 02:41:57 +00:00
|
|
|
const [isUploading, setIsUploading] = useState(false);
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
|
|
|
|
|
const [nodeId, setNodeId] = useState('');
|
|
|
|
|
const [vmid, setVmid] = useState(100);
|
|
|
|
|
const [name, setName] = useState('');
|
|
|
|
|
const [memory, setMemory] = useState(2048);
|
|
|
|
|
const [cores, setCores] = useState(2);
|
|
|
|
|
const [sockets, setSockets] = useState(1);
|
|
|
|
|
const [osType, setOsType] = useState('l26');
|
|
|
|
|
const [storage, setStorage] = useState('');
|
|
|
|
|
const [diskSize, setDiskSize] = useState(20);
|
|
|
|
|
const [netBridge, setNetBridge] = useState('vmbr0');
|
|
|
|
|
const [iso, setIso] = useState('');
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2026-06-22 02:41:57 +00:00
|
|
|
if (!isOpen) return;
|
|
|
|
|
listProxmoxClusters()
|
|
|
|
|
.then((cls) => {
|
|
|
|
|
setClusters(cls);
|
|
|
|
|
const target = cls.find((c) => c.id === clusterId) ? clusterId : cls[0]?.id ?? clusterId;
|
|
|
|
|
setSelectedClusterId(target);
|
|
|
|
|
})
|
|
|
|
|
.catch(console.error);
|
|
|
|
|
}, [isOpen, clusterId]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!isOpen || !selectedClusterId) return;
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
|
2026-06-22 02:41:57 +00:00
|
|
|
listProxmoxNodes(selectedClusterId)
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
.then((data) => {
|
|
|
|
|
const nodeNames = (data as Array<{ node?: string; status?: string }>)
|
|
|
|
|
.filter((n) => n.status === 'online' || n.node)
|
|
|
|
|
.map((n) => n.node ?? '')
|
|
|
|
|
.filter(Boolean);
|
|
|
|
|
setNodes(nodeNames);
|
|
|
|
|
setNodeId(nodeNames[0] ?? '');
|
|
|
|
|
})
|
|
|
|
|
.catch(() => toast.error('Failed to load cluster nodes'));
|
2026-06-22 02:41:57 +00:00
|
|
|
}, [isOpen, selectedClusterId]);
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
|
2026-06-22 02:41:57 +00:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (!isOpen || !selectedClusterId || !nodeId) return;
|
|
|
|
|
|
|
|
|
|
listProxmoxStorages(selectedClusterId, nodeId)
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
.then((data) => {
|
2026-06-22 02:41:57 +00:00
|
|
|
const storageIds = data.map((s) => s.storage).filter(Boolean);
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
setStorages(storageIds);
|
|
|
|
|
setStorage(storageIds[0] ?? 'local-lvm');
|
2026-06-22 02:41:57 +00:00
|
|
|
|
|
|
|
|
const isoCapable = data
|
|
|
|
|
.filter((s) => !s.content || s.content.includes('iso'))
|
|
|
|
|
.map((s) => s.storage)
|
|
|
|
|
.filter(Boolean);
|
|
|
|
|
setIsoStorages(isoCapable);
|
|
|
|
|
setIsoStorage(isoCapable[0] ?? '');
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
})
|
|
|
|
|
.catch(() => {
|
|
|
|
|
setStorages(['local-lvm', 'local']);
|
|
|
|
|
setStorage('local-lvm');
|
|
|
|
|
});
|
2026-06-22 02:41:57 +00:00
|
|
|
}, [isOpen, selectedClusterId, nodeId]);
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
|
2026-06-22 02:41:57 +00:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (!isOpen || !selectedClusterId || !nodeId || !isoStorage) {
|
|
|
|
|
setIsoImages([]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-06-21 23:16:13 +00:00
|
|
|
|
2026-06-22 02:41:57 +00:00
|
|
|
listIsoImages(selectedClusterId, nodeId, isoStorage)
|
|
|
|
|
.then((imgs) => {
|
|
|
|
|
setIsoImages(imgs);
|
|
|
|
|
})
|
|
|
|
|
.catch(() => setIsoImages([]));
|
|
|
|
|
}, [isOpen, selectedClusterId, nodeId, isoStorage]);
|
|
|
|
|
|
|
|
|
|
const handleUploadIso = async () => {
|
|
|
|
|
if (!selectedClusterId || !nodeId || !isoStorage) {
|
|
|
|
|
toast.error('Select a cluster, node, and ISO storage before uploading');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const selected = await openFileDialog({
|
|
|
|
|
title: 'Select ISO file',
|
|
|
|
|
filters: [{ name: 'ISO Images', extensions: ['iso'] }],
|
|
|
|
|
multiple: false,
|
|
|
|
|
});
|
|
|
|
|
if (!selected) return;
|
2026-06-21 23:16:13 +00:00
|
|
|
|
2026-06-22 02:41:57 +00:00
|
|
|
const filePath = selected as string;
|
|
|
|
|
setIsUploading(true);
|
|
|
|
|
try {
|
|
|
|
|
await uploadIsoImage(selectedClusterId, nodeId, isoStorage, filePath);
|
|
|
|
|
toast.success('ISO upload started — refreshing image list');
|
|
|
|
|
const imgs = await listIsoImages(selectedClusterId, nodeId, isoStorage);
|
|
|
|
|
setIsoImages(imgs);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
toast.error(`Upload failed: ${e}`);
|
|
|
|
|
} finally {
|
|
|
|
|
setIsUploading(false);
|
|
|
|
|
}
|
2026-06-21 23:16:13 +00:00
|
|
|
};
|
|
|
|
|
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
const handleSubmit = async () => {
|
|
|
|
|
if (!nodeId) { toast.error('Please select a target node'); return; }
|
|
|
|
|
if (!name.trim()) { toast.error('VM name is required'); return; }
|
|
|
|
|
if (vmid < 100 || vmid > 999999999) { toast.error('VMID must be between 100 and 999999999'); return; }
|
|
|
|
|
|
|
|
|
|
setIsSubmitting(true);
|
|
|
|
|
try {
|
2026-06-22 02:41:57 +00:00
|
|
|
await createProxmoxVm(selectedClusterId, {
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
nodeId,
|
|
|
|
|
vmid,
|
|
|
|
|
name: name.trim(),
|
|
|
|
|
memory,
|
|
|
|
|
cores,
|
|
|
|
|
sockets,
|
|
|
|
|
osType,
|
|
|
|
|
storage,
|
|
|
|
|
diskSize,
|
|
|
|
|
netBridge,
|
2026-06-22 02:41:57 +00:00
|
|
|
iso: iso || undefined,
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
});
|
|
|
|
|
toast.success(`VM "${name}" created successfully (VMID: ${vmid})`);
|
|
|
|
|
onCreated();
|
|
|
|
|
handleClose();
|
|
|
|
|
} catch (err) {
|
|
|
|
|
toast.error(`Failed to create VM: ${err}`);
|
|
|
|
|
} finally {
|
|
|
|
|
setIsSubmitting(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleClose = () => {
|
|
|
|
|
setName('');
|
|
|
|
|
setVmid(100);
|
|
|
|
|
setMemory(2048);
|
|
|
|
|
setCores(2);
|
|
|
|
|
setSockets(1);
|
|
|
|
|
setOsType('l26');
|
|
|
|
|
setDiskSize(20);
|
|
|
|
|
setNetBridge('vmbr0');
|
|
|
|
|
setIso('');
|
|
|
|
|
onClose();
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-22 02:41:57 +00:00
|
|
|
const isoLabel = (volid: string, imgName?: string) => {
|
|
|
|
|
const filename = imgName ?? volid.split('/').pop() ?? volid;
|
|
|
|
|
return filename;
|
|
|
|
|
};
|
|
|
|
|
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
return (
|
|
|
|
|
<Dialog open={isOpen} onOpenChange={handleClose}>
|
|
|
|
|
<DialogContent className="max-w-lg max-h-[90vh] overflow-y-auto">
|
|
|
|
|
<DialogHeader>
|
|
|
|
|
<DialogTitle>Create Virtual Machine</DialogTitle>
|
|
|
|
|
</DialogHeader>
|
|
|
|
|
|
|
|
|
|
<div className="space-y-4 py-2">
|
2026-06-22 02:41:57 +00:00
|
|
|
{clusters.length > 1 && (
|
|
|
|
|
<div className="space-y-1">
|
|
|
|
|
<Label>Datacenter / Cluster</Label>
|
|
|
|
|
<Select value={selectedClusterId} onValueChange={setSelectedClusterId}>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="Select cluster" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{clusters.map((c) => (
|
|
|
|
|
<SelectItem key={c.id} value={c.id}>{c.name}</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
<div className="grid grid-cols-2 gap-4">
|
|
|
|
|
<div className="space-y-1">
|
2026-06-22 02:41:57 +00:00
|
|
|
<Label>Node</Label>
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
<Select value={nodeId} onValueChange={setNodeId}>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="Select node" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{nodes.map((n) => (
|
|
|
|
|
<SelectItem key={n} value={n}>{n}</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-1">
|
|
|
|
|
<Label htmlFor="vm-vmid">VM ID</Label>
|
|
|
|
|
<Input
|
|
|
|
|
id="vm-vmid"
|
|
|
|
|
type="number"
|
|
|
|
|
min={100}
|
|
|
|
|
max={999999999}
|
|
|
|
|
value={vmid}
|
|
|
|
|
onChange={(e) => setVmid(Number(e.target.value))}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="space-y-1">
|
|
|
|
|
<Label htmlFor="vm-name">Name</Label>
|
|
|
|
|
<Input
|
|
|
|
|
id="vm-name"
|
|
|
|
|
value={name}
|
|
|
|
|
onChange={(e) => setName(e.target.value)}
|
|
|
|
|
placeholder="my-vm"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="space-y-1">
|
2026-06-22 02:41:57 +00:00
|
|
|
<Label>OS Type</Label>
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
<Select value={osType} onValueChange={setOsType}>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{OS_TYPES.map((o) => (
|
|
|
|
|
<SelectItem key={o.value} value={o.value}>{o.label}</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-3 gap-4">
|
|
|
|
|
<div className="space-y-1">
|
|
|
|
|
<Label htmlFor="vm-memory">Memory (MB)</Label>
|
|
|
|
|
<Input
|
|
|
|
|
id="vm-memory"
|
|
|
|
|
type="number"
|
|
|
|
|
min={256}
|
|
|
|
|
step={256}
|
|
|
|
|
value={memory}
|
|
|
|
|
onChange={(e) => setMemory(Number(e.target.value))}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-1">
|
|
|
|
|
<Label htmlFor="vm-cores">Cores</Label>
|
|
|
|
|
<Input
|
|
|
|
|
id="vm-cores"
|
|
|
|
|
type="number"
|
|
|
|
|
min={1}
|
2026-06-21 23:16:13 +00:00
|
|
|
max={512}
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
value={cores}
|
|
|
|
|
onChange={(e) => setCores(Number(e.target.value))}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-1">
|
|
|
|
|
<Label htmlFor="vm-sockets">Sockets</Label>
|
|
|
|
|
<Input
|
|
|
|
|
id="vm-sockets"
|
|
|
|
|
type="number"
|
|
|
|
|
min={1}
|
|
|
|
|
max={4}
|
|
|
|
|
value={sockets}
|
|
|
|
|
onChange={(e) => setSockets(Number(e.target.value))}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-2 gap-4">
|
|
|
|
|
<div className="space-y-1">
|
2026-06-22 02:41:57 +00:00
|
|
|
<Label>Storage</Label>
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
{storages.length > 0 ? (
|
|
|
|
|
<Select value={storage} onValueChange={setStorage}>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="Select storage" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{storages.map((s) => (
|
|
|
|
|
<SelectItem key={s} value={s}>{s}</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
) : (
|
|
|
|
|
<Input
|
|
|
|
|
value={storage}
|
|
|
|
|
onChange={(e) => setStorage(e.target.value)}
|
|
|
|
|
placeholder="local-lvm"
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-1">
|
|
|
|
|
<Label htmlFor="vm-disksize">Disk Size (GB)</Label>
|
|
|
|
|
<Input
|
|
|
|
|
id="vm-disksize"
|
|
|
|
|
type="number"
|
|
|
|
|
min={1}
|
|
|
|
|
value={diskSize}
|
|
|
|
|
onChange={(e) => setDiskSize(Number(e.target.value))}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="space-y-1">
|
|
|
|
|
<Label htmlFor="vm-bridge">Network Bridge</Label>
|
|
|
|
|
<Input
|
|
|
|
|
id="vm-bridge"
|
|
|
|
|
value={netBridge}
|
|
|
|
|
onChange={(e) => setNetBridge(e.target.value)}
|
|
|
|
|
placeholder="vmbr0"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-06-22 02:41:57 +00:00
|
|
|
<div className="space-y-2">
|
|
|
|
|
<div className="flex items-center justify-between">
|
|
|
|
|
<Label>ISO Image (optional)</Label>
|
|
|
|
|
{isoStorage && (
|
|
|
|
|
<Button
|
|
|
|
|
type="button"
|
|
|
|
|
variant="outline"
|
|
|
|
|
size="sm"
|
|
|
|
|
onClick={() => void handleUploadIso()}
|
|
|
|
|
disabled={isUploading || !nodeId}
|
|
|
|
|
className="h-7 text-xs"
|
|
|
|
|
>
|
|
|
|
|
<Upload className="mr-1.5 h-3 w-3" />
|
|
|
|
|
{isUploading ? 'Uploading...' : 'Upload ISO'}
|
|
|
|
|
</Button>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
{isoStorages.length > 0 && (
|
|
|
|
|
<div className="space-y-1">
|
|
|
|
|
<Label className="text-xs text-muted-foreground">Storage</Label>
|
|
|
|
|
<Select value={isoStorage} onValueChange={setIsoStorage}>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="Select ISO storage" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{isoStorages.map((s) => (
|
|
|
|
|
<SelectItem key={s} value={s}>{s}</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{isoImages.length > 0 ? (
|
|
|
|
|
<Select value={iso} onValueChange={setIso}>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="Select ISO (optional)" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
<SelectItem value="">— None —</SelectItem>
|
|
|
|
|
{isoImages.map((img) => (
|
|
|
|
|
<SelectItem key={img.volid} value={img.volid}>
|
|
|
|
|
{isoLabel(img.volid, img.name)}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
2026-06-21 23:16:13 +00:00
|
|
|
) : (
|
2026-06-22 02:41:57 +00:00
|
|
|
<Input
|
|
|
|
|
value={iso}
|
|
|
|
|
onChange={(e) => setIso(e.target.value)}
|
|
|
|
|
placeholder="local:iso/ubuntu-24.04.iso"
|
|
|
|
|
/>
|
2026-06-21 23:16:13 +00:00
|
|
|
)}
|
2026-06-22 02:41:57 +00:00
|
|
|
<p className="text-xs text-muted-foreground">
|
|
|
|
|
{isoImages.length > 0
|
|
|
|
|
? `${isoImages.length} ISO(s) available`
|
|
|
|
|
: 'Format: storage:iso/filename'}
|
|
|
|
|
</p>
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<DialogFooter>
|
|
|
|
|
<Button variant="outline" onClick={handleClose} disabled={isSubmitting}>
|
|
|
|
|
Cancel
|
|
|
|
|
</Button>
|
2026-06-22 02:41:57 +00:00
|
|
|
<Button
|
|
|
|
|
onClick={() => void handleSubmit()}
|
|
|
|
|
disabled={isSubmitting || !nodeId || !name.trim()}
|
|
|
|
|
>
|
fix(proxmox): fix VM actions, remove Disk column, add Create VM
Issue 1 — VM actions silently doing nothing:
The root cause was a missing <Toaster> mount in App.tsx. All
toast.success/error calls were no-ops because the sonner Toaster
component was never rendered. Added it at the App root.
Also added dialog:allow-confirm capability (was missing, caused VM
delete confirmation to throw silently).
Issue 2 — Remove Disk column:
PVE cluster/resources returns only static disk allocation, not actual
usage, making the column misleading. Removed from VMList header, row,
and the diskPercent calculation.
Issue 3 — Add VM creation:
- New list_proxmox_nodes Tauri command (GET /nodes) for real node list
- New create_proxmox_vm Tauri command with server-side input validation:
vmid range, numeric bounds, node/storage/bridge path-safety check,
ISO volume-ID format check to prevent comma-property injection
- CreateVmDialog component with node/storage discovery on open
- "Add VM" button wired into VMsPage
MigrationDialog now fetches real cluster nodes via list_proxmox_nodes
instead of inferring them from the VMs already in the list.
Added suspendProxmoxVm, resumeProxmoxVm, listProxmoxNodes,
createProxmoxVm client wrappers to proxmoxClient.ts.
Tests: 446 Rust + 405 frontend, all pass. 19 new VMList tests (TDD),
7 new Rust tests for security validation logic.
2026-06-21 23:01:37 +00:00
|
|
|
{isSubmitting ? 'Creating...' : 'Create VM'}
|
|
|
|
|
</Button>
|
|
|
|
|
</DialogFooter>
|
|
|
|
|
</DialogContent>
|
|
|
|
|
</Dialog>
|
|
|
|
|
);
|
|
|
|
|
}
|