dotlinux guide

Virtualization Automation with Shell Scripting Tools: A Comprehensive Guide

Table of Contents

  1. Fundamentals of Virtualization Automation
  2. Key Tools for Virtualization Automation
  3. Usage Methods: Automating Common Virtualization Tasks
  4. Common Practices in Virtualization Automation
  5. Best Practices for Shell Scripting in Virtualization
  6. Conclusion
  7. References

1. Fundamentals of Virtualization Automation

1.1 What is Virtualization?

Virtualization is the process of creating a software-based (virtual) representation of physical resources, such as servers, storage, or networks. The primary goal is to abstract physical hardware, enabling multiple virtual environments (e.g., VMs) to run on a single physical host. Key components include:

  • Hypervisor: Software that manages VMs (e.g., KVM, VirtualBox, VMware ESXi).
  • VM: A guest operating system (OS) and applications running on virtualized resources.
  • Virtual Resources: CPU, memory, storage, and network interfaces allocated to VMs.

Hypervisors are categorized into:

  • Type 1 (Bare-Metal): Run directly on hardware (e.g., KVM, VMware ESXi).
  • Type 2 (Hosted): Run on top of a host OS (e.g., VirtualBox, VMware Workstation).

1.2 Why Shell Scripting for Virtualization Automation?

Shell scripting (e.g., Bash, Zsh) is ideal for automating virtualization tasks due to:

  • Accessibility: Preinstalled on nearly all Unix-like systems (Linux, macOS).
  • CLI Integration: Hypervisors expose command-line interfaces (CLIs) (e.g., virsh, VBoxManage), which shell scripts can call directly.
  • Flexibility: Supports logic (conditionals, loops), variables, and integration with other tools (e.g., awk, sed, curl).
  • Lightweight: No need for heavy dependencies (unlike Python or Go for simple tasks).

Shell scripts automate repetitive workflows like VM provisioning, backups, and lifecycle management, reducing manual effort and human error.

2. Key Tools for Virtualization Automation

Most hypervisors provide CLI tools to manage VMs. Below are the most common tools and their use cases:

ToolHypervisorKey FeaturesExample Command
virshKVM/QEMU (libvirt)Define, create, start/stop VMs; manage resourcesvirsh start my-vm
VBoxManageVirtualBoxCreate VMs, manage disks, networkingVBoxManage createvm --name my-vm
vmrunVMwareControl VMs, take snapshots, deploy OVAsvmrun start /path/to/vm.vmx
qemu-imgKVM/QEMUCreate/manage disk images (qcow2, raw)qemu-img create -f qcow2 disk.qcow2 20G

2.1 libvirt/virsh (KVM/QEMU)

libvirt is an open-source API for managing virtualization, and virsh is its command-line interface. It supports KVM, QEMU, Xen, and more. virsh is widely used in enterprise Linux environments for KVM management.

2.2 VBoxManage (VirtualBox)

VBoxManage is the CLI for Oracle VirtualBox, a popular type-2 hypervisor. It handles VM creation, disk management, and networking, making it ideal for development or small-scale deployments.

2.3 vmrun (VMware)

vmrun controls VMware VMs (Workstation, Fusion, ESXi). It supports starting/stopping VMs, taking snapshots, and deploying OVA/OVF templates.

2.4 qemu-img (Disk Management)

qemu-img creates and manipulates disk images (e.g., qcow2, raw, vmdk). It is critical for pre-provisioning storage for VMs in KVM environments.

3. Usage Methods: Automating Common Virtualization Tasks

Below are practical examples of automating key virtualization workflows with shell scripts.

3.1 Creating and Provisioning VMs

Example 1: Create a KVM VM with virsh

This script creates a VM from an XML definition file, allocates storage with qemu-img, and starts the VM.

#!/bin/bash
# create_kvm_vm.sh
set -euo pipefail  # Exit on errors, unset vars, and pipeline failures

VM_NAME="web-server"
DISK_PATH="/var/lib/libvirt/images/${VM_NAME}.qcow2"
RAM_MB="2048"  # 2GB
VCPUS="2"
OS_ISO="/iso/ubuntu-22.04.iso"  # Path to OS installer ISO

# Step 1: Create disk image
echo "Creating disk image..."
qemu-img create -f qcow2 "$DISK_PATH" 20G  # 20GB disk

