maj
This commit is contained in:
122
docs/01_vision_fonctionnelle.md
Normal file
122
docs/01_vision_fonctionnelle.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# 01 – Vision fonctionnelle et objectifs
|
||||
|
||||
## Nom de l’application
|
||||
|
||||
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
|
||||
|
||||
L’application 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 l’interface.
|
||||
- Visualiser l’historique des benchmarks d’une 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 d’un bench).
|
||||
- Lire les infos d’un 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 d’un JSON produit par un script Bash exécuté sur la machine.
|
||||
- Enregistrement d’un `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 d’accueil :
|
||||
- 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 n’est pas un outil de supervision).
|
||||
- Pas de support Windows/macOS dans la première version (Linux seulement).
|
||||
- Pas d’agent 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 l’app via `docker-compose up -d`.
|
||||
- Copier une commande depuis le Dashboard, l’exécuter sur une machine Linux, et voir :
|
||||
- Le device apparaître (ou se mettre à jour).
|
||||
- Un nouveau benchmark visible dans l’interface.
|
||||
- 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 l’interface.
|
||||
242
docs/02_model_donnees.md
Normal file
242
docs/02_model_donnees.md
Normal 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 d’ensemble
|
||||
|
||||
Tables principales :
|
||||
- `devices`
|
||||
- `hardware_snapshots`
|
||||
- `benchmarks`
|
||||
- `manufacturer_links`
|
||||
- `documents`
|
||||
|
||||
Optionnel (plus tard) :
|
||||
- `users` (si auth interne)
|
||||
- `settings` (config globale de l’app)
|
||||
|
||||
---
|
||||
|
||||
## 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` n’est 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 d’un 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 d’exé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 l’application.
|
||||
|
||||
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
537
docs/03_api_backend.md
Normal 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.
|
||||
|
||||
L’API 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 d’un benchmark.
|
||||
- Consultation des devices.
|
||||
- Consultation de l’historique des benchmarks.
|
||||
- Gestion des liens constructeur.
|
||||
- Gestion des documents (PDF, images).
|
||||
3. Les règles d’authentification (token simple).
|
||||
4. Les codes d’erreur principaux et attentes de validation.
|
||||
|
||||
---
|
||||
|
||||
## 2. Schéma JSON – payload d’un 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 à l’absence 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 d’un 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 d’un 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 d’entré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 d’un 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 l’historique de benchmarks d’un 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 d’un 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 : l’objet 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 d’env `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 d’erreur 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 l’origine (IP) des appels `POST /api/benchmark`.
|
||||
|
||||
---
|
||||
475
docs/04_bench_script_client.md
Normal file
475
docs/04_bench_script_client.md
Normal 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 l’endpoint backend `POST /api/benchmark`.
|
||||
|
||||
- `--token <TOKEN>` (obligatoire)
|
||||
Token d’authentification à 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 d’aide 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 l’OS.
|
||||
- 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 l’OS et préparer la commande d’installation 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 d’entrées `Locator` dans `dmidecode` (type DIMM).
|
||||
- `slots_used` : slots où `Size` n’est pas `No Module Installed`.
|
||||
- `ecc` : champ `Total Width` vs `Data Width` ou `Error Correction Type`.
|
||||
- `layout` : tableau d’objets 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 d’objets :
|
||||
- `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 d’objets :
|
||||
- `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 d’objets :
|
||||
- `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 l’instant, 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 d’erreur (console).
|
||||
- Optionnel : afficher `/tmp/bench_response.txt`.
|
||||
|
||||
- Si succès :
|
||||
- Afficher un message confirmant l’ID 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. < 5–10 minutes en mode complet, < 2–3 minutes en mode `--short`).
|
||||
192
docs/05_webui_design.md
Normal file
192
docs/05_webui_design.md
Normal file
@@ -0,0 +1,192 @@
|
||||
|
||||
# 05 – Design WebUI (structure, pages, composants)
|
||||
|
||||
Objectif : définir l’interface utilisateur de Linux BenchTools, les pages, les composants, l’organisation 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**
|
||||
- 0–50 : rouge
|
||||
- 51–75 : orange
|
||||
- 76–100 : 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: 2025‑12‑07 |
|
||||
+---------------------------------------------------------------------------+
|
||||
| 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 i7‑6700 (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: 2025‑12‑07 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
|
||||
216
docs/06_backend_architecture.md
Normal file
216
docs/06_backend_architecture.md
Normal 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 d’un 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 d’un hardware snapshot
|
||||
6. Création d’un 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
|
||||
|
||||
238
docs/08_installation_bootstrap.md
Normal file
238
docs/08_installation_bootstrap.md
Normal file
@@ -0,0 +1,238 @@
|
||||
|
||||
# 08 – Script d'installation & Bootstrapping (install.sh)
|
||||
|
||||
Objectif : fournir un guide exhaustif et un script d’installation automatisée de l’application
|
||||
**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
|
||||
- L’installation via Docker ou native
|
||||
- La génération automatique de l’arborescence
|
||||
- Les variables d’environnement 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 l’application fonctionne via un health check
|
||||
8. Afficher les URL utiles et les commandes d’usage
|
||||
|
||||
---
|
||||
|
||||
# 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 d’installation Debian/Ubuntu).
|
||||
|
||||
Exemple :
|
||||
|
||||
```bash
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "[ERREUR] Docker n’est 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 l’installation
|
||||
|
||||
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 d’un certificat TLS
|
||||
|
||||
263
docs/09_tests_qualite.md
Normal file
263
docs/09_tests_qualite.md
Normal 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 l’application
|
||||
(backend, script bench, frontend), afin d’assurer 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 l’API
|
||||
- UX minimale (lisibilité, tri, navigation)
|
||||
4. **Tests de bout en bout (E2E)**
|
||||
- Exécution complète d’un 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 d’intégration** : endpoints FastAPI avec base SQLite de test.
|
||||
- **Tests E2E API** : envoi d’un 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 d’installation 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 d’options
|
||||
|
||||
- `--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 d’erreur 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 l’application.
|
||||
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 d’un 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 d’un 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 d’un device.
|
||||
2. Ajouter un lien avec label + URL.
|
||||
3. Vérifier qu’il est cliquable.
|
||||
4. Tester suppression.
|
||||
|
||||
---
|
||||
|
||||
# 5. Tests E2E (de bout en bout)
|
||||
|
||||
Objectif : couvrir la chaîne complète depuis la machine cliente jusqu’au 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) qu’un 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 d’un 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 d’un backend en mode test
|
||||
3. Envoi d’un payload JSON factice
|
||||
4. Vérification de la réponse HTTP
|
||||
|
||||
---
|
||||
|
||||
# 8. Critères de qualité
|
||||
|
||||
L’application 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 d’auth/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 d’un badge “build/test status” dans le README principal
|
||||
216
docs/10_roadmap_evolutions.md
Normal file
216
docs/10_roadmap_evolutions.md
Normal file
@@ -0,0 +1,216 @@
|
||||
|
||||
# 10 – Roadmap & évolutions futures pour Linux BenchTools
|
||||
|
||||
Objectif : lister les évolutions possibles de l’application, 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 d’aide à 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 d’installation (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 d’icô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 l’envoyer).
|
||||
- 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 d’un 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 d’usage :
|
||||
- “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 d’un “baseline” par device :
|
||||
- par exemple moyenne des N meilleurs scores.
|
||||
- Lors d’un 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 d’historique (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.
|
||||
Reference in New Issue
Block a user