From d83f81be66f52238cfc3319a14a75215bc096eca Mon Sep 17 00:00:00 2001 From: zamentur Date: Sat, 3 Oct 2015 22:17:02 +0200 Subject: [PATCH] [fix] Restore with the app restore script from the backup --- data/actionsmap/yunohost.yml | 3 ++ data/hooks/restore/08-conf_ssh | 9 +++- data/hooks/restore/11-conf_ynh_mysql | 2 +- data/hooks/restore/21-conf_ynh_certs | 2 +- data/hooks/restore/23-data_mail | 2 +- lib/yunohost/backup.py | 80 ++++++++++++++++++++-------- locales/en.json | 5 ++ 7 files changed, 77 insertions(+), 26 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 9dfb4a499..125858d35 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -628,6 +628,9 @@ backup: --ignore-apps: help: Do not restore apps action: store_true + --ignore-hooks: + help: Do not restore hooks + action: store_true --force: help: Force restauration on an already installed system action: store_true diff --git a/data/hooks/restore/08-conf_ssh b/data/hooks/restore/08-conf_ssh index 71ac9df38..0c0f9bf9b 100644 --- a/data/hooks/restore/08-conf_ssh +++ b/data/hooks/restore/08-conf_ssh @@ -1,4 +1,9 @@ backup_dir="$1/conf/ssh" -sudo cp -a $backup_dir/. /etc/ssh -sudo service ssh restart +if [ -d /etc/ssh/ ]; then + sudo cp -a $backup_dir/. /etc/ssh + sudo service ssh restart +else + echo "SSH is not installed" +fi + diff --git a/data/hooks/restore/11-conf_ynh_mysql b/data/hooks/restore/11-conf_ynh_mysql index bbea73fb1..e4d71b369 100644 --- a/data/hooks/restore/11-conf_ynh_mysql +++ b/data/hooks/restore/11-conf_ynh_mysql @@ -1,6 +1,6 @@ backup_dir="$1/conf/ynh/mysql" -service mysql restart +sudo service mysql restart sudo cp -a $backup_dir/mysql /etc/yunohost/mysql mysqlpwd=$(sudo cat /etc/yunohost/mysql) sudo mysqladmin flush-privileges -p"$mysqlpwd" diff --git a/data/hooks/restore/21-conf_ynh_certs b/data/hooks/restore/21-conf_ynh_certs index 897e303ff..d1eb532ed 100644 --- a/data/hooks/restore/21-conf_ynh_certs +++ b/data/hooks/restore/21-conf_ynh_certs @@ -1,6 +1,6 @@ backup_dir="$1/conf/ynh/certs" -mkdir -p /etc/yunohost/certs/ +sudo mkdir -p /etc/yunohost/certs/ sudo cp -a $backup_dir/. /etc/yunohost/certs/ sudo yunohost app ssowatconf diff --git a/data/hooks/restore/23-data_mail b/data/hooks/restore/23-data_mail index 594c667dd..995308273 100644 --- a/data/hooks/restore/23-data_mail +++ b/data/hooks/restore/23-data_mail @@ -1,6 +1,6 @@ backup_dir="$1/data/mail" -sudo cp -a $backup_dir/. /var/mail +sudo cp -a $backup_dir/. /var/mail/ || echo 'No mail found' # Restart services to use migrated certs sudo service postfix restart diff --git a/lib/yunohost/backup.py b/lib/yunohost/backup.py index 9e1200f98..a5809ff72 100644 --- a/lib/yunohost/backup.py +++ b/lib/yunohost/backup.py @@ -162,6 +162,8 @@ def backup_create(name=None, description=None, output_directory=None, for app_id in apps_filtered: app_setting_path = '/etc/yunohost/apps/' + app_id + tmp_app_dir = '{:s}/apps/{:s}'.format(tmp_dir, app_id) + # Check if the app has a backup script app_script = app_setting_path + '/scripts/backup' if not os.path.isfile(app_script): @@ -169,8 +171,22 @@ def backup_create(name=None, description=None, output_directory=None, msignals.display(m18n.n('unbackup_app', app_id), 'warning') continue + + # Copy the app restore script + app_restore_script = app_setting_path + '/scripts/restore' + if os.path.isfile(app_script): + try: + filesystem.mkdir(tmp_app_dir, 0750, True, uid='admin') + shutil.copy(app_restore_script, tmp_app_dir) + except: + logger.exception("error while copying restore script of '%s'", app_id) + msignals.display(m18n.n('restore_app_copy_failed', app=app_id), + 'warning') + else: + logger.warning("restore script '%s' not found", app_script) + msignals.display(m18n.n('unrestorable_app', app_id), + 'warning') - tmp_app_dir = '{:s}/apps/{:s}'.format(tmp_dir, app_id) tmp_app_bkp_dir = tmp_app_dir + '/backup' msignals.display(m18n.n('backup_running_app_script', app_id)) try: @@ -251,7 +267,7 @@ def backup_create(name=None, description=None, output_directory=None, return { 'archive': info } -def backup_restore(name, hooks=[], apps=[], ignore_apps=False, force=False): +def backup_restore(name, hooks=[], apps=[], ignore_apps=False, ignore_hooks=False, force=False): """ Restore from a local backup archive @@ -265,6 +281,7 @@ def backup_restore(name, hooks=[], apps=[], ignore_apps=False, force=False): """ from yunohost.hook import hook_add from yunohost.hook import hook_callback + from yunohost.hook import hook_exec # Retrieve and open the archive archive_file = backup_info(name)['path'] @@ -329,32 +346,53 @@ def backup_restore(name, hooks=[], apps=[], ignore_apps=False, force=False): logger.info("executing the post-install...") tools_postinstall(domain, 'yunohost', True) + # Run hooks + if not ignore_hooks: + msignals.display(m18n.n('restore_running_hooks')) + hook_callback('restore', hooks, args=[tmp_dir]) + # Add apps restore hook if not ignore_apps: # Filter applications to restore apps_list = set(info['apps'].keys()) apps_filtered = set() - if apps: - for a in apps: - if a not in apps_list: - logger.warning("app '%s' not found", a) - msignals.display(m18n.n('unrestore_app', a), 'warning') - else: - apps_filtered.add(a) - else: - apps_filtered = apps_list - - for app_id in apps_filtered: - hook = "/etc/yunohost/apps/%s/scripts/restore" % app_id - if os.path.isfile(hook): - hook_add(app_id, hook) - logger.info("app '%s' will be restored", app_id) - else: + if not apps: + apps=apps_list + + from yunohost.app import _is_installed + for app_id in apps: + if app_id not in apps_list: + logger.warning("app '%s' not found", app_id) msignals.display(m18n.n('unrestore_app', app_id), 'warning') + elif _is_installed(app_id): + logger.warning("app '%s' already installed", app_id) + msignals.display(m18n.n('restore_already_installed_app', app=app_id), 'warning') + elif not os.path.isfile('{:s}/apps/{:s}/restore'.format(tmp_dir, app_id)): + logger.warning("backup for '%s' doesn't contain a restore script", app_id) + msignals.display(m18n.n('no_restore_script', app=app_id), 'warning') + else: + apps_filtered.add(app_id) + + for app_id in apps_filtered: + app_bkp_dir='{:s}/apps/{:s}'.format(tmp_dir, app_id) + try: + # Copy app settings + app_setting_path = '/etc/yunohost/apps/' + app_id + shutil.copytree(app_bkp_dir + '/settings', app_setting_path + '/settings') + + # Execute app restore script + app_restore_script=app_bkp_dir+'/restore' + tmp_script = '/tmp/restore_%s_%s' % (name,app_id) + subprocess.call(['install', '-Dm555', app_restore_script, tmp_script]) + hook_exec(tmp_script, args=[app_bkp_dir, app_id]) + + except: + logger.exception("error while restoring backup of '%s'", app_id) + msignals.display(m18n.n('restore_app_failed', app=app_id), + 'error') + # Cleaning settings directory + shutil.rmtree(app_setting_path + '/settings', ignore_errors=True) - # Run hooks - msignals.display(m18n.n('restore_running_hooks')) - hook_callback('restore', hooks, args=[tmp_dir]) # Remove temporary directory os.system('rm -rf %s' % tmp_dir) diff --git a/locales/en.json b/locales/en.json index 6838c7ddb..286d7257b 100644 --- a/locales/en.json +++ b/locales/en.json @@ -156,10 +156,15 @@ "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}]", + "restore_app_failed" : "Unable to restore the app '{app:s}'", "restore_running_hooks" : "Running restoration hooks...", "restore_failed" : "Unable to restore the system", "restore_complete" : "Restore complete", + "restore_already_installed_app": "An app is already installed with the id '{app:s}'", "unbackup_app" : "App '{:s}' will not be saved", + "unrestorable_app" : "App '{:s}' will not be restored", + "restore_app_copy_failed" : "Unable to copy the restore script of app '{app:s}'", + "no_restore_script": "No restore script found for the app '{app:s}'", "unrestore_app" : "App '{:s}' will not be restored", "backup_delete_error" : "Unable to delete '{:s}'", "backup_deleted" : "Backup successfully deleted",