Configured clouds and scheduling

Define a cloud catalog and automatically place machines on prepared libvirt hosts.

Vmango exposes configured clouds rather than asking users to assemble a libvirt domain. Administrators prepare hosts, pools and networks and define their private bindings. Users select an image, instance type, AZ, logical network and storage class. The scheduler assigns a host, shown read-only in the machine details.

Configure a cloud

Keep the image definitions from the shipped configuration, or define images using the image guide. Define each host’s connection and backend settings directly in its cloud. The example assumes an active libvirt network named default and a writable pool named default; Vmango does not create them.

cloud "local" {
    name = "Local cloud"
    # Keep the nested image definitions from vmango.quickstart.conf here.

    zone "local" { name = "Local zone" }
    network "lan" { name = "Private LAN" }
    storage_class "standard" { name = "Standard storage" }

    instance_type "small" {
        name = "Small"
        cpu = 2
        cpu_request = 1
        memory_mib = 2048
        boot_disk_gib = 20
    }

    host "local" {
        uri = "qemu:///system"
        config_drive_pool = "default"
        image_pool = "default"
        zone = "local"
        labels = { rack = "rack-a" }
        cpu_reserve = 1
        cpu_overcommit = 4
        memory_reserve_mib = 1024
        network "lan" { network = "default" }
        storage_class "standard" {
            pool = "default"
            format = "qcow2"
        }
    }
}

Each host owns its libvirt connection and belongs to exactly one cloud and AZ. To add another host, add a host block with its own uri, zone and network/pool bindings. Host names and connection URIs must be globally unique across clouds; several hosts can share the same AZ. Use architecture-appropriate image IDs; unsupported combinations are rejected.

Connection settings uri, image_pool, config_drive_pool, config_drive_suffix, config_drive_write_format, emulator, graphics_listen, qcow_prealloc_metadata and cache all belong directly in cloud.host. image_pool and config_drive_pool default to default, config_drive_suffix to _config.iso and config_drive_write_format to nocloud. graphics_listen defaults to the backend’s listener setting.

Migrate existing connections

Move the contents of each former top-level libvirt "name" block into host "name" in its cloud, then remove the top-level block. Preserve the exact host name, URI and pool settings so resource routes, task scopes and image ownership stay associated with the same backend. Top-level libvirt blocks and legacy libvirt_uri / libvirt_config_drive_* options now fail startup with a migration instruction. Backend settings do not belong in the public cloud API.

Resources and placement

cpu sets the actual vCPU count. cpu_request defaults to cpu, must be positive and no greater than it, and affects admission only; it does not impose quotas or CPU shares. Memory requests equal guest RAM; memory overselling is unsupported. boot_disk_gib sets the size of a newly created boot disk and must satisfy the image minimum. Additional disks have independent sizes.

Each create inventories all cloud hosts, including stopped and unmanaged VMs. Existing VMs without scheduler metadata count at their actual configured CPU/RAM. Failed inventory reads fail admission. Host reserves reduce the available budget; disk and lazy image preparation capacity are checked too. Competing provisioning and storage commands execute serially so they cannot admit the same capacity twice.

Placement is optional. Required equality labels filter candidates; preferred labels affect scoring and do not guarantee a match. Only advertised attributes are accepted. These semantics are independent of libvirt node names. With no hints, placement is automatic within the selected AZ.

Disks, interfaces and existing machines

A storage class maps to a pool on each host. The same class on two hosts does not make storage shared. A standalone disk is scheduled within its AZ and remains host-bound after detachment. A new disk for an existing machine uses that machine’s host. Selecting existing local disks during creation constrains placement to their owning host; disks from different hosts cannot be combined or silently copied.

The main Networks page lists the selected cloud’s logical network catalog, including display names and network IDs. Its cloud selector scopes the list; multiple host bindings for one logical network appear as one entry. Backend libvirt network names are shown as read-only diagnostics on each Hosts detail page and remain available through the read-only host diagnostic API under /api/v1/administration/clouds/{cloud}/hosts/{node}/networks. Administrators provision those networks outside Vmango.

