Files
proxmox-snapshot-service/pvesnap/naming.py
T
2026-07-30 16:52:58 +02:00

89 lines
3.0 KiB
Python

"""Namensschema der von pvesnap verwalteten Snapshots.
Ein Name sieht so aus: auto-taeglich-20260730-023000
^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^
| | Datum Uhrzeit
| Kurzname der Gruppe
Praefix aus [global]
Nur Snapshots, die exakt auf dieses Muster passen, werden von pvesnap
angefasst. Von Hand angelegte Snapshots bleiben damit garantiert unberuehrt.
"""
from __future__ import annotations
import re
from datetime import datetime
# Proxmox erlaubt fuer Snapshot-Namen nur begrenzte Laenge - wir bleiben
# bewusst deutlich darunter.
MAX_NAME_LEN = 40
_STAMP_LEN = len("-20260730-023000")
def max_slug_len(prefix):
return max(1, MAX_NAME_LEN - len(prefix) - _STAMP_LEN)
def effective_slug(prefix, slug):
"""Der Kurzname, wie er tatsaechlich im Snapshot-Namen landet."""
return slug[: max_slug_len(prefix)]
def build_name(prefix, slug, moment):
return "%s-%s-%s" % (prefix, effective_slug(prefix, slug),
moment.strftime("%Y%m%d-%H%M%S"))
def name_pattern(prefix, slug=None):
part = re.escape(effective_slug(prefix, slug)) if slug else r"[A-Za-z0-9]+"
return re.compile(r"^%s-(%s)-(\d{8})-(\d{6})$" % (re.escape(prefix), part))
def parse_name(prefix, name):
"""Zerlegt einen Snapshot-Namen; gibt None zurueck, wenn er nicht zu uns gehoert."""
match = name_pattern(prefix).match(str(name))
if not match:
return None
slug, date_part, time_part = match.groups()
try:
created = datetime.strptime(date_part + time_part, "%Y%m%d%H%M%S")
except ValueError:
return None
return {"slug": slug, "created": created}
def render_description(template, group, guest, moment, prefix):
"""Setzt die Platzhalter der Beschreibungs-Vorlage ein."""
from .util import format_duration # lokal, um Zyklen zu vermeiden
values = {
"prefix": prefix,
"group": group.name,
"group_slug": group.slug,
"vmid": guest.vmid,
"name": guest.name or "",
"type": "LXC" if guest.type == "lxc" else "VM",
"node": guest.node or "",
"pool": guest.pool or "",
"tags": ",".join(guest.tags),
"date": moment.strftime("%Y-%m-%d"),
"time": moment.strftime("%H:%M:%S"),
"datetime": moment.strftime("%Y-%m-%d %H:%M:%S"),
"timestamp": int(moment.timestamp()),
"keep_time": format_duration(group.keep_time),
"keep_count": group.keep_count if group.keep_count else "unbegrenzt",
"schedule": _schedule_text(group),
}
try:
text = str(template).format(**values)
except (KeyError, IndexError, ValueError):
# Unbekannter Platzhalter: lieber eine brauchbare Beschreibung als ein Abbruch.
text = "pvesnap | Gruppe: %s | erstellt: %s" % (group.name, values["datetime"])
return text.strip()[:1024]
def _schedule_text(group):
from .schedule import describe
return describe(group)