[IMP] script todo: QEMU — rouvrir le suivi d'installation (dernier run / historique)
Si le dashboard se ferme (bug, sortie), on peut désormais le ROUVRIR sur un
run passé pour reprendre l'analyse. Nouvelle entrée [11] du menu QEMU :
« 📈 Rouvrir le suivi d'installation (dernier run / historique) ».
- mon.list_install_runs() : liste les runs (~/.erplibre/qemu-install/*/
session.json) triés du plus récent au plus ancien.
- _qemu_reopen_monitor : affiche l'historique (VM par run), choix (défaut =
le dernier), puis run_monitor(session.json) rouvre le dashboard.
- « Lister les images » passe de [11] à [12] ; config -> 13+.
Validé : 20 runs listés, dashboard reconstruit (titre + 5 VM) depuis un
session.json passé.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4f0c3cd217
commit
0b02e9fe43
3 changed files with 95 additions and 0 deletions
|
|
@ -44,6 +44,34 @@ def session_dir() -> Path:
|
||||||
return base
|
return base
|
||||||
|
|
||||||
|
|
||||||
|
def list_install_runs() -> list:
|
||||||
|
"""Runs d'installation passés (chacun a un session.json), TRIÉS du plus
|
||||||
|
récent au plus ancien. Chaque entrée : dict {label, manifest, mtime,
|
||||||
|
vms, branch}. Permet de ROUVRIR le suivi d'un run (le dashboard s'étant
|
||||||
|
fermé sur un bug, on reprend l'analyse)."""
|
||||||
|
runs = []
|
||||||
|
for d in sorted(session_dir().glob("*/"), reverse=True):
|
||||||
|
manifest = d / "session.json"
|
||||||
|
if not manifest.is_file():
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
data = json.loads(manifest.read_text())
|
||||||
|
mtime = manifest.stat().st_mtime
|
||||||
|
except (OSError, ValueError):
|
||||||
|
continue
|
||||||
|
runs.append(
|
||||||
|
{
|
||||||
|
"label": d.name.rstrip("/"),
|
||||||
|
"manifest": str(manifest),
|
||||||
|
"mtime": mtime,
|
||||||
|
"vms": data.get("vms", []),
|
||||||
|
"branch": data.get("branch", ""),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
runs.sort(key=lambda r: r["mtime"], reverse=True)
|
||||||
|
return runs
|
||||||
|
|
||||||
|
|
||||||
def _launch_one(ip: str, remote_cmd: str, log_path: str) -> None:
|
def _launch_one(ip: str, remote_cmd: str, log_path: str) -> None:
|
||||||
"""Lance une install SSH DÉTACHÉE : attend le sshd, exécute, journalise
|
"""Lance une install SSH DÉTACHÉE : attend le sshd, exécute, journalise
|
||||||
la sortie puis écrit le marqueur de fin avec le code de sortie."""
|
la sortie puis écrit le marqueur de fin avec le code de sortie."""
|
||||||
|
|
|
||||||
|
|
@ -1087,6 +1087,11 @@ class TODO:
|
||||||
"Test a VM (open Odoo in a CLI browser)"
|
"Test a VM (open Odoo in a CLI browser)"
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"prompt_description": t(
|
||||||
|
"Reopen install monitoring (last run / history)"
|
||||||
|
)
|
||||||
|
},
|
||||||
{"section": t("Catalog")},
|
{"section": t("Catalog")},
|
||||||
{"prompt_description": t("List available images and specs")},
|
{"prompt_description": t("List available images and specs")},
|
||||||
]
|
]
|
||||||
|
|
@ -1121,6 +1126,8 @@ class TODO:
|
||||||
elif status == "10":
|
elif status == "10":
|
||||||
self._qemu_test_vm()
|
self._qemu_test_vm()
|
||||||
elif status == "11":
|
elif status == "11":
|
||||||
|
self._qemu_reopen_monitor()
|
||||||
|
elif status == "12":
|
||||||
self._qemu_list_images()
|
self._qemu_list_images()
|
||||||
else:
|
else:
|
||||||
cmd_no_found = True
|
cmd_no_found = True
|
||||||
|
|
@ -1383,6 +1390,46 @@ class TODO:
|
||||||
)
|
)
|
||||||
print(f"⚠ {msg}")
|
print(f"⚠ {msg}")
|
||||||
|
|
||||||
|
def _qemu_reopen_monitor(self):
|
||||||
|
"""Rouvre le suivi d'installation (dashboard) sur un run PASSÉ : le
|
||||||
|
dernier par défaut, ou un choix dans l'historique. Utile quand le
|
||||||
|
dashboard s'est fermé et qu'on veut reprendre l'analyse."""
|
||||||
|
from script.todo import qemu_install_monitor as mon
|
||||||
|
|
||||||
|
runs = mon.list_install_runs()
|
||||||
|
if not runs:
|
||||||
|
print(t("No install run found in history."))
|
||||||
|
return
|
||||||
|
print(f"\n{t('Install runs (most recent first):')}")
|
||||||
|
for i, r in enumerate(runs, 1):
|
||||||
|
names = ", ".join(v.get("name", "?") for v in r["vms"])
|
||||||
|
star = " *" if i == 1 else ""
|
||||||
|
print(
|
||||||
|
f" [{i}] {r['label']} — {len(r['vms'])} VM{star}\n"
|
||||||
|
f" {names}"
|
||||||
|
)
|
||||||
|
sel = input(
|
||||||
|
t("Choice (number, blank = last): ")
|
||||||
|
).strip()
|
||||||
|
run = runs[0]
|
||||||
|
if sel:
|
||||||
|
try:
|
||||||
|
idx = int(sel) - 1
|
||||||
|
if 0 <= idx < len(runs):
|
||||||
|
run = runs[idx]
|
||||||
|
else:
|
||||||
|
print(t("Invalid selection."))
|
||||||
|
return
|
||||||
|
except ValueError:
|
||||||
|
print(t("Invalid selection."))
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
mon.run_monitor(run["manifest"])
|
||||||
|
except ImportError:
|
||||||
|
print(t("Install textual for the dashboard (pip)."))
|
||||||
|
except Exception as exc:
|
||||||
|
print(f"{t('Command failed: ')}{exc}")
|
||||||
|
|
||||||
def _qemu_choose_cli_browser(self):
|
def _qemu_choose_cli_browser(self):
|
||||||
"""Offre la LISTE des navigateurs CLI installés, plus une option pour
|
"""Offre la LISTE des navigateurs CLI installés, plus une option pour
|
||||||
en INSTALLER un autre, et renvoie celui choisi, sinon None."""
|
en INSTALLER un autre, et renvoie celui choisi, sinon None."""
|
||||||
|
|
|
||||||
|
|
@ -1488,6 +1488,26 @@ TRANSLATIONS = {
|
||||||
"fr": "🧪 Tester une VM (ouvrir Odoo dans un navigateur CLI)",
|
"fr": "🧪 Tester une VM (ouvrir Odoo dans un navigateur CLI)",
|
||||||
"en": "🧪 Test a VM (open Odoo in a CLI browser)",
|
"en": "🧪 Test a VM (open Odoo in a CLI browser)",
|
||||||
},
|
},
|
||||||
|
"Reopen install monitoring (last run / history)": {
|
||||||
|
"fr": "📈 Rouvrir le suivi d'installation (dernier run / historique)",
|
||||||
|
"en": "📈 Reopen install monitoring (last run / history)",
|
||||||
|
},
|
||||||
|
"No install run found in history.": {
|
||||||
|
"fr": "Aucun run d'installation dans l'historique.",
|
||||||
|
"en": "No install run found in history.",
|
||||||
|
},
|
||||||
|
"Install runs (most recent first):": {
|
||||||
|
"fr": "Runs d'installation (du plus récent) :",
|
||||||
|
"en": "Install runs (most recent first):",
|
||||||
|
},
|
||||||
|
"Choice (number, blank = last): ": {
|
||||||
|
"fr": "Choix (numéro, vide = le dernier) : ",
|
||||||
|
"en": "Choice (number, blank = last): ",
|
||||||
|
},
|
||||||
|
"Invalid selection.": {
|
||||||
|
"fr": "Sélection invalide.",
|
||||||
|
"en": "Invalid selection.",
|
||||||
|
},
|
||||||
"Resolving VM IP...": {
|
"Resolving VM IP...": {
|
||||||
"fr": "Résolution de l'IP de la VM…",
|
"fr": "Résolution de l'IP de la VM…",
|
||||||
"en": "Resolving VM IP...",
|
"en": "Resolving VM IP...",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue