| |

LFCS 156 ๐Ÿง KVM โ€” Basic VM Management

โฑ๏ธ Estimated read: 10 min | |

The previous chapter introduced KVM as a type-1 hypervisor that turns the Linux kernel into a virtualization layer. This chapter covers the practical management of virtual machines: creating them, controlling their lifecycle, adjusting their resources, and working with snapshots and disks. The LFCS exam tests the virsh commands and the virt-install syntax, along with the operational discipline of graceful shutdown versus forced destruction. The critical trap is the assumption that virsh destroy is a normal shutdown. It is the equivalent of pulling the power plugโ€”it terminates the QEMU process immediately, risking filesystem corruption in the guest. The virsh shutdown sends the ACPI signal and allows the guest to close cleanly .

Key point: virt-install creates a VM and registers it with libvirt. virsh start, virsh shutdown, and virsh destroy control the lifecycle. virsh setmem and virsh setvcpus adjust the resources. virsh snapshot-create-as creates a snapshot, and virsh snapshot-revert restores it. The virsh undefine removes the VM definition but not the disk image unless --remove-all-storage is specified .


Why basic VM management requires a specific mental model

The lifecycle problem. A VM has several states: defined (registered but not running), running, paused, and shut off. The virsh list shows only the running VMs. The virsh list --all shows every VM, including the shut-off ones . The virsh start transitions from defined to running. The virsh shutdown requests a graceful stop. The virsh destroy forces the stop. The virsh suspend pauses the VM, and the virsh resume resumes it . The state determines which operations are valid.

The resource adjustment problem. The virsh setmem and virsh setvcpus change the allocated memory and CPU. The change requires the --config flag to persist across reboots, and the --live flag to apply immediately to the running VM. The --maximum flag sets the maximum value that the VM can be hot-plugged to. Without the --config flag, the change is lost on the next boot . The memory and CPU changes are subject to the maximum values set at creation.

The snapshot problem. A snapshot captures the state of the VM at a point in time. The virsh snapshot-create-as creates it. The virsh snapshot-list shows the snapshots. The virsh snapshot-revert restores the VM to the snapshot. The snapshot is not a backup: it lives on the same storage as the VM, and the destruction of the underlying disk destroys the snapshot . The snapshot is for the rollback, not for the disaster recovery.

The disk problem. The VM’s disk is a file on the host. The qemu-img create creates the disk image. The virsh attach-disk adds a new disk to the running VM. The virsh domblklist lists the disks. The virsh detach-disk removes the disk . The disk image is the persistent data; the VM definition is the configuration.

The undefine problem. The virsh undefine removes the VM definition from libvirt. The disk image remains. The virsh undefine --remove-all-storage removes the definition and the disk images . The distinction matters: the undefine without the storage removal allows the disk to be reused or inspected.

The trade-off. The virsh commands are the CLI for the libvirt API. The virt-manager is the GUI for the same API. The CLI is scriptable and the correct tool for the automation. The GUI is the visual tool for the occasional management. The exam tests the CLI.


a. Creating a VM with virt-install

The virt-install command creates a VM from an installation source. The required options are the name, the memory, the vCPUs, the disk, and the location.

sudo virt-install \
  --name web-vm \
  --memory 2048 \
  --vcpus 2 \
  --disk size=10,format=qcow2 \
  --location http://ftp.ubuntu.com/ubuntu/dists/jammy/main/installer-amd64/ \
  --os-variant ubuntu22.04 \
  --network default \
  --graphics none

The --name is the unique VM name. The --memory is in MiB. The --vcpus is the number of virtual CPUs. The --disk size=10 creates a 10 GB qcow2 image in the default storage pool (/var/lib/libvirt/images/) . The --location is the installation source: an HTTP URL, an NFS path, or a local ISO. The --os-variant optimizes the VM configuration for the specific OS. The --network default connects to the default NAT network. The --graphics none uses the text-based console .

For a cloud image that is already installed, the --import flag skips the installer and boots the existing image.

sudo virt-install \
  --name cloud-vm \
  --memory 2048 \
  --vcpus 2 \
  --disk path=/var/lib/libvirt/images/ubuntu.img,format=qcow2 \
  --import \
  --os-variant ubuntu22.04 \
  --network default

The --import tells virt-install that the disk already contains a bootable OS. The --disk path=... specifies the existing image file .


b. The lifecycle and resource management

The virsh commands control the VM state. The virsh list shows the running VMs. The virsh start starts a defined VM. The virsh shutdown requests a graceful stop.

