108 lines
3.6 KiB
PHP
108 lines
3.6 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Services\OpenStack;
|
||
|
|
|
||
|
|
use App\Services\Labs\DefinitionLab;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Traduit un lab.yaml en modèle Heat (étape 10) : un réseau Neutron par
|
||
|
|
* réseau du lab, sans DHCP et sans sécurité de port (les élèves configurent
|
||
|
|
* eux-mêmes leurs adresses), et une VM par machine, avec une interface par
|
||
|
|
* réseau déclaré, dans l'ordre (= ordre des interfaces ens3, ens4…).
|
||
|
|
*
|
||
|
|
* Jamais de routeur vers l'extérieur : les réseaux de lab sont isolés,
|
||
|
|
* conformément à CLAUDE.md (anti-abus, pas d'accès Internet depuis les VM
|
||
|
|
* élèves).
|
||
|
|
*/
|
||
|
|
class GenerateurTemplateHeat
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* @return array{template: array, noms_machines: array<int, string>}
|
||
|
|
*/
|
||
|
|
public function genererDepuis(DefinitionLab $lab, string $prefixe): array
|
||
|
|
{
|
||
|
|
$resources = [];
|
||
|
|
$outputs = [];
|
||
|
|
|
||
|
|
foreach ($lab->reseaux as $reseau) {
|
||
|
|
$cleReseau = self::cle($reseau['nom']);
|
||
|
|
|
||
|
|
$resources["reseau_{$cleReseau}"] = [
|
||
|
|
'type' => 'OS::Neutron::Net',
|
||
|
|
'properties' => [
|
||
|
|
'name' => "{$prefixe}-{$reseau['nom']}",
|
||
|
|
'port_security_enabled' => false,
|
||
|
|
],
|
||
|
|
];
|
||
|
|
|
||
|
|
$resources["sousreseau_{$cleReseau}"] = [
|
||
|
|
'type' => 'OS::Neutron::Subnet',
|
||
|
|
'properties' => [
|
||
|
|
'network' => ['get_resource' => "reseau_{$cleReseau}"],
|
||
|
|
'cidr' => $reseau['cidr'],
|
||
|
|
'enable_dhcp' => false,
|
||
|
|
],
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
$nomsMachines = [];
|
||
|
|
|
||
|
|
foreach ($lab->machines as $machine) {
|
||
|
|
$cleMachine = self::cle($machine['nom']);
|
||
|
|
$nomsMachines[] = $machine['nom'];
|
||
|
|
$ports = [];
|
||
|
|
|
||
|
|
foreach ($machine['reseaux'] as $nomReseau) {
|
||
|
|
$cleReseau = self::cle($nomReseau);
|
||
|
|
$clePort = "port_{$cleMachine}_{$cleReseau}";
|
||
|
|
|
||
|
|
$resources[$clePort] = [
|
||
|
|
'type' => 'OS::Neutron::Port',
|
||
|
|
'properties' => [
|
||
|
|
'network' => ['get_resource' => "reseau_{$cleReseau}"],
|
||
|
|
'port_security_enabled' => false,
|
||
|
|
'fixed_ips' => [],
|
||
|
|
],
|
||
|
|
];
|
||
|
|
|
||
|
|
$ports[] = ['port' => ['get_resource' => $clePort]];
|
||
|
|
}
|
||
|
|
|
||
|
|
$resources["machine_{$cleMachine}"] = [
|
||
|
|
'type' => 'OS::Nova::Server',
|
||
|
|
'properties' => [
|
||
|
|
'name' => "{$prefixe}-{$machine['nom']}",
|
||
|
|
'image' => $machine['image'],
|
||
|
|
'flavor' => $machine['flavor'],
|
||
|
|
'networks' => $ports,
|
||
|
|
],
|
||
|
|
];
|
||
|
|
|
||
|
|
$outputs["{$cleMachine}_id"] = [
|
||
|
|
'description' => "Id de l'instance {$machine['nom']}",
|
||
|
|
'value' => ['get_resource' => "machine_{$cleMachine}"],
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
$template = [
|
||
|
|
'heat_template_version' => '2021-04-16',
|
||
|
|
'description' => "Lab {$lab->identifiant} ({$prefixe})",
|
||
|
|
'resources' => $resources,
|
||
|
|
'outputs' => $outputs,
|
||
|
|
];
|
||
|
|
|
||
|
|
return ['template' => $template, 'noms_machines' => $nomsMachines];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Les noms de ressources Heat ne peuvent pas contenir les caractères du
|
||
|
|
* nom du lab (ex: "pc-a" → "pc_a"). Utilisé aussi par CreerStackLab pour
|
||
|
|
* retrouver, dans les sorties de la stack, quelle clé correspond à
|
||
|
|
* quelle machine.
|
||
|
|
*/
|
||
|
|
public static function cle(string $nom): string
|
||
|
|
{
|
||
|
|
return str_replace('-', '_', $nom);
|
||
|
|
}
|
||
|
|
}
|