mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
snapshot: Improved messages and minor refactoring
- Make the default snapshot detection slightly more robust and refactor. - Expand description to explain automatic snapshotting, etc. - Show description even after setup. - Show default snapshot as a bootstrap label. - Message explaing how rollback can be undone. - Minor updates to delete/rollback confirmation messages. - Minor style refactoring
This commit is contained in:
parent
5e18a648e1
commit
d615709b8a
@ -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(_):
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 %}
|
||||
<h2>{{ title }}</h2>
|
||||
{% block configuration %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<table class="table table-bordered table-condensed table-striped">
|
||||
<thead>
|
||||
<th>{% trans "Number" %}</th>
|
||||
<th>{% trans "Date" %}</th>
|
||||
<th>{% trans "Description" %}</th>
|
||||
<th>{% trans "Rollback" %}</th>
|
||||
<th>{% trans "Delete" %}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for snapshot in snapshots %}
|
||||
{% if snapshot.description != "current" %}
|
||||
<tr>
|
||||
<td>{{ snapshot.number }}</td>
|
||||
<td>{{ snapshot.date }}</td>
|
||||
<td>
|
||||
{% if snapshot.is_default %}
|
||||
{% trans "[default subvolume]" %}<br />
|
||||
{% endif %}
|
||||
{{ snapshot.description }}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% url 'snapshot:rollback' snapshot.number %}"
|
||||
class="btn btn-default btn-sm"
|
||||
role="button"
|
||||
title="{% blocktrans with number=snapshot.number %}Rollback to snapshot #{{ number }}{% endblocktrans %}">
|
||||
<span class="glyphicon glyphicon-repeat"
|
||||
aria-hidden="true"></span>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{% if not snapshot.is_default %}
|
||||
<a href="{% url 'snapshot:delete' snapshot.number %}"
|
||||
class="btn btn-default btn-sm"
|
||||
role="button"
|
||||
title="{% blocktrans with number=snapshot.number %}Delete snapshot #{{ number }}{% endblocktrans %}">
|
||||
<span class="glyphicon glyphicon-trash"
|
||||
aria-hidden="true"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<thead>
|
||||
<th>{% trans "Number" %}</th>
|
||||
<th>{% trans "Date" %}</th>
|
||||
<th>{% trans "Description" %}</th>
|
||||
<th>{% trans "Rollback" %}</th>
|
||||
<th>{% trans "Delete" %}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for snapshot in snapshots %}
|
||||
{% if snapshot.description != "current" %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ snapshot.number }}
|
||||
{% if snapshot.is_default %}
|
||||
<span class="label label-primary">
|
||||
{% trans "active" %}
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ snapshot.date }}</td>
|
||||
<td>{{ snapshot.description }}</td>
|
||||
<td>
|
||||
<a href="{% url 'snapshot:rollback' snapshot.number %}"
|
||||
class="btn btn-default btn-sm" role="button"
|
||||
title="{% blocktrans trimmed with number=snapshot.number %}
|
||||
Rollback to snapshot #{{ number }}
|
||||
{% endblocktrans %}">
|
||||
<span class="glyphicon glyphicon-repeat"
|
||||
aria-hidden="true"></span>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{% if not snapshot.is_default %}
|
||||
<a href="{% url 'snapshot:delete' snapshot.number %}"
|
||||
class="btn btn-default btn-sm" role="button"
|
||||
title="{% blocktrans trimmed with number=snapshot.number %}
|
||||
Delete snapshot #{{ number }}
|
||||
{% endblocktrans %}">
|
||||
<span class="glyphicon glyphicon-trash"
|
||||
aria-hidden="true"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@ -79,7 +82,8 @@
|
||||
{% csrf_token %}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% trans "Create Snapshot" %}"/>
|
||||
value="{% trans "Create Snapshot" %}"/>
|
||||
</form>
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@ -24,11 +24,7 @@
|
||||
{% block content %}
|
||||
<h2>{{ title }}</h2>
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
The snapshot will be permanently deleted. Please confirm.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p>{% trans "Delete this snapshot permanently?" %}</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
@ -54,7 +50,9 @@
|
||||
{% csrf_token %}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% blocktrans with number=snapshot.number %}Delete Snapshot #{{ number }}{% endblocktrans %}"/>
|
||||
value="{% blocktrans trimmed with number=snapshot.number %}
|
||||
Delete Snapshot #{{ number }}
|
||||
{% endblocktrans %}"/>
|
||||
</form>
|
||||
</p>
|
||||
|
||||
|
||||
@ -24,9 +24,13 @@
|
||||
{% block content %}
|
||||
<h2>{{ title }}</h2>
|
||||
|
||||
<p>{% trans "Roll back the system to this snapshot?" %}</p>
|
||||
|
||||
<p>
|
||||
{% 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 %}
|
||||
</p>
|
||||
|
||||
@ -54,7 +58,9 @@
|
||||
{% csrf_token %}
|
||||
|
||||
<input type="submit" class="btn btn-primary"
|
||||
value="{% blocktrans with number=snapshot.number %}Rollback to Snapshot #{{ number }}{% endblocktrans %}"/>
|
||||
value="{% blocktrans trimmed with number=snapshot.number %}
|
||||
Rollback to Snapshot #{{ number }}
|
||||
{% endblocktrans %}"/>
|
||||
</form>
|
||||
</p>
|
||||
|
||||
|
||||
@ -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'),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user