From 00015e4d033db2613a19523e1451b6957dfadbac Mon Sep 17 00:00:00 2001 From: opi Date: Tue, 22 Sep 2015 20:04:21 +0200 Subject: [PATCH 01/13] [enh] Create shallow clone to increase app installation time --- lib/yunohost/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index d8b1b7b7a..4b88ebb0c 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -1034,7 +1034,7 @@ def _fetch_app_from_git(app): if os.system('wget "%s" -O "%s.zip" > /dev/null 2>&1' % (url, app_tmp_folder)) == 0: return _extract_app_from_file(app_tmp_folder +'.zip', remove=True) - git_result = os.system('git clone %s %s' % (app, app_tmp_folder)) + git_result = os.system('git clone --depth=1 %s %s' % (app, app_tmp_folder)) git_result_2 = 0 try: with open(app_tmp_folder + '/manifest.json') as json_manifest: @@ -1064,7 +1064,7 @@ def _fetch_app_from_git(app): app_tmp_folder = install_tmp +'/'+ app if os.path.exists(app_tmp_folder): shutil.rmtree(app_tmp_folder) - git_result = os.system('git clone %s -b %s %s' % (app_info['git']['url'], app_info['git']['branch'], app_tmp_folder)) + git_result = os.system('git clone --depth=1 %s -b %s %s' % (app_info['git']['url'], app_info['git']['branch'], app_tmp_folder)) git_result_2 = os.system('cd %s && git reset --hard %s' % (app_tmp_folder, str(app_info['git']['revision']))) if not git_result == git_result_2 == 0: From b03f7d7413f5a363ecb6796b2bc25e0aa3d46414 Mon Sep 17 00:00:00 2001 From: opi Date: Tue, 22 Sep 2015 22:05:40 +0200 Subject: [PATCH 02/13] [fix] Can't reset a shallow clone --- lib/yunohost/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index 4b88ebb0c..05b2789ad 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -1064,7 +1064,7 @@ def _fetch_app_from_git(app): app_tmp_folder = install_tmp +'/'+ app if os.path.exists(app_tmp_folder): shutil.rmtree(app_tmp_folder) - git_result = os.system('git clone --depth=1 %s -b %s %s' % (app_info['git']['url'], app_info['git']['branch'], app_tmp_folder)) + git_result = os.system('git clone %s -b %s %s' % (app_info['git']['url'], app_info['git']['branch'], app_tmp_folder)) git_result_2 = os.system('cd %s && git reset --hard %s' % (app_tmp_folder, str(app_info['git']['revision']))) if not git_result == git_result_2 == 0: From c1e97a17d38f6f7ae3600fc66a4598febb0b3cf6 Mon Sep 17 00:00:00 2001 From: zamentur Date: Wed, 30 Sep 2015 22:27:36 +0200 Subject: [PATCH 03/13] [enh] Disable restore of all mysql, it will be done by apps --- data/hooks/restore/11-system_mysql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/hooks/restore/11-system_mysql b/data/hooks/restore/11-system_mysql index 23293b153..f25e4ef6f 100644 --- a/data/hooks/restore/11-system_mysql +++ b/data/hooks/restore/11-system_mysql @@ -1,5 +1,5 @@ backup_dir="$1/mysql" mysqlpwd=$(sudo cat /etc/yunohost/mysql) -sudo mysql -uroot -p"$mysqlpwd" mysql < $backup_dir/mysql.sql +#sudo mysql -uroot -p"$mysqlpwd" mysql < $backup_dir/mysql.sql sudo mysqladmin flush-privileges -p"$mysqlpwd" From 85626134ef30e8af6234a9b40b6c908901bf377e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Wed, 30 Sep 2015 21:51:28 +0200 Subject: [PATCH 04/13] [enh] Allow to filter which app to backup/restore --- data/actionsmap/yunohost.yml | 6 ++++++ lib/yunohost/backup.py | 37 ++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index ef03afcdb..bbeba80d3 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -590,6 +590,9 @@ backup: --hooks: help: List of backup hooks names to execute nargs: "*" + --apps: + help: List of application names to backup + nargs: "*" --ignore-apps: help: Do not backup apps action: store_true @@ -606,6 +609,9 @@ backup: --hooks: help: List of restauration hooks names to execute nargs: "*" + --apps: + help: List of application names to restore + nargs: "*" --ignore-apps: help: Do not restore apps action: store_true diff --git a/lib/yunohost/backup.py b/lib/yunohost/backup.py index 7f98b118d..2e21c3e7d 100644 --- a/lib/yunohost/backup.py +++ b/lib/yunohost/backup.py @@ -42,7 +42,7 @@ logger = getActionLogger('yunohost.backup') def backup_create(name=None, description=None, output_directory=None, - no_compress=False, hooks=[], ignore_apps=False): + no_compress=False, hooks=[], apps=[], ignore_apps=False): """ Create a backup local archive @@ -52,6 +52,7 @@ def backup_create(name=None, description=None, output_directory=None, output_directory -- Output directory for the backup no_compress -- Do not create an archive file hooks -- List of backup hooks names to execute + apps -- List of application names to backup ignore_apps -- Do not backup apps """ @@ -126,8 +127,22 @@ def backup_create(name=None, description=None, output_directory=None, # Add apps backup hook if not ignore_apps: from yunohost.app import app_info + + # Filter applications to backup + apps_list = set(os.listdir('/etc/yunohost/apps')) + 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('unbackup_app', a), 'warning') + else: + apps_filtered.add(a) + else: + apps_filtered = apps_list + try: - for app_id in os.listdir('/etc/yunohost/apps'): + for app_id in apps_filtered: hook = '/etc/yunohost/apps/%s/scripts/backup' % app_id if os.path.isfile(hook): hook_add(app_id, hook) @@ -192,13 +207,14 @@ def backup_create(name=None, description=None, output_directory=None, msignals.display(m18n.n('backup_complete'), 'success') -def backup_restore(name, hooks=[], ignore_apps=False, force=False): +def backup_restore(name, hooks=[], apps=[], ignore_apps=False, force=False): """ Restore from a local backup archive Keyword argument: name -- Name of the local backup archive hooks -- List of restoration hooks names to execute + apps -- List of application names to restore ignore_apps -- Do not restore apps force -- Force restauration on an already installed system @@ -270,7 +286,20 @@ def backup_restore(name, hooks=[], ignore_apps=False, force=False): # Add apps restore hook if not ignore_apps: - for app_id in info['apps'].keys(): + # 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) From 3fe92d81f72105b7c189f66b445df55dc721e4ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Wed, 30 Sep 2015 22:05:40 +0200 Subject: [PATCH 05/13] [fix] Retrieve the domain to restore only for the postinstall --- lib/yunohost/backup.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/yunohost/backup.py b/lib/yunohost/backup.py index 2e21c3e7d..9106197bc 100644 --- a/lib/yunohost/backup.py +++ b/lib/yunohost/backup.py @@ -255,15 +255,6 @@ def backup_restore(name, hooks=[], apps=[], ignore_apps=False, force=False): logger.info("restoring from backup '%s' created on %s", name, time.ctime(info['created_at'])) - # Retrieve domain from the backup - try: - with open("%s/yunohost/current_host" % tmp_dir, 'r') as f: - domain = f.readline().rstrip() - except IOError: - logger.error("unable to retrieve domain from '%s/yunohost/current_host'", - tmp_dir) - raise MoulinetteError(errno.EIO, m18n.n('backup_invalid_archive')) - # Check if YunoHost is installed if os.path.isfile('/etc/yunohost/installed'): msignals.display(m18n.n('yunohost_already_installed'), 'warning') @@ -281,6 +272,16 @@ def backup_restore(name, hooks=[], apps=[], ignore_apps=False, force=False): raise MoulinetteError(errno.EEXIST, m18n.n('restore_failed')) else: from yunohost.tools import tools_postinstall + + # Retrieve the domain from the backup + try: + with open("%s/yunohost/current_host" % tmp_dir, 'r') as f: + domain = f.readline().rstrip() + except IOError: + logger.error("unable to retrieve domain from '%s/yunohost/current_host'", + tmp_dir) + raise MoulinetteError(errno.EIO, m18n.n('backup_invalid_archive')) + logger.info("executing the post-install...") tools_postinstall(domain, 'yunohost', True) @@ -337,6 +338,7 @@ def backup_list(): except ValueError: continue result.append(name) + result.sort() return { 'archives': result } From 4c37d8f27349b91770329cc59b1e1e0651652c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Thu, 1 Oct 2015 00:28:10 +0200 Subject: [PATCH 06/13] [fix] Do not process app backup script as hook --- lib/yunohost/app.py | 6 +++-- lib/yunohost/backup.py | 52 +++++++++++++++++++++++------------------- locales/en.json | 1 + 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index d8b1b7b7a..ac8026668 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -351,7 +351,8 @@ def app_upgrade(auth, app=[], url=None, file=None): for line in lines: sources.write(re.sub(r''+ original_app_id +'', app_id, line)) - # Add hooks + # Clean hooks and add new ones + hook_remove(app_id) if 'hooks' in os.listdir(app_tmp_folder): for hook in os.listdir(app_tmp_folder +'/hooks'): hook_add(app_id, app_tmp_folder +'/hooks/'+ hook) @@ -451,7 +452,8 @@ def app_install(auth, app, label=None, args=None): os.makedirs(app_setting_path) os.system('touch %s/settings.yml' % app_setting_path) - # Add hooks + # Clean hooks and add new ones + hook_remove(app_id) if 'hooks' in os.listdir(app_tmp_folder): for file in os.listdir(app_tmp_folder +'/hooks'): hook_add(app_id, app_tmp_folder +'/hooks/'+ file) diff --git a/lib/yunohost/backup.py b/lib/yunohost/backup.py index 9106197bc..b294fea18 100644 --- a/lib/yunohost/backup.py +++ b/lib/yunohost/backup.py @@ -57,8 +57,7 @@ def backup_create(name=None, description=None, output_directory=None, """ # TODO: Add a 'clean' argument to clean output directory - from yunohost.hook import hook_add - from yunohost.hook import hook_callback + from yunohost.hook import hook_callback, hook_exec tmp_dir = None @@ -117,6 +116,10 @@ def backup_create(name=None, description=None, output_directory=None, else: os.system('chown -hR admin: %s' % tmp_dir) + # Run system hooks + msignals.display(m18n.n('backup_running_hooks')) + hook_callback('backup', hooks, args=[tmp_dir]) + # Initialize backup info info = { 'description': description or '', @@ -124,7 +127,7 @@ def backup_create(name=None, description=None, output_directory=None, 'apps': {}, } - # Add apps backup hook + # Backup apps if not ignore_apps: from yunohost.app import app_info @@ -141,28 +144,28 @@ def backup_create(name=None, description=None, output_directory=None, else: apps_filtered = apps_list - try: - for app_id in apps_filtered: - hook = '/etc/yunohost/apps/%s/scripts/backup' % app_id - if os.path.isfile(hook): - hook_add(app_id, hook) + # Run apps backup scripts + for app_id in apps_filtered: + script = '/etc/yunohost/apps/{:s}/scripts/backup'.format(app_id) + if not os.path.isfile(script): + logger.warning("backup script '%s' not found", script) + msignals.display(m18n.n('unbackup_app', app_id), + 'warning') + continue - # Add app info - i = app_info(app_id) - info['apps'][app_id] = { - 'version': i['version'], - } - else: - logger.warning("unable to find app's backup hook '%s'", - hook) - msignals.display(m18n.n('unbackup_app', app_id), - 'warning') - except IOError as e: - logger.info("unable to add apps backup hook: %s", str(e)) - - # Run hooks - msignals.display(m18n.n('backup_running_hooks')) - hook_callback('backup', hooks, args=[tmp_dir]) + try: + msignals.display(m18n.n('backup_running_app_script', app_id)) + hook_exec(script, args=[tmp_dir]) + except: + logger.exception("error while executing script '%s'", script) + msignals.display(m18n.n('unbackup_app', app_id), + 'error') + else: + # Add app info + i = app_info(app_id) + info['apps'][app_id] = { + 'version': i['version'], + } # Create backup info file with open("%s/info.json" % tmp_dir, 'w') as f: @@ -367,6 +370,7 @@ def backup_info(name): info_file) raise MoulinetteError(errno.EIO, m18n.n('backup_invalid_archive')) + # TODO: TAILLE! return { 'path': archive_file, 'created_at': time.strftime(m18n.n('format_datetime_short'), diff --git a/locales/en.json b/locales/en.json index 2d5ff8dd6..4006ff6ed 100644 --- a/locales/en.json +++ b/locales/en.json @@ -143,6 +143,7 @@ "backup_output_directory_forbidden" : "Forbidden output directory", "backup_output_directory_not_empty" : "Output directory is not empty", "backup_running_hooks" : "Running backup hooks...", + "backup_running_app_script" : "Running backup script of app '{:s}'...", "backup_creating_archive" : "Creating the backup archive...", "backup_extracting_archive" : "Extracting the backup archive...", "backup_archive_open_failed" : "Unable to open the backup archive", From cf0af877d928630c785bb5de1bebe4a3003b55aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Thu, 1 Oct 2015 02:49:51 +0200 Subject: [PATCH 07/13] [enh] Add succeed hooks to the backup archive info --- lib/yunohost/backup.py | 13 +++++++++---- lib/yunohost/hook.py | 8 ++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/yunohost/backup.py b/lib/yunohost/backup.py index b294fea18..81693ca70 100644 --- a/lib/yunohost/backup.py +++ b/lib/yunohost/backup.py @@ -116,17 +116,21 @@ def backup_create(name=None, description=None, output_directory=None, else: os.system('chown -hR admin: %s' % tmp_dir) - # Run system hooks - msignals.display(m18n.n('backup_running_hooks')) - hook_callback('backup', hooks, args=[tmp_dir]) - # Initialize backup info info = { 'description': description or '', 'created_at': timestamp, 'apps': {}, + 'hooks': {}, } + # Run system hooks + msignals.display(m18n.n('backup_running_hooks')) + hooks_ret = hook_callback('backup', hooks, args=[tmp_dir]) + + # Add hooks results to the info + info['hooks'] = hooks_ret['succeed'] + # Backup apps if not ignore_apps: from yunohost.app import app_info @@ -377,4 +381,5 @@ def backup_info(name): time.gmtime(info['created_at'])), 'description': info['description'], 'apps': info['apps'], + 'hooks': info['hooks'], } diff --git a/lib/yunohost/hook.py b/lib/yunohost/hook.py index 8384ec942..ab8bdacf9 100644 --- a/lib/yunohost/hook.py +++ b/lib/yunohost/hook.py @@ -174,7 +174,7 @@ def hook_callback(action, hooks=[], args=None): args -- Ordered list of arguments to pass to the script """ - result = { 'succeed': list(), 'failed': list() } + result = { 'succeed': {}, 'failed': {} } hooks_dict = {} # Retrieve hooks @@ -209,15 +209,15 @@ def hook_callback(action, hooks=[], args=None): # Iterate over hooks and execute them for priority in sorted(hooks_dict): for name, info in iter(hooks_dict[priority].items()): + state = 'succeed' filename = '%s-%s' % (priority, name) try: hook_exec(info['path'], args=args) except: logger.exception("error while executing hook '%s'", info['path']) - result['failed'].append(filename) - else: - result['succeed'].append(filename) + state = 'failed' + result[state][filename] = info['path'] return result From 89b6b79e60ac84a36ca08b427ac2dd6bace51d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Thu, 1 Oct 2015 03:06:32 +0200 Subject: [PATCH 08/13] [enh] Add archive size to backup info and return info at creation --- data/actionsmap/yunohost.yml | 4 ++++ lib/yunohost/backup.py | 15 +++++++++++++-- lib/yunohost/monitor.py | 10 +++++----- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index bbeba80d3..69a3cb291 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -635,6 +635,10 @@ backup: arguments: name: help: Name of the local backup archive + -H: + full: --human-readable + help: Print sizes in human readable format + action: store_true ############################# diff --git a/lib/yunohost/backup.py b/lib/yunohost/backup.py index 81693ca70..b63b2c864 100644 --- a/lib/yunohost/backup.py +++ b/lib/yunohost/backup.py @@ -213,6 +213,10 @@ def backup_create(name=None, description=None, output_directory=None, msignals.display(m18n.n('backup_complete'), 'success') + # Return backup info + info['name'] = name + return { 'archive': info } + def backup_restore(name, hooks=[], apps=[], ignore_apps=False, force=False): """ @@ -350,14 +354,17 @@ def backup_list(): return { 'archives': result } -def backup_info(name): +def backup_info(name, human_readable=False): """ Get info about a local backup archive Keyword arguments: name -- Name of the local backup archive + human_readable -- Print sizes in human readable format """ + from yunohost.monitor import binary_to_human + archive_file = '%s/%s.tar.gz' % (archives_path, name) if not os.path.isfile(archive_file): logger.error("no local backup archive found at '%s'", archive_file) @@ -374,7 +381,10 @@ def backup_info(name): info_file) raise MoulinetteError(errno.EIO, m18n.n('backup_invalid_archive')) - # TODO: TAILLE! + size = os.path.getsize(archive_file) + if human_readable: + size = binary_to_human(size) + 'B' + return { 'path': archive_file, 'created_at': time.strftime(m18n.n('format_datetime_short'), @@ -382,4 +392,5 @@ def backup_info(name): 'description': info['description'], 'apps': info['apps'], 'hooks': info['hooks'], + 'size': size, } diff --git a/lib/yunohost/monitor.py b/lib/yunohost/monitor.py index 541e0892e..9db5e3234 100644 --- a/lib/yunohost/monitor.py +++ b/lib/yunohost/monitor.py @@ -130,7 +130,7 @@ def monitor_disk(units=None, mountpoint=None, human_readable=False): else: if human_readable: for i in ['used', 'avail', 'size']: - d[i] = _binary_to_human(d[i]) + 'B' + d[i] = binary_to_human(d[i]) + 'B' _set(dname, d) for dname in devices_names: _set(dname, 'not-available') @@ -201,7 +201,7 @@ def monitor_network(units=None, human_readable=False): if human_readable: for k in i.keys(): if k != 'time_since_update': - i[k] = _binary_to_human(i[k]) + 'B' + i[k] = binary_to_human(i[k]) + 'B' result[u][iname] = i elif u == 'infos': try: @@ -261,10 +261,10 @@ def monitor_system(units=None, human_readable=False): if human_readable: for i in ram.keys(): if i != 'percent': - ram[i] = _binary_to_human(ram[i]) + 'B' + ram[i] = binary_to_human(ram[i]) + 'B' for i in swap.keys(): if i != 'percent': - swap[i] = _binary_to_human(swap[i]) + 'B' + swap[i] = binary_to_human(swap[i]) + 'B' result[u] = { 'ram': ram, 'swap': swap @@ -510,7 +510,7 @@ def _extract_inet(string, skip_netmask=False, skip_loopback=True): return result -def _binary_to_human(n, customary=False): +def binary_to_human(n, customary=False): """ Convert bytes or bits into human readable format with binary prefix From e5fa8556cfd07d02290eb277481d0d817bd3c87f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Thu, 1 Oct 2015 03:19:51 +0200 Subject: [PATCH 09/13] [fix] Copy app backup script with proper permissions to be executed --- lib/yunohost/backup.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/yunohost/backup.py b/lib/yunohost/backup.py index b63b2c864..5e56f5435 100644 --- a/lib/yunohost/backup.py +++ b/lib/yunohost/backup.py @@ -29,8 +29,8 @@ import sys import json import errno import time -import shutil import tarfile +import subprocess from moulinette.core import MoulinetteError from moulinette.utils.log import getActionLogger @@ -149,6 +149,7 @@ def backup_create(name=None, description=None, output_directory=None, apps_filtered = apps_list # Run apps backup scripts + tmp_script = '/tmp/backup_' + str(timestamp) for app_id in apps_filtered: script = '/etc/yunohost/apps/{:s}/scripts/backup'.format(app_id) if not os.path.isfile(script): @@ -159,7 +160,8 @@ def backup_create(name=None, description=None, output_directory=None, try: msignals.display(m18n.n('backup_running_app_script', app_id)) - hook_exec(script, args=[tmp_dir]) + subprocess.call(['install', '-Dm555', script, tmp_script]) + hook_exec(tmp_script, args=[tmp_dir]) except: logger.exception("error while executing script '%s'", script) msignals.display(m18n.n('unbackup_app', app_id), @@ -170,6 +172,7 @@ def backup_create(name=None, description=None, output_directory=None, info['apps'][app_id] = { 'version': i['version'], } + subprocess.call(['rm', '-f', tmp_script]) # Create backup info file with open("%s/info.json" % tmp_dir, 'w') as f: From e9a10e79fb9356ddc20b6cc48bf47005efc47285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Thu, 1 Oct 2015 19:27:19 +0200 Subject: [PATCH 10/13] [enh] Allow to show backup information at listing --- data/actionsmap/yunohost.yml | 13 +++++++++++++ lib/yunohost/backup.py | 25 ++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 69a3cb291..ca539090b 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -625,6 +625,15 @@ backup: api: GET /backup/archives configuration: lock: false + arguments: + -i: + full: --with-info + help: Show backup information for each archive + action: store_true + -H: + full: --human-readable + help: Print sizes in human readable format + action: store_true ### backup_info() info: @@ -635,6 +644,10 @@ backup: arguments: name: help: Name of the local backup archive + -d: + full: --with-details + help: Show additional backup information + action: store_true -H: full: --human-readable help: Print sizes in human readable format diff --git a/lib/yunohost/backup.py b/lib/yunohost/backup.py index 5e56f5435..703f4a285 100644 --- a/lib/yunohost/backup.py +++ b/lib/yunohost/backup.py @@ -31,6 +31,7 @@ import errno import time import tarfile import subprocess +from collections import OrderedDict from moulinette.core import MoulinetteError from moulinette.utils.log import getActionLogger @@ -332,10 +333,14 @@ def backup_restore(name, hooks=[], apps=[], ignore_apps=False, force=False): msignals.display(m18n.n('restore_complete'), 'success') -def backup_list(): +def backup_list(with_info=False, human_readable=False): """ List available local backup archives + Keyword arguments: + with_info -- Show backup information for each archive + human_readable -- Print sizes in human readable format + """ result = [] @@ -354,15 +359,22 @@ def backup_list(): result.append(name) result.sort() + if result and with_info: + d = OrderedDict() + for a in result: + d[a] = backup_info(a, human_readable=human_readable) + result = d + return { 'archives': result } -def backup_info(name, human_readable=False): +def backup_info(name, with_details=False, human_readable=False): """ Get info about a local backup archive Keyword arguments: name -- Name of the local backup archive + with_details -- Show additional backup information human_readable -- Print sizes in human readable format """ @@ -388,12 +400,15 @@ def backup_info(name, human_readable=False): if human_readable: size = binary_to_human(size) + 'B' - return { + result = { 'path': archive_file, 'created_at': time.strftime(m18n.n('format_datetime_short'), time.gmtime(info['created_at'])), 'description': info['description'], - 'apps': info['apps'], - 'hooks': info['hooks'], 'size': size, } + + if with_details: + for d in ['apps', 'hooks']: + result[d] = info[d] + return result From 79484416a30224bc45499168d5c8e4d2ec52a3f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Thu, 1 Oct 2015 20:28:34 +0200 Subject: [PATCH 11/13] [enh] Store hooks results by name instead of filename --- lib/yunohost/hook.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/yunohost/hook.py b/lib/yunohost/hook.py index ab8bdacf9..30d08ba1f 100644 --- a/lib/yunohost/hook.py +++ b/lib/yunohost/hook.py @@ -217,7 +217,10 @@ def hook_callback(action, hooks=[], args=None): logger.exception("error while executing hook '%s'", info['path']) state = 'failed' - result[state][filename] = info['path'] + try: + result[state][name].append(info['path']) + except KeyError: + result[state][name] = [info['path']] return result From b57d945af9576340622680a0be1be84eabff2d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Thu, 1 Oct 2015 20:51:20 +0200 Subject: [PATCH 12/13] [enh] Update dependencies for the upcoming unified package --- debian/control | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/debian/control b/debian/control index 561083c2e..4c96298da 100644 --- a/debian/control +++ b/debian/control @@ -9,17 +9,22 @@ Homepage: https://yunohost.org/ Package: moulinette-yunohost Architecture: all Depends: moulinette (>= 2.2.1), - python-psutil, - python-requests, - glances, - python-pip, - pyminiupnpc, - dnsutils, - bind9utils, - python-apt, - ca-certificates, - python-dnspython, - netcat-openbsd, - iproute + python-psutil, + python-requests, + glances, + python-pip, + pyminiupnpc, + dnsutils, + bind9utils, + python-apt, + ca-certificates, + python-dnspython, + netcat-openbsd, + iproute, + unzip, + git-core, + curl, + mariadb-server | mysql-server, php5-mysql | php5-mysqlnd +Conflicts: iptables-persistent Description: YunoHost Python scripts Python functions to manage a YunoHost instance From a4acd4c4e50dda6072242c01ebbf3ba764822d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Thu, 1 Oct 2015 22:07:43 +0200 Subject: [PATCH 13/13] [fix] Update backup_restore api route and configuration --- data/actionsmap/yunohost.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index ca539090b..b338616f4 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -600,9 +600,7 @@ backup: ### backup_restore() restore: action_help: Restore from a local backup archive - api: POST /restore - configuration: - authenticate: false + api: POST /backup/restore/ arguments: name: help: Name of the local backup archive