database backup

This commit is contained in:
Spitap
2022-07-21 13:48:44 +02:00
parent 56ed214fb5
commit 27b9de6755
4 changed files with 78 additions and 5 deletions

View File

@@ -92,6 +92,21 @@ You can activate it as follows::
It will automatically install latest versions of modoboa and its plugins. 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 <your domain>
.. note::
Then follow the step on the console
Change the generated hostname Change the generated hostname
----------------------------- -----------------------------

View File

@@ -141,6 +141,13 @@ class PostgreSQL(Database):
self.dbhost, dbname, dbuser, path) self.dbhost, dbname, dbuser, path)
utils.exec_cmd(cmd, sudo_user=self.dbuser) 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): class MySQL(Database):
@@ -250,6 +257,11 @@ class MySQL(Database):
"mysql -h {} -u {} -p{} {} < {}".format( "mysql -h {} -u {} -p{} {} < {}".format(
self.dbhost, dbuser, dbpassword, dbname, path) 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): def get_backend(config):

View File

@@ -14,7 +14,7 @@ def install(appname, config, upgrade, backup):
if backup: if backup:
utils.printcolor("Starting up backup...", utils.MAGENTA) utils.printcolor("Starting up backup...", utils.MAGENTA)
script = importlib.import_module("modoboa_installer.backup") script = importlib.import_module("modoboa_installer.backup")
getattr(script, Backup())(config).run() getattr(script, "BACKUP"())(config).run()
return return
utils.printcolor("Installing {}".format(appname), utils.MAGENTA) utils.printcolor("Installing {}".format(appname), utils.MAGENTA)
try: try:

View File

@@ -3,16 +3,30 @@
import shutil import shutil
import utils import utils
import os 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(): 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): def __init__(self, config):
self.config = config self.config = config
self.destinationPath = "" self.destinationPath = ""
self.BACKUPDIRECTORY = ["mails", "custom", "databases"] self.BACKUPDIRECTORY = ["mails/", "custom/", "databases/"]
def preparePath(self): def preparePath(self):
@@ -56,6 +70,7 @@ class Backup():
user_value = None user_value = None
while (user_value != '' and not self.validatePath(user_value)): while (user_value != '' and not self.validatePath(user_value)):
print("Enter backup path, please provide an empty folder.") print("Enter backup path, please provide an empty folder.")
print("CTRL+C to cancel")
user_value = utils.user_input("-> ") user_value = utils.user_input("-> ")
@@ -74,7 +89,7 @@ class Backup():
f" ({home_path}) seems not right...", utils.RED) f" ({home_path}) seems not right...", utils.RED)
else: else:
shutil.copytree(home_path, self.destinationPath+"mails/") shutil.copytree(home_path, self.destinationPath + self.BACKUPDIRECTORY[0])
utils.printcolor("Mail backup complete!", utils.GREEN) utils.printcolor("Mail backup complete!", utils.GREEN)
@@ -85,7 +100,7 @@ class Backup():
Feel free to suggest to add others!""" Feel free to suggest to add others!"""
utils.printcolor("Backing up some custom configuration...", utils.MAGENTA) utils.printcolor("Backing up some custom configuration...", utils.MAGENTA)
custom_path = self.destinationPath+"custom/" custom_path = self.destinationPath + self.BACKUPDIRECTORY[1]
"""AMAVIS""" """AMAVIS"""
amavis_custom = "/etc/amavis/conf.d/99-custom" amavis_custom = "/etc/amavis/conf.d/99-custom"
@@ -103,6 +118,36 @@ class Backup():
def backupDBs(self): def backupDBs(self):
"""Backing up databases""" """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): def run(self):
self.setPath() self.setPath()
@@ -110,5 +155,6 @@ class Backup():
self.backupMails() self.backupMails()
self.backupCustomConfig() self.backupCustomConfig()
self.backupDBs() self.backupDBs()
self.backupCompletion()