Add option to compress backups

This commit is contained in:
Andrew 2022-03-02 11:34:26 -05:00
parent 15610210b9
commit e0b8fb35fe
8 changed files with 69 additions and 10 deletions

View File

@ -104,8 +104,8 @@ class Management_Controller:
return management_helper.get_backup_config(server_id) return management_helper.get_backup_config(server_id)
@staticmethod @staticmethod
def set_backup_config(server_id: int, backup_path: str = None, max_backups: int = None, excluded_dirs: list = None): def set_backup_config(server_id: int, backup_path: str = None, max_backups: int = None, excluded_dirs: list = None, compress: bool = False,):
return management_helper.set_backup_config(server_id, backup_path, max_backups, excluded_dirs) return management_helper.set_backup_config(server_id, backup_path, max_backups, excluded_dirs, compress)
@staticmethod @staticmethod
def get_excluded_backup_dirs(server_id: int): def get_excluded_backup_dirs(server_id: int):

View File

@ -128,6 +128,7 @@ class Backups(Model):
excluded_dirs = CharField(null=True) excluded_dirs = CharField(null=True)
max_backups = IntegerField() max_backups = IntegerField()
server_id = ForeignKeyField(Servers, backref='backups_server') server_id = ForeignKeyField(Servers, backref='backups_server')
compress = BooleanField(default=False)
class Meta: class Meta:
table_name = 'backups' table_name = 'backups'
database = database database = database
@ -313,19 +314,21 @@ class helpers_management:
"backup_path": row.server_id.backup_path, "backup_path": row.server_id.backup_path,
"excluded_dirs": row.excluded_dirs, "excluded_dirs": row.excluded_dirs,
"max_backups": row.max_backups, "max_backups": row.max_backups,
"server_id": row.server_id.server_id "server_id": row.server_id.server_id,
"compress": row.compress
} }
except IndexError: except IndexError:
conf = { conf = {
"backup_path": None, "backup_path": None,
"excluded_dirs": None, "excluded_dirs": None,
"max_backups": 0, "max_backups": 0,
"server_id": server_id "server_id": server_id,
"compress": False,
} }
return conf return conf
@staticmethod @staticmethod
def set_backup_config(server_id: int, backup_path: str = None, max_backups: int = None, excluded_dirs: list = None): def set_backup_config(server_id: int, backup_path: str = None, max_backups: int = None, excluded_dirs: list = None, compress: bool = False):
logger.debug(f"Updating server {server_id} backup config with {locals()}") logger.debug(f"Updating server {server_id} backup config with {locals()}")
if Backups.select().where(Backups.server_id == server_id).count() != 0: if Backups.select().where(Backups.server_id == server_id).count() != 0:
new_row = False new_row = False
@ -334,7 +337,8 @@ class helpers_management:
conf = { conf = {
"excluded_dirs": None, "excluded_dirs": None,
"max_backups": 0, "max_backups": 0,
"server_id": server_id "server_id": server_id,
"compress": False
} }
new_row = True new_row = True
if max_backups is not None: if max_backups is not None:
@ -342,6 +346,7 @@ class helpers_management:
if excluded_dirs is not None: if excluded_dirs is not None:
dirs_to_exclude = ",".join(excluded_dirs) dirs_to_exclude = ",".join(excluded_dirs)
conf['excluded_dirs'] = dirs_to_exclude conf['excluded_dirs'] = dirs_to_exclude
conf['compress'] = compress
if not new_row: if not new_row:
with database.atomic(): with database.atomic():
if backup_path is not None: if backup_path is not None:

View File

@ -9,7 +9,7 @@ from app.classes.shared.console import console
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
try: try:
from zipfile import ZipFile from zipfile import ZipFile, ZIP_DEFLATED
except ModuleNotFoundError as err: except ModuleNotFoundError as err:
logger.critical(f"Import Error: Unable to load {err.name} module", exc_info=True) logger.critical(f"Import Error: Unable to load {err.name} module", exc_info=True)
@ -87,4 +87,25 @@ class FileHelpers:
return True return True
@staticmethod
def make_compressed_archive(path_to_destination, path_to_zip):
# create a ZipFile object
path_to_destination += '.zip'
with ZipFile(path_to_destination, 'w', ZIP_DEFLATED) as z:
for root, _dirs, files in os.walk(path_to_zip, topdown=True):
ziproot = path_to_zip
for file in files:
try:
logger.info(f"backing up: {os.path.join(root, file)}")
if os.name == "nt":
z.write(os.path.join(root, file), os.path.join(root.replace(ziproot, ""), file))
else:
z.write(os.path.join(root, file), os.path.join(root.replace(ziproot, "/"), file))
except Exception as e:
logger.warning(f"Error backing up: {os.path.join(root, file)}! - Error was: {e}")
return True
file_helper = FileHelpers() file_helper = FileHelpers()

View File