# Step 2: Define VM XML (simplified example)
VM_XML=$(cat <<EOF
<domain type='kvm'>
  <name>${VM_NAME}</name>
  <memory unit='MiB'>${RAM_MB}</memory>
  <vcpu placement='static'>${VCPUS}</vcpu>
  <os>
    <type arch='x86_64' machine='pc-q35-7.2'>hvm</type>
    <boot dev='cdrom'/>
  </os>
  <devices>
    <disk type='file' device='disk'>
      <source file='${DISK_PATH}'/>
      <target dev='vda' bus='virtio'/>
    </disk>
    <cdrom type='file'>
      <source file='${OS_ISO}'/>
      <target dev='sda' bus='sata'/>
    </cdrom>
    <interface type='network'>
      <source network='default'/>  # Use default libvirt network
    </interface>
  </devices>
</domain>
EOF
)

# Step 3: Define and start the VM
echo "Defining VM..."
echo "$VM_XML" | virsh define --file /dev/stdin

echo "Starting VM..."
virsh start "$VM_NAME"

# Verify status
echo "VM status:"
virsh list --all | grep "$VM_NAME"

Example 2: Create a VirtualBox VM with VBoxManage

This script creates a VirtualBox VM, attaches a disk, and configures networking.

#!/bin/bash
# create_vbox_vm.sh
set -euo pipefail

VM_NAME="dev-vm"
VM_DIR="$HOME/VirtualBox VMs/${VM_NAME}"
DISK_SIZE="20480"  # 20GB (in MB)
RAM_MB="2048"
VCPUS="2"
ISO_PATH="$HOME/isos/ubuntu-22.04.iso"

# Create VM directory
mkdir -p "$VM_DIR"

# Create VM
VBoxManage createvm --name "$VM_NAME" --ostype Ubuntu_64 --register

# Configure memory and CPU
VBoxManage modifyvm "$VM_NAME" --memory "$RAM_MB" --cpus "$VCPUS"

# Create and attach disk
VBoxManage createmedium disk --filename "${VM_DIR}/${VM_NAME}_disk.vdi" --size "$DISK_SIZE" --format VDI
VBoxManage storagectl "$VM_NAME" --name "SATA Controller" --add sata --controller IntelAHCI
VBoxManage storageattach "$VM_NAME" --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium "${VM_DIR}/${VM_NAME}_disk.vdi"

# Attach ISO for installation
VBoxManage storagectl "$VM_NAME" --name "IDE Controller" --add ide
VBoxManage storageattach "$VM_NAME" --storagectl "IDE Controller" --port 0 --device 0 --type dvddrive --medium "$ISO_PATH"

# Configure networking (NAT)
VBoxManage modifyvm "$VM_NAME" --nic1 nat

echo "VM created. Start with: VBoxManage startvm $VM_NAME --type headless"

3.2 Managing VM Lifecycle (Start/Stop/Suspend)

Automate starting/stopping VMs based on schedules (e.g., start dev VMs in the morning, stop them at night).

Example: Lifecycle Management Script

#!/bin/bash
# manage_vm_lifecycle.sh
set -euo pipefail

VM_NAME="dev-vm"
ACTION="$1"  # start/stop/suspend/resume

case "$ACTION" in
  start)
    echo "Starting $VM_NAME..."
    virsh start "$VM_NAME"  # Use VBoxManage startvm for VirtualBox
    ;;
  stop)
    echo "Stopping $VM_NAME..."
    virsh shutdown "$VM_NAME"  # Graceful shutdown; use destroy for force stop
    ;;
  suspend)
    echo "Suspending $VM_NAME..."
    virsh suspend "$VM_NAME"
    ;;
  resume)
    echo "Resuming $VM_NAME..."
    virsh resume "$VM_NAME"
    ;;
  *)
    echo "Usage: $0 [start|stop|suspend|resume]"
    exit 1
    ;;
esac

3.3 Resource Allocation (vCPU, Memory, Storage)

Adjust VM resources dynamically with scripts. For example, scale up memory for a VM during peak usage:

#!/bin/bash
# resize_vm_resources.sh
set -euo pipefail

VM_NAME="app-vm"
NEW_MEMORY_MB="4096"  # 4GB

# Check if VM is running (memory resize requires shutdown for some hypervisors)
if virsh domstate "$VM_NAME" | grep -q "running"; then
  echo "Stopping VM to resize memory..."
  virsh shutdown "$VM_NAME"
  # Wait for VM to stop
  while virsh domstate "$VM_NAME" | grep -q "running"; do
    sleep 5
  done
