This commit is contained in:
2025-12-14 10:40:54 +01:00
parent 5d483b0df5
commit 8428bf9c82
55 changed files with 9763 additions and 391 deletions

View File

@@ -0,0 +1,122 @@
# 01 Vision fonctionnelle et objectifs
## Nom de lapplication
Nom provisoire : **Linux BenchTools**
Objectif : application self-hosted permettant de :
- Recenser les machines (physiques, VM, SBC type Raspberry Pi).
- Collecter des informations matérielles (CPU, RAM, GPU, stockage, réseau, carte mère, OS).
- Lancer des benchmarks standardisés via un **script client** exécuté sur les machines.
- Recevoir et stocker les résultats de bench sur un **serveur central**.
- Calculer une **note globale** et des sous-scores (CPU, mémoire, disque, réseau, GPU).
- Afficher un **dashboard** triant les machines par performance globale.
- Associer des liens constructeurs et des documents (PDF / images) à chaque machine.
- tu verifiera bien sur la coherence entre tous les fichier de consigne de prompt et si le choix des outils est cohérent
Lapplication doit être :
- **Self-hosted** sur une machine Linux (Debian) au format Docker.
- Légère (SQLite, pas de dépendance à une grosse base).
- Accessible sur le réseau local (via reverse proxy existant).
- Exploitable autant pour des serveurs que des PC ou des VMs.
---
## Rôles et usages
### Rôle principal : utilisateur/admin unique (Gilles)
Actions possibles :
- Ajouter/modifier une machine (device) et ses métadonnées (description, localisation, tags).
- Visualiser les informations hardware associées à une machine.
- Lancer un bench sur une machine en copiant une commande fournie par linterface.
- Visualiser lhistorique des benchmarks dune machine.
- Consulter les notes globales et par catégorie (CPU, RAM, disque, réseau, GPU).
- Ajouter/éditer des liens vers les sites constructeurs.
- Uploader des notices PDF, factures, schémas, photos.
---
## Fonctionnalités principales (MVP)
1. **Gestion des machines (devices)**
- CRUD basique :
- Créer un device (ou auto-création à la réception dun bench).
- Lire les infos dun device.
- Modifier la description, la localisation, les tags.
- Un device représente une machine logique (hostname ou nom choisi).
2. **Snapshots hardware**
- À chaque bench, un snapshot de létat matériel et OS est enregistré :
- CPU (modèle, cœurs, threads, fréquences, cache, vendor).
- RAM (total, slots, type, capacités).
- GPU (modèle, mémoire, vendor).
- Disques (liste, type, taille, interface, SMART résumé).
- Réseau (interfaces, vitesses, IPs).
- Carte mère (vendor, modèle, BIOS).
- OS (nom, version, kernel, architecture, type machine : bare metal / VM).
- Ces infos sont liées à un `hardware_snapshot` et référencées par un `benchmark`.
3. **Benchmarks**
- Réception dun JSON produit par un script Bash exécuté sur la machine.
- Enregistrement dun `benchmark` avec :
- Date/heure du run.
- Version du script client.
- Scores par catégorie : `cpu_score`, `memory_score`, `disk_score`, `network_score`, `gpu_score`.
- `global_score` calculé selon une formule configurable (par ex. moyenne pondérée).
- Détails bruts en JSON (`details_json`) pour audit.
4. **Liens constructeur**
- Attacher à un device des liens HTTP :
- Fiche produit constructeur.
- Page support / BIOS / drivers.
- Documentation technique.
5. **Documents**
- Upload de fichiers (surtout PDF) associés à un device :
- Notices / manuels.
- Factures.
- Photos / schémas.
- Stockage sur disque, références dans SQLite.
6. **Dashboard Web**
- Page daccueil :
- Statistiques globales (nombre de devices, nombre total de benchmarks, date dernier bench, score moyen).
- Tableau trié par `global_score` décroissant.
- Indicateur compact par ligne :
- Hostname + description.
- Dernier `global_score`.
- Détail CPU/Mem/Disk/Net/GPU du dernier bench.
- Section "Quick bench script" :
- Affichage de la commande shell à copier/coller pour exécuter le script client.
---
## Non-objectifs (MVP)
- Pas de multi-tenant ni de gestion avancée de droits utilisateurs.
- Pas de monitoring temps réel (ce nest pas un outil de supervision).
- Pas de support Windows/macOS dans la première version (Linux seulement).
- Pas dagent resident/daemon permanent sur les clients (simple script à exécuter ponctuellement).
---
## Contraintes techniques
- Backend en **Python** (FastAPI recommandé).
- Base de données : **SQLite** (fichier sur disque).
- WebUI simple (HTML/CSS/JS minimal, éventuellement HTMX).
- Déploiement via **Docker** + `docker-compose`.
- Script client en **Bash** (priorité Debian/Ubuntu, extensible ensuite).
---
## Critères de réussite (MVP)
- Être capable de :
- Déployer lapp via `docker-compose up -d`.
- Copier une commande depuis le Dashboard, lexécuter sur une machine Linux, et voir :
- Le device apparaître (ou se mettre à jour).
- Un nouveau benchmark visible dans linterface.
- Voir la machine triée correctement dans le dashboard par `global_score`.
- Pouvoir attacher au moins un PDF à un device et le télécharger depuis linterface.

242
docs/02_model_donnees.md Normal file
View File

