Virtual Machine Management with virsh: Complete Guide

Introduction

Virsh (Virtualization Shell) is the command-line interface for managing KVM/QEMU virtual machines through libvirt. As the most powerful and flexible tool for VM administration, virsh provides granular control over every aspect of virtual machine lifecycle, from creation and configuration to monitoring and troubleshooting.

This comprehensive guide explores virsh's extensive capabilities, covering everything from basic VM operations to advanced management techniques used in production environments. Whether you're managing a single development VM or orchestrating hundreds of virtual machines across multiple hosts, mastering virsh is essential for efficient virtualization management.

Unlike graphical tools like virt-manager, virsh offers scriptable, automation-friendly commands that integrate seamlessly into DevOps workflows, CI/CD pipelines, and infrastructure-as-code solutions. Its consistent interface and comprehensive feature set make it the tool of choice for professional system administrators and cloud engineers.

By the end of this guide, you'll be proficient in using virsh to manage virtual machines, networks, storage pools, and snapshots, enabling you to automate complex virtualization workflows and troubleshoot issues with confidence.

Understanding Virsh and Libvirt

What is Virsh?

Virsh is a command-line tool that communicates with the libvirt daemon (libvirtd) to manage virtualization platforms including KVM, QEMU, Xen, VMware, and others. It provides:

  • VM lifecycle management (create, start, stop, delete)
  • Resource allocation and modification
  • Network and storage configuration
  • Snapshot and cloning operations
  • Live migration capabilities
  • Monitoring and statistics collection

Libvirt Architecture

┌──────────────────────────────────────┐
│         virsh (CLI Tool)             │
├──────────────────────────────────────┤
│      libvirt API (libvirt-client)    │
├──────────────────────────────────────┤
│    libvirtd (Virtualization Daemon)  │
├──────────────────────────────────────┤
│  Hypervisor Drivers (KVM, QEMU, Xen) │
├──────────────────────────────────────┤
│          Physical Hardware           │
└──────────────────────────────────────┘

Connection URIs

Virsh connects to hypervisors using URI schemes:

# Local system connection (default)
virsh --connect qemu:///system

# Remote connection via SSH
virsh --connect qemu+ssh://user@remote-host/system

# Remote connection via TLS
virsh --connect qemu+tls://remote-host/system

# User session (non-root)
virsh --connect qemu:///session

# Check current connection
virsh uri

Basic Virsh Commands

Getting Help

# General help
virsh help

# Help for specific command
virsh help list
virsh help start

# List all commands by category
virsh help | less

# Search for commands
virsh help | grep snapshot

Listing Virtual Machines

# List running VMs
virsh list

# List all VMs (including stopped)
virsh list --all

# List VMs with additional details
virsh list --all --title

# List only inactive VMs
virsh list --inactive

# List with more information
virsh list --all --name
virsh list --all --uuid

Example output:

 Id   Name        State
----------------------------
 1    ubuntu-vm   running
 2    centos-vm   running
 -    debian-vm   shut off

VM Information and Details

# Display VM information
virsh dominfo ubuntu-vm

# Show VM ID
virsh domid ubuntu-vm

# Show VM UUID
virsh domuuid ubuntu-vm

# Show VM state
virsh domstate ubuntu-vm

# Display all VM metadata
virsh metadata ubuntu-vm --uri http://example.com/

# Show VM configuration (XML)
virsh dumpxml ubuntu-vm

# Show VM configuration with security info
virsh dumpxml ubuntu-vm --security-info

# Save configuration to file
virsh dumpxml ubuntu-vm > ubuntu-vm.xml

VM Lifecycle Management

Starting Virtual Machines

# Start a VM
virsh start ubuntu-vm

# Start VM and open console
virsh start ubuntu-vm --console

# Start from paused state
virsh start ubuntu-vm --paused

# Force start (ignore errors)
virsh start ubuntu-vm --force-boot

# Start with specific boot device
virsh start ubuntu-vm --boot-device cdrom

Stopping Virtual Machines

# Graceful shutdown (ACPI signal)
virsh shutdown ubuntu-vm

# Shutdown with specific mode
virsh shutdown ubuntu-vm --mode acpi

# Force power off (immediate)
virsh destroy ubuntu-vm

# Reboot VM
virsh reboot ubuntu-vm

