Stock de stacks prêtes par lab dans Redis (prise atomique en Lua, ménage par comparaison avec Heat, disjoncteur), files gérées par Horizon, séances planifiables. Correcteur Go sur l'hyperviseur : socket Unix, commandes lues dans le lab.yaml uniquement, exécution par l'agent invité QEMU. Une création de stack ratée est supprimée et réessayée deux fois, puis la session passe en échec, visible du prof. Corrige aussi trois défauts des étapes précédentes : la console se coupait à la première frappe d'un navigateur (trames texte), l'élève ne pouvait pas rejoindre une séance, la déconnexion n'avait pas de jeton CSRF. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.9 KiB
Runbook — Labs, stock chaud et correction (étapes 10 et 11)
Où sont les choses
| Élément | Emplacement |
|---|---|
| Source éditoriale des labs | paillasse-contenus/ (dépôt de contenu, pas de code) |
| Copie de travail lue par le portail et le correcteur | labs/ à la racine de ce dépôt → synchronisée vers /opt/labs sur le serveur |
Catalogue (table labs) |
php artisan labs:synchroniser, lancé par Ansible après chaque synchronisation de labs/ |
Lecture d'un lab.yaml |
portail/app/Services/Labs/DefinitionLab.php |
| Traduction lab → gabarit Heat | portail/app/Services/OpenStack/GenerateurTemplateHeat.php |
| Construction d'une stack (3 essais) | portail/app/Services/OpenStack/FabriqueStack.php |
| Authentification OpenStack | portail/app/Services/OpenStack/KeystoneAuth.php (mot de passe — ADR 0002, rotation : compte-service-openstack.md) |
| Stock chaud | portail/app/Services/Labs/StockChaud.php, job CreerStackStock, commande labs:remplir-stock chaque minute — ADR 0003 |
| Admission (stock ou construction) | SeanceController::admettre → CreerStackLab si le stock est vide |
| Suppression et expiration | SupprimerStackLab, commande labs:expirer-sessions chaque minute |
| Files de jobs | Laravel Horizon, service systemd portail-horizon : superviseurs sessions (4 processus) et stock (2), config/horizon.php |
| Correcteur | service systemd correcteur (Go, correcteur/, binaire /usr/local/sbin/correcteur), socket /run/correcteur/correcteur.sock (0660 root:www-data) |
| Correction côté portail | ClientCorrecteur, CorrigerSession, table corrections |
| Tests du parcours réel | portail/tests/Reels/ (préparation + parcours prof/élève) |
États d'une session de lab
en_attente → (prof : Admettre) → actif tout de suite si le stock a une
stack, sinon admis puis actif quand CreerStackLab a fini → expire ou
termine. Après 3 essais ratés : echec, la raison est affichée au prof
qui peut cliquer « Réessayer » (retour à admis).
Ajouter un nouveau lab
- Le lab existe dans
paillasse-contenus/{id}/lab.yaml. L'ordre des réseaux d'une machine décide de l'ordre des interfaces (ens3,ens4…). Les vérifications dont l'id commence parbonus-ne comptent pas pour « réussi ». - Le copier dans
labs/{id}/lab.yamlde ce dépôt. - Vérifier que les images et flavors existent (
openstack image list,openstack flavor list) et que l'image ahw_qemu_guest_agent=yes(sinon le correcteur répondagent_injoignable). - Déployer :
cd ansible && script -q /dev/null ansible-playbook correcteur.yml -i inventory.ini(portail + correcteur). Le lab entre au catalogue, et son stock se remplit dans la minute. - Tester le parcours :
portail/tests/Reels/(voir l'en-tête des deux scripts), puis supprimer les données de test.
Stock chaud
ssh paillasse "cd /var/www/portail && sudo -u www-data HOME=/tmp php8.3 artisan labs:remplir-stock"
Affiche, par lab : cible, prêtes, en construction, commandées, retirées,
disjoncteur. Réglages (.env du portail, sinon valeurs de config/labs.php) :
LABS_CAPACITE_VM(15) : plafond de VMeleve.petit, sessions et stock compris ;LABS_STOCK_TAILLE(1) : stacks prêtes par lab hors séance.
Disjoncteur ouvert (« oui ») : 3 échecs définitifs de suite sur ce lab. Lire
storage/logs/laravel.log (CreerStackStock), corriger la cause (image,
flavor, quota…), puis le réarmer sans attendre ses 30 min :
sudo -u www-data HOME=/tmp php8.3 artisan tinker --execute='Illuminate\Support\Facades\Redis::del("stock:echecs:{lab}");'
Vider le stock d'un lab (les stacks seront supprimées par le ménage) : passer
LABS_STOCK_TAILLE=0 puis attendre une minute, ou supprimer la clé
stock:pretes:{lab} (le ménage supprime alors les stacks orphelines après 10 min).
Correcteur
systemctl status correcteur
journalctl -u correcteur -f # une ligne par vérification : instance, lab, id, résultat, durée
Il n'accepte que {"instance": uuid, "lab": id, "verification": id}, refuse
tout champ en plus, et n'exécute que la commande du lab.yaml, en root dans
la VM, par guest-exec (10 s maximum). Avant d'exécuter, il vérifie dans les
métadonnées libvirt que la VM appartient au projet paillasse et porte le
nom de la machine visée. Codes d'erreur : requete_invalide, lab_inconnu,
verification_inconnue, machine_non_conforme, agent_injoignable,
delai_depasse.
Inspecter les stacks sur le serveur
sudo -i
export PATH=/opt/kolla-venv/bin:$PATH
export OS_CLIENT_CONFIG_FILE=/etc/kolla/clouds-paillasse.yaml OS_CLOUD=paillasse-service
openstack stack list # lab-session-{id}-e{n} : sessions ; stock-{lab}-{xxxxxx}-e{n} : stock
openstack server list
Pièges rencontrés
- Heat refuse une application credential (
Delegated tokens cannot manage trusts), même--unrestricted: voir ADR 0002. - Horizon garde le code et la configuration en mémoire : le rôle Ansible le redémarre après chaque synchronisation de code ou changement de
.env. - Timeouts emboîtés : job (280 s) < superviseur Horizon (300 s) <
REDIS_QUEUE_RETRY_AFTER(330 s). Sinon Redis redonne un job encore en cours à un autre processus, et deux stacks sont construites. - Console muette après la première touche :
nova-serialproxyferme la connexion à la première trame WebSocket texte. Le proxy Go envoie tout en binaire — voir post-mortem du 2026-10-08. sudo -u www-data php artisan ...exigeHOME=/tmp(pas de$HOMEinscriptible pourwww-data).- Une stack appartient à une session (un élève, une tentative) ; une stack du stock n'y retourne jamais après avoir été donnée.