fi

# Update memory
virsh setmaxmem "$VM_NAME" "$NEW_MEMORY_MB"M --config  # Persistent
virsh setmem "$VM_NAME" "$NEW_MEMORY_MB"M --config      # Current allocation

echo "Memory updated to ${NEW_MEMORY_MB}MB. Starting VM..."
virsh start "$VM_NAME"

3.4 Networking Configuration

Automate virtual network setup (e.g., bridges, NAT) for VMs. This example creates a Linux bridge and attaches a KVM VM to it:

#!/bin/bash
# create_bridge.sh
set -euo pipefail

BRIDGE_NAME="br0"
PHYSICAL_INTERFACE="eth0"  # Replace with your interface

# Install bridge-utils if missing
if ! command -v brctl &> /dev/null; then
  sudo apt-get install -y bridge-utils  # For Debian/Ubuntu
  # sudo yum install -y bridge-utils      # For RHEL/CentOS
fi

# Create bridge
sudo brctl addbr "$BRIDGE_NAME"
sudo brctl addif "$BRIDGE_NAME" "$PHYSICAL_INTERFACE"

# Bring up interfaces
sudo ip link set dev "$PHYSICAL_INTERFACE" up
sudo ip link set dev "$BRIDGE_NAME" up

# Update VM to use the bridge (persistent)
VM_NAME="web-vm"
virsh detach-interface "$VM_NAME" network --config  # Remove default network
virsh attach-interface "$VM_NAME" bridge --source "$BRIDGE_NAME" --model virtio --config

echo "Bridge $BRIDGE_NAME created. VM $VM_NAME attached."

4. Common Practices in Virtualization Automation

4.1 Template-Based Deployment

Instead of creating VMs from scratch, use templates (pre-configured base VMs) to accelerate provisioning. Scripts can clone templates and customize them (e.g., hostname, IP).

Example: Clone a KVM Template with virt-clone

#!/bin/bash
# clone_vm_from_template.sh
set -euo pipefail

TEMPLATE_NAME="ubuntu-template"
NEW_VM_NAME="app-server-01"
NEW_DISK_PATH="/var/lib/libvirt/images/${NEW_VM_NAME}.qcow2"

# Clone the template
virt-clone --original "$TEMPLATE_NAME" --name "$NEW_VM_NAME" --file "$NEW_DISK_PATH"

# Customize the VM (e.g., set hostname via cloud-init or guestfish)
echo "Customizing VM..."
# Example: Use guestfish to edit /etc/hostname (requires libguestfs-tools)
guestfish --rw -a "$NEW_DISK_PATH" <<EOF
run
mount /dev/sda1 /
edit /etc/hostname
$NEW_VM_NAME
EOF

echo "Cloned VM $NEW_VM_NAME from template."

4.2 Integration with Configuration Management

Shell scripts can call tools like Ansible, Puppet, or Chef to configure VMs post-provisioning. For example:

#!/bin/bash
# provision_with_ansible.sh
set -euo pipefail

VM_NAME="db-vm"
ANSIBLE_PLAYBOOK="configure-db.yml"

# Start VM and wait for SSH
virsh start "$VM_NAME"
echo "Waiting for VM to boot..."
while ! ping -c 1 -W 1 "$VM_NAME" &> /dev/null; do
  sleep 5
done

# Run Ansible playbook
ansible-playbook -i "$VM_NAME," "$ANSIBLE_PLAYBOOK" --user ubuntu --key-file ~/.ssh/id_rsa

4.3 Backup and Recovery Automation

Automate VM backups using disk snapshots or image cloning. This script takes a daily snapshot of a KVM VM with qemu-img:

#!/bin/bash
# backup_vm.sh
set -euo pipefail

VM_NAME="critical-vm"
DISK_PATH="/var/lib/libvirt/images/${VM_NAME}.qcow2"
BACKUP_DIR="/backups/vm-snapshots"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${VM_NAME}_snapshot_${TIMESTAMP}.qcow2"

# Create backup dir
mkdir -p "$BACKUP_DIR"

# Take snapshot (internal snapshot for qcow2)
echo "Taking snapshot of $VM_NAME..."
virsh snapshot-create-as --domain "$VM_NAME" --name "backup_${TIMESTAMP}" --description "Daily backup"

# Alternatively: Clone the disk (full backup)
# qemu-img convert -f qcow2 -O qcow2 "$DIS