# Reboot with ACPI
virsh reboot ubuntu-vm --mode acpi

# Hard reset (like physical reset button)
virsh reset ubuntu-vm

Suspending and Resuming

# Suspend (pause) VM
virsh suspend ubuntu-vm

# Resume suspended VM
virsh resume ubuntu-vm

# Save VM state to disk (hibernate)
virsh save ubuntu-vm /var/lib/libvirt/images/ubuntu-vm.save

# Restore VM from saved state
virsh restore /var/lib/libvirt/images/ubuntu-vm.save

# Save with custom XML for restore
virsh save ubuntu-vm --xml custom.xml /tmp/ubuntu-vm.save

Autostart Configuration

# Enable autostart on host boot
virsh autostart ubuntu-vm

# Disable autostart
virsh autostart ubuntu-vm --disable

# Check autostart status
virsh dominfo ubuntu-vm | grep Autostart

Deleting Virtual Machines

# Undefine VM (remove configuration, keep disk)
virsh undefine ubuntu-vm

# Undefine and remove all storage
virsh undefine ubuntu-vm --remove-all-storage

# Undefine with snapshots
virsh undefine ubuntu-vm --snapshots-metadata

# Undefine with managed save
virsh undefine ubuntu-vm --managed-save

# Complete removal
virsh undefine ubuntu-vm \
  --remove-all-storage \
  --snapshots-metadata \
  --managed-save

Creating and Defining Virtual Machines

Creating VM from XML

# Create VM configuration XML
cat > ubuntu-vm.xml << 'EOF'
<domain type='kvm'>
  <name>ubuntu-vm</name>
  <memory unit='GiB'>4</memory>
  <vcpu placement='static'>2</vcpu>
  <os>
    <type arch='x86_64' machine='pc'>hvm</type>
    <boot dev='hd'/>
  </os>
  <devices>
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/ubuntu-vm.qcow2'/>
      <target dev='vda' bus='virtio'/>
    </disk>
    <interface type='network'>
      <source network='default'/>
      <model type='virtio'/>
    </interface>
    <graphics type='vnc' port='-1' autoport='yes'/>
    <console type='pty'/>
  </devices>
</domain>
EOF

# Define VM from XML
virsh define ubuntu-vm.xml

# Create and start immediately
virsh create ubuntu-vm.xml

# Define but don't start
virsh define ubuntu-vm.xml

Using virt-install with virsh

# Create VM with virt-install
virt-install \
  --name ubuntu-vm \
  --memory 4096 \
  --vcpus 2 \
  --disk path=/var/lib/libvirt/images/ubuntu-vm.qcow2,size=20 \
  --os-variant ubuntu22.04 \
  --network network=default,model=virtio \
  --graphics vnc \
  --cdrom /var/lib/libvirt/images/ubuntu-22.04.iso \
  --print-xml > ubuntu-vm.xml

# Review and modify XML before defining
vim ubuntu-vm.xml

# Define the VM
virsh define ubuntu-vm.xml

Editing VM Configuration

Interactive XML Editing

# Edit VM configuration
virsh edit ubuntu-vm

# This opens the VM XML in your default editor
# Changes are validated before saving

Modifying VM Settings

# Change VM description
virsh desc ubuntu-vm "Ubuntu 22.04 web server"

# View description
virsh desc ubuntu-vm

# Change VM title
virsh metadata ubuntu-vm \
  --uri http://libvirt.org/title \
  --key title \
  --set "Production Web Server"

# Set custom metadata
virsh metadata ubuntu-vm \
  --uri http://example.com/ \
  --key environment \
  --set "production"

Resource Modification

# Change maximum memory (requires VM restart)
virsh setmaxmem ubuntu-vm 8G --config

# Change current memory (live)
virsh setmem ubuntu-vm 4G --live

# Change memory permanently
virsh setmem ubuntu-vm 4G --config

# View memory settings
virsh dommemstat ubuntu-vm

# Change vCPU count
virsh setvcpus ubuntu-vm 4 --config --maximum
virsh setvcpus ubuntu-vm 4 --config
virsh setvcpus ubuntu-vm 4 --live

# View CPU info
virsh vcpucount ubuntu-vm
virsh vcpuinfo ubuntu-vm

