Here's the workflow that I use for creating/managing KVM- and QEMU-based VMs:
Make sure you have satisfied the following:
virt-install — this comes with 'virtinst' package on Ubuntu
virt-builder — this is part of 'libguestfs-tools' package on Ubuntu
libvirtd — Install libvirt (I think the package on Ubuntu is 'libvirt-daemon'); and make sure libvirtd` is running (check it by running systemctl status libvirtd).
Make sure your libvirt's default network is active:
$> sudo virsh net-list Name State Autostart Persistent -------------------------------------------- default active yes yes
Make sure sudo works for your user.
Build a VM image.
virt-builder lets you rapidly create and customize virtual machine disk iamges. When you first run virt-builder to create, say, an Ubuntu VM, it'll create the disk image (and then caches a a compressed template - the location is ~/.cache/virt-builder/). So the first run will take a few minutes; after that every new VM image creation will take just about a minute or so.
Example usage:
Find what OS disk images virt-builder supports:
$ virt-builder --list | less
Simple usage: build an Ubuntu "Focal" disk image image, of QCOW2 format, 20G size, with a root password of your choice:
$ cd /var/lib/libvirt/images/ $ sudo virt-builder ubuntu-20.04 --format qcow2 --size 20G \ -o focal-vm1.qcow2 --root-password secret
Import the image to libvirt.
Once you have the disk image, ubuntu-focal-vm.qcow2, you want to import it into libvirt so that you can manage it with libvirt's shell tool, virsh.
Assuming you have libvirtd running you can import the disk image you created in step (1) with the virt-install command (note: we're not installing anything here, but merely importing the disk image into libvirt). The VM gets 4GM (4096 MB), so make sure that's available:
$ sudo virt-install --name focal-vm1 --ram 4096 \ --disk path=/var/lib/libvirt/images/focal-vm1.qcow2,format=qcow2 \ --nographics --os-variant ubuntu20.04 --import
A quick usage of virsh (you can also the GUI tool virt-manager, or GNOME Boxes).
To list all the virtual machines (online and offline):
$ sudo virsh list --all
Start a VM, and see the boot process on the serial console
$ sudo virsh start --console
To take an "internal" snapshot of your VM:
$ sudo virsh snapshot-create-as focal-vm1 snap1 "Clean Focal 1"
With this kind of snapshot (called "internal snapshots"), the original and its delta, i.e. the snapshot, are stored in a single disk image file; this is convenient for moving it across machines. This only works with QCOW2 images.
To revert to the snapshot:
$ sudo virsh snapshot-revert focal-vm1 snap1
To gracefully shutdown and delete a VM, including its disk image:
$ sudo virsh stop f27vm1 $ sudo virsh undefine f27vm1 --remove-all-storage
The 'virt-builder' man page is well-worth reading: https://libguestfs.org/virt-builder.1.html
A really nice 15-minute lightening talk on 'virt-builder by its maintainer: https://archive.fosdem.org/2014/schedule/event/libguestfs/
Skim through man virsh
Fedora developer's guide that shows usage of virt-builder, virt-install, and virsh https://developer.fedoraproject.org/tools/virt-builder/about.html