mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
[fix] Validate backup/restore hooks and show restoration result
This commit is contained in:
parent
76c7b3b3db
commit
a51e395bca
2 changed files with 90 additions and 25 deletions
|
@ -62,7 +62,7 @@ def backup_create(name=None, description=None, output_directory=None,
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# TODO: Add a 'clean' argument to clean output directory
|
# TODO: Add a 'clean' argument to clean output directory
|
||||||
from yunohost.hook import hook_callback, hook_exec
|
from yunohost.hook import hook_list, hook_callback, hook_exec
|
||||||
|
|
||||||
tmp_dir = None
|
tmp_dir = None
|
||||||
|
|
||||||
|
@ -136,9 +136,24 @@ def backup_create(name=None, description=None, output_directory=None,
|
||||||
|
|
||||||
# Run system hooks
|
# Run system hooks
|
||||||
if not ignore_hooks:
|
if not ignore_hooks:
|
||||||
msignals.display(m18n.n('backup_running_hooks'))
|
# Check hooks availibility
|
||||||
hooks_ret = hook_callback('backup', hooks, args=[tmp_dir])
|
hooks_available = hook_list('backup')['hooks']
|
||||||
info['hooks'] = hooks_ret['succeed']
|
hooks_filtered = set()
|
||||||
|
if hooks:
|
||||||
|
for hook in hooks:
|
||||||
|
if hook not in hooks_available:
|
||||||
|
logger.exception("backup hook '%s' not found", hook)
|
||||||
|
msignals.display(m18n.n('backup_hook_unknown', hook=hook),
|
||||||
|
'error')
|
||||||
|
else:
|
||||||
|
hooks_filtered.add(hook)
|
||||||
|
else:
|
||||||
|
hooks_filtered = hooks_available
|
||||||
|
|
||||||
|
if hooks_filtered:
|
||||||
|
msignals.display(m18n.n('backup_running_hooks'))
|
||||||
|
ret = hook_callback('backup', hooks_filtered, args=[tmp_dir])
|
||||||
|
info['hooks'] = ret['succeed']
|
||||||
|
|
||||||
# Backup apps
|
# Backup apps
|
||||||
if not ignore_apps:
|
if not ignore_apps:
|
||||||
|
@ -205,10 +220,10 @@ def backup_create(name=None, description=None, output_directory=None,
|
||||||
finally:
|
finally:
|
||||||
filesystem.rm(tmp_script, force=True)
|
filesystem.rm(tmp_script, force=True)
|
||||||
|
|
||||||
# Check if something has been saved
|
# Check if something has been saved
|
||||||
if ignore_hooks and not info['apps']:
|
if not info['hooks'] and not info['apps']:
|
||||||
_clean_tmp_dir(1)
|
_clean_tmp_dir(1)
|
||||||
raise MoulinetteError(errno.EINVAL, m18n.n('backup_nothings_done'))
|
raise MoulinetteError(errno.EINVAL, m18n.n('backup_nothings_done'))
|
||||||
|
|
||||||
# Create backup info file
|
# Create backup info file
|
||||||
with open("%s/info.json" % tmp_dir, 'w') as f:
|
with open("%s/info.json" % tmp_dir, 'w') as f:
|
||||||
|
@ -270,9 +285,12 @@ def backup_restore(name, hooks=[], apps=[], ignore_apps=False, ignore_hooks=Fals
|
||||||
force -- Force restauration on an already installed system
|
force -- Force restauration on an already installed system
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from yunohost.hook import hook_add
|
from yunohost.hook import hook_add, hook_list, hook_callback, hook_exec
|
||||||
from yunohost.hook import hook_callback
|
|
||||||
from yunohost.hook import hook_exec
|
# Validate what to restore
|
||||||
|
if ignore_hooks and ignore_apps:
|
||||||
|
raise MoulinetteError(errno.EINVAL,
|
||||||
|
m18n.n('restore_action_required'))
|
||||||
|
|
||||||
# Retrieve and open the archive
|
# Retrieve and open the archive
|
||||||
info = backup_info(name)
|
info = backup_info(name)
|
||||||
|
@ -291,6 +309,13 @@ def backup_restore(name, hooks=[], apps=[], ignore_apps=False, ignore_hooks=Fals
|
||||||
tmp_dir)
|
tmp_dir)
|
||||||
os.system('rm -rf %s' % tmp_dir)
|
os.system('rm -rf %s' % tmp_dir)
|
||||||
|
|
||||||
|
def _clean_tmp_dir(retcode=0):
|
||||||
|
ret = hook_callback('post_backup_restore', args=[tmp_dir, retcode])
|
||||||
|
if not ret['failed']:
|
||||||
|
filesystem.rm(tmp_dir, True, True)
|
||||||
|
else:
|
||||||
|
msignals.display(m18n.n('restore_cleaning_failed'), 'warning')
|
||||||
|
|
||||||
# Extract the tarball
|
# Extract the tarball
|
||||||
msignals.display(m18n.n('backup_extracting_archive'))
|
msignals.display(m18n.n('backup_extracting_archive'))
|
||||||
tar.extractall(tmp_dir)
|
tar.extractall(tmp_dir)
|
||||||
|
@ -308,6 +333,12 @@ def backup_restore(name, hooks=[], apps=[], ignore_apps=False, ignore_hooks=Fals
|
||||||
logger.info("restoring from backup '%s' created on %s", name,
|
logger.info("restoring from backup '%s' created on %s", name,
|
||||||
time.ctime(info['created_at']))
|
time.ctime(info['created_at']))
|
||||||
|
|
||||||
|
# Initialize restauration summary result
|
||||||
|
result = {
|
||||||
|
'apps': [],
|
||||||
|
'hooks': {},
|
||||||
|
}
|
||||||
|
|
||||||
# Check if YunoHost is installed
|
# Check if YunoHost is installed
|
||||||
if os.path.isfile('/etc/yunohost/installed'):
|
if os.path.isfile('/etc/yunohost/installed'):
|
||||||
msignals.display(m18n.n('yunohost_already_installed'), 'warning')
|
msignals.display(m18n.n('yunohost_already_installed'), 'warning')
|
||||||
|
@ -338,18 +369,40 @@ def backup_restore(name, hooks=[], apps=[], ignore_apps=False, ignore_hooks=Fals
|
||||||
logger.info("executing the post-install...")
|
logger.info("executing the post-install...")
|
||||||
tools_postinstall(domain, 'yunohost', True)
|
tools_postinstall(domain, 'yunohost', True)
|
||||||
|
|
||||||
# Run hooks
|
# Run system hooks
|
||||||
if not ignore_hooks:
|
if not ignore_hooks:
|
||||||
if hooks is None or len(hooks)==0:
|
# Filter hooks to execute
|
||||||
hooks=info['hooks'].keys()
|
hooks_list = set(info['hooks'].keys())
|
||||||
|
_is_hook_in_backup = lambda h: True
|
||||||
|
if hooks:
|
||||||
|
def _is_hook_in_backup(h):
|
||||||
|
if h in hooks_list:
|
||||||
|
return True
|
||||||
|
logger.warning("hook '%s' not executed in the backup '%s'",
|
||||||
|
h, archive_file)
|
||||||
|
msignals.display(m18n.n('backup_archive_hook_not_exec', hook=h),
|
||||||
|
'error')
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
hooks = hooks_list
|
||||||
|
|
||||||
hooks_filtered=list(set(hooks) & set(info['hooks'].keys()))
|
# Check hooks availibility
|
||||||
hooks_unexecuted=set(hooks) - set(info['hooks'].keys())
|
hooks_available = hook_list('restore')['hooks']
|
||||||
for hook in hooks_unexecuted:
|
hooks_filtered = set()
|
||||||
logger.warning("hook '%s' not in this backup", hook)
|
for hook in hooks:
|
||||||
msignals.display(m18n.n('backup_hook_unavailable', hook), 'warning')
|
if not _is_hook_in_backup(hook):
|
||||||
msignals.display(m18n.n('restore_running_hooks'))
|
continue
|
||||||
hook_callback('restore', hooks_filtered, args=[tmp_dir])
|
if hook not in hooks_available:
|
||||||
|
logger.exception("restoration hook '%s' not found", hook)
|
||||||
|
msignals.display(m18n.n('restore_hook_unavailable', hook=hook),
|
||||||
|
'error')
|
||||||
|
continue
|
||||||
|
hooks_filtered.add(hook)
|
||||||
|
|
||||||
|
if hooks_filtered:
|
||||||
|
msignals.display(m18n.n('restore_running_hooks'))
|
||||||
|
ret = hook_callback('restore', hooks_filtered, args=[tmp_dir])
|
||||||
|
result['hooks'] = ret['succeed']
|
||||||
|
|
||||||
# Add apps restore hook
|
# Add apps restore hook
|
||||||
if not ignore_apps:
|
if not ignore_apps:
|
||||||
|
@ -409,14 +462,21 @@ def backup_restore(name, hooks=[], apps=[], ignore_apps=False, ignore_hooks=Fals
|
||||||
'error')
|
'error')
|
||||||
# Cleaning app directory
|
# Cleaning app directory
|
||||||
shutil.rmtree(app_setting_path, ignore_errors=True)
|
shutil.rmtree(app_setting_path, ignore_errors=True)
|
||||||
|
else:
|
||||||
|
result['apps'].append(app_id)
|
||||||
finally:
|
finally:
|
||||||
filesystem.rm(tmp_script, force=True)
|
filesystem.rm(tmp_script, force=True)
|
||||||
|
|
||||||
# Remove temporary directory
|
# Check if something has been restored
|
||||||
os.system('rm -rf %s' % tmp_dir)
|
if not result['hooks'] and not result['apps']:
|
||||||
|
_clean_tmp_dir(1)
|
||||||
|
raise MoulinetteError(errno.EINVAL, m18n.n('restore_nothings_done'))
|
||||||
|
|
||||||
|
_clean_tmp_dir()
|
||||||
msignals.display(m18n.n('restore_complete'), 'success')
|
msignals.display(m18n.n('restore_complete'), 'success')
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def backup_list(with_info=False, human_readable=False):
|
def backup_list(with_info=False, human_readable=False):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -144,6 +144,7 @@
|
||||||
"backup_output_directory_required" : "You must provide an output directory for the backup",
|
"backup_output_directory_required" : "You must provide an output directory for the backup",
|
||||||
"backup_output_directory_forbidden" : "Forbidden output directory",
|
"backup_output_directory_forbidden" : "Forbidden output directory",
|
||||||
"backup_output_directory_not_empty" : "Output directory is not empty",
|
"backup_output_directory_not_empty" : "Output directory is not empty",
|
||||||
|
"backup_hook_unknown" : "Backup hook '{hook:s}' unknown",
|
||||||
"backup_running_hooks" : "Running backup hooks...",
|
"backup_running_hooks" : "Running backup hooks...",
|
||||||
"backup_running_app_script" : "Running backup script of app '{:s}'...",
|
"backup_running_app_script" : "Running backup script of app '{:s}'...",
|
||||||
"backup_creating_archive" : "Creating the backup archive...",
|
"backup_creating_archive" : "Creating the backup archive...",
|
||||||
|
@ -151,18 +152,22 @@
|
||||||
"backup_archive_open_failed" : "Unable to open the backup archive",
|
"backup_archive_open_failed" : "Unable to open the backup archive",
|
||||||
"backup_archive_name_unknown" : "Unknown local backup archive named '{:s}'",
|
"backup_archive_name_unknown" : "Unknown local backup archive named '{:s}'",
|
||||||
"backup_archive_name_exists" : "Backup archive name already exists",
|
"backup_archive_name_exists" : "Backup archive name already exists",
|
||||||
|
"backup_archive_hook_not_exec" : "Hook '{hook:s}' not executed in this backup",
|
||||||
"backup_archive_app_not_found" : "App '{app:s}' not found in the backup archive",
|
"backup_archive_app_not_found" : "App '{app:s}' not found in the backup archive",
|
||||||
"backup_app_failed" : "Unable to back up the app '{app:s}'",
|
"backup_app_failed" : "Unable to back up the app '{app:s}'",
|
||||||
"backup_nothings_done" : "There is nothing to save",
|
"backup_nothings_done" : "There is nothing to save",
|
||||||
"backup_cleaning_failed" : "Unable to clean backup directory",
|
"backup_cleaning_failed" : "Unable to clean backup temporary directory",
|
||||||
"backup_complete" : "Backup complete",
|
"backup_complete" : "Backup complete",
|
||||||
"backup_invalid_archive" : "Invalid backup archive",
|
"backup_invalid_archive" : "Invalid backup archive",
|
||||||
"backup_hook_unavailable" : "The hook '{:s}' is not in this backup",
|
"restore_action_required" : "You must specify something to restore",
|
||||||
"restore_confirm_yunohost_installed" : "Do you really want to restore an already installed system? [{answers:s}]",
|
"restore_confirm_yunohost_installed" : "Do you really want to restore an already installed system? [{answers:s}]",
|
||||||
|
"restore_hook_unavailable" : "Restauration hook '{hook:s}' not available on your system",
|
||||||
"restore_app_failed" : "Unable to restore the app '{app:s}'",
|
"restore_app_failed" : "Unable to restore the app '{app:s}'",
|
||||||
"restore_running_hooks" : "Running restoration hooks...",
|
"restore_running_hooks" : "Running restoration hooks...",
|
||||||
"restore_running_app_script" : "Running restore script of app '{app:s}'...",
|
"restore_running_app_script" : "Running restore script of app '{app:s}'...",
|
||||||
"restore_failed" : "Unable to restore the system",
|
"restore_failed" : "Unable to restore the system",
|
||||||
|
"restore_nothings_done" : "Nothing has been restored",
|
||||||
|
"restore_cleaning_failed" : "Unable to clean restoration temporary directory",
|
||||||
"restore_complete" : "Restore complete",
|
"restore_complete" : "Restore complete",
|
||||||
"restore_already_installed_app": "An app is already installed with the id '{app:s}'",
|
"restore_already_installed_app": "An app is already installed with the id '{app:s}'",
|
||||||
"unbackup_app" : "App '{app:s}' will not be saved",
|
"unbackup_app" : "App '{app:s}' will not be saved",
|
||||||
|
|
Loading…
Add table
Reference in a new issue