VM Resource Management

CPU Management

# Pin vCPU to physical CPU
virsh vcpupin ubuntu-vm 0 0
virsh vcpupin ubuntu-vm 1 1

# View CPU pinning
virsh vcpupin ubuntu-vm

# Unpin vCPU (allow scheduling on any CPU)
virsh vcpupin ubuntu-vm 0 0-7

# Set CPU shares (scheduling priority)
virsh schedinfo ubuntu-vm --set cpu_shares=2048

# View scheduler info
virsh schedinfo ubuntu-vm

# Show CPU statistics
virsh cpu-stats ubuntu-vm --total

Memory Management

# Set memory balloon target
virsh setmem ubuntu-vm 2G

# View memory statistics
virsh dommemstat ubuntu-vm

# Set memory parameters
virsh memtune ubuntu-vm --hard-limit 8388608 --soft-limit 4194304

# View memory tuning
virsh memtune ubuntu-vm

# Get memory balloon info
virsh dominfo ubuntu-vm | grep memory

Disk Management

# List VM disks
virsh domblklist ubuntu-vm

# Show disk statistics
virsh domblkstat ubuntu-vm vda

# Attach new disk to running VM
virsh attach-disk ubuntu-vm \
  /var/lib/libvirt/images/ubuntu-vm-disk2.qcow2 \
  vdb \
  --driver qemu \
  --subdriver qcow2 \
  --type disk \
  --live

# Attach disk permanently
virsh attach-disk ubuntu-vm \
  /var/lib/libvirt/images/ubuntu-vm-disk2.qcow2 \
  vdb \
  --driver qemu \
  --subdriver qcow2 \
  --config --persistent

# Detach disk
virsh detach-disk ubuntu-vm vdb --live
virsh detach-disk ubuntu-vm vdb --config

# Resize disk
virsh blockresize ubuntu-vm vda 50G

# Get disk info
virsh domblkinfo ubuntu-vm vda

Network Interface Management

# List VM network interfaces
virsh domiflist ubuntu-vm

# Show interface statistics
virsh domifstat ubuntu-vm vnet0

# Attach network interface
virsh attach-interface ubuntu-vm \
  --type network \
  --source default \
  --model virtio \
  --config --live

# Detach network interface
virsh detach-interface ubuntu-vm \
  --type network \
  --mac 52:54:00:xx:xx:xx \
  --config

# Get interface details
virsh domif-getlink ubuntu-vm vnet0

# Set link state
virsh domif-setlink ubuntu-vm vnet0 up
virsh domif-setlink ubuntu-vm vnet0 down

Storage Pool Management

Listing Storage Pools

# List all storage pools
virsh pool-list --all

# List active pools
virsh pool-list

# List inactive pools
virsh pool-list --inactive

# List with detailed info
virsh pool-list --all --details

Creating Storage Pools

# Create directory-based storage pool
virsh pool-define-as mypool dir \
  --target /var/lib/libvirt/pools/mypool

# Build the pool
virsh pool-build mypool

# Start the pool
virsh pool-start mypool

# Set pool to autostart
virsh pool-autostart mypool

# One-line pool creation
virsh pool-define-as mypool dir --target /var/lib/libvirt/pools/mypool && \
virsh pool-build mypool && \
virsh pool-start mypool && \
virsh pool-autostart mypool

Storage Pool Operations

# Show pool information
virsh pool-info mypool

# Display pool XML
virsh pool-dumpxml mypool

# Refresh pool (scan for new volumes)
virsh pool-refresh mypool

# Delete pool (destroy)
virsh pool-destroy mypool

# Undefine pool
virsh pool-undefine mypool

# Delete pool storage
virsh pool-delete mypool

Volume Management

# List volumes in pool
virsh vol-list mypool

# Create new volume
virsh vol-create-as mypool \
  ubuntu-vm-disk.qcow2 \
  20G \
  --format qcow2

# Clone volume
virsh vol-clone \
  --pool mypool \
  ubuntu-vm-disk.qcow2 \
  ubuntu-vm-disk-clone.qcow2

# Delete volume
virsh vol-delete --pool mypool ubuntu-vm-disk.qcow2

# Show volume info
virsh vol-info --pool mypool ubuntu-vm-disk.qcow2