@@ -0,0 +1,242 @@
# 02 Modèle de données (SQLite)
Objectif : définir le schéma relationnel pour SQLite, exploité par SQLAlchemy (ou équivalent).
## Vue densemble
Tables principales :
- `devices`
- `hardware_snapshots`
- `benchmarks`
- `manufacturer_links`
- `documents`
Optionnel (plus tard) :
- `users` (si auth interne)
- `settings` (config globale de lapp)
---
## Table devices
Représente une machine (physique ou virtuelle).
Champs :
- `id` (INTEGER, PK, autoincrement)
- `hostname` (TEXT, non nul)
- `fqdn` (TEXT, nullable)
- `description` (TEXT, nullable)
- `asset_tag` (TEXT, nullable) identifiant interne/inventaire
- `location` (TEXT, nullable)
- `owner` (TEXT, nullable)
- `tags` (TEXT, nullable) liste séparée par virgules ou JSON
- `created_at` (DATETIME, non nul)
- `updated_at` (DATETIME, non nul)
Contraintes :
- `hostname` peut être utilisé comme identifiant logique si `device_identifier` nest pas fourni par le client.
- Index recommandé : `idx_devices_hostname`.
---
## Table hardware_snapshots
Snapshot détaillé de la configuration matérielle et OS au moment dun bench.
Champs :
- `id` (INTEGER, PK)
- `device_id` (INTEGER, FK -> devices.id)
- `captured_at` (DATETIME, non nul)
### CPU
- `cpu_vendor` (TEXT)
- `cpu_model` (TEXT)
- `cpu_microarchitecture` (TEXT, nullable)
- `cpu_cores` (INTEGER)
- `cpu_threads` (INTEGER)
- `cpu_base_freq_ghz` (REAL, nullable)
- `cpu_max_freq_ghz` (REAL, nullable)
- `cpu_cache_l1_kb` (INTEGER, nullable)
- `cpu_cache_l2_kb` (INTEGER, nullable)
- `cpu_cache_l3_kb` (INTEGER, nullable)
- `cpu_flags` (TEXT, nullable) chaîne ou JSON (AVX, AES, etc.)
- `cpu_tdp_w` (REAL, nullable)
### RAM
- `ram_total_mb` (INTEGER)
- `ram_slots_total` (INTEGER, nullable)
- `ram_slots_used` (INTEGER, nullable)
- `ram_ecc` (BOOLEAN, nullable)
- `ram_layout_json` (TEXT, nullable)
Exemple JSON :
```json
[
{ "slot": "DIMM_A1", "size_mb": 16384, "type": "DDR4", "speed_mhz": 2133, "vendor": "Corsair", "part_number": "XXXX" }
]
```
### GPU
- `gpu_summary` (TEXT, nullable) ex: "Intel UHD 630"
- `gpu_vendor` (TEXT, nullable)
- `gpu_model` (TEXT, nullable)
- `gpu_driver_version` (TEXT, nullable)
- `gpu_memory_dedicated_mb` (INTEGER, nullable)
- `gpu_memory_shared_mb` (INTEGER, nullable)
- `gpu_api_support` (TEXT, nullable) ex: "OpenGL 4.6, Vulkan"
### Stockage
- `storage_summary` (TEXT, nullable) résumé human readable
- `storage_devices_json` (TEXT, nullable)
Exemple JSON :
```json
[
{
"name": "/dev/nvme0n1",
"type": "NVMe",
"interface": "PCIe 3.0 x4",
"capacity_gb": 1000,
"vendor": "Samsung",
"model": "970 EVO Plus",
"smart_health": "PASSED",
"temperature_c": 42
}
]
```
- `partitions_json` (TEXT, nullable)
### Réseau
- `network_interfaces_json` (TEXT, nullable)
Exemple :
```json
[
{
"name": "eth0",
"type": "ethernet",
"mac": "aa:bb:cc:dd:ee:ff",
"ip": "10.0.0.10",
"speed_mbps": 1000,
"driver": "e1000e"
}
]
```
### OS / Carte mère
- `os_name` (TEXT)
- `os_version` (TEXT)
- `kernel_version` (TEXT)
- `architecture` (TEXT) "x86_64", "arm64"
- `virtualization_type` (TEXT, nullable) "kvm", "vmware", "none", etc.
- `motherboard_vendor` (TEXT, nullable)
- `motherboard_model` (TEXT, nullable)
- `bios_version` (TEXT, nullable)
- `bios_date` (TEXT, nullable)
### Divers
- `sensors_json` (TEXT, nullable) valeurs de températures, etc.
- `raw_info_json` (TEXT, nullable) dump brut de commandes (inxi, lshw, etc.)
Index recommandés :
- `idx_hw_snapshots_device_id`
- `idx_hw_snapshots_captured_at`
---
## Table benchmarks
Représente un run de bench.
Champs :
- `id` (INTEGER, PK)
- `device_id` (INTEGER, FK -> devices.id)
- `hardware_snapshot_id` (INTEGER, FK -> hardware_snapshots.id)
- `run_at` (DATETIME, non nul)
- `bench_script_version` (TEXT, non nul)
### Scores
- `global_score` (REAL, non nul)
- `cpu_score` (REAL, nullable)
- `memory_score` (REAL, nullable)
- `disk_score` (REAL, nullable)
- `network_score` (REAL, nullable)
- `gpu_score` (REAL, nullable)
### Détails
- `details_json` (TEXT, non nul)
Contient toutes les valeurs brutes :
- CPU events/sec, temps dexécution, etc.
- Throughput mémoire.
- Read/write MB/s, IOPS.
- Vitesse iperf3, ping.
- Score GPU, etc.
- `notes` (TEXT, nullable)
Index :
- `idx_benchmarks_device_id`
- `idx_benchmarks_run_at`
---
## Table manufacturer_links
Liens vers les ressources en ligne du constructeur.
Champs :
- `id` (INTEGER, PK)
- `device_id` (INTEGER, FK -> devices.id)
- `label` (TEXT, non nul) ex: "Support HP", "Page produit Lenovo"
- `url` (TEXT, non nul)
Index :
- `idx_links_device_id`
---
## Table documents
Fichiers (PDF, images, etc.) associés à un device.
Champs :
- `id` (INTEGER, PK)
- `device_id` (INTEGER, FK -> devices.id)
- `doc_type` (TEXT, non nul) `manual`, `warranty`, `invoice`, `photo`, `other`
- `filename` (TEXT, non nul) nom original
- `stored_path` (TEXT, non nul) chemin relatif sur le serveur
- `mime_type` (TEXT, non nul)
- `size_bytes` (INTEGER, non nul)
- `uploaded_at` (DATETIME, non nul)
Index :
- `idx_documents_device_id`
---
## Éventuelle table settings (optionnelle)
Pour stocker des paramètres globaux de lapplication.
Champs :
- `id` (INTEGER, PK)
- `key` (TEXT, unique)
- `value` (TEXT)
Exemples :
- `default_bench_server_url`
- `default_iperf_server`
- `score_weights_json` (pondération CPU/Mem/Disque/Réseau/GPU)

537
docs/03_api_backend.md Normal file
View File

