summaryrefslogtreecommitdiff
path: root/raveos-center/raveos_center/oldalak/rendszer/snapshotok.py
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-center/raveos_center/oldalak/rendszer/snapshotok.py')
-rw-r--r--raveos-center/raveos_center/oldalak/rendszer/snapshotok.py247
1 files changed, 247 insertions, 0 deletions
diff --git a/raveos-center/raveos_center/oldalak/rendszer/snapshotok.py b/raveos-center/raveos_center/oldalak/rendszer/snapshotok.py
new file mode 100644
index 0000000..8d9b08c
--- /dev/null
+++ b/raveos-center/raveos_center/oldalak/rendszer/snapshotok.py
@@ -0,0 +1,247 @@
+from PyQt6.QtCore import QProcess, Qt
+from PyQt6.QtWidgets import QHBoxLayout, QInputDialog, QLineEdit, QMessageBox, QVBoxLayout, QWidget
+
+from raveos_center import muveletek, snapshotok
+from raveos_center.elemek import Kartya, cimke, gomb
+from raveos_center.folyamat import FolyamatAblak
+from raveos_center.hatter import ervenytelenit, gyorsitott, tarolt
+
+AZON = "snapshotok"
+CIM = "Snapshotok"
+
+
+class SnapshotSor(QWidget):
+ def __init__(self, elem, utolso, visszaallit, torol):
+ super().__init__()
+ self.setObjectName("appsor")
+ self.setProperty("utolso", utolso)
+ self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True)
+ sor = QHBoxLayout(self)
+ sor.setContentsMargins(16, 12, 16, 12)
+ sor.setSpacing(16)
+ datum = cimke(elem["datum"], "mono")
+ datum.setFixedWidth(150)
+ sor.addWidget(datum)
+ szovegek = QVBoxLayout()
+ szovegek.setSpacing(2)
+ szovegek.addWidget(cimke(elem["leiras"] or "-", None, True))
+ szovegek.addWidget(cimke(f"#{elem['szam']} {elem['tipus_nev']}", "monohalvany"))
+ sor.addLayout(szovegek, 1)
+ helper = muveletek.helper_elerheto()
+ vissza = gomb("Visszaállítás", kicsi=True)
+ vissza.setEnabled(helper)
+ vissza.clicked.connect(lambda: visszaallit(elem))
+ sor.addWidget(vissza, 0, Qt.AlignmentFlag.AlignVCenter)
+ torles = gomb("Törlés", kicsi=True)
+ torles.setEnabled(helper)
+ torles.clicked.connect(lambda: torol(elem))
+ sor.addWidget(torles, 0, Qt.AlignmentFlag.AlignVCenter)
+
+
+class Snapshotok(QWidget):
+ def __init__(self, kozpont):
+ super().__init__()
+ self.kozpont = kozpont
+ self.adat = None
+ doboz = QVBoxLayout(self)
+ doboz.setContentsMargins(0, 20, 0, 0)
+ doboz.setSpacing(16)
+ fej = QHBoxLayout()
+ fej.setSpacing(16)
+ self.leiras = cimke(
+ "A btrfs snapshot a rendszer egy pillanatnyi állapota. Ha egy frissítés után gond van, egy korábbi "
+ "állapotra vissza tudsz állni. A saját fájljaidat (/home) a visszaállítás nem érinti.",
+ "masodlagos",
+ True,
+ )
+ fej.addWidget(self.leiras, 1)
+ self.uj_gomb = gomb("Új snapshot", fo=True)
+ self.uj_gomb.clicked.connect(self.uj)
+ fej.addWidget(self.uj_gomb, 0, Qt.AlignmentFlag.AlignTop)
+ doboz.addLayout(fej)
+ self.info = cimke("", "monozold", True)
+ self.info.hide()
+ doboz.addWidget(self.info)
+ self.figyelem = cimke("", "figyelem", True)
+ self.figyelem.hide()
+ doboz.addWidget(self.figyelem)
+ self.beallitas_gomb = gomb("Snapper beállítása", fo=True)
+ self.beallitas_gomb.clicked.connect(self._beallitas)
+ self.beallitas_gomb.hide()
+ gs = QHBoxLayout()
+ gs.addWidget(self.beallitas_gomb)
+ gs.addStretch(1)
+ doboz.addLayout(gs)
+ self.kartya = Kartya(terkoz=0, margo=0)
+ doboz.addWidget(self.kartya)
+ doboz.addStretch(1)
+
+ def megjelenik(self, *args):
+ if tarolt("snapshotok") is None:
+ self.uj_gomb.setEnabled(False)
+ self._info("Betöltés...")
+ gyorsitott("snapshotok", snapshotok.allapot, kesz=self._kesz, hiba=self._hiba, kor=30)
+ if args and args[0] == "uj":
+ self.uj()
+
+ def frissit(self):
+ ervenytelenit("snapshotok", "snapshot")
+ gyorsitott("snapshotok", snapshotok.allapot, kesz=self._kesz, hiba=self._hiba)
+
+ def _hiba(self, uzenet):
+ self._figyelmeztet(f"A snapshotok nem olvashatók: {uzenet}")
+
+ def _info(self, szoveg):
+ self.info.setText(szoveg)
+ self.info.setVisible(bool(szoveg))
+
+ def _figyelmeztet(self, szoveg):
+ self.figyelem.setText(szoveg)
+ self.figyelem.setVisible(bool(szoveg))
+
+ def _kesz(self, adat):
+ self.adat = adat
+ helper = muveletek.helper_elerheto()
+ kesz = adat["fajlrendszer"] == "btrfs" and adat["snapper"]
+ self.uj_gomb.setVisible(kesz)
+ self.uj_gomb.setEnabled(kesz and helper)
+ self.beallitas_gomb.setVisible(snapshotok.snapper_telepitheto(adat))
+ self.beallitas_gomb.setEnabled(helper)
+ self.kartya.setVisible(kesz)
+ if adat["fajlrendszer"] != "btrfs":
+ self._info("")
+ self._figyelmeztet(
+ f"Snapshothoz btrfs fájlrendszer kell. Ez a gép {adat['fajlrendszer'] or 'ismeretlen'} fájlrendszert "
+ "használ, ezért itt nem érhető el. A RaveOS telepítésekor a lemez partícionálásánál ext4 és btrfs "
+ "közül lehet választani: ha snapshotot szeretnél, a btrfs-t válaszd."
+ )
+ return
+ if not adat["snapper"]:
+ self._info("")
+ if snapshotok.snapper_telepitheto(adat):
+ self._figyelmeztet(
+ "A gép btrfs-t használ, de a snapper még nincs beállítva. Egy kattintással beállítható: "
+ "utána minden csomagművelet előtt automatikusan snapshot készül."
+ )
+ else:
+ self._figyelmeztet(
+ "A gép btrfs-t használ, de az alvolumen-elrendezése eltér a RaveOS-étól (@ és @snapshots), "
+ "ezért a snapper itt nem állítható be automatikusan."
+ )
+ return
+ if adat["alvolumen"] != "/@":
+ self._figyelmeztet("A rendszer most nem a fő alvolumenről (@) fut, ezért visszaállítás nem indítható.")
+ elif adat["hiba"]:
+ self._figyelmeztet(adat["hiba"])
+ elif not helper:
+ self._figyelmeztet("A RaveOS Center rendszerhelpere nincs telepítve, ezért snapshot nem kezelhető.")
+ else:
+ self._figyelmeztet("")
+ self._info(
+ ("Automatikus snapshot minden csomagművelet előtt és után (snap-pac). " if adat["snap_pac"] else "")
+ + f"{len(adat['lista'])} snapshot, a régiek automatikusan törlődnek."
+ )
+ self._lista(adat)
+
+ def _lista(self, adat):
+ elrendezes = self.kartya.elrendezes
+ while elrendezes.count():
+ w = elrendezes.takeAt(0).widget()
+ if w:
+ w.deleteLater()
+ if not adat["lista"]:
+ ures = cimke("Még nincs snapshot.", "halvany")
+ ures.setContentsMargins(16, 16, 16, 16)
+ elrendezes.addWidget(ures)
+ return
+ for i, elem in enumerate(adat["lista"]):
+ elrendezes.addWidget(SnapshotSor(elem, i == len(adat["lista"]) - 1, self.visszaallit, self.torol))
+
+ def _futtat(self, cim, lepes, siker):
+ ablak = FolyamatAblak(self, cim, [lepes], siker)
+ ablak.exec()
+ self.frissit()
+ return ablak.rendben
+
+ def uj(self):
+ if not self.adat or not self.uj_gomb.isEnabled():
+ return
+ leiras, ok = QInputDialog.getText(
+ self, "Új snapshot", "Leírás (például: Driver csere előtt):", QLineEdit.EchoMode.Normal, "Kézi snapshot"
+ )
+ leiras = leiras.strip()
+ if not ok:
+ return
+ if not snapshotok.ervenyes_leiras(leiras):
+ QMessageBox.warning(self, "Új snapshot", "A leírás 1-80 karakter lehet: betűk, számok, szóköz és . _ : , ( ) -")
+ return
+ self._futtat("Új snapshot", muveletek.Lepes("Snapshot készítése", muveletek.root("snapshot", leiras)), "A snapshot elkészült.")
+
+ def torol(self, elem):
+ if QMessageBox.question(
+ self, "Snapshot törlése", f"Törlöd a(z) #{elem['szam']} snapshotot?\n{elem['datum']} {elem['leiras']}"
+ ) != QMessageBox.StandardButton.Yes:
+ return
+ self._futtat(
+ "Snapshot törlése",
+ muveletek.Lepes("Snapshot törlése", muveletek.root("snapshot-torles", str(elem["szam"]))),
+ "A snapshot törölve.",
+ )
+
+ def visszaallit(self, elem):
+ kernelek = snapshotok.kernel_valtozas(elem["szam"])
+ ellenorizheto = kernelek is not None
+ kernelek = kernelek or []
+ hianyzo = [k for k in kernelek if not k["cache"]]
+ if hianyzo:
+ QMessageBox.warning(
+ self,
+ "Visszaállítás",
+ "Ennek a snapshotnak a kernelcsomagja már nincs meg a csomag-cache-ben "
+ f"({', '.join(k['nev'] + ' ' + k['regi'] for k in hianyzo)}), ezért a visszaállított rendszer nem "
+ "indulna el. Válassz újabb snapshotot.",
+ )
+ return
+ kernel_szoveg = "".join(f"\n- {k['nev']}: {k['most'] or 'nincs'} -> {k['regi']}" for k in kernelek)
+ szoveg = (
+ f"A rendszer visszaáll erre az állapotra:\n#{elem['szam']} {elem['datum']} {elem['leiras']}\n\n"
+ "A saját fájljaid (/home) nem változnak. A mostani rendszer a következő visszaállításig megmarad "
+ "tartalékként. A változás újraindítás után lép életbe."
+ + (f"\n\nA kernel is visszaáll:{kernel_szoveg}" if kernelek else "")
+ + ("" if ellenorizheto else "\n\nA snapshot kernelverziója innen nem olvasható, a visszaállítás előtt a rendszer "
+ "ellenőrzi, és ha a kernelcsomag hiányzik, nem végzi el.")
+ + "\n\nFolytatod?"
+ )
+ if QMessageBox.question(self, "Visszaállítás", szoveg) != QMessageBox.StandardButton.Yes:
+ return
+ rendben = self._futtat(
+ "Visszaállítás",
+ muveletek.Lepes("Snapshot visszaállítása", muveletek.root("snapshot-visszaallit", str(elem["szam"]))),
+ "A visszaállítás elkészült. Indítsd újra a gépet.",
+ )
+ if not rendben:
+ return
+ doboz = QMessageBox(self)
+ doboz.setWindowTitle("Visszaállítás")
+ doboz.setIcon(QMessageBox.Icon.Warning)
+ doboz.setText(
+ "A visszaállítás újraindítás után lép életbe. Amit addig a gépen változtatsz (telepítés, beállítás, "
+ "rendszerfájlok), az a tartalék rendszerbe kerül, és elvész. A /home-ban lévő fájljaid megmaradnak.\n\n"
+ "Javasolt most újraindítani."
+ )
+ most = doboz.addButton("Újraindítás most", QMessageBox.ButtonRole.AcceptRole)
+ doboz.addButton("Később", QMessageBox.ButtonRole.RejectRole)
+ doboz.setDefaultButton(most)
+ doboz.exec()
+ if doboz.clickedButton() is most:
+ QProcess.startDetached("systemctl", ["reboot"])
+
+ def _beallitas(self):
+ self._futtat(
+ "Snapper beállítása",
+ muveletek.Lepes("Snapper beállítása", muveletek.root("snapper-beallitas")),
+ "A snapper beállítva, az első snapshot elkészült.",
+ )
+
+
+FUL = Snapshotok