# Get volume path
virsh vol-path --pool mypool ubuntu-vm-disk.qcow2

# Resize volume
virsh vol-resize --pool mypool ubuntu-vm-disk.qcow2 30G

# Upload to volume
virsh vol-upload --pool mypool ubuntu-vm-disk.qcow2 /path/to/image.qcow2

# Download from volume
virsh vol-download --pool mypool ubuntu-vm-disk.qcow2 /backup/image.qcow2

Network Management

Listing Networks

# List all networks
virsh net-list --all

# List active networks
virsh net-list

# List inactive networks
virsh net-list --inactive

Creating Virtual Networks

# Create NAT network
cat > nat-network.xml << 'EOF'
<network>
  <name>nat-network</name>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='virbr1' stp='on' delay='0'/>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.100.2' end='192.168.100.254'/>
    </dhcp>
  </ip>
</network>
EOF

virsh net-define nat-network.xml
virsh net-start nat-network
virsh net-autostart nat-network

# Create isolated network
cat > isolated-network.xml << 'EOF'
<network>
  <name>isolated-network</name>
  <bridge name='virbr-iso' stp='on' delay='0'/>
  <ip address='10.0.0.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='10.0.0.2' end='10.0.0.254'/>
    </dhcp>
  </ip>
</network>
EOF

virsh net-define isolated-network.xml
virsh net-start isolated-network
virsh net-autostart isolated-network

# Create bridge network (for existing bridge)
cat > bridge-network.xml << 'EOF'
<network>
  <name>bridge-network</name>
  <forward mode='bridge'/>
  <bridge name='br0'/>
</network>
EOF

virsh net-define bridge-network.xml
virsh net-start bridge-network

Network Operations

# Show network information
virsh net-info default

# Display network XML
virsh net-dumpxml default

# Edit network
virsh net-edit default

# Start network
virsh net-start nat-network

# Stop network
virsh net-destroy nat-network

# Set network to autostart
virsh net-autostart nat-network

# Disable autostart
virsh net-autostart nat-network --disable

# Delete network
virsh net-undefine nat-network

# Show DHCP leases
virsh net-dhcp-leases default

Network DHCP Management

# Add static DHCP entry
virsh net-update default add ip-dhcp-host \
  "<host mac='52:54:00:xx:xx:xx' name='webserver' ip='192.168.122.10'/>" \
  --live --config

# Remove DHCP entry
virsh net-update default delete ip-dhcp-host \
  "<host mac='52:54:00:xx:xx:xx'/>" \
  --live --config

# Add DHCP range
virsh net-update default add ip-dhcp-range \
  "<range start='192.168.122.100' end='192.168.122.200'/>" \
  --live --config

# View all DHCP leases
virsh net-dhcp-leases default --mac 52:54:00:xx:xx:xx

Snapshot Management

Creating Snapshots

# Create snapshot
virsh snapshot-create-as ubuntu-vm \
  snapshot1 \
  "Clean install state"

# Create snapshot with custom XML
virsh snapshot-create ubuntu-vm

# Create snapshot with disk state
virsh snapshot-create-as ubuntu-vm snapshot2 \
  "Before updates" \
  --disk-only

# Create snapshot without memory state (faster)
virsh snapshot-create-as ubuntu-vm snapshot3 \
  "Quick snapshot" \
  --no-metadata

# Create snapshot with specific disk
virsh snapshot-create-as ubuntu-vm snapshot4 \
  --diskspec vda,file=/var/lib/libvirt/images/snap4.qcow2

Listing Snapshots

# List all snapshots
virsh snapshot-list ubuntu-vm

# List with tree view
virsh snapshot-list ubuntu-vm --tree

# List with detailed info
virsh snapshot-list ubuntu-vm --details

# Show current snapshot
virsh snapshot-current ubuntu-vm

# Show current snapshot name only
virsh snapshot-current ubuntu-vm --name

Snapshot Operations

# Show snapshot info
virsh snapshot-info ubuntu-vm snapshot1

# Display snapshot XML
virsh snapshot-dumpxml ubuntu-vm snapshot1

# Revert to snapshot
virsh snapshot-revert ubuntu-vm snapshot1

# Revert and start VM
virsh snapshot-revert ubuntu-vm snapshot1 --running

