mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-09-19 04:59:01 +00:00
backups: New app to manage borgbackup archives
Reviewed-by: Joseph Nuthalapati <njoseph@thoughtworks.com>
This commit is contained in:
parent
7e2c9b1095
commit
c852cd824f
122
actions/backups
Executable file
122
actions/backups
Executable file
@ -0,0 +1,122 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- mode: python -*-
|
||||||
|
#
|
||||||
|
# This file is part of FreedomBox.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
Configuration helper for backups.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
REPOSITORY = '/tmp/freedombox-backups'
|
||||||
|
|
||||||
|
|
||||||
|
def parse_arguments():
|
||||||
|
"""Return parsed command line arguments as dictionary."""
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
||||||
|
|
||||||
|
subparsers.add_parser(
|
||||||
|
'setup', help='Create repository if it does not already exist')
|
||||||
|
subparsers.add_parser('info', help='Show repository information')
|
||||||
|
subparsers.add_parser('list', help='List repository contents')
|
||||||
|
|
||||||
|
create = subparsers.add_parser('create', help='Create archive')
|
||||||
|
create.add_argument('--name', help='Archive name', required=True)
|
||||||
|
create.add_argument('--path', help='Path to archive', required=True)
|
||||||
|
|
||||||
|
delete = subparsers.add_parser('delete', help='Delete archive')
|
||||||
|
delete.add_argument('--name', help='Archive name', required=True)
|
||||||
|
|
||||||
|
extract = subparsers.add_parser('extract', help='Extract archive contents')
|
||||||
|
extract.add_argument('--name', help='Archive name', required=True)
|
||||||
|
extract.add_argument('--destination', help='Extract destination',
|
||||||
|
required=True)
|
||||||
|
|
||||||
|
export = subparsers.add_parser('export',
|
||||||
|
help='Export archive contents as tarball')
|
||||||
|
export.add_argument('--name', help='Archive name', required=True)
|
||||||
|
export.add_argument('--filename', help='Tarball file name', required=True)
|
||||||
|
|
||||||
|
subparsers.required = True
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_setup(_):
|
||||||
|
"""Create repository if it does not already exist."""
|
||||||
|
try:
|
||||||
|
subprocess.run(['borg', 'info', REPOSITORY], check=True)
|
||||||
|
except:
|
||||||
|
subprocess.run(['borg', 'init', '--encryption', 'none', REPOSITORY])
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_info(_):
|
||||||
|
"""Show repository information."""
|
||||||
|
subprocess.run(['borg', 'info', '--json', REPOSITORY], check=True)
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_list(_):
|
||||||
|
"""List repository contents."""
|
||||||
|
subprocess.run(['borg', 'list', '--json', REPOSITORY], check=True)
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_create(arguments):
|
||||||
|
"""Create archive."""
|
||||||
|
subprocess.run([
|
||||||
|
'borg', 'create', '--json', REPOSITORY + '::' + arguments.name,
|
||||||
|
arguments.path
|
||||||
|
], check=True)
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_delete(arguments):
|
||||||
|
"""Delete archive."""
|
||||||
|
subprocess.run(['borg', 'delete', REPOSITORY + '::' + arguments.name],
|
||||||
|
check=True)
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_extract(arguments):
|
||||||
|
"""Extract archive contents."""
|
||||||
|
prev_dir = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(os.path.expanduser(arguments.destination))
|
||||||
|
subprocess.run(['borg', 'extract', REPOSITORY + '::' + arguments.name],
|
||||||
|
check=True)
|
||||||
|
finally:
|
||||||
|
os.chdir(prev_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_export(arguments):
|
||||||
|
"""Export archive contents as tarball."""
|
||||||
|
subprocess.run([
|
||||||
|
'borg', 'export-tar', REPOSITORY + '::' + arguments.name,
|
||||||
|
arguments.filename
|
||||||
|
], check=True)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Parse arguments and perform all duties."""
|
||||||
|
arguments = parse_arguments()
|
||||||
|
|
||||||
|
subcommand = arguments.subcommand.replace('-', '_')
|
||||||
|
subcommand_method = globals()['subcommand_' + subcommand]
|
||||||
|
subcommand_method(arguments)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
1
data/etc/plinth/modules-enabled/backups
Normal file
1
data/etc/plinth/modules-enabled/backups
Normal file
@ -0,0 +1 @@
|
|||||||
|
plinth.modules.backups
|
||||||
85
plinth/modules/backups/__init__.py
Normal file
85
plinth/modules/backups/__init__.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#
|
||||||
|
# This file is part of FreedomBox.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
FreedomBox app to manage backup archives.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from plinth import actions
|
||||||
|
from plinth.menu import main_menu
|
||||||
|
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
managed_packages = ['borgbackup']
|
||||||
|
|
||||||
|
name = _('Backups')
|
||||||
|
|
||||||
|
description = [_('Backups allows creating and managing backup archives.'), ]
|
||||||
|
|
||||||
|
service = None
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
"""Intialize the module."""
|
||||||
|
menu = main_menu.get('system')
|
||||||
|
menu.add_urlname(name, 'glyphicon-duplicate', 'backups:index')
|
||||||
|
|
||||||
|
|
||||||
|
def setup(helper, old_version=None):
|
||||||
|
"""Install and configure the module."""
|
||||||
|
helper.install(managed_packages)
|
||||||
|
helper.call('post', actions.superuser_run, 'backups', ['setup'])
|
||||||
|
|
||||||
|
|
||||||
|
def get_info():
|
||||||
|
output = actions.superuser_run('backups', ['info'])
|
||||||
|
return json.loads(output)
|
||||||
|
|
||||||
|
|
||||||
|
def list_archives():
|
||||||
|
output = actions.superuser_run('backups', ['list'])
|
||||||
|
return json.loads(output)['archives']
|
||||||
|
|
||||||
|
|
||||||
|
def get_archive(name):
|
||||||
|
for archive in list_archives():
|
||||||
|
if archive['name'] == name:
|
||||||
|
return archive
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def create_archive(name, path):
|
||||||
|
actions.superuser_run('backups',
|
||||||
|
['create', '--name', name, '--path', path])
|
||||||
|
|
||||||
|
|
||||||
|
def delete_archive(name):
|
||||||
|
actions.superuser_run('backups', ['delete', '--name', name])
|
||||||
|
|
||||||
|
|
||||||
|
def extract_archive(name, destination):
|
||||||
|
actions.superuser_run(
|
||||||
|
'backups', ['extract', '--name', name, '--destination', destination])
|
||||||
|
|
||||||
|
|
||||||
|
def export_archive(name, filename):
|
||||||
|
actions.superuser_run('backups',
|
||||||
|
['export', '--name', name, '--filename', filename])
|
||||||
43
plinth/modules/backups/forms.py
Normal file
43
plinth/modules/backups/forms.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#
|
||||||
|
# This file is part of FreedomBox.
|
||||||
|
#
|
||||||
|
# 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 backups module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class CreateArchiveForm(forms.Form):
|
||||||
|
name = forms.CharField(label=_('Archive name'), strip=True,
|
||||||
|
help_text=_('Name for new backup archive.'))
|
||||||
|
|
||||||
|
path = forms.CharField(label=_('Path'), strip=True, help_text=_(
|
||||||
|
'Disk path to a folder on this server that will be archived into '
|
||||||
|
'backup repository.'))
|
||||||
|
|
||||||
|
|
||||||
|
class ExtractArchiveForm(forms.Form):
|
||||||
|
path = forms.CharField(label=_('Path'), strip=True, help_text=_(
|
||||||
|
'Disk path to a folder on this server where the archive will be '
|
||||||
|
'extracted.'))
|
||||||
|
|
||||||
|
|
||||||
|
class ExportArchiveForm(forms.Form):
|
||||||
|
filename = forms.CharField(
|
||||||
|
label=_('Exported filename'), strip=True,
|
||||||
|
help_text=_('Name for the tar file exported from the archive.'))
|
||||||
89
plinth/modules/backups/templates/backups.html
Normal file
89
plinth/modules/backups/templates/backups.html
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% comment %}
|
||||||
|
#
|
||||||
|
# This file is part of FreedomBox.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block page_head %}
|
||||||
|
<style type="text/css">
|
||||||
|
.share-operations form {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.share-operations {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2>{{ title }}</h2>
|
||||||
|
|
||||||
|
{% for paragraph in description %}
|
||||||
|
<p>{{ paragraph|safe }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a title="{% trans 'Create archive' %}"
|
||||||
|
role="button" class="btn btn-primary"
|
||||||
|
href="{% url 'backups:create' %}">
|
||||||
|
{% trans 'Create archive' %}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% if not archives %}
|
||||||
|
<p>{% trans 'No archives currently exist.' %}</p>
|
||||||
|
{% else %}
|
||||||
|
<table class="table table-bordered table-condensed table-striped"
|
||||||
|
id="archives-list">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Name" %}</th>
|
||||||
|
<th>{% trans "Time" %}</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for archive in archives %}
|
||||||
|
<tr id="archive-{{ archive.name }}" class="archive">
|
||||||
|
<td class="archive-name">{{ archive.name }}</td>
|
||||||
|
<td class="archive-time">{{ archive.time }}</td>
|
||||||
|
<td class="archive-operations">
|
||||||
|
<a class="archive-extract btn btn-sm btn-default"
|
||||||
|
href="{% url 'backups:extract' archive.name %}">
|
||||||
|
{% trans "Extract" %}
|
||||||
|
</a>
|
||||||
|
<a class="archive-export btn btn-sm btn-default"
|
||||||
|
href="{% url 'backups:export' archive.name %}">
|
||||||
|
{% trans "Export" %}
|
||||||
|
</a>
|
||||||
|
<a class="archive-delete btn btn-sm btn-default"
|
||||||
|
href="{% url 'backups:delete' archive.name %}">
|
||||||
|
<span class="glyphicon glyphicon-trash" aria-hidden="true">
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
57
plinth/modules/backups/templates/backups_delete.html
Normal file
57
plinth/modules/backups/templates/backups_delete.html
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% comment %}
|
||||||
|
#
|
||||||
|
# This file is part of FreedomBox.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% load bootstrap %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>{{ title }}</h2>
|
||||||
|
|
||||||
|
<p>{% trans "Delete this archive permanently?" %}</p>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<table class="table table-bordered table-condensed table-striped">
|
||||||
|
<thead>
|
||||||
|
<th>{% trans "Name" %}</th>
|
||||||
|
<th>{% trans "Time" %}</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{{ archive.name }}</td>
|
||||||
|
<td>{{ archive.time }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<form class="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
<input type="submit" class="btn btn-danger"
|
||||||
|
value="{% blocktrans trimmed with name=archive.name %}
|
||||||
|
Delete Archive {{ name }}
|
||||||
|
{% endblocktrans %}"/>
|
||||||
|
</form>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
37
plinth/modules/backups/templates/backups_form.html
Normal file
37
plinth/modules/backups/templates/backups_form.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% comment %}
|
||||||
|
#
|
||||||
|
# This file is part of FreedomBox.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% load bootstrap %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3>{{ title }}</h3>
|
||||||
|
|
||||||
|
<form class="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{{ form|bootstrap }}
|
||||||
|
|
||||||
|
<input type="submit" class="btn btn-primary"
|
||||||
|
value="{% trans "Submit" %}"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
35
plinth/modules/backups/urls.py
Normal file
35
plinth/modules/backups/urls.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#
|
||||||
|
# This file is part of FreedomBox.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
URLs for the backups module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.conf.urls import url
|
||||||
|
|
||||||
|
from .views import IndexView, CreateArchiveView, DeleteArchiveView, \
|
||||||
|
ExtractArchiveView, ExportArchiveView
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^sys/backups/$', IndexView.as_view(), name='index'),
|
||||||
|
url(r'^sys/backups/create/$', CreateArchiveView.as_view(), name='create'),
|
||||||
|
url(r'^sys/backups/(?P<name>[a-z0-9]+)/delete/$',
|
||||||
|
DeleteArchiveView.as_view(), name='delete'),
|
||||||
|
url(r'^sys/backups/(?P<name>[a-z0-9]+)/extract/$',
|
||||||
|
ExtractArchiveView.as_view(), name='extract'),
|
||||||
|
url(r'^sys/backups/(?P<name>[a-z0-9]+)/export/$',
|
||||||
|
ExportArchiveView.as_view(), name='export'),
|
||||||
|
]
|
||||||
136
plinth/modules/backups/views.py
Normal file
136
plinth/modules/backups/views.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#
|
||||||
|
# This file is part of FreedomBox.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
Views for the backups app.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
|
from django.http import Http404
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from django.views.generic import FormView, TemplateView
|
||||||
|
|
||||||
|
from plinth.modules import backups
|
||||||
|
|
||||||
|
from .forms import CreateArchiveForm, ExtractArchiveForm, ExportArchiveForm
|
||||||
|
|
||||||
|
|
||||||
|
class IndexView(TemplateView):
|
||||||
|
"""View to show list of archives."""
|
||||||
|
template_name = 'backups.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
"""Return additional context for rendering the template."""
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context['title'] = backups.name
|
||||||
|
context['description'] = backups.description
|
||||||
|
context['info'] = backups.get_info()
|
||||||
|
context['archives'] = backups.list_archives()
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class CreateArchiveView(SuccessMessageMixin, FormView):
|
||||||
|
"""View to create a new archive."""
|
||||||
|
form_class = CreateArchiveForm
|
||||||
|
prefix = 'backups'
|
||||||
|
template_name = 'backups_form.html'
|
||||||
|
success_url = reverse_lazy('backups:index')
|
||||||
|
success_message = _('Archive created.')
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
"""Return additional context for rendering the template."""
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context['title'] = _('Create Archive')
|
||||||
|
return context
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
"""Create the archive on valid form submission."""
|
||||||
|
backups.create_archive(form.cleaned_data['name'],
|
||||||
|
form.cleaned_data['path'])
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteArchiveView(SuccessMessageMixin, TemplateView):
|
||||||
|
"""View to delete an archive."""
|
||||||
|
template_name = 'backups_delete.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
"""Return additional context for rendering the template."""
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context['title'] = _('Delete Archive')
|
||||||
|
context['archive'] = backups.get_archive(self.kwargs['name'])
|
||||||
|
if context['archive'] is None:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
||||||
|
def post(self, request, name):
|
||||||
|
"""Delete the archive."""
|
||||||
|
backups.delete_archive(name)
|
||||||
|
messages.success(request, _('Archive deleted.'))
|
||||||
|
return redirect(reverse_lazy('backups:index'))
|
||||||
|
|
||||||
|
|
||||||
|
class ExtractArchiveView(SuccessMessageMixin, FormView):
|
||||||
|
"""View to extract an archive."""
|
||||||
|
form_class = ExtractArchiveForm
|
||||||
|
prefix = 'backups'
|
||||||
|
template_name = 'backups_form.html'
|
||||||
|
success_url = reverse_lazy('backups:index')
|
||||||
|
success_message = _('Archive extracted.')
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
"""Return additional context for rendering the template."""
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context['title'] = _('Extract Archive')
|
||||||
|
context['archive'] = backups.get_archive(self.kwargs['name'])
|
||||||
|
if context['archive'] is None:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
"""Create the archive on valid form submission."""
|
||||||
|
backups.extract_archive(self.kwargs['name'], form.cleaned_data['path'])
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class ExportArchiveView(SuccessMessageMixin, FormView):
|
||||||
|
"""View to export an archive."""
|
||||||
|
form_class = ExportArchiveForm
|
||||||
|
prefix = 'backups'
|
||||||
|
template_name = 'backups_form.html'
|
||||||
|
success_url = reverse_lazy('backups:index')
|
||||||
|
success_message = _('Archive exported.')
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
"""Return additional context for rendering the template."""
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context['title'] = _('Export Archive')
|
||||||
|
context['archive'] = backups.get_archive(self.kwargs['name'])
|
||||||
|
if context['archive'] is None:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
"""Create the archive on valid form submission."""
|
||||||
|
backups.export_archive(self.kwargs['name'],
|
||||||
|
form.cleaned_data['filename'])
|
||||||
|
return super().form_valid(form)
|
||||||
Loading…
x
Reference in New Issue
Block a user