Skip to main content

Overview

The SmolVMManager class provides low-level operations for creating, starting, stopping, and managing VMs with proper state persistence and cleanup. It orchestrates VM lifecycle, networking, and state management across runtimes (Firecracker and QEMU). Key Features:
  • Backend-agnostic VM orchestration (Firecracker/QEMU)
  • SQLite-backed state persistence
  • Automatic resource allocation (IP, TAP, ports)
  • Network setup with NAT and port forwarding
  • Prerequisite validation

Constructor

SmolVMManager(
    data_dir: Path | None = None,
    socket_dir: Path | None = None,
    backend: str | None = None,
)

Parameters

data_dir
Path | None
default:"None"
Directory for state database. If omitted, SmolVM resolves a writable default:
  • $SMOLVM_DATA_DIR environment variable
  • ~/.local/state/smolvm (user state directory)
  • /var/lib/smolvm (system fallback)
socket_dir
Path | None
default:"None"
Directory for VM sockets. Defaults to /tmp.
backend
str | None
default:"None"
Runtime backend: "firecracker", "qemu", or "auto". Defaults to "auto" via smolvm.backends.resolve_backend().

Example

from smolvm.vm import SmolVMManager
from pathlib import Path

# Use default data directory resolution
sdk = SmolVMManager()

# Or specify custom paths
sdk = SmolVMManager(
    data_dir=Path("/custom/state"),
    socket_dir=Path("/custom/sockets"),
    backend="firecracker",
)

Class Methods

from_id

@classmethod
def from_id(cls, vm_id: str, **kwargs: Any) -> SmolVMManager
Create an SDK instance and verify a VM exists. Useful for attaching to an existing VM from a different process.
vm_id
str
required
The VM identifier to look up.
**kwargs
Any
Forwarded to __init__() (e.g., data_dir, backend).
Returns: A SmolVMManager instance whose state DB contains the VM. Raises: VMNotFoundError if no VM with this ID exists.
Example
from smolvm.vm import SmolVMManager

sdk = SmolVMManager.from_id("my-vm")
info = sdk.get("my-vm")
print(info.status)

VM Lifecycle

create

def create(self, config: VMConfig) -> VMInfo
Create a new microVM. This allocates resources (IP, TAP device) and persists state, but does not start the VM.
config
VMConfig
required
VM configuration.
Returns: VMInfo for the created VM. Raises:
  • VMAlreadyExistsError: If VM ID already exists.
  • NetworkError: If network setup fails.
  • ValidationError: If config is invalid.
Example
from smolvm.vm import SmolVMManager
from smolvm.types import VMConfig
from pathlib import Path

sdk = SmolVMManager()
config = VMConfig(
    vm_id="test-vm",
    vcpu_count=2,
    mem_size_mib=512,
    kernel_path=Path("/path/to/kernel"),
    rootfs_path=Path("/path/to/rootfs.ext4"),
    boot_args="console=ttyS0 reboot=k panic=1 pci=off init=/init",
)

vm_info = sdk.create(config)
print(f"Created VM: {vm_info.vm_id} with IP {vm_info.network.guest_ip}")

start

def start(
    self,
    vm_id: str,
    boot_timeout: float = 30.0,
) -> VMInfo
Start a microVM.
vm_id
str
required
The VM identifier.
boot_timeout
float
default:"30.0"
Maximum seconds to wait for boot.
Returns: Updated VMInfo. Raises:
  • VMNotFoundError: If VM doesn’t exist.
  • SmolVMError: If VM is not in CREATED or STOPPED state.
  • TimeoutError: If boot times out.

stop

def stop(self, vm_id: str, timeout: float = 10.0) -> VMInfo
Stop a running microVM.
vm_id
str
required
The VM identifier.
timeout
float
default:"10.0"
Seconds to wait for graceful shutdown before killing.
Returns: Updated VMInfo. Raises: VMNotFoundError if VM doesn’t exist.

delete

def delete(self, vm_id: str) -> None
Delete a VM and all its resources.
vm_id
str
required
The VM identifier.
Raises: VMNotFoundError if VM doesn’t exist.

VM Information

get

def get(self, vm_id: str) -> VMInfo
Get VM information.
vm_id
str
required
The VM identifier.
Returns: VMInfo for the VM. Raises: VMNotFoundError if VM doesn’t exist.

list_vms

def list_vms(self, status: VMState | None = None) -> list[VMInfo]
List all VMs.
status
VMState | None
default:"None"
Filter by status (optional).
Returns: List of VMInfo objects.
Example
from smolvm.vm import SmolVMManager
from smolvm.types import VMState

sdk = SmolVMManager()

# List all VMs
all_vms = sdk.list_vms()

# List only running VMs
running = sdk.list_vms(status=VMState.RUNNING)
for vm in running:
    print(f"{vm.vm_id}: {vm.network.guest_ip}")

State Management

reconcile

def reconcile(self) -> list[str]
Reconcile state with actual system state. Detects and marks stale VMs (marked running but process dead). Returns: List of VM IDs that were marked as ERROR.
Example
sdk = SmolVMManager()
stale_vms = sdk.reconcile()
if stale_vms:
    print(f"Found {len(stale_vms)} stale VMs: {stale_vms}")

SSH Access

get_ssh_commands

def get_ssh_commands(
    self,
    vm_id: str,
    *,
    ssh_user: str = "root",
    key_path: str | Path | None = None,
    public_host: str | None = None,
) -> dict[str, str]
Return ready-to-run SSH commands for a VM.
vm_id
str
required
The VM identifier.
ssh_user
str
default:"root"
SSH username.
key_path
str | Path | None
default:"None"
Optional SSH private key path.
public_host
str | None
default:"None"
Public hostname for remote access.
Returns: Dictionary containing:
  • "private_ip": connect directly to guest IP from host
  • "localhost_port": connect via reserved forwarded host port
  • "public": connect from internet (only when public_host given)
Example
sdk = SmolVMManager()
commands = sdk.get_ssh_commands(
    "my-vm",
    ssh_user="ubuntu",
    key_path="~/.ssh/id_ed25519",
)
print("SSH via localhost:", commands["localhost_port"])
print("SSH via private IP:", commands["private_ip"])

Prerequisites

check_prerequisites

def check_prerequisites(self) -> list[str]
Check if all prerequisites are met. Uses backend-specific validation:
  • firecracker: KVM + Linux networking + Firecracker binary
  • qemu: qemu-system binary + SSH client
Returns: List of error messages (empty if all good).
Example
sdk = SmolVMManager()
errors = sdk.check_prerequisites()
if errors:
    print("Prerequisites missing:")
    for error in errors:
        print(f"  - {error}")
else:
    print("All prerequisites met!")

Context Manager

The SmolVMManager class implements the context manager protocol:
with SmolVMManager() as sdk:
    vm_info = sdk.create(config)
    sdk.start(vm_info.vm_id)
    # Resources automatically released on exit

close

def close(self) -> None
Release all resources held by this manager. Closes open log-file handles. Calling close() more than once is safe (idempotent).

Attributes

data_dir

data_dir: Path
Directory for state database and VM-specific files.

socket_dir

socket_dir: Path
Directory for VM sockets.

backend

backend: str
Resolved runtime backend ("firecracker" or "qemu").

disk_dir

disk_dir: Path
Directory for isolated VM disk images (data_dir/disks).

state

state: StateManager
State manager for VM persistence.

network

network: NetworkManager
Network manager for TAP devices and routing.

host

host: HostManager
Host capability manager.

Build docs developers (and LLMs) love