diff options
Diffstat (limited to 'raveos-center/raveos_center/snapshotok.py')
| -rw-r--r-- | raveos-center/raveos_center/snapshotok.py | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/raveos-center/raveos_center/snapshotok.py b/raveos-center/raveos_center/snapshotok.py new file mode 100644 index 0000000..f4bd097 --- /dev/null +++ b/raveos-center/raveos_center/snapshotok.py @@ -0,0 +1,116 @@ +import json +import re +import subprocess +from pathlib import Path + +from raveos_center import rendszerinfo + +SNAP_PAC = Path("/usr/share/libalpm/hooks/05-snap-pac-pre.hook") +TIPUSOK = {"pre": "csomagművelet előtt", "post": "csomagművelet után", "single": "kézi"} + + +def _futtat(parancs, ido=30): + try: + return subprocess.run(parancs, capture_output=True, text=True, timeout=ido) + except (OSError, subprocess.TimeoutExpired): + return None + + +def fajlrendszer(): + kimenet = _futtat(["findmnt", "-no", "FSTYPE", "/"]) + return kimenet.stdout.strip() if kimenet and kimenet.returncode == 0 else "" + + +def gyoker_alvolumen(): + kimenet = _futtat(["findmnt", "-no", "OPTIONS", "/"]) + if not kimenet: + return "" + for opcio in kimenet.stdout.strip().split(","): + if opcio.startswith("subvol="): + return opcio[len("subvol="):] + return "" + + +def snapshots_csatolva(): + kimenet = _futtat(["findmnt", "-no", "SOURCE", "/.snapshots"]) + return bool(kimenet and kimenet.returncode == 0 and kimenet.stdout.strip()) + + +def snap_pac(): + return SNAP_PAC.exists() + + +def _elem(nyers): + tipus = nyers.get("type", "single") + adat = nyers.get("userdata") or {} + return { + "szam": nyers.get("number", 0), + "datum": (nyers.get("date") or "")[:16], + "tipus": tipus, + "tipus_nev": "telepítés" if adat.get("important") == "yes" and tipus == "single" else TIPUSOK.get(tipus, tipus), + "leiras": nyers.get("description") or "", + "pre_szam": nyers.get("pre-number"), + "aktiv": bool(nyers.get("active")), + } + + +def allapot(): + fs = fajlrendszer() + adat = { + "fajlrendszer": fs, + "snapper": rendszerinfo.snapper_elerheto(), + "snap_pac": snap_pac(), + "alvolumen": gyoker_alvolumen(), + "csatolva": snapshots_csatolva(), + "lista": [], + "hiba": "", + } + if fs != "btrfs" or not adat["snapper"]: + return adat + kimenet = _futtat(["snapper", "--jsonout", "-c", "root", "list"]) + if not kimenet or kimenet.returncode != 0: + adat["hiba"] = (kimenet.stderr.strip() if kimenet else "") or "A snapshotok listája nem olvasható." + return adat + try: + nyers = json.loads(kimenet.stdout).get("root", []) + except ValueError: + adat["hiba"] = "A snapper válasza nem értelmezhető." + return adat + adat["lista"] = [_elem(n) for n in reversed(nyers) if n.get("number", 0) != 0] + return adat + + +def ervenyes_leiras(szoveg): + return 1 <= len(szoveg) <= 80 and all(c.isalnum() or c.isspace() or c in "._:,()-" for c in szoveg) + + +def kernel_valtozas(szam): + gyoker = Path(f"/.snapshots/{int(szam)}/snapshot") + valtozasok = [] + try: + if not (gyoker / "usr/lib/modules").is_dir(): + return None + pkgbase_fajlok = list(gyoker.glob("usr/lib/modules/*/pkgbase")) + except OSError: + return None + for pb in pkgbase_fajlok: + try: + nev = pb.read_text().strip() + except OSError: + continue + if not re.fullmatch(r"[a-z0-9][a-z0-9._+-]*", nev): + continue + regi = _futtat(["pacman", "--dbpath", str(gyoker / "var/lib/pacman"), "-Q", nev]) + most = _futtat(["pacman", "-Q", nev]) + regi_v = regi.stdout.split()[1] if regi and regi.returncode == 0 and len(regi.stdout.split()) > 1 else "" + most_v = most.stdout.split()[1] if most and most.returncode == 0 and len(most.stdout.split()) > 1 else "" + if regi_v and regi_v != most_v: + cache = any( + not p.name.endswith(".sig") for p in Path("/var/cache/pacman/pkg").glob(f"{nev}-{regi_v}-*.pkg.tar.*") + ) + valtozasok.append({"nev": nev, "regi": regi_v, "most": most_v, "cache": cache}) + return valtozasok + + +def snapper_telepitheto(adat): + return adat["fajlrendszer"] == "btrfs" and not adat["snapper"] and adat["alvolumen"] == "/@" and adat["csatolva"] |