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'; import { listProxmoxNodes, listProxmoxDatastores, createProxmoxVm } from '@/lib/proxmoxClient'; 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) { const [nodes, setNodes] = useState([]); const [storages, setStorages] = useState([]); const [isSubmitting, setIsSubmitting] = useState(false); 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(() => { if (!isOpen || !clusterId) return; listProxmoxNodes(clusterId) .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')); listProxmoxDatastores(clusterId) .then((data) => { const storageIds = (data as Array<{ storage?: string }>) .map((s) => s.storage ?? '') .filter(Boolean); setStorages(storageIds); setStorage(storageIds[0] ?? 'local-lvm'); }) .catch(() => { setStorages(['local-lvm', 'local']); setStorage('local-lvm'); }); }, [isOpen, clusterId]); 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 { await createProxmoxVm(clusterId, { nodeId, vmid, name: name.trim(), memory, cores, sockets, osType, storage, diskSize, netBridge, iso: iso.trim() || undefined, }); 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(); }; return ( Create Virtual Machine
setVmid(Number(e.target.value))} />
setName(e.target.value)} placeholder="my-vm" />
setMemory(Number(e.target.value))} />
setCores(Number(e.target.value))} />
setSockets(Number(e.target.value))} />
{storages.length > 0 ? ( ) : ( setStorage(e.target.value)} placeholder="local-lvm" /> )}
setDiskSize(Number(e.target.value))} />
setNetBridge(e.target.value)} placeholder="vmbr0" />
setIso(e.target.value)} placeholder="local:iso/ubuntu-24.04.iso" />

Format: storage:iso/filename.iso

); }