# Delete snapshot
virsh snapshot-delete ubuntu-vm snapshot1

# Delete snapshot and children
virsh snapshot-delete ubuntu-vm snapshot1 --children

# Delete snapshot metadata only
virsh snapshot-delete ubuntu-vm snapshot1 --metadata

Snapshot Parent-Child Relationships

# Show snapshot parent
virsh snapshot-parent ubuntu-vm snapshot2

# Show snapshot children
virsh snapshot-list ubuntu-vm --tree

# Create child snapshot
virsh snapshot-create-as ubuntu-vm child-snapshot \
  "Child of snapshot1" \
  --parent snapshot1

Console and Display Management

Accessing VM Console

# Connect to serial console
virsh console ubuntu-vm

# Exit console: Ctrl+]

# Connect with safe console
virsh console ubuntu-vm --safe

# Force console reconnect
virsh console ubuntu-vm --force

VNC Display Management

# Show VNC display
virsh vncdisplay ubuntu-vm

# Output: :0 (means port 5900)

# Connect with VNC viewer
virt-viewer ubuntu-vm

# Remote VNC connection
virt-viewer -c qemu+ssh://user@host/system ubuntu-vm

# Change VNC password
virsh domdisplay ubuntu-vm

Graphics and Display

# Get display URI
virsh domdisplay ubuntu-vm

# Set graphics password
virsh edit ubuntu-vm
# Add in graphics section:
# <graphics type='vnc' passwd='yourpassword'/>

# Take screenshot
virsh screenshot ubuntu-vm /tmp/screenshot.ppm

# Convert to common format
convert /tmp/screenshot.ppm /tmp/screenshot.png

Monitoring and Statistics

System Resource Monitoring

# Real-time VM statistics
virt-top

# Show domain statistics
virsh domstats ubuntu-vm

# CPU statistics
virsh cpu-stats ubuntu-vm --total

# Per-CPU statistics
virsh cpu-stats ubuntu-vm

# Memory statistics
virsh dommemstat ubuntu-vm

# Block device stats
virsh domblkstat ubuntu-vm vda

# Block device info
virsh domblkinfo ubuntu-vm vda

# Network interface statistics
virsh domifstat ubuntu-vm vnet0

Performance Monitoring

# Get VM job info (for long-running operations)
virsh domjobinfo ubuntu-vm

# Monitor block I/O tuning
virsh blkiotune ubuntu-vm

# Set I/O weight
virsh blkiotune ubuntu-vm --weight 500

# Get VM time info
virsh domtime ubuntu-vm

# Set VM time
virsh domtime ubuntu-vm --now

# Show control info
virsh domcontrol ubuntu-vm

# Show state reason
virsh domstate ubuntu-vm --reason

Event Monitoring

# Monitor all events
virsh event --all

# Monitor events for specific domain
virsh event --domain ubuntu-vm

# Monitor lifecycle events
virsh event --event lifecycle

# Monitor specific event types
virsh event --event reboot
virsh event --event shutdown

# List event types
virsh event --list

Advanced Operations

Live Migration Preparation

# Check migration capabilities
virsh capabilities

# Get VM XML for migration planning
virsh dumpxml ubuntu-vm > ubuntu-vm-migrate.xml

# Test migration viability
virsh migrate --verbose --live --p2p ubuntu-vm \
  qemu+ssh://destination-host/system \
  --dry-run

VM Cloning

# Clone VM (VM must be shut down)
virt-clone --original ubuntu-vm \
  --name ubuntu-vm-clone \
  --file /var/lib/libvirt/images/ubuntu-vm-clone.qcow2

# Clone with auto name
virt-clone --original ubuntu-vm --auto-clone

# Clone specific disks only
virt-clone --original ubuntu-vm \
  --name ubuntu-vm-clone \
  --file /var/lib/libvirt/images/disk1.qcow2 \
  --file /var/lib/libvirt/images/disk2.qcow2

Backup and Restore

# Backup VM configuration
virsh dumpxml ubuntu-vm > /backup/ubuntu-vm-config.xml

# Backup including sensitive info
virsh dumpxml ubuntu-vm --security-info > /backup/ubuntu-vm-full.xml

# Backup disk
virsh domblklist ubuntu-vm
cp /var/lib/libvirt/images/ubuntu-vm.qcow2 /backup/

