From 27b9de6755c077c53662085a34019a0fa0310943 Mon Sep 17 00:00:00 2001 From: Spitap Date: Thu, 21 Jul 2022 13:48:44 +0200 Subject: [PATCH] database backup --- README.rst | 15 ++++++++ modoboa_installer/database.py | 12 ++++++ modoboa_installer/scripts/__init__.py | 2 +- modoboa_installer/scripts/backup.py | 54 +++++++++++++++++++++++++-- 4 files changed, 78 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index dd8424e..bc08e66 100644 --- a/README.rst +++ b/README.rst @@ -92,6 +92,21 @@ You can activate it as follows:: It will automatically install latest versions of modoboa and its plugins. +Backup mode +------------ + +An experimental backup mode is available. + +.. note:: + + You must keep the original configuration file, ie the one used for + the installation. Otherwise, you will need to recreate it manually with the right informations !. + +You can start the process as follows:: + $ sudo ./run.py --backup +.. note:: + Then follow the step on the console + Change the generated hostname ----------------------------- diff --git a/modoboa_installer/database.py b/modoboa_installer/database.py index 41b79df..1878cb2 100644 --- a/modoboa_installer/database.py +++ b/modoboa_installer/database.py @@ -141,6 +141,13 @@ class PostgreSQL(Database): self.dbhost, dbname, dbuser, path) utils.exec_cmd(cmd, sudo_user=self.dbuser) + def dumpDatabase(self, dbname, dbuser, dbpassword, path): + """Dump DB to SQL file""" + self._setup_pgpass(dbname, dbuser, dbpassword) + cmd = "pg_dump -h {} -d {} -U {} -O -w > {}".format( + self.dbhost, dbname, dbuser, path) + utils.exec_cmd(cmd, sudo_user=self.dbuser) + class MySQL(Database): @@ -250,6 +257,11 @@ class MySQL(Database): "mysql -h {} -u {} -p{} {} < {}".format( self.dbhost, dbuser, dbpassword, dbname, path) ) + def dumpDatabase(self, dbname, dbuser, dbpassword, path): + """Dump DB to SQL file""" + cmd = "mysqldump -h {} -u {} -p{} {} > {}".format( + self.dbhost, dbuser, dbpassword, dbname, path) + utils.exec_cmd(cmd, sudo_user=self.dbuser) def get_backend(config): diff --git a/modoboa_installer/scripts/__init__.py b/modoboa_installer/scripts/__init__.py index b101966..8f526d5 100644 --- a/modoboa_installer/scripts/__init__.py +++ b/modoboa_installer/scripts/__init__.py @@ -14,7 +14,7 @@ def install(appname, config, upgrade, backup): if backup: utils.printcolor("Starting up backup...", utils.MAGENTA) script = importlib.import_module("modoboa_installer.backup") - getattr(script, Backup())(config).run() + getattr(script, "BACKUP"())(config).run() return utils.printcolor("Installing {}".format(appname), utils.MAGENTA) try: diff --git a/modoboa_installer/scripts/backup.py b/modoboa_installer/scripts/backup.py index ba2b476..5fa1af8 100644 --- a/modoboa_installer/scripts/backup.py +++ b/modoboa_installer/scripts/backup.py @@ -3,16 +3,30 @@ import shutil import utils import os +from .. import database -#TODO: have version of each modoboa componenent saved into the config file to restore the same version +#TODO: have version of each modoboa componenents saved into the config file to restore the same version class Backup(): +#Backup structure ( {optional} ): +#{{backup_folder}} +#|| +#||--> installer.cfg +#||--> custom +# |--> { (copy of) /etc/amavis/conf.d/99-custom } +# |--> { (copy of) /etc/postfix/custom_whitelist.cidr } +#||--> databases +# |--> modoboa.sql +# |--> { amavis.sql } +# |--> { spamassassin.sql } +#||--> mails +# |--> vmails def __init__(self, config): self.config = config self.destinationPath = "" - self.BACKUPDIRECTORY = ["mails", "custom", "databases"] + self.BACKUPDIRECTORY = ["mails/", "custom/", "databases/"] def preparePath(self): @@ -56,6 +70,7 @@ class Backup(): user_value = None while (user_value != '' and not self.validatePath(user_value)): print("Enter backup path, please provide an empty folder.") + print("CTRL+C to cancel") user_value = utils.user_input("-> ") @@ -74,7 +89,7 @@ class Backup(): f" ({home_path}) seems not right...", utils.RED) else: - shutil.copytree(home_path, self.destinationPath+"mails/") + shutil.copytree(home_path, self.destinationPath + self.BACKUPDIRECTORY[0]) utils.printcolor("Mail backup complete!", utils.GREEN) @@ -85,7 +100,7 @@ class Backup(): Feel free to suggest to add others!""" utils.printcolor("Backing up some custom configuration...", utils.MAGENTA) - custom_path = self.destinationPath+"custom/" + custom_path = self.destinationPath + self.BACKUPDIRECTORY[1] """AMAVIS""" amavis_custom = "/etc/amavis/conf.d/99-custom" @@ -103,6 +118,36 @@ class Backup(): def backupDBs(self): """Backing up databases""" + utils.printcolor("Backing up databases...", utils.MAGENTA) + + dump_path = self.destinationPath + self.BACKUPDIRECTORY[2] + backend = database.get_backend(self.config) + + """Modoboa""" + dbname = self.config.get("modoboa", "dbname") + dbuser = self.config.get("modoboa", "dbuser") + dbpasswd = self.config.get("modoboa", "dbpassword") + backend.dumpDatabase(dbname, dbuser, dbpasswd, dump_path+"modoboa.sql") + + """Amavis""" + if (self.config.has_option("amavis", "enabled") and + not self.config.getboolean("amavis", "enabled")): + dbname = self.config.get("amavis", "dbname") + dbuser = self.config.get("amavis", "dbuser") + dbpasswd = self.config.get("amavis", "dbpassword") + backend.dumpDatabase(dbname, dbuser, dbpasswd, dump_path+"amavis.sql") + + """SpamAssassin""" + if (self.config.has_option("spamassassin", "enabled") and + not self.config.getboolean("spamassassin", "enabled")): + dbname = self.config.get("spamassassin", "dbname") + dbuser = self.config.get("spamassassin", "dbuser") + dbpasswd = self.config.get("spamassassin", "dbpassword") + backend.dumpDatabase(dbname, dbuser, dbpasswd, dump_path+"spamassassin.sql") + + def backupCompletion(self): + utils.printcolor("Backup process done, your backup is availible here:" + f"--> {self.destinationPath}", utils.GREEN) def run(self): self.setPath() @@ -110,5 +155,6 @@ class Backup(): self.backupMails() self.backupCustomConfig() self.backupDBs() + self.backupCompletion()