# QCOW2 Module (`herolib_virt::qcow2`)
## Overview
The QCOW2 module provides a comprehensive Rust interface for creating and managing QCOW2 disk images. QCOW2 (QEMU Copy-On-Write version 2) is a widely-used disk image format that supports snapshots, compression, and sparse allocation, making it ideal for virtual machines and containerized environments.
## Requirements
This module requires `qemu-img` to be installed:
- **Debian/Ubuntu**: `sudo apt-get install qemu-utils`
- **macOS**: `brew install qemu`
- **RedHat/CentOS**: `sudo yum install qemu-img`
- **Arch**: `pacman -S qemu-img`
## Quick Start
### Creating a Disk Image
```rust
use herolib_virt::qcow2;
// Create a 50 GiB QCOW2 disk image
let disk_path = qcow2::create("/var/vms/my-vm.qcow2", 50)?;
println!("Created disk: {}", disk_path);
```
### Creating Snapshots
```rust
use herolib_virt::qcow2;
let disk = "/var/vms/my-vm.qcow2";
// Create a snapshot before making changes
qcow2::snapshot_create(disk, "before-update")?;
// ... make changes ...
// Create another snapshot after successful changes
qcow2::snapshot_create(disk, "after-update")?;
// List all snapshots
let snapshots = qcow2::snapshot_list(disk)?;
for snap in snapshots {
println!("Snapshot: {:?}", snap.name);
}
// Delete old snapshot
qcow2::snapshot_delete(disk, "before-update")?;
```
### Getting Image Information
```rust
use herolib_virt::qcow2;
// Get detailed image information
let info = qcow2::info("/var/vms/disk.qcow2")?;
println!("Image info: {:?}", info);
// Access specific fields from JSON
if let Some(size) = info.get("virtual-size") {
println!("Virtual size: {} bytes", size);
}
if let Some(disk_size) = info.get("actual-size") {
println!("Actual size on disk: {} bytes", disk_size);
}
```
### Using Ubuntu Cloud Images
```rust
use herolib_virt::qcow2;
// Download and prepare Ubuntu 24.04 image
let base = qcow2::build_ubuntu_24_04_base("/var/vms/images", Some(100))?;
println!("Base image: {}", base.base_image_path);
println!("Snapshot: {}", base.snapshot);
// You can now use this as a base for cloning or snapshot-based VMs
```
## API Reference
### Functions
#### `create(path: &str, size_gb: i64) -> Result<String, Qcow2Error>`
Creates a new QCOW2 disk image with the specified virtual size. The actual file size will be smaller due to QCOW2's sparse allocation.
**Parameters:**
- `path`: Full path where the image should be created
- `size_gb`: Virtual size in GiB (must be > 0)
**Returns:** Path to the created image
**Example:**
```rust
let disk = qcow2::create("/tmp/disk.qcow2", 20)?;
```
#### `info(path: &str) -> Result<Value, Qcow2Error>`
Retrieves detailed information about a QCOW2 image. Returns the data as JSON parsed by `serde_json`.
**Parameters:**
- `path`: Path to the QCOW2 image
**Returns:** JSON object with image information
**Example:**
```rust
let info = qcow2::info("/tmp/disk.qcow2")?;
if let Some(virtual_size) = info.get("virtual-size") {
println!("Size: {}", virtual_size);
}
```
#### `snapshot_create(path: &str, name: &str) -> Result<(), Qcow2Error>`
Creates a snapshot of the QCOW2 image. Useful for creating restore points.
**Parameters:**
- `path`: Path to the QCOW2 image
- `name`: Name for the snapshot (cannot be empty)
**Note:** The image must not be in use by a running VM.
**Example:**
```rust
qcow2::snapshot_create("/tmp/disk.qcow2", "checkpoint")?;
```
#### `snapshot_delete(path: &str, name: &str) -> Result<(), Qcow2Error>`
Deletes a snapshot from the QCOW2 image.
**Parameters:**
- `path`: Path to the QCOW2 image
- `name`: Name of the snapshot to delete
**Example:**
```rust
qcow2::snapshot_delete("/tmp/disk.qcow2", "checkpoint")?;
```
#### `snapshot_list(path: &str) -> Result<Vec<Qcow2Snapshot>, Qcow2Error>`
Lists all snapshots in a QCOW2 image.
**Parameters:**
- `path`: Path to the QCOW2 image
**Returns:** Vector of `Qcow2Snapshot` structures
**Example:**
```rust
let snapshots = qcow2::snapshot_list("/tmp/disk.qcow2")?;
for snap in snapshots {
println!("Snapshot: {:?}", snap.name);
}
```
#### `build_ubuntu_24_04_base(dest_dir: &str, size_gb: Option<i64>) -> Result<BuildBaseResult, Qcow2Error>`
Downloads the Canonical Ubuntu 24.04 (Noble) cloud image and optionally resizes it.
**Parameters:**
- `dest_dir`: Directory to store the image
- `size_gb`: Optional new virtual size (None = use cloud image default)
**Returns:** `BuildBaseResult` with image path, snapshot name, and URL
**Example:**
```rust
let base = qcow2::build_ubuntu_24_04_base("/var/vms/images", Some(100))?;
println!("Image at: {}", base.base_image_path);
```
### Types
#### `Qcow2Snapshot`
Represents a snapshot of a QCOW2 image.
**Fields:**
- `id: Option<String>` - Internal QEMU snapshot ID
- `name: Option<String>` - Human-readable snapshot name
- `vm_state_size: Option<i64>` - Size of VM state data (bytes)
- `date_sec: Option<i64>` - Unix timestamp (seconds)
- `date_nsec: Option<i64>` - Nanoseconds component
- `vm_clock_nsec: Option<i64>` - VM clock value
#### `BuildBaseResult`
Result of building a base image.
**Fields:**
- `base_image_path: String` - Path to the downloaded/resized image
- `snapshot: String` - Name of the base snapshot
- `url: String` - Source download URL
- `resized_to_gb: Option<i64>` - Size if resized, None otherwise
## Common Patterns
### Pattern: VM Disk Lifecycle
```rust
use herolib_virt::qcow2;
// 1. Create a disk for a new VM
let disk = qcow2::create("/var/vms/production.qcow2", 100)?;
// 2. Create a snapshot before major changes
qcow2::snapshot_create(&disk, "pre-deployment")?;
// 3. ... perform updates/deployments ...
// 4. Check disk usage
let info = qcow2::info(&disk)?;
println!("Actual size: {:?}", info.get("actual-size"));
// 5. Clean up old snapshots
let snapshots = qcow2::snapshot_list(&disk)?;
for snap in snapshots {
if let Some(name) = snap.name {
if name.starts_with("old-") {
qcow2::snapshot_delete(&disk, &name)?;
}
}
}
```
### Pattern: Multi-Tier Image Hierarchy
```rust
use herolib_virt::qcow2;
// 1. Create a base image from cloud image
let base = qcow2::build_ubuntu_24_04_base("/images", Some(50))?;
println!("Base image: {}", base.base_image_path);
// 2. Create snapshots for different configurations
qcow2::snapshot_create(&base.base_image_path, "web-server")?;
qcow2::snapshot_create(&base.base_image_path, "database")?;
qcow2::snapshot_create(&base.base_image_path, "cache")?;
// 3. Now each of these snapshots can serve as base for specific VM classes
```
### Pattern: Snapshot Workflow for Testing
```rust
use herolib_virt::qcow2;
let disk = "/var/vms/test.qcow2";
qcow2::create(disk, 30)?;
// Create clean state
qcow2::snapshot_create(disk, "clean")?;
// Test 1
qcow2::snapshot_create(disk, "test1-start")?;
// ... run test 1 ...
qcow2::snapshot_delete(disk, "test1-start")?;
// Test 2
qcow2::snapshot_create(disk, "test2-start")?;
// ... run test 2 ...
qcow2::snapshot_delete(disk, "test2-start")?;
// Keep the clean snapshot for future tests
```
## Error Handling
All functions return `Result<T, Qcow2Error>`. Errors include:
- **CommandExecutionFailed**: `qemu-img` not found or couldn't be executed
- **CommandFailed**: `qemu-img` executed but returned an error
- **JsonParseError**: Failed to parse JSON output from `qemu-img info`
- **IoError**: Filesystem or permission error
- **Other**: Various validation or dependency errors
**Example:**
```rust
use herolib_virt::qcow2;
match qcow2::create("/tmp/disk.qcow2", 50) {
Ok(path) => println!("Created: {}", path),
Err(e) => eprintln!("Failed to create disk: {}", e),
}
```
## Performance Considerations
1. **Sparse Allocation**: QCOW2 files start small and grow as data is written. The virtual size is not immediately consumed on disk.
2. **Snapshot Overhead**: Each snapshot adds metadata overhead. Keep the number of snapshots reasonable (typically < 10 active snapshots).
3. **Format Efficiency**: QCOW2 is good for development/testing but raw images may be faster for high-performance production workloads.
4. **Defragmentation**: Large numbers of snapshots can fragment the image file. Consider consolidating snapshots periodically.
## Rhai Integration
The QCOW2 module is fully accessible from Rhai scripts:
```rhai
// Create a disk
let disk = qcow2_create("/tmp/vm.qcow2", 50);
// Create snapshots
qcow2_snapshot_create(disk, "initial");
// List snapshots
let snaps = qcow2_snapshot_list(disk);
for snap in snaps {
print("Snapshot: " + snap.name);
}
// Get info
let info = qcow2_info(disk);
print("Info: " + info);
```
## Troubleshooting
### "qemu-img not found"
**Solution**: Install QEMU tools for your platform (see Requirements above)
### "Image is locked or in use"
**Solution**: Ensure no VMs are running with the image attached, then try again
### "Snapshot name cannot be empty"
**Solution**: Provide a non-empty string for the snapshot name
### "Size must be > 0"
**Solution**: Specify a positive GiB size
## See Also
- [Cloud Hypervisor](../cloudhv/README.md) - Use QCOW2 images with VMs
- [QEMU Documentation](https://www.qemu.org/docs/master/tools/qemu-img.html) - Official qemu-img reference
- [QCOW2 Format](https://github.com/qemu/qemu/blob/master/docs/interop/qcow2.txt) - Technical format specification