# Restore VM
virsh define /backup/ubuntu-vm-config.xml
cp /backup/ubuntu-vm.qcow2 /var/lib/libvirt/images/
virsh start ubuntu-vm

# Block-copy for live backup
virsh blockcommit ubuntu-vm vda --active --pivot

Managing Saved States

# Save VM state to file
virsh save ubuntu-vm /var/lib/libvirt/save/ubuntu-vm.save

# Save with description
virsh save ubuntu-vm /var/lib/libvirt/save/ubuntu-vm.save \
  "Pre-upgrade state"

# Restore VM from saved state
virsh restore /var/lib/libvirt/save/ubuntu-vm.save

# Show saved state info
virsh save-image-dumpxml /var/lib/libvirt/save/ubuntu-vm.save

# Edit saved state XML
virsh save-image-edit /var/lib/libvirt/save/ubuntu-vm.save

# Define new XML for restore
virsh save-image-define /var/lib/libvirt/save/ubuntu-vm.save new-config.xml

Security and Access Control

Access Control Lists

# Set VM permissions
virsh edit ubuntu-vm

# Add security labels (SELinux example)
<seclabel type='dynamic' model='selinux' relabel='yes'>
  <label>system_u:system_r:svirt_t:s0:c100,c200</label>
  <imagelabel>system_u:object_r:svirt_image_t:s0:c100,c200</imagelabel>
</seclabel>

Managing Secrets

# Define secret (for encrypted disks, etc.)
cat > secret.xml << 'EOF'
<secret ephemeral='no' private='yes'>
  <description>LUKS encryption key</description>
  <uuid>12345678-1234-1234-1234-123456789abc</uuid>
</secret>
EOF

virsh secret-define secret.xml

# Set secret value
virsh secret-set-value 12345678-1234-1234-1234-123456789abc \
  $(echo -n "secretpassword" | base64)

# List secrets
virsh secret-list

# Get secret value
virsh secret-get-value 12345678-1234-1234-1234-123456789abc

# Delete secret
virsh secret-undefine 12345678-1234-1234-1234-123456789abc

Troubleshooting with Virsh

Debugging VM Issues

# Get detailed error information
virsh domstate ubuntu-vm --reason

# Check VM control state
virsh domcontrol ubuntu-vm

# View domain job info
virsh domjobinfo ubuntu-vm

# Dump VM core for analysis
virsh dump ubuntu-vm /tmp/ubuntu-vm.dump --memory-only

# Reset VM (hard reset)
virsh reset ubuntu-vm

# Send key sequence to VM
virsh send-key ubuntu-vm KEY_LEFTCTRL KEY_LEFTALT KEY_DELETE

Libvirt Daemon Management

# Check libvirt version
virsh version

# Get system information
virsh sysinfo

# Show host capabilities
virsh capabilities

# Get host information
virsh nodeinfo

# Show memory statistics
virsh nodememstats

# Show CPU statistics
virsh nodecpustats

# Get host CPU map
virsh nodecpumap

# Suspend host
virsh nodesuspend mem 3600

# Get libvirt daemon status
systemctl status libvirtd

# Restart libvirt daemon
systemctl restart libvirtd

Common Issues and Solutions

Issue: VM won't start

# Check detailed state
virsh domstate ubuntu-vm --reason

# Verify disk exists
virsh domblklist ubuntu-vm

# Check disk permissions
ls -l /var/lib/libvirt/images/

# Validate XML
virsh define ubuntu-vm.xml

# Check logs
journalctl -u libvirtd -f
tail -f /var/log/libvirt/qemu/ubuntu-vm.log

Issue: Cannot connect to console

# Verify console is configured
virsh dumpxml ubuntu-vm | grep console

# Try different console type
virsh console ubuntu-vm --devname serial0

# Check if VM is responding
virsh domstate ubuntu-vm

Issue: Network not working

# Check network is active
virsh net-list

# Start network if needed
virsh net-start default

# Verify VM network interface
virsh domiflist ubuntu-vm

# Check DHCP leases
virsh net-dhcp-leases default

Automation and Scripting

Batch Operations

#!/bin/bash
# Start all VMs
for vm in $(virsh list --name --inactive); do
    echo "Starting $vm..."
    virsh start "$vm"