Interfaces select a configured logical network, resolved on the existing host. Interface attachment accepts network (a logical network ID) and optional mac. NIC model and VLAN are selected by the administrator’s host network binding; model, vlan and other unsupported request fields are rejected. Observed interface responses retain model and vlan for diagnostics. Custom network creation remains outside this workflow.

Unmanaged VMs are visible and counted, but read-only until explicit adoption. Adoption does not change resources, power state, disks or placement, and does not claim ownership of pre-existing disks. Deleting an adopted VM preserves unowned disks. Preserve the private volume ownership metadata alongside task history.

An explicit instance type change requires a stopped managed VM, stays on its current host, applies the selected type’s autostart policy and preserves all disk sizes, applied guest devices and graphics listener bindings. If that host lacks resources, the task fails; there is no automatic migration, stop or restart. Catalog edits never silently resize or reconfigure existing machines or disks.

Set autostart in instance_type blocks (default false). Image settings guest_agent, graphics and video_model control guest integration and devices; their defaults are true, vnc and none. The cloud’s private host block sets graphics_listen as an IP address, with omission preserving the backend default. Creation’s start flag is a separate one-time action. Adoption preserves existing policy and devices, and accepted tasks snapshot policy and private host bindings. None of these five settings accepts per-machine overrides; the machine PATCH endpoint is removed and effective values remain read-only.

System disks and boot order

Vmango assigns an explicit boot priority to the system disk when creating a VM or attaching disks. The root attachment alias identifies the system disk. If there is only one ordinary disk, it can be selected without an alias. The configdrive disk contains cloud-init data and is never selected automatically as the system disk, even though it is attached through virtio.

When reattaching a system disk to a machine with other data disks, set its alias to root. Vmango does not guess which of several unlabelled disks contains an OS. Device names and PCI addresses are preserved; the system disk need not be vda.

Legacy hd/cdrom boot settings are converted on disk attachment when a system disk can be identified. An already attached installation CD keeps its configured precedence. Existing explicit bootable hard disks, direct kernel boot and legacy PXE-only or mixed PXE boot policies are preserved. With per-device priorities, a reattached system disk is added after existing optical/network boot entries when no hard disk has a priority. Newly attached installation media can be selected through the firmware boot menu or an explicit libvirt boot configuration.

Existing machines are not rewritten or restarted merely by upgrading Vmango. Disk attachment requires a stopped VM, and the updated boot order takes effect on its next start.

API and migration

Machine, disk, interface and native console operations use /api/v1/clouds/{cloud}. Create uses catalog references and an AZ without a host input. Machine URLs use the stable VM UUID. Volumes use /clouds/{cloud}/volumes/{volume} with unpadded base64url(node) + "." + base64url(path) as the compound ID. VM disk references and existing_disks: [{volume_id}] use that same ID without a separate public host field. These addresses do not move a resource. Every request validates cloud membership. All mutations use durable tasks with visible progress and diagnostics.

Volumes, like Machines, shows one selected cloud’s flat inventory. Both list APIs return {items, unavailable_hosts}; partial failures preserve successful rows and remain explicit even when every host fails. VM/volume detail provides the logical catalog needed by ordinary forms. A null catalog means supplemental discovery failed; empty arrays mean known-empty choices. Dedicated infrastructure browsing is under Administration → Clouds → Cloud; Tasks keeps its existing URLs.

The old /api/v1/nodes/..., /api/v1/hosts/..., host-segment volume routes and global /vms, /volumes and /networks endpoints are removed without aliases. Read-only administrative diagnostics use /api/v1/administration/clouds/{cloud}/hosts/.... Authentication remains installation/principal scoped. Workloads, SSH keys, cloud-init templates and workload task history require an explicit configured namespace. The same cloud may serve several namespaces; Administration inventory and history remain independent of workspace selection. See the repository namespace user guide for configuration and everyday use, or the migration guide for existing installations.

See Automation API for Swagger UI, authentication and an overview of supported operations. The repository’s API reference lists the routes, task behavior and console examples. Binary archives include QUICKSTART.md, API.md, CLOUDS.md, IMAGES.md, TASKS.md and MIGRATION.md for offline reference. They use the maintained repository guides, with internal guide links adjusted to the archive filenames.