Skip to content

Provisioning workflows

Experimental: validate TempXE, bridge, and firewalld behavior on your hardware before production use. Read prepare-safety before bare-metal prepare.

End-to-end path from unknown hardware to a running guest VM, standalone on a YAIDAP jumphost or orchestrated from the UMKIM hub.

discover hardware → edit draft → add to inventory → validate → prepare HV → create guest

When UMKIM binds a site with provider: yaidap, the same steps run on the jumphost via connector Jobs; the hub owns inventory edits and sync. See UMKIM integration for action mapping.

Add the host to any inventory group with SSH access:

Terminal window
ansible-playbook -i inventory/mine playbooks/discover-hosts.yml \
--tags check_host_details --limit my-hv01

Output (defaults):

inventory/example/generated/host_vars/<hostname>.yml
inventory/example/generated/host_vars/<hostname>.notes.json
inventory/example/generated/hosts/<hostname>.yml

PXE discovery (tempxe_discovery.enabled: true in host_vars): Anaconda collector runs during PXE boot. Collect drafts after hosts POST their tarball:

Terminal window
ansible-playbook -i inventory/mine playbooks/configure-tempxe.yml \
--tags collect_discovery --limit my-hv01

tempxe_stop runs the same collect before removing the TempXE container. Raw tarballs stay in generated/pxe-discovery/.

Open generated/host_vars/<hostname>.yml. Replace every CHANGE_ME:

Field Set to
uplinks[].physical_network Fabric name matching networks[]
uplinks[].networks[].network_name Entry from group_vars/all networks
networks in group_vars/all CIDR, gateway, VLAN tag, DNS
ansible_host Management IP in hypervisors.yml / guests.yml
mac_address Verify against notes.nics
vm_network true on HV uplinks that should become libvirt bridges
configure_firewalld Stays false so prepare does not start firewalld or lock SSH

Copy the finished file to host_vars/my-hv01.yml and add the host to hypervisors.yml.

Terminal window
ansible-playbook playbooks/validate-all.yml --tags validate -i inventory/mine

Fix schema errors before prepare.

Terminal window
ansible-playbook playbooks/configure-hypervisors.yml --tags prepare \
-i inventory/mine --limit my-hv01

Optional GPU host prep (reboot):

Terminal window
--tags prepare_gpu_passthrough,prepare

Keep configure_firewalld false (-e configure_firewalld=false) so prepare does not start firewalld or lock SSH.

configure_firewalld stays false, so YAIDAP prepare does not start firewalld or lock SSH.

The fleet_spoke_firewall role stays off unless fleet_spoke_firewall_enabled is true. That flag defaults to configure_firewalld (false). The role does not disable firewalld. When it is enabled it starts firewalld, trusts the WireGuard interface, and allows the overlay to TCP 6443, 10250, and hostNetwork LLM TCP 8080. Spoke Traefik NodePorts 30080, 30443, and 30081 are opened when spoke ingress is enabled.

When an operator turns YAIDAP firewalld on, firewalld_cluster_profile (default true) trusts 10.10.0.0/16 (UMKIM WireGuard), 192.168.0.0/16 (Calico; flannel is disabled), and 10.43.0.0/16, and trusts wg-umkim and wg0 when those interfaces exist.

Inventory zones also get TCP 80, 443, 30080, 30443, and 30081. Zone targets are DROP. TCP 6443 and 10250 are not opened on those DROP zones; trusted overlay and pod sources can reach them. TCP 179 (Calico BGP) is not in that zone list. host_prepare opens TCP 179, 6443, and 10250 only on its opt-in firewalld path (configure_firewalld true), because Calico peers are management-LAN addresses.

When firewalld is already running (firewall-cmd --state succeeds), K3s overlay tasks open spoke Traefik NodePorts if spoke ingress is enabled and trust discovered pod CIDRs on every cluster node, not only the bootstrap node. Those tasks do not start firewalld.

host_vars/my-vm01.yml:

os: rocky-9
vm_location: my-hv01 # or least-utilized
provisioning_provider: libvirt
uplinks:
- name: n0p0
networks:
- network_name: mgmt_nw
cloudinit: true
ip: "{{ ansible_host }}"

Add my-vm01 to guests.yml with ansible_host and vm_location. Set cloudinit_password via -e or vault (required for cloud-init guests).

