This document explains the hypervisor abstraction architecture for developers who want to understand, extend, or maintain the multi-hypervisor support.
- Architecture Overview
- Design Principles
- Directory Structure
- Core Components
- Adding a New Hypervisor
- API Reference
- Testing
The abstraction layer provides a single unified API that works across different hypervisors. Scripts use this API instead of calling hypervisor-specific commands directly.
┌──────────────────────────────────────────────────────────┐
│ User Scripts (deploy_rook_ceph.sh, create-vm.sh) │
└────────────────────┬─────────────────────────────────────┘
│ Uses: hv_create_vm(), hv_start_vm(), etc.
┌────────────┴────────────┐
│ lib/hypervisor.sh │ (Abstraction API)
│ - Auto-detection │
│ - Function routing │
│ - Common interface │
└────────┬─────────┬────────┘
│ │
┌────────────┴──┐ ┌──┴─────────────┐
│ proxmox.sh │ │cloudhypervisor.sh│ (Backend Implementations)
│ - qm commands│ │ - ch-remote │
└───────┬───────┘ └────────┬────────┘
│ │
┌───────┴────────┐ ┌───────┴────────┐
│ Proxmox VE │ │Cloud Hypervisor│ (Actual Hypervisors)
│ (qm, pct) │ │ (REST API) │
└────────────────┘ └────────────────┘
# User calls abstraction API
hv_create_vm 4141 "os1" 4 8192
# lib/hypervisor.sh routes to detected hypervisor
if [[ $HV_TYPE == "proxmox" ]]; then
proxmox_create_vm 4141 "os1" 4 8192
elif [[ $HV_TYPE == "cloudhypervisor" ]]; then
cloudhypervisor_create_vm 4141 "os1" 4 8192
fi
# Backend implementation executes hypervisor-specific commands
# Proxmox: qm create 4141 --name os1 --cores 4 --memory 8192
# Cloud Hypervisor: Creates JSON config + directory structureAll hypervisor operations go through lib/hypervisor.sh. No script should call qm or cloud-hypervisor directly.
Bad:
qm start 4141Good:
source lib/hypervisor.sh
hv_init
hv_start_vm 4141The system automatically detects the available hypervisor. Users don't need to configure anything unless they want to override.
# Auto-detect (default)
HYPERVISOR=auto ./deploy_rook_ceph.sh
# Explicit override
HYPERVISOR=cloudhypervisor ./deploy_rook_ceph.shBoth implementations support identical operations. If a feature works on Proxmox, it should work on Cloud Hypervisor (and vice versa).
Existing Proxmox scripts work unchanged. The abstraction is additive only.
If an operation isn't supported or fails, return immediately with a clear error. Don't attempt fallbacks that could cause data loss.
lib/
├── hypervisor.sh # Main abstraction layer (300 lines)
│ # - Detection logic
│ # - API definitions
│ # - Function routing
│
├── hypervisors/ # Backend implementations
│ ├── proxmox.sh # Proxmox VE backend (400 lines)
│ │ # - qm command wrappers
│ └── cloudhypervisor.sh # Cloud Hypervisor backend (800 lines)
│ # - VM lifecycle management
│ # - API socket communication
│
└── common/ # Shared utilities
├── cloudinit.sh # Cloud-init ISO generation (200 lines)
│ # - NoCloud format
│ # - user-data / meta-data
├── network.sh # Network management (200 lines)
│ # - Bridge creation
│ # - TAP device management
└── storage.sh # Storage utilities (300 lines)
# - Disk creation / cloning
# - Format conversion (qcow2 ↔ raw)
Purpose: Main abstraction interface
Key Functions:
detect_hypervisor()- Auto-detect Proxmox or Cloud Hypervisorhv_init()- Initialize hypervisor backendhv_*()- Unified API functions (route to backend)
Initialization:
source lib/hypervisor.sh
# Initialize (detects hypervisor, loads backend)
hv_init
# Check which hypervisor is active
echo "Using: $(hv_get_type)"
# Check specific hypervisor
if hv_is_proxmox; then
echo "Running on Proxmox VE"
fiPurpose: Proxmox VE backend implementation
Pattern: Thin wrappers around qm commands
Example:
proxmox_start_vm() {
local vm_id="$1"
if ! proxmox_vm_exists "$vm_id"; then
echo "ERROR: VM $vm_id does not exist" >&2
return 1
fi
qm start "$vm_id"
}Purpose: Cloud Hypervisor backend implementation
Pattern: Manages VM config files + process lifecycle
Example:
cloudhypervisor_start_vm() {
local vm_id="$1"
local config_file=$(_ch_vm_config "$vm_id")
# Parse config to build command
local cpus=$(jq -r '.cpus.boot_vcpus' "$config_file")
local memory_mb=$(($(jq -r '.memory.size' "$config_file") / 1024 / 1024))
# Launch cloud-hypervisor process
cloud-hypervisor \
--api-socket "$(_ch_vm_socket "$vm_id")" \
--cpus "boot=${cpus}" \
--memory "size=${memory_mb}M" \
...
}Purpose: Shared utilities used by backends
Independent: Can be used standalone without abstraction layer
Example:
source lib/common/network.sh
# Create bridge
create_bridge chbr1199 10.1.199.254/24
# Create TAP device attached to bridge
create_tap_device tap-vm0-0 chbr1199To add support for a new hypervisor (e.g., QEMU/KVM, Firecracker):
Create lib/hypervisors/yourname.sh:
#!/usr/bin/env bash
# Initialize
yourname_init() {
# Check if hypervisor is available
if ! command -v yourtool >/dev/null 2>&1; then
echo "ERROR: yourtool not found" >&2
return 1
fi
return 0
}
# Implement all required functions
yourname_create_vm() {
local vm_id="$1"
local name="$2"
local cores="$3"
local memory_mb="$4"
# Your implementation here
echo "Creating VM $vm_id with yourtool..."
}
yourname_start_vm() {
local vm_id="$1"
# Your implementation here
}
# ... implement all other functions
# Export functions
export -f yourname_init
export -f yourname_create_vm
export -f yourname_start_vm
# ... export all functionsEdit lib/hypervisor.sh:
detect_hypervisor() {
local config_hv="${HYPERVISOR:-auto}"
if [[ "$config_hv" != "auto" ]]; then
case "$config_hv" in
proxmox|cloudhypervisor|yourname) # Add here
echo "$config_hv"
return 0
;;
*)
echo "ERROR: Unknown hypervisor type: $config_hv" >&2
return 1
;;
esac
fi
# Auto-detection
if command -v qm >/dev/null 2>&1; then
echo "proxmox"
return 0
fi
if command -v cloud-hypervisor >/dev/null 2>&1; then
echo "cloudhypervisor"
return 0
fi
# Add your detection logic
if command -v yourtool >/dev/null 2>&1; then
echo "yourname"
return 0
fi
echo "ERROR: No supported hypervisor detected" >&2
return 1
}# Force your hypervisor
export HYPERVISOR=yourname
# Test initialization
source lib/hypervisor.sh
hv_init
# Test VM creation
hv_create_vm 9999 "test" 2 2048
hv_start_vm 9999
hv_vm_status 9999
hv_stop_vm 9999
hv_destroy_vm 9999Create docs/YOURNAME.md with:
- Installation instructions
- Configuration guide
- Limitations vs other hypervisors
- Troubleshooting
Create a new VM.
Example:
hv_create_vm 4141 "os1" 4 8192Start a VM.
Stop a VM (forcefully).
Shutdown a VM gracefully.
Destroy/delete a VM and all its resources.
Check if VM exists (returns 0 if yes, 1 if no).
Get VM status (returns: "running", "stopped", "unknown").
Wait for VM to reach running state.
Set CPU cores.
Set memory in MB.
Clone VM from template.
Add network interface to VM.
Configure specific network interface.
Add disk to VM.
Proxmox: disk_spec = storage name (e.g., "local")
Cloud Hypervisor: disk_spec = disk size, creates raw file
Resize disk (increase only).
Import external disk to VM.
Attach cloud-init ISO to VM.
Configure cloud-init user and SSH keys.
Configure cloud-init network settings.
Convert VM to template.
Create template from cloud image.
Get current hypervisor type ("proxmox" or "cloudhypervisor").
Returns 0 if using Proxmox.
Returns 0 if using Cloud Hypervisor.
Print hypervisor information.
Test individual backend functions:
# Test Proxmox backend
source lib/hypervisors/proxmox.sh
proxmox_init
proxmox_create_vm 9999 "test" 2 2048
proxmox_start_vm 9999
proxmox_vm_status 9999
proxmox_destroy_vm 9999
# Test Cloud Hypervisor backend
source lib/hypervisors/cloudhypervisor.sh
cloudhypervisor_init
cloudhypervisor_create_vm 9999 "test" 2 2048
# ...Test via abstraction layer:
# Test abstraction with Proxmox
export HYPERVISOR=proxmox
source lib/hypervisor.sh
hv_init
./create-vm.sh 4444 9999 test.local 10.1.199.199/24 10.1.199.254
# Test abstraction with Cloud Hypervisor
export HYPERVISOR=cloudhypervisor
source lib/hypervisor.sh
hv_init
./create-vm.sh 4444 9998 test2.local 10.1.199.198/24 10.1.199.254Full deployment tests:
# Test on Proxmox
export HYPERVISOR=proxmox
./deploy_rook_ceph.sh
# Verify Kubernetes cluster
kubectl get nodes
kubectl -n rook-ceph exec deploy/rook-ceph-tools -- ceph -s
# Test on Cloud Hypervisor
export HYPERVISOR=cloudhypervisor
./deploy_rook_ceph.sh
# Same verification
kubectl get nodes
kubectl -n rook-ceph exec deploy/rook-ceph-tools -- ceph -s| Feature | Proxmox | Cloud Hypervisor | Notes |
|---|---|---|---|
| VM create | ✅ | ✅ | Full parity |
| VM start/stop | ✅ | ✅ | |
| CPU/Memory config | ✅ | ✅ | |
| Multi-NIC | ✅ | ✅ | |
| Multi-disk | ✅ | ✅ | |
| Cloud-init | ✅ (built-in) | ✅ (NoCloud) | Different methods |
| Live migration | ✅ | ❌ | Proxmox only |
| Snapshots | ✅ (GUI) | qemu-img snapshot | |
| Console access | ✅ (VNC) | ✅ (serial) | Different protocols |
Always check for errors and return non-zero:
my_function() {
local vm_id="$1"
# Validate input
if [[ -z "$vm_id" ]]; then
echo "ERROR: VM ID required" >&2
return 1
fi
# Check prerequisites
if ! my_vm_exists "$vm_id"; then
echo "ERROR: VM $vm_id does not exist" >&2
return 1
fi
# Perform operation
my_tool do_something "$vm_id" || {
echo "ERROR: Operation failed for VM $vm_id" >&2
return 1
}
return 0
}Use INFO/WARN/ERROR prefixes:
echo "INFO: Starting VM $vm_id" >&2
echo "WARN: No cloud-init ISO found, using defaults" >&2
echo "ERROR: Failed to create VM $vm_id" >&2Use jq for JSON config files:
local cpus=$(jq -r '.cpus.boot_vcpus' "$config_file")
local memory=$(jq -r '.memory.size' "$config_file")Check state before operations:
if my_vm_exists "$vm_id"; then
echo "INFO: VM $vm_id already exists, skipping creation"
return 0
fi
# Proceed with creation...# Set bash debug mode
set -x
# Run with verbose output
export DEBUG=1
./deploy_rook_ceph.shsource lib/hypervisor.sh
hv_init
hv_info# Add to script
declare -F # List all functions
type hv_create_vm # Show function definition- Use
snake_casefor functions and variables - Prefix backend functions with hypervisor name:
proxmox_,cloudhypervisor_ - Keep functions focused (one task per function)
- Document complex logic with comments
- Test on both Proxmox and Cloud Hypervisor
- Update API documentation
- Add error handling
- Update relevant docs/*.md files
- No breaking changes to existing Proxmox deployments
Potential improvements:
-
Additional Hypervisors
- QEMU/KVM (libvirt)
- Firecracker
- AWS (EC2)
- Azure (VMs)
-
Enhanced Features
- VM snapshots (unified API)
- Live migration abstraction
- Resource monitoring
- Automated testing framework
-
Performance
- Parallel VM creation
- Optimized disk cloning
- Network performance tuning
-
Observability
- Structured logging (JSON)
- Metrics collection
- Health checks