@ -604,6 +604,11 @@ class Server:
else: else:
# If not, just remove the file # If not, just remove the file
os.remove(excluded_dir) os.remove(excluded_dir)
if conf['compress']:
logger.debug("Found compress backup to be true. Calling compressed archive")
file_helper.make_compressed_archive(helper.get_os_understandable_path(backup_filename), tempDir)
else:
logger.debug("Found compress backup to be false. Calling NON-compressed archive")
file_helper.make_archive(helper.get_os_understandable_path(backup_filename), tempDir) file_helper.make_archive(helper.get_os_understandable_path(backup_filename), tempDir)
while len(self.list_backups()) > conf["max_backups"] and conf["max_backups"] > 0: while len(self.list_backups()) > conf["max_backups"] and conf["max_backups"] > 0:

View File

@ -1061,6 +1061,7 @@ class PanelHandler(BaseHandler):
logger.debug(self.request.arguments) logger.debug(self.request.arguments)
server_id = self.get_argument('id', None) server_id = self.get_argument('id', None)
server_obj = self.controller.servers.get_server_obj(server_id) server_obj = self.controller.servers.get_server_obj(server_id)
compress = self.get_argument('compress', False)
check_changed = self.get_argument('changed') check_changed = self.get_argument('changed')
if str(check_changed) == str(1): if str(check_changed) == str(1):
checked = self.get_body_arguments('root_path') checked = self.get_body_arguments('root_path')
@ -1091,7 +1092,7 @@ class PanelHandler(BaseHandler):
server_obj = self.controller.servers.get_server_obj(server_id) server_obj = self.controller.servers.get_server_obj(server_id)
server_obj.backup_path = backup_path server_obj.backup_path = backup_path
self.controller.servers.update_server(server_obj) self.controller.servers.update_server(server_obj)
self.controller.management.set_backup_config(server_id, max_backups=max_backups, excluded_dirs=checked) self.controller.management.set_backup_config(server_id, max_backups=max_backups, excluded_dirs=checked, compress=bool(compress))
self.controller.management.add_to_audit_log(exec_user['user_id'], self.controller.management.add_to_audit_log(exec_user['user_id'],
f"Edited server {server_id}: updated backups", f"Edited server {server_id}: updated backups",

View File

@ -55,6 +55,16 @@
<div class="form-group"> <div class="form-group">
<label for="server_path">{{ translate('serverBackups', 'maxBackups', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverBackups', 'maxBackupsDesc', data['lang']) }}</small> </label> <label for="server_path">{{ translate('serverBackups', 'maxBackups', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverBackups', 'maxBackupsDesc', data['lang']) }}</small> </label>
<input type="text" class="form-control" name="max_backups" id="max_backups" value="{{ data['backup_config']['max_backups'] }}" placeholder="{{ translate('serverBackups', 'maxBackups', data['lang']) }}" > <input type="text" class="form-control" name="max_backups" id="max_backups" value="{{ data['backup_config']['max_backups'] }}" placeholder="{{ translate('serverBackups', 'maxBackups', data['lang']) }}" >
</div>
<div class="form-group">
<label for="compress" class="form-check-label ml-4 mb-4"></label>
{% if data['backup_config']['compress'] %}
<input type="checkbox" class="form-check-input" id="compress" name="compress"
checked="" value="True">{{ translate('serverBackups', 'compress', data['lang']) }}
{% else %}
<input type="checkbox" class="form-check-input" id="compress" name="compress"
value="True">{{ translate('serverBackups', 'compress', data['lang']) }}
{% end %}
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="server">{{ translate('serverBackups', 'exclusionsTitle', data['lang']) }} <small> - {{ translate('serverBackups', 'excludedChoose', data['lang']) }}</small></label> <label for="server">{{ translate('serverBackups', 'exclusionsTitle', data['lang']) }} <small> - {{ translate('serverBackups', 'excludedChoose', data['lang']) }}</small></label>

View File

@ -0,0 +1,16 @@
# Generated by database migrator
import peewee
def migrate(migrator, database, **kwargs):
migrator.add_columns('backups', compress=peewee.BooleanField(default=False))
"""
Write your migrations here.
"""
def rollback(migrator, database, **kwargs):
migrator.drop_columns('backups', ['compress'])
"""
Write your rollback migrations here.
"""

View File

@ -243,7 +243,8 @@
"excludedBackups": "Excluded Paths: ", "excludedBackups": "Excluded Paths: ",
"excludedChoose": "Choose the paths you wish to exclude from your backups", "excludedChoose": "Choose the paths you wish to exclude from your backups",
"clickExclude": "Click to select Exclusions", "clickExclude": "Click to select Exclusions",
"exclusionsTitle": "Backup Exclusions" "exclusionsTitle": "Backup Exclusions",
"compress": "Compress Backup"
}, },
"serverFiles": { "serverFiles": {
"noscript": "The file manager does not work without JavaScript", "noscript": "The file manager does not work without JavaScript",