Starting work on backup system
This commit is contained in:
@@ -6,11 +6,16 @@ import sys
|
|||||||
from .. import utils
|
from .. import utils
|
||||||
|
|
||||||
|
|
||||||
def install(appname, config, upgrade):
|
def install(appname, config, upgrade, backup):
|
||||||
"""Install an application."""
|
"""Install an application."""
|
||||||
if (config.has_option(appname, "enabled") and
|
if (config.has_option(appname, "enabled") and
|
||||||
not config.getboolean(appname, "enabled")):
|
not config.getboolean(appname, "enabled")):
|
||||||
return
|
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)
|
utils.printcolor("Installing {}".format(appname), utils.MAGENTA)
|
||||||
try:
|
try:
|
||||||
script = importlib.import_module(
|
script = importlib.import_module(
|
||||||
|
|||||||
114
modoboa_installer/scripts/backup.py
Normal file
114
modoboa_installer/scripts/backup.py
Normal 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()
|
||||||
|
|
||||||
|
|
||||||
@@ -163,19 +163,26 @@ def copy_from_template(template, dest, context):
|
|||||||
fp.write(ConfigFileTemplate(buf).substitute(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."""
|
"""Create a new installer config file if needed."""
|
||||||
|
isPresent = True
|
||||||
if os.path.exists(dest):
|
if os.path.exists(dest):
|
||||||
return
|
return isPresent
|
||||||
if upgrade:
|
if upgrade:
|
||||||
printcolor(
|
printcolor(
|
||||||
"You cannot upgrade an existing installation without a "
|
"You cannot upgrade an existing installation without a "
|
||||||
"configuration file.", RED)
|
"configuration file.", RED)
|
||||||
sys.exit(1)
|
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(
|
printcolor(
|
||||||
"Configuration file {} not found, creating new one."
|
"Configuration file {} not found, creating new one."
|
||||||
.format(dest), YELLOW)
|
.format(dest), YELLOW)
|
||||||
gen_config(dest, interactive)
|
gen_config(dest, interactive)
|
||||||
|
return isPresent
|
||||||
|
|
||||||
|
|
||||||
def has_colours(stream):
|
def has_colours(stream):
|
||||||
|
|||||||
24
run.py
24
run.py
@@ -44,6 +44,13 @@ def upgrade_disclaimer(config):
|
|||||||
" will be impacted:", utils.BLUE
|
" 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):
|
def main(input_args):
|
||||||
"""Install process."""
|
"""Install process."""
|
||||||
@@ -51,6 +58,8 @@ def main(input_args):
|
|||||||
versions = (
|
versions = (
|
||||||
["latest"] + list(compatibility_matrix.COMPATIBILITY_MATRIX.keys())
|
["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,
|
parser.add_argument("--debug", action="store_true", default=False,
|
||||||
help="Enable debug output")
|
help="Enable debug output")
|
||||||
parser.add_argument("--force", action="store_true", default=False,
|
parser.add_argument("--force", action="store_true", default=False,
|
||||||
@@ -79,8 +88,8 @@ def main(input_args):
|
|||||||
if args.debug:
|
if args.debug:
|
||||||
utils.ENV["debug"] = True
|
utils.ENV["debug"] = True
|
||||||
utils.printcolor("Welcome to Modoboa installer!\n", utils.GREEN)
|
utils.printcolor("Welcome to Modoboa installer!\n", utils.GREEN)
|
||||||
utils.check_config_file(args.configfile, args.interactive, args.upgrade)
|
wasConfigFileAlreadyThere = utils.check_config_file(args.configfile, args.interactive, args.upgrade, args.backup)
|
||||||
if args.stop_after_configfile_check:
|
if args.stop_after_configfile_check or (not wasConfigFileAlreadyThere and args.backup):
|
||||||
return
|
return
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
with open(args.configfile) as fp:
|
with open(args.configfile) as fp:
|
||||||
@@ -91,11 +100,14 @@ def main(input_args):
|
|||||||
config.set("dovecot", "domain", args.domain)
|
config.set("dovecot", "domain", args.domain)
|
||||||
config.set("modoboa", "version", args.version)
|
config.set("modoboa", "version", args.version)
|
||||||
config.set("modoboa", "install_beta", str(args.beta))
|
config.set("modoboa", "install_beta", str(args.beta))
|
||||||
# Display disclaimerpython 3 linux distribution
|
# Display disclaimer python 3 linux distribution
|
||||||
if not args.upgrade:
|
if args.upgrade:
|
||||||
installation_disclaimer(args, config)
|
|
||||||
else:
|
|
||||||
upgrade_disclaimer(config)
|
upgrade_disclaimer(config)
|
||||||
|
elif args.backup:
|
||||||
|
backup_disclamer()
|
||||||
|
else:
|
||||||
|
installation_disclaimer(args, config)
|
||||||
|
|
||||||
# Show concerned components
|
# Show concerned components
|
||||||
components = []
|
components = []
|
||||||
for section in config.sections():
|
for section in config.sections():
|
||||||
|
|||||||
Reference in New Issue
Block a user