mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-20 10:34:30 +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('setup', help='Configure snapper')
|
||||||
subparsers.add_parser('list', help='List snapshots')
|
subparsers.add_parser('list', help='List snapshots')
|
||||||
subparsers.add_parser('create', help='Create snapshot')
|
subparsers.add_parser('create', help='Create snapshot')
|
||||||
|
subparsers.add_parser('get-config', help='Configurations of snapshot')
|
||||||
|
|
||||||
subparser = subparsers.add_parser('delete',
|
subparser = subparsers.add_parser('delete',
|
||||||
help='Delete a snapshot by number')
|
help='Delete a snapshot by number')
|
||||||
@ -46,6 +47,10 @@ def parse_arguments():
|
|||||||
subparser = subparsers.add_parser('delete-all',
|
subparser = subparsers.add_parser('delete-all',
|
||||||
help='Delete all the snapshots')
|
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 = subparsers.add_parser('rollback', help='Rollback to snapshot')
|
||||||
subparser.add_argument('number', help='Number of snapshot to rollback to')
|
subparser.add_argument('number', help='Number of snapshot to rollback to')
|
||||||
|
|
||||||
@ -163,6 +168,22 @@ def subcommand_delete_all(_):
|
|||||||
subprocess.run(command, check=True)
|
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):
|
def subcommand_rollback(arguments):
|
||||||
"""Rollback to snapshot."""
|
"""Rollback to snapshot."""
|
||||||
command = [
|
command = [
|
||||||
|
|||||||
@ -23,6 +23,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
from plinth import actions
|
from plinth import actions
|
||||||
from plinth.menu import main_menu
|
from plinth.menu import main_menu
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
@ -58,3 +59,11 @@ def setup(helper, old_version=None):
|
|||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
helper.install(managed_packages)
|
helper.install(managed_packages)
|
||||||
helper.call('post', actions.superuser_run, 'snapshot', ['setup'])
|
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 %}
|
{% block configuration %}
|
||||||
<p>
|
<p>
|
||||||
<div class="row">
|
<form class="form" method="post">
|
||||||
<form class="form" method="post">
|
{% csrf_token %}
|
||||||
{% 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">
|
<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' %}"/>
|
value="{% trans 'Create Snapshot' %}"/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="col-xs-6 text-right">
|
<div class="col-xs-6 text-right">
|
||||||
<a title="{% trans 'Delete all the snapshots' %}"
|
<a title="{% trans 'Delete all the snapshots' %}"
|
||||||
role="button" class="btn btn-danger"
|
role="button" class="btn btn-danger"
|
||||||
{% if snapshots|length == 1 %}
|
{% if snapshots|length == 1 %}
|
||||||
disabled="disabled"
|
disabled="disabled"
|
||||||
{% else %}
|
{% else %}
|
||||||
href="{% url 'snapshot:delete-all' %}"
|
href="{% url 'snapshot:delete-all' %}"
|
||||||
{% endif %}>
|
{% endif %}>
|
||||||
{% trans 'Delete All' %}
|
{% trans 'Delete All' %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|||||||
@ -27,14 +27,27 @@ from django.urls import reverse
|
|||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from plinth import actions
|
from plinth import actions
|
||||||
|
from plinth.errors import ActionError
|
||||||
from plinth.modules import snapshot as snapshot_module
|
from plinth.modules import snapshot as snapshot_module
|
||||||
|
|
||||||
|
from . import is_timeline_snapshots_enabled
|
||||||
|
from .forms import SnapshotForm
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
"""Show snapshot list."""
|
"""Show snapshot list."""
|
||||||
|
status = get_status()
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
actions.superuser_run('snapshot', ['create'])
|
form = SnapshotForm(request.POST, prefix='snapshot')
|
||||||
messages.success(request, _('Created 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'])
|
output = actions.superuser_run('snapshot', ['list'])
|
||||||
snapshots = json.loads(output)
|
snapshots = json.loads(output)
|
||||||
@ -42,7 +55,8 @@ def index(request):
|
|||||||
return TemplateResponse(request, 'snapshot.html', {
|
return TemplateResponse(request, 'snapshot.html', {
|
||||||
'title': snapshot_module.name,
|
'title': snapshot_module.name,
|
||||||
'description': snapshot_module.description,
|
'description': snapshot_module.description,
|
||||||
'snapshots': snapshots
|
'snapshots': snapshots,
|
||||||
|
'form': form
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -50,9 +64,8 @@ def delete(request, number):
|
|||||||
"""Show confirmation to delete a snapshot."""
|
"""Show confirmation to delete a snapshot."""
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
actions.superuser_run('snapshot', ['delete', number])
|
actions.superuser_run('snapshot', ['delete', number])
|
||||||
messages.success(request,
|
messages.success(
|
||||||
_('Deleted snapshot #{number}.').format(
|
request, _('Deleted snapshot #{number}.').format(number=number))
|
||||||
number=number))
|
|
||||||
return redirect(reverse('snapshot:index'))
|
return redirect(reverse('snapshot:index'))
|
||||||
|
|
||||||
output = actions.superuser_run('snapshot', ['list'])
|
output = actions.superuser_run('snapshot', ['list'])
|
||||||
@ -85,9 +98,9 @@ def rollback(request, number):
|
|||||||
"""Show confirmation to rollback to a snapshot."""
|
"""Show confirmation to rollback to a snapshot."""
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
actions.superuser_run('snapshot', ['rollback', number])
|
actions.superuser_run('snapshot', ['rollback', number])
|
||||||
messages.success(request,
|
messages.success(
|
||||||
_('Rolled back to snapshot #{number}.').format(
|
request,
|
||||||
number=number))
|
_('Rolled back to snapshot #{number}.').format(number=number))
|
||||||
messages.warning(
|
messages.warning(
|
||||||
request,
|
request,
|
||||||
_('The system must be restarted to complete the rollback.'))
|
_('The system must be restarted to complete the rollback.'))
|
||||||
@ -105,3 +118,27 @@ def rollback(request, number):
|
|||||||
'title': _('Rollback to Snapshot'),
|
'title': _('Rollback to Snapshot'),
|
||||||
'snapshot': 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