Skip to content

Instantly share code, notes, and snippets.

@shamil
Last active February 27, 2025 16:07
Show Gist options
  • Save shamil/62935d9b456a6f9877b5 to your computer and use it in GitHub Desktop.
Save shamil/62935d9b456a6f9877b5 to your computer and use it in GitHub Desktop.
How to mount a qcow2 disk image

How to mount a qcow2 disk image

This is a quick guide to mounting a qcow2 disk images on your host server. This is useful to reset passwords, edit files, or recover something without the virtual machine running.

Step 1 - Enable NBD on the Host

modprobe nbd max_part=8

Step 2 - Connect the QCOW2 as network block device

qemu-nbd --connect=/dev/nbd0 /var/lib/vz/images/100/vm-100-disk-1.qcow2

Step 3 - Find The Virtual Machine Partitions

fdisk /dev/nbd0 -l

Step 4 - Mount the partition from the VM

mount /dev/nbd0p1 /mnt/somepoint/

Step 5 - After you done, unmount and disconnect

umount /mnt/somepoint/
qemu-nbd --disconnect /dev/nbd0
rmmod nbd
@Kreijstal
Copy link

Kreijstal commented Feb 6, 2025

Expanding a partitiion:

#!/bin/bash

# Script to expand the disk and Btrfs filesystem of an Arch Linux VM managed by virsh.
# This script performs *offline* filesystem resizing on the host.
# The VM is NOT booted during filesystem resize.
# *** IMPORTANT: THIS SCRIPT NOW INCLUDES BTRFS BALANCE FOR COMPLETE RESIZE ***

# --- Configuration ---
VM_NAME="archlinux"
QCOW2_IMAGE="/home/kreijstal/Downloads/vm/Arch-Linux-x86_64-basic-20240201.210938.qcow2"
SIZE_TO_ADD="40G"  # Amount to add to the existing virtual size
NBD_DEVICE="/dev/nbd0"
PARTITION_NUMBER=3  # Partition number to expand (usually root)
FILESYSTEM_TYPE="btrfs" # Filesystem type: btrfs, ext4, xfs (adjust if needed)
MOUNT_POINT="/mnt" # Mount point on the host for filesystem resize

# --- Step 1: Resize the .qcow2 image ---
echo "Step 1: Resizing qcow2 image..."
qemu-img resize "$QCOW2_IMAGE" "+$SIZE_TO_ADD"
if [ $? -ne 0 ]; then
  echo "Error resizing qcow2 image. Aborting."
  exit 1
fi
echo "qcow2 image resized."

# --- Step 2: Load the NBD kernel module ---
echo "Step 2: Loading NBD kernel module..."
sudo modprobe nbd max_part=8
if [ $? -ne 0 ]; then
  echo "Error loading NBD module. Aborting."
  exit 1
fi
echo "NBD module loaded."

# --- Step 3: Connect the qcow2 image to an NBD device ---
echo "Step 3: Connecting qcow2 image to NBD device..."
sudo qemu-nbd --connect="$NBD_DEVICE" "$QCOW2_IMAGE"
if [ $? -ne 0 ]; then
  echo "Error connecting qcow2 image to NBD device. Aborting."
  exit 1
fi
echo "qcow2 image connected to NBD device."

# --- Step 4: Fix the GPT backup header location ---
echo "Step 4: Fixing GPT backup header..."
sudo sgdisk -e "$NBD_DEVICE"
if [ $? -ne 0 ]; then
  echo "Error fixing GPT backup header. Proceeding anyway (may be non-critical)."
fi
echo "GPT backup header fixed (or attempted)."

# --- Step 5: Expand the partition using parted ---
echo "Step 5: Expanding partition $PARTITION_NUMBER using parted..."
sudo parted "$NBD_DEVICE" resizepart "$PARTITION_NUMBER" 100% -s
if [ $? -ne 0 ]; then
  echo "Error expanding partition. Aborting."
  sudo qemu-nbd --disconnect "$NBD_DEVICE"
  sudo rmmod nbd
  exit 1
