import type { Metadata } from "next" import { getTranslations, getMessages, setRequestLocale } from "next-intl/server" import { Link } from "@/i18n/navigation" import { DocHeader } from "@/components/ui/doc-header" import { Callout } from "@/components/ui/callout" import CopyableCode from "@/components/CopyableCode" export async function generateMetadata({ params, }: { params: Promise<{ locale: string }> }): Promise { const { locale } = await params const t = await getTranslations({ locale, namespace: "docs.diskManager.importDiskImageVm.meta" }) return { title: t("title"), description: t("description"), openGraph: { title: t("ogTitle"), description: t("ogDescription"), type: "article", url: "https://macrimi.github.io/ProxMenux/docs/disk-manager/import-disk-image-vm", }, } } type StepData = { title: string; body?: string; bodyRich?: string; intro?: string; items?: string[] } type StringItem = string type RelatedItem = { href: string; label: string; tail?: string } export default async function ImportDiskImageVMPage({ params, }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) const t = await getTranslations({ locale, namespace: "docs.diskManager.importDiskImageVm" }) const messages = (await getMessages({ locale })) as unknown as { docs: { diskManager: { importDiskImageVm: { prereqs: { items: StringItem[] } steps: { list: StepData[] } related: { items: RelatedItem[] } } } } } const prereqItems = messages.docs.diskManager.importDiskImageVm.prereqs.items const stepList = messages.docs.diskManager.importDiskImageVm.steps.list const relatedItems = messages.docs.diskManager.importDiskImageVm.related.items const code = (chunks: React.ReactNode) => {chunks} const strong = (chunks: React.ReactNode) => {chunks} const em = (chunks: React.ReactNode) => {chunks} return (
{t.rich("intro.body", { em, strong })}

{t("howRuns.heading")}

{t.rich("howRuns.body", { code })}

{`┌─────────────────────────────────────────────┐
│  PHASE 1 — Collect every decision           │
│  (nothing touched yet)                      │
└──────────────────┬──────────────────────────┘
                   ▼
      qm list — user picks target VM
      (target VM should be powered off)
                   │
                   ▼
      pvesm status -content images
      ├─ 0 candidates → abort
      │   "no storage for disk images"
      ├─ 1 candidate  → auto-select, skip dialog
      └─ 2+           → user picks
                   │
                   ▼
      Source directory
      ├─ default: /var/lib/vz/template/iso
      └─ custom:  user types absolute path
          └─ not a directory → abort
                   │
                   ▼
      Scan the directory (maxdepth 1)
      for *.img *.qcow2 *.vmdk *.raw
      ├─ 0 results → abort
      │   "no compatible disk images found"
      └─ N results → continue
                   │
                   ▼
      User selects one or several images
      (checklist — multiple allowed)
                   │
                   ▼
      For each image, user picks:
      ├─ Bus:   scsi (default) / virtio / sata / ide
      ├─ SSD emulation (ssd=1)
      │   └─ offered only when bus ≠ virtio
      └─ Bootable? (adds to boot order in Phase 2)
                   │
                   ▼
      Summary of everything Phase 2 will do
                   │
   ┌──────── Cancel   OR   Confirm ────┐
   ▼                                   ▼
Exit, nothing        ┌─────────────────┴─────────────────┐
was changed          │  PHASE 2 — Import and attach       │
                     └─────────────────┬─────────────────┘
                                       ▼
                       For each selected image:
                       ├─ qm importdisk  \\
                       │       \\
                       │      
                       │    (format conversion is transparent:
                       │     qcow2/vmdk/img → raw when the
                       │     target cannot hold the source
                       │     format natively — LVM, ZFS, …)
                       │
                       ├─ Find next free {bus}N slot
                       │   (scans qm config)
                       │
                       └─ qm set  -{bus}N \\
                             :vm--disk-N[,ssd=1]
                                       │
                                       ▼
                       If any image was marked bootable:
                       └─ qm set  --boot order={bus}N
                          (first bootable wins; others can be
                           reordered later in the Proxmox UI)
                                       │
                                       ▼
                       Verify: qm config  shows the
                       new slot(s) and, if applicable, the
                       new boot order
                                       │
                                       ▼
                       Source image file on the host is
                       kept unchanged (copied, not moved)`}
      

{t("prereqs.heading")}

    {prereqItems.map((_, idx) => (
  • {t.rich(`prereqs.items.${idx}`, { code, strong })}
  • ))}

{t("steps.heading")}

{stepList.map((step, idx) => (
{t("steps.stepLabel")} {idx + 1}

{step.title}

{step.bodyRich ? (

{t.rich(`steps.list.${idx}.bodyRich`, { code, strong })}

) : step.intro ? ( <>

{step.intro}

{step.items && (
    {step.items.map((_, i) => (
  • {t.rich(`steps.list.${idx}.items.${i}`, { strong, code })}
  • ))}
)} ) : ( step.body &&

{step.body}

)}
))}

{t("manual.heading")}

{t.rich("manual.body", { code })}

{t.rich("manual.warnBody", { code })}

{t("troubleshoot.heading")}

{t.rich("troubleshoot.noImagesBody", { code })} {t("troubleshoot.slowBody")} {t("troubleshoot.uefiBody")}

{t("related.heading")}

    {relatedItems.map((item) => (
  • {item.label} {item.tail}
  • ))}
) }