[enh] Bind folders in data backup hooks instead of copying them

This commit is contained in:
Jérôme Lebleu 2015-10-03 00:56:52 +02:00
parent 8c3e27b769
commit 7280a56e16
7 changed files with 74 additions and 14 deletions

View file

@ -0,0 +1,29 @@
CAN_BIND=1
# Bind a directory or copy it on error
#
# usage: ynh_bind_or_cp srcdir destdir as_root
# | arg: srcdir - directory to bind or copy
# | arg: destdir - mountpoint or destination directory
# | arg: as_root - 1 to execute commands as root
ynh_bind_or_cp() {
SRCDIR=$1
DESTDIR=$2
SUDO_CMD="sudo"
[[ "$3" != "1" ]] && SUDO_CMD=""
if [[ $CAN_BIND == 1 ]]; then
$SUDO_CMD mkdir -p $DESTDIR
$SUDO_CMD mount --bind "$SRCDIR" "$DESTDIR"
if [[ $? == 0 ]]; then
for m in $(mount | grep " $SRCDIR" | awk '{ print $3 }'); do
$SUDO_CMD mount --bind "$m" "${DESTDIR}${m#${SRCDIR}}"
done
return
fi
echo "Error: bind mounting seems to be disabled on your system."
echo "You have maybe to check your apparmor configuration."
CAN_BIND=0
fi
$SUDO_CMD cp -r "$SRCDIR" "$DESTDIR"
}

View file

@ -1,4 +1,10 @@
backup_dir="$1/data/home"
mkdir -p $backup_dir
sudo rsync -a --exclude='/yunohost*' /home/ $backup_dir/
. /usr/share/yunohost/apps/helpers
for f in $(find /home/* -type d -prune | awk -F/ '{print $NF}'); do
if [[ ! "$f" =~ ^yunohost|lost\+found ]]; then
ynh_bind_or_cp "/home/$f" "${backup_dir}/$f" 1
fi
done

View file

@ -1,3 +1,5 @@
backup_dir="$1/data/mail"
sudo cp -a /var/mail/. $backup_dir
. /usr/share/yunohost/apps/helpers
ynh_bind_or_cp /var/mail $backup_dir 1

View file

@ -0,0 +1,13 @@
tmp_dir=$1
retcode=$2
FAILURE=0
# Iterate over inverted ordered mountpoints to prevent issues
for m in $(mount | grep " ${tmp_dir}" | awk '{ print $3 }' | tac); do
sudo umount $m
[[ $? != 0 ]] && FAILURE=1
done
exit $FAILURE

View file

@ -119,8 +119,12 @@ def backup_create(name=None, description=None, output_directory=None,
filesystem.rm(tmp_dir, recursive=True)
filesystem.mkdir(tmp_dir, 0750, parents=True, uid='admin')
def _clean_tmp_dir():
filesystem.rm(tmp_dir, True, True)
def _clean_tmp_dir(retcode=0):
ret = hook_callback('post_backup_create', args=[tmp_dir, retcode])
if not ret['failed']:
filesystem.rm(tmp_dir, True, True)
else:
msignals.display(m18n.n('backup_cleaning_failed'), 'warning')
# Initialize backup info
info = {
@ -194,7 +198,7 @@ def backup_create(name=None, description=None, output_directory=None,
# Check if something has been saved
if ignore_hooks and not info['apps']:
_clean_tmp_dir()
_clean_tmp_dir(1)
raise MoulinetteError(errno.EINVAL, m18n.n('backup_nothings_done'))
# Create backup info file
@ -224,7 +228,7 @@ def backup_create(name=None, description=None, output_directory=None,
logger.exception("unable to open the archive '%s' for writing",
archive_file)
if tar is None:
_clean_tmp_dir()
_clean_tmp_dir(2)
raise MoulinetteError(errno.EIO,
m18n.n('backup_archive_open_failed'))
tar.add(tmp_dir, arcname='')
@ -435,8 +439,8 @@ def backup_info(name, with_details=False, human_readable=False):
for d in ['apps', 'hooks']:
result[d] = info[d]
return result
def backup_delete(name):
"""
Delete a backup
@ -444,12 +448,12 @@ def backup_delete(name):
Keyword arguments:
name -- Name of the local backup archive
"""
"""
from yunohost.hook import hook_callback
hook_callback('pre_backup_delete', args=[name])
archive_file = '%s/%s.tar.gz' % (archives_path, name)
info_file = "%s/%s.info.json" % (archives_path, name)
for backup_file in [archive_file,info_file]:
if not os.path.isfile(backup_file):
@ -459,8 +463,9 @@ def backup_delete(name):
os.remove(backup_file)
except:
logger.exception("unable to delete '%s'", backup_file)
raise MoulinetteError(errno.EIO, m18n.n('backup_delete_error',backup_file))
raise MoulinetteError(errno.EIO,
m18n.n('backup_delete_error',backup_file))
hook_callback('post_backup_delete', args=[name])
msignals.display(m18n.n('backup_deleted'), 'success')

View file

@ -212,11 +212,15 @@ def hook_callback(action, hooks=[], args=None):
state = 'succeed'
filename = '%s-%s' % (priority, name)
try:
hook_exec(info['path'], args=args)
ret = hook_exec(info['path'], args=args)
except:
logger.exception("error while executing hook '%s'",
info['path'])
state = 'failed'
if ret != 0:
logger.error("error while executing hook '%s', retcode: %d",
info['path'], ret)
state = 'failed'
try:
result[state][name].append(info['path'])
except KeyError:

View file

@ -152,6 +152,7 @@
"backup_archive_name_exists" : "Backup archive name already exists",
"backup_app_failed" : "Unable to back up the app '{app:s}'",
"backup_nothings_done" : "There is nothing to save",
"backup_cleaning_failed" : "Unable to clean backup directory",
"backup_complete" : "Backup complete",
"backup_invalid_archive" : "Invalid backup archive",
"restore_confirm_yunohost_installed" : "Do you really want to restore an already installed system? [{answers:s}]",