[IMP] script todo: réduction — sauvegarde optionnelle + effacement du backup
Trois améliorations autour de la sauvegarde de disque à la réduction : - La sauvegarde .bak n'est plus systématique : on DEMANDE (défaut OUI) « Sauvegarder le disque avant réduction ? ». Si non, avertissement (un échec pourrait casser le disque, pas de restauration possible). - À la FIN, après avoir proposé de démarrer la VM (donc après test manuel possible), on propose d'EFFACER la sauvegarde (défaut NON -> on la garde par prudence). - « Nettoyer QEMU » détecte désormais les sauvegardes *.qcow2.bak (libellé « sauvegarde de disque (redim.) ») et permet de les effacer. _qemu_shrink_revert gère l'absence de sauvegarde (avertit de lancer fsck au lieu de restaurer). Validé de bout en bout sur image jetable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c9ec5b98b9
commit
8be034f25e
2 changed files with 89 additions and 20 deletions
|
|
@ -1699,12 +1699,8 @@ class TODO:
|
|||
):
|
||||
print(t("Cancelled."))
|
||||
return
|
||||
# Réduction SÛRE via virt-resize (réduit FS + partition + GPT).
|
||||
# On opère sur une COPIE : l'original n'est remplacé qu'en cas de
|
||||
# SUCCÈS -> aucune corruption possible. (Le brut « qemu-img resize
|
||||
# --shrink » tronquait le conteneur sans réduire le FS/partition
|
||||
# -> GPT de secours perdue, racine tronquée -> dracut-initqueue en
|
||||
# échec, OS non bootable.)
|
||||
# Réduction SÛRE (qemu-nbd : réduit FS + partition + GPT, avec
|
||||
# sauvegarde optionnelle restaurée en cas d'échec).
|
||||
if not self._qemu_safe_shrink(name, disk, new_gb):
|
||||
self._qemu_offer_start(name, was_shut_down)
|
||||
return
|
||||
|
|
@ -1730,9 +1726,24 @@ class TODO:
|
|||
):
|
||||
self._qemu_grow_guest_fs(name)
|
||||
|
||||
# 5) La VM a été éteinte pour l'opération : proposer de la redémarrer.
|
||||
# 5) La VM a été éteinte pour l'opération : proposer de la redémarrer
|
||||
# (l'utilisateur peut ainsi TESTER avant de décider du backup).
|
||||
self._qemu_offer_start(name, was_shut_down)
|
||||
|
||||
# 6) Réduction réussie AVEC sauvegarde : proposer de l'effacer une fois
|
||||
# la VM testée (défaut : NON -> on garde le backup par prudence).
|
||||
bak = getattr(self, "_shrink_backup", None)
|
||||
if shrink and bak and os.path.exists(bak):
|
||||
print(f"\n{t('A disk backup was kept:')} {bak}")
|
||||
if self._is_yes(
|
||||
input(t("Delete this backup now? (y/N): "))
|
||||
):
|
||||
subprocess.run(["sudo", "rm", "-f", bak], check=False)
|
||||
print(t("Backup deleted."))
|
||||
else:
|
||||
print(t("Backup kept (delete later via Clean up QEMU)."))
|
||||
self._shrink_backup = None
|
||||
|
||||
def _qemu_offer_start(self, name, was_shut_down):
|
||||
"""Si la VM a été éteinte pour l'opération, le noter et proposer de la
|
||||
redémarrer (sinon ne rien demander)."""
|
||||
|
|
@ -1771,13 +1782,22 @@ class TODO:
|
|||
)
|
||||
return False
|
||||
target = int(round(new_gb * (1 << 30)))
|
||||
bak = f"{disk}.bak"
|
||||
print(f"\n{t('Backing up the disk before shrinking…')}")
|
||||
if subprocess.run(
|
||||
["sudo", "cp", "--reflink=auto", "--sparse=always", disk, bak]
|
||||
).returncode != 0:
|
||||
print(t("Backup failed; aborting."))
|
||||
return False
|
||||
# Sauvegarde OPTIONNELLE (défaut OUI) : permet de restaurer en cas
|
||||
# d'échec, et de tester la VM avant de la supprimer (proposé à la fin).
|
||||
self._shrink_backup = None
|
||||
bak = None
|
||||
if self._is_yes_default_yes(
|
||||
input(t("Back up the disk before shrinking? (Y/n): "))
|
||||
):
|
||||
bak = f"{disk}.bak"
|
||||
print(f"\n{t('Backing up the disk before shrinking…')}")
|
||||
if subprocess.run(
|
||||
["sudo", "cp", "--reflink=auto", "--sparse=always", disk, bak]
|
||||
).returncode != 0:
|
||||
print(t("Backup failed; aborting."))
|
||||
return False
|
||||
else:
|
||||
print(f"⚠ {t('No backup: a failure could leave the disk broken.')}")
|
||||
subprocess.run(["sudo", "modprobe", "nbd", "max_part=16"], check=False)
|
||||
dev = None
|
||||
try:
|
||||
|
|
@ -1865,20 +1885,30 @@ class TODO:
|
|||
)
|
||||
self._qemu_nbd_disconnect(dev)
|
||||
dev = None
|
||||
print(f"✅ {t('Disk safely shrunk. Backup kept at:')} {bak}")
|
||||
self._shrink_backup = bak # proposé à la suppression après le boot
|
||||
if bak:
|
||||
print(
|
||||
f"✅ {t('Disk safely shrunk. Backup kept at:')} {bak}"
|
||||
)
|
||||
else:
|
||||
print(f"✅ {t('Disk safely shrunk.')}")
|
||||
return True
|
||||
finally:
|
||||
if dev:
|
||||
self._qemu_nbd_disconnect(dev)
|
||||
|
||||
def _qemu_shrink_revert(self, bak, disk, changed):
|
||||
"""Restaure le disque depuis la sauvegarde .bak si on l'a modifié
|
||||
(changed) ; sinon retire juste la sauvegarde inutile. Renvoie False
|
||||
(la réduction a échoué)."""
|
||||
if changed:
|
||||
"""Restaure le disque depuis la sauvegarde si on l'a modifié (changed)
|
||||
et qu'une sauvegarde existe ; sinon retire la sauvegarde inutile.
|
||||
Renvoie False (la réduction a échoué)."""
|
||||
if changed and bak:
|
||||
print(t("Restoring the original disk from backup…"))
|
||||
subprocess.run(["sudo", "mv", "-f", bak, disk], check=False)
|
||||
else:
|
||||
elif changed and not bak:
|
||||
print(
|
||||
f"⚠ {t('No backup to restore; run fsck on the disk before use.')}"
|
||||
)
|
||||
elif bak:
|
||||
subprocess.run(["sudo", "rm", "-f", bak], check=False)
|
||||
return False
|
||||
|
||||
|
|
@ -2360,6 +2390,9 @@ class TODO:
|
|||
stem = re.sub(r"(_VARS)?\.fd$", "", os.path.basename(path))
|
||||
if stem not in domains:
|
||||
orphans.append((size, path, t("orphan UEFI nvram")))
|
||||
# Sauvegardes de disque laissées par un redimensionnement (.qcow2.bak).
|
||||
for size, path in self._qemu_find_files(disk_dir, "*.qcow2.bak"):
|
||||
orphans.append((size, path, t("disk backup (resize)")))
|
||||
if orphans:
|
||||
total = sum(o[0] for o in orphans)
|
||||
print(f"\n{t('Orphan files:')}")
|
||||
|
|
|
|||
|
|
@ -1448,6 +1448,42 @@ TRANSLATIONS = {
|
|||
"fr": "Sauvegarde du disque avant réduction…",
|
||||
"en": "Backing up the disk before shrinking…",
|
||||
},
|
||||
"Back up the disk before shrinking? (Y/n): ": {
|
||||
"fr": "Sauvegarder le disque avant réduction ? (O/n, défaut : oui) : ",
|
||||
"en": "Back up the disk before shrinking? (Y/n, default: yes): ",
|
||||
},
|
||||
"No backup: a failure could leave the disk broken.": {
|
||||
"fr": "Sans sauvegarde : un échec pourrait rendre le disque inutilisable.",
|
||||
"en": "No backup: a failure could leave the disk broken.",
|
||||
},
|
||||
"Disk safely shrunk.": {
|
||||
"fr": "Disque réduit en toute sécurité.",
|
||||
"en": "Disk safely shrunk.",
|
||||
},
|
||||
"No backup to restore; run fsck on the disk before use.": {
|
||||
"fr": "Pas de sauvegarde à restaurer ; lancez fsck avant utilisation.",
|
||||
"en": "No backup to restore; run fsck on the disk before use.",
|
||||
},
|
||||
"A disk backup was kept:": {
|
||||
"fr": "Une sauvegarde du disque a été conservée :",
|
||||
"en": "A disk backup was kept:",
|
||||
},
|
||||
"Delete this backup now? (y/N): ": {
|
||||
"fr": "Effacer cette sauvegarde maintenant ? (o/N) : ",
|
||||
"en": "Delete this backup now? (y/N): ",
|
||||
},
|
||||
"Backup deleted.": {
|
||||
"fr": "Sauvegarde effacée.",
|
||||
"en": "Backup deleted.",
|
||||
},
|
||||
"Backup kept (delete later via Clean up QEMU).": {
|
||||
"fr": "Sauvegarde conservée (à effacer plus tard via Nettoyer QEMU).",
|
||||
"en": "Backup kept (delete later via Clean up QEMU).",
|
||||
},
|
||||
"disk backup (resize)": {
|
||||
"fr": "sauvegarde de disque (redim.)",
|
||||
"en": "disk backup (resize)",
|
||||
},
|
||||
"Backup failed; aborting.": {
|
||||
"fr": "Échec de la sauvegarde ; abandon.",
|
||||
"en": "Backup failed; aborting.",
|
||||
|
|
|
|||
Loading…
Reference in a new issue