mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
Option to enable/disble automatic timeline snapshots
Signed-off-by: Hanisha P<hanishap@thoughtworks.com> Reviewed-by: Joseph Nuthalapati <njoseph@thoughtworks.com>
This commit is contained in:
parent
a2997a0c70
commit
76ffad7955
@ -38,6 +38,7 @@ def parse_arguments():
|
||||
subparsers.add_parser('setup', help='Configure snapper')
|
||||
subparsers.add_parser('list', help='List snapshots')
|
||||
subparsers.add_parser('create', help='Create snapshot')
|
||||
subparsers.add_parser('get-config', help='Configurations of snapshot')
|
||||
|
||||
subparser = subparsers.add_parser('delete',
|
||||
help='Delete a snapshot by number')
|
||||
@ -46,6 +47,10 @@ def parse_arguments():
|
||||
subparser = subparsers.add_parser('delete-all',
|
||||
help='Delete all the snapshots')
|
||||
|
||||
subparser = subparsers.add_parser('configure',
|
||||
help='Configure automatic snapshots')
|
||||
subparser.add_argument('config')
|
||||
|
||||
subparser = subparsers.add_parser('rollback', help='Rollback to snapshot')
|
||||
subparser.add_argument('number', help='Number of snapshot to rollback to')
|
||||
|
||||
@ -163,6 +168,22 @@ def subcommand_delete_all(_):
|
||||
subprocess.run(command, check=True)
|
||||
|
||||
|
||||
def subcommand_configure(arguments):
|
||||
command = ['snapper', 'set-config', arguments.config]
|
||||
subprocess.run(command, check=True)
|
||||
|
||||
|
||||
def subcommand_get_config(_):
|
||||
command = ['snapper', 'get-config']
|
||||
process = subprocess.run(command, stdout=subprocess.PIPE, check=True)
|
||||
lines = process.stdout.decode().splitlines()
|
||||
config = {}
|
||||
for line in lines[2:]:
|
||||
parts = [part.strip() for part in line.split('|')]
|
||||
config[parts[0]] = parts[1]
|
||||
print(json.dumps(config))
|
||||
|
||||
|
||||
def subcommand_rollback(arguments):
|
||||
"""Rollback to snapshot."""
|
||||
command = [
|
||||
|
||||
@ -23,6 +23,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from plinth import actions
|
||||
from plinth.menu import main_menu
|
||||
import json
|
||||
|
||||
|
||||
version = 1
|
||||
@ -58,3 +59,11 @@ def setup(helper, old_version=None):
|
||||
"""Install and configure the module."""
|
||||
helper.install(managed_packages)
|
||||
helper.call('post', actions.superuser_run, 'snapshot', ['setup'])
|
||||
|
||||
|
||||
def is_timeline_snapshots_enabled():
|
||||
"""Return whether timeline snapshots are enabled."""
|
||||
output = actions.superuser_run('snapshot', ['get-config'])
|
||||
output = json.loads(output)
|
||||
return output['TIMELINE_CREATE'] == "yes"
|
||||
|
||||
|
||||
29
plinth/modules/snapshot/forms.py
Normal file
29
plinth/modules/snapshot/forms.py
Normal file
@ -0,0 +1,29 @@
|
||||
#
|
||||
# This file is part of Plinth.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
Forms for snapshot module.
|
||||
"""
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class SnapshotForm(forms.Form):
|
||||
enable_timeline_snapshots = forms.BooleanField(
|
||||
label=_('Enable Timeline Snapshots'), required=False, help_text=_(
|
||||
'Uncheck this to disable timeline snapshots '
|
||||
'(hourly, daily, monthly and yearly).'))
|
||||
@ -23,27 +23,32 @@
|
||||
|
||||
{% block configuration %}
|
||||
<p>
|
||||
<div class="row">
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
<h3>{% trans "Configuration" %}</h3>
|
||||
{{ form|bootstrap }}
|
||||
<input type="submit" class="btn btn-primary" name="update"
|
||||
value="{% trans "Update setup" %}"/>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-xs-6 text-left">
|
||||
<input type="submit" class="btn btn-primary"
|
||||
<input type="submit" class="btn btn-primary" name="create"
|
||||
value="{% trans 'Create Snapshot' %}"/>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
|
||||
<div class="col-xs-6 text-right">
|
||||
<a title="{% trans 'Delete all the snapshots' %}"
|
||||
role="button" class="btn btn-danger"
|
||||
{% if snapshots|length == 1 %}
|
||||
disabled="disabled"
|
||||
{% else %}
|
||||
href="{% url 'snapshot:delete-all' %}"
|
||||
{% endif %}>
|
||||
{% trans 'Delete All' %}
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-6 text-right">
|
||||
<a title="{% trans 'Delete all the snapshots' %}"
|
||||
role="button" class="btn btn-danger"
|
||||
{% if snapshots|length == 1 %}
|
||||
disabled="disabled"
|
||||
{% else %}
|
||||
href="{% url 'snapshot:delete-all' %}"
|
||||
{% endif %}>
|
||||
{% trans 'Delete All' %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<div class="row">
|
||||
|
||||
@ -27,14 +27,27 @@ from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from plinth import actions
|
||||
from plinth.errors import ActionError
|
||||
from plinth.modules import snapshot as snapshot_module
|
||||
|
||||
from . import is_timeline_snapshots_enabled
|
||||
from .forms import SnapshotForm
|
||||
|
||||
|
||||
def index(request):
|
||||
"""Show snapshot list."""
|
||||
status = get_status()
|
||||
if request.method == 'POST':
|
||||
actions.superuser_run('snapshot', ['create'])
|
||||
messages.success(request, _('Created snapshot.'))
|
||||
form = SnapshotForm(request.POST, prefix='snapshot')
|
||||
if 'create' in request.POST:
|
||||
actions.superuser_run('snapshot', ['create'])
|
||||
messages.success(request, _('Created snapshot.'))
|
||||
if 'update' in request.POST and form.is_valid():
|
||||
_apply_changes(request, status, form.cleaned_data)
|
||||
status = get_status()
|
||||
form = SnapshotForm(initial=status, prefix='snapshot')
|
||||
else:
|
||||
form = SnapshotForm(initial=status, prefix='snapshot')
|
||||
|
||||
output = actions.superuser_run('snapshot', ['list'])
|
||||
snapshots = json.loads(output)
|
||||
@ -42,7 +55,8 @@ def index(request):
|
||||
return TemplateResponse(request, 'snapshot.html', {
|
||||
'title': snapshot_module.name,
|
||||
'description': snapshot_module.description,
|
||||
'snapshots': snapshots
|
||||
'snapshots': snapshots,
|
||||
'form': form
|
||||
})
|
||||
|
||||
|
||||
@ -50,9 +64,8 @@ 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'])
|
||||
@ -85,9 +98,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,
|
||||
_('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.'))
|
||||
@ -105,3 +118,27 @@ def rollback(request, number):
|
||||
'title': _('Rollback to Snapshot'),
|
||||
'snapshot': snapshot
|
||||
})
|
||||
|
||||
|
||||
def get_status():
|
||||
return {'enable_timeline_snapshots': is_timeline_snapshots_enabled()}
|
||||
|
||||
|
||||
def _apply_changes(request, old_status, new_status):
|
||||
"""Try to apply changes and handle errors."""
|
||||
try:
|
||||
__apply_changes(request, old_status, new_status)
|
||||
except ActionError as exception:
|
||||
messages.error(request,
|
||||
_('Action error: {0} [{1}] [{2}]').format(
|
||||
exception.args[0], exception.args[1],
|
||||
exception.args[2]))
|
||||
|
||||
|
||||
def __apply_changes(request, old_status, new_status):
|
||||
if old_status['enable_timeline_snapshots'] != new_status['enable_timeline_snapshots']:
|
||||
timeline_create = "TIMELINE_CREATE=yes" if new_status[
|
||||
'enable_timeline_snapshots'] else "TIMELINE_CREATE=no"
|
||||
actions.superuser_run('snapshot', ['configure', timeline_create])
|
||||
messages.success(request,
|
||||
_('Timeline Snapshots configuration updated'))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user