ajoute la liaison Laravel-OpenStack et le modèle Heat du lab 08
Un gabarit Heat généré depuis chaque lab.yaml, une stack par session de lab (création à l'admission, suppression à l'expiration via des jobs Redis et un worker systemd dédié). Passage du compte de service à une authentification par mot de passe : Heat refuse de créer un trust à partir d'un jeton d'application credential (voir ADR 0002). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
8742bde807
commit
67a754f733
34 changed files with 1095 additions and 91 deletions
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\LabSession;
|
||||
use App\Models\LabSessionMachine;
|
||||
use App\Models\Seance;
|
||||
use App\Services\OpenStack\JetonConsole;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
|
@ -11,34 +12,33 @@ use Illuminate\Support\Facades\Auth;
|
|||
/**
|
||||
* Émet des jetons de console série à usage court (étape 9) : le navigateur
|
||||
* ne reçoit jamais l'adresse de nova-serialproxy, seulement un jeton Redis
|
||||
* valable 5 minutes. L'élève peut écrire dans sa propre VM ; le prof ne
|
||||
* peut que regarder celle d'un élève de sa classe.
|
||||
* valable 5 minutes. L'élève peut écrire dans ses propres VM ; le prof ne
|
||||
* peut que regarder celles d'un élève de sa classe (étape 10 : une session
|
||||
* de lab a plusieurs machines, voir LabSessionMachine).
|
||||
*/
|
||||
class ConsoleController extends Controller
|
||||
{
|
||||
public function __construct(private readonly JetonConsole $jetons) {}
|
||||
|
||||
public function pourEleve(LabSession $labSession): JsonResponse
|
||||
public function pourEleve(LabSession $labSession, LabSessionMachine $labSessionMachine): JsonResponse
|
||||
{
|
||||
$eleve = Auth::guard('eleve')->user();
|
||||
abort_if($labSession->eleve_id !== $eleve->id, 403);
|
||||
abort_if($labSession->etat !== LabSession::ADMIS, 403, 'En attente d\'admission.');
|
||||
abort_if($labSession->stack_id === null, 404, 'Aucune VM associée à cette session.');
|
||||
abort_if($labSessionMachine->lab_session_id !== $labSession->id, 404);
|
||||
|
||||
return response()->json([
|
||||
'jeton' => $this->jetons->pourEcriture($labSession->stack_id),
|
||||
'jeton' => $this->jetons->pourEcriture($labSessionMachine->instance_id),
|
||||
]);
|
||||
}
|
||||
|
||||
public function pourProf(Seance $seance, LabSession $labSession): JsonResponse
|
||||
public function pourProf(Seance $seance, LabSession $labSession, LabSessionMachine $labSessionMachine): JsonResponse
|
||||
{
|
||||
abort_if($seance->classe->user_id !== Auth::guard('web')->id(), 403);
|
||||
abort_if($labSession->seance_id !== $seance->id, 404);
|
||||
abort_if($labSession->etat !== LabSession::ADMIS, 403, 'Élève pas encore admis.');
|
||||
abort_if($labSession->stack_id === null, 404, 'Aucune VM associée à cette session.');
|
||||
abort_if($labSessionMachine->lab_session_id !== $labSession->id, 404);
|
||||
|
||||
return response()->json([
|
||||
'jeton' => $this->jetons->pourLecture($labSession->stack_id),
|
||||
'jeton' => $this->jetons->pourLecture($labSessionMachine->instance_id),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Jobs\CreerStackLab;
|
||||
use App\Models\Classe;
|
||||
use App\Models\LabSession;
|
||||
use App\Models\Seance;
|
||||
|
|
@ -34,7 +35,7 @@ class SeanceController extends Controller
|
|||
abort_if($seance->classe->user_id !== Auth::guard('web')->id(), 403);
|
||||
|
||||
return view('seances.attente', [
|
||||
'seance' => $seance->load(['classe', 'lab', 'labSessions.eleve']),
|
||||
'seance' => $seance->load(['classe', 'lab', 'labSessions.eleve', 'labSessions.machines']),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -45,16 +46,27 @@ class SeanceController extends Controller
|
|||
|
||||
return view('seances.console-prof', [
|
||||
'seance' => $seance->load('lab'),
|
||||
'labSession' => $labSession->load('eleve'),
|
||||
'labSession' => $labSession->load(['eleve', 'machines']),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Admettre un élève, c'est lancer son lab : la stack Heat se construit
|
||||
* en tâche de fond (étape 10), le terminal apparaît une fois prête.
|
||||
*/
|
||||
public function admettre(Seance $seance, LabSession $labSession): RedirectResponse
|
||||
{
|
||||
abort_if($seance->classe->user_id !== Auth::guard('web')->id(), 403);
|
||||
abort_if($labSession->seance_id !== $seance->id, 404);
|
||||
|
||||
$labSession->update(['etat' => LabSession::ADMIS]);
|
||||
$dureeMinutes = $labSession->lab->duree_min ?? 45;
|
||||
|
||||
$labSession->update([
|
||||
'etat' => LabSession::ADMIS,
|
||||
'expire_a' => now()->addMinutes($dureeMinutes),
|
||||
]);
|
||||
|
||||
CreerStackLab::dispatch($labSession);
|
||||
|
||||
return redirect()->route('seances.attente', $seance);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue