Orphan VM Import
Overview
Orphan VM Import is an admin-only workflow that lets the panel adopt KVM virtual machines that already exist on a hypervisor but are not yet tracked in the database. Typical sources:
- VMs that existed on the host before the slave agent was attached.
- VMs created directly with the
virshcommand-line tool. - VMs migrated in from another control panel.
The import is non-destructive. Nothing on the hypervisor is moved, renamed, copied, or restarted. The VM keeps running through the import.
Concepts
- Domain: libvirt's name for a single VM. (Libvirt is the management daemon that controls KVM on each host.)
- qcow2: the standard disk-image file format for KVM VMs.
- Storage row: a record in the panel that tells it which directory on the hypervisor holds disk files. The import needs every disk to either match an existing storage row or have a new one created.
- Pending Assignment: the holding state an imported VM lives in until an admin assigns it to a real user.
- Synthetic plan: a per-VM plan auto-created during import that mirrors the actual CPU, RAM, and disk size of the imported VM. It is hidden from customer plan listings.
Eligibility
When you scan a hypervisor, the panel inspects every libvirt domain the panel does not already track. For each domain it reads the libvirt XML, runs qemu-img info against each disk, and runs virsh domifaddr to collect any guest-reported IP addresses.
A domain is eligible only when every disk meets both:
| Property | Required value |
|---|---|
| Disk format | qcow2 |
| Backend | Regular file on the host filesystem |
Anything else (LVM, ZFS, raw block devices, Ceph RBD) is reported with a "Skipped: ..." reason. Cloud-init or config ISOs, commonly attached as sdx, ending in .iso, or with paths containing cidata or cloudinit, are auto-excluded from eligibility and listed under a separate "CDROMs (excluded)" group.
The VM's runtime state (running, paused, shut off) does not affect eligibility.
Admin: discovering orphan VMs
- Open Hypervisors > Hypervisor and pick the host.
- Scroll to the Orphan VMs card (below GPU Devices).
- Click Scan for Orphan VMs. A progress bar appears while libvirt domains are inspected; the panel updates in real time over WebSocket.
Each row shows:
- Domain name (the libvirt name, for example
h1631). - Runtime state (running, paused, shut off).
- vCPU count and RAM size.
- A badge per disk classifying it.
- An Import button (eligible) or a "Skipped: ..." reason (ineligible).
Clicking a domain name opens a side panel with the full inspected payload: every disk, every NIC (network interface card) with detected guest IPs, and the libvirt VNC port (VNC is the remote-screen protocol used to view the VM's display).
Scan results are cached for one hour. Click Re-scan to refresh.
Admin: importing a single VM
Click Import on an eligible row. The import dialog opens and lists every disk:
- Disks whose directory matches an existing storage row get a green Matched: StorageName badge. No action needed.
- Disks whose directory does not match any storage row are tagged Needs assignment. For each:
- Use existing: pick an existing storage row.
- Create new: register the disk's directory as a brand new storage row. Edit the suggested name and path, then confirm.
Confirm the dialog. The VM is imported:
- Owner is set to a system "Orphan Imports" user (suspended; never logs in).
- Plan is a synthetic per-VM plan named
imported-hypervisor-domaincarrying the actual CPU, RAM, and disk size of the VM. The plan is hidden from customer plan listings. - Status reflects the libvirt runtime state.
- The instance carries a Pending Assignment flag.
Admin: bulk import
If at least two rows have every disk already matched to an existing storage, an Import All Eligible (n) button appears below the table. Click it to import each eligible row in sequence. Rows that need storage assignment are skipped with a warning toast; open them one at a time to choose storage.
Admin: the Pending Assignment banner
Imported instances display a banner at the top of their admin manage page:
This instance was imported and is pending user assignment. Click Assign User in the banner to open the assignment modal, then optionally pick a real plan and add IPs.
Customers never see this banner; the synthetic owner is suspended.
Admin: assigning a user (and plan)
Click Assign User on the banner.
- User (required): pick any real user on the platform.
- Plan (optional): defaults to the synthetic per-VM plan. Pick a real plan to replace it.
On submit:
- The instance's owner becomes the chosen user.
- The Pending Assignment flag clears and the banner disappears.
- If a real plan was picked, the synthetic
imported-...plan is soft-deleted (it has no other instances by construction). If you kept the synthetic plan, it stays attached.
Limitations (v1)
- Non-qcow2 disks (LVM, ZFS, raw block, Ceph RBD) are reported but not importable. Convert to qcow2 first.
- The panel will not run
qemu-img convertfor you. - Scan one hypervisor at a time; there is no bulk multi-hypervisor scan.
- Only IPs already detected on the guest (via
qemu-guest-agentor DHCP lease) are linked, and only when they fall inside a subnet you already have on the hypervisor. Unmatched IPs are written to the import task log; assign them by hand afterwards. - Existing libvirt snapshot history is not adopted. Only the current disk state is imported.
- CDROM and floppy devices are listed informationally and excluded from the imported disk list.
Check that the slave on that hypervisor is online and that the domain's libvirt UUID and name do not already match an instance the panel manages.
Re-importing after hard delete
If you destroy an imported instance and then want to re-adopt the same domain, the destroy flow cleans up the panel's records but leaves the actual qcow2 disks and the libvirt domain in place. Run Scan for Orphan VMs again. The domain reappears in the list and can be re-imported. There is a guard that refuses to re-adopt a domain currently tracked as a non-trashed instance on the same hypervisor.
Troubleshooting
Discovery completes but the table is empty
The panel already tracks every domain on this hypervisor. Confirm by listing instances on the hypervisor manage page.
A specific domain shows "Skipped: ..." but should be importable
Click the domain name to open the side panel and read the per-disk classification. The skip reason is shown next to each unsupported disk. Most common cause: one disk on a non-qcow2 backend (LVM volume, raw block). Convert to a qcow2 file before re-scanning.
Import dialog says "No existing storages, switch to Create new"
The hypervisor has no storage rows that cover the disk's directory. Either register a new one from the dialog (recommended) or add a storage row first under Hypervisors > Hypervisor > Storage.
A detected IP is not linked
Either qemu-guest-agent or the DHCP lease did not report it, or no subnet on the hypervisor contains it. Check the import task log for entries like Found 192.0.2.10 on MAC 52:54:00:aa:bb:01 but no matching subnet on this hypervisor, then assign the IP by hand after the import finishes.
Imported instance fails on power actions, network suspend, or destroy
Update the slave agent. Older slaves expect interface names of the form vir<instance-name> (the literal vir prefix), but imported VMs have libvirt-assigned names like vnet0 that older code paths do not recognize. Update from Hypervisors > Hypervisor > Update Agent.
Related pages
- Live Migration - move imported VMs between hypervisors.
- Instance Images - turn an imported VM into a reusable template.