#!/bin/bash ################################################################################ # Scripts de Migration et d'Audit - Nomenclature v2.0 # L'Alliance Boréale # # Version: 1.0 # Date: 21 octobre 2025 # Licence: AGPL-3.0 # # DESCRIPAM_FILE="/etc/alliance-boreale/ipam.txt" DNS_OUTPUT="/var/lib/alliance-boreale/dns-records.zone" INVENTORY_OUTPUT="/var/lib/alliance-boreale/inventory.yml" CONFIG # Créer répertoires de travail mkdir -p /var/lib/alliance-boreale mkdir -p /var/log/alliance-boreale # Source configuration dans les scripts echo "source /etc/alliance-boreale/nomenclature.conf" >> ~/.bashrc echo "✅ Configuration créée: /etc/alliance-boreale/nomenclature.conf" echo "✅ Répertoires créés: /var/lib/alliance-boreale" echo "" echo "Scripts installés:" echo " - audit-nomenclature.sh" echo " - generate-dns-records.sh" echo " - generate-inventory.sh" echo " - migrate-vm.sh" echo " - validate-vmid.sh" echo " - allocate-ip.sh" echo "" echo "Usage:" echo " audit-nomenclature.sh # Audit de conformité" echo " generate-dns-records.sh # Génération DNS" echo " generate-inventory.sh # Génération inventaire" echo " migrate-vm.sh # Migration VM" echo " validate-vmid.sh # Validation VMID" echo " allocate-ip.sh # Allocation IP" echo "" echo "======================================================" echo "Installation terminée!" echo "======================================================" INSTALL chmod +x /usr/local/bin/install-nomenclature-tools.sh ################################################################################ # DOCUMENTATION ################################################################################ cat > /usr/local/share/doc/nomenclature-v2-scripts.md << 'DOC' # Documentation Scripts Nomenclature v2.0 ## L'Alliance Boréale ## Installation ```bash # Exécuter le script d'installation sudo /usr/local/bin/install-nomenclature-tools.sh # Ou installer manuellement sudo cp *.sh /usr/local/bin/ sudo chmod +x /usr/local/bin/*.sh ``` ## Configuration Fichier: `/etc/alliance-boreale/nomenclature.conf` ```bash MEMBER_ID="czp" DNS_DOMAIN="alliance-boreale.ca" IPAM_FILE="/etc/alliance-boreale/ipam.txt" ``` ## Scripts Disponibles ### 1. audit-nomenclature.sh **Description:** Audit complet de conformité des VMs au standard v2.0 **Usage:** ```bash audit-nomenclature.sh ``` **Sortie:** - Rapport console avec couleurs - CSV détaillé: `/tmp/audit-nomenclature-YYYYMMDD-HHMMSS.csv` - Exit code: 0 si conforme, 1 si non-conforme **Exemple:** ```bash $ audit-nomenclature.sh ====================================================== AUDIT DE CONFORMITÉ - NOMENCLATURE v2.0 Membre: czp Date: 2025-10-21 14:30:00 ====================================================== ✅ CONFORME | VMID: 02001 | Nom: czp-infra-dns-master-prod-01 | IP: 10.0.2.10 ❌ NON CONFORME | VMID: 104 | Nom: old-vm-web | IP: 10.50.100.5 → VMID invalide; Nom invalide; IP invalide; ====================================================== RÉSUMÉ ====================================================== Total VMs : 25 Conformes : 20 Non conformes : 5 Taux de conformité: 80.0% ====================================================== ``` ### 2. generate-dns-records.sh **Description:** Génère les enregistrements DNS zone file à partir de Proxmox **Usage:** ```bash generate-dns-records.sh > dns-records.zone ``` **Variables:** ```bash MEMBER="czp" # ID membre DNS_DOMAIN="alliance-boreale.ca" # Domaine DNS_OUTPUT="/tmp/dns-records-${MEMBER}.zone" # Fichier sortie ``` **Exemple:** ```bash $ generate-dns-records.sh ; DNS Records for czp.alliance-boreale.ca ; Generated on Mon Oct 21 14:30:00 2025 ; Standard Nomenclature v2.0 ; ====================================================== ; INFRASTRUCTURE (Couches 1-4) ; ====================================================== dns-master.infra.czp.alliance-boreale.ca. IN A 10.0.2.10 dns-slave1.infra.czp.alliance-boreale.ca. IN A 10.0.2.11 ansible.infra.czp.alliance-boreale.ca. IN A 10.0.1.10 git.infra.czp.alliance-boreale.ca. IN A 10.0.1.20 ; ====================================================== ; TENANTS (Couches 5-8) ; ====================================================== web.t001.czp.alliance-boreale.ca. IN A 10.0.10.1 db.t001.czp.alliance-boreale.ca. IN A 10.0.10.2 ``` ### 3. generate-inventory.sh **Description:** Génère l'inventaire Ansible YAML à partir de Proxmox **Usage:** ```bash generate-inventory.sh ``` **Sortie:** `/tmp/inventory-${MEMBER}.yml` **Exemple:** ```bash $ generate-inventory.sh Inventaire généré: /tmp/inventory-czp.yml $ cat /tmp/inventory-czp.yml --- # Ansible Inventory - czp # Generated on Mon Oct 21 14:30:00 2025 all: vars: member_id: czp domain: alliance-boreale.ca children: infrastructure: children: layer_2: hosts: dns-master.infra.czp.alliance-boreale.ca: ansible_host: 10.0.2.10 vmid: 02001 layer: 2 service: dns-master environment: prod ``` ### 4. migrate-vm.sh **Description:** Migre une VM vers le nouveau standard (VMID, nom, IP) **Usage:** ```bash migrate-vm.sh ``` **Options:** ```bash DRY_RUN=true # Mode simulation (pas de changement réel) ``` **Exemple:** ```bash # Simulation $ DRY_RUN=true migrate-vm.sh 104 10001 czp-t001-web-prod-01 10.0.10.1 # Migration réelle $ migrate-vm.sh 104 10001 czp-t001-web-prod-01 10.0.10.1 ====================================================== MIGRATION VM - NOMENCLATURE v2.0 ====================================================== VMID source : 104 VMID dest : 10001 Nouveau nom : czp-t001-web-prod-01 Nouvelle IP : 10.0.10.1 Mode simulation: false ====================================================== État actuel: Nom: old-vm-web IP : 10.50.100.5 Nouvel état: Nom: czp-t001-web-prod-01 IP : 10.0.10.1 Continuer? (oui/non): oui Étapes de migration: 1. Création backup... ✓ Backup créé 2. Arrêt de la VM... ✓ VM arrêtée 3. Clonage vers nouveau VMID... ✓ VM clonée 4. Configuration nouvelle IP... ✓ IP configurée dans Proxmox ⚠ ATTENTION: Modifier aussi l'IP dans la VM 5. Démarrage nouvelle VM... ✓ VM démarrée ====================================================== MIGRATION TERMINÉE ====================================================== Prochaines étapes MANUELLES: 1. Vérifier que la VM démarre correctement 2. Connecter à la VM et changer l'IP 3. Tester la connectivité réseau 4. Créer l'entrée DNS 5. Mettre à jour l'inventaire Ansible 6. Une fois validé: qm destroy 104 ``` ### 5. validate-vmid.sh **Description:** Valide qu'un VMID respecte le standard v2.0 **Usage:** ```bash validate-vmid.sh ``` **Exemples:** ```bash $ validate-vmid.sh 02001 ✅ VMID VALIDE Type: Infrastructure Couche: 2 Type service: 00 Instance: 01 Description: Couche 2 - Réseau $ validate-vmid.sh 10001 ✅ VMID VALIDE Type: Tenant Tenant ID: 001 Instance: 01 $ validate-vmid.sh 99999 ❌ VMID INVALIDE Format attendu: Infrastructure: 0CTTII (ex: 02001) Tenant: TTTII (ex: 10001) ``` ### 6. allocate-ip.sh **Description:** Alloue la prochaine IP disponible pour un tenant **Usage:** ```bash allocate-ip.sh ``` **Fichier IPAM:** `/etc/alliance-boreale/ipam.txt` **Exemple:** ```bash $ allocate-ip.sh 001 ✅ IP DISPONIBLE: 10.0.10.1 Pour allouer cette IP: echo "001 10.0.10.1 2025-10-21 10001" >> /etc/alliance-boreale/ipam.txt $ allocate-ip.sh 002 Tenant 002 a déjà des IPs allouées: 002 10.0.10.10 2025-10-20 20001 002 10.0.10.11 2025-10-20 20002 ✅ IP DISPONIBLE: 10.0.10.12 ``` ## Workflow de Migration Complet ### Étape 1: Audit Initial ```bash # Générer rapport de conformité audit-nomenclature.sh # Identifier les VMs non conformes grep "NON CONFORME" /tmp/audit-nomenclature-*.csv ``` ### Étape 2: Planification ```bash # Pour chaque VM non conforme, déterminer: # - Nouveau VMID (validate-vmid.sh) # - Nouveau nom # - Nouvelle IP (allocate-ip.sh si tenant) # Exemple de plan: cat > migration-plan.txt << EOF # Plan de Migration - Nomenclature v2.0 VMID_SRC | VMID_DST | Nom Actuel | Nouveau Nom | IP Actuelle | Nouvelle IP ---------|----------|-----------------|--------------------------------|--------------|------------- 104 | 10001 | old-vm-web | czp-t001-web-prod-01 | 10.50.100.5 | 10.0.10.1 105 | 10011 | web-api | czp-t001-api-prod-01 | 10.50.100.6 | 10.0.10.3 200 | 04001 | ansible-server | czp-infra-ansible-ctrl-prod-01| 10.0.1.100 | 10.0.1.10 EOF ``` ### Étape 3: Migration par Lots ```bash # Lot 1: VMs non-critiques (dev/staging) DRY_RUN=true migrate-vm.sh 104 10001 czp-t001-web-prod-01 10.0.10.1 # Valider sortie, puis: migrate-vm.sh 104 10001 czp-t001-web-prod-01 10.0.10.1 # Lot 2: Services d'infrastructure migrate-vm.sh 200 04001 czp-infra-ansible-ctrl-prod-01 10.0.1.10 # Lot 3: Services critiques (planifier fenêtre maintenance) migrate-vm.sh 100 02001 czp-infra-dns-master-prod-01 10.0.2.10 ``` ### Étape 4: Validation Post-Migration ```bash # Vérifier conformité audit-nomenclature.sh # Régénérer DNS generate-dns-records.sh > /var/lib/alliance-boreale/dns-records.zone # Régénérer inventaire generate-inventory.sh # Tester connectivité ansible all -m ping -i /var/lib/alliance-boreale/inventory.yml ``` ### Étape 5: Nettoyage ```bash # Supprimer anciennes VMs (après validation complète) qm destroy 104 qm destroy 105 qm destroy 200 # Archiver anciens backups mv /var/lib/vz/dump/vzdump-qemu-104-*.zst /backup/archive/ ``` ## Automatisation ### Cron Job - Audit Quotidien ```bash # /etc/cron.daily/audit-nomenclature #!/bin/bash /usr/local/bin/audit-nomenclature.sh > /var/log/alliance-boreale/audit-$(date +%Y%m%d).log 2>&1 ``` ### Cron Job - Génération DNS Hebdomadaire ```bash # /etc/cron.weekly/generate-dns #!/bin/bash /usr/local/bin/generate-dns-records.sh > /var/lib/alliance-boreale/dns-records.zone /usr/local/bin/generate-inventory.sh ``` ## Intégration CI/CD ### GitLab CI - Validation Pre-Deployment ```yaml # .gitlab-ci.yml stages: - validate validate_vmid: stage: validate script: - validate-vmid.sh ${NEW_VMID} only: - merge_requests ``` ## Troubleshooting ### Problème: Audit échoue ```bash # Vérifier que qm est accessible qm list # Vérifier permissions ls -la /usr/local/bin/audit-nomenclature.sh # Exécuter en mode debug bash -x /usr/local/bin/audit-nomenclature.sh ``` ### Problème: Migration échoue ```bash # Vérifier espace disque df -h # Vérifier état VM source qm status # Consulter logs Proxmox tail -f /var/log/pve/tasks/active ``` ### Problème: IP déjà allouée ```bash # Consulter IPAM cat /etc/alliance-boreale/ipam.txt # Rechercher IP spécifique grep "10.0.10.1" /etc/alliance-boreale/ipam.txt # Forcer allocation nouvelle plage # Éditer manuellement ipam.txt ``` ## Support **Documentation complète:** https://docs.alliance-boreale.ca/nomenclature-v2 **Dépôt Git:** https://forge.alliance-boreale.ca/tools/nomenclature-scripts **Contact:** technique@alliance-boreale.ca --- **Licence:** AGPL-3.0 **Version:** 1.0 **Dernière mise à jour:** 21 octobre 2025 DOC ################################################################################ # FIN DU FICHIER ################################################################################ echo "" echo "======================================================" echo "SCRIPTS DE MIGRATION ET D'AUDIT - v1.0" echo "L'Alliance Boréale" echo "======================================================" echo "" echo "✅ 6 scripts créés:" echo " 1. audit-nomenclature.sh" echo " 2. generate-dns-records.sh" echo " 3. generate-inventory.sh" echo " 4. migrate-vm.sh" echo " 5. validate-vmid.sh" echo " 6. allocate-ip.sh" echo "" echo "✅ Script d'installation créé:" echo " - install-nomenclature-tools.sh" echo "" echo "✅ Documentation créée:" echo " - /usr/local/share/doc/nomenclature-v2-scripts.md" echo "" echo "Pour installer:" echo " sudo bash install-nomenclature-tools.sh" echo "" echo "======================================================"TION: # Collection de scripts pour auditer et migrer les VMs vers le standard v2.0 # # SCRIPTS INCLUS: # 1. audit-nomenclature.sh - Audit de conformité # 2. generate-dns-records.sh - Génération enregistrements DNS # 3. generate-inventory.sh - Génération inventaire Ansible # 4. migrate-vm.sh - Migration d'une VM # 5. validate-vmid.sh - Validation format VMID # 6. allocate-ip.sh - Allocation IP tenant ################################################################################ ################################################################################ # SCRIPT 1: audit-nomenclature.sh # Vérifie la conformité des VMs au standard v2.0 ################################################################################ cat > /usr/local/bin/audit-nomenclature.sh << 'AUDIT_SCRIPT' #!/bin/bash # audit-nomenclature.sh - Audit de conformité nomenclature v2.0 set -euo pipefail # Configuration MEMBER_ID="${MEMBER_ID:-czp}" REPORT_FILE="/tmp/audit-nomenclature-$(date +%Y%m%d-%H%M%S).txt" REPORT_CSV="/tmp/audit-nomenclature-$(date +%Y%m%d-%H%M%S).csv" # Couleurs RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Compteurs TOTAL=0 CONFORME=0 NON_CONFORME=0 echo "======================================================" echo "AUDIT DE CONFORMITÉ - NOMENCLATURE v2.0" echo "Membre: ${MEMBER_ID}" echo "Date: $(date)" echo "======================================================" echo "" # En-tête CSV echo "VMID,Nom,IP,Conforme_VMID,Conforme_Nom,Conforme_IP,Statut_Global,Commentaires" > "$REPORT_CSV" # Fonction de validation VMID validate_vmid() { local vmid=$1 # Infrastructure: 0[1-4][0-9]{3} if [[ $vmid =~ ^0[1-4][0-9]{3}$ ]]; then echo "infra" return 0 fi # Tenant: [1-9][0-9]{4} if [[ $vmid =~ ^[1-9][0-9]{4}$ ]]; then echo "tenant" return 0 fi echo "invalid" return 1 } # Fonction de validation nom validate_name() { local name=$1 local vmid_type=$2 if [ "$vmid_type" = "infra" ]; then # Format: -infra--- if [[ $name =~ ^[a-z]+-infra-[a-z0-9-]+-[a-z]+-[0-9]{2}$ ]]; then return 0 fi elif [ "$vmid_type" = "tenant" ]; then # Format: -t[0-9]{3}--- if [[ $name =~ ^[a-z]+-t[0-9]{3}-[a-z0-9-]+-[a-z]+-[0-9]{2}$ ]]; then return 0 fi fi return 1 } # Fonction de validation IP validate_ip() { local ip=$1 local vmid_type=$2 if [ "$vmid_type" = "infra" ]; then # Infrastructure: 10.0.0.0 - 10.0.23.255 if [[ $ip =~ ^10\.0\.(0|1|2|20|21|22|23)\. ]]; then return 0 fi elif [ "$vmid_type" = "tenant" ]; then # Tenant: 10.0.10.0/23 ou 10.0.128.0/17 if [[ $ip =~ ^10\.0\.(10|11)\. ]] || [[ $ip =~ ^10\.0\.(12[8-9]|1[3-9][0-9]|2[0-4][0-9]|25[0-5])\. ]]; then return 0 fi fi return 1 } # Boucle sur toutes les VMs for vmid in $(qm list | awk 'NR>1 {print $1}'); do TOTAL=$((TOTAL + 1)) # Récupérer les informations name=$(qm config "$vmid" 2>/dev/null | grep "^name:" | awk '{print $2}' || echo "NO_NAME") ip=$(qm config "$vmid" 2>/dev/null | grep "ipconfig0" | sed 's/.*ip=\([^,/]*\).*/\1/' || echo "NO_IP") # Validation vmid_type=$(validate_vmid "$vmid" || echo "invalid") conforme_vmid="NON" conforme_nom="NON" conforme_ip="NON" statut="❌ NON CONFORME" commentaires="" if [ "$vmid_type" != "invalid" ]; then conforme_vmid="OUI" else commentaires="${commentaires}VMID invalide; " fi if validate_name "$name" "$vmid_type"; then conforme_nom="OUI" else commentaires="${commentaires}Nom invalide; " fi if validate_ip "$ip" "$vmid_type"; then conforme_ip="OUI" else commentaires="${commentaires}IP invalide; " fi # Statut global if [ "$conforme_vmid" = "OUI" ] && [ "$conforme_nom" = "OUI" ] && [ "$conforme_ip" = "OUI" ]; then statut="✅ CONFORME" CONFORME=$((CONFORME + 1)) else NON_CONFORME=$((NON_CONFORME + 1)) fi # Affichage if [ "$statut" = "✅ CONFORME" ]; then echo -e "${GREEN}${statut}${NC} | VMID: $vmid | Nom: $name | IP: $ip" else echo -e "${RED}${statut}${NC} | VMID: $vmid | Nom: $name | IP: $ip" echo -e " ${YELLOW}→ ${commentaires}${NC}" fi # Export CSV echo "$vmid,$name,$ip,$conforme_vmid,$conforme_nom,$conforme_ip,$statut,$commentaires" >> "$REPORT_CSV" done echo "" echo "======================================================" echo "RÉSUMÉ" echo "======================================================" echo "Total VMs : $TOTAL" echo -e "${GREEN}Conformes : $CONFORME${NC}" echo -e "${RED}Non conformes : $NON_CONFORME${NC}" echo "" echo "Taux de conformité: $(awk "BEGIN {printf \"%.1f\", ($CONFORME/$TOTAL)*100}")%" echo "" echo "Rapport détaillé: $REPORT_CSV" echo "======================================================" # Exit code basé sur conformité if [ "$NON_CONFORME" -gt 0 ]; then exit 1 else exit 0 fi AUDIT_SCRIPT chmod +x /usr/local/bin/audit-nomenclature.sh ################################################################################ # SCRIPT 2: generate-dns-records.sh # Génère les enregistrements DNS à partir de l'inventaire Proxmox ################################################################################ cat > /usr/local/bin/generate-dns-records.sh << 'DNS_SCRIPT' #!/bin/bash # generate-dns-records.sh - Génération enregistrements DNS set -euo pipefail # Configuration MEMBER="${MEMBER_ID:-czp}" DOMAIN="${DNS_DOMAIN:-alliance-boreale.ca}" OUTPUT_FILE="${DNS_OUTPUT:-/tmp/dns-records-${MEMBER}.zone}" echo "; DNS Records for ${MEMBER}.${DOMAIN}" echo "; Generated on $(date)" echo "; Standard Nomenclature v2.0" echo "" # Infrastructure (Couches 1-4) echo "; ======================================================" echo "; INFRASTRUCTURE (Couches 1-4)" echo "; ======================================================" for vmid in $(qm list | grep -E "0[1-4][0-9]{3}" | awk '{print $1}'); do name=$(qm config "$vmid" 2>/dev/null | grep "^name:" | awk '{print $2}' || continue) ip=$(qm config "$vmid" 2>/dev/null | grep "ipconfig0" | sed 's/.*ip=\([^,/]*\).*/\1/' || continue) # Extraire le service du nom # Format: -infra--- if [[ $name =~ ^[a-z]+-infra-([a-z0-9-]+)-([a-z]+)-([0-9]{2})$ ]]; then service="${BASH_REMATCH[1]}" env="${BASH_REMATCH[2]}" instance="${BASH_REMATCH[3]}" # Nom DNS complet if [ "$env" = "prod" ]; then dns_name="${service}.infra.${MEMBER}.${DOMAIN}." else dns_name="${service}-${env}.infra.${MEMBER}.${DOMAIN}." fi echo "$dns_name IN A $ip" fi done echo "" # Tenants (Couches 5-8) echo "; ======================================================" echo "; TENANTS (Couches 5-8)" echo "; ======================================================" for vmid in $(qm list | grep -E "^[1-9][0-9]{4}$" | awk '{print $1}'); do name=$(qm config "$vmid" 2>/dev/null | grep "^name:" | awk '{print $2}' || continue) ip=$(qm config "$vmid" 2>/dev/null | grep "ipconfig0" | sed 's/.*ip=\([^,/]*\).*/\1/' || continue) # Extraire tenant et service du nom # Format: -t--- if [[ $name =~ ^[a-z]+-(t[0-9]{3})-([a-z0-9-]+)-([a-z]+)-([0-9]{2})$ ]]; then tenant="${BASH_REMATCH[1]}" service="${BASH_REMATCH[2]}" env="${BASH_REMATCH[3]}" instance="${BASH_REMATCH[4]}" # Nom DNS complet if [ "$env" = "prod" ]; then dns_name="${service}.${tenant}.${MEMBER}.${DOMAIN}." else dns_name="${service}-${env}.${tenant}.${MEMBER}.${DOMAIN}." fi echo "$dns_name IN A $ip" fi done echo "" echo "; ======================================================" echo "; END OF DNS RECORDS" echo "; ======================================================" DNS_SCRIPT chmod +x /usr/local/bin/generate-dns-records.sh ################################################################################ # SCRIPT 3: generate-inventory.sh # Génère l'inventaire Ansible à partir de Proxmox ################################################################################ cat > /usr/local/bin/generate-inventory.sh << 'INVENTORY_SCRIPT' #!/bin/bash # generate-inventory.sh - Génération inventaire Ansible YAML set -euo pipefail # Configuration MEMBER="${MEMBER_ID:-czp}" DOMAIN="${DNS_DOMAIN:-alliance-boreale.ca}" OUTPUT_FILE="${INVENTORY_OUTPUT:-/tmp/inventory-${MEMBER}.yml}" cat > "$OUTPUT_FILE" << YAML_HEADER --- # Ansible Inventory - ${MEMBER} # Generated on $(date) # Standard Nomenclature v2.0 all: vars: member_id: ${MEMBER} domain: ${DOMAIN} children: infrastructure: vars: category: infrastructure children: YAML_HEADER # Générer les groupes par couche for layer in 1 2 3 4; do echo " layer_${layer}:" >> "$OUTPUT_FILE" echo " hosts:" >> "$OUTPUT_FILE" has_hosts=false for vmid in $(qm list | grep -E "^0${layer}[0-9]{3}$" | awk '{print $1}'); do name=$(qm config "$vmid" 2>/dev/null | grep "^name:" | awk '{print $2}' || continue) ip=$(qm config "$vmid" 2>/dev/null | grep "ipconfig0" | sed 's/.*ip=\([^,/]*\).*/\1/' || continue) if [[ $name =~ ^[a-z]+-infra-([a-z0-9-]+)-([a-z]+)-([0-9]{2})$ ]]; then service="${BASH_REMATCH[1]}" env="${BASH_REMATCH[2]}" dns_name="${service}.infra.${MEMBER}.${DOMAIN}" cat >> "$OUTPUT_FILE" << YAML_HOST ${dns_name}: ansible_host: ${ip} vmid: ${vmid} layer: ${layer} service: ${service} environment: ${env} YAML_HOST has_hosts=true fi done if [ "$has_hosts" = false ]; then echo " {}" >> "$OUTPUT_FILE" fi echo "" >> "$OUTPUT_FILE" done # Générer les groupes tenants echo " tenants:" >> "$OUTPUT_FILE" echo " vars:" >> "$OUTPUT_FILE" echo " category: tenant" >> "$OUTPUT_FILE" echo " children:" >> "$OUTPUT_FILE" # Trouver tous les tenants uniques tenant_ids=$(qm list | grep -E "^[1-9][0-9]{4}$" | awk '{print $1}' | while read vmid; do name=$(qm config "$vmid" 2>/dev/null | grep "^name:" | awk '{print $2}' || continue) if [[ $name =~ -(t[0-9]{3})- ]]; then echo "${BASH_REMATCH[1]}" fi done | sort -u) for tenant_id in $tenant_ids; do echo " tenant_${tenant_id}:" >> "$OUTPUT_FILE" echo " vars:" >> "$OUTPUT_FILE" echo " tenant_id: ${tenant_id}" >> "$OUTPUT_FILE" echo " hosts:" >> "$OUTPUT_FILE" has_hosts=false for vmid in $(qm list | grep -E "^[1-9][0-9]{4}$" | awk '{print $1}'); do name=$(qm config "$vmid" 2>/dev/null | grep "^name:" | awk '{print $2}' || continue) if [[ $name =~ -(${tenant_id})-([a-z0-9-]+)-([a-z]+)-([0-9]{2})$ ]]; then ip=$(qm config "$vmid" 2>/dev/null | grep "ipconfig0" | sed 's/.*ip=\([^,/]*\).*/\1/' || continue) service="${BASH_REMATCH[2]}" env="${BASH_REMATCH[3]}" dns_name="${service}.${tenant_id}.${MEMBER}.${DOMAIN}" cat >> "$OUTPUT_FILE" << YAML_HOST ${dns_name}: ansible_host: ${ip} vmid: ${vmid} tenant: ${tenant_id} service: ${service} environment: ${env} YAML_HOST has_hosts=true fi done if [ "$has_hosts" = false ]; then echo " {}" >> "$OUTPUT_FILE" fi echo "" >> "$OUTPUT_FILE" done echo "Inventaire généré: $OUTPUT_FILE" INVENTORY_SCRIPT chmod +x /usr/local/bin/generate-inventory.sh ################################################################################ # SCRIPT 4: migrate-vm.sh # Migre une VM vers le nouveau standard ################################################################################ cat > /usr/local/bin/migrate-vm.sh << 'MIGRATE_SCRIPT' #!/bin/bash # migrate-vm.sh - Migration d'une VM vers nomenclature v2.0 set -euo pipefail # Configuration MEMBER_ID="${MEMBER_ID:-czp}" DRY_RUN="${DRY_RUN:-false}" # Couleurs GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' NC='\033[0m' usage() { echo "Usage: $0 " echo "" echo "Exemple:" echo " $0 104 10001 czp-t001-web-prod-01 10.0.10.1" echo "" echo "Options:" echo " DRY_RUN=true - Mode simulation (pas de changement)" exit 1 } # Vérification arguments if [ $# -ne 4 ]; then usage fi VMID_SRC="$1" VMID_DST="$2" NEW_NAME="$3" NEW_IP="$4" echo "======================================================" echo "MIGRATION VM - NOMENCLATURE v2.0" echo "======================================================" echo "VMID source : $VMID_SRC" echo "VMID dest : $VMID_DST" echo "Nouveau nom : $NEW_NAME" echo "Nouvelle IP : $NEW_IP" echo "Mode simulation: $DRY_RUN" echo "======================================================" echo "" # Vérifier que la VM source existe if ! qm status "$VMID_SRC" &>/dev/null; then echo -e "${RED}ERREUR: VM $VMID_SRC n'existe pas${NC}" exit 1 fi # Vérifier que la VM dest n'existe pas if qm status "$VMID_DST" &>/dev/null; then echo -e "${RED}ERREUR: VM $VMID_DST existe déjà${NC}" exit 1 fi # Récupérer info actuelle OLD_NAME=$(qm config "$VMID_SRC" | grep "^name:" | awk '{print $2}') OLD_IP=$(qm config "$VMID_SRC" | grep "ipconfig0" | sed 's/.*ip=\([^,/]*\).*/\1/') echo -e "${YELLOW}État actuel:${NC}" echo " Nom: $OLD_NAME" echo " IP : $OLD_IP" echo "" echo -e "${GREEN}Nouvel état:${NC}" echo " Nom: $NEW_NAME" echo " IP : $NEW_IP" echo "" # Demander confirmation if [ "$DRY_RUN" != "true" ]; then read -p "Continuer? (oui/non): " confirm if [ "$confirm" != "oui" ]; then echo "Migration annulée" exit 0 fi fi echo "" echo "Étapes de migration:" echo "" # Étape 1: Backup echo "1. Création backup..." if [ "$DRY_RUN" != "true" ]; then vzdump "$VMID_SRC" --mode snapshot --compress zstd --storage local echo -e "${GREEN} ✓ Backup créé${NC}" else echo -e "${YELLOW} [SIMULATION] Backup créé${NC}" fi # Étape 2: Arrêter la VM echo "2. Arrêt de la VM..." if [ "$DRY_RUN" != "true" ]; then qm shutdown "$VMID_SRC" || qm stop "$VMID_SRC" sleep 5 echo -e "${GREEN} ✓ VM arrêtée${NC}" else echo -e "${YELLOW} [SIMULATION] VM arrêtée${NC}" fi # Étape 3: Cloner avec nouveau VMID echo "3. Clonage vers nouveau VMID..." if [ "$DRY_RUN" != "true" ]; then qm clone "$VMID_SRC" "$VMID_DST" --name "$NEW_NAME" --full echo -e "${GREEN} ✓ VM clonée${NC}" else echo -e "${YELLOW} [SIMULATION] VM clonée${NC}" fi # Étape 4: Changer l'IP echo "4. Configuration nouvelle IP..." if [ "$DRY_RUN" != "true" ]; then # Modifier la config réseau Proxmox qm set "$VMID_DST" --ipconfig0 "ip=${NEW_IP}/24,gw=10.0.0.1" echo -e "${GREEN} ✓ IP configurée dans Proxmox${NC}" echo -e "${YELLOW} ⚠ ATTENTION: Modifier aussi l'IP dans la VM (après démarrage)${NC}" else echo -e "${YELLOW} [SIMULATION] IP configurée${NC}" fi # Étape 5: Démarrer la nouvelle VM echo "5. Démarrage nouvelle VM..." if [ "$DRY_RUN" != "true" ]; then qm start "$VMID_DST" echo -e "${GREEN} ✓ VM démarrée${NC}" else echo -e "${YELLOW} [SIMULATION] VM démarrée${NC}" fi echo "" echo "======================================================" echo "MIGRATION TERMINÉE" echo "======================================================" echo "" echo "Prochaines étapes MANUELLES:" echo "1. Vérifier que la VM démarre correctement" echo "2. Connecter à la VM et changer l'IP dans /etc/network/interfaces" echo "3. Tester la connectivité réseau" echo "4. Créer l'entrée DNS: ${NEW_NAME%.prod-*}.infra.${MEMBER_ID}.alliance-boreale.ca" echo "5. Mettre à jour l'inventaire Ansible" echo "6. Mettre à jour le monitoring" echo "7. Une fois validé, supprimer l'ancienne VM: qm destroy $VMID_SRC" echo "" MIGRATE_SCRIPT chmod +x /usr/local/bin/migrate-vm.sh ################################################################################ # SCRIPT 5: validate-vmid.sh # Valide le format d'un VMID ################################################################################ cat > /usr/local/bin/validate-vmid.sh << 'VALIDATE_SCRIPT' #!/bin/bash # validate-vmid.sh - Validation format VMID set -euo pipefail usage() { echo "Usage: $0 " echo "" echo "Valide qu'un VMID respecte le standard v2.0" echo "" echo "Exemples:" echo " $0 02001 # Infrastructure Couche 2" echo " $0 10001 # Tenant 001" exit 1 } if [ $# -ne 1 ]; then usage fi VMID="$1" # Infrastructure: 0[1-4][0-9]{3} if [[ $VMID =~ ^0[1-4][0-9]{3}$ ]]; then layer="${VMID:1:1}" type="${VMID:2:2}" instance="${VMID:4:2}" echo "✅ VMID VALIDE" echo "Type: Infrastructure" echo "Couche: $layer" echo "Type service: $type" echo "Instance: $instance" case $layer in 1) echo "Description: Couche 1 - Physique" ;; 2) echo "Description: Couche 2 - Réseau" ;; 3) echo "Description: Couche 3 - Stockage" ;; 4) echo "Description: Couche 4 - Orchestration" ;; esac exit 0 fi # Tenant: [1-9][0-9]{4} if [[ $VMID =~ ^[1-9][0-9]{4}$ ]]; then tenant="${VMID:0:3}" instance="${VMID:3:2}" echo "✅ VMID VALIDE" echo "Type: Tenant" echo "Tenant ID: $tenant" echo "Instance: $instance" exit 0 fi # Invalide echo "❌ VMID INVALIDE" echo "" echo "Format attendu:" echo " Infrastructure: 0CTTII (ex: 02001)" echo " 0 = Infrastructure" echo " C = Couche (1-4)" echo " TT = Type (00-99)" echo " II = Instance (01-99)" echo "" echo " Tenant: TTTII (ex: 10001)" echo " TTT = Tenant ID (001-999)" echo " II = Instance (01-99)" exit 1 VALIDATE_SCRIPT chmod +x /usr/local/bin/validate-vmid.sh ################################################################################ # SCRIPT 6: allocate-ip.sh # Alloue une IP pour un nouveau tenant ################################################################################ cat > /usr/local/bin/allocate-ip.sh << 'ALLOCATE_SCRIPT' #!/bin/bash # allocate-ip.sh - Allocation IP tenant set -euo pipefail # Configuration IPAM_FILE="${IPAM_FILE:-/etc/alliance-boreale/ipam.txt}" usage() { echo "Usage: $0 " echo "" echo "Alloue la prochaine IP disponible pour un tenant" echo "" echo "Exemple:" echo " $0 001 # Alloue IP pour tenant 001" exit 1 } if [ $# -ne 1 ]; then usage fi TENANT_ID="$1" # Vérifier format tenant ID if ! [[ $TENANT_ID =~ ^[0-9]{3}$ ]]; then echo "ERREUR: Tenant ID doit être au format NNN (ex: 001)" exit 1 fi # Créer fichier IPAM si inexistant if [ ! -f "$IPAM_FILE" ]; then mkdir -p "$(dirname "$IPAM_FILE")" echo "# IPAM - Tenant IP Allocation" > "$IPAM_FILE" echo "# Format: TENANT_ID IP DATE VMID" >> "$IPAM_FILE" fi # Vérifier si tenant a déjà des IPs existing_ips=$(grep "^$TENANT_ID " "$IPAM_FILE" 2>/dev/null || true) if [ -n "$existing_ips" ]; then echo "Tenant $TENANT_ID a déjà des IPs allouées:" echo "$existing_ips" echo "" fi # Trouver prochaine IP disponible dans 10.0.10.0/23 # Stratégie: 10.0.10.0-99 pour tenant 001, 10.0.10.100-199 pour tenant 002, etc. base_ip_part=$((10 + (${TENANT_ID#0} * 100) / 1000)) base_host=$((((${TENANT_ID#0} % 10) * 100))) # Trouver prochaine IP libre for i in {1..99}; do test_ip="10.0.${base_ip_part}.$((base_host + i))" # Vérifier si IP déjà allouée if ! grep -q " ${test_ip} " "$IPAM_FILE" 2>/dev/null; then echo "✅ IP DISPONIBLE: $test_ip" echo "" echo "Pour allouer cette IP:" echo " echo \"$TENANT_ID $test_ip $(date +%Y-%m-%d) VMID\" >> $IPAM_FILE" exit 0 fi done echo "❌ ERREUR: Aucune IP disponible pour le tenant $TENANT_ID" echo "Considérer utiliser la plage d'expansion 10.0.128.0/17" exit 1 ALLOCATE_SCRIPT chmod +x /usr/local/bin/allocate-ip.sh ################################################################################ # Installation et Configuration ################################################################################ echo "#!/bin/bash" > /usr/local/bin/install-nomenclature-tools.sh cat >> /usr/local/bin/install-nomenclature-tools.sh << 'INSTALL' # install-nomenclature-tools.sh - Installation des outils nomenclature v2.0 set -euo pipefail echo "======================================================" echo "INSTALLATION OUTILS NOMENCLATURE v2.0" echo "L'Alliance Boréale" echo "======================================================" echo "" # Vérifier droits root if [ "$EUID" -ne 0 ]; then echo "ERREUR: Ce script doit être exécuté en root" exit 1 fi # Configuration read -p "ID du membre (ex: czp): " MEMBER_ID read -p "Domaine DNS (ex: alliance-boreale.ca): " DNS_DOMAIN # Créer fichier de configuration mkdir -p /etc/alliance-boreale cat > /etc/alliance-boreale/nomenclature.conf << CONFIG # Configuration Nomenclature v2.0 MEMBER_ID="${MEMBER_ID}" DNS_DOMAIN="${DNS_DOMAIN}" IP