Files
pve-update/proxmox-update.py

116 lines
3.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
import subprocess
import logging
import datetime
import os
import sys
import re
# ========== Einstellungen ==========
ZFS_DATASETS = ["rpool/ROOT", "rpool/pveconf"]
SNAPSHOT_TAG = "pve-update-via-cron"
MAX_SNAPSHOTS = 5
LOGFILE = "/var/log/proxmox_update.log"
REBOOT_FLAG = os.environ.get("REBOOT", "NO").upper()
TIMESTAMP = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
# ========== Logging Setup ==========
logging.basicConfig(
filename=LOGFILE,
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
)
def run(cmd, check=True):
"""Kommando ausführen"""
logging.debug(f"Running: {cmd}")
try:
result = subprocess.run(
cmd, shell=True, check=check,
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
return result.stdout.decode().strip()
except subprocess.CalledProcessError as e:
logging.error(f"Fehler bei Befehl: {cmd}")
logging.error(e.stderr.decode().strip())
if check:
raise
return ""
def has_updates():
"""apt update ausführen & prüfen, ob Updates vorhanden"""
try:
output = run("apt update")
if "upgradable" in output.lower():
logging.info("Updates verfügbar.")
return True
logging.info("Keine Updates verfügbar.")
return False
except Exception:
logging.error("apt update fehlgeschlagen.")
sys.exit(2)
def is_kernel_update_available():
"""Prüfen, ob ein Kernel-Update verfügbar ist"""
output = run("apt list --upgradable", check=False)
return any("linux-image-" in line for line in output.splitlines())
def create_snapshot(dataset):
"""Snapshot mit Tag erstellen"""
snapshot_name = f"{dataset}@{SNAPSHOT_TAG}-{TIMESTAMP}"
logging.info(f"Erstelle Snapshot: {snapshot_name}")
run(f"zfs snapshot {snapshot_name}")
def cleanup_snapshots(dataset):
"""Alte Snapshots mit dem definierten Tag löschen"""
logging.info(f"Bereinige alte Snapshots in {dataset}")
snap_list = run(f"zfs list -t snapshot -o name -s creation | grep '^{dataset}@{SNAPSHOT_TAG}-'", check=False).splitlines()
if len(snap_list) > MAX_SNAPSHOTS:
for snap in snap_list[:-MAX_SNAPSHOTS]:
logging.info(f"Lösche Snapshot: {snap}")
run(f"zfs destroy {snap}")
def upgrade_system():
"""Upgrade durchführen"""
try:
logging.info("Starte apt dist-upgrade …")
run("apt dist-upgrade -y")
logging.info("Führe apt autoremove aus …")
run("apt autoremove -y")
except Exception:
logging.error("Upgrade fehlgeschlagen.")
sys.exit(2)
def main():
logging.info("===== Proxmox Update & Snapshot gestartet =====")
if os.geteuid() != 0:
print("Dieses Skript muss als root ausgeführt werden.")
sys.exit(2)
if not has_updates():
logging.info("Beende keine Updates.")
sys.exit(0)
# Snapshots nur bei Update
for dataset in ZFS_DATASETS:
create_snapshot(dataset)
cleanup_snapshots(dataset)
# Upgrade
upgrade_system()
# Kernel-Update erkennen
if is_kernel_update_available():
logging.warning("Kernel-Update erkannt Neustart empfohlen.")
if REBOOT_FLAG == "YES":
logging.info("Reboot wird ausgeführt …")
run("reboot")
sys.exit(1) # Exit 1 = Neustart empfohlen
logging.info("===== Update-Vorgang abgeschlossen =====")
sys.exit(0)
if __name__ == "__main__":
main()