[IMP] qemu: table lisible/scrollable, guest-exec autorisé, service Odoo, choix navigateur
Suivi d'installation (qemu_install_monitor.py) :
- Table VM/État LISIBLE : largeurs de colonnes fixes (VM 26, ⚠ 4, État 12,
Durée 7, Disque 8) -> l'État n'est plus tronqué à 3-4 caractères
(« ❌ effacée », « ⏸ en pause » lisibles) ; table défilable (overflow-x,
height 1fr) pour les longs noms et les gros parcs.
- « w » web : offre désormais la LISTE des navigateurs CLI installés
(_choose_browser) pour choisir lequel utiliser, + option [i] installer.
Déploiement (deploy_qemu.py) :
- guest-exec AUTORISÉ : on vide la liste de blocage de qemu-ga
(block-rpcs/blacklist vides — pas allow-rpcs qui est une liste BLANCHE et
casserait les autres RPC), + neutralise /etc/sysconfig/qemu-ga (Fedora).
Installation (todo.py) :
- Profils AVEC Odoo (install_odoo*) UNIQUEMENT : Odoo est enregistré comme
service systemd (erplibre.service, inspiré de script/systemd/
install_daemon.sh) puis enable --now. Pas pour ERPLibre seul / mobile /
Déploiement.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ab8bfec113
commit
8278c38f46
3 changed files with 98 additions and 17 deletions
|
|
@ -978,8 +978,23 @@ def build_cloud_config(
|
|||
" qemu-guest-agent) || (command -v dnf >/dev/null && dnf install -y"
|
||||
" qemu-guest-agent) || (command -v pacman >/dev/null && pacman -S"
|
||||
" --noconfirm qemu-guest-agent) || true",
|
||||
" - systemctl enable --now qemu-guest-agent 2>/dev/null"
|
||||
" || systemctl enable --now qemu-ga 2>/dev/null || true",
|
||||
# Autorise guest-exec (bloqué par défaut sur certaines distros).
|
||||
# On VIDE la liste de blocage (block-rpcs/blacklist) plutôt que
|
||||
# d'utiliser allow-rpcs (liste BLANCHE : casserait les autres RPC).
|
||||
# Les deux clés couvrent les versions anciennes (blacklist) et
|
||||
# récentes (block-rpcs) de qemu-ga.
|
||||
" - mkdir -p /etc/qemu && printf '[general]\\nblock-rpcs=\\n"
|
||||
"blacklist=\\n' > /etc/qemu/qemu-ga.conf || true",
|
||||
# Fedora/RHEL bloquent guest-exec via /etc/sysconfig/qemu-ga.
|
||||
" - [ -f /etc/sysconfig/qemu-ga ] && sed -i"
|
||||
" 's/^BLACKLIST_RPC=.*/BLACKLIST_RPC=/'"
|
||||
" /etc/sysconfig/qemu-ga || true",
|
||||
" - systemctl enable qemu-guest-agent 2>/dev/null"
|
||||
" || systemctl enable qemu-ga 2>/dev/null || true",
|
||||
# restart (et non enable --now) : recharge la config si l'agent était
|
||||
# déjà démarré par l'image cloud.
|
||||
" - systemctl restart qemu-guest-agent 2>/dev/null"
|
||||
" || systemctl restart qemu-ga 2>/dev/null || true",
|
||||
]
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ def run_monitor(manifest_path: str, run_app: bool = True):
|
|||
|
||||
class Monitor(App):
|
||||
CSS = """
|
||||
DataTable { width: 58; border: solid $accent; }
|
||||
DataTable { width: 74; height: 1fr; overflow-x: auto; border: solid $accent; }
|
||||
RichLog { border: solid $accent; }
|
||||
#telemetry { height: 1; color: $text-muted; }
|
||||
#stats { height: 1; color: $accent; }
|
||||
|
|
@ -526,11 +526,14 @@ def run_monitor(manifest_path: str, run_app: bool = True):
|
|||
table = DataTable(id="vms", cursor_type="row")
|
||||
# Clés de colonnes explicites : update_cell() les référence.
|
||||
# La colonne « ⚠ » (erreurs détectées) est à GAUCHE d'« État ».
|
||||
table.add_column("VM", key="vm")
|
||||
table.add_column("⚠", key="err")
|
||||
table.add_column("État", key="state")
|
||||
table.add_column("Durée", key="elapsed")
|
||||
table.add_column("Disque", key="disk")
|
||||
# Largeurs FIXES pour les colonnes courtes -> l'État n'est plus
|
||||
# tronqué (« ❌ effacée », « ⏸ en pause » lisibles) ; la table
|
||||
# défile horizontalement (overflow-x) pour les noms de VM longs.
|
||||
table.add_column("VM", key="vm", width=26)
|
||||
table.add_column("⚠", key="err", width=4)
|
||||
table.add_column("État", key="state", width=12)
|
||||
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"]
|
||||
|
|
@ -835,16 +838,9 @@ def run_monitor(manifest_path: str, run_app: bool = True):
|
|||
if not vm or not vm.get("ip"):
|
||||
self.notify("Pas d'IP pour cette VM.", title="Web")
|
||||
return
|
||||
browser = cli_browser()
|
||||
browser = self._choose_browser()
|
||||
if not browser:
|
||||
browser = self._install_cli_browser()
|
||||
if not browser:
|
||||
self.notify(
|
||||
"Aucun navigateur CLI disponible.",
|
||||
title="Web",
|
||||
severity="warning",
|
||||
)
|
||||
return
|
||||
return
|
||||
url = f"http://{vm['ip']}:8069"
|
||||
with self.suspend():
|
||||
print(f"→ {browser} {url}")
|
||||
|
|
@ -863,6 +859,40 @@ def run_monitor(manifest_path: str, run_app: bool = True):
|
|||
except EOFError:
|
||||
pass
|
||||
|
||||
def _choose_browser(self):
|
||||
"""Offre la LISTE des navigateurs CLI installés et laisse choisir
|
||||
lequel utiliser pour voir la page. Si aucun n'est installé, propose
|
||||
d'en installer un. Renvoie le binaire choisi, ou None."""
|
||||
available = [b for b in CLI_BROWSERS if shutil.which(b)]
|
||||
if not available:
|
||||
browser = self._install_cli_browser()
|
||||
if not browser:
|
||||
self.notify(
|
||||
"Aucun navigateur CLI disponible.",
|
||||
title="Web",
|
||||
severity="warning",
|
||||
)
|
||||
return browser
|
||||
with self.suspend():
|
||||
print("Quel navigateur utiliser pour voir la page ?")
|
||||
for i, b in enumerate(available, 1):
|
||||
print(f" [{i}] {b}{' *' if i == 1 else ''}")
|
||||
print(" [i] Installer un autre navigateur")
|
||||
sel = input(
|
||||
f"Choix (numéro, vide = {available[0]}) : "
|
||||
).strip().lower()
|
||||
if sel == "i":
|
||||
return self._install_cli_browser()
|
||||
if not sel:
|
||||
return available[0]
|
||||
try:
|
||||
idx = int(sel) - 1
|
||||
if 0 <= idx < len(available):
|
||||
return available[idx]
|
||||
except ValueError:
|
||||
pass
|
||||
return available[0]
|
||||
|
||||
def _install_cli_browser(self):
|
||||
"""Demande QUEL navigateur CLI installer (w3m/lynx/links/elinks),
|
||||
affiche la commande, l'exécute après validation. Renvoie le binaire
|
||||
|
|
|
|||
|
|
@ -2533,12 +2533,48 @@ class TODO:
|
|||
pass
|
||||
return profiles[0] # défaut : ERPLibre + Odoo 18
|
||||
|
||||
@staticmethod
|
||||
def _qemu_odoo_service_cmd():
|
||||
"""Snippet shell (exécuté dans la VM) qui installe ERPLibre/Odoo comme
|
||||
service systemd (inspiré de script/systemd/install_daemon.sh) puis
|
||||
l'active + démarre. N'est ajouté QUE pour les profils avec Odoo."""
|
||||
return (
|
||||
'SVC_USER=$(whoami); SVC_GROUP=$(id -gn); '
|
||||
'SVC_DIR="$HOME/git/erplibre"; '
|
||||
"sudo tee /etc/systemd/system/erplibre.service >/dev/null <<UNIT\n"
|
||||
"[Unit]\n"
|
||||
"Description=ERPLibre\n"
|
||||
"Requires=postgresql.service\n"
|
||||
"After=network.target network-online.target postgresql.service\n"
|
||||
"\n"
|
||||
"[Service]\n"
|
||||
"Type=simple\n"
|
||||
"User=$SVC_USER\n"
|
||||
"Group=$SVC_GROUP\n"
|
||||
"Restart=always\n"
|
||||
"RestartSec=5\n"
|
||||
"ExecStart=$SVC_DIR/run.sh\n"
|
||||
"WorkingDirectory=$SVC_DIR\n"
|
||||
"StandardOutput=journal+console\n"
|
||||
"\n"
|
||||
"[Install]\n"
|
||||
"WantedBy=multi-user.target\n"
|
||||
"UNIT\n"
|
||||
"sudo systemctl daemon-reload; "
|
||||
"sudo systemctl enable --now erplibre.service"
|
||||
)
|
||||
|
||||
def _qemu_erplibre_remote_cmd(self, branch, final_cmd=None):
|
||||
"""Script d'installation ERPLibre exécuté DANS la VM (curl/git/make
|
||||
puis clone + `final_cmd` dans ~/git/erplibre). `final_cmd` par défaut :
|
||||
install_os + install_odoo_18."""
|
||||
if not final_cmd:
|
||||
final_cmd = f"make install_os && make {self.ERPLIBRE_ODOO_TARGET}"
|
||||
# Profils AVEC Odoo (install_odoo*) uniquement : après l'install, on
|
||||
# enregistre Odoo comme service systemd (enable + start). Pas pour
|
||||
# « ERPLibre seul », « mobile » ni « Déploiement ».
|
||||
if "install_odoo" in final_cmd:
|
||||
final_cmd = f"{final_cmd} && {self._qemu_odoo_service_cmd()}"
|
||||
return (
|
||||
"set -e; "
|
||||
# Attendre la FIN de cloud-init : pendant sa phase « paquets » il
|
||||
|
|
|
|||
Loading…
Reference in a new issue