[IMP] script todo: suivi install — colonne « Odoo » (état :8069)
Nouvelle colonne « Odoo » dans le dashboard : teste par TCP si l'UI web répond sur le port 8069 de la VM (🟢 up / — sinon). Une fois « up » détecté, on ne re-teste plus (Odoo ne redescend pas en cours d'install). Le test (socket, timeout 0,5 s) est fait dans le thread collecteur -> n'impacte pas la fluidité de l'UI. Validé headless : port ouvert -> 🟢, fermé -> —. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1ebf2b353f
commit
7904c72d71
1 changed files with 34 additions and 4 deletions
|
|
@ -18,6 +18,7 @@ import json
|
|||
import os
|
||||
import shlex
|
||||
import shutil
|
||||
import socket
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
|
@ -280,6 +281,17 @@ def scan_log_errors(log_path: str) -> tuple[int, int]:
|
|||
return nerr, nwarn
|
||||
|
||||
|
||||
def _port_open(ip: str, port: int = 8069, timeout: float = 0.5) -> bool:
|
||||
"""Vrai si un TCP connect réussit (l'UI web Odoo écoute sur :8069)."""
|
||||
if not ip:
|
||||
return False
|
||||
try:
|
||||
with socket.create_connection((ip, port), timeout=timeout):
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def _read_new(path: str, offset: int) -> tuple[str, int]:
|
||||
"""Lit le log à partir de `offset` (lecture incrémentale). Renvoie
|
||||
(nouveau_texte, nouvel_offset). Bloquant -> à appeler dans un thread."""
|
||||
|
|
@ -645,6 +657,9 @@ def run_monitor(manifest_path: str, run_app: bool = True):
|
|||
self._errcount = {}
|
||||
# Sommaire de stats déplié (clic) ou non.
|
||||
self._stats_open = False
|
||||
# VM dont l'UI Odoo (:8069) répond déjà : une fois détectée « up »,
|
||||
# on ne re-teste plus (Odoo ne redescend pas en cours d'install).
|
||||
self._odoo_up = set()
|
||||
# Debounce du changement de VM : la sélection défile vite au
|
||||
# clavier ; on ne recharge le log qu'une fois le curseur STABILISÉ.
|
||||
self._pending_sel = None
|
||||
|
|
@ -673,11 +688,13 @@ def run_monitor(manifest_path: str, run_app: bool = True):
|
|||
table.add_column("VM", key="vm", width=26)
|
||||
table.add_column("⚠", key="err", width=4)
|
||||
table.add_column("État", key="state", width=12)
|
||||
# « Odoo » : l'UI web répond-elle sur :8069 ? (🟢 up / — down)
|
||||
table.add_column("Odoo", key="odoo", width=6)
|
||||
table.add_column("Durée", key="elapsed", width=7)
|
||||
table.add_column("Disque", key="disk", width=8)
|
||||
for vm in vms:
|
||||
table.add_row(
|
||||
vm["name"], "", "⏳", "--:--", "-", key=vm["name"]
|
||||
vm["name"], "", "⏳", "—", "--:--", "-", key=vm["name"]
|
||||
)
|
||||
# max_lines borne la mémoire/rendu (un install verbeux × 30 VM).
|
||||
self._log = RichLog(
|
||||
|
|
@ -769,7 +786,7 @@ def run_monitor(manifest_path: str, run_app: bool = True):
|
|||
def _collect_table(self):
|
||||
"""(THREAD) statut + taille disque de chaque VM + télémétrie. AUCUNE
|
||||
mise à jour d'UI ici : uniquement des I/O bloquantes déportées."""
|
||||
disks, status, errors = {}, {}, {}
|
||||
disks, status, errors, odoo = {}, {}, {}, {}
|
||||
for vm in vms:
|
||||
name = vm["name"]
|
||||
disks[name] = _fmt_size(disk_actual_size(vm_disk_path(vm)))
|
||||
|
|
@ -784,19 +801,27 @@ def run_monitor(manifest_path: str, run_app: bool = True):
|
|||
# peut contenir des erreurs passées inaperçues.
|
||||
if st[0] in ("done", "failed") and name not in errors:
|
||||
errors[name] = scan_log_errors(vm["log"])
|
||||
return disks, status, self._collect_tele(), errors
|
||||
# Odoo up ? On ne teste que celles pas encore confirmées up
|
||||
# et non effacées (test TCP court sur :8069).
|
||||
if name not in self._odoo_up and self._domstate.get(
|
||||
name
|
||||
) != "gone":
|
||||
if _port_open(vm.get("ip"), 8069):
|
||||
odoo[name] = True
|
||||
return disks, status, self._collect_tele(), errors, odoo
|
||||
|
||||
async def _tick_table(self):
|
||||
# I/O (lectures de logs, stat disque, /proc) DÉPORTÉES en thread ->
|
||||
# la boucle d'événements Textual reste fluide même sous forte
|
||||
# charge ou disque lent. Les mises à jour d'UI restent sur la boucle.
|
||||
try:
|
||||
disks, status, tele, errors = await asyncio.to_thread(
|
||||
disks, status, tele, errors, odoo = await asyncio.to_thread(
|
||||
self._collect_table
|
||||
)
|
||||
except Exception:
|
||||
return
|
||||
self._errcount.update(errors)
|
||||
self._odoo_up.update(odoo)
|
||||
try:
|
||||
table = self.query_one("#vms", DataTable)
|
||||
now = time.time()
|
||||
|
|
@ -804,6 +829,11 @@ def run_monitor(manifest_path: str, run_app: bool = True):
|
|||
for vm in vms:
|
||||
name = vm["name"]
|
||||
self._set_cell(table, name, "disk", disks.get(name, "-"))
|
||||
# Colonne Odoo : 🟢 dès que :8069 répond, sinon « — ».
|
||||
self._set_cell(
|
||||
table, name, "odoo",
|
||||
"🟢" if name in self._odoo_up else "—",
|
||||
)
|
||||
if name in self._final:
|
||||
continue
|
||||
ds = self._domstate.get(name)
|
||||
|
|
|
|||
Loading…
Reference in a new issue