Starting work on backup system

This commit is contained in:
Spitap
2022-07-19 19:06:53 +02:00
parent 9ff989a062
commit 56ed214fb5
4 changed files with 147 additions and 9 deletions

View File

@@ -6,11 +6,16 @@ import sys
from .. import utils
def install(appname, config, upgrade):
def install(appname, config, upgrade, backup):
"""Install an application."""
if (config.has_option(appname, "enabled") and
not config.getboolean(appname, "enabled")):
return
if backup:
utils.printcolor("Starting up backup...", utils.MAGENTA)
script = importlib.import_module("modoboa_installer.backup")
getattr(script, Backup())(config).run()
return
utils.printcolor("Installing {}".format(appname), utils.MAGENTA)
try:
script = importlib.import_module(

View File

@@ -0,0 +1,114 @@
"""Backup script for pre-installed instance"""
import shutil
import utils
import os
#TODO: have version of each modoboa componenent saved into the config file to restore the same version
class Backup():
def __init__(self, config):
self.config = config
self.destinationPath = ""
self.BACKUPDIRECTORY = ["mails", "custom", "databases"]
def preparePath(self):
for dir in self.BACKUPDIRECTORY:
os.mkdir(self.destinationPath + dir)
def validatePath(self, path):
"""Check basic condition for backup directory"""
if os.path.isfile(path):
print("Error, you provided a file instead of a directory!")
return False
if not os.path.exists(path):
createDir = input(f"\"{path}\" doesn't exists, would you like to create it ? [Y/n]\n").lower()
if createDir == "y" or createDir == "yes":
os.mkdir(path)
else:
return False
if len(os.listdir(path)) != 0:
delDir = input("Warning : backup folder is not empty, it will be purged if you continue... [Y/n]").lower()
if delDir == "y" or delDir == "yes":
shutil.rmtree(path)
else:
return False
self.destinationPath = path
if self.destinationPath[-1] != "/":
self.destinationPath += "/"
self.preparePath()
return True
def setPath(self):
"""Setup backup directory"""
user_value = None
while (user_value != '' and not self.validatePath(user_value)):
print("Enter backup path, please provide an empty folder.")
user_value = utils.user_input("-> ")
def backupConfigFile(self):
utils.copy_file("installer.cfg", self.destinationPath)
def backupMails(self):
utils.printcolor("Backing up mails", utils.MAGENTA)
home_path = self.config.get("dovecot", "home_dir")
if not os.path.exists(home_path) or os.path.isfile(home_path):
utils.printcolor("Error backing up Email, provided path "
f" ({home_path}) seems not right...", utils.RED)
else:
shutil.copytree(home_path, self.destinationPath+"mails/")
utils.printcolor("Mail backup complete!", utils.GREEN)
def backupCustomConfig(self):
"""Custom config :
- Amavis : /etc/amavis/conf.d/99-custom
- Postscreen : /etc/postfix/custom_whitelist.cidr
Feel free to suggest to add others!"""
utils.printcolor("Backing up some custom configuration...", utils.MAGENTA)
custom_path = self.destinationPath+"custom/"
"""AMAVIS"""
amavis_custom = "/etc/amavis/conf.d/99-custom"
if os.path.isfile(amavis_custom):
utils.copy_file(amavis_custom, custom_path)
utils.printcolor("Amavis custom configuration saved!", utils.GREEN)
"""POSTSCREEN"""
postscreen_custom = "/etc/postfix/custom_whitelist.cidr"
if os.path.isfile(postscreen_custom):
utils.copy_file(postscreen_custom, custom_path)
utils.printcolor("Postscreen whitelist custom configuration saved!", utils.GREEN)
def backupDBs(self):
"""Backing up databases"""
def run(self):
self.setPath()
self.backupConfigFile()
self.backupMails()
self.backupCustomConfig()
self.backupDBs()

View File

@@ -163,19 +163,26 @@ def copy_from_template(template, dest, context):
fp.write(ConfigFileTemplate(buf).substitute(context))
def check_config_file(dest, interactive=False, upgrade=False):
def check_config_file(dest, interactive=False, upgrade=False, backup=False):
"""Create a new installer config file if needed."""
isPresent = True
if os.path.exists(dest):
return
return isPresent
if upgrade:
printcolor(
"You cannot upgrade an existing installation without a "
"configuration file.", RED)
sys.exit(1)
elif backup:
isPresent = False
printcolor(
"Your configuration file hasn't been found. A new one will be generated. "
"Please edit it with correct password for the databases !", RED)
printcolor(
"Configuration file {} not found, creating new one."
.format(dest), YELLOW)
gen_config(dest, interactive)
return isPresent
def has_colours(stream):

22
run.py
View File

@@ -44,6 +44,13 @@ def upgrade_disclaimer(config):
" will be impacted:", utils.BLUE
)
def backup_disclamer():
"""Display backup disclamer. """
utils.printcolor(
"Your mail server will be backed up (messages and databases) locally."
" !! You should really transfer the backup somewhere else..."
" Custom configuration (like to postfix) won't be saved.", utils.BLUE)
def main(input_args):
"""Install process."""
@@ -51,6 +58,8 @@ def main(input_args):
versions = (
["latest"] + list(compatibility_matrix.COMPATIBILITY_MATRIX.keys())
)
parser.add_argument("--backup", action="store_true", default=False,
help="Backing up previously installed instance")
parser.add_argument("--debug", action="store_true", default=False,
help="Enable debug output")
parser.add_argument("--force", action="store_true", default=False,
@@ -79,8 +88,8 @@ def main(input_args):
if args.debug:
utils.ENV["debug"] = True
utils.printcolor("Welcome to Modoboa installer!\n", utils.GREEN)
utils.check_config_file(args.configfile, args.interactive, args.upgrade)
if args.stop_after_configfile_check:
wasConfigFileAlreadyThere = utils.check_config_file(args.configfile, args.interactive, args.upgrade, args.backup)
if args.stop_after_configfile_check or (not wasConfigFileAlreadyThere and args.backup):
return
config = configparser.ConfigParser()
with open(args.configfile) as fp:
@@ -92,10 +101,13 @@ def main(input_args):
config.set("modoboa", "version", args.version)
config.set("modoboa", "install_beta", str(args.beta))
# Display disclaimer python 3 linux distribution
if not args.upgrade:
installation_disclaimer(args, config)
else:
if args.upgrade:
upgrade_disclaimer(config)
elif args.backup:
backup_disclamer()
else:
installation_disclaimer(args, config)
# Show concerned components
components = []
for section in config.sections():