@@ -0,0 +1,537 @@
# 03 Spécification API Backend (FastAPI)
Objectif : définir précisément les endpoints backend, les schémas JSON échangés et les règles métier associées.
LAPI sera exposée sous `/api`.
---
## 1. Contenu attendu de ce fichier
Ce document doit servir de référence au développeur backend. Il décrit :
1. Le format du payload JSON envoyé par le script de benchmark (`bench.sh`) vers le backend.
2. Les endpoints REST nécessaires :
- Réception dun benchmark.
- Consultation des devices.
- Consultation de lhistorique des benchmarks.
- Gestion des liens constructeur.
- Gestion des documents (PDF, images).
3. Les règles dauthentification (token simple).
4. Les codes derreur principaux et attentes de validation.
---
## 2. Schéma JSON payload dun benchmark
Endpoint cible : `POST /api/benchmark`
Le script client envoie un JSON de la forme :
```json
{
"device_identifier": "elitedesk-800g3",
"bench_script_version": "1.0.0",
"hardware": {
"cpu": {
"vendor": "Intel",
"model": "Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz",
"microarchitecture": "Skylake",
"cores": 4,
"threads": 8,
"base_freq_ghz": 3.4,
"max_freq_ghz": 4.0,
"cache_l1_kb": 256,
"cache_l2_kb": 1024,
"cache_l3_kb": 8192,
"flags": ["avx", "avx2", "aes"],
"tdp_w": 65
},
"ram": {
"total_mb": 65536,
"slots_total": 4,
"slots_used": 4,
"ecc": false,
"layout": [
{
"slot": "DIMM_A1",
"size_mb": 16384,
"type": "DDR4",
"speed_mhz": 2133,
"vendor": "Corsair",
"part_number": "XYZ"
}
]
},
"gpu": {
"vendor": "Intel",
"model": "Intel HD Graphics 530",
"driver_version": "xxx",
"memory_dedicated_mb": null,
"memory_shared_mb": 512,
"api_support": ["OpenGL 4.5"]
},
"storage": {
"devices": [
{
"name": "/dev/nvme0n1",
"type": "NVMe",
"interface": "PCIe 3.0 x4",
"capacity_gb": 1000,
"vendor": "Samsung",
"model": "970 EVO Plus",
"smart_health": "PASSED",
"temperature_c": 42
}
],
"partitions": [
{
"name": "/dev/nvme0n1p1",
"mount_point": "/",
"fs_type": "ext4",
"used_gb": 50,
"total_gb": 100
}
]
},
"network": {
"interfaces": [
{
"name": "eth0",
"type": "ethernet",
"mac": "aa:bb:cc:dd:ee:ff",
"ip": "10.0.0.10",
"speed_mbps": 1000,
"driver": "e1000e"
}
]
},
"motherboard": {
"vendor": "HP",
"model": "HP 8054",
"bios_version": "P01 Ver. 02.48",
"bios_date": "2023-05-10"
},
"os": {
"name": "Debian",
"version": "12 (bookworm)",
"kernel_version": "6.1.0-xx-amd64",
"architecture": "x86_64",
"virtualization_type": "none"
},
"sensors": {
"cpu_temp_c": 45,
"disk_temps_c": {
"/dev/nvme0n1": 42
}
},
"raw_info": {
"lscpu": "raw text…",
"lsblk": "raw text…"
}
},
"results": {
"cpu": {
"events_per_sec": 12000,
"duration_s": 10,
"score": 90
},
"memory": {
"throughput_mib_s": 20000,
"score": 95
},
"disk": {
"read_mb_s": 1200,
"write_mb_s": 1000,
"iops_read": 50000,
"iops_write": 45000,
"latency_ms": 1.2,
"score": 94
},
"network": {
"upload_mbps": 930,
"download_mbps": 940,
"ping_ms": 1.2,
"jitter_ms": 0.3,
"packet_loss_percent": 0.0,
"score": 88
},
"gpu": {
"glmark2_score": null,
"score": null
},
"global_score": 92
}
}
```
Remarques importantes :
- Certains champs peuvent être `null` ou absents en fonction de la machine (ex: pas de GPU dédié).
- Le backend doit être robuste à labsence de certains blocs (ex: pas de `network` si aucun test réseau).
---
## 3. Logique de traitement côté backend
1. **Auth**
- Lecture du header `Authorization: Bearer <TOKEN>`.
- Comparaison avec une valeur stockée dans la config/ENV (`API_TOKEN`).
- Si token invalide ou absent : réponse 401.
2. **Résolution du device**
- Chercher un enregistrement `devices` avec `hostname == device_identifier`.
- Si trouvé :
- Utiliser `device_id` existant.
- Sinon :
- Créer un nouveau `device` minimal avec :
- `hostname = device_identifier`
- `created_at`, `updated_at` = maintenant.
3. **Création dun hardware_snapshot**
- Mapper le contenu `hardware` vers la table `hardware_snapshots` telle que définie dans `02_model_donnees.md`.
- Exemples :
- `hardware.cpu.vendor` -> `cpu_vendor`
- `hardware.ram.total_mb` -> `ram_total_mb`
- `hardware.storage.devices` -> JSON dans `storage_devices_json`
- etc.
- `captured_at` = `now()` (ou `run_at` du benchmark si fourni).
4. **Création dun benchmark**
- `run_at` = `now()` (ou fourni explicitement plus tard).
- `bench_script_version` = champ du payload.
- Scores :
- `cpu_score` = `results.cpu.score` (si présent).
- `memory_score` = `results.memory.score`
- `disk_score` = `results.disk.score`
- `network_score` = `results.network.score`
- `gpu_score` = `results.gpu.score`
- `global_score` = `results.global_score`
- `details_json` = JSON complet de `results` (ou éventuellement de `results` + métriques brutes).
5. **Réponse**
- En cas de succès, renvoyer :
```json
{
"status": "ok",
"device_id": 1,
"benchmark_id": 42
}
```
---
## 4. Endpoints détaillés
### 4.1. POST /api/benchmark
- Rôle : point dentrée unique des résultats du script client.
- Auth : header `Authorization: Bearer <TOKEN>`.
- Body : JSON (voir schéma ci-dessus).
- Codes de réponse :
- `200` succès.
- `400` JSON invalide / validation Pydantic échouée.
- `401` token invalide ou manquant.
- `500` erreur interne.
---
### 4.2. GET /api/devices
Objectif : lister les devices avec un résumé de leur dernier benchmark.
Paramètres query :
- `page` (int, optionnel, défaut 1)
- `page_size` (int, optionnel, défaut 20)
- `search` (string, optionnel filtre sur hostname/description/tags)
Réponse (exemple simplifié) :
```json
{
"items": [
{
"id": 1,
"hostname": "elitedesk-800g3",
"description": "HP EliteDesk 800 G3 SFF",
"location": "Bureau",
"tags": ["lab", "dev"],
"last_benchmark": {
"id": 42,
"run_at": "2025-12-07T10:32:00Z",
"global_score": 92,
"cpu_score": 90,
"memory_score": 95,
"disk_score": 94,
"network_score": 88,
"gpu_score": null
}
}
],
"total": 1,
"page": 1,
"page_size": 20
}
```
---
### 4.3. GET /api/devices/{device_id}
Objectif : récupérer le détail dun device.
Réponse (exemple) :
```json
{
"id": 1,
"hostname": "elitedesk-800g3",
"fqdn": "elitedesk-800g3.maison43",
"description": "HP EliteDesk 800 G3 SFF (serveur dev)",
"asset_tag": "LAB-001",
"location": "Bureau",
"owner": "Gilles",
"tags": ["lab", "proxmox"],
"created_at": "2025-12-01T10:00:00Z",
"updated_at": "2025-12-07T10:32:00Z",
"last_hardware_snapshot": {
"captured_at": "2025-12-07T10:32:00Z",
"cpu_vendor": "Intel",
"cpu_model": "Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz",
"cpu_cores": 4,
"cpu_threads": 8,
"ram_total_mb": 65536,
"storage_summary": "NVMe 1TB + HDD 2TB",
"gpu_summary": "Intel HD Graphics 530",
"os_name": "Debian",
"os_version": "12 (bookworm)",
"kernel_version": "6.1.0-xx-amd64"
},
"last_benchmark": {
"id": 42,
"run_at": "2025-12-07T10:32:00Z",
"global_score": 92,
"cpu_score": 90,
"memory_score": 95,
"disk_score": 94,
"network_score": 88,
"gpu_score": null
}
}
```
---
### 4.4. GET /api/devices/{device_id}/benchmarks
Objectif : récupérer lhistorique de benchmarks dun device.
Paramètres :
- `limit` (int, défaut 20)
- `offset` (int, défaut 0)
Réponse :
```json
{
"items": [
{
"id": 42,
"run_at": "2025-12-07T10:32:00Z",
"global_score": 92,
"cpu_score": 90,
"memory_score": 95,
"disk_score": 94,
"network_score": 88,
"gpu_score": null
},
{
"id": 35,
"run_at": "2025-12-05T09:10:00Z",
"global_score": 89,
"cpu_score": 88,
"memory_score": 92,
"disk_score": 90,
"network_score": 85,
"gpu_score": null
}
],
"total": 2,
"limit": 20,
"offset": 0
}
```
---
### 4.5. GET /api/benchmarks/{benchmark_id}
Objectif : récupérer les détails complets dun benchmark.
Réponse :
```json
{
"id": 42,
"device_id": 1,
"hardware_snapshot_id": 10,
"run_at": "2025-12-07T10:32:00Z",
"bench_script_version": "1.0.0",
"global_score": 92,
"cpu_score": 90,
"memory_score": 95,
"disk_score": 94,
"network_score": 88,
"gpu_score": null,
"details": {
"cpu": {
"events_per_sec": 12000,
"duration_s": 10,
"score": 90
},
"memory": {
"throughput_mib_s": 20000,
"score": 95
},
"disk": {
"read_mb_s": 1200,
"write_mb_s": 1000,
"iops_read": 50000,
"iops_write": 45000,
"latency_ms": 1.2,
"score": 94
},
"network": {
"upload_mbps": 930,
"download_mbps": 940,
"ping_ms": 1.2,
"jitter_ms": 0.3,
"packet_loss_percent": 0,
"score": 88
},
"gpu": {
"glmark2_score": null,
"score": null
},
"global_score": 92
}
}
```
Note : `details` reflète `details_json` de la base.
---
### 4.6. Liens constructeur
#### GET /api/devices/{device_id}/links
Réponse :
```json
[
{
"id": 1,
"label": "Support HP",
"url": "https://support.hp.com/..."
},
{
"id": 2,
"label": "Page produit",
"url": "https://www.hp.com/..."
}
]
```
#### POST /api/devices/{device_id}/links
Body :
```json
{
"label": "Support HP",
"url": "https://support.hp.com/..."
}
```
Réponse : lobjet créé avec `id`.
#### PUT /api/links/{id}
Body idem POST (label + url).
#### DELETE /api/links/{id}
- Réponse : `204 No Content` en cas de succès.
---
### 4.7. Documents
#### GET /api/devices/{device_id}/docs
Réponse :
```json
[
{
"id": 1,
"doc_type": "manual",
"filename": "manual_elitedesk.pdf",
"mime_type": "application/pdf",
"size_bytes": 3456789,
"uploaded_at": "2025-05-01T10:00:00Z"
}
]
```
#### POST /api/devices/{device_id}/docs
- Type : `multipart/form-data`
- Champs :
- `file` (fichier binaire)
- `doc_type` (string)
Réponse : métadonnées du document créé.
#### GET /api/docs/{doc_id}/download
- Sert le fichier binaire avec le bon `Content-Type`.
---
## 5. Authentification
MVP : token simple.
- Variable denv `API_TOKEN` côté backend.
- Chaque requête `POST /api/benchmark` doit inclure :
```http
Authorization: Bearer <API_TOKEN>
```
- Les endpoints de lecture (GET) peuvent être :
- soit publics sur le LAN,
- soit protégés par un autre mécanisme (reverse proxy) hors scope de cette spec.
---
## 6. Gestion des erreurs et validations
- Utiliser des modèles Pydantic pour :
- valider la structure de `hardware` et `results` autant que possible sans être bloquant.
- autoriser des champs optionnels (None / manquants).
- Codes derreur génériques :
- 400 : données invalides (schema).
- 401 : auth.
- 404 : ressources inexistantes (device, benchmark, link, doc).
- 413 : payload trop volumineux (facultatif selon config).
- 500 : erreur interne.
Logs :
- Logguer les erreurs de parsing JSON.
- Logguer lorigine (IP) des appels `POST /api/benchmark`.
---

View File

