VM Operations

Complete guide to VM lifecycle management - create, start, stop, destroy, snapshots using Infinization and QEMU

VM Operations

Introduction

The VM lifecycle management system manages VM creation, startup, and teardown through Infinization, a TypeScript library that builds and spawns QEMU processes directly. This approach bypasses libvirt for VM management, providing more control and simpler architecture.

Uses QEMU/KVM for virtualization, Prisma for database, and automated OS installation. Firewall rules are managed via nftables. All operations include automatic cleanup on errors.

Architecture Overview

graph TD
    API[GraphQL API] --> Service[CreateMachineService]
    Service --> Infinization[Infinization Module]
    Service --> Firewall[nftables]
    Infinization --> QEMU[QEMU Process]
    QEMU --> KVM[KVM Hypervisor]

    style Infinization fill:#22c55e,stroke:#16a34a,color:#fff
    style Firewall fill:#f59e0b,stroke:#d97706,color:#000
    style QEMU fill:#64748b,stroke:#475569,color:#fff

Key Components:

  • Infinization: TypeScript QEMU command builder - manages VM lifecycle
  • nftables: Network filtering (firewall rules)
  • QEMU: Actual hypervisor process
  • KVM: Hardware acceleration

VM Creation Process

Overview

Creates VMs from database configuration through phases: validation, data fetching, ISO generation, storage setup, firewall configuration, QEMU command building, and VM startup.

CreateMachineService Architecture

File: backend/app/services/CreateMachineServiceV2.ts

Core components:

  • InfinizationService: QEMU command builder and process management
  • Prisma client: Database operations
  • FirewallManager: Network filter management (via nftables)
  • Debugger: Logging

Creation Phases

Initialization

Initialize InfinizationService instance for QEMU process management.

Validation

Validate Prisma client exists and check preconditions via validatePrismaClient().

Data Fetching

Fetch template (resources), configuration (graphics/options), and applications from database:

  • prisma.machineTemplate.findUnique()
  • prisma.machineConfiguration.findUnique()
  • prisma.machineApplication.findMany()

Unattended ISO Generation

Generate custom ISO with autoinstall configuration via createUnattendedManager() and generateNewImage(). See Unattended Installation.

Status Update

Update machine status to 'building' in database transaction (20s timeout).

Storage Setup

Create QCOW2 disk image using qemu-img:

  • Volume name: ${machine.internalName}-main.qcow2
  • Format: QCOW2 with thin provisioning
  • Capacity from template or machine.diskSizeGB

Firewall Verification

Verify firewall infrastructure exists (created by Prisma callbacks in utils/modelCallbacks/machine.ts). Uses nftables to apply network rules.

QEMU Command Building

Infinization builds the QEMU command line with:

  • Memory allocation
  • CPU configuration (cores, topology)
  • Storage devices
  • Network interfaces (with nwfilter reference)
  • Graphics (SPICE/VNC)
  • VirtIO channels
  • Optional features (GPU passthrough, etc.)

VM Startup

Spawn QEMU process via Infinization and update status to 'running' in database.

Error Handling and Rollback

In CreateMachineService.create() method, on failure, cleanup occurs in reverse order:

  1. Log error with stack trace
  2. Kill QEMU process if running
  3. Delete temporary ISO (if in temp directory)
  4. Delete storage volume
  5. Cleanup database via MachineCleanupService
  6. Re-throw error

Storage Management

Storage Configuration

Directory-based storage:

  • Path: INFINIBAY_STORAGE_POOL_PATH (default: '/opt/infinibay/disks')
  • Created automatically if missing

Storage Volume Creation

Key steps:

  1. Name: ${machine.internalName}-main.qcow2
  2. Format: QCOW2 with lazy_refcounts, extended_l2, nocow
  3. Thin provisioning (allocation: 0)
  4. Capacity from template or machine.diskSizeGB
  5. Created via qemu-img create

Environment Variables

Variable Description Default
INFINIBAY_BASE_DIR Base directory for all Infinibay data '/opt/infinibay'
INFINIBAY_STORAGE_POOL_PATH Storage directory ${INFINIBAY_BASE_DIR}/disks

Firewall Integration

Automatic Firewall Setup

Prisma callbacks in backend/app/utils/modelCallbacks/machine.ts create firewall infrastructure on machine insert. Uses nftables for network filtering.

Filter Application

Firewall rules applied via nftables. VM rules are organized in per-VM chains that inherit department rules.

Filter Priority

Priority 100: Department (evaluated first) Priority 200: VM (can override department rules)

Template System

Templates

