Qlean
Qlean is a system-level isolation testing library based on QEMU/KVM, providing complete virtual machine isolation environments for Rust projects.
Overview
Qlean provides a comprehensive testing solution for projects requiring system-level isolation by launching lightweight virtual machines during tests. It addresses two major challenges:
1. Complete Resource Isolation
Many projects require root privileges or direct manipulation of system-level resources. Traditional single-machine tests can easily crash the host system if tests fail. Qlean uses virtual machine isolation to completely isolate these operations within the VM, ensuring host system stability.
2. Convenient Multi-Machine Testing
For projects requiring multi-machine collaboration, Qlean provides a simple API that allows you to easily create and manage multiple VM instances in test code without complex infrastructure configuration.
Key Features
- 🔒 Complete Isolation: Based on QEMU/KVM, providing full virtual machine isolation
- 🔄 Multi-Machine Support: Easily create and manage multiple virtual machines
- 🛡️ RAII-style Interface: Automatic resource management ensures VMs are properly cleaned up
- 📦 Out-of-the-Box: Automated image downloading and extraction, no manual configuration needed
- 🐧 Linux Native: Native support for Linux hosts with multiple Linux distributions
- 🌐 Multi-Distro Support: Built-in support for Debian, Ubuntu, Fedora, and Arch Linux
- 🎯 Custom Images: Use any Linux distribution with URL/local path + checksum verification
- ⚡ Performance Optimized**: Streaming hash computation with 5-30% performance improvement
Usage
Host Setup
Install CLI utils
Before using Qlean, ensure that QEMU, guestfish, libvirt, libguestfs-tools and some other utils are properly installed on your Linux host. You can verify the installation with the following commands:
Configure qemu-bridge-helper
Qlean uses qemu-bridge-helper to manage networking for multiple virtual machines, so it requires proper configuration.
The CAP_NET_ADMIN capability needs to be set on for the default network helper:
The ACL mechanism enforced by qemu-bridge-helper defaults to blacklisting all users, so the qlbr0 bridge created by qlean must be explicitly allowed:
Getting Started
Add the dependency to your Cargo.toml:
[]
= "0.2"
= { = "1", = ["full"] }
Basic Example
Here's a simple test example with single machine:
use Result;
use ;
async
The following is another example of a multi-machine test:
use Result;
use ;
async
For more examples, please refer to the tests directory.
Multi-Distribution Support
Qlean provides built-in support for multiple mainstream Linux distributions. Each distribution is optimized for ease of use and compatibility.
Supported Distributions
| Distribution | Status | WSL Compatible | Boot File Extraction | Version |
|---|---|---|---|---|
| Debian | ✅ Stable | ⚠️ Requires guestfish | Auto (guestfish) | Debian 13 (Trixie) |
| Ubuntu | ✅ Stable | ✅ Fully Compatible | Pre-extracted | Ubuntu 24.04 LTS (Noble) |
| Fedora | ✅ Stable | ⚠️ Requires guestfish | Auto (guestfish) | Fedora 41 |
| Arch | ✅ Stable | ⚠️ Requires guestfish | Auto (guestfish) | Latest |
| Custom | ✅ Stable | ✅ Optional | Flexible | Any Linux distro |
Quick Start with Different Distributions
Ubuntu (Recommended for WSL users)
use Result;
use ;
async
Fedora
async
Arch Linux
async
💡 Tip: Ubuntu is the recommended distribution for WSL users as it doesn't require guestfish for boot file extraction.
Custom Images
Qlean supports using custom Linux distributions through URL downloads or local file paths, with mandatory checksum verification for security.
Features
- 🔗 Flexible Sources: Download from URL or use local qcow2 files
- 🔒 Security First: Mandatory SHA-256/SHA-512 checksum verification
- 🪟 WSL Compatible: Optional pre-extracted kernel/initrd mode
- 🎯 Any Distribution: Support for any Linux distribution with qcow2 images
Two Modes
Mode 1: Pre-extracted Boot Files (Recommended for WSL)
Provide the image, kernel, and initrd files separately with checksums. This mode works on WSL and doesn't require guestfish.
use Result;
use ;
async
Mode 2: Auto-extract Boot Files (Native Linux only)
Provide only the image file with its checksum. Qlean will automatically extract kernel and initrd using guestfish.
async
Using Local Files
You can also use local qcow2 images:
use PathBuf;
async
How to Get Checksums
For Ubuntu cloud images:
# 1. Visit Ubuntu cloud images
# https://cloud-images.ubuntu.com/noble/current/
# 2. Download SHA256SUMS file
# 3. Find checksums for your files
For other distributions:
- Fedora: Check the CHECKSUM file in the release directory
- Arch: Look for
.SHA256files alongside the image - Custom images: Compute using
sha256sum your-file.qcow2orsha512sum your-file.qcow2
Security
All custom images require checksum verification. This ensures:
- ✅ Protection against corrupted downloads
- ✅ Protection against man-in-the-middle attacks
- ✅ Verification of file integrity
If the checksum doesn't match, image creation will fail with an error.
Common Errors
Error: "guestfish not available"
This error occurs when using auto-extraction mode (Mode 2) on WSL or without guestfish installed.
Solution:
- Use Mode 1 (pre-extracted boot files) for WSL compatibility, or
- Install libguestfs-tools on native Linux:
sudo apt install libguestfs-tools
Error: "hash mismatch"
This indicates the file doesn't match the expected checksum.
Solution:
- Verify you copied the correct hash from the official source
- Re-download the file (might be corrupted)
- Check you're using the correct hash type (SHA256 vs SHA512)
Network Configuration
Qlean uses a dedicated libvirt virtual network to provide isolated, reproducible networking for test VMs. The default network definition is stored at ~/.local/share/qlean/network.xml as follows:
qlean
This configuration defines a NAT-based virtual network named qlean (used internally by libvirt) that creates a Linux bridge interface called qlbr0. The bridge is assigned the IP address 192.168.221.1 and serves as the gateway for a /24 subnet (192.168.221.0/24). A built-in DHCP server automatically assigns IP addresses to virtual machines in the range 192.168.221.2 to 192.168.221.254, enabling seamless network connectivity between the host, test VMs, and—via NAT—the external network.
[!NOTE] If the
192.168.221.0/24subnet conflicts with your local network, you may edit the configuration file to use a different IP range,but keep the<name>qlean</name>and<bridge name='qlbr0'/>unchanged to ensure compatibility with qlean's internal logic.
API Reference
Top-Level Interface
create_image(distro, name) - Create or retrieve a VM image from the specified distribution
Supported distributions:
Distro::Debian- Debian 13 (Trixie)Distro::Ubuntu- Ubuntu 24.04 LTS (Noble) - WSL friendlyDistro::Fedora- Fedora 41Distro::Arch- Arch Linux (latest)
pub async
create_custom_image(name, config) - Create a custom image with flexible configuration
pub async
Configuration types:
with_machine(image, config, f) - Execute an async closure in a virtual machine with automatic resource cleanup
with_pool(f) - Execute an async closure in a machine pool with automatic resource cleanup
-
MachineConfig- Configuration for virtual machine resources (CPU, memory, disk)
Machine Core Interface
Machine::new(image, config)- Create a new machine instanceMachine::init()- Initialize the machine (first boot with cloud-init)Machine::spawn()- Start the machine (normal boot)Machine::exec(command)- Execute a command in the VM and return the outputMachine::shutdown()- Gracefully shutdown the virtual machineMachine::upload(src, dst)- Upload a file or directory to the VMMachine::download(src, dst)- Download a file or directory from the VMMachine::get_ip()- Get the IP address of the VM
Machine Pool Interface
MachinePool::new()- Create a new, empty machine poolMachinePool::add(name, image, config)- Add a new machine instance to the poolMachinePool::get(name)- Get a machine instance by the nameMachinePool::init_all()- Initialize all machines in the pool concurrentlyMachinePool::spawn_all()- Spawn all machines in the pool concurrentlyMachinePool::shutdown_all()- Shutdown all machines in the pool concurrently
std::fs Compatible Interface
The following methods provide filesystem operations compatible with std::fs semantics:
Machine::copy(from, to)- Copy a file within the VMMachine::create_dir(path)- Create a directoryMachine::create_dir_all(path)- Create a directory and all missing parent directoriesMachine::exists(path)- Check if a path existsMachine::hard_link(src, dst)- Create a hard linkMachine::metadata(path)- Get file/directory metadataMachine::read(path)- Read file contents as bytesMachine::read_dir(path)- Read directory entriesMachine::read_link(path)- Read symbolic link targetMachine::read_to_string(path)- Read file contents as stringMachine::remove_dir_all(path)- Remove a directory after removing all its contentsMachine::remove_file(path)- Remove a fileMachine::rename(from, to)- Rename or move a file/directoryMachine::set_permissions(path, perm)- Set file/directory permissionsMachine::write(path, contents)- Write bytes to a file
License
This project is licensed under the MIT license.