From 4d8b3c145d97fb8c6aba9ca58ca143a5e66ac546 Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Wed, 5 Sep 2018 06:21:56 -0400 Subject: [PATCH] backups: Use backups API for restore Signed-off-by: James Valleroy Reviewed-by: Joseph Nuthalapati --- actions/backups | 27 +++++++++++++++++++++------ plinth/modules/backups/__init__.py | 19 +++++++++++++++---- plinth/modules/backups/backups.py | 5 +++-- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/actions/backups b/actions/backups index f0a272842..40abc7546 100755 --- a/actions/backups +++ b/actions/backups @@ -25,6 +25,7 @@ import glob import json import os import subprocess +import sys import tarfile REPOSITORY = '/var/lib/freedombox/borgbackup' @@ -170,12 +171,26 @@ def subcommand_get_export_apps(arguments): def subcommand_restore(arguments): """Restore files from an exported archive.""" - prev_dir = os.getcwd() - try: - os.chdir('/') - subprocess.run(['tar', 'xf', arguments.filename], check=True) - finally: - os.chdir(prev_dir) + locations_data = ''.join(sys.stdin) + locations = json.loads(locations_data) + + found_file = False + with tarfile.open(arguments.filename) as t: + for member in t.getmembers(): + path = '/' + member.name + if path in locations['files']: + t.extract(member, '/') + found_file = True + else: + for d in locations['directories']: + if path.startswith(d): + t.extract(member, '/') + found_file = True + break + + if not found_file: + print('No matching files or directories found in archive:', locations) + sys.exit(1) def main(): diff --git a/plinth/modules/backups/__init__.py b/plinth/modules/backups/__init__.py index cb7dfb419..f3a559227 100644 --- a/plinth/modules/backups/__init__.py +++ b/plinth/modules/backups/__init__.py @@ -29,7 +29,7 @@ from plinth import actions from plinth.menu import main_menu from plinth.modules import udiskie -from .backups import backup_apps +from .backups import backup_apps, restore_apps version = 1 @@ -162,13 +162,24 @@ def get_export_apps(filename): return output.splitlines() +def _restore_handler(packet): + """Perform restore operation on packet.""" + locations = { + 'directories': packet.directories, + 'files': packet.files + } + locations_data = json.dumps(locations) + actions.superuser_run( + 'backups', ['restore', '--filename', packet.label], + input=locations_data.encode()) + + def restore_exported(label, name, apps=None): """Restore files from exported backup archive.""" filename = find_exported_archive(label, name) if filename: - # TODO: Use backups API. - actions.superuser_run( - 'backups', ['restore', '--filename', filename]) + restore_apps(_restore_handler, app_names=apps, create_subvolume=False, + backup_file=filename) else: raise FileNotFoundError( errno.ENOENT, os.strerror(errno.ENOENT), filename) diff --git a/plinth/modules/backups/backups.py b/plinth/modules/backups/backups.py index c5f31429e..36e834176 100644 --- a/plinth/modules/backups/backups.py +++ b/plinth/modules/backups/backups.py @@ -152,7 +152,8 @@ def backup_apps(backup_handler, app_names=None, label=None): _lockdown_apps(apps, lockdown=False) -def restore_apps(restore_handler, app_names=None, create_subvolume=True): +def restore_apps(restore_handler, app_names=None, create_subvolume=True, + backup_file=None): """Restore data belonging to a set of applications.""" if not app_names: apps = _list_of_all_apps_for_backup() @@ -171,7 +172,7 @@ def restore_apps(restore_handler, app_names=None, create_subvolume=True): restore_root = '/' subvolume = False - packet = Packet('restore', 'apps', restore_root, manifests) + packet = Packet('restore', 'apps', restore_root, manifests, backup_file) _run_operation(restore_handler, packet) if subvolume: