Chez XEFI Advanced, les techniciens devaient se connecter manuellement en RDS sur chaque serveur client pour vérifier l'état des jobs Veeam — une dizaine de connexions par jour, zéro visibilité centralisée, risque d'oubli réel sur des sauvegardes critiques. Mission : concevoir de A à Z un système d'agrégation automatique des statuts, visible depuis une interface web unique sans aucune ouverture de session RDS, avec alerting automatique en cas d'échec.
XEFI Advanced est une entité spécialisée dans la supervision et la gestion d'infrastructures client. Chaque client dispose d'un ou plusieurs serveurs de sauvegarde Veeam Backup & Replication. Pour connaître l'état d'un job — réussi, en warning, ou en échec — un technicien devait ouvrir une session Bureau à distance sur le serveur concerné, naviguer dans la console Veeam, lire les logs, et fermer la session. Multiplié par une dizaine de serveurs chaque matin, cette procédure représentait une perte de temps significative et un risque opérationnel réel : un job en échec pouvait passer inaperçu si la vérification manuelle était oubliée.
L'objectif était de développer une solution sans agent propriétaire, sans modification de l'infrastructure cliente, et deployable rapidement sur n'importe quel serveur. Contrainte supplémentaire non négociable : tout devait fonctionner en PowerShell 5, la version installée en production chez les clients, sans possibilité d'upgrade vers PS7.
Le projet a évolué en quatre phases successives, chaque phase répondant à une limite découverte dans la précédente. Ce n'est pas une progression linéaire prévue dès le départ — c'est le résultat d'une exploration technique itérative face à des contraintes réelles découvertes en chemin.
Le premier objectif était de valider qu'il était possible d'extraire automatiquement les données de Veeam sans passer par la console graphique. Veeam stocke ses métadonnées de jobs dans des fichiers .vbm au format XML. Un script PowerShell parse ces fichiers, extrait les statuts, dates, volumétries et noms de jobs, et compile le tout dans un status.json. Ce JSON est ensuite envoyé à un serveur Flask local (Python) qui l'insère dans une base SQLite et génère un dashboard HTML affichant la météo des sauvegardes en temps réel.
Résultat : le parsing fonctionne et le dashboard affiche correctement les données. Limite identifiée : tout tourne sur le même serveur. Pour centraliser plusieurs clients, il faut rendre l'agent accessible depuis l'extérieur.
Pour rendre le système distribué, le script PowerShell est transformé en un véritable agent HTTP grâce à la classe HttpListener native de .NET. L'agent s'exécute en tâche de fond sur le serveur Veeam, écoute sur le port 9444 et expose un endpoint GET /status qui retourne le JSON des sauvegardes à la demande. La communication est sécurisée en TLS 1.2 avec un certificat auto-signé exporté et importé dans le store Windows de confiance du collecteur.
Côté collecteur (PC portable), un script Python Flask scrape périodiquement tous les agents, stocke les résultats en SQLite et présente un dashboard centralisé multi-serveurs. L'alerting est géré par mail_parser.py qui détecte les statuts Failed ou Warning et envoie une notification SMTP au technicien responsable.
Mini-projet MailHog : pour tester l'alerting sans risquer d'envoyer de faux mails aux techniciens en production, un environnement isolé a été monté avec MailHog_windows_amd64.exe — un faux serveur SMTP qui capture les mails localement et les affiche dans une interface web. Ce mini-lab permettait de simuler des pannes et valider le comportement du système d'alerte complètement indépendamment du reste de l'infrastructure.
La direction souhaitait intégrer non seulement les sauvegardes locales, mais aussi les copies hors-site gérées via Veeam Cloud Connect. L'idée : le SRV Cloud Connect XEFI héberge des copies de sauvegarde pour les clients — si on pouvait y accéder, on aurait une vision complète locale et distante depuis une seule interface.
Un lab complet a été monté pour tester : pfSense virtuel, 3 vSwitches Hyper-V simulant trois réseaux séparés, un SRV VEEAM client et un SRV Cloud Connect. La découverte a été bloquante : le Cloud Connect XEFI n'expose pas les métadonnées des jobs clients. Contrairement à un serveur Veeam standard, le Cloud Connect ne donne accès qu'aux données de réplication brutes, sans les fichiers .vbm associés aux jobs clients. Cette information n'est documentée nulle part officiellement. La piste a dû être abandonnée.
La solution au blocage Cloud Connect : plutôt que d'interroger le Cloud Connect lui-même, l'agent est déployé directement sur les trois serveurs de stockage qui hébergent physiquement les copies hors-site. Chaque serveur expose son propre status.json via l'agent HTTPS. Le SRV Cloud Connect, reconverti en orchestrateur, interroge les trois agents en parallèle via collect_backup_copy_status.py, compile les trois stockage01/02/03.json en un unique merged-status.json et l'expose via son propre endpoint GET /recap.
Le PC portable collecteur appelle uniquement ce point d'entrée unique — il n'a plus à connaître les serveurs de stockage individuellement. Le script run_centralization.py orchestre tout le processus en arrière-plan de façon autonome. Le dashboard final affiche la météo de l'ensemble du parc, local et hors-site, depuis une seule interface web sans aucune connexion RDS.
Le projet final est découpé en deux emplacements distincts : les fichiers déployés sur les serveurs (agents), et les fichiers qui tournent sur le PC collecteur central.
Script principal de l'agent. Parse les fichiers .vbm de Veeam, extrait statuts, dates et volumétries, et expose le JSON via HttpListener sur le port 9444 en TLS 1.2.
Script d'installation automatisée. Crée une tâche planifiée Windows pour que l'agent démarre au boot du serveur sans aucune intervention manuelle.
Carnet d'adresses des agents à surveiller. Contient les IP, ports et noms des serveurs Veeam à scraper. Modifiable sans toucher au code.
Certificats TLS 1.2 auto-signés (stockage01/02/03.cer) exportés depuis chaque serveur. Importés dans le store Windows du collecteur pour établir la confiance sans CA tierce.
JSON générés par chaque agent. Contiennent l'état de toutes les sauvegardes : nom du job, statut, date d'exécution, taille transférée.
Fichier de fusion compilé par le SRV Cloud Connect. Agrège les trois fichiers de stockage en un seul point d'entrée pour le collecteur central.
Chef d'orchestre Flask. Démarre le serveur web, expose les routes du dashboard, lit la base SQLite et formate les données pour l'affichage. Point d'entrée principal.
Script de collecte multi-agents. Interroge chaque agent en parallèle (threading), récupère les JSON et détecte les changements de statut depuis le dernier scrape.
Module d'alerting. Analyse les statuts reçus et envoie un mail SMTP en cas de job Failed ou Warning détecté pour la première fois depuis le dernier état connu.
Module de corrélation. Associe les jobs locaux avec leurs copies hors-site pour détecter les incohérences : sauvegarde OK mais copie distante en échec.
Scripts d'automatisation globale. Lancent la collecte, la fusion des JSON, la mise à jour de la base et le refresh du dashboard en une seule commande.
Base SQLite contenant l'historique des 30 derniers jours par serveur. Permet d'afficher des tendances et de détecter des patterns d'échecs récurrents sur la durée.
Scripts d'initialisation de la base. Créent les tables, indexes et données de référence lors du premier déploiement sur un nouveau collecteur.
index.html, history.html, veeam-dashboard-multi.html — pages du dashboard en dark mode. Vue globale, vue par serveur, historique 30 jours avec codes couleur par statut.
Utilitaire de diagnostic. Vérifie que les données s'insèrent correctement en base sans ouvrir le navigateur — pratique lors du débogage en ligne de commande.
?? incompatible PowerShell 5Le null-coalescing $a ?? $b n'existe qu'en PS7+. PS5 parse l'expression sans erreur mais retourne une valeur nulle, ce qui corrompait les JSON pendant des heures avant identification. Fix : réécriture de tous les opérateurs en if($a){$a}else{$b}.
Le certificat auto-signé est rejeté par défaut. Double fix : verify=False provisoire pour déboguer, puis import du .cer dans le Trusted Root CA du store Windows et passage à verify='cert.cer' en production.
Les appels à l'API Veeam depuis un runspace bloquaient indéfiniment. Fix : isolation dans des jobs PowerShell séparés avec Wait-Job -Timeout 30 et nettoyage forcé des jobs orphelins.
Centreon utilisait déjà le 8443 sur les serveurs XEFI. L'agent échouait silencieusement au démarrage. Fix : scan préalable des ports intégré au script d'installation, migration sur le port 9444.
.vbm pendant un job actifVeeam écrit dans ses fichiers pendant l'exécution d'un job, provoquant une lecture XML partielle corrompue. Fix : détection des fichiers verrouillés via try/catch sur l'ouverture, retry avec délai de 2 secondes et log de l'échec.
Sans purge, la base doublait de taille chaque semaine. Fix : routine de nettoyage automatique dans init_db_step2.py qui supprime les entrées de plus de 30 jours à chaque démarrage du collecteur.
Développer sans filet dans un environnement de production réel — chaque test sur les serveurs clients avait un impact potentiel. Ça force à tester localement d'abord, à écrire des logs explicites partout, et à prévoir des rollback avant d'intervenir sur une machine en production.
PowerShell comme langage de production sérieux — gérer des threads, exposer un serveur HTTP, signer des certificats TLS, tout en restant compatible PS5 : c'est un niveau de contrainte qui force à comprendre le runtime .NET sous-jacent, pas juste la syntaxe du langage.
L'architecture itérative face aux contraintes réelles — le Cloud Connect était une impasse documentée nulle part. Savoir pivoter, reconstruire un lab de test et trouver un contournement (les SRV de stockage) sans perdre le fil du projet, c'est la compétence principale que ce stage a développée.
La séparation des responsabilités — diviser en modules indépendants (mail_parser, correlator, collect_backup_copy_status) plutôt qu'un script monolithique a rendu le débogage infiniment plus rapide et chaque composant testable isolément.