proxmox-ova-to-vzdump-conve.../README.md

314 lines
9.8 KiB
Markdown

# ova2vzdump
*[English](#english) · [Deutsch](#deutsch)*
<a id="english"></a>
Convert OVA appliances (VirtualBox / VMware export) into **Proxmox
vzdump** `.vma.zst` backup files that can be restored with `qmrestore`.
The tricky part is `vma`, the proprietary container format Proxmox uses
for QEMU backups. The `vma` binary only ships with Proxmox, so this tool
runs inside a Docker image that installs `pve-qemu-kvm` from the Proxmox
no-subscription apt repo. That way you can convert appliances on any
machine with Docker — no PVE host required.
## Pipeline
1. Extract OVA tar → OVF descriptor + VMDK disk(s)
2. Parse OVF XML → CPU, memory, disks, NICs
3. `qemu-img convert` each VMDK → raw
4. Synthesize a `qemu-server.conf`
5. `vma create` packs raws + conf → `.vma`
6. `zstd` compresses → `vzdump-qemu-<vmid>-<ts>.vma.zst`
## Usage
### Build the image
```bash
docker compose build
```
### Web UI
```bash
docker compose up
# browse http://localhost:8880
```
Uploads land in `./data/uploads`, results in `./data/output`.
### Getting a test OVA
ova2vzdump ships a built-in test OVA generator — both the CLI and the
web UI have a dedicated entry point. Two modes:
- **stub** (default, ~1 KB): valid OVA with an empty VMDK. Fast, exercises
the full `extract → parse → qemu-img → vma → zstd` pipeline. Not bootable.
- **bootable** (~80 MB): packages a pre-cached **Alpine Linux** raw image
(downloaded during `docker build`, sha512-verified). After `qmrestore`
on Proxmox the VM actually boots to an Alpine login prompt — this is
what you want for a real end-to-end test.
Existing test OVAs are reused by default; pass `--force` to rebuild.
#### CLI
```bash
# stub:
docker compose run --rm ova2vzdump create-test-ova \
/data/uploads/test.ova --name demo
# bootable Alpine:
docker compose run --rm ova2vzdump create-test-ova \
/data/uploads/alpine.ova --name alpine --bootable
# rebuild:
docker compose run --rm ova2vzdump create-test-ova \
/data/uploads/test.ova --force
```
#### Web UI
Click the **Create test OVA** tab, pick a name, tick **Bootable** if you
want real Alpine, hit Create. The list at the bottom shows what's already
in the upload directory and offers direct download. The generated OVA
also appears as an available input on the **Convert** tab.
If you'd rather grab a real-world appliance from elsewhere:
- **TurnKey Linux Core** (~250 MB):
[turnkeylinux.org/core](https://www.turnkeylinux.org/core) → VM build.
- **DIY**: export any small VM from VirtualBox via
`File → Export Appliance…``.ova`.
### CLI
```bash
docker run --rm \
-v "$PWD/data/uploads:/in" \
-v "$PWD/data/output:/out" \
ova2vzdump:latest convert /in/appliance.ova /out \
--vmid 123 --storage local-lvm
```
Output filename looks like `vzdump-qemu-123-2026_04_21-12_30_00.vma.zst`.
### Restore on Proxmox
Copy the `.vma.zst` onto a PVE node into a backup-capable storage (for
example `/var/lib/vz/dump/`), then:
```bash
qmrestore vzdump-qemu-123-2026_04_21-12_30_00.vma.zst 123 --storage local-lvm
```
## Options
| Flag | Meaning | Default |
| ---- | ------- | ------- |
| `--vmid` | **Placeholder** VMID — overridden at restore time | `100` |
| `--storage` | **Placeholder** storage name in qemu-server.conf — overridden by `qmrestore --storage` | `local-lvm` |
| `--keep-workdir` | Keep intermediate raw disks + vma for debugging | off |
> `qmrestore <file> <target-vmid> [--storage <name>]` always decides the
> real VMID and storage. The values baked into the archive are only
> placeholders; you can leave the defaults for most use cases and only
> tweak them if you want a meaningful filename like
> `vzdump-qemu-<originally-intended-vmid>-*.vma.zst`.
## Config mapping
| OVF | qemu-server.conf |
| --- | ---------------- |
| `VirtualHardwareSection` CPU quantity | `cores` |
| `VirtualHardwareSection` memory | `memory` (MiB) |
| OS description heuristic (`linux`/`windows`/…) | `ostype` (`l26` / `win10` / `other`) |
| Disks w/ SCSI controller | `scsiN` + `scsihw: virtio-scsi-pci` |
| Disks w/ SATA controller | `sataN` |
| Disks w/ IDE controller | `ideN` |
| Ethernet subtype | `netN: <model>=auto,bridge=vmbr0` |
Heuristics are conservative; review the generated config after restore
before booting production workloads.
## Limitations
- OVF 1.x / 2.x only (DMTF envelope namespace).
- `manifest`, `cert`, and signed OVAs are not verified.
- Firmware (BIOS vs. UEFI) is not read from OVF — defaults to SeaBIOS.
Edit the config after restore if your appliance needs OVMF.
- MAC addresses are not preserved (Proxmox assigns new ones on import).
## Local development (without Docker)
You need `qemu-img`, `vma`, and `zstd` on your PATH — i.e. you must be on
a Proxmox host. Then:
```bash
pip install -e .
ova2vzdump convert appliance.ova ./out
```
---
<a id="deutsch"></a>
# ova2vzdump (Deutsch)
Konvertiert OVA-Appliances (Export aus VirtualBox / VMware) in **Proxmox
vzdump** `.vma.zst`-Backup-Dateien, die sich mit `qmrestore` direkt
zurückspielen lassen.
Der knifflige Teil ist `vma` — das proprietäre Container-Format, in dem
Proxmox seine QEMU-Backups speichert. Die `vma`-Binary gibt es nur mit
Proxmox, deshalb läuft dieses Tool in einem Docker-Image, das
`pve-qemu-kvm` aus dem Proxmox-No-Subscription-Apt-Repo installiert.
Dadurch kannst du Appliances auf jeder Maschine mit Docker konvertieren —
ganz ohne PVE-Host.
## Pipeline
1. OVA-Tar entpacken → OVF-Descriptor + VMDK-Disk(s)
2. OVF-XML parsen → CPU, RAM, Disks, NICs
3. Jede VMDK mit `qemu-img convert` nach raw konvertieren
4. Eine `qemu-server.conf` generieren
5. `vma create` packt raws + config → `.vma`
6. `zstd` komprimiert → `vzdump-qemu-<vmid>-<ts>.vma.zst`
## Benutzung
### Image bauen
```bash
docker compose build
```
### Web-UI
```bash
docker compose up
# dann http://localhost:8880 öffnen
```
Uploads landen in `./data/uploads`, Ergebnisse in `./data/output`.
### Test-OVA bekommen
ova2vzdump bringt einen eingebauten Test-OVA-Generator mit — sowohl die
CLI als auch die Web-UI haben einen eigenen Einstiegspunkt. Zwei Modi:
- **stub** (Default, ~1 KB): valide OVA mit leerer VMDK. Schnell, testet
die komplette Pipeline `extract → parse → qemu-img → vma → zstd`.
Nicht bootbar.
- **bootable** (~80 MB): verpackt ein vorgecachtes **Alpine-Linux**-Raw-
Image (wird beim `docker build` heruntergeladen, sha512-verifiziert).
Nach `qmrestore` auf Proxmox bootet die VM tatsächlich in einen
Alpine-Login — das ist der echte End-to-End-Test.
Vorhandene Test-OVAs werden standardmäßig wiederverwendet; `--force` baut
neu.
#### CLI
```bash
# Stub:
docker compose run --rm ova2vzdump create-test-ova \
/data/uploads/test.ova --name demo
# Bootbares Alpine:
docker compose run --rm ova2vzdump create-test-ova \
/data/uploads/alpine.ova --name alpine --bootable
# Neu bauen:
docker compose run --rm ova2vzdump create-test-ova \
/data/uploads/test.ova --force
```
#### Web-UI
Auf den Tab **Create test OVA** klicken, Name wählen, Häkchen bei
**Bootable** setzen wenn du echtes Alpine willst, auf Create klicken. Die
Liste unten zeigt, was im Upload-Verzeichnis liegt, mit direkten
Download-Buttons. Die erzeugte OVA erscheint auch im **Convert**-Tab als
auswählbare Eingabe.
Lieber eine echte Appliance von woanders?
- **TurnKey Linux Core** (~250 MB):
[turnkeylinux.org/core](https://www.turnkeylinux.org/core) → VM-Build.
- **DIY**: irgendeine kleine VM aus VirtualBox exportieren via
`Datei → Appliance exportieren…``.ova`.
### CLI (Konvertierung)
```bash
docker run --rm \
-v "$PWD/data/uploads:/in" \
-v "$PWD/data/output:/out" \
ova2vzdump:latest convert /in/appliance.ova /out \
--vmid 123 --storage local-lvm
```
Der Ausgabedateiname sieht etwa so aus:
`vzdump-qemu-123-2026_04_21-12_30_00.vma.zst`.
### Restore auf Proxmox
Die `.vma.zst` auf einen PVE-Node in ein backup-fähiges Storage kopieren
(z.B. `/var/lib/vz/dump/`), dann:
```bash
qmrestore vzdump-qemu-123-2026_04_21-12_30_00.vma.zst 123 --storage local-lvm
```
## Optionen
| Flag | Bedeutung | Default |
| ---- | --------- | ------- |
| `--vmid` | **Platzhalter**-VMID — wird beim Restore überschrieben | `100` |
| `--storage` | **Platzhalter**-Storage-Name in `qemu-server.conf` — wird durch `qmrestore --storage` überschrieben | `local-lvm` |
| `--keep-workdir` | Zwischenergebnisse (raw-Disks, vma) behalten, zum Debuggen | aus |
> `qmrestore <file> <ziel-vmid> [--storage <name>]` entscheidet immer die
> echte VMID und das Storage. Die Werte im Archiv sind nur Platzhalter —
> Defaults reichen meist. Du passt sie höchstens an, wenn du einen
> sprechenden Dateinamen haben willst, z.B.
> `vzdump-qemu-<ursprüngliche-vmid>-*.vma.zst`.
## Config-Mapping
| OVF | qemu-server.conf |
| --- | ---------------- |
| `VirtualHardwareSection` CPU-Anzahl | `cores` |
| `VirtualHardwareSection` RAM | `memory` (MiB) |
| OS-Description-Heuristik (`linux`/`windows`/…) | `ostype` (`l26` / `win10` / `other`) |
| Disks am SCSI-Controller | `scsiN` + `scsihw: virtio-scsi-pci` |
| Disks am SATA-Controller | `sataN` |
| Disks am IDE-Controller | `ideN` |
| Ethernet-Subtyp | `netN: <model>=auto,bridge=vmbr0` |
Die Heuristiken sind konservativ; bitte die generierte Config nach dem
Restore einmal prüfen, bevor du produktive Workloads startest.
## Limitierungen
- Nur OVF 1.x / 2.x (DMTF-Envelope-Namespace).
- `manifest`, `cert` und signierte OVAs werden nicht verifiziert.
- Firmware (BIOS vs. UEFI) wird nicht aus der OVF gelesen — Default ist
SeaBIOS. Config nach dem Restore manuell anpassen, falls deine
Appliance OVMF braucht.
- MAC-Adressen werden nicht übernommen (Proxmox vergibt beim Import
neue).
## Lokale Entwicklung (ohne Docker)
Du brauchst `qemu-img`, `vma` und `zstd` im PATH — also de facto einen
Proxmox-Host. Dann:
```bash
pip install -e .
ova2vzdump convert appliance.ova ./out
```