"""Prueft, ob pvesnap ueberhaupt arbeiten kann. Hintergrund: pvesh fuehrt die Proxmox-API im eigenen Prozess aus. Der Snapshot-Task ist damit ein Kindprozess von pvesnap und erbt dessen Umgebung - also auch Einschraenkungen aus der systemd-Unit. Eine schreibgeschuetzte /etc faellt dabei nicht als Rechtefehler auf, sondern als "cfs-lock 'storage-XXX' error: got lock request timeout", weil pmxcfs seine Sperren als Verzeichnisse unter /etc/pve/priv/lock/ anlegt. """ from __future__ import annotations import os from .proxmox import pvesh_available PMXCFS = "/etc/pve" PMXCFS_LOCKDIR = "/etc/pve/priv/lock" def _read_only(path): """True, wenn `path` auf einem schreibgeschuetzt eingehaengten Dateisystem liegt.""" try: stats = os.statvfs(path) except OSError: return False return bool(stats.f_flag & getattr(os, "ST_RDONLY", 1)) def check_environment(require_pve=True): """Liste von Problemen; leer heisst: alles in Ordnung.""" problems = [] if os.geteuid() != 0: problems.append("pvesnap muss als root laufen (pvesh benoetigt root-Rechte).") if require_pve and not pvesh_available(): problems.append("'pvesh' nicht gefunden - laeuft pvesnap auf einem " "Proxmox-VE-Host?") if not os.path.isdir(PMXCFS): if require_pve: problems.append("%s nicht vorhanden - laeuft pve-cluster?" % PMXCFS) return problems if _read_only(PMXCFS) or not os.access(PMXCFS, os.W_OK): problems.append( "%s ist nicht beschreibbar. Snapshots scheitern dann mit " "\"cfs-lock 'storage-...' error: got lock request timeout\", weil " "Proxmox seine Sperren unter %s anlegt. Ursache ist meist eine " "Sandbox-Option in der systemd-Unit (ProtectSystem=, ReadOnlyPaths=) " "- pruefen mit: systemctl show pvesnap -p ProtectSystem -p ProtectHome" % (PMXCFS, PMXCFS_LOCKDIR)) # ProtectHome=yes ersetzt /root durch ein leeres, unlesbares Verzeichnis. try: empty_root = os.path.isdir("/root") and not os.listdir("/root") except OSError: empty_root = True if empty_root: problems.append("/root ist leer oder nicht lesbar (ProtectHome= in der " "systemd-Unit?). Proxmox erreicht andere Nodes im Cluster " "ueber die SSH-Schluessel in /root/.ssh.") return problems def warn_about_environment(log, require_pve=True): """Probleme protokollieren; gibt True zurueck, wenn alles passt.""" problems = check_environment(require_pve=require_pve) for problem in problems: log.error("Umgebung: %s", problem) return not problems