database backup
This commit is contained in:
15
README.rst
15
README.rst
@@ -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
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user