Templates in MachineTemplate model provide default cores, RAM, storage. Optional—machines can use custom sizing.

Resource resolution uses template values with machine-specific fallback.

VM Lifecycle Operations

These operations control VM state after creation. Infinization manages QEMU processes directly:

Operation Description Implementation
Start VM Start QEMU process Spawn new QEMU process with built command
Stop VM (Graceful) ACPI shutdown signal Send ACPI shutdown via QMP/guest agent
Force Power Off Kill QEMU process SIGTERM/SIGKILL to QEMU process
Restart VM (Graceful) ACPI reboot signal Send reboot via QMP/guest agent
Reset VM (Hard) Hard reset QMP system_reset command
Pause VM Pause execution QMP stop command
Resume VM Resume paused VM QMP cont command
Delete VM Remove VM Kill process, delete storage

Use graceful operations when possible. Force operations only for unresponsive VMs.

Snapshot Operations

Reference: SnapshotService.ts

Types

  • Internal: Stored in QCOW2 file (fast, file grows)
  • External: New QCOW2 with backing chain (slower, more flexible)

Operations

Operation Description
Create qemu-img snapshot -c
List qemu-img snapshot -l
Restore qemu-img snapshot -a
Delete qemu-img snapshot -d

GPU Passthrough

PCI address format: 0000:B4:00.0. Infinization adds VFIO device passthrough to QEMU command.

Requirements:

  • IOMMU enabled (Intel: intel_iommu=on, AMD: amd_iommu=on)
  • GPU not in use by host (vfio-pci driver bound)
  • Allowed vendors: NVIDIA, AMD/ATI

Uses systeminformation library to detect GPUs in getGraphics() resolver.

Unattended Installation System

Generates custom ISOs with autoinstall configs for automated OS installation.

Architecture

  • UnattendedWindowsManager: Windows 10/11 (unattend.xml)
  • UnattendedUbuntuManager: Ubuntu (cloud-init YAML)
  • UnattendedRedHatManager: Fedora/RedHat (kickstart)

Process

  1. Validate ISO path
  2. Generate OS-specific config
  3. Extract ISO with 7z
  4. Add config to extracted directory
  5. Create new ISO with xorriso/mkisofs
  6. Cleanup temp files
  7. Return ISO path

Factory pattern in createUnattendedManager() maps OS to manager. Throws error for unsupported OS.

Temporary ISOs: Stored in INFINIBAY_ISO_TEMP_DIR, deleted on rollback.

Configuration Storage

Stored in MachineConfiguration model:

  • graphicProtocol: spice/vnc
  • graphicPassword: Random 8-char password
  • graphicHost: Host address
  • graphicPort: -1 (autoport)
  • assignedGpuBus: PCI address if GPU passthrough

Error Handling

QEMU Process: Check process exit codes, capture stderr.

Transactions: Quick status updates only (20s timeout). Heavy operations outside transactions.

Rollback: Kill QEMU → delete temp ISO → delete storage volume → database cleanup.

Environment Variables Reference

Variable Description Default
INFINIBAY_BASE_DIR Base directory for all data '/opt/infinibay'
INFINIBAY_STORAGE_POOL_PATH Storage directory ${INFINIBAY_BASE_DIR}/disks
INFINIBAY_ISO_TEMP_DIR Temporary ISO directory ${INFINIBAY_BASE_DIR}/iso/temp
APP_HOST Graphics host address '0.0.0.0'

Diagrams

VM Creation Flow

sequenceDiagram
    actor User
    participant Service as CreateMachineService
    participant Unattended as UnattendedManager
    participant Storage as Storage
    participant Firewall as FirewallManager
    participant Infinization
    participant QEMU

    User->>Service: create()
    Service->>Service: Initialize & fetch data
    Service->>Unattended: generateNewImage()
    Unattended-->>Service: ISO path
    Service->>Storage: Create QCOW2 volume
    Storage-->>Service: Volume path
    Service->>Firewall: ensureFirewallForVM()
    Service->>Infinization: Build QEMU command
    Infinization->>QEMU: Spawn process
    QEMU-->>Service: VM running
    Service-->>User: Success

Rollback Process

sequenceDiagram
    participant Service
    participant QEMU
    participant FileSystem
    participant Storage
    participant Cleanup as MachineCleanupService
    participant DB as Database

    Service->>Service: Error detected
    Service->>QEMU: Kill process
    Service->>FileSystem: Delete temp ISO
    Service->>Storage: Delete volume
    Service->>Cleanup: cleanupVM()
    Cleanup->>DB: Delete records
    Cleanup->>Service: Done
    Service->>User: Throw error