import { mdiHarddiskPlus } from "@mdi/js"; import Icon from "@mdi/react"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import DeleteIcon from "@mui/icons-material/Delete"; import ExpandIcon from "@mui/icons-material/Expand"; import { Button, IconButton, Paper, Tooltip, Typography } from "@mui/material"; import React from "react"; import { DiskImage } from "../../api/DiskImageApi"; import { ServerApi } from "../../api/ServerApi"; import { VMFileDisk, VMInfo, VMState } from "../../api/VMApi"; import { ConvertDiskImageDialog } from "../../dialogs/ConvertDiskImageDialog"; import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider"; import { VMDiskFileWidget } from "../vms/VMDiskFileWidget"; import { CheckboxInput } from "./CheckboxInput"; import { DiskBusSelect } from "./DiskBusSelect"; import { DiskImageSelect } from "./DiskImageSelect"; import { DiskSizeInput } from "./DiskSizeInput"; import { SelectInput } from "./SelectInput"; import { TextInput } from "./TextInput"; export function VMDisksList(p: { vm: VMInfo; state?: VMState; onChange?: () => void; editable: boolean; diskImagesList: DiskImage[]; }): React.ReactElement { const [currBackupRequest, setCurrBackupRequest] = React.useState< VMFileDisk | undefined >(); const addNewDisk = () => { p.vm.file_disks.push({ format: "QCow2", size: 10000 * 1000 * 1000, bus: "Virtio", delete: false, name: `disk${p.vm.file_disks.length}`, new: true, }); p.onChange?.(); }; const handleBackupRequest = (disk: VMFileDisk) => { setCurrBackupRequest(disk); }; const handleFinishBackup = () => { setCurrBackupRequest(undefined); }; return ( <> {/* disks list */} {p.vm.file_disks.map((d, num) => ( { p.vm.file_disks.splice(num, 1); p.onChange?.(); }} onRequestBackup={handleBackupRequest} diskImagesList={p.diskImagesList} /> ))} {p.vm.file_disks.length === 0 && ( No disk file yet! )} {p.editable && } {/* Disk backup */} {currBackupRequest && ( )} ); } function DiskInfo(p: { editable: boolean; canBackup: boolean; disk: VMFileDisk; onChange?: () => void; removeFromList: () => void; onRequestBackup: (disk: VMFileDisk) => void; diskImagesList: DiskImage[]; }): React.ReactElement { const confirm = useConfirm(); const expandDisk = () => { if (p.disk.resize === true) { p.disk.resize = false; p.disk.size = p.disk.originalSize!; } else { p.disk.resize = true; p.disk.originalSize = p.disk.size!; } p.onChange?.(); }; const deleteDisk = async () => { if (p.disk.deleteType) { p.disk.deleteType = undefined; p.onChange?.(); return; } const keepFile = await confirm( `You asked to delete the disk ${p.disk.name}. Do you want to keep the block file or not ? `, "Delete disk", "Keep the file", "Delete the file" ); if (!(await confirm("Do you really want to delete this disk?"))) return; p.disk.deleteType = keepFile ? "keepfile" : "deletefile"; p.onChange?.(); }; if (!p.editable || !p.disk.new) return ( <> {p.editable && !p.disk.deleteType && ( {p.disk.resize === true ? ( ) : ( )} )} {p.editable && ( {p.disk.deleteType ? ( ) : ( )} )} {p.canBackup && ( { p.onRequestBackup(p.disk); }} > )} } /> {/* New disk size*/} {p.disk.resize && !p.disk.deleteType && ( { p.disk.size = v; p.onChange?.(); }} /> )} ); return (
/^[a-zA-Z0-9]+$/.test(v)} value={p.disk.name} onValueChange={(v) => { p.disk.name = v ?? ""; p.onChange?.(); }} />
{ p.disk.format = v as any; if (p.disk.format === "Raw") p.disk.is_sparse = true; p.onChange?.(); }} /> {/* Bus selection */} { p.disk.bus = v; p.onChange?.(); }} /> {/* Raw disk: choose sparse mode */} {p.disk.format === "Raw" && ( { if (p.disk.format === "Raw") p.disk.is_sparse = v; p.onChange?.(); }} /> )} {/* Resize disk image */} {!!p.disk.from_image && ( { p.disk.resize = v; p.onChange?.(); }} /> )} {/* Disk size */} {(!p.disk.from_image || p.disk.resize === true) && ( { p.disk.size = v; p.onChange?.(); }} /> )} {/* Disk image selection */} { p.disk.from_image = v; p.onChange?.(); }} />
); }