314 lines
9.8 KiB
Markdown
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
|
|
```
|