Images et microVM
Construire des microVMs
Avant de lire : Préparer votre environnement, Cloner, compiler et tester, la section virtualisation du manuel de cloud native, et la Partie 2 de Delonixfile et VMfile.
Cette page mène un contributeur d'un hôte Linux nu jusqu'à la construction, au démarrage et au test de VMs avec Delonix, et montre où se trouve le code lorsqu'il faut modifier quelque chose. Après elle, vous pouvez préparer un hôte pour Cloud Hypervisor et libvirt, prévoir quel backend une VM obtient, et tester une modification de VM via la CLI. Elle suppose que vous avez déjà lu Préparer votre environnement et que vous savez construire l'arborescence (Cloner, compiler et tester).
Ce qui a été vérifié pour cette page. Chaque commande et chaque option ci-dessous ont été vérifiées contre
delonix <group> --helpd'un binaire construit à partir de cette arborescence, et les commandes en lecture seule / de configuration (vm ls,vm reach,vm default-backend,image vm ls,manifest validate,stack apply --dry-run, les erreurs de sélection du backend) ont été exécutées avecDELONIX_ROOTetDELONIX_NET_RUNTIME_DIRpointant vers un répertoire jetable. Le démarrage d'une VM, la construction d'une image et le pull depuis le registre n'ont pas été exécutés lors de cette relecture — le comportement de ces opérations provient du code, des ADR et des tests scriptés référencés ci-dessous.
Utilisez toujours le binaire que vous avez construit (./target/debug/delonix), et non celui de
votre PATH, et isolez toujours les deux racines d'état pendant vos expérimentations — voir
Isolation.
1. Prérequis de l'hôte#
KVM#
Les deux backends locaux ont besoin de la virtualisation matérielle :
ls -l /dev/kvm # must exist; missing = VT-x/AMD-V off in firmware, or no nested virt
id -nG | tr ' ' '\n' | grep -x kvm # your user must be in the kvm group
scripts/install.sh (par défaut, c'est-à-dire sans --no-vm) vous ajoute aux groupes kvm et
libvirt et avertit lorsque /dev/kvm est absent. Les changements de groupe nécessitent une
nouvelle session.
Cloud Hypervisor et son firmware#
Le backend est disponible lorsque cloud-hypervisor est dans le PATH
(CloudHypervisorBackend::available dans crates/adapters/delonix-vm/src/lib.rs). Lorsque la
distribution ne le fournit pas en paquet, l'installateur télécharge le binaire statique amont
dans /usr/local/bin/cloud-hypervisor, épinglé à une version et à un SHA-256 dans
scripts/install.sh.
Pour démarrer une cloud image sans --kernel, CH a besoin d'un firmware UEFI.
default_ch_firmware utilise $DELONIX_HYPERVISOR_FW s'il est défini, sinon le premier fichier
existant de DEFAULT_CH_FIRMWARES :
/usr/local/share/delonix/CLOUDHV.fd ← EDK2 build from cloud-hypervisor/edk2 (preferred)
/usr/share/delonix/CLOUDHV.fd
/usr/local/share/delonix/hypervisor-fw ← rust-hypervisor-firmware (fallback)
/usr/share/delonix/hypervisor-fw
L'ordre compte. Mesuré et consigné dans le commentaire de documentation de la constante : sous
rust-hypervisor-fw, aucune des images construites par ce projet ne démarre dans CH ; avec EDK2
CLOUDHV.fd, elles démarrent. hypervisor-fw reste un repli pour les hôtes qui n'ont que lui.
L'installateur récupère les deux (chacun épinglé par tag et SHA-256). Le test unitaire
o_edk2_vem_antes_do_hypervisor_fw_na_procura_de_firmware protège cet ordre.
libvirt / QEMU#
Le backend libvirt est disponible lorsque virsh et qemu-system-x86_64 sont tous deux dans le
PATH (LibvirtBackend::available). L'installateur installe QEMU et un paquet de daemon libvirt,
et active libvirtd (par socket activation lorsque c'est pris en charge).
La connexion libvirt utilisée compte plus qu'il n'y paraît (libvirt_uri_for) :
| Situation | Connexion | Conséquence |
|---|---|---|
--net-mode nat ou bridge |
qemu:///system |
IP joignable ; nécessite le groupe libvirt (ou root) |
pas de --net-mode, connexion système utilisable |
qemu:///system, nat choisi automatiquement |
IP par DHCP depuis le réseau libvirt (virbr0) |
pas de --net-mode, connexion système non utilisable, rootless |
qemu:///session, mode utilisateur |
aucune IP visible ni joignable ; vm create avertit |
Sur qemu:///system, QEMU s'exécute sous l'utilisateur du service libvirt, qui ne peut pas lire un
disque situé sous un home en 0700. Pour un appelant rootless, le XML du domaine reçoit un
seclabel DAC statique qui épingle QEMU à votre uid/gid avec relabel='no', de sorte que votre
propre overlay démarre sans que son propriétaire soit changé.
Outils que le code VM invoque#
| Outil | Paquet (Debian / Fedora) | Utilisé par |
|---|---|---|
qemu-img |
qemu-utils / qemu-img |
overlays par VM, vm convert, snapshots sur CH, construction d'images |
cloud-localds |
cloud-image-utils / cloud-utils |
ISO de seed NoCloud — générée à chaque vm create d'une image cloud-init sauf si --seed est fourni (crates/) |
virsh |
libvirt-clients / libvirt-client |
backend libvirt |
virt-customize, virt-sparsify, virt-copy-out |
libguestfs-tools / guestfs-tools |
vm build / image vm build uniquement |
vmimage::tool_package associe un binaire manquant à son paquet, de sorte qu'un outil manquant est
signalé par son nom plutôt que par un simple No such file or directory.
Uniquement pour construire des images : --with-image-build#
image vm build exécute virt-customize, qui construit une petite appliance avec supermin. Trois
problèmes d'hôte la cassent d'une manière qui ne ressemble pas à des problèmes d'hôte ;
scripts/install.sh --with-image-build les traite, et tool_failure_hint (cmd/vmimage.rs) les
nomme lorsqu'un build échoue :
- Aucun client DHCP sur l'hôte. supermin copie les paquets de l'hôte dans l'appliance ; sans
isc-dhcp-client, l'appliance n'a pas de réseau et le build meurt surTemporary failure resolving …. L'installateur l'installe. /boot/vmlinuz-*est en 0600 (Debian/Ubuntu). supermin copie le noyau de l'hôte et échoue avecPermission denied. L'installateur exécutechmod 0644 /boot/vmlinuz-*— cela abaisse une frontière de sécurité de l'hôte (tout utilisateur local peut lire l'image du noyau) ; c'est donc opt-in, et l'installateur affiche comment revenir en arrière (sudo chmod 0600 /boot/vmlinuz-*). L'indication d'échec montre aussi comment faire survivre ce réglage aux mises à jour du noyau.- passt, uniquement avec
image vm build --network. libguestfs donne un réseau à l'appliance via passt. Son profil AppArmor (Debian/Ubuntu) interdit le répertoire d'exécution qu'utilise libguestfs, et le passt fourni dans Ubuntu 24.04 démarre mais ne distribue jamais de bail —dhclientattend ~300 s et le build continue sans réseau, pour échouer plus tard sur un miroir de paquets. Remèdes :
mkdir -p /tmp/delonix-run && chmod 700 /tmp/delonix-run
XDG_RUNTIME_DIR=/tmp/delonix-run ./target/debug/delonix image vm build --network …
et, si cela échoue encore, un passt récent en premier dans le PATH (l'installateur en
construit un dans /usr/local/bin). Ne « désactivez » pas passt avec un stub qui échoue :
libguestfs utilise alors le stub et meurt dessus.
Le mode --offline de la recette dorée évite entièrement le piège 3 : il récupère et vérifie les
paquets sur l'hôte et exécute l'invité avec --no-network.
L'isolation d'abord#
Cette machine peut exécuter d'autres charges de travail. Avant toute commande vm allant au-delà de
--help :
export DELONIX_ROOT=$HOME/dlx-dev/root
export DELONIX_NET_RUNTIME_DIR=/tmp/dlx-dev-run # keep it SHORT (AF_UNIX sun_path is 108 bytes)
export TMPDIR=$HOME/dlx-dev/tmp # VMfile builds put whole disks here
mkdir -p "$DELONIX_ROOT" "$DELONIX_NET_RUNTIME_DIR" "$TMPDIR"
Les deux racines, toujours : isoler uniquement DELONIX_ROOT laisse les sockets réseau partagées
avec l'état réel, et cela a déjà redémarré de vraies charges de travail (voir
Cloner, compiler et tester). Une VM Cloud Hypervisor refuse aussi d'emblée lorsque
<root>/vms/<name>.sock ne tiendrait pas dans sun_path (ch_socket_paths_fit) ; évitez donc les
chemins DELONIX_ROOT très profonds.
2. Les backends et comment l'un d'eux est choisi#
Le port et le registre#
VmBackend (crates/adapters/delonix-vm/src/lib.rs) est le port que chaque hyperviseur
implémente : id, available, boot, is_running, ip, stop, plus des méthodes avec
implémentation par défaut (destroy, pause, unpause, resume,
snapshot/restore/snapshots/delete_snapshot, preserve_snapshots, ip_is_predicted,
manages_own_storage, auto_selectable, disk_health). Une implémentation par défaut qui ne peut
pas être honorée échoue de manière fermée avec un message, jamais par un no-op silencieux.
Les backends vivent dans un registre (BACKENDS), et non dans un match :
| Backend | Crate | Alias | Sélection automatique |
|---|---|---|---|
cloud-hypervisor |
delonix-vm (intégré) |
ch, cloudhypervisor |
oui |
libvirt |
delonix-vm (intégré) |
kvm, qemu |
oui |
proxmox |
delonix-proxmox (enregistré par la CLI) |
— | non — sélectionné par nom uniquement |
register_backend refuse un id/alias qui appartient à un autre backend, et refuse
auto_selectable: true pour tout ce qui n'est pas intégré : l'auto-détection interroge
available() de chaque candidat, et un backend distant ne peut y répondre que par le réseau.
L'enregistrement ne fait aucune I/O ; la factory s'exécute la première fois que le backend est
sélectionné. backend_for sur une VM existante résout le backend enregistré, et un nom inconnu est
une erreur (auparavant, il retombait sur CH).
Ordre de priorité de la sélection pour une nouvelle VM#
D'après delonix_vm::create_with et resolve_vm_defaults (cmd/vm.rs), la première
correspondance l'emporte :
--backend(oubackend:dans le manifeste).- Le
HYPERVISORde l'image (enregistré par un build de VMfile), lorsque--diskdésigne une image locale. DELONIX_VM_BACKEND(pour toute la session).delonix vm default-backend --set <backend>(pour toute la machine, stocké dans<DELONIX_ROOT>/vm-default-backend).- Heuristique de capacités :
volumesprésents ⇒libvirt(seul libvirt fait du virtio-9p) ; une cloud image sans--kernel⇒libvirtsi libvirt est disponible ; sinon auto-détection — le premier backend enregistré sélectionnable automatiquement qui est installé (CH, puis libvirt).
Ainsi, sur un hôte doté des deux hyperviseurs, un simple vm create d'une cloud image aboutit sur
libvirt ; passez --backend cloud-hypervisor (ou définissez un défaut) pour obtenir une microVM
sur le SDN.
$ delonix vm default-backend
none (auto-detection: cloud-hypervisor if installed, else libvirt)
$ delonix vm default-backend --set ch
default backend set to cloud-hypervisor
$ delonix vm default-backend --set bogus
error invalid argument: unknown VM backend: 'bogus' (use 'cloud-hypervisor', 'libvirt')
$ delonix vm default-backend --clear
default backend cleared (falls back to auto-detection)
Proxmox VE (distant)#
bins/delonix-runtime-bin/src/cmd/vmbackends.rs::register_configured enregistre le backend Proxmox
au démarrage lorsqu'il est configuré par l'environnement (une mauvaise configuration est un
avertissement, jamais une erreur fatale pour des commandes sans rapport) :
| Variable | Signification |
|---|---|
DELONIX_PROXMOX_URL |
URL de base de l'API, p. ex. https:/. Non définie = backend non enregistré. |
DELONIX_PROXMOX_NODE |
Obligatoire. Le nœud unique auquel s'adresse ce backend (tel que GET /nodes le nomme). |
DELONIX_PROXMOX_SECRET |
Identifiant préféré : nom d'un kind: Secret avec tokenId+tokenSecret (ou username+password). |
DELONIX_PROXMOX_TOKEN_ID + DELONIX_PROXMOX_TOKEN |
Jeton d'API depuis l'environnement. |
DELONIX_PROXMOX_USER + DELONIX_PROXMOX_PASSWORD |
Connexion par mot de passe (ticket, réauthentifié sur 401). |
DELONIX_PROXMOX_INSECURE_TLS |
1/true/yes pour ignorer la vérification du certificat. Opt-in, jamais un repli. |
DELONIX_PROXMOX_BRIDGE |
Bridge par défaut sur le nœud (un bridge par VM l'emporte). |
DELONIX_PROXMOX_VLAN |
Tag VLAN par défaut, 1–4094 ; hors plage, c'est une erreur, et non une NIC silencieusement sans tag. |
Sans configuration, --backend proxmox répond que le backend « is not available in this build » et
indique ce qu'il faut définir (exécuté). Le backend possède son propre stockage
(manages_own_storage), donc aucun overlay local ni seed NoCloud n'est créé ; --hostname/--ssh-key
vont au cloud-init du nœud, et --user-data est refusé. Conception et limites :
ADR-0008. Un backend OpenStack est seulement proposé
(ADR-0039) ; il n'existe aucun code pour lui.
3. Images#
Les images VM vivent dans VmImageStore (cmd/vmimage.rs) sous <DELONIX_ROOT>/vm-images/ : un
qcow2 plus un enregistrement de métadonnées JSON (VmImage) par image. delonix image vm ls les
liste avec TYPE (cloud-init / appliance) et DEFAULTS (vCPU/mémoire enregistrés).
Images officielles#
OFFICIAL_REPOS dans cmd/vmimage.rs :
| Clé | Dépôt | Contenu |
|---|---|---|
k8s |
ghcr. |
nœud Kubernetes (kubeadm/kubelet/kubectl + delonix-cri) |
base |
ghcr. |
OS de base avec le moteur delonix, sans Kubernetes (p. ex. ubuntu-24.04) |
appliances |
ghcr. |
appliances de fournisseurs, sans cloud-init |
delonix vm ls-remote # tags of the Kubernetes golden repo
delonix vm ls-remote --no-k8s # tags of the base repo
delonix vm pull # the official Kubernetes golden
delonix vm pull --no-k8s # the official base image
delonix vm pull <oci-ref> --name <local-name>
Les images sont des artefacts OCI à blob unique ; le pull vérifie les digests du manifeste et du
blob, et restaure les métadonnées à partir des annotations du manifeste. Les mêmes verbes existent
sous la forme delonix image vm pull/ls-remote/push. Remarque : vm create sans --disk et
sans image locale télécharge l'image dorée officielle ; il a donc besoin du réseau.
Construire la recette dorée#
delonix vm build -t <tag> (la même commande que delonix image vm build ; les deux partagent un seul jeu
d'arguments) sans vm.yaml ni VMfile dans le contexte exécute la recette intégrée. Les exemples
ci-dessous utilisent la graphie image vm :
# Kubernetes node, packages fetched and verified on the HOST, guest offline
delonix image vm build --offline --k8s-version 1.34 -t delonix-vm-k8s:1.34
# no Kubernetes: just the engine, rootless-ready
delonix image vm build --no-k8s --distro debian --debian-release bookworm -t delonix-vm-base:debian-bookworm
Options pertinentes (consultez image vm build --help pour les valeurs par défaut) :
--distro ubuntu|debian|rocky|fedora, --ubuntu-release, --debian-release, --rocky-release,
--fedora-release (release et build, p. ex. 42-1.1), --k8s-version, --offline,
--no-k8s, --extra-package, --extra-run, --cri-bin, --delonix-bin, --root-password (sans
elle, aucun compte n'a de mot de passe), --node-exporter[=<addr>], --no-compress. Votre propre
recette est un VMfile ou un vm.yaml — voir Delonixfile et VMfile. Le dossier images/ du
dépôt fournit un vm.yaml par distribution (ubuntu, debian, rocky, fedora, construites hors ligne) et par appliance ;
scripts/verify-images.sh les construit dans un DELONIX_ROOT isolé et relit le qcow2
(--self-test prouve que ses vérifications peuvent échouer). L'installation de paquets, les profils de la recette dorée, le démarrage
des images construites et les builders d'appliances n'ont pas encore été validés (notes de release v4.2.0). Les
builds d'images sont uniquement amd64 (ADR-0018).
Convertir et importer#
delonix vm convert <image-or-path> --to raw|qcow2|vmdk|vdi|vhdx|vhd [-o out] [--compress]
delonix image vm import disk.qcow2 -t opnsense:26.1 --appliance --default-vcpus 2 --default-memory 3G
vm convert aplatit (aucune chaîne de backing) ; --compress n'est accepté que pour qcow2 et
vmdk. import --appliance enregistre cloud_init: false : vm create n'attache alors aucun
seed et refuse --hostname/--ssh-key/--user-data en les nommant, car l'invité ne les lirait
jamais. Les scripts de construction d'appliances se trouvent dans scripts/appliances/.
4. Créer et exécuter#
vm create#
delonix vm create dev --disk delonix-vm-base:ubuntu-24.04 \
--backend cloud-hypervisor --vcpus 2 --memory 2G \
--ssh-key @$HOME/.ssh/id_ed25519.pub --hostname dev --wait
Ce qui se passe (cmd/vm.rs → delonix_vm::create_with) :
- La politique du nœud est imposée avant la résolution de toute image (
policy::enforce). - Résolution du disque (
resolve_image_ref) :--url-imgl'emporte (téléchargé, mis en cache, vérifié contre<url>.sha256lorsqu'il est proposé) ; sinon--diskest recherché comme nom d'image locale, puis comme chemin vers le qcow2 d'une image stockée ; sinon il est utilisé comme simple chemin ; sans--disk, c'est l'unique image dorée locale, ou l'image officielle est récupérée par pull. - Les valeurs par défaut issues des métadonnées de l'image complètent
--vcpus/--memory/--backenduniquement là où ils ne sont pas définis. - Seed : une ISO NoCloud (configuration réseau par MAC, hostname, clés) est générée, sauf si
--seedest fourni, si l'image est une appliance ou si le backend est distant.--user-dataremplace le user-data généré. - Backend choisi (section 2) ; une vérification d'admission refuse lorsque l'hôte manque de
RAM ; un
--namespaceautre quedefaultest refusé sur libvirt (la VM vit survirbr0, en dehors du SDN Delonix). - Overlay :
<root>/vms/<name>.qcow2, un qcow2 mince au-dessus de la base (prepare_local_overlay) ;--disk-size <GiB>l'agrandit et ne peut pas être inférieur à la base. - Démarrage : le
bootdu backend.createest idempotent : une VM existante et en cours d'exécution est renvoyée telle quelle.
Les images publiées ne définissent de mot de passe sur aucun compte (voir --root-password
ci-dessus) ; passez donc --ssh-key si vous voulez vous connecter en SSH.
--wait et l'IP prédite. Sur libvirt, l'IP provient d'un vrai bail DHCP ; en avoir une prouve
donc que l'invité a démarré. Sur Cloud Hypervisor, l'IP est calculée à partir de la MAC avant
que l'invité ne s'exécute (ip_is_predicted) ; --wait sonde donc aussi l'adresse par ARP depuis
l'intérieur du holder réseau (delonix_sdn::infra::sdn_reachable) jusqu'à --boot-timeout (120 s
par défaut). Trois issues : démarrée ; « which could not be verified from here » (la sonde n'a pas
pu être lancée) ; « is running but never answered … computed from the MAC, not observed ». Utilisez
vm console pour voir pourquoi.
Verbes du quotidien (day-2)#
| Commande | Remarques |
|---|---|
delonix vm ls [--namespace <ns>] [--ports] [-o json] |
liste les VMs |
delonix describe vm <name> / delonix delete vm <name> |
il n'existe ni vm describe ni vm rm ; les verbes génériques les remplacent |
delonix vm console <name> [-e ^X] |
console série ; détachement avec Ctrl-] par défaut ($DELONIX_CONSOLE_ESCAPE). libvirt : virsh console comme processus enfant ; CH : la socket de console <root>/ |
delonix vm ssh <name|ip> [-l user] [-i key] [-- cmd] |
IP issue de l'enregistrement ; utilisateur par défaut delonix sur les images cloud-init, root sur les appliances |
delonix vm vnc <name> |
uniquement pour les VMs libvirt créées avec --vnc (CH n'a pas d'affichage) |
delonix vm stop <name> |
conserve le disque, l'enregistrement et les snapshots. libvirt : le domaine est supprimé de la définition (undefine) (les métadonnées des snapshots sont préservées d'abord) |
delonix vm start <name> / restart <name> |
reconstruisent le démarrage à partir de l'enregistrement et réutilisent l'overlay ; start sur une VM en cours d'exécution est un no-op, restart redémarre toujours |
delonix vm pause / unpause <name> |
suspendent les vCPUs, la mémoire est conservée en RAM ; CH et libvirt |
delonix vm migrate <name> --host <h> --network <n> |
stop-copy-start par SSH vers un autre hôte ; interruption réelle (ADR-0031 explique pourquoi la migration à chaud est hors périmètre) |
delonix vm prune |
récupère l'état dont aucun enregistrement de VM ne rend compte |
Snapshots#
delonix vm snapshot create|ls|rm|restore <vm> [<snapshot>] :
| Backend | VM en cours d'exécution | VM arrêtée |
|---|---|---|
| libvirt | create est un checkpoint système (mémoire + disque) |
disque uniquement ; les quatre verbes définissent le domaine juste le temps de la commande |
| cloud-hypervisor | ls uniquement (qemu-img info -U) ; create/restore/rm refusés — le VMM en cours d'exécution verrouille le disque et CH n'a pas d'API de snapshot disque à chaud |
les quatre, via qemu-img snapshot |
| proxmox | create (avec l'état de la VM), ls, restore |
idem ; rm non implémenté (échoue de manière fermée) |
Les snapshots libvirt survivent à vm stop/vm start : undefine --snapshots-metadata ne supprime
que la comptabilité de libvirt ; preserve_snapshots exporte donc le XML de chaque snapshot dans
<root>/vms/<vm>/snapshots/ avant l'arrêt, et boot les redéfinit (en réécrivant l'uuid du
domaine, qui change à chaque définition).
Déclaratif#
kind: VirtualMachine (compute.delonix.io/v1alpha1) reflète vm create ; un exemple complet et
annoté se trouve dans examples/vm.yaml. kind: Workload avec type: microvm se réduit à une
VirtualMachine dont le backend est forcé à cloud-hypervisor ; demander un autre backend est
une erreur (ADR-0006). Les deux ont été exécutés dans une
racine jetable :
apiVersion: compute.delonix.io/v1alpha1
kind: VirtualMachine
metadata: { name: dev }
spec:
disk: delonix-vm-base:ubuntu-24.04
resources: { vcpus: 2, memory: 2G }
cloudInit:
hostname: dev
sshKeys: ["@~/.ssh/id_ed25519.pub"]
---
apiVersion: compute.delonix.io/v1alpha1
kind: Workload
metadata: { name: fast }
spec:
type: microvm
microvm: { disk: delonix-vm-base:ubuntu-24.04, vcpus: 1, memory: 1G }
$ delonix manifest validate -f vm.yaml
stack validate: OK — 2 document(s), all references resolved
$ delonix stack apply -f vm.yaml --dry-run | grep backend
backend: null
backend: cloud-hypervisor
Appliquez avec delonix vm apply -f vm.yaml ou delonix stack apply -f vm.yaml (non exécuté ici).
5. Réseau pour les VMs#
| Cloud Hypervisor | libvirt | |
|---|---|---|
| Où vit la NIC | un tap sur un réseau Delonix (--network, par défaut ingress) à l'intérieur du holder réseau — le même SDN que les containers |
virbr0 (nat) ou un bridge de l'hôte, dans le namespace réseau de l'hôte |
| IP | bail du DHCP du holder, déterministe à partir de la MAC | DHCP de libvirt ; --ip en réserve une (nat uniquement) |
| Isolation par namespace | oui (--namespace) |
refusée |
| VM ↔ container par IP | directe | container → VM fonctionne via l'hôte ; VM → container nécessite un port publié ou vm bridge |
vm reach (lecture seule, sans privilège) liste les passerelles libvirt et, pour chaque port
publié par un container en cours d'exécution, indique si une VM peut l'atteindre. Un port publié sur
le 127.0.0.1 par défaut est invisible pour les VMs ; la commande affiche la republication exacte,
p. ex. DELONIX_PUBLISH_ADDR=<gateway> delonix net ingress publish <c> <port> — joignable depuis les
VMs de ce réseau, pas depuis le LAN externe.
vm bridge <network> [--vm-subnet <cidr>] [--apply] est expérimental et nécessite root : une
veth de l'hôte vers le holder plus des routes, qui donne aux VMs libvirt une joignabilité IP directe
vers un réseau de containers. Sans --apply, la commande n'affiche que le plan.
vm unbridge <network> le démonte (également en dry-run sans --apply). C'est la seule exception
délibérée au rootless dans le code VM (cmd/vmbridge.rs).
6. Dépannage#
| Symptôme | Cause | Correctif |
|---|---|---|
/dev/kvm does not exist / la VM ne démarre pas |
virtualisation désactivée, ou pas de virtualisation imbriquée | activez VT-x/AMD-V ; dans une VM, activez la virtualisation imbriquée |
no VM backend available |
ni cloud-hypervisor ni virsh+qemu-system-x86_64 dans le PATH |
installez-en un ; scripts/install.sh le fait |
| VM CH « en cours d'exécution » mais ne répond jamais ; l'overlay reste minuscule | le firmware ne peut pas démarrer l'image (p. ex. seul hypervisor-fw est installé) |
installez EDK2 CLOUDHV.fd dans /, ou définissez DELONIX_HYPERVISOR_FW, ou utilisez --backend libvirt |
vm ls n'affiche aucune IP pour une VM libvirt |
repli sur qemu:///session en mode utilisateur |
rejoignez le groupe libvirt et reconnectez-vous, ou --net-mode nat |
warning: cannot reach qemu:/ |
pas dans le groupe libvirt |
sudo usermod -aG libvirt $USER, nouvelle session |
vm console sur libvirt : « Active console session exists » |
une session précédente est morte de manière non propre | le code actuel passe --force à virsh console ; mettez à jour votre binaire |
| VM CH refusée avant le démarrage en mentionnant le chemin de la socket | <root>/ dépasse 108 octets |
DELONIX_ROOT ou nom de VM plus court |
namespace '…' is not enforceable on the 'libvirt' backend |
les VMs libvirt sont en dehors du SDN | --backend cloud-hypervisor, ou retirez --namespace |
vm snapshot create refusé sur une VM CH en cours d'exécution |
CH n'a pas de snapshot disque à chaud | vm stop d'abord, ou utilisez libvirt |
--hostname/--ssh-key refusés |
l'image est une appliance (cloud_init: false) |
configurez l'appliance via sa propre console/interface |
cloud-localds not found |
cloud-image-utils manquant |
installez-le (nécessaire pour chaque vm create cloud-init) |
image vm build : cp: cannot open '/ |
le noyau de l'hôte est en 0600 | install., ou sudo chmod 0644 / (abaisse une frontière) |
image vm build : Temporary failure resolving … |
l'appliance n'a pas de réseau : client DHCP de l'hôte manquant, ou passt | installez isc-dhcp-client ; pour --network, utilisez XDG_RUNTIME_DIR=/ et un passt récent en premier dans le PATH ; ou construisez avec --offline |
| une étape se met en pause ~300 s, puis les installations de paquets échouent | passt n'a jamais distribué de bail ; dhclient a expiré |
comme ci-dessus |
--offline belong to the built-in golden recipe … |
option de la recette dorée utilisée avec un VMfile | retirez-la ; le VMfile décrit le build |
`--network` is for VMfile builds |
--network sans VMfile |
utilisez --offline pour la recette dorée |
le build d'un VMfile remplit /tmp |
chaque étape est un disque complet aplati sous $TMPDIR |
définissez TMPDIR sur un système de fichiers volumineux ; supprimez les répertoires delonix-vmfile-* restants après des échecs |
VM backend 'proxmox' is not available in this build |
le backend n'est pas configuré | définissez les variables DELONIX_PROXMOX_* (section 2) |
7. Pour les contributeurs#
Où se trouve le code#
| Domaine | Chemin |
|---|---|
Port, registre, backends CH et libvirt, create_with, snapshots, recherche du firmware |
crates/ |
| Génération du seed NoCloud | crates/ |
| Backend Proxmox | crates/ |
CLI vm, kind: VirtualMachine, vm reach |
bins/ |
| Store d'images, recette dorée, pull/push/import/convert, indications d'échec | bins/ |
| VMfile | bins/ |
| Enregistrement des backends depuis l'environnement | bins/ |
vm bridge |
bins/ |
Réduction de kind: Workload |
bins/ |
| Construction d'appliances | scripts/appliances/ |
Ajouter un backend#
Lisez d'abord ADR-0008 ; c'est le modèle. En résumé :
- Implémentez
VmBackenddans son propre crate s'il parle à une API distante (le crate du moteur reste exempt de clients HTTP), placé dans le répertoire de sa couche et listé dansscripts/arch_fitness.py(voir Architecture). - Enregistrez-le avec
register_backenddepuis le processus qui connaît sa configuration, avecauto_selectable: false, sauf s'il s'agit d'un backend local, sans configuration, intégré àdelonix-vm. - Surchargez délibérément
manages_own_storage,destroy,resumeetip_is_predicted: pour un backend distant,stopetdestroyne sont pas la même opération, etbootsur une VM arrêtée ne doit pas en créer une seconde. - Laissez les verbes non pris en charge sur leurs implémentations par défaut qui échouent de manière
fermée ; refusez par leur nom les champs de
VmConfignon pris en charge avant de créer quoi que ce soit. - Ne publiez pas un backend qu'on n'a jamais vu démarrer une VM. Les nouveaux backends et les nouvelles frontières d'hyperviseur passent par un ADR (docs/adr/).
Tests#
- Tests unitaires purs — les constructeurs d'argv et de XML sont des fonctions pures, ils se
testent donc sans hyperviseur : p. ex.
libvirt_snapshot_argv_uses_flags_not_positional,snapshot_xml_with_uuid,libvirt_domain_xml, le test de l'ordre des firmwares ci-dessus, les tests du registre et deauto_detect, et les tests de parseur/scaffold danscmd/vmfile.rs. Exécutezcargo test -p delonix-vmetcargo test -p delonix-runtime-bin vmfile(voir Cloner, compiler et tester pourprotocet le répertoire cible). scripts/e2e.sh— les sectionsvms'exécutent sans hyperviseur (listage, refus) et, lorsque c'est disponible, exercent les snapshots à travers stop/start sur libvirt (nécessitevirsh,qemu-imget unqemu:///systemutilisable) et sur Cloud Hypervisor. Le script isole les deux racines d'état par défaut ; la section CH refuse de s'exécuter si seuleDELONIX_ROOTest isolée. Les sections dont l'hyperviseur est absent sont signalées comme ignorées, et non comme réussies.- Test en conditions réelles Proxmox —
crates/providers/delonix-proxmox/tests/live.rscrée et détruit une VM contre un vrai nœud et est ignoré sauf siDELONIX_PROXMOX_TEST_URL(ainsi que_NODE,_USER,_PASS) est défini :cargo test -p delonix-proxmox --test live -- --nocapture. Utilisez un nœud jetable. - Cycle de vie des providers — lorsque vous modifiez
delonix-vmou un provider, prouvez le cycle de vie complet (create, stop, start, snapshot, destroy) uniquement à travers la CLIdelonix, en observant l'hyperviseur en lecture seule (virsh -r,GETd'API), sans jamais le réparer à la main entre les étapes. - Regardez, ne devinez pas. Lorsqu'un invité ne démarre pas, la console série (
vm console) ou une capture d'écran libvirt répond en quelques secondes à ce que des hypothèses mettent des heures à trouver — et validez avec la commande qu'un utilisateur taperait, et non avec les options pratiques pour le débogage (--vnca un jour masqué un échec de démarrage qui ne se produisait que sans périphérique vidéo).
Suivant : Dépannage — un index organisé par symptôme pour les gates et les pièges d'hôte que vous pouvez rencontrer en construisant et en testant.