@@ -0,0 +1,475 @@
# 04 Spécification du script client de benchmark (bench.sh)
Objectif : définir précisément le comportement du script Bash exécuté sur les machines clientes pour :
- collecter les informations matérielles et système,
- exécuter les benchmarks,
- calculer les scores,
- envoyer un JSON complet au backend via HTTP.
Ce fichier sert de référence pour écrire `scripts/bench.sh` dans le dépôt.
---
## 1. Usage et interface en ligne de commande
Le script doit être exécutable en one-liner depuis une machine cliente, par exemple :
```bash
curl -s https://gitea.maison43.duckdns.org/gilles/linux-benchtools/raw/branch/main/scripts/bench.sh \
| bash -s -- \
--server https://bench.maison43/api/benchmark \
--token "XXXXXXX" \
--device "elitedesk-800g3" \
--iperf-server 10.0.0.10 \
--short
```
### 1.1. Arguments supportés
- `--server <URL>` (obligatoire)
URL de lendpoint backend `POST /api/benchmark`.
- `--token <TOKEN>` (obligatoire)
Token dauthentification à envoyer dans `Authorization: Bearer <TOKEN>`.
- `--device <NAME>` (optionnel)
Identifiant logique de la machine (`device_identifier`).
Si non fourni, utiliser `hostname` de la machine.
- `--iperf-server <HOST>` (optionnel)
Hôte/IP du serveur iperf3 utilisé pour les tests réseau.
- `--skip-cpu`, `--skip-memory`, `--skip-disk`, `--skip-network`, `--skip-gpu` (optionnels)
Permettent de désactiver certains tests.
- `--short` (optionnel)
Version “rapide” des tests (durées/tailles réduites).
- `--help`
Affiche un message daide et quitte.
### 1.2. Variables internes
- `BENCH_SCRIPT_VERSION` (string, ex: `"1.0.0"`)
Doit être mise à jour à chaque changement incompatible du script.
---
## 2. Pré-requis et compatibilité
### 2.1. OS visés (MVP)
- Debian / Ubuntu / Proxmox (base Debian).
Le script doit :
- Lire `/etc/os-release` pour détecter lOS.
- Utiliser `apt-get` pour installer les paquets manquants.
### 2.2. Outils nécessaires
Le script doit vérifier et installer si besoin :
- `curl`
- `jq` (construction JSON)
- `sysbench` (CPU + mémoire)
- `fio` (disque)
- `iperf3` (réseau, si `--iperf-server` fourni)
- `dmidecode` (RAM, carte mère, BIOS)
- `lsblk`
- `lscpu`
- `smartmontools` (optionnel pour SMART disques)
- `lm-sensors` (optionnel pour températures)
- `glmark2` (optionnel pour GPU si dispo)
---
## 3. Structure générale du script
1. Parser les arguments.
2. Vérifier `--server` et `--token` (sinon erreur + exit 1).
3. Déterminer :
- `DEVICE_IDENTIFIER` = `--device` ou `hostname`.
- `BENCH_SCRIPT_VERSION`.
4. Détecter lOS et préparer la commande dinstallation de paquets.
5. Vérifier/installer les outils nécessaires.
6. Collecter les informations hardware et OS.
7. Exécuter les benchmarks (en respectant les flags `--skip-*`).
8. Calculer les scores (CPU, mémoire, disque, réseau, GPU, global).
9. Construire le JSON.
10. Envoyer le JSON au backend.
11. Afficher un récap et le statut HTTP.
---
## 4. Collecte des informations matérielles et système
Toutes les infos doivent ensuite être assemblées dans le bloc `hardware` du JSON.
### 4.1. CPU
Commandes possibles :
- `lscpu`
- `/proc/cpuinfo`
Informations à extraire :
- `vendor` : ligne `Vendor ID` (ou `GenuineIntel`, `AuthenticAMD`, etc.).
- `model` : `Model name`.
- `microarchitecture` : optionnel (peut être déterminé via une table interne si souhaité, sinon laisser vide).
- `cores` : `Core(s) per socket` × `Socket(s)` ou `CPU(s)` minus hyperthreading.
- `threads` : `CPU(s)` (nombre logique).
- `base_freq_ghz` : depuis `lscpu` (MHz -> GHz).
- `max_freq_ghz` : `CPU max MHz` si disponible.
- `cache_l1_kb`, `cache_l2_kb`, `cache_l3_kb` : `L1d cache`, `L2 cache`, `L3 cache`.
- `flags` : liste depuis `Flags` / `Features`.
- `tdp_w` : non triviale à extraire dans un script, peut rester null.
### 4.2. RAM
Commandes :
- `free -m`
- `dmidecode --type memory` (requiert sudo)
Infos :
- `total_mb` : depuis `free -m`.
- `slots_total` : nombre dentrées `Locator` dans `dmidecode` (type DIMM).
- `slots_used` : slots où `Size` nest pas `No Module Installed`.
- `ecc` : champ `Total Width` vs `Data Width` ou `Error Correction Type`.
- `layout` : tableau dobjets avec :
- `slot` (Locator)
- `size_mb`
- `type` (DDR3/DDR4/DDR5/etc.)
- `speed_mhz`
- `vendor`
- `part_number`
### 4.3. GPU
Commandes :
- `lspci | grep -i vga`
- éventuellement `nvidia-smi` si NVIDIA.
Infos :
- `vendor` : Intel, NVIDIA, AMD…
- `model` : texte brut de `lspci`.
- `driver_version` : si récupérable (`nvidia-smi --query-gpu=driver_version`).
- `memory_dedicated_mb` : via `nvidia-smi`/outils spécifiques si possible, sinon null.
- `memory_shared_mb` : éventuellement via `lspci`/`/proc`, sinon null.
- `api_support` : optionnel (OpenGL/Vulkan), peut être laissé vide.
### 4.4. Stockage (disques et partitions)
Commandes :
- `lsblk -o NAME,SIZE,TYPE,MODEL,TRAN,MOUNTPOINT,FSTYPE`
- `smartctl -H /dev/sdX` (si présent)
- éventuellement `nvme list` / `nvme smart-log`.
Infos :
- `devices` : tableau dobjets :
- `name` (ex: `/dev/nvme0n1`)
- `type` (HDD/SSD/NVMe, déduit de `TYPE`/`TRAN`/nom).
- `interface` (SATA, PCIe 3.0 x4, USB, etc. si déductible).
- `capacity_gb` : depuis `SIZE`.
- `vendor` / `model` : `MODEL`.
- `smart_health` : `PASSED` / `FAILED` / null.
- `temperature_c` : si dispo via SMART.
- `partitions` : tableau dobjets :
- `name`
- `mount_point`
- `fs_type`
- `used_gb`
- `total_gb`
### 4.5. Réseau
Commandes :
- `ip addr`
- `ip -o link`
- `ethtool <iface>` (pour vitesse si dispo).
- pour Wi-Fi : `iw dev` / `iwconfig`.
Infos :
- `interfaces` : tableau dobjets :
- `name` (ex: `eth0`, `enp3s0`, `wlan0`)
- `type` (`ethernet`, `wifi`, `other`)
- `mac`
- `ip` (IPv4 principale si existante)
- `speed_mbps` : via `ethtool`.
- `driver` : éventuellement depuis `/sys/class/net/<iface>/device/driver`.
### 4.6. Carte mère / BIOS
Commandes :
- `dmidecode --type baseboard`
- `dmidecode --type bios`
Infos :
- `motherboard.vendor`
- `motherboard.model`
- `bios_version`
- `bios_date`
### 4.7. OS
Commandes :
- `/etc/os-release`
- `uname -r`
- `uname -m`
- `systemd-detect-virt` (si dispo).
Infos :
- `name` : ID ou PRETTY_NAME.
- `version` : VERSION ou VERSION_CODENAME.
- `kernel_version` : `uname -r`.
- `architecture` : `uname -m`.
- `virtualization_type` : sortie de `systemd-detect-virt` (kvm, qemu, none, etc.).
### 4.8. Capteurs (facultatif)
- `sensors` (lm-sensors)
- `smartctl -A` pour température disques.
Infos :
- `sensors.cpu_temp_c` (ou valeur moyenne).
- `sensors.disk_temps_c` : map `{ "/dev/nvme0n1": 42 }`.
---
## 5. Benchmarks à exécuter
Les résultats iront dans le bloc `results` du JSON.
### 5.1. CPU sysbench
Commande par défaut (mode complet) :
```bash
sysbench cpu --cpu-max-prime=20000 --threads="$(nproc)" run
```
Mode `--short` :
```bash
sysbench cpu --cpu-max-prime=10000 --threads="$(nproc)" run
```
Valeurs à extraire :
- `events_per_sec` : ligne `events per second: X`.
- `duration_s` : temps total (`total time:`).
Score CPU :
- Score simple :
- définir une valeur de référence (par ex. 5000 events/s = 50 points).
- `cpu_score = min(100, events_per_sec / ref * 50)` (ajuster plus tard).
- Pour linstant, le script peut :
- soit calculer cette note,
- soit juste envoyer les valeurs brutes et laisser le backend calculer.
### 5.2. Mémoire sysbench
Commande (complet) :
```bash
sysbench memory --memory-total-size=2G --memory-oper=write run
```
Mode `--short` :
```bash
sysbench memory --memory-total-size=512M --memory-oper=write run
```
Valeurs :
- `throughput_mib_s` : ligne `transferred (XXXX MiB/sec)`.
Score mémoire :
- Basé sur `throughput_mib_s` et une référence.
### 5.3. Disque fio
Profil simple (séquentiel read/write 1GiB) :
```bash
fio --name=bench_seq_rw \
--rw=readwrite \
--bs=1M \
--size=1G \
--numjobs=1 \
--iodepth=16 \
--filename=/tmp/fio_benchfile \
--direct=1 \
--group_reporting
```
Mode `--short` :
- Taille 256M.
Valeurs à extraire (via parsing ou `--output-format=json`) :
- `read_mb_s`
- `write_mb_s`
- éventuellement `iops_read`, `iops_write`, `latency_ms`.
Score disque :
- Moyenne pondérée de read/write vs valeurs de référence.
Après test, supprimer `/tmp/fio_benchfile`.
### 5.4. Réseau iperf3
Uniquement si `--iperf-server` fourni.
Download (client -> server, test reverse) :
```bash
iperf3 -c "$IPERF_SERVER" -R -J
```
Upload :
```bash
iperf3 -c "$IPERF_SERVER" -J
```
Utiliser le JSON (`-J`) + `jq` pour extraire :
- `upload_mbps`
- `download_mbps`
- `jitter_ms`
- `packet_loss_percent` (si UDP, option future).
Ping (latence) :
```bash
ping -c 5 "$IPERF_SERVER"
```
Extraire :
- `ping_ms` = moyenne.
Score réseau :
- Combinaison débit (min(up, down)) et latence (ping).
### 5.5. GPU glmark2 (optionnel)
Si `glmark2` disponible :
```bash
glmark2
```
Extraire :
- Score global `glmark2_score`.
Score GPU :
- Normalisation simple vs référence.
---
## 6. Construction du JSON
Le script utilise `jq` pour construire le JSON final :
Structure :
```json
{
"device_identifier": "...",
"bench_script_version": "1.0.0",
"hardware": { ... },
"results": { ... }
}
```
Principes :
- Utiliser `jq -n` et passer les valeurs via `--arg` / `--argjson`.
- Attention aux nombres vs strings (utiliser `--argjson` pour les nombres).
- Gérer proprement les valeurs nulles (par exemple si test GPU non réalisé).
Exemple (simplifié) en shell :
```bash
payload=$(jq -n --arg device_identifier "$DEVICE_IDENTIFIER" --arg bench_script_version "$BENCH_SCRIPT_VERSION" --argjson cpu "$CPU_JSON" --argjson ram "$RAM_JSON" --argjson results "$RESULTS_JSON" '{
device_identifier: $device_identifier,
bench_script_version: $bench_script_version,
hardware: {
cpu: $cpu,
ram: $ram
},
results: $results
}')
```
---
## 7. Envoi au backend
Commandes :
```bash
HTTP_RESPONSE=$(curl -s -o /tmp/bench_response.txt -w "%{http_code}" \
-X POST "$SERVER_URL" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d "$payload")
```
- Si `HTTP_RESPONSE` != `200` :
- Afficher un message derreur (console).
- Optionnel : afficher `/tmp/bench_response.txt`.
- Si succès :
- Afficher un message confirmant lID du benchmark si présent dans la réponse.
---
## 8. Gestion des erreurs à prévoir
- Absence de `--server` ou `--token` -> erreur et exit.
- Outils manquants et impossible à installer -> avertir, sauter le test concerné, transmettre `score = null`.
- Erreurs iperf3 (serveur indisponible) -> ignorer la partie réseau, `network` null.
- Temps de test trop long -> proposer un mode `--short`.
---
## 9. Journalisation locale (optionnelle)
- Possibilité de logger les infos dans `/var/log/linux_benchtools_client.log` ou `/tmp/linux_benchtools_client.log`.
- Log recommandé :
- Date/heure.
- SERVER, DEVICE_IDENTIFIER.
- Résumé des scores.
- Code HTTP de la réponse.
---
## 10. Bonnes pratiques
- Ne jamais supprimer ou modifier des fichiers système.
- Nettoyer les fichiers temporaires (fio, résultats intermédiaires).
- Garder le script idempotent : on peut le relancer sans casser la machine.
- Prévoir un délai total raisonnable pour un run complet (ex. < 510 minutes en mode complet, < 23 minutes en mode `--short`).

192
docs/05_webui_design.md Normal file
View File

@@ -0,0 +1,192 @@
# 05 Design WebUI (structure, pages, composants)
Objectif : définir linterface utilisateur de Linux BenchTools, les pages, les composants, lorganisation visuelle et les interactions nécessaires.
---
# 1. Principes généraux
- Interface orientée **observabilité** des performances machines.
- Style sombre **Monokai-like**.
- Pages structurées en **cartes** et **tableaux lisibles**.
- Navigation : **Dashboard**, **Devices**, **Settings**.
- Composants réutilisables : badges score, cartes hardware, tableaux benchmark.
---
# 2. Pages de la WebUI
## 2.1. Dashboard (`/`)
Présente un aperçu du parc machines et un classement global.
### Contenu :
- **Stats globales**
- Nombre de devices
- Nombre total de benchmarks
- Score global moyen
- Dernier bench reçu
- **Tableau Top Devices**
- Rang
- Hostname
- Description
- Score global
- Scores CPU/MEM/DISK/NET/GPU
- Dernier run
- **Bloc “Quick Bench Script”**
- Commande à copier pour exécuter un bench sur une nouvelle machine.
---
## 2.2. Liste Devices (`/devices`)
- Tableau paginé et filtrable
- Colonnes :
- Hostname
- Description
- Location
- Tags
- Dernier Score
- Dernier Bench
- Bouton “Voir”
Barre de recherche : filtre hostname / tags / description.
---
## 2.3. Page Device Détail (`/devices/{id}`)
### Sections :
#### A. Bandeau principal
- Hostname
- Description
- Tags
- Localisation / Owner
#### B. Résumé Hardware
- CPU : modèle, cores, threads, fréquences
- RAM : total, slots utilisés, détail
- GPU
- Stockage (NVMe/SSD/HDD)
- Réseau
- Carte mère / BIOS
- OS / kernel
#### C. Dernier Benchmark
- Score global + badge couleur
- Scores CPU / MEM / DISK / NET / GPU
- Timestamp
- Bouton “Voir JSON complet”
#### D. Onglets
1. **Summary**
2. **Benchmarks**
- Tableau simple
- Évolution future en graphe
3. **Documents**
- Upload PDF/images
- Liste des documents
- Boutons download/delete
4. **Links**
- Liste des liens constructeurs
- Form ajout
- Edit / Delete
---
## 2.4. Settings (`/settings`)
Champs configurables :
- Bench server URL
- Default iperf-server
- Token API (lecture seule)
- Commande bench générée automatiquement
---
# 3. Style visuel (Monokai Dark)
### Couleurs
- Fond général : `#1e1e1e`
- Cartes : `#2d2d2d`
- Texte principal : `#f8f8f2`
- Texte secondaire : `#cccccc`
- Success : `#a6e22e`
- Warning : `#fd971f`
- Danger : `#f92672`
### Composants
- **Badge Score**
- 050 : rouge
- 5175 : orange
- 76100 : vert
- **Cartes Hardware**
- Layout en 2 ou 3 colonnes
- **Tableaux**
- Style striped + hover highlight
---
# 4. Mockups ASCII
## Dashboard
```
+---------------------------------------------------------------------------+
| Linux BenchTools Dashboard |
+---------------------------------------------------------------------------+
| Stats |
| Devices: 12 Benchmarks: 47 Avg Score: 78.4 Last: 20251207 |
+---------------------------------------------------------------------------+
| Top Devices |
+---------------------------------------------------------------------------+
| # | Hostname | Score | CPU | MEM | DISK | NET | GPU | Last Run |
|---------------------------------------------------------------------------|
| 1 | elitedesk-800g3 | 92 | 90 | 95 | 94 | 88 | -- | 10:32 |
+---------------------------------------------------------------------------+
| Quick Bench Script |
| curl -s https://.../bench.sh | bash -s -- --server ... --token XXXX |
+---------------------------------------------------------------------------+
```
## Page Device
```
Device: elitedesk-800g3
Location: Bureau Tags: lab, dev
Hardware Summary:
CPU: Intel i76700 (4C/8T, 3.4 → 4.0 GHz)
RAM: 64GB (4×16GB)
GPU: Intel HD 530
Storage: NVMe 1TB + HDD 2TB
Network: eth0 1Gbps
OS: Debian 12 / Kernel 6.1
Last Benchmark:
Global Score: 92 [GREEN]
CPU 90 | MEM 95 | DISK 94 | NET 88 | GPU --
Run: 20251207 10:32
Tabs: [Summary] [Benchmarks] [Documents] [Links]
```
---
# 5. API utilisée par le frontend
- `/api/devices`
- `/api/devices/{id}`
- `/api/devices/{id}/benchmarks`
- `/api/devices/{id}/docs`
- `/api/docs/{id}/download`
- `/api/devices/{id}/links`
---
# 6. Améliorations futures
- Graphiques dévolution des scores (Chart.js)
- Mode mobile
- Compare devices
- Notifications en cas de baisse anormale de performance

