first commit
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user