# Session de développement - 2026-01-10 ## Détection Proxmox et optimisations UI **Durée :** Session complète **Objectif principal :** Détecter si le système est Proxmox (hôte ou guest) **Statut :** ✅ Terminé et documenté --- ## 🎯 Contexte de départ L'utilisateur voyait "debian" dans son système qui est en réalité une **VM Proxmox**. Il n'y avait aucun moyen de distinguer : - Un serveur Proxmox VE (hyperviseur) - Une VM hébergée sur Proxmox - Un conteneur LXC Proxmox - Un système Debian standard **Question initiale :** "comment detecter s'il s'agit d'un systeme proxmox ? je voit debian" --- ## 📋 Travaux réalisés ### 1️⃣ Détection Proxmox VE (FEATURE MAJEURE) #### A. Script bench.sh v1.5.0 **Fichier :** `scripts/bench.sh` **Version :** 1.4.0 → 1.5.0 **Changements :** - Nouvelle fonction `detect_proxmox()` (lignes 268-322) - Intégration dans `collect_system_info()` (ligne 343) - Ajout objet `virtualization` dans JSON système (ligne 407) - Affichage console avec icônes (lignes 414-426) **Fonction detect_proxmox() :** ```bash # Retourne un objet JSON : { "is_proxmox_host": true/false, "is_proxmox_guest": true/false, "proxmox_version": "8.1.3", "virtualization_type": "kvm" } ``` **Méthodes de détection :** | Type | Méthode | Indicateur | |------|---------|-----------| | **Hôte Proxmox** | `command -v pveversion` | Commande disponible | | | `pveversion \| grep pve-manager` | Version extraite | | | `[[ -d /etc/pve ]]` | Dossier config existe | | **Guest Proxmox** | `systemd-detect-virt` | kvm, qemu, lxc | | | `command -v qemu-ga` | Agent QEMU présent | | | `systemctl is-active qemu-guest-agent` | Service actif | | | `dmidecode -t system` | Contient "QEMU" ou "Proxmox" | **Affichage console :** ``` Hostname: debian-vm OS: debian 13 (trixie) Kernel: 6.12.57+deb13-amd64 💠 VM/Conteneur Proxmox détecté (type: kvm) ``` Ou pour un hôte : ``` Hostname: pve-host OS: debian 12 (bookworm) Kernel: 6.8.12-1-pve 🔷 Proxmox VE Host détecté (version: 8.1.3) ``` #### B. Base de données **Migration 017 :** `backend/migrations/017_add_proxmox_fields.sql` ```sql ALTER TABLE hardware_snapshots ADD COLUMN is_proxmox_host BOOLEAN DEFAULT FALSE; ALTER TABLE hardware_snapshots ADD COLUMN is_proxmox_guest BOOLEAN DEFAULT FALSE; ALTER TABLE hardware_snapshots ADD COLUMN proxmox_version TEXT; ``` **Script d'application :** `backend/apply_migration_017.py` **Exécution :** ```bash cd /home/gilles/projects/serv_benchmark/backend python3 apply_migration_017.py ``` **Résultat :** ``` 🔧 Application de la migration 017... ✅ Migration 017 appliquée avec succès ✅ Colonne is_proxmox_host ajoutée ✅ Colonne is_proxmox_guest ajoutée ✅ Colonne proxmox_version ajoutée ``` #### C. Backend Python **1. Modèle SQLAlchemy** **Fichier :** `backend/app/models/hardware_snapshot.py` **Lignes :** 70-72 ```python is_proxmox_host = Column(Boolean, nullable=True) is_proxmox_guest = Column(Boolean, nullable=True) proxmox_version = Column(String(100), nullable=True) ``` **2. Schéma Pydantic** **Fichier :** `backend/app/schemas/hardware.py` **Lignes :** 123-128 (nouvelle classe) ```python class VirtualizationInfo(BaseModel): """Virtualization information schema""" is_proxmox_host: bool = False is_proxmox_guest: bool = False proxmox_version: Optional[str] = None virtualization_type: Optional[str] = None ``` **Ligne 191 :** Ajout dans `HardwareData` ```python virtualization: Optional[VirtualizationInfo] = None ``` **Ligne 232-234 :** Ajout dans `HardwareSnapshotResponse` ```python is_proxmox_host: Optional[bool] = None is_proxmox_guest: Optional[bool] = None proxmox_version: Optional[str] = None ``` **3. Extraction API** **Fichier :** `backend/app/api/benchmark.py` **Lignes :** 133-141 ```python # Virtualization (support both old and new format) if hw.virtualization: snapshot.virtualization_type = hw.virtualization.virtualization_type snapshot.is_proxmox_host = hw.virtualization.is_proxmox_host snapshot.is_proxmox_guest = hw.virtualization.is_proxmox_guest snapshot.proxmox_version = hw.virtualization.proxmox_version elif hw.os and hw.os.virtualization_type: # Fallback for old format snapshot.virtualization_type = hw.os.virtualization_type ``` #### D. Frontend JavaScript **Fichier :** `frontend/js/device_detail.js` **Lignes :** 692-704 ```javascript // Virtualization info with Proxmox detection let virtualizationInfo = 'N/A'; if (snapshot.is_proxmox_host) { const version = snapshot.proxmox_version ? ` v${snapshot.proxmox_version}` : ''; virtualizationInfo = `🔷 Proxmox VE Host${version}`; } else if (snapshot.is_proxmox_guest) { const vType = snapshot.virtualization_type || 'VM'; virtualizationInfo = `💠 Proxmox Guest (${vType})`; } else if (snapshot.virtualization_type && snapshot.virtualization_type !== 'none') { virtualizationInfo = snapshot.virtualization_type; } else { virtualizationInfo = 'Aucune'; } ``` **Affichage dans section OS :** - Ligne "Virtualisation" montre maintenant le type Proxmox avec icône - Exemples : - `🔷 Proxmox VE Host v8.1.3` - `💠 Proxmox Guest (kvm)` - `kvm` (si virtualisation non-Proxmox) - `Aucune` (si bare metal) --- ### 2️⃣ Informations batterie dans section Carte mère **Fichier :** `frontend/js/device_detail.js` **Lignes :** 114-130 **Ajouts :** ```javascript // Add battery info if available if (snapshot.battery_percentage !== null && snapshot.battery_percentage !== undefined) { const batteryIcon = snapshot.battery_percentage >= 80 ? '🔋' : snapshot.battery_percentage >= 20 ? '🔋' : '🪫'; const batteryColor = snapshot.battery_percentage >= 80 ? 'var(--color-success)' : snapshot.battery_percentage >= 20 ? 'var(--color-warning)' : 'var(--color-error)'; const batteryStatus = snapshot.battery_status ? ` (${snapshot.battery_status})` : ''; items.push({ label: `${batteryIcon} Batterie`, value: `${Math.round(snapshot.battery_percentage)}%${batteryStatus}` }); } if (snapshot.battery_health && snapshot.battery_health !== 'Unknown') { items.push({ label: 'Santé batterie', value: snapshot.battery_health }); } ``` **Affichage :** - Pourcentage avec code couleur (vert ≥80%, orange ≥20%, rouge <20%) - Icône : 🔋 (pleine) ou 🪫 (vide) - Statut : Charging, Discharging, Full, etc. - Santé : Good, Fair, Poor - Conditionnel : affiché uniquement si batterie présente --- ### 3️⃣ Optimisation affichage cartes mémoire **Fichier :** `frontend/css/memory-slots.css` **Objectif :** Rendre les cartes mémoire plus compactes (moins d'espace vertical) **Changements :** | Élément | Avant | Après | Ligne | |---------|-------|-------|-------| | `.memory-slot` padding | 1rem | 0.75rem | 29 | | `.memory-slot` border-radius | 12px | 8px | 28 | | `.memory-slot-header` margin-bottom | 0.75rem | 0.5rem | 95 | | `.memory-slot-header` padding-bottom | 0.5rem | 0.4rem | 96 | | `.memory-slot-body` gap | 0.5rem | 0.35rem | 139 | | `.memory-slot-size` font-size | 1.75rem | 1.5rem | 143 | | `.memory-slot-size` margin-bottom | 0.25rem | 0.15rem | 146 | | `.memory-slot-spec` font-size | 0.9rem | 0.85rem | 159 | | `.memory-slot-spec` padding | 0.35rem 0 | 0.2rem 0 | 160 | **Résultat :** Interface 20-30% plus compacte verticalement, plus d'informations visibles sans scroll. --- ### 4️⃣ Correction schéma RAM Slot **Fichier :** `backend/app/schemas/hardware.py` **Lignes :** 25-35 **Problème :** Le script bench.sh envoyait des champs que le schéma n'acceptait pas : - `speed_unit` (MT/s ou MHz) - `form_factor` (DIMM, SO-DIMM, etc.) - `manufacturer` (alors que le schéma utilisait `vendor`) **Solution :** ```python class RAMSlot(BaseModel): """RAM slot information""" slot: str size_mb: int type: Optional[str] = None speed_mhz: Optional[int] = None speed_unit: Optional[str] = None # ✅ AJOUTÉ form_factor: Optional[str] = None # ✅ AJOUTÉ vendor: Optional[str] = None manufacturer: Optional[str] = None # ✅ AJOUTÉ (alias) part_number: Optional[str] = None ``` **Compatibilité :** Le schéma accepte maintenant `vendor` ET `manufacturer` (pour rétrocompatibilité). --- ### 5️⃣ Note importante : Fréquence RAM à 0 **Observation :** Dans les données API, tous les slots RAM ont `speed_mhz: 0` **Exemple :** ```json { "slot": "DIMM", "size_mb": 16384, "type": "DDR4", "speed_mhz": 0, "vendor": "SK", "part_number": null } ``` **Explication :** C'est **NORMAL sur VM** ! - `dmidecode` ne peut pas toujours récupérer la fréquence RAM sur machine virtuelle - Le système hôte Proxmox virtualise le matériel - Les informations DMI sont souvent incomplètes ou simulées **Frontend :** Déjà géré correctement ! ```javascript // device_detail.js ligne 344 ${dimm.speed_mhz && dimm.speed_mhz > 0 ? `