From 3e5dcfcbf5e2af293230bd16f65aeb4f8c8a86b3 Mon Sep 17 00:00:00 2001
From: Joseph Nuthalapati
Date: Wed, 22 Nov 2017 20:27:13 +0530
Subject: [PATCH] snapshots: Button to delete all snapshots
- closes #1144
Signed-off-by: Joseph Nuthalapati
Reviewed-by: James Valleroy
---
actions/snapshot | 45 ++++++++++----
.../modules/snapshot/templates/snapshot.html | 40 +++++++++----
.../snapshot/templates/snapshot_delete.html | 2 +-
.../templates/snapshot_delete_all.html | 59 ++++++++++++++++++
plinth/modules/snapshot/urls.py | 3 +-
plinth/modules/snapshot/views.py | 60 ++++++++++++-------
6 files changed, 160 insertions(+), 49 deletions(-)
create mode 100644 plinth/modules/snapshot/templates/snapshot_delete_all.html
diff --git a/actions/snapshot b/actions/snapshot
index e21197baf..778f54de0 100755
--- a/actions/snapshot
+++ b/actions/snapshot
@@ -15,17 +15,17 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
#
-
"""
Configuration helper for filesystem snapshots.
"""
-import augeas
import argparse
import json
import os
import subprocess
+import augeas
+
FSTAB = '/etc/fstab'
AUG_FSTAB = '/files/etc/fstab'
@@ -39,9 +39,13 @@ def parse_arguments():
subparsers.add_parser('list', help='List snapshots')
subparsers.add_parser('create', help='Create snapshot')
- subparser = subparsers.add_parser('delete', help='Delete snapshot')
+ subparser = subparsers.add_parser('delete',
+ help='Delete a snapshot by number')
subparser.add_argument('number', help='Number of snapshot to delete')
+ subparser = subparsers.add_parser('delete-all',
+ help='Delete all the snapshots')
+
subparser = subparsers.add_parser('rollback', help='Rollback to snapshot')
subparser.add_argument('number', help='Number of snapshot to rollback to')
@@ -68,8 +72,8 @@ def _add_fstab_entry(mount_point):
"""Add mountpoint for subvolumes."""
snapshots_mount_point = os.path.join(mount_point, '.snapshots')
- aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
- augeas.Augeas.NO_MODL_AUTOLOAD)
+ aug = augeas.Augeas(
+ flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
aug.set('/augeas/load/Fstab/lens', 'Fstab.lns')
aug.set('/augeas/load/Fstab/incl[last() + 1]', FSTAB)
aug.load()
@@ -95,11 +99,15 @@ def _add_fstab_entry(mount_point):
aug.save()
-def subcommand_list(_):
- """List snapshots."""
+def _get_snapper_list():
command = ['snapper', 'list']
process = subprocess.run(command, stdout=subprocess.PIPE, check=True)
- lines = process.stdout.decode().splitlines()
+ return process.stdout.decode().splitlines()
+
+
+def subcommand_list(_):
+ """List snapshots."""
+ lines = _get_snapper_list()
keys = ('type', 'number', 'pre_number', 'date', 'user', 'cleanup',
'description')
snapshots = []
@@ -137,15 +145,30 @@ def subcommand_create(_):
def subcommand_delete(arguments):
- """Delete snapshot."""
+ """Delete a snapshot by number."""
command = ['snapper', 'delete', arguments.number]
subprocess.run(command, check=True)
+def subcommand_delete_all(_):
+ """Delete all the snapshots."""
+ lines = _get_snapper_list()
+ snapshot_range = [line.split('|')[1].strip() for line in lines[3:]]
+ if snapshot_range:
+ if len(snapshot_range) == 1:
+ to_delete = snapshot_range[0]
+ else:
+ to_delete = '-'.join([snapshot_range[0], snapshot_range[-1]])
+ command = ['snapper', 'delete', to_delete]
+ subprocess.run(command, check=True)
+
+
def subcommand_rollback(arguments):
"""Rollback to snapshot."""
- command = ['snapper', 'rollback', '--description', 'created by rollback',
- arguments.number]
+ command = [
+ 'snapper', 'rollback', '--description', 'created by rollback',
+ arguments.number
+ ]
subprocess.run(command, check=True)
diff --git a/plinth/modules/snapshot/templates/snapshot.html b/plinth/modules/snapshot/templates/snapshot.html
index 3fc81e2d5..72c60005c 100644
--- a/plinth/modules/snapshot/templates/snapshot.html
+++ b/plinth/modules/snapshot/templates/snapshot.html
@@ -22,6 +22,29 @@
{% load i18n %}
{% block configuration %}
+
+
+
-
-
-
-
{% endblock %}
diff --git a/plinth/modules/snapshot/templates/snapshot_delete.html b/plinth/modules/snapshot/templates/snapshot_delete.html
index 92d285c7c..f94eb791c 100644
--- a/plinth/modules/snapshot/templates/snapshot_delete.html
+++ b/plinth/modules/snapshot/templates/snapshot_delete.html
@@ -49,7 +49,7 @@
+
+
+{% endblock %}
diff --git a/plinth/modules/snapshot/urls.py b/plinth/modules/snapshot/urls.py
index 2dc1403a7..3ffd9d651 100644
--- a/plinth/modules/snapshot/urls.py
+++ b/plinth/modules/snapshot/urls.py
@@ -14,7 +14,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
#
-
"""
URLs for the snapshot module.
"""
@@ -23,10 +22,10 @@ from django.conf.urls import url
from . import views
-
urlpatterns = [
url(r'^sys/snapshot/$', views.index, name='index'),
url(r'^sys/snapshot/(?P\d+)/delete$', views.delete, name='delete'),
+ url(r'^sys/snapshot/all/delete$', views.delete_all, name='delete-all'),
url(r'^sys/snapshot/(?P\d+)/rollback$', views.rollback,
name='rollback'),
]
diff --git a/plinth/modules/snapshot/views.py b/plinth/modules/snapshot/views.py
index a300760ac..0a714be4c 100644
--- a/plinth/modules/snapshot/views.py
+++ b/plinth/modules/snapshot/views.py
@@ -14,17 +14,17 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
#
-
"""
Views for snapshot module.
"""
+import json
+
from django.contrib import messages
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.translation import ugettext as _
-import json
from plinth import actions
from plinth.modules import snapshot as snapshot_module
@@ -39,40 +39,55 @@ def index(request):
output = actions.superuser_run('snapshot', ['list'])
snapshots = json.loads(output)
- return TemplateResponse(request, 'snapshot.html',
- {'title': snapshot_module.name,
- 'description': snapshot_module.description,
- 'snapshots': snapshots})
+ return TemplateResponse(request, 'snapshot.html', {
+ 'title': snapshot_module.name,
+ 'description': snapshot_module.description,
+ 'snapshots': snapshots
+ })
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 #{number}.').format(number=number))
+ 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 = next(s for s in snapshots if s['number'] == number)
+
+ return TemplateResponse(request, 'snapshot_delete.html', {
+ 'title': _('Delete Snapshot'),
+ 'snapshot': snapshot
+ })
+
+
+def delete_all(request):
+ """Show confirmation to delete all snapshots."""
+ if request.method == 'POST':
+ actions.superuser_run('snapshot', ['delete-all'])
+ messages.success(request, _('Deleted all snapshots.'))
return redirect(reverse('snapshot:index'))
output = actions.superuser_run('snapshot', ['list'])
snapshots = json.loads(output)
- snapshot = None
- for current_snapshot in snapshots:
- if current_snapshot['number'] == number:
- snapshot = current_snapshot
-
- return TemplateResponse(request, 'snapshot_delete.html',
- {'title': _('Delete Snapshot'),
- 'snapshot': snapshot})
+ return TemplateResponse(request, 'snapshot_delete_all.html', {
+ 'title': _('Delete Snapshots'),
+ 'snapshots': snapshots[1:]
+ })
def rollback(request, number):
"""Show confirmation to rollback to a snapshot."""
if request.method == 'POST':
actions.superuser_run('snapshot', ['rollback', number])
- messages.success(
- request,
- _('Rolled back to snapshot #{number}.').format(number=number))
+ messages.success(request,
+ _('Rolled back to snapshot #{number}.').format(
+ number=number))
messages.warning(
request,
_('The system must be restarted to complete the rollback.'))
@@ -86,6 +101,7 @@ def rollback(request, number):
if current_snapshot['number'] == number:
snapshot = current_snapshot
- return TemplateResponse(request, 'snapshot_rollback.html',
- {'title': _('Rollback to Snapshot'),
- 'snapshot': snapshot})
+ return TemplateResponse(request, 'snapshot_rollback.html', {
+ 'title': _('Rollback to Snapshot'),
+ 'snapshot': snapshot
+ })