# List running VMs
virsh list

# List all VMs
virsh list --all

# Start a VM
virsh start web-vm

# Graceful shutdown
virsh shutdown web-vm

# Force stop (power off)
virsh destroy web-vm

# Show VM details
virsh dominfo web-vm

The virsh dominfo shows the VM ID, the name, the state, the CPU count, the memory, and the autostart setting. The virsh console web-vm connects to the serial console . The virsh edit web-vm opens the XML definition in the editor.

The resource adjustment uses the setmem and setvcpus commands with the --config flag for the persistence.

# Set the maximum memory (persistent)
virsh setmaxmem web-vm 4096 --config

# Set the current memory (persistent)
virsh setmem web-vm 4096 --config

# Set the vCPUs (persistent)
virsh setvcpus web-vm 4 --config

The setmaxmem sets the ceiling that the setmem can reach. The setmem changes the current allocation. The setvcpus changes the CPU count. The --config flag writes the change to the VM definition, so it survives the reboot .


c. Snapshots and disk management

A snapshot captures the VM state. The virsh snapshot-create-as creates a named snapshot. The virsh snapshot-list shows the snapshots. The virsh snapshot-revert restores.

# Create a snapshot
virsh snapshot-create-as web-vm snap-before-upgrade --description "Before kernel upgrade"

# List snapshots
virsh snapshot-list web-vm

# Revert to a snapshot
virsh snapshot-revert web-vm snap-before-upgrade

# Delete a snapshot
virsh snapshot-delete web-vm snap-before-upgrade

The snapshot-create-as with the VM running creates an internal snapshot if the disk is qcow2. The snapshot includes the disk state and the memory state. The snapshot-revert restores the VM to that point. The snapshot-delete removes the snapshot .

The disk management uses the qemu-img and the virsh commands.

# Create a disk image
qemu-img create -f qcow2 /var/lib/libvirt/images/data.qcow2 20G

# Attach the disk to a running VM
virsh attach-disk web-vm /var/lib/libvirt/images/data.qcow2 vdb --persistent

# List the disks
virsh domblklist web-vm

# Detach the disk
virsh detach-disk web-vm vdb --persistent

The attach-disk adds the disk to the running VM. The vdb is the device name inside the guest. The --persistent flag writes the change to the VM definition. The detach-disk removes the disk. The domblklist lists the attached disks .


Complete Example Session

# ============================================
# PART 1: CREATE A VM
# ============================================

sudo virt-install \
  --name web-vm \
  --memory 2048 \
  --vcpus 2 \
  --disk size=10,format=qcow2 \
  --location http://ftp.ubuntu.com/ubuntu/dists/jammy/main/installer-amd64/ \
  --os-variant ubuntu22.04 \
  --network default \
  --graphics none
# ============================================
# PART 2: LIST THE VMS
# ============================================

virsh list --all
# Id   Name      State
# -------------------------
# 1    web-vm    running
# ============================================
# PART 3: SHOW VM INFO
# ============================================

virsh dominfo web-vm
# Id:             1
# Name:           web-vm
# State:          running
# CPU(s):         2
# Max memory:     2097152 KiB
# ============================================
# PART 4: ADJUST MEMORY
# ============================================

virsh setmaxmem web-vm 4096 --config
virsh setmem web-vm 4096 --config
# ============================================
# PART 5: ADJUST VCPUS
# ============================================

virsh setvcpus web-vm 4 --config
# ============================================
# PART 6: GRACEFUL SHUTDOWN
# ============================================

virsh shutdown web-vm
# ============================================
# PART 7: CREATE A SNAPSHOT
# ============================================

virsh snapshot-create-as web-vm snap1 --description "Before upgrade"
virsh snapshot-list web-vm
# ============================================
# PART 8: ATTACH A DISK
# ============================================

qemu-img create -f qcow2 /var/lib/libvirt/images/data.qcow2 20G
virsh attach-disk web-vm /var/lib/libvirt/images/data.qcow2 vdb --persistent
virsh domblklist web-vm
# ============================================
# PART 9: REMOVE THE VM
# ============================================

virsh undefine web-vm --remove-all-storage

The nine parts trace the basic VM management: creation, listing, inspection, memory, vCPUs, shutdown, snapshot, disk attach, and removal.


Quick Reference

virt-install Options

OptionPurpose
--nameVM name
--memoryMemory in MiB
--vcpusCPU count
--disk size=NCreate disk
--disk path=...Use existing disk
--importSkip installer
--locationInstall source
--os-variantOS profile
--networkNetwork

