diff --git a/actions/snapshot b/actions/snapshot index 8f0a3dd64..0e196fcb8 100755 --- a/actions/snapshot +++ b/actions/snapshot @@ -85,17 +85,27 @@ def subcommand_list(_): parts = [part.strip() for part in line.split('|')] snapshots.append(dict(zip(keys, parts))) - # Mark default subvolume. + default = _get_default_snapshot() + for snapshot in snapshots: + snapshot['is_default'] = (snapshot['number'] == default) + + print(json.dumps(snapshots)) + + +def _get_default_snapshot(): + """Return the default snapshot by looking at default subvolume.""" command = ['btrfs', 'subvolume', 'get-default', '/'] process = subprocess.run(command, stdout=subprocess.PIPE, check=True) output = process.stdout.decode() - default = None - if '.snapshots' in output: - default = output.split('/')[1] - for snapshot in snapshots: - snapshot['is_default'] = snapshot['number'] == default - print(json.dumps(snapshots)) + output_parts = output.split() + if len(output_parts) >= 9: + path = output.split()[8] + path_parts = path.split('/') + if len(path_parts) == 3 and path_parts[0] == '.snapshots': + return path_parts[1] + + return None def subcommand_create(_): diff --git a/plinth/modules/snapshot/__init__.py b/plinth/modules/snapshot/__init__.py index c679cf7db..55e11ca40 100644 --- a/plinth/modules/snapshot/__init__.py +++ b/plinth/modules/snapshot/__init__.py @@ -35,7 +35,16 @@ title = _('Snapshots') description = [ _('Snapshots allows creating and managing filesystem snapshots. These can ' - 'be used to roll back the system to a previous state.') + 'be used to roll back the system to a previously known good state in ' + 'case of unwanted changes to the system.'), + + _('Automatic snapshots are taken every hour, day, month and year. Older ' + 'snapshots are automatically deleted keeping 10 of each kind and 50 in ' + 'total. Although snapshots are efficient and only store the ' + 'differences, they may be deleted to reclaim free space. Individual ' + 'files from older snapshots can be accessed by visiting ".snapshots" ' + 'directory in the filesystem. Snapshots are not a replacement for ' + 'backups.') ] service = None diff --git a/plinth/modules/snapshot/templates/snapshot.html b/plinth/modules/snapshot/templates/snapshot.html index 3a0d1b157..01eab9489 100644 --- a/plinth/modules/snapshot/templates/snapshot.html +++ b/plinth/modules/snapshot/templates/snapshot.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "simple_service.html" %} {% comment %} # # This file is part of Plinth. @@ -21,55 +21,58 @@ {% load bootstrap %} {% load i18n %} -{% block content %} -
| {% trans "Number" %} | -{% trans "Date" %} | -{% trans "Description" %} | -{% trans "Rollback" %} | -{% trans "Delete" %} | - - - {% for snapshot in snapshots %} - {% if snapshot.description != "current" %} -
|---|---|---|---|---|
| {{ snapshot.number }} | -{{ snapshot.date }} | -
- {% if snapshot.is_default %}
- {% trans "[default subvolume]" %} - {% endif %} - {{ snapshot.description }} - |
- - - - - | -- {% if not snapshot.is_default %} - - - - {% endif %} - | -{% trans "Number" %} | +{% trans "Date" %} | +{% trans "Description" %} | +{% trans "Rollback" %} | +{% trans "Delete" %} | + + + {% for snapshot in snapshots %} + {% if snapshot.description != "current" %} +
| + {{ snapshot.number }} + {% if snapshot.is_default %} + + {% trans "active" %} + + {% endif %} + | +{{ snapshot.date }} | +{{ snapshot.description }} | ++ + + + | ++ {% if not snapshot.is_default %} + + + + {% endif %} + | +
- {% blocktrans trimmed %} - The snapshot will be permanently deleted. Please confirm. - {% endblocktrans %} -
+{% trans "Delete this snapshot permanently?" %}
{% trans "Roll back the system to this snapshot?" %}
+{% blocktrans trimmed %} - The system will be rolled back to the selected snapshot. Please confirm. + A new snapshot with the current state of the file system will be + automatically created. You will be able to undo a rollback by + reverting to the newly created snapshot. {% endblocktrans %}
@@ -54,7 +58,9 @@ {% csrf_token %} + value="{% blocktrans trimmed with number=snapshot.number %} + Rollback to Snapshot #{{ number }} + {% endblocktrans %}"/> diff --git a/plinth/modules/snapshot/views.py b/plinth/modules/snapshot/views.py index 87702a4e9..1cdcbef0d 100644 --- a/plinth/modules/snapshot/views.py +++ b/plinth/modules/snapshot/views.py @@ -41,6 +41,7 @@ def index(request): return TemplateResponse(request, 'snapshot.html', {'title': snapshot_module.title, + 'description': snapshot_module.description, 'snapshots': snapshots}) @@ -48,16 +49,17 @@ def delete(request, number): """Show confirmation to delete a snapshot.""" if request.method == 'POST': actions.superuser_run('snapshot', ['delete', number]) - messages.success(request, _('Deleted snapshot.')) + messages.success( + request, _('Deleted snapshot #{number}.').format(number=number)) return redirect(reverse('snapshot:index')) output = actions.superuser_run('snapshot', ['list']) snapshots = json.loads(output) snapshot = None - for s in snapshots: - if s['number'] == number: - snapshot = s + for current_snapshot in snapshots: + if current_snapshot['number'] == number: + snapshot = current_snapshot return TemplateResponse(request, 'snapshot_delete.html', {'title': _('Delete Snapshot'), @@ -68,7 +70,9 @@ def rollback(request, number): """Show confirmation to rollback to a snapshot.""" if request.method == 'POST': actions.superuser_run('snapshot', ['rollback', number]) - messages.success(request, _('Set default subvolume for rollback.')) + messages.success( + request, + _('Rolled back to snapshot #{number}.').format(number=number)) messages.warning( request, _('The system must be restarted to complete the rollback.')) @@ -78,9 +82,9 @@ def rollback(request, number): snapshots = json.loads(output) snapshot = None - for s in snapshots: - if s['number'] == number: - snapshot = s + for current_snapshot in snapshots: + if current_snapshot['number'] == number: + snapshot = current_snapshot return TemplateResponse(request, 'snapshot_rollback.html', {'title': _('Rollback to Snapshot'),