done

# Stop all running VMs gracefully
for vm in $(virsh list --name); do
    echo "Shutting down $vm..."
    virsh shutdown "$vm"
done

# Create snapshots for all VMs
for vm in $(virsh list --name --all); do
    snapshot_name="snapshot-$(date +%Y%m%d-%H%M%S)"
    echo "Creating snapshot $snapshot_name for $vm"
    virsh snapshot-create-as "$vm" "$snapshot_name" "Automated snapshot"
done

Resource Monitoring Script

#!/bin/bash
# Monitor VM resources

while true; do
    clear
    echo "=== VM Resource Usage ==="
    echo ""

    for vm in $(virsh list --name); do
        echo "VM: $vm"

        # CPU usage
        cpu_time=$(virsh cpu-stats "$vm" --total | grep "cpu_time" | awk '{print $3}')
        echo "  CPU Time: $cpu_time seconds"

        # Memory usage
        virsh dommemstat "$vm" | head -n 4

        # Disk usage
        virsh domblkstat "$vm" vda | head -n 2

        echo ""
    done

    sleep 5
done

Backup Automation

#!/bin/bash
# Automated VM backup script

BACKUP_DIR="/backup/vms"
DATE=$(date +%Y%m%d)

mkdir -p "$BACKUP_DIR"

for vm in $(virsh list --name --all); do
    echo "Backing up $vm..."

    # Backup configuration
    virsh dumpxml "$vm" > "$BACKUP_DIR/${vm}-${DATE}.xml"

    # Create snapshot
    virsh snapshot-create-as "$vm" "backup-$DATE"

    # Backup disk (if VM is shut down)
    if [ "$(virsh domstate $vm)" = "shut off" ]; then
        disk=$(virsh domblklist "$vm" | grep vda | awk '{print $2}')
        if [ -n "$disk" ]; then
            cp "$disk" "$BACKUP_DIR/${vm}-${DATE}.qcow2"
        fi
    fi
done

echo "Backup completed"

Performance Optimization

Tuning VM Performance

# Set CPU mode to host-passthrough
virsh edit ubuntu-vm
# Change: <cpu mode='host-passthrough'/>

# Enable CPU cache passthrough
<cpu mode='host-passthrough'>
  <cache mode='passthrough'/>
</cpu>

# Set I/O thread pinning
virsh edit ubuntu-vm
<iothreads>2</iothreads>
<iothreadids>
  <iothread id='1'/>
  <iothread id='2'/>
</iothreadids>

# Pin I/O threads
virsh iothreadpin ubuntu-vm 1 0-3
virsh iothreadpin ubuntu-vm 2 4-7

# Set memory backing
<memoryBacking>
  <hugepages/>
  <nosharepages/>
  <locked/>
</memoryBacking>

Block Device Tuning

# Set I/O tuning parameters
virsh blkiotune ubuntu-vm --device /dev/vda --total-bytes-sec 104857600
virsh blkiotune ubuntu-vm --device /dev/vda --read-bytes-sec 52428800
virsh blkiotune ubuntu-vm --device /dev/vda --write-bytes-sec 52428800

# Set block I/O throttling
virsh blockresize ubuntu-vm vda 50G

Conclusion

Virsh is an indispensable tool for managing KVM/QEMU virtual machines, providing comprehensive control over every aspect of virtualization infrastructure. This guide has covered the essential commands and operations needed for day-to-day VM management, from basic lifecycle operations to advanced tuning and troubleshooting.

Key takeaways:

  • Virsh provides scriptable, automation-friendly VM management
  • Master basic operations (start, stop, list) before moving to advanced features
  • Understand storage pools and networks for efficient resource management
  • Use snapshots strategically for backup and testing workflows
  • Monitor VM performance regularly to identify bottlenecks
  • Leverage virsh in scripts for automation and batch operations

As you gain proficiency with virsh, you'll discover it's the most efficient way to manage virtualization infrastructure, especially when combined with configuration management tools like Ansible or Terraform. The command-line interface enables powerful automation possibilities that graphical tools cannot match.

Continue exploring advanced virsh features like live migration, NUMA tuning, and CPU pinning to optimize performance for production workloads. With virsh mastery, you'll be able to manage large-scale virtualization environments with confidence and efficiency.