[IMP] script todo: QEMU [4] — choix infos avancées OU changer l'état de VM

Après « virsh list --all », le menu propose désormais :
  [1] Infos avancées (vCPU, RAM, disque)
  [2] Changer l'état d'une ou plusieurs VM
  [Entrée] Rien

Changement d'état (_qemu_change_state) :
- Saisie d'une liste de VM séparée par des virgules (noms ou ID, résolus
  via _qemu_domname et validés contre les VM existantes).
- Choix de l'état cible : Ouvrir (start) ou Fermer (shutdown).
- DOUBLE validation (« Appliquer : … ? » puis « Confirmer pour de vrai ? »)
  avant d'exécuter virsh start/shutdown sur chaque VM.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mathieu Benoit 2026-07-29 11:09:40 +00:00
parent 22dcf96853
commit 4bebf5a397
2 changed files with 126 additions and 3 deletions

View file

@ -1134,10 +1134,69 @@ class TODO:
cmd = "sudo virsh list --all"
print(f"{t('Will execute:')} {cmd}")
self.execute.exec_command_live(cmd, source_erplibre=False)
if ask_advanced and self._is_yes(
input(t("Show advanced info (vCPU, RAM, disk)? (y/N): "))
):
if not ask_advanced:
return
# Menu contextuel : infos avancées, ou changer l'état de VM.
print(f"\n{t('What do you want to do?')}")
print(f" [1] {t('Advanced info (vCPU, RAM, disk)')}")
print(f" [2] {t('Change the state of one or more VMs')}")
print(f" [{t('Enter')}] {t('Nothing')}")
choice = input(t("Choice: ")).strip()
if choice == "1":
self._qemu_list_vms_advanced()
elif choice == "2":
self._qemu_change_state()
def _qemu_change_state(self):
"""Démarre (« ouvrir ») ou éteint (« fermer ») une liste de VM saisie
séparée par des virgules, avec DOUBLE validation."""
names = self._qemu_list_domains()
if not names:
print(f"\n{t('No VM found.')}")
return
print(f"\n{t('Available VMs:')} {', '.join(names)}")
raw = input(t("VMs to change (comma-separated): ")).strip()
targets = [n.strip() for n in raw.split(",") if n.strip()]
if not targets:
print(t("Nothing selected."))
return
# Résoudre les ID -> noms et valider l'existence.
resolved, unknown = [], []
known = set(names)
for tgt in targets:
real = self._qemu_domname(tgt)
(resolved if real in known else unknown).append(real)
if unknown:
print(f"{t('Unknown VM(s):')} {', '.join(unknown)}")
return
# Choix de l'état cible : ouvrir (démarrer) ou fermer (éteindre).
print(f"\n{t('Target state:')}")
print(f" [1] {t('Open (start)')}")
print(f" [2] {t('Close (shut down)')}")
st = input(t("Choice: ")).strip()
if st == "1":
action, verb = "start", t("start")
elif st == "2":
action, verb = "shutdown", t("shut down")
else:
print(t("Cancelled."))
return
# DOUBLE validation avant d'appliquer.
summary = f"{verb} -> {', '.join(resolved)}"
if not self._is_yes(
input(f"{t('Apply:')} {summary} ? (o/N) : ")
):
print(t("Cancelled."))
return
if not self._is_yes(
input(t("Confirm for real? (y/N): "))
):
print(t("Cancelled."))
return
for real in resolved:
cmd = f"sudo virsh {action} {shlex.quote(real)}"
print(f"\n{t('Will execute:')} {cmd}")
self.execute.exec_command_live(cmd, source_erplibre=False)
@staticmethod
def _qemu_dominfo(name):

View file

@ -1452,6 +1452,70 @@ TRANSLATIONS = {
"fr": "Afficher les infos avancées (vCPU, RAM, disque) ? (o/N) : ",
"en": "Show advanced info (vCPU, RAM, disk)? (y/N): ",
},
"What do you want to do?": {
"fr": "Que voulez-vous faire ?",
"en": "What do you want to do?",
},
"Advanced info (vCPU, RAM, disk)": {
"fr": "Infos avancées (vCPU, RAM, disque)",
"en": "Advanced info (vCPU, RAM, disk)",
},
"Change the state of one or more VMs": {
"fr": "Changer l'état d'une ou plusieurs VM",
"en": "Change the state of one or more VMs",
},
"Enter": {
"fr": "Entrée",
"en": "Enter",
},
"Nothing": {
"fr": "Rien",
"en": "Nothing",
},
"Choice: ": {
"fr": "Choix : ",
"en": "Choice: ",
},
"Available VMs:": {
"fr": "VM disponibles :",
"en": "Available VMs:",
},
"VMs to change (comma-separated): ": {
"fr": "VM à modifier (séparées par des virgules) : ",
"en": "VMs to change (comma-separated): ",
},
"Unknown VM(s):": {
"fr": "VM inconnue(s) :",
"en": "Unknown VM(s):",
},
"Target state:": {
"fr": "État cible :",
"en": "Target state:",
},
"Open (start)": {
"fr": "Ouvrir (démarrer)",
"en": "Open (start)",
},
"Close (shut down)": {
"fr": "Fermer (éteindre)",
"en": "Close (shut down)",
},
"start": {
"fr": "démarrer",
"en": "start",
},
"shut down": {
"fr": "éteindre",
"en": "shut down",
},
"Apply:": {
"fr": "Appliquer :",
"en": "Apply:",
},
"Confirm for real? (y/N): ": {
"fr": "Confirmer pour de vrai ? (o/N) : ",
"en": "Confirm for real? (y/N): ",
},
"Storage": {
"fr": "Stockage",
"en": "Storage",