diff --git a/actions/backups b/actions/backups index 5a79bc01f..62e872829 100755 --- a/actions/backups +++ b/actions/backups @@ -41,7 +41,8 @@ def parse_arguments(): create = subparsers.add_parser('create', help='Create archive') create.add_argument('--name', help='Archive name', required=True) - create.add_argument('--path', help='Path to archive', required=True) + create.add_argument( + '--path', help='Paths to include in archive', nargs='+') delete = subparsers.add_parser('delete', help='Delete archive') delete.add_argument('--name', help='Archive name', required=True) @@ -91,8 +92,7 @@ def subcommand_create(arguments): """Create archive.""" subprocess.run([ 'borg', 'create', '--json', REPOSITORY + '::' + arguments.name, - arguments.path - ], check=True) + ] + arguments.path, check=True) def subcommand_delete(arguments): diff --git a/plinth/modules/backups/__init__.py b/plinth/modules/backups/__init__.py index 68ff63e62..0567b56b6 100644 --- a/plinth/modules/backups/__init__.py +++ b/plinth/modules/backups/__init__.py @@ -22,6 +22,7 @@ import json from django.utils.translation import ugettext_lazy as _ +from .backups import backup_apps from plinth import actions from plinth.menu import main_menu from plinth.modules import udiskie @@ -67,9 +68,15 @@ def get_archive(name): return None -def create_archive(name, path): +def _backup_handler(packet): + """Performs backup operation on packet.""" + paths = packet.directories + packet.files actions.superuser_run('backups', - ['create', '--name', name, '--path', path]) + ['create', '--name', packet.label, '--path'] + paths) + + +def create_archive(name, app_names): + backup_apps(_backup_handler, app_names, name) def delete_archive(name): diff --git a/plinth/modules/backups/backups.py b/plinth/modules/backups/backups.py index e317d963e..ec65ca64b 100644 --- a/plinth/modules/backups/backups.py +++ b/plinth/modules/backups/backups.py @@ -63,7 +63,7 @@ def _validate_directories_and_files(df): class Packet: """Information passed to a handlers for backup/restore operations.""" - def __init__(self, operation, scope, root, manifests=None): + def __init__(self, operation, scope, root, manifests=None, label=None): """Initialize the packet. operation is either 'backup' or 'restore. @@ -80,6 +80,7 @@ class Packet: self.scope = scope self.root = root self.manifests = manifests + self.label = label self.directories = [] self.files = [] @@ -95,7 +96,7 @@ class Packet: self.files += backup[x]['files'] -def backup_full(backup_handler): +def backup_full(backup_handler, label=None): """Backup the entire system.""" if not _is_snapshot_available(): raise Exception('Full backup is not supported without snapshots.') @@ -103,7 +104,7 @@ def backup_full(backup_handler): snapshot = _take_snapshot() backup_root = snapshot['mount_path'] - packet = Packet('backup', 'full', backup_root) + packet = Packet('backup', 'full', backup_root, label) _run_operation(backup_handler, packet) _delete_snapshot(snapshot) @@ -122,7 +123,7 @@ def restore_full(restore_handler): _switch_to_subvolume(subvolume) -def backup_apps(backup_handler, app_names=None): +def backup_apps(backup_handler, app_names=None, label=None): """Backup data belonging to a set of applications.""" if not app_names: apps = _list_of_all_apps_for_backup() @@ -141,7 +142,7 @@ def backup_apps(backup_handler, app_names=None): backup_root = '/' snapshotted = False - packet = Packet('backup', 'apps', backup_root, manifests) + packet = Packet('backup', 'apps', backup_root, manifests, label) _run_operation(backup_handler, packet) if snapshotted: diff --git a/plinth/modules/backups/forms.py b/plinth/modules/backups/forms.py index b23ea8171..2c221e948 100644 --- a/plinth/modules/backups/forms.py +++ b/plinth/modules/backups/forms.py @@ -38,10 +38,6 @@ class CreateArchiveForm(forms.Form): help_text=_('Apps to include in the backup'), widget=forms.CheckboxSelectMultiple) - path = forms.CharField(label=_('Path'), strip=True, help_text=_( - 'Disk path to a folder on this server that will be archived into ' - 'backup repository.')) - def __init__(self, *args, **kwargs): """Initialize the form with selectable apps.""" super().__init__(*args, **kwargs) diff --git a/plinth/modules/backups/views.py b/plinth/modules/backups/views.py index ab6b26aff..e0e1dc7cf 100644 --- a/plinth/modules/backups/views.py +++ b/plinth/modules/backups/views.py @@ -71,7 +71,7 @@ class CreateArchiveView(SuccessMessageMixin, FormView): def form_valid(self, form): """Create the archive on valid form submission.""" backups.create_archive(form.cleaned_data['name'], - form.cleaned_data['path']) + form.cleaned_data['selected_apps']) return super().form_valid(form)