View File

@@ -0,0 +1,216 @@
# 06 Architecture Backend & Déploiement (FastAPI + Uvicorn + Docker)
Objectif : définir la structure technique du backend, l'organisation du code, les dépendances,
le déploiement via Docker, et les bonnes pratiques de maintenance.
---
# 1. Architecture générale du backend
Le backend repose sur :
- Python **3.11+**
- **FastAPI** (framework web)
- **Uvicorn** (serveur ASGI)
- **SQLite** (stockage local)
- **SQLAlchemy** (ORM)
- **Pydantic** (validation des schémas)
- Docker (déploiement)
- Arborescence claire modulaire
---
# 2. Arborescence recommandée
```
backend/
├── app/
│ ├── api/
│ │ ├── benchmark.py
│ │ ├── devices.py
│ │ ├── docs.py
│ │ ├── links.py
│ │ └── __init__.py
│ │
│ ├── core/
│ │ ├── config.py
│ │ ├── security.py
│ │ └── __init__.py
│ │
│ ├── models/
│ │ ├── device.py
│ │ ├── hardware_snapshot.py
│ │ ├── benchmark.py
│ │ ├── manufacturer_link.py
│ │ ├── document.py
│ │ └── __init__.py
│ │
│ ├── schemas/
│ │ ├── benchmark.py
│ │ ├── device.py
│ │ ├── hardware.py
│ │ ├── document.py
│ │ ├── link.py
│ │ └── __init__.py
│ │
│ ├── db/
│ │ ├── base.py
│ │ ├── session.py
│ │ ├── init_db.py
│ │ └── __init__.py
│ │
│ ├── utils/
│ │ ├── scoring.py
│ │ └── __init__.py
│ │
│ ├── main.py
│ └── __init__.py
├── Dockerfile
├── requirements.txt
└── README.md
```
---
# 3. Dépendances backend (requirements.txt)
```
fastapi
uvicorn
sqlalchemy
alembic
pydantic
python-multipart
jinja2
aiofiles
```
---
# 4. Fonctionnement principal
## 4.1 main.py
- Initialise FastAPI
- Charge les routes `/api/*`
- Initialise la base SQLite
- Expose un `GET /api/health`
---
# 5. Configuration (core/config.py)
Variables chargées via environnement :
- `API_TOKEN`
- `DATABASE_URL``sqlite:///./data.db`
- `UPLOAD_DIR``./uploads`
---
# 6. Déploiement Docker
## 6.1 Dockerfile
```
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app ./app
RUN mkdir -p /app/uploads /app/data
ENV API_TOKEN=CHANGE_ME
ENV DATABASE_URL=sqlite:////app/data/data.db
ENV UPLOAD_DIR=/app/uploads
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8007"]
```
---
## 6.2 docker-compose.yml
```
version: "3.9"
services:
backend:
build: ./backend
container_name: linux_benchtools_backend
ports:
- "8007:8007"
volumes:
- ./backend/data:/app/data
- ./backend/uploads:/app/uploads
environment:
API_TOKEN: "SUPER_SECRET_TOKEN"
DATABASE_URL: "sqlite:////app/data/data.db"
UPLOAD_DIR: "/app/uploads"
restart: unless-stopped
```
---
# 7. Gestion des documents (PDF, images)
- Stockés dans `/app/uploads`
- Nommage unique (hash)
- Entrée correspondante dans la BDD
- Accessibles via `/api/docs/{id}/download`
---
# 8. Pipeline dun benchmark
1. Le client exécute `bench.sh`
2. Un JSON complet est envoyé vers POST `/api/benchmark`
3. Vérification du token
4. Recherche ou création du device
5. Création dun hardware snapshot
6. Création dun benchmark
7. Calcul / stockage du score global
8. Réponse `{status: "ok", ...}`
---
# 9. Module scoring (utils/scoring.py)
Calcule :
```
global_score =
cpu * 0.30 +
mem * 0.20 +
disk * 0.25 +
net * 0.15 +
gpu * 0.10
```
Utilise les scores normalisés reçus depuis le client.
---
# 10. Sécurité
- API Token unique pour tous les clients
- Upload limité en taille
- CORS restreint au LAN si besoin
- Aucun endpoint destructif sans authentification
---
# 11. Maintenance
- Backup SQLite via cron
- Logs Docker
- Vérification santé via `/api/health`
- Ajout futur : export JSON/CSV global

View File

@@ -0,0 +1,238 @@
# 08 Script d'installation & Bootstrapping (install.sh)
Objectif : fournir un guide exhaustif et un script dinstallation automatisée de lapplication
**Linux BenchTools** (backend + frontend + dépendances) ainsi que son organisation dans le dépôt.
Ce fichier décrit :
- Le rôle du script `install.sh`
- Les prérequis système
- Linstallation via Docker ou native
- La génération automatique de larborescence
- Les variables denvironnement nécessaires
- Le lancement des services
---
# 1. Objectifs du script `install.sh`
Le script doit :
1. Vérifier les prérequis (Docker, Docker Compose, Python si installation native)
2. Créer l'arborescence du projet si inexistante
3. Générer les fichiers `.env` nécessaires
4. Installer le backend (FastAPI)
5. Installer le frontend (fichiers statiques)
6. Construire et lancer les conteneurs
7. Vérifier que lapplication fonctionne via un health check
8. Afficher les URL utiles et les commandes dusage
---
# 2. Arborescence créée automatiquement
```
linux-benchtools/
├── backend/
│ ├── app/
│ ├── Dockerfile
│ ├── requirements.txt
│ └── data/ (auto)
├── frontend/
│ ├── index.html
│ ├── devices.html
│ ├── device_detail.html
│ ├── settings.html
│ ├── css/
│ └── js/
├── uploads/ (auto)
├── docker-compose.yml
├── .env
└── install.sh
```
---
# 3. Prérequis système
Le script doit vérifier la présence de :
- **curl**
- **git**
- **Docker**
- **Docker Compose (plugin)**
Si absent → afficher un message clair (avec commande dinstallation Debian/Ubuntu).
Exemple :
```bash
if ! command -v docker >/dev/null 2>&1; then
echo "[ERREUR] Docker nest pas installé."
echo "Installez-le avec :"
echo " curl -fsSL https://get.docker.com | sh"
exit 1
fi
```
---
# 4. Fichier `.env` généré
Le script crée automatiquement un fichier `.env` si absent.
Exemple :
```
API_TOKEN=$(openssl rand -hex 32)
DATABASE_URL=sqlite:////app/data/data.db
UPLOAD_DIR=/app/uploads
BACKEND_PORT=8007
FRONTEND_PORT=8087
```
---
# 5. docker-compose.yml généré
Le script crée un fichier minimal :
```
version: "3.9"
services:
backend:
build: ./backend
ports:
- "${BACKEND_PORT}:8007"
volumes:
- ./backend/data:/app/data
- ./uploads:/app/uploads
env_file: .env
restart: unless-stopped
frontend:
image: nginx:latest
volumes:
- ./frontend:/usr/share/nginx/html:ro
ports:
- "${FRONTEND_PORT}:80"
restart: unless-stopped
```
---
# 6. Installation native (option)
Si l'utilisateur passe `install.sh --native` :
- Installation Python + venv
- Installation requirements.txt
- Exécution via :
```
uvicorn app.main:app --host 0.0.0.0 --port 8007
```
Frontend servi via un simple `python3 -m http.server`.
---
# 7. Vérification de linstallation
Une fois les services lancés :
```
curl -s http://localhost:${BACKEND_PORT}/api/health
```
Si réponse :
```
{"status":"ok"}
```
→ installation validée.
---
# 8. Affichage final après installation
Le script doit afficher :
```
Installation terminée !
Backend API : http://localhost:8007
Frontend UI : http://localhost:8087
Token API : <xxx>
Pour exécuter un benchmark sur une machine :
curl -s <URL bench.sh> | bash -s -- --server http://<ip>:8007/api/benchmark --token <TOKEN>
```
---
# 9. Structure du script `install.sh`
### Exemple de squelette :
```bash
#!/usr/bin/env bash
set -e
echo "[INFO] Vérification des prérequis..."
# test docker, docker compose, curl...
echo "[INFO] Création des dossiers..."
mkdir -p backend/data
mkdir -p uploads
echo "[INFO] Génération du fichier .env..."
if [ ! -f .env ]; then
API_TOKEN=$(openssl rand -hex 32)
cat <<EOF > .env
API_TOKEN=$API_TOKEN
DATABASE_URL=sqlite:////app/data/data.db
UPLOAD_DIR=/app/uploads
BACKEND_PORT=8007
FRONTEND_PORT=8087
EOF
fi
echo "[INFO] Construction des containers..."
docker compose build
echo "[INFO] Lancement..."
docker compose up -d
echo "[INFO] Vérification..."
sleep 2
curl -s http://localhost:8007/api/health || {
echo "[ERREUR] Le backend ne répond pas."
exit 1
}
echo "----------------------------------------------"
echo " Linux BenchTools installé avec succès !"
echo " Backend : http://localhost:8007"
echo " Frontend : http://localhost:8087"
echo " Token : $(grep API_TOKEN .env | cut -d= -f2)"
echo "----------------------------------------------"
```
---
# 10. Améliorations futures
- Choix interactif du port
- Installation sans Docker (automatique)
- Ajout d'un mode "cluster" (plusieurs workers backend)
- Génération automatique dun certificat TLS

263
docs/09_tests_qualite.md Normal file
View File

@@ -0,0 +1,263 @@
# 09 Stratégie de tests, validation et qualité pour Linux BenchTools
Objectif : définir comment tester et valider chaque brique de lapplication
(backend, script bench, frontend), afin dassurer fiabilité, reproductibilité des mesures
et facilité de maintenance.
Ce document sert de guide pour écrire les tests et scénarios de validation manuelle.
---
# 1. Périmètre des tests
Les tests couvrent :
1. **Backend API**
- Validation des endpoints
- Validation de la persistance en base
- Validation de la sécurité (token)
2. **Script client `bench.sh`**
- Fonctionnement sur différentes machines Debian/Ubuntu
- Gestion des erreurs (outils manquants, serveur indisponible)
- Qualité du JSON envoyé
3. **Frontend WebUI**
- Rendu des pages (Dashboard, Devices, Device Detail, Settings)
- Consommation correcte de lAPI
- UX minimale (lisibilité, tri, navigation)
4. **Tests de bout en bout (E2E)**
- Exécution complète dun bench depuis un client → apparition dans le Dashboard.
---
# 2. Tests Backend
## 2.1. Types de tests
- **Tests unitaires** : fonctions isolées (scoring, mapping JSON → modèles).
- **Tests dintégration** : endpoints FastAPI avec base SQLite de test.
- **Tests E2E API** : envoi dun payload complet depuis un script de test.
Framework recommandé :
- `pytest`
- `httpx` ou client de test FastAPI
## 2.2. Cas de test principaux
### a) POST /api/benchmark
- [OK] Payload complet, token valide :
- Retourne 200
- Crée un `device` si inexistant
- Crée un `hardware_snapshot`
- Crée un `benchmark`
- [OK] Device existant :
- Réutilise le `device`
- [ERR] Token manquant :
- 401
- [ERR] Token incorrect :
- 401
- [ERR] JSON invalide :
- 400
### b) GET /api/devices
- [OK] Base vide → items = [].
- [OK] Avec plusieurs devices et benchmarks :
- Retourne un `last_benchmark` cohérent.
- [OK] Paramètres `page`, `page_size` :
- Pagination effective.
### c) GET /api/devices/{id}
- [OK] Device existant :
- Retourne résumé, snapshot, dernier benchmark.
- [ERR] Device inexistant :
- 404.
### d) Liens constructeur
- [OK] CRUD complet sur `/api/devices/{id}/links`.
- [ERR] URL invalide (peut être toléré ou validé selon règle).
### e) Documents
- [OK] Upload PDF :
- Fichier stocké physiquement
- Entrée BDD créée
- [OK] Download :
- Renvoie bon `Content-Type`
- [ERR] doc_id invalide :
- 404.
---
# 3. Tests Script client (bench.sh)
## 3.1. Contexte
Les tests sur `bench.sh` sont principalement :
- des tests manuels guidés
- des tests automatisables partiellement (CI dans un container Docker).
## 3.2. Cas de test
### a) Aide & usage
- `bench.sh --help` → affiche usage.
- Sans arguments → erreur claire.
### b) Prérequis
- Si `curl`, `jq`, `sysbench`, `fio` manquants :
- message explicite
- tentative dinstallation si possible (apt-get)
- en cas déchec, test concerné désactivé mais script continue.
### c) Exécution minimale
- `bench.sh --server http://backend:8007/api/benchmark --token XXX` :
- Détecte le hostname
- Exécute les tests par défaut
- Envoie un JSON valide (vérifiable via logs backend).
### d) Modes doptions
- `--short` :
- Durées de tests CPU/mémoire/disk raccourcies
- `--skip-network` :
- Aucun test iperf3, bloc `results.network` absent ou null
- `--iperf-server` avec serveur iperf opérationnel :
- Champs réseau correctement renseignés.
### e) Gestion des erreurs réseau
- Backend down :
- Message derreur clair
- Code HTTP ≠ 200 connu
- Iperf3 indisponible :
- Bloc network absent/null
---
# 4. Tests Frontend
## 4.1. Smoke tests (manuels)
- Accès à :
- `/` → Dashboard
- `/devices`
- `/devices/{id}`
- `/settings`
- Vérification du rendu :
- Aucune erreur JS console
- Chargement des datas via API
- Tri de base dans les tableaux
## 4.2. Tests fonctionnels (scénarios)
### Scénario 1 : Premier lancement
1. Déployer lapplication.
2. Vérifier Dashboard vide, message “Aucun device”.
3. Exécuter `bench.sh` sur une machine.
4. Rafraîchir Dashboard :
- Device apparaît avec score.
### Scénario 2 : consultation dun device
1. Cliquer sur un device dans le Dashboard.
2. Page détail :
- Hardware résumé cohérent.
- Dernier benchmark affiché.
3. Onglet Benchmarks :
- Historique listé.
### Scénario 3 : Documents
1. Aller dans onglet Documents dun device.
2. Uploader un PDF.
3. Vérifier sa présence dans la liste.
4. Télécharger pour confirmer.
### Scénario 4 : Liens constructeur
1. Onglet Links dun device.
2. Ajouter un lien avec label + URL.
3. Vérifier quil est cliquable.
4. Tester suppression.
---
# 5. Tests E2E (de bout en bout)
Objectif : couvrir la chaîne complète depuis la machine cliente jusquau Dashboard.
### Scénario E2E type
1. Lancer backend + frontend via `docker compose up`.
2. Déployer `bench.sh` sur un client Debian.
3. Exécuter :
```bash
curl -s https://.../bench.sh | bash -s -- \
--server http://IP_BACKEND:8007/api/benchmark \
--token XXX \
--iperf-server 10.0.0.10
```
4. Vérifier côté backend (logs) quun benchmark a été créé.
5. Ouvrir le Dashboard :
- Device présent, scores visibles.
---
# 6. Données de test
Créer un répertoire `tests/data/` contenant :
- Exemples de payload JSON de bench :
- `bench_full.json` (tous tests)
- `bench_no_gpu.json`
- `bench_short.json`
- Scripts auxiliaires :
- `send_bench_payload.py` (envoi direct dun payload pour tests).
---
# 7. Automatisation CI (optionnel)
Intégration avec :
- GitHub Actions
- Gitea Actions / Drone / Woodpecker
Tâches CI typiques :
1. `pytest` sur le backend
2. Lancement dun backend en mode test
3. Envoi dun payload JSON factice
4. Vérification de la réponse HTTP
---
# 8. Critères de qualité
Lapplication sera considérée comme “OK” pour usage perso si :
- Au moins 1 test unitaire par endpoint critique
- Un scénario E2E réussi
- `bench.sh` fonctionne sur :
- 1 machine physique
- 1 VM
- Les erreurs dauth/token sont gérées proprement
- Le Dashboard reste utilisable avec plusieurs dizaines de devices et benchmarks
---
# 9. Améliorations possibles
- Ajout de tests de charge (Gatling / k6) sur le backend
- Ajout de tests de non-régression des scores (baseline)
- Ajout de tests visuels (Playwright, Cypress)
- Intégration dun badge “build/test status” dans le README principal

View File

@@ -0,0 +1,216 @@
# 10 Roadmap & évolutions futures pour Linux BenchTools
Objectif : lister les évolutions possibles de lapplication, organisées par phases, avec une vision
à court, moyen et long terme. Ce fichier sert de base pour prioriser les développements.
---
# 1. Vision globale
Linux BenchTools doit évoluer depuis un simple serveur de benchmarks centralisés vers :
- Un **inventaire matériel dynamique** de ton parc.
- Un **historique de performance** exploitable (avant/après upgrade, changement de config, etc.).
- Un **outil daide à la décision** (quelle machine est la plus adaptée pour tel usage).
- Un **hub de diagnostics** (détection de régression de perf, disques fragiles, réseau bridé…).
---
# 2. Phase 1 MVP (déjà spécifiée dans les fichiers 01 → 09)
Fonctionnalités :
- Réception de benchmarks via `bench.sh`
- Stockage dans SQLite
- Dashboard avec classement des machines
- Détail device + historique de benchmarks
- Liens constructeur
- Upload de documents (PDF, images)
- Script dinstallation (Docker / compose)
Objectif :
Avoir une base utilisable **en production perso** sur ton infra maison.
---
# 3. Phase 2 Améliorations UX & stabilité
## 3.1. Frontend
- Tri avancé sur les colonnes (score, date dernier bench, hostname).
- Filtre par tags, type de machine (bare-metal / VM / SBC).
- Ajout dicônes simples (type machine, OS, réseau 1G/2.5G/10G…).
- Page “Benchmarks” globale (tous les benchmarks, filtrables par device).
## 3.2. Backend
- Meilleure gestion des erreurs côté API (messages clairs, codes cohérents).
- Pagination plus fine (page_size configurable).
- Logging structuré (JSON logs optionnels).
- Limitation taille payload JSON (protection simple).
## 3.3. Script client
- Mode “dry-run” (afficher JSON sans lenvoyer).
- Mode “debug” (log détaillé des commandes).
---
# 4. Phase 3 Historisation avancée & graphes
## 4.1. Graphes dans la WebUI
- Sur page device :
- Graphique du **global_score** sur le temps.
- Graphiques séparés :
- CPU score vs temps
- Mémoire score vs temps
- Disque score vs temps
- Réseau score vs temps
- Lib JS possible :
- Chart.js ou ECharts (simple, self-hosté).
## 4.2. Comparaison de benchmarks
- Comparer 2 benchmarks dun même device :
- Afficher les différences (avant/après ajout RAM, changement SSD…).
- Comparer 2 devices :
- Table des scores côte-à-côte.
- Exemple dusage :
- “Quelle machine est la meilleure candidate pour un nouveau service Docker ?”
---
# 5. Phase 4 Détection de régressions & alertes
## 5.1. Détection automatique
- Calcul dun “baseline” par device :
- par exemple moyenne des N meilleurs scores.
- Lors dun nouveau bench :
- si le score est inférieur de X% à la baseline → marquer en **WARNING**.
- Indicateurs :
- CPU plus lent
- Disque sensiblement plus lent (fragilité SSD/HDD)
- Réseau plus lent (câble / switch / config ?)
## 5.2. Alertes
- Marquage visuel dans la WebUI (icône warning).
- Export JSON ou webhook Webhook simple :
- POST vers un endpoint externe (ex: Home Assistant, Node-RED, etc.)
- Intégration possible :
- Appel HTTP vers Home Assistant pour créer une notification.
---
# 6. Phase 5 Intégrations externes
## 6.1. Intégration Gitea / Git
- Stocker le dépôt `bench.sh` dans une forge (déjà le cas).
- Ajouter :
- Liens vers la version exacte du script qui a généré tel bench.
- Option :
- Webhook Gitea → déclencher bench sur un device après un changement de config.
## 6.2. Intégration Home Assistant
- Exposer certains indicateurs via une API ou MQTT :
- Dernier score par device
- Warn/alert sur régression
- Dashboard HA :
- Carte des machines avec état “OK / Warning / Error”.
## 6.3. Intégration Prometheus / Grafana (option)
- Exporter métriques (nombre de devices, benchs, scores moyens) via `/metrics`.
- Visualisation dans Grafana.
---
# 7. Phase 6 Extensions techniques
## 7.1. Support multi-OS
- Extension `bench.sh` pour :
- Linux non-Debian (Arch, Fedora)
- macOS (optionnel)
- Windows (PowerShell script séparé)
## 7.2. Agents “semi-persistants”
- Mode où un service systemd sur certains serveurs :
- exécute un bench toutes les X semaines.
- envoie automatiquement les données au backend.
## 7.3. Export / Import
- Export complet de :
- devices
- benchmarks
- hardware_snapshots
- Formats :
- JSON
- CSV (pour certains tableaux)
- Import depuis un ancien fichier → migration facile vers nouvelle instance.
---
# 8. Phase 7 UX & ergonomie avancées
- Tags et “groupes” de devices (ex: “serveurs prod”, “lab”, “RPi”, “Proxmox nodes”).
- Vues filtrées :
- Vue “serveurs”
- Vue “VM Proxmox”
- Vue “SBC (RPi, OPi, etc.)”
- Possibilité de nommer des “profils” :
- ex: “Profil NVR”, “Profil VM/Proxmox”, “Profil PC Gaming”
- et voir les devices qui matchent le mieux chaque profil en fonction de leur score.
---
# 9. Idées long terme (si tu veux pousser très loin)
- Auto-détection hardware via une petite API agent qui tourne sur les machines en continu (au-delà du script ponctuel).
- Benchmark réseau multi-nœuds :
- topologie logical de ton réseau
- latences et débits entre plusieurs points.
- Vue “Carte du réseau” :
- affichage graphique des performances entre différentes machines.
- Plugins :
- Ajouter une API plugin pour créer ses propres tests (ex: bench spécifique Docker, base de données, etc.).
---
# 10. Priorisation suggérée
1. **Stabiliser MVP** (Phase 1 + tests fichier 09)
2. UX de base + tri / filtre (Phase 2)
3. Graphes dhistorique (Phase 3)
4. Détection régressions + petites alertes (Phase 4)
5. Intégrations Home Assistant / Prometheus (Phase 5)
6. Support multi-OS (Phase 6)
7. Développements avancés (Phase 7+8)
---
# 11. TODO résumé par phase
- Phase 1 :
- Implémenter API, DB, bench.sh, WebUI minimal, Docker, install.sh
- Phase 2 :
- Tri, filtres, ergonomie
- Phase 3 :
- Graphes (global_score, composantes)
- Phase 4 :
- Baselines, détection de régression, marquage visuel
- Phase 5 :
- Webhooks / MQTT / intégration HA
- Phase 6 :
- Scripts bench pour autres OS
- Phase 7 :
- Vues avancées, cartes réseau, plugins
Ce document pourra servir de base à un Kanban (Gitea, Kanboard, etc.) en créant une tâche par élément de la roadmap.