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
|
|
@ -6,32 +6,57 @@
|
|||
@if ($labSession->etat === \App\Models\LabSession::EN_ATTENTE)
|
||||
<meta http-equiv="refresh" content="5">
|
||||
@endif
|
||||
<div class="mx-auto max-w-4xl px-5 py-14 lg:px-10">
|
||||
<div class="mx-auto max-w-5xl px-5 py-14 lg:px-10">
|
||||
<p class="font-mono text-sm font-semibold">{{ $seance->lab->titre }}</p>
|
||||
@if ($labSession->etat === \App\Models\LabSession::EN_ATTENTE)
|
||||
<div class="py-20 text-center">
|
||||
<h1 class="text-4xl font-extrabold tracking-tight">En attente que le prof t'admette…</h1>
|
||||
<p class="mt-4 font-semibold">Cette page se rafraîchit toute seule.</p>
|
||||
</div>
|
||||
@elseif ($labSession->stack_id)
|
||||
<h1 class="mt-2 text-3xl font-extrabold tracking-tight">Ta console</h1>
|
||||
<div id="terminal" class="mt-4 h-[480px] overflow-hidden rounded-2xl border border-[#e3e5e8]" style="background:#13233A"></div>
|
||||
@elseif ($labSession->etat === \App\Models\LabSession::ADMIS)
|
||||
<meta http-equiv="refresh" content="4">
|
||||
<div class="py-20 text-center">
|
||||
<h1 class="text-4xl font-extrabold tracking-tight">Préparation de tes VM…</h1>
|
||||
<p class="mt-4 font-semibold">Ça prend généralement moins d'une minute.</p>
|
||||
</div>
|
||||
@elseif ($labSession->machines->isNotEmpty())
|
||||
<h1 class="mt-2 text-3xl font-extrabold tracking-tight">Tes machines</h1>
|
||||
<div class="mt-4 flex gap-2" role="tablist">
|
||||
@foreach ($labSession->machines as $i => $machine)
|
||||
<button type="button" data-onglet="{{ $machine->id }}" class="onglet-machine rounded-lg border border-[#dadce0] px-4 py-2 font-mono font-bold {{ $i === 0 ? 'bg-[#0b57d0] text-white' : 'bg-white' }}">{{ $machine->nom }}</button>
|
||||
@endforeach
|
||||
</div>
|
||||
@foreach ($labSession->machines as $i => $machine)
|
||||
<div data-panneau="{{ $machine->id }}" @if ($i !== 0) hidden @endif class="mt-2 h-[480px] overflow-hidden rounded-2xl border border-[#e3e5e8]" style="background:#13233A">
|
||||
<div id="terminal-{{ $machine->id }}" class="h-full"></div>
|
||||
</div>
|
||||
@endforeach
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/css/xterm.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/lib/xterm.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0.10.0/lib/addon-fit.min.js"></script>
|
||||
<script src="{{ asset('js/console-reelle.js') }}"></script>
|
||||
<script>
|
||||
fetch('{{ route('console.eleve', $labSession) }}', {
|
||||
method: 'POST',
|
||||
headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]')?.content || '{{ csrf_token() }}' },
|
||||
}).then(function (r) { return r.json(); }).then(function (d) {
|
||||
window.SyllabusConsoleReelle.mount(document.getElementById('terminal'), { jeton: d.jeton, lectureSeule: false });
|
||||
var monte = {};
|
||||
document.querySelectorAll('.onglet-machine').forEach(function (bouton) {
|
||||
bouton.addEventListener('click', function () {
|
||||
var id = bouton.dataset.onglet;
|
||||
document.querySelectorAll('.onglet-machine').forEach(function (b) { b.classList.toggle('bg-[#0b57d0]', b === bouton); b.classList.toggle('text-white', b === bouton); b.classList.toggle('bg-white', b !== bouton); });
|
||||
document.querySelectorAll('[data-panneau]').forEach(function (p) { p.hidden = p.dataset.panneau !== id; });
|
||||
});
|
||||
});
|
||||
@foreach ($labSession->machines as $machine)
|
||||
fetch('{{ route('console.eleve', [$labSession, $machine]) }}', {
|
||||
method: 'POST',
|
||||
headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
|
||||
}).then(function (r) { return r.json(); }).then(function (d) {
|
||||
window.SyllabusConsoleReelle.mount(document.getElementById('terminal-{{ $machine->id }}'), { jeton: d.jeton, lectureSeule: false });
|
||||
});
|
||||
@endforeach
|
||||
</script>
|
||||
@else
|
||||
<div class="py-20 text-center">
|
||||
<h1 class="text-4xl font-extrabold tracking-tight">Tu es admis·e !</h1>
|
||||
<p class="mt-4 font-semibold">Le lancement de ta VM arrive dans une prochaine étape du déploiement.</p>
|
||||
<h1 class="text-4xl font-extrabold tracking-tight">La préparation a échoué</h1>
|
||||
<p class="mt-4 font-semibold">Préviens ton prof.</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue