L6 – Virtualization Systems
Cross-Platform Cheat Sheet: VMware Workstation, VirtualBox, libvirt/virsh
Logical architecture · system reference · lifecycle Rosetta Stone · per-system CLI · networking · snapshots · migration · gotchas
Pragmatic reference for running, scripting, and migrating virtual machines with the three major cross-platform hypervisor stacks. Companion to the VM Disk Image Formats cheat sheet, which covers everything at the disk layer. June 2026.
1. Logical architecture
Every desktop or server hypervisor splits into a management plane (the tools you type into) and an execution plane (the process and kernel module that actually run the guest). The layers below apply to all three systems; only the names change. Blue layers belong to the guest, gray layers belong to the host.
| Layer | Role | Implementation in the three systems |
|---|---|---|
| L6 | Guest OS and applications | Sees only the virtual hardware below |
| L5 | Virtual hardware (device models) | NIC: e1000e, vmxnet3, virtio-net. Disk controller: LSI/PVSCSI, AHCI, virtio-blk/scsi. Firmware: BIOS or UEFI. Versioned as VMware hardware version and libvirt machine type (i440fx or q35). |
| VM boundary | ||
| L4 | VMM / execution engine | VMware VMM plus vmmon kernel module; VirtualBox VMM plus vboxdrv (or the Hyper-V/WHP backend on Windows); KVM kernel module with a QEMU process as device model |
| L3 | Management service | Per-VM vmware-vmx process plus host services (vmnet, USB arbitrator); VBoxSVC plus one process per VM; libvirtd (or modular virtqemud) spawning qemu-system-x86_64 per VM |
| L2 | Client tools and APIs | Workstation GUI, vmrun, vmcli, ovftool; VirtualBox Manager, VBoxManage; virsh, virt-install, virt-manager, Cockpit, all through the libvirt API |
| L1 | VM definition and state files | .vmx plus VMDKs, .vmsn/.vmss, vmware.log; .vbox XML plus disks, Snapshots/, Logs/; libvirt domain XML in /etc/libvirt/qemu/ plus /var/lib/libvirt/images/ |
| L0 | Host OS and CPU extensions | VT-x/AMD-V with EPT/NPT; IOMMU (VT-d) for PCI passthrough |
Five working principles
| # | Principle | Practical consequence |
|---|---|---|
| 1 | Management plane and execution plane are separate: the CLI talks to a service, the service owns the per-VM process. | GUIs are optional everywhere. virsh -c qemu+ssh://host/system administers remote hosts, VBoxManage drives headless servers, vmrun scripts the Workstation library. |
| 2 | A VM is just files: a definition, disks, NVRAM, logs. | Backing up the folder backs up the VM, but registration state (UUID, MAC, inventory) lives outside it. Use the clone and import commands instead of raw folder copies. |
| 3 | Only one hypervisor owns the CPU virtualization extensions at full speed. | On Windows, Hyper-V, WSL2, and VBS push Workstation and VirtualBox onto the slower Windows Hypervisor Platform. On Linux, a running KVM guest blocks the others. |
| 4 | Virtual hardware is versioned and chosen at creation time. | Pick firmware (BIOS vs UEFI) and machine type (i440fx vs q35, VMware hardware version) deliberately; upgrades are easy, downgrades are not. |
| 5 | Guest integration is a contract: tools, additions, or agent expose IP reporting, file operations, fsfreeze, and clipboard. | Without the in-guest package, half of the lifecycle commands in section 3 return nothing. Install it first (section 7). |
2. System reference
| System | Hosts and license | VM definition and home | Native disk | CLI and GUI |
|---|---|---|---|---|
| VMware Workstation Pro(Fusion on macOS) | Windows, Linux; Fusion covers macOS including Apple Silicon. Free for personal and commercial use since late 2024 (Broadcom portal download). | .vmx (ini-style text) inside the VM folder. Home: ~/vmware or Documents\Virtual Machines. | VMDK | vmrun, vmcli, ovftool, vmware-vdiskmanager; Workstation / Fusion GUI |
| VirtualBox | Windows, Linux, macOS (Arm hosts run Arm guests only, 7.1+), Solaris. GPLv3 core; the Extension Pack (PUEL license) adds USB 2/3, VRDP, and disk encryption. | .vbox XML per VM plus a global registry in ~/.config/VirtualBox/VirtualBox.xml. Home: ~/VirtualBox VMs. | VDI (reads VMDK, VHD) | VBoxManage (covers everything), VBoxHeadless; VirtualBox Manager GUI |
| KVM + QEMU + libvirt(virsh) | Linux only (kernel module, near type 1). Fully open source. | libvirt domain XML in /etc/libvirt/qemu/ (edit via virsh edit, never by hand on disk). Home: /var/lib/libvirt/images (system) or ~/.local/share/libvirt (session). | qcow2, raw | virsh, virt-install, virt-clone, virt-viewer; virt-manager GUI, Cockpit web console |
Choosing a system
| If you need | Pick | Why |
|---|---|---|
| Linux server or homelab automation, near-native performance, PCI passthrough | KVM + libvirt | Kernel-level hypervisor, scriptable over SSH, foundation of Proxmox and oVirt |
| Polished desktop virtualization on Windows or Linux, strong 3D, dev/test snapshot workflows | VMware Workstation | Mature device models and graphics stack, now free |
| Free cross-platform desktop VMs, classroom and lab portability, OVA sharing | VirtualBox | Runs everywhere, one CLI for everything, easy appliance exchange |
| A macOS host | VMware Fusion or UTM | Workstation does not exist on macOS; VirtualBox on Apple Silicon runs Arm guests only |
| Headless CI or scripted labs on a desktop OS | VBoxManage or vmrun | Both fully drive VMs without a GUI |
| Production Linux virtualization with live migration | libvirt/KVM | virsh migrate –live, storage pools, hooks; step up to Proxmox when you want a UI |
3. Lifecycle Rosetta Stone
The same daily operations in all three CLIs. VMware guest operations need -gu user -gp password and running VMware Tools; VirtualBox guest operations need Guest Additions; libvirt agent queries need qemu-guest-agent in the guest.
| Task | VMware Workstation (vmrun) | VirtualBox (VBoxManage) | libvirt (virsh) |
|---|---|---|---|
| List all defined VMs | No registry command; the library lives in the GUI. Locate .vmx files on disk. | VBoxManage list vms | virsh list –all |
| List running VMs | vmrun list | VBoxManage list runningvms | virsh list |
| Start headless | vmrun start vm.vmx nogui | VBoxManage startvm X –type headless | virsh start vm |
| Graceful shutdown | vmrun stop vm.vmx soft | VBoxManage controlvm X acpipowerbutton | virsh shutdown vm |
| Force off | vmrun stop vm.vmx hard | VBoxManage controlvm X poweroff | virsh destroy vm |
| Save state to disk | vmrun suspend vm.vmx | VBoxManage controlvm X savestate | virsh managedsave vm (resumes on next virsh start) |
| Pause / resume in RAM | vmrun pause vm.vmx / unpause | VBoxManage controlvm X pause / resume | virsh suspend vm / virsh resume vm |
| Take snapshot | vmrun snapshot vm.vmx Snap1 | VBoxManage snapshot X take Snap1 [–live] | virsh snapshot-create-as vm Snap1 |
| List snapshots | vmrun listSnapshots vm.vmx | VBoxManage snapshot X list | virsh snapshot-list vm |
| Revert to snapshot | vmrun revertToSnapshot vm.vmx Snap1 | VBoxManage snapshot X restore Snap1 | virsh snapshot-revert vm Snap1 |
| Delete snapshot | vmrun deleteSnapshot vm.vmx Snap1 | VBoxManage snapshot X delete Snap1 | virsh snapshot-delete vm Snap1 |
| Full clone | vmrun clone src.vmx dst.vmx full -cloneName=Y | VBoxManage clonevm X –name Y –register | virt-clone -o vm -n vm2 –auto-clone |
| Linked clone | vmrun clone src.vmx dst.vmx linked -snapshot=Snap1 -cloneName=Y | VBoxManage clonevm X –snapshot Snap1 –options link –name Y –register | No first-class command: create a qcow2 overlay on a base image, then virt-install –import (see the companion sheet) |
| Get guest IP | vmrun getGuestIPAddress vm.vmx -wait | VBoxManage guestproperty get X “/VirtualBox/GuestInfo/Net/0/V4/IP” | virsh domifaddr vm [–source agent] or virsh net-dhcp-leases default |
| Run command in guest | vmrun -gu u -gp p runProgramInGuest vm.vmx “/bin/ls” “-la” | VBoxManage guestcontrol X run –exe /bin/ls –username u –password p –wait-stdout — -la | Use SSH; the raw alternative is guest-exec JSON via virsh qemu-agent-command |
| Copy file host to guest | vmrun -gu u -gp p copyFileFromHostToGuest vm.vmx src.txt /tmp/dst.txt | VBoxManage guestcontrol X copyto –username u –password p src.txt –target-directory /tmp/ | virt-copy-in -d vm file.txt /tmp/ (offline only) or scp |
| Attach / eject ISO | GUI or edit the CD lines in .vmx | VBoxManage storageattach X –storagectl SATA –port 1 –device 0 –type dvddrive –medium x.iso (eject: –medium emptydrive) | virsh change-media vm sda x.iso –insert / –eject (target name from virsh domblklist vm) |
| Change RAM / CPU (offline) | Edit memsize and numvcpus in .vmx | VBoxManage modifyvm X –memory 8192 –cpus 4 | virsh setmaxmem vm 8G –config, virsh setmem vm 8G –config, virsh setvcpus vm 4 –config |
| Autostart with the host | Workstation 17+: File menu, Configure Auto Start | VBoxManage modifyvm X –autostart-enabled on plus a one-time host autostart service setup | virsh autostart vm |
| Export portable appliance | ovftool vm.vmx vm.ova | VBoxManage export X –output x.ova | No native OVA export: virsh dumpxml plus the disk; virt-v2v handles OVA import |
| Import appliance | ovftool vm.ova ~/vmware/ | VBoxManage import x.ova | virt-v2v -i ova x.ova -o libvirt |
4. Per-system toolbox
4.1 VMware Workstation
vmrun is the scripting workhorse and addresses VMs by their .vmx path. Workstation 17 also ships vmcli, a module-based CLI (Power, Snapshot, Disk, ConfigParams) useful for offline VM configuration. On Fusion, the same commands take -T fusion instead of -T ws.
| Task | Command or location |
|---|---|
| Export / import OVA | ovftool vm.vmx vm.ova / ovftool –acceptAllEulas vm.ova ~/vmware/ (add –lax for nonconforming appliances) |
| Shrink or convert a VMDK | vmware-vdiskmanager -k disk.vmdk; vmware-vdiskmanager -r src.vmdk -t 0 dst.vmdk |
| Key .vmx parameters | memsize = “8192”, numvcpus = “4”, firmware = “efi”, ethernet0.virtualDev = “vmxnet3”, ethernet0.connectionType = “nat”, vhv.enable = “TRUE” (nested virtualization) |
| Network editor | Windows: Edit menu, Virtual Network Editor. Linux: vmware-netcfg. NAT is vmnet8, host-only is vmnet1, bridged is vmnet0. |
| NAT port forwarding | Windows: Virtual Network Editor, NAT Settings. Linux: add to the [incomingtcp] section of /etc/vmware/vmnet8/nat/nat.conf (for example 2222 = 192.168.152.10:22), then restart vmware-networks. |
| Host services (Linux) | systemctl status vmware (vmware-networks, vmware-usbarbitrator) |
| Rebuild kernel modules after a kernel update (Linux) | vmware-modconfig –console –install-all (community-patched modules exist for bleeding-edge kernels) |
| Per-VM log | vmware.log inside the VM folder, first stop for any boot problem |
| Moved or copied prompt | Answer I copied it to regenerate UUID and MAC; I moved it keeps both. Wrong answer equals MAC conflict. |
4.2 VirtualBox
Everything the GUI does, VBoxManage does too. A complete VM from zero:
VBoxManage createvm –name dev1 –ostype Ubuntu_64 –register
VBoxManage modifyvm dev1 –memory 8192 –cpus 4 –nic1 nat \
–natpf1 “ssh,tcp,,2222,,22” –graphicscontroller vmsvga –vram 128
VBoxManage createmedium disk –filename “$HOME/VirtualBox VMs/dev1/dev1.vdi” –size 61440
VBoxManage storagectl dev1 –name SATA –add sata –controller IntelAhci
VBoxManage storageattach dev1 –storagectl SATA –port 0 –device 0 \
–type hdd –medium “$HOME/VirtualBox VMs/dev1/dev1.vdi”
VBoxManage storageattach dev1 –storagectl SATA –port 1 –device 0 \
–type dvddrive –medium ubuntu-24.04.iso
VBoxManage startvm dev1 –type headless
| Task | Command |
|---|---|
| Inspect a VM | VBoxManage showvminfo X [–machinereadable] |
| List supported guest OS types | VBoxManage list ostypes |
| Unattended OS install | VBoxManage unattended install X –iso=ubuntu.iso –user=u –password=p –install-additions |
| Shared folder | VBoxManage sharedfolder add X –name data –hostpath /srv/data –automount |
| RDP console (Extension Pack) | VBoxManage modifyvm X –vrde on –vrdeport 5001 |
| Nested virtualization | VBoxManage modifyvm X –nested-hw-virt on |
| Move the default machine folder | VBoxManage setproperty machinefolder /tank/vms |
| Install the Extension Pack | VBoxManage extpack install Oracle_VirtualBox_Extension_Pack.vbox-extpack |
| Rebuild kernel modules after a kernel update (Linux) | sudo /sbin/vboxconfig (or rely on the dkms/akmod package) |
| Per-VM log | Logs/VBox.log inside the VM folder; service log is VBoxSVC.log in the global config directory |
4.3 libvirt and virsh
The number one gotcha first: libvirt has two default connections. qemu:///system (the root daemon, default storage in /var/lib/libvirt/images, the default NAT network) and qemu:///session (per-user, user-mode networking, a completely separate VM list). virt-manager defaults to system; non-root virsh defaults to session. If virsh list shows nothing, you are on the wrong one. Fix it permanently:
export LIBVIRT_DEFAULT_URI=qemu:///system # add to your shell profile
sudo usermod -aG libvirt,kvm $USER # manage system VMs without sudo
Create a VM with virt-install:
virt-install –name dev1 –memory 8192 –vcpus 4 \
–disk size=60,format=qcow2 –cdrom ubuntu-24.04.iso \
–os-variant ubuntu24.04 –network network=default –graphics spice
# Import an existing disk instead of installing:
virt-install –name dev2 –memory 4096 –vcpus 2 \
–disk path=/var/lib/libvirt/images/dev2.qcow2 –import –os-variant ubuntu24.04
| Task | Command |
|---|---|
| List OS variant names | virt-install –osinfo list |
| Dump / edit a VM definition | virsh dumpxml vm > vm.xml / virsh edit vm |
| Define / remove a VM | virsh define vm.xml / virsh undefine vm –remove-all-storage –nvram |
| Serial console | virsh console vm (guest kernel needs console=ttyS0) |
| Graphical console | virt-viewer vm or virsh domdisplay vm |
| Disks and NICs of a VM | virsh domblklist vm / virsh domiflist vm |
| Hot-add a disk | virsh attach-disk vm /var/lib/libvirt/images/extra.qcow2 vdb –subdriver qcow2 –persistent |
| Storage pools and volumes | virsh pool-list –all, virsh vol-list default, virsh vol-create-as default d.qcow2 60G –format qcow2 |
| Virtual networks | virsh net-list –all, virsh net-start default, virsh net-autostart default (default NAT bridge is virbr0, 192.168.122.0/24) |
| Merge an external snapshot overlay | virsh blockcommit vm vda –active –pivot |
| Live migrate | virsh migrate –live vm qemu+ssh://host2/system (shared storage, or add –copy-storage-all) |
| Administer a remote host | virsh -c qemu+ssh://user@host/system list –all |
| Guest agent ping | virsh qemu-agent-command vm ‘{“execute”:”guest-ping”}’ |
5. Networking models
| Mode | VMware Workstation | VirtualBox | libvirt |
|---|---|---|---|
| NAT (outbound only, guest hidden) | vmnet8 with built-in DHCP and NAT service | –nic1 nat (per-VM, isolated) or a shared NAT Network via VBoxManage natnetwork add | The default network: virbr0 bridge with dnsmasq |
| Bridged (guest joins the LAN) | vmnet0, mapped in the Virtual Network Editor | –nic1 bridged –bridgeadapter1 eno1 | <interface type=”bridge”> to a host bridge br0; macvtap also works but blocks host-to-guest traffic |
| Host-only (host and guests only) | vmnet1 | hostonly adapter, or hostonlynet on 7.0+ | A libvirt network without a <forward> element (isolated) |
| Port forward into NAT | Virtual Network Editor NAT Settings; on Linux edit /etc/vmware/vmnet8/nat/nat.conf | VBoxManage modifyvm X –natpf1 “ssh,tcp,,2222,,22” (delete: –natpf1 delete ssh) | No one-liner on the system NAT: prefer bridged, a libvirt hook script, or session-mode hostfwd |
Rule of thumb: NAT for getting online fast, bridged when the guest must be reachable from the LAN, host-only for lab isolation. Inbound access to a NAT guest always means explicit port forwarding.
6. Snapshot and clone semantics
| System | Disk mechanism | Memory state | Where it lives and how it merges |
|---|---|---|---|
| VMware | Delta VMDKs (disk-000001.vmdk) tracked by the .vmsd dictionary | .vmsn file per snapshot | All inside the VM folder. Snapshot Manager Delete All consolidates the chain back into the base disks. |
| VirtualBox | Differencing images in the Snapshots/ subfolder | .sav file | Inside the VM folder. snapshot delete merges the differencing layer down automatically. |
| libvirt | Internal snapshots inside qcow2 (all disks must be qcow2), or external overlay files via snapshot-create-as –disk-only | Inside the qcow2 for internal snapshots; virsh managedsave files otherwise | Snapshot metadata in /var/lib/libvirt/qemu/snapshot/. External overlays merge with virsh blockcommit –active –pivot. |
Clones across all three systems regenerate the UUID and MAC address; that is exactly why the clone commands in section 3 beat raw folder copies. Linked clones (VMware, VirtualBox) and qcow2 backing files (libvirt) are the same L2 idea: one read-only base, many small overlays.
7. Guest integration packages
| System | Package | What it unlocks and how to install |
|---|---|---|
| VMware | open-vm-tools (Linux), VMware Tools ISO (Windows) | Time sync, IP reporting for getGuestIPAddress, shared folders (hgfs), drag and drop, fsfreeze for consistent snapshots. Linux guest: apt install open-vm-tools (add open-vm-tools-desktop for GUI guests). |
| VirtualBox | Guest Additions | Shared folders (vboxsf), clipboard, auto-resize, guestcontrol and guestproperty. Devices menu, Insert Guest Additions CD; Linux guests can use the distro package virtualbox-guest-utils. |
| libvirt/KVM | qemu-guest-agent plus virtio drivers; spice-vdagent for desktop guests | Reliable virsh shutdown, domifaddr –source agent, fsfreeze during backups, clipboard over SPICE. Linux guest: apt install qemu-guest-agent. Windows guest: the virtio-win driver ISO covers storage, network, and the agent. |
8. Moving VMs between systems
The disk converts in one qemu-img command (companion sheet, section 5); the work is in the VM definition around it.
| # | Step | Detail |
|---|---|---|
| 1 | Uninstall the source guest tools | Old tools fight the new platform (ghost NICs, broken time sync) |
| 2 | Consolidate or delete all snapshots | Converters read a single disk layer |
| 3 | Record firmware and controller | BIOS vs UEFI and the disk controller model must match on the target, or the guest does not boot |
| 4 | Convert the disk | qemu-img convert -p -O <target-format> src dst; alternatively VBoxManage clonemedium or ovftool for whole appliances |
| 5 | Create the target VM around the converted disk | Match firmware; pick a NIC the guest already knows (e1000e is the safe default); Windows guests moving to KVM need virtio drivers injected first, or use virt-v2v, which automates steps 1 to 5 for VMware sources |
| 6 | Boot, install target tools, fix networking | Predictable interface names change with the NIC model; Windows may ask to reactivate; suspend BitLocker beforehand, since vTPM state does not travel |
9. Coexistence and host gotchas
| Gotcha | Mitigation |
|---|---|
| Hyper-V, WSL2, or VBS active on Windows: Workstation and VirtualBox crawl | They fall back to the Windows Hypervisor Platform. Either accept it, or disable with bcdedit /set hypervisorlaunchtype off plus Memory Integrity off (this breaks WSL2 and Credential Guard). |
| virsh list is empty but virt-manager shows VMs | URI mismatch: set LIBVIRT_DEFAULT_URI=qemu:///system (section 4.3) |
| libvirt: permission denied on a disk in a custom path | SELinux/AppArmor labeling. Keep images under /var/lib/libvirt/images, or relabel the directory for svirt. |
| VirtualBox VMs refuse to start after a Linux kernel update | sudo /sbin/vboxconfig rebuilds vboxdrv |
| Workstation modules fail to build on a new kernel | vmware-modconfig –console –install-all; community module patches cover very new kernels |
| USB passthrough not working | VirtualBox: Extension Pack plus vboxusers group membership. VMware on Linux: the vmware-usbarbitrator service. libvirt: a <hostdev> USB entry. |
| MAC or UUID conflicts after copying a VM folder | Use the clone commands; in VMware answer I copied it at first boot |
| Nested virtualization off by default | vhv.enable = “TRUE” in .vmx; VBoxManage modifyvm X –nested-hw-virt on; KVM: kvm_intel nested=1 plus <cpu mode=”host-passthrough”/> |
| Guest clock drifts after suspend or snapshot revert | Guest tools or agent time sync (section 7), plus NTP in the guest |
| Headless server with no console access to a libvirt guest | Enable a serial console in the guest and use virsh console; or virsh domdisplay plus SSH tunneling for SPICE/VNC |
10. Where everything lives on disk
| System | VM home | Global config and registry | Logs and services |
|---|---|---|---|
| VMware | ~/vmware (Linux), Documents\Virtual Machines (Windows) | Linux: /etc/vmware/ (networking), inventory in ~/.vmware/inventory.vmx. Windows: %APPDATA%\VMware. | vmware.log per VM folder. Linux services: vmware-networks, vmware-usbarbitrator. Windows: VMware NAT, DHCP, Authorization services. |
| VirtualBox | ~/VirtualBox VMs | ~/.config/VirtualBox/VirtualBox.xml (Windows: %USERPROFILE%\.VirtualBox) | Logs/VBox.log per VM; VBoxSVC.log in the global config dir. VBoxSVC starts on demand; kernel module vboxdrv. |
| libvirt | /var/lib/libvirt/images (system), ~/.local/share/libvirt (session) | /etc/libvirt/qemu/*.xml (domains), /etc/libvirt/qemu/networks/, daemon config /etc/libvirt/qemu.conf | /var/log/libvirt/qemu/<vm>.log. Daemons: libvirtd or modular virtqemud, virtnetworkd. Default bridge virbr0. |