Lifecycle Commands

CommandPurpose
virsh listRunning VMs
virsh list --allAll VMs
virsh start <vm>Start
virsh shutdown <vm>Graceful stop
virsh destroy <vm>Force stop
virsh undefine <vm>Remove definition

Resource Commands

CommandPurpose
virsh setmem <vm> <MB>Current memory
virsh setmaxmem <vm> <MB>Max memory
virsh setvcpus <vm> <N>CPU count

Snapshot and Disk Commands

CommandPurpose
virsh snapshot-create-asCreate snapshot
virsh snapshot-listList snapshots
virsh snapshot-revertRevert
virsh attach-diskAdd disk
virsh detach-diskRemove disk
virsh domblklistList disks

Best Practices

โœ… Do This:

virsh shutdown web-vm
<!-- Use graceful shutdown for routine stop -->       # โœ…
virsh setmem web-vm 4096 --config
<!-- Persist the resource change -->                 # โœ…
virsh undefine web-vm --remove-all-storage
<!-- Remove the definition and the disks -->          # โœ…

โŒ Don’t Do This:

virsh destroy web-vm
# For the routine shutdown
<!-- Use shutdown; destroy is force power off -->     # โŒ
virsh setmem web-vm 4096
# Without --config
<!-- The change is lost on reboot -->                # โŒ
# Assume a snapshot is a backup
<!-- The snapshot lives on the same storage -->      # โŒ

Common Pitfalls

PitfallWhy It HappensFix
Resource change lostNo --configAdd the flag
VM cannot startDisk missing or corruptCheck virsh domblklist
Snapshot revert failsVM running with a different diskStop the VM first
Disk not visible in guestDevice not recognizedCheck the guest’s lsblk
Undefine leaves the diskNot using --remove-all-storageRemove the disk manually

Real-World Examples

1. Create VM

virt-install --name vm1 --memory 2048 --vcpus 2 --disk size=10 --os-variant ubuntu22.04 --location http://...

2. List VMs

virsh list --all

3. Start VM

virsh start vm1

4. Shutdown

virsh shutdown vm1

5. Force Stop

virsh destroy vm1

6. Set Memory

virsh setmem vm1 4096 --config

7. Snapshot

virsh snapshot-create-as vm1 snap1

8. Attach Disk

virsh attach-disk vm1 /path/disk.qcow2 vdb --persistent

9. Detach Disk

virsh detach-disk vm1 vdb --persistent

10. Undefine

virsh undefine vm1 --remove-all-storage

Visual

VM Lifecycle

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  virt-install โ†’ VM defined                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ virsh start
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Running                                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ”‚                       โ”‚
           โ”‚ virsh shutdown        โ”‚ virsh destroy
           โ–ผ                       โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Shut off            โ”‚  โ”‚  Shut off (forced)   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ”‚                         โ”‚
           โ”‚ virsh undefine          โ”‚ virsh undefine
           โ–ผ                         โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Removed                                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Snapshot Rollback

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  VM State A                                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ snapshot-create-as
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Snapshot: snap1                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ Changes happen
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  VM State B                                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ snapshot-revert snap1
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  VM State A restored                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
VM creationvirt-install
Import existing--import
List runningvirsh list
List allvirsh list --all
Startvirsh start
Graceful stopvirsh shutdown
Force stopvirsh destroy
Memoryvirsh setmem --config
vCPUsvirsh setvcpus --config
Snapshotvirsh snapshot-create-as

Key takeaways:

  • virsh destroy is force stop, not normal shutdown. It terminates the QEMU process immediately. The virsh shutdown sends the ACPI signal and allows the graceful close. The routine stop uses the shutdown; the destroy is for the hung VM .
  • The --config flag persists the resource change. The setmem and setvcpus without the flag change only the running VM. The change is lost on the reboot.
  • The snapshot is not a backup. It lives on the same storage as the VM. The snapshot is for the rollback before the risky change. The backup requires a separate copy.
  • The undefine --remove-all-storage removes the disks. The undefine without the flag removes only the definition. The disk image remains and can be reused.
  • The --import flag creates a VM from the existing image. It skips the installer and boots the image directly. The cloud images use this pattern.

Remember: The virt-install is the creation. The virsh start is the running. The virsh shutdown is the graceful. The virsh destroy is the force. The --config is the persistence. The snapshot-create-as is the rollback. The undefine --remove-all-storage is the removal. The exam tests the lifecycle and the flag semantics.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!