If the HV exposes the same network_name on multiple uplinks, set hypervisor_uplink on the guest attachment.

Dry-run capacity for vm_location: least-utilized:

Terminal window
ansible-playbook playbooks/plan-vm-placement.yml --tags plan -i inventory/mine

Create (resolves placement, writes concrete vm_location into host_vars/):

Terminal window
ansible-playbook playbooks/provision-vms.yml --tags create \
-i inventory/mine --limit my-vm01 -e cloudinit_password='CHANGE_ME'

Destroy:

Terminal window
ansible-playbook playbooks/provision-vms.yml --tags destroy \
-i inventory/mine --limit my-vm01

Stub a hypervisor in hypervisors.yml + host_vars/{name}.yml, sync, discover, then import promoted drafts:

Terminal window
umkim site inventory sync SITE --wait
umkim site host provision SITE new-hv01 --action discover --wait
# or PXE (TempXE; requires tempxe_discovery.enabled + MAC in host_vars):
umkim site host provision SITE new-hv01 --action discover_pxe --confirm --wait
umkim site inventory import preview SITE --wait
umkim site inventory import apply SITE --confirm \
--paths host_vars/new-hv01.yml,hypervisors.yml

Discovery output lands under jumphost generated/. Resolve CHANGE_ME placeholders surfaced in preview warnings before sync or the next provision action.

For hypervisors in hypervisors.yml with complete host_vars:

Terminal window
umkim site inventory sync SITE --wait
umkim site host provision SITE bm-hv01 --action install_bm --confirm --wait

The connector runs YAIDAP install-bare-metal.yml (install_bm tag) with -e tempxe_confirm=true and -e install_os=true. Requires --confirm. Default timeout 900s. TempXE is disarmed on success and failure.

Standalone equivalent:

Terminal window
ansible-playbook playbooks/install-bare-metal.yml --tags install_bm \
-i inventory/mine --limit bm-hv01 \
-e tempxe_confirm=true -e install_os=true

Legacy manual path: arm TempXE with install_os: true, reboot to PXE, wait for /root/ks-post.log, then tempxe_stop.

Terminal window
umkim site inventory sync SITE --wait
umkim site host provision SITE guest01 --action plan_vm --wait # dry-run
umkim site host provision SITE guest01 --action create_vm --wait

After successful create_vm, the fleet-site controller:

  1. Parses vm_location from YAIDAP_RESULT in job logs (schema: yaidap.integration.v1; falls back to legacy FLEET_YAIDAP_VM_LOCATION= when absent).
  2. Rewrites guests.yml and host_vars/{guest}.yml from schedule tokens (least-utilized, auto, empty) to the concrete hypervisor.
  3. Auto-syncs inventory to the jumphost.

If placement stays least-utilized after create, inspect job logs for YAIDAP_RESULT and a concrete vm_location field.

Full operator runbook with cluster intent and FleetClusterJoin:

  1. Edit inventory (console, CLI, or API) — Inventory model
  2. umkim site inventory sync SITE --wait
  3. umkim site host provision SITE guest01 --wait — create_vm
  4. umkim site host cluster-apply SITE guest01 — or wait for autoApply
  5. Download bootstrap bundle; run bootstrap.sh on first control
  6. umkim cluster provision NAME

Details: Site provisioning.

Step Playbook Tag UMKIM action
Discover (SSH) discover-hosts.yml check_host_details discover
Discover (PXE) configure-tempxe.yml collect_discovery discover_pxe
Validate validate-all.yml validate — (run on jumphost)
Prepare HV configure-hypervisors.yml prepare — (run on jumphost)
GPU host prep configure-hypervisors.yml prepare_gpu_passthrough —
Plan placement plan-vm-placement.yml plan plan_vm
Create guest provision-vms.yml create create_vm
Destroy guest provision-vms.yml destroy destroy
BM OS install install-bare-metal.yml install_bm install_bm
PXE discovery discover-pxe.yml discover_pxe discover_pxe
TempXE status configure-tempxe.yml tempxe_status status
Structured validate validate-integration.yml validate_integration — (jumphost / -e yaidap_emit_result=true)

The published umkim tree does not include examples/homelab/. Automation playbook: playbooks/flows/site-provision-yaidap.yml.