fi
echo "Partition $PARTITION_NUMBER expanded."

# --- Step 6: Mount the resized partition on the host ---
echo "Step 6: Mounting partition $PARTITION_NUMBER on $MOUNT_POINT..."
sudo mount "${NBD_DEVICE}p${PARTITION_NUMBER}" "$MOUNT_POINT"
if [ $? -ne 0 ]; then
  echo "Error mounting partition. Aborting."
  sudo qemu-nbd --disconnect "$NBD_DEVICE"
  sudo rmmod nbd
  exit 1
fi
echo "Partition ${PARTITION_NUMBER} mounted on $MOUNT_POINT."

# --- Step 7: Resize the filesystem on the host ---
echo "Step 7: Resizing $FILESYSTEM_TYPE filesystem on the host..."
if [ "$FILESYSTEM_TYPE" = "btrfs" ]; then
  FS_RESIZE_COMMAND="sudo btrfs filesystem resize max $MOUNT_POINT"
elif [ "$FILESYSTEM_TYPE" = "ext4" ]; then
  FS_RESIZE_COMMAND="sudo resize2fs ${NBD_DEVICE}p${PARTITION_NUMBER}"
elif [ "$FILESYSTEM_TYPE" = "xfs" ]; then
  FS_RESIZE_COMMAND="sudo xfs_growfs $MOUNT_POINT" # xfs_growfs on mount point
else
  echo "Error: Unsupported filesystem type '$FILESYSTEM_TYPE' for offline resize in script."
  echo "Please resize the filesystem manually after booting the VM."
  FS_RESIZE_COMMAND="" # No command to run
fi

if [ -n "$FS_RESIZE_COMMAND" ]; then
  eval "$FS_RESIZE_COMMAND" # Execute the filesystem resize command
  if [ $? -ne 0 ]; then
    echo "Error resizing $FILESYSTEM_TYPE filesystem. Aborting."
    sudo umount "$MOUNT_POINT"
    sudo qemu-nbd --disconnect "$NBD_DEVICE"
    sudo rmmod nbd
    exit 1
  fi
  echo "$FILESYSTEM_TYPE filesystem resized."

  # --- Step 8: Balance Btrfs filesystem (REQUIRED for Btrfs to use new space) ---
  if [ "$FILESYSTEM_TYPE" = "btrfs" ]; then
    echo "Step 8: Balancing Btrfs filesystem (REQUIRED)..."
    sudo btrfs balance start --full-balance "$MOUNT_POINT"
    if [ $? -ne 0 ]; then
      echo "Warning: Error running btrfs balance (non-critical, but recommended to check manually)."
    else
      echo "Btrfs balance completed."
    fi
  fi
fi

# --- Step 9: Unmount the partition from the host ---
echo "Step 9: Unmounting partition from $MOUNT_POINT..."
sudo umount "$MOUNT_POINT"
if [ $? -ne 0 ]; then
  echo "Warning: Error unmounting $MOUNT_POINT (may need manual unmount)."
fi
echo "Partition unmounted from $MOUNT_POINT."


# --- Step 10: Disconnect the NBD device and unload the module (cleanup) ---
echo "Step 10: Disconnecting NBD device and unloading module..."
sudo qemu-nbd --disconnect="$NBD_DEVICE"
sudo rmmod nbd
echo "NBD device disconnected and module unloaded."

# --- Step 11: Start the VM ---
echo "Step 11: Starting VM '$VM_NAME'..."
virsh start "$VM_NAME"
if [ $? -ne 0 ]; then
  echo "Error starting VM '$VM_NAME'. Please check virsh logs."
  exit 1
fi
echo "VM '$VM_NAME' started."

echo "--- Disk and Filesystem Expansion Process Completed (Offline) ---"
echo "--- Log in to your VM to verify the expanded filesystem using 'df -h /' ---"

exit 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment