Fehlgeschlagene Container-Snapshots wurden als Erfolg gemeldet
Bei Containern schreibt pvesh den Fortschritt vor die UPID, alles in eine
Zeile:
Creating snap: 100% complete...done."UPID:node:...:vzsnapshot:100:..."
Die UPID wurde zeilenweise mit startswith() gesucht und deshalb nicht
gefunden. Ohne UPID liess sich der Task nicht verfolgen - ein Fehlschlag
blieb damit unbemerkt und pvesnap protokollierte "Snapshot angelegt",
obwohl Proxmox nur einen halbfertigen Eintrag (snapstate "prepare") in der
Konfiguration hinterlassen hatte. Genau so sind die beiden Leichen bei
LXC 100 entstanden.
* Die UPID wird jetzt per Suchmuster aus der gesamten Ausgabe geholt,
egal woran sie haengt.
* Zusaetzlich wird nach dem Anlegen nachgesehen, ob der Snapshot wirklich
da und vollstaendig ist. Damit faellt ein stiller Fehlschlag auch dann
auf, wenn weder Rueckgabewert noch Task ihn melden.
Auf pvetest01 mit Container 100 geprueft: anlegen (Task wird verfolgt,
Eintrag vollstaendig, rbd-Snapshot vorhanden), einbinden (rootfs als ext4,
/etc/hostname liefert "unifi"), Explorer und Web-Oberflaeche inklusive
ZIP, sowie loeschen ueber die Vorhaltezahl.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ab610a1f5a
commit
8577b23b0c
+42
-6
@@ -8,6 +8,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
@@ -17,6 +18,9 @@ log = logging.getLogger("pvesnap.proxmox")
|
|||||||
|
|
||||||
PVESH = "/usr/bin/pvesh"
|
PVESH = "/usr/bin/pvesh"
|
||||||
|
|
||||||
|
# UPID:node:PID:PSTART:STARTTIME:TYPE:ID:USER:
|
||||||
|
_UPID_PATTERN = re.compile(r"UPID:[^\s\"']+")
|
||||||
|
|
||||||
|
|
||||||
class ProxmoxError(Exception):
|
class ProxmoxError(Exception):
|
||||||
"""Ein pvesh-Aufruf ist fehlgeschlagen."""
|
"""Ein pvesh-Aufruf ist fehlgeschlagen."""
|
||||||
@@ -184,7 +188,12 @@ class Proxmox:
|
|||||||
except ProxmoxError:
|
except ProxmoxError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return self._retry(what, lambda: self._task(guest, args, what), skip_retry=exists)
|
def attempt():
|
||||||
|
result = self._task(guest, args, what)
|
||||||
|
self._verify_created(guest, name)
|
||||||
|
return result
|
||||||
|
|
||||||
|
return self._retry(what, attempt, skip_retry=exists)
|
||||||
|
|
||||||
def delete_snapshot(self, guest, name, force=False):
|
def delete_snapshot(self, guest, name, force=False):
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
@@ -319,8 +328,35 @@ class Proxmox:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _extract_upid(output):
|
def _extract_upid(output):
|
||||||
for line in (output or "").splitlines():
|
"""UPID aus der Antwort von pvesh fischen.
|
||||||
candidate = line.strip().strip('"')
|
|
||||||
if candidate.startswith("UPID:"):
|
Bei Containern schreibt pvesh den Fortschritt vor die UPID, alles in
|
||||||
return candidate
|
einer Zeile:
|
||||||
return None
|
|
||||||
|
Creating snap: 100% complete...done."UPID:node:...:vzsnapshot:100:..."
|
||||||
|
|
||||||
|
Zeilenweise auf den Anfang zu pruefen findet die UPID dort nicht - und
|
||||||
|
ohne UPID bliebe ein fehlgeschlagener Task unbemerkt.
|
||||||
|
"""
|
||||||
|
match = _UPID_PATTERN.search(output or "")
|
||||||
|
return match.group(0) if match else None
|
||||||
|
|
||||||
|
def _verify_created(self, guest, name):
|
||||||
|
"""Nachsehen, ob der Snapshot wirklich brauchbar entstanden ist.
|
||||||
|
|
||||||
|
Zweite Sicherung fuer den Fall, dass ein Fehlschlag weder ueber den
|
||||||
|
Rueckgabewert noch ueber den Task sichtbar wird: Proxmox laesst dann
|
||||||
|
einen halbfertigen Eintrag ("snapstate") in der Konfiguration stehen.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
snapshots = self.list_snapshots(guest)
|
||||||
|
except ProxmoxError:
|
||||||
|
return # nicht schlimmer machen als noetig
|
||||||
|
found = next((s for s in snapshots if s.name == name), None)
|
||||||
|
if found is None:
|
||||||
|
raise ProxmoxError("Der Snapshot '%s' ist nach dem Anlegen nicht "
|
||||||
|
"vorhanden." % name)
|
||||||
|
if not found.complete:
|
||||||
|
raise ProxmoxError("Der Snapshot '%s' ist unvollstaendig geblieben "
|
||||||
|
"(snapstate: %s) - er enthaelt keine Daten."
|
||||||
|
% (name, found.snapstate))
|
||||||
|
|||||||
Reference in New Issue
Block a user