mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-27 10:44:33 +00:00
backups: Use the backup component in all apps
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: Veiko Aasa <veiko17@disroot.org>
This commit is contained in:
parent
f630fb6059
commit
fb1898befc
@ -9,13 +9,14 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, menu
|
from plinth import cfg, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.config import get_hostname
|
from plinth.modules.config import get_hostname
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.names.components import DomainType
|
from plinth.modules.names.components import DomainType
|
||||||
from plinth.signals import domain_added, domain_removed, post_hostname_change
|
from plinth.signals import domain_added, domain_removed, post_hostname_change
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
# pylint: disable=C0103
|
# pylint: disable=C0103
|
||||||
|
|
||||||
@ -76,6 +77,10 @@ class AvahiApp(app_module.App):
|
|||||||
daemon = Daemon('daemon-avahi', managed_services[0])
|
daemon = Daemon('daemon-avahi', managed_services[0])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-avahi',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
if self.is_enabled():
|
if self.is_enabled():
|
||||||
domain_added.send_robust(sender='avahi',
|
domain_added.send_robust(sender='avahi',
|
||||||
domain_type='domain-type-local',
|
domain_type='domain-type-local',
|
||||||
|
|||||||
@ -3,10 +3,8 @@
|
|||||||
Application manifest for avahi.
|
Application manifest for avahi.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
# Services that intend to make themselves discoverable will drop files into
|
# Services that intend to make themselves discoverable will drop files into
|
||||||
# /etc/avahi/services. Currently, we don't intend to make that customizable.
|
# /etc/avahi/services. Currently, we don't intend to make that customizable.
|
||||||
# There is no necessity for backup and restore. This manifest will ensure that
|
# There is no necessity for backup and restore. This manifest will ensure that
|
||||||
# avahi enable/disable setting is preserved.
|
# avahi enable/disable setting is preserved.
|
||||||
backup = validate_backup({})
|
backup = {}
|
||||||
|
|||||||
@ -75,10 +75,10 @@ def _backup_handler(packet, encryption_passphrase=None):
|
|||||||
get_valid_filename(packet.path) + '.json')
|
get_valid_filename(packet.path) + '.json')
|
||||||
manifests = {
|
manifests = {
|
||||||
'apps': [{
|
'apps': [{
|
||||||
'name': app.name,
|
'name': component.app.app_id,
|
||||||
'version': app.app.app.info.version,
|
'version': component.app.info.version,
|
||||||
'backup': app.manifest
|
'backup': component.manifest
|
||||||
} for app in packet.apps]
|
} for component in packet.components]
|
||||||
}
|
}
|
||||||
with open(manifest_path, 'w') as manifest_file:
|
with open(manifest_path, 'w') as manifest_file:
|
||||||
json.dump(manifests, manifest_file)
|
json.dump(manifests, manifest_file)
|
||||||
@ -124,9 +124,9 @@ def restore_archive_handler(packet, encryption_passphrase=None):
|
|||||||
actions.superuser_run('backups', arguments, input=locations_data.encode())
|
actions.superuser_run('backups', arguments, input=locations_data.encode())
|
||||||
|
|
||||||
|
|
||||||
def restore_from_upload(path, apps=None):
|
def restore_from_upload(path, app_ids=None):
|
||||||
"""Restore files from an uploaded .tar.gz backup file"""
|
"""Restore files from an uploaded .tar.gz backup file"""
|
||||||
api.restore_apps(_restore_exported_archive_handler, app_names=apps,
|
api.restore_apps(_restore_exported_archive_handler, app_ids=app_ids,
|
||||||
create_subvolume=False, backup_file=path)
|
create_subvolume=False, backup_file=path)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -10,79 +10,38 @@ TODO:
|
|||||||
- Implement unit tests.
|
- Implement unit tests.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import importlib
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from plinth import actions, action_utils, module_loader, setup
|
from plinth import action_utils, actions
|
||||||
|
from plinth import app as app_module
|
||||||
|
from plinth import setup
|
||||||
|
|
||||||
|
from .components import BackupRestore
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def validate(backup):
|
|
||||||
"""Validate the backup' information schema."""
|
|
||||||
assert isinstance(backup, dict)
|
|
||||||
|
|
||||||
if 'config' in backup:
|
|
||||||
assert isinstance(backup['config'], dict)
|
|
||||||
_validate_directories_and_files(backup['config'])
|
|
||||||
|
|
||||||
if 'data' in backup:
|
|
||||||
assert isinstance(backup['data'], dict)
|
|
||||||
_validate_directories_and_files(backup['data'])
|
|
||||||
|
|
||||||
if 'secrets' in backup:
|
|
||||||
assert isinstance(backup['secrets'], dict)
|
|
||||||
_validate_directories_and_files(backup['secrets'])
|
|
||||||
|
|
||||||
if 'services' in backup:
|
|
||||||
assert isinstance(backup['services'], list)
|
|
||||||
for service in backup['services']:
|
|
||||||
assert isinstance(service, (str, dict))
|
|
||||||
if isinstance(service, dict):
|
|
||||||
_validate_service(service)
|
|
||||||
|
|
||||||
return backup
|
|
||||||
|
|
||||||
|
|
||||||
def _validate_directories_and_files(section):
|
|
||||||
"""Validate directories and files keys in a section."""
|
|
||||||
if 'directories' in section:
|
|
||||||
assert isinstance(section['directories'], list)
|
|
||||||
for directory in section['directories']:
|
|
||||||
assert isinstance(directory, str)
|
|
||||||
|
|
||||||
if 'files' in section:
|
|
||||||
assert isinstance(section['files'], list)
|
|
||||||
for file_path in section['files']:
|
|
||||||
assert isinstance(file_path, str)
|
|
||||||
|
|
||||||
|
|
||||||
def _validate_service(service):
|
|
||||||
"""Validate a service manifest provided as a dictionary."""
|
|
||||||
assert isinstance(service['name'], str)
|
|
||||||
assert isinstance(service['type'], str)
|
|
||||||
assert service['type'] in ('apache', 'uwsgi', 'system')
|
|
||||||
if service['type'] == 'apache':
|
|
||||||
assert service['kind'] in ('config', 'site', 'module')
|
|
||||||
|
|
||||||
|
|
||||||
class BackupError:
|
class BackupError:
|
||||||
"""Represent an backup/restore operation error."""
|
"""Represent an backup/restore operation error."""
|
||||||
def __init__(self, error_type, app, hook=None):
|
|
||||||
|
def __init__(self, error_type, component, hook=None):
|
||||||
"""Initialize the error object."""
|
"""Initialize the error object."""
|
||||||
self.error_type = error_type
|
self.error_type = error_type
|
||||||
self.app = app
|
self.component = component
|
||||||
self.hook = hook
|
self.hook = hook
|
||||||
|
|
||||||
def __eq__(self, other_error):
|
def __eq__(self, other_error):
|
||||||
"""Compare to error objects."""
|
"""Compare to error objects."""
|
||||||
return (self.error_type == other_error.error_type
|
return (self.error_type == other_error.error_type
|
||||||
and self.app == other_error.app
|
and self.component == other_error.component
|
||||||
and self.hook == other_error.hook)
|
and self.hook == other_error.hook)
|
||||||
|
|
||||||
|
|
||||||
class Packet:
|
class Packet:
|
||||||
"""Information passed to a handlers for backup/restore operations."""
|
"""Information passed to a handlers for backup/restore operations."""
|
||||||
def __init__(self, operation, scope, root, apps=None, path=None):
|
|
||||||
|
def __init__(self, operation, scope, root, components=None, path=None):
|
||||||
"""Initialize the packet.
|
"""Initialize the packet.
|
||||||
|
|
||||||
operation is either 'backup' or 'restore.
|
operation is either 'backup' or 'restore.
|
||||||
@ -101,7 +60,7 @@ class Packet:
|
|||||||
self.operation = operation
|
self.operation = operation
|
||||||
self.scope = scope
|
self.scope = scope
|
||||||
self.root = root
|
self.root = root
|
||||||
self.apps = apps
|
self.components = components
|
||||||
self.path = path
|
self.path = path
|
||||||
self.errors = []
|
self.errors = []
|
||||||
|
|
||||||
@ -112,11 +71,11 @@ class Packet:
|
|||||||
|
|
||||||
def _process_manifests(self):
|
def _process_manifests(self):
|
||||||
"""Look at manifests and fill up the list of directories/files."""
|
"""Look at manifests and fill up the list of directories/files."""
|
||||||
for app in self.apps:
|
for component in self.components:
|
||||||
for section in ['config', 'data', 'secrets']:
|
for section in ['config', 'data', 'secrets']:
|
||||||
self.directories += app.manifest.get(section, {}).get(
|
section = getattr(component, section)
|
||||||
'directories', [])
|
self.directories += section.get('directories', [])
|
||||||
self.files += app.manifest.get(section, {}).get('files', [])
|
self.files += section.get('files', [])
|
||||||
|
|
||||||
|
|
||||||
def backup_full(backup_handler, path=None):
|
def backup_full(backup_handler, path=None):
|
||||||
@ -146,25 +105,25 @@ def restore_full(restore_handler):
|
|||||||
_switch_to_subvolume(subvolume)
|
_switch_to_subvolume(subvolume)
|
||||||
|
|
||||||
|
|
||||||
def backup_apps(backup_handler, path, app_names=None,
|
def backup_apps(backup_handler, path, app_ids=None,
|
||||||
encryption_passphrase=None):
|
encryption_passphrase=None):
|
||||||
"""Backup data belonging to a set of applications."""
|
"""Backup data belonging to a set of applications."""
|
||||||
if not app_names:
|
if not app_ids:
|
||||||
apps = get_all_apps_for_backup()
|
components = get_all_components_for_backup()
|
||||||
else:
|
else:
|
||||||
apps = get_apps_in_order(app_names)
|
components = get_components_in_order(app_ids)
|
||||||
|
|
||||||
if _is_snapshot_available():
|
if _is_snapshot_available():
|
||||||
snapshot = _take_snapshot()
|
snapshot = _take_snapshot()
|
||||||
backup_root = snapshot['mount_path']
|
backup_root = snapshot['mount_path']
|
||||||
snapshotted = True
|
snapshotted = True
|
||||||
else:
|
else:
|
||||||
_lockdown_apps(apps, lockdown=True)
|
_lockdown_apps(components, lockdown=True)
|
||||||
original_state = _shutdown_services(apps)
|
original_state = _shutdown_services(components)
|
||||||
backup_root = '/'
|
backup_root = '/'
|
||||||
snapshotted = False
|
snapshotted = False
|
||||||
|
|
||||||
packet = Packet('backup', 'apps', backup_root, apps, path)
|
packet = Packet('backup', 'apps', backup_root, components, path)
|
||||||
_run_operation(backup_handler, packet,
|
_run_operation(backup_handler, packet,
|
||||||
encryption_passphrase=encryption_passphrase)
|
encryption_passphrase=encryption_passphrase)
|
||||||
|
|
||||||
@ -172,29 +131,29 @@ def backup_apps(backup_handler, path, app_names=None,
|
|||||||
_delete_snapshot(snapshot)
|
_delete_snapshot(snapshot)
|
||||||
else:
|
else:
|
||||||
_restore_services(original_state)
|
_restore_services(original_state)
|
||||||
_lockdown_apps(apps, lockdown=False)
|
_lockdown_apps(components, lockdown=False)
|
||||||
|
|
||||||
|
|
||||||
def restore_apps(restore_handler, app_names=None, create_subvolume=True,
|
def restore_apps(restore_handler, app_ids=None, create_subvolume=True,
|
||||||
backup_file=None, encryption_passphrase=None):
|
backup_file=None, encryption_passphrase=None):
|
||||||
"""Restore data belonging to a set of applications."""
|
"""Restore data belonging to a set of applications."""
|
||||||
if not app_names:
|
if not app_ids:
|
||||||
apps = get_all_apps_for_backup()
|
components = get_all_components_for_backup()
|
||||||
else:
|
else:
|
||||||
apps = get_apps_in_order(app_names)
|
components = get_components_in_order(app_ids)
|
||||||
|
|
||||||
_install_apps_before_restore(apps)
|
_install_apps_before_restore(components)
|
||||||
|
|
||||||
if _is_snapshot_available() and create_subvolume:
|
if _is_snapshot_available() and create_subvolume:
|
||||||
subvolume = _create_subvolume(empty=False)
|
subvolume = _create_subvolume(empty=False)
|
||||||
restore_root = subvolume['mount_path']
|
restore_root = subvolume['mount_path']
|
||||||
else:
|
else:
|
||||||
_lockdown_apps(apps, lockdown=True)
|
_lockdown_apps(components, lockdown=True)
|
||||||
original_state = _shutdown_services(apps)
|
original_state = _shutdown_services(components)
|
||||||
restore_root = '/'
|
restore_root = '/'
|
||||||
subvolume = False
|
subvolume = False
|
||||||
|
|
||||||
packet = Packet('restore', 'apps', restore_root, apps, backup_file)
|
packet = Packet('restore', 'apps', restore_root, components, backup_file)
|
||||||
_run_operation(restore_handler, packet,
|
_run_operation(restore_handler, packet,
|
||||||
encryption_passphrase=encryption_passphrase)
|
encryption_passphrase=encryption_passphrase)
|
||||||
|
|
||||||
@ -202,10 +161,10 @@ def restore_apps(restore_handler, app_names=None, create_subvolume=True,
|
|||||||
_switch_to_subvolume(subvolume)
|
_switch_to_subvolume(subvolume)
|
||||||
else:
|
else:
|
||||||
_restore_services(original_state)
|
_restore_services(original_state)
|
||||||
_lockdown_apps(apps, lockdown=False)
|
_lockdown_apps(components, lockdown=False)
|
||||||
|
|
||||||
|
|
||||||
def _install_apps_before_restore(apps):
|
def _install_apps_before_restore(components):
|
||||||
"""Install/upgrade apps needed before restoring a backup.
|
"""Install/upgrade apps needed before restoring a backup.
|
||||||
|
|
||||||
Upgrading apps to latest version before backups reduces the chance of newer
|
Upgrading apps to latest version before backups reduces the chance of newer
|
||||||
@ -213,92 +172,57 @@ def _install_apps_before_restore(apps):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
modules_to_setup = []
|
modules_to_setup = []
|
||||||
for backup_app in apps:
|
for component in components:
|
||||||
if backup_app.app.setup_helper.get_state() in ('needs-setup',
|
module = importlib.import_module(component.app.__class__.__module__)
|
||||||
'needs-update'):
|
if module.setup_helper.get_state() in ('needs-setup', 'needs-update'):
|
||||||
modules_to_setup.append(backup_app.name)
|
modules_to_setup.append(component.app.app_id)
|
||||||
|
|
||||||
setup.run_setup_on_modules(modules_to_setup)
|
setup.run_setup_on_modules(modules_to_setup)
|
||||||
|
|
||||||
|
|
||||||
class BackupApp:
|
def _get_backup_restore_component(app):
|
||||||
"""A application that can be backed up and its manifest."""
|
"""Return the backup/restore component of the app."""
|
||||||
def __init__(self, name, app):
|
for component in app.components.values():
|
||||||
"""Initialize object and load manfiest."""
|
if isinstance(component, BackupRestore):
|
||||||
self.name = name
|
return component
|
||||||
self.app = app
|
|
||||||
|
|
||||||
# Has no backup related meta data
|
raise TypeError
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_components_for_backup():
|
||||||
|
"""Return a list of all components that can be backed up."""
|
||||||
|
components = []
|
||||||
|
|
||||||
|
for app_ in app_module.App.list():
|
||||||
try:
|
try:
|
||||||
self.manifest = app.backup
|
module = importlib.import_module(app_.__class__.__module__)
|
||||||
except AttributeError:
|
if module.setup_helper.get_state() != 'needs-setup':
|
||||||
raise TypeError
|
components.append(_get_backup_restore_component(app_))
|
||||||
|
|
||||||
self.has_data = bool(app.backup)
|
|
||||||
|
|
||||||
def __eq__(self, other_app):
|
|
||||||
"""Check if this app is same as another."""
|
|
||||||
return self.name == other_app.name and \
|
|
||||||
self.app == other_app.app and \
|
|
||||||
self.manifest == other_app.manifest and \
|
|
||||||
self.has_data == other_app.has_data
|
|
||||||
|
|
||||||
def is_installed(self):
|
|
||||||
"""Return whether app is installed.
|
|
||||||
|
|
||||||
Return true even if the app needs update.
|
|
||||||
"""
|
|
||||||
return self.app.setup_helper.get_state() != 'needs-setup'
|
|
||||||
|
|
||||||
def run_hook(self, hook, packet):
|
|
||||||
"""Run a hook inside an application."""
|
|
||||||
if not hasattr(self.app, hook):
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
getattr(self.app, hook)(packet)
|
|
||||||
except Exception as exception:
|
|
||||||
logger.exception(
|
|
||||||
'Error running backup/restore hook for app %s: %s', self.name,
|
|
||||||
exception)
|
|
||||||
packet.errors.append(BackupError('hook', self.app, hook=hook))
|
|
||||||
|
|
||||||
|
|
||||||
def get_all_apps_for_backup():
|
|
||||||
"""Return a list of all applications that can be backed up."""
|
|
||||||
apps = []
|
|
||||||
for module_name, module in module_loader.loaded_modules.items():
|
|
||||||
try:
|
|
||||||
backup_app = BackupApp(module_name, module)
|
|
||||||
if backup_app.is_installed():
|
|
||||||
apps.append(backup_app)
|
|
||||||
except TypeError: # Application not available for backup/restore
|
except TypeError: # Application not available for backup/restore
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return apps
|
return components
|
||||||
|
|
||||||
|
|
||||||
def get_apps_in_order(app_names):
|
def get_components_in_order(app_ids):
|
||||||
"""Return a list of app modules in order of dependency."""
|
"""Return a list of backup components in order of app dependencies."""
|
||||||
apps = []
|
components = []
|
||||||
for module_name, module in module_loader.loaded_modules.items():
|
for app_ in app_module.App.list():
|
||||||
if module_name in app_names:
|
if app_.app_id in app_ids:
|
||||||
apps.append(BackupApp(module_name, module))
|
components.append(_get_backup_restore_component(app_))
|
||||||
|
|
||||||
return apps
|
return components
|
||||||
|
|
||||||
|
|
||||||
def _lockdown_apps(apps, lockdown):
|
def _lockdown_apps(components, lockdown):
|
||||||
"""Mark apps as in/out of lockdown mode and disable all user interaction.
|
"""Mark apps as in/out of lockdown mode and disable all user interaction.
|
||||||
|
|
||||||
This is a flag in the app module. It will enforced by a middleware that
|
This is a flag in the app module. It will enforced by a middleware that
|
||||||
will intercept all interaction and show a lockdown message.
|
will intercept all interaction and show a lockdown message.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
for app in apps:
|
for component in components:
|
||||||
app.app.locked = lockdown
|
component.app.locked = lockdown
|
||||||
|
|
||||||
# XXX: Lockdown the application UI by implementing a middleware
|
|
||||||
|
|
||||||
|
|
||||||
def _is_snapshot_available():
|
def _is_snapshot_available():
|
||||||
@ -347,6 +271,7 @@ def _switch_to_subvolume(subvolume):
|
|||||||
|
|
||||||
class ServiceHandler:
|
class ServiceHandler:
|
||||||
"""Abstraction to help with service shutdown/restart."""
|
"""Abstraction to help with service shutdown/restart."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create(backup_app, service):
|
def create(backup_app, service):
|
||||||
service_type = 'system'
|
service_type = 'system'
|
||||||
@ -381,6 +306,7 @@ class ServiceHandler:
|
|||||||
|
|
||||||
class SystemServiceHandler(ServiceHandler):
|
class SystemServiceHandler(ServiceHandler):
|
||||||
"""Handle starting and stopping of system services for backup."""
|
"""Handle starting and stopping of system services for backup."""
|
||||||
|
|
||||||
def __init__(self, backup_app, service):
|
def __init__(self, backup_app, service):
|
||||||
"""Initialize the object."""
|
"""Initialize the object."""
|
||||||
super().__init__(backup_app, service)
|
super().__init__(backup_app, service)
|
||||||
@ -400,6 +326,7 @@ class SystemServiceHandler(ServiceHandler):
|
|||||||
|
|
||||||
class ApacheServiceHandler(ServiceHandler):
|
class ApacheServiceHandler(ServiceHandler):
|
||||||
"""Handle starting and stopping of Apache services for backup."""
|
"""Handle starting and stopping of Apache services for backup."""
|
||||||
|
|
||||||
def __init__(self, backup_app, service):
|
def __init__(self, backup_app, service):
|
||||||
"""Initialize the object."""
|
"""Initialize the object."""
|
||||||
super().__init__(backup_app, service)
|
super().__init__(backup_app, service)
|
||||||
@ -424,18 +351,19 @@ class ApacheServiceHandler(ServiceHandler):
|
|||||||
['enable', '--name', self.web_name, '--kind', self.kind])
|
['enable', '--name', self.web_name, '--kind', self.kind])
|
||||||
|
|
||||||
|
|
||||||
def _shutdown_services(apps):
|
def _shutdown_services(components):
|
||||||
"""Shutdown all services specified by manifests.
|
"""Shutdown all services specified by backup manifests.
|
||||||
|
|
||||||
- Services are shutdown in the reverse order of the apps listing.
|
- Services are shutdown in the reverse order of the components listing.
|
||||||
|
|
||||||
Return the current state of the services so they can be restored
|
Return the current state of the services so they can be restored
|
||||||
accurately.
|
accurately.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
state = []
|
state = []
|
||||||
for app in apps:
|
for component in components:
|
||||||
for service in app.manifest.get('services', []):
|
for service in component.services:
|
||||||
state.append(ServiceHandler.create(app, service))
|
state.append(ServiceHandler.create(component, service))
|
||||||
|
|
||||||
for service in reversed(state):
|
for service in reversed(state):
|
||||||
service.stop()
|
service.stop()
|
||||||
@ -480,8 +408,14 @@ def _run_hooks(hook, packet):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
logger.info('Running %s hooks', hook)
|
logger.info('Running %s hooks', hook)
|
||||||
for app in packet.apps:
|
for component in packet.components:
|
||||||
app.run_hook(hook, packet)
|
try:
|
||||||
|
getattr(component, hook)(packet)
|
||||||
|
except Exception as exception:
|
||||||
|
logger.exception(
|
||||||
|
'Error running backup/restore hook for app %s: %s',
|
||||||
|
component.app.app_id, exception)
|
||||||
|
packet.errors.append(BackupError('hook', component, hook=hook))
|
||||||
|
|
||||||
|
|
||||||
def _run_operation(handler, packet, encryption_passphrase=None):
|
def _run_operation(handler, packet, encryption_passphrase=None):
|
||||||
|
|||||||
@ -24,16 +24,16 @@ from .repository import get_repositories
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _get_app_choices(apps):
|
def _get_app_choices(components):
|
||||||
"""Return a list of check box multiple choices from list of apps."""
|
"""Return a list of check box multiple choices from list of components."""
|
||||||
choices = []
|
choices = []
|
||||||
for app in apps:
|
for component in components:
|
||||||
name = app.app.app.info.name
|
name = component.app.info.name
|
||||||
if not app.has_data:
|
if not component.has_data:
|
||||||
name = ugettext('{app} (No data to backup)').format(
|
name = ugettext('{app} (No data to backup)').format(
|
||||||
app=app.app.app.info.name)
|
app=component.app.info.name)
|
||||||
|
|
||||||
choices.append((app.name, name))
|
choices.append((component.app_id, name))
|
||||||
|
|
||||||
return choices
|
return choices
|
||||||
|
|
||||||
@ -59,9 +59,12 @@ class CreateArchiveForm(forms.Form):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
"""Initialize the form with selectable apps."""
|
"""Initialize the form with selectable apps."""
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
apps = api.get_all_apps_for_backup()
|
components = api.get_all_components_for_backup()
|
||||||
self.fields['selected_apps'].choices = _get_app_choices(apps)
|
choices = _get_app_choices(components)
|
||||||
self.fields['selected_apps'].initial = [app.name for app in apps]
|
self.fields['selected_apps'].choices = choices
|
||||||
|
self.fields['selected_apps'].initial = [
|
||||||
|
choice[0] for choice in choices
|
||||||
|
]
|
||||||
self.fields['repository'].choices = _get_repository_choices()
|
self.fields['repository'].choices = _get_repository_choices()
|
||||||
|
|
||||||
|
|
||||||
@ -72,10 +75,13 @@ class RestoreForm(forms.Form):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
"""Initialize the form with selectable apps."""
|
"""Initialize the form with selectable apps."""
|
||||||
apps = kwargs.pop('apps')
|
components = kwargs.pop('components')
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields['selected_apps'].choices = _get_app_choices(apps)
|
choices = _get_app_choices(components)
|
||||||
self.fields['selected_apps'].initial = [app.name for app in apps]
|
self.fields['selected_apps'].choices = choices
|
||||||
|
self.fields['selected_apps'].initial = [
|
||||||
|
choice[0] for choice in choices
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class UploadForm(forms.Form):
|
class UploadForm(forms.Form):
|
||||||
|
|||||||
@ -3,9 +3,7 @@
|
|||||||
Application manifest for backups.
|
Application manifest for backups.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
# Currently, backup application does not have any settings. However, settings
|
# Currently, backup application does not have any settings. However, settings
|
||||||
# such as scheduler settings, backup location, secrets to connect to remove
|
# such as scheduler settings, backup location, secrets to connect to remove
|
||||||
# servers need to be backed up.
|
# servers need to be backed up.
|
||||||
backup = validate_backup({})
|
backup = {}
|
||||||
|
|||||||
@ -158,6 +158,7 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
|
|
||||||
def remove(self):
|
def remove(self):
|
||||||
"""Remove a borg repository"""
|
"""Remove a borg repository"""
|
||||||
|
|
||||||
def list_archives(self):
|
def list_archives(self):
|
||||||
"""Return list of archives in this repository."""
|
"""Return list of archives in this repository."""
|
||||||
output = self.run(['list-repo', '--path', self.borg_path])
|
output = self.run(['list-repo', '--path', self.borg_path])
|
||||||
@ -165,12 +166,12 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
return sorted(archives, key=lambda archive: archive['start'],
|
return sorted(archives, key=lambda archive: archive['start'],
|
||||||
reverse=True)
|
reverse=True)
|
||||||
|
|
||||||
def create_archive(self, archive_name, app_names):
|
def create_archive(self, archive_name, app_ids):
|
||||||
"""Create a new archive in this repository with given name."""
|
"""Create a new archive in this repository with given name."""
|
||||||
archive_path = self._get_archive_path(archive_name)
|
archive_path = self._get_archive_path(archive_name)
|
||||||
passphrase = self.credentials.get('encryption_passphrase', None)
|
passphrase = self.credentials.get('encryption_passphrase', None)
|
||||||
api.backup_apps(_backup_handler, path=archive_path,
|
api.backup_apps(_backup_handler, path=archive_path, app_ids=app_ids,
|
||||||
app_names=app_names, encryption_passphrase=passphrase)
|
encryption_passphrase=passphrase)
|
||||||
|
|
||||||
def delete_archive(self, archive_name):
|
def delete_archive(self, archive_name):
|
||||||
"""Delete an archive with given name from this repository."""
|
"""Delete an archive with given name from this repository."""
|
||||||
@ -222,6 +223,7 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
|
|
||||||
def get_download_stream(self, archive_name):
|
def get_download_stream(self, archive_name):
|
||||||
"""Return an stream of .tar.gz binary data for a backup archive."""
|
"""Return an stream of .tar.gz binary data for a backup archive."""
|
||||||
|
|
||||||
class BufferedReader(io.BufferedReader):
|
class BufferedReader(io.BufferedReader):
|
||||||
"""Improve performance of buffered binary streaming.
|
"""Improve performance of buffered binary streaming.
|
||||||
|
|
||||||
@ -235,6 +237,7 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
binary data.
|
binary data.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __next__(self):
|
def __next__(self):
|
||||||
"""Override to call read() instead of readline()."""
|
"""Override to call read() instead of readline()."""
|
||||||
chunk = self.read(io.DEFAULT_BUFFER_SIZE)
|
chunk = self.read(io.DEFAULT_BUFFER_SIZE)
|
||||||
@ -279,11 +282,11 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
output = self.run(['get-archive-apps', '--path', archive_path])
|
output = self.run(['get-archive-apps', '--path', archive_path])
|
||||||
return output.splitlines()
|
return output.splitlines()
|
||||||
|
|
||||||
def restore_archive(self, archive_name, apps=None):
|
def restore_archive(self, archive_name, app_ids=None):
|
||||||
"""Restore an archive from this repository to the system."""
|
"""Restore an archive from this repository to the system."""
|
||||||
archive_path = self._get_archive_path(archive_name)
|
archive_path = self._get_archive_path(archive_name)
|
||||||
passphrase = self.credentials.get('encryption_passphrase', None)
|
passphrase = self.credentials.get('encryption_passphrase', None)
|
||||||
api.restore_apps(restore_archive_handler, app_names=apps,
|
api.restore_apps(restore_archive_handler, app_ids=app_ids,
|
||||||
create_subvolume=False, backup_file=archive_path,
|
create_subvolume=False, backup_file=archive_path,
|
||||||
encryption_passphrase=passphrase)
|
encryption_passphrase=passphrase)
|
||||||
|
|
||||||
|
|||||||
@ -8,13 +8,18 @@ from unittest.mock import MagicMock, call, patch
|
|||||||
import pytest
|
import pytest
|
||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
|
|
||||||
|
from plinth.app import App
|
||||||
|
|
||||||
from .. import api, forms, repository
|
from .. import api, forms, repository
|
||||||
|
from ..components import BackupRestore
|
||||||
|
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
|
|
||||||
|
setup_helper = MagicMock()
|
||||||
|
|
||||||
|
|
||||||
def _get_test_manifest(name):
|
def _get_test_manifest(name):
|
||||||
return api.validate({
|
return {
|
||||||
'config': {
|
'config': {
|
||||||
'directories': ['/etc/' + name + '/config.d/'],
|
'directories': ['/etc/' + name + '/config.d/'],
|
||||||
'files': ['/etc/' + name + '/config'],
|
'files': ['/etc/' + name + '/config'],
|
||||||
@ -32,50 +37,42 @@ def _get_test_manifest(name):
|
|||||||
'name': name,
|
'name': name,
|
||||||
'kind': 'site'
|
'kind': 'site'
|
||||||
}]
|
}]
|
||||||
})
|
}
|
||||||
|
|
||||||
|
|
||||||
def _get_backup_app(name):
|
def _get_backup_component(name):
|
||||||
"""Return a dummy BackupApp object."""
|
"""Return a BackupRestore component."""
|
||||||
return api.BackupApp(name, MagicMock(backup=_get_test_manifest(name)))
|
return BackupRestore(name, **_get_test_manifest(name))
|
||||||
|
|
||||||
|
|
||||||
class TestBackupApp:
|
class AppTest(App):
|
||||||
"""Test the BackupApp class."""
|
"""Sample App for testing."""
|
||||||
@staticmethod
|
app_id = 'test-app'
|
||||||
def test_run_hook():
|
|
||||||
"""Test running a hook on an application."""
|
|
||||||
packet = api.Packet('backup', 'apps', '/', [])
|
|
||||||
hook = 'testhook_pre'
|
|
||||||
app = MagicMock()
|
|
||||||
backup_app = api.BackupApp('app_name', app)
|
|
||||||
backup_app.run_hook(hook, packet)
|
|
||||||
|
|
||||||
app.testhook_pre.assert_has_calls([call(packet)])
|
|
||||||
assert not packet.errors
|
|
||||||
|
|
||||||
app.testhook_pre.reset_mock()
|
def _get_test_app(name):
|
||||||
app.testhook_pre.side_effect = Exception()
|
"""Return an App."""
|
||||||
backup_app.run_hook(hook, packet)
|
app = AppTest()
|
||||||
assert packet.errors == [api.BackupError('hook', app, hook=hook)]
|
app.app_id = name
|
||||||
|
app._all_apps[name] = app
|
||||||
del app.testhook_pre
|
app.add(_get_backup_component(name + '-component'))
|
||||||
backup_app.run_hook(hook, packet)
|
return app
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures('load_cfg')
|
@pytest.mark.usefixtures('load_cfg')
|
||||||
class TestBackupProcesses:
|
class TestBackupProcesses:
|
||||||
"""Test cases for backup processes"""
|
"""Test cases for backup processes"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test_packet_process_manifests():
|
def test_packet_collected_files_directories():
|
||||||
"""Test that directories/files are collected from manifests."""
|
"""Test that directories/files are collected from manifests."""
|
||||||
apps = [_get_backup_app('a'), _get_backup_app('b')]
|
components = [_get_backup_component('a'), _get_backup_component('b')]
|
||||||
packet = api.Packet('backup', 'apps', '/', apps)
|
packet = api.Packet('backup', 'apps', '/', components)
|
||||||
for app in apps:
|
for component in components:
|
||||||
for section in ['config', 'data', 'secrets']:
|
for section in ['config', 'data', 'secrets']:
|
||||||
for directory in app.manifest[section]['directories']:
|
for directory in getattr(component, section)['directories']:
|
||||||
assert directory in packet.directories
|
assert directory in packet.directories
|
||||||
for file_path in app.manifest[section]['files']:
|
for file_path in getattr(component, section)['files']:
|
||||||
assert file_path in packet.files
|
assert file_path in packet.files
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -97,50 +94,56 @@ class TestBackupProcesses:
|
|||||||
restore_handler.assert_called_once()
|
restore_handler.assert_called_once()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@patch('plinth.module_loader.loaded_modules.items')
|
@patch('importlib.import_module')
|
||||||
def test_get_all_apps_for_backup(modules):
|
@patch('plinth.app.App.list')
|
||||||
"""Test listing apps supporting backup and needing backup."""
|
def test_get_all_components_for_backup(apps_list, import_module):
|
||||||
apps = [
|
"""Test listing components supporting backup and needing backup."""
|
||||||
('a', MagicMock(backup=_get_test_manifest('a'))),
|
modules = [MagicMock(), MagicMock(), MagicMock()]
|
||||||
('b', MagicMock(backup=_get_test_manifest('b'))),
|
import_module.side_effect = modules
|
||||||
('c', MagicMock(backup=None)),
|
apps = [_get_test_app('a'), _get_test_app('b'), _get_test_app('c')]
|
||||||
('d', MagicMock()),
|
modules[1].setup_helper.get_state.side_effect = ['needs-setup']
|
||||||
]
|
apps_list.return_value = apps
|
||||||
del apps[3][1].backup
|
|
||||||
modules.return_value = apps
|
|
||||||
|
|
||||||
returned_apps = api.get_all_apps_for_backup()
|
returned_components = api.get_all_components_for_backup()
|
||||||
expected_apps = [
|
expected_components = [
|
||||||
api.BackupApp('a', apps[0][1]),
|
apps[0].components['a-component'],
|
||||||
api.BackupApp('b', apps[1][1]),
|
apps[2].components['c-component']
|
||||||
api.BackupApp('c', apps[2][1])
|
|
||||||
]
|
]
|
||||||
assert returned_apps == expected_apps
|
assert returned_components == expected_components
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@patch('plinth.module_loader.loaded_modules.items')
|
@patch('plinth.app.App.list')
|
||||||
def test_get_apps_in_order(modules):
|
def test_get_components_in_order(apps_list):
|
||||||
"""Test that apps are listed in correct dependency order."""
|
"""Test that components are listed in correct dependency order."""
|
||||||
apps = [
|
apps = [
|
||||||
('names', MagicMock(backup=_get_test_manifest('names'))),
|
_get_test_app('names'),
|
||||||
('config', MagicMock(backup=_get_test_manifest('config'))),
|
_get_test_app('other'),
|
||||||
|
_get_test_app('config')
|
||||||
]
|
]
|
||||||
modules.return_value = apps
|
apps_list.return_value = apps
|
||||||
|
|
||||||
app_names = ['config', 'names']
|
app_ids = ['config', 'names']
|
||||||
apps = api.get_apps_in_order(app_names)
|
components = api.get_components_in_order(app_ids)
|
||||||
assert apps[0].name == 'names'
|
assert len(components) == 2
|
||||||
assert apps[1].name == 'config'
|
assert components[0].app_id == 'names'
|
||||||
|
assert components[1].app_id == 'config'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test__lockdown_apps():
|
def test__lockdown_apps():
|
||||||
"""Test that locked flag is set for each app."""
|
"""Test that locked flag is set for each app."""
|
||||||
app_a = MagicMock(locked=False)
|
apps = [_get_test_app('test-app-1'), _get_test_app('test-app-2')]
|
||||||
app_b = MagicMock(locked=None)
|
components = [
|
||||||
apps = [MagicMock(app=app_a), MagicMock(app=app_b)]
|
apps[0].components['test-app-1-component'],
|
||||||
api._lockdown_apps(apps, True)
|
apps[1].components['test-app-2-component']
|
||||||
assert app_a.locked is True
|
]
|
||||||
assert app_b.locked is True
|
|
||||||
|
api._lockdown_apps(components, True)
|
||||||
|
assert apps[0].locked
|
||||||
|
assert apps[1].locked
|
||||||
|
|
||||||
|
api._lockdown_apps(components, False)
|
||||||
|
assert not apps[0].locked
|
||||||
|
assert not apps[1].locked
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@patch('plinth.action_utils.webserver_is_enabled')
|
@patch('plinth.action_utils.webserver_is_enabled')
|
||||||
@ -148,19 +151,20 @@ class TestBackupProcesses:
|
|||||||
@patch('plinth.actions.superuser_run')
|
@patch('plinth.actions.superuser_run')
|
||||||
def test__shutdown_services(run, service_is_running, webserver_is_enabled):
|
def test__shutdown_services(run, service_is_running, webserver_is_enabled):
|
||||||
"""Test that services are stopped in correct order."""
|
"""Test that services are stopped in correct order."""
|
||||||
apps = [_get_backup_app('a'), _get_backup_app('b')]
|
components = [_get_backup_component('a'), _get_backup_component('b')]
|
||||||
service_is_running.return_value = True
|
service_is_running.return_value = True
|
||||||
webserver_is_enabled.return_value = True
|
webserver_is_enabled.return_value = True
|
||||||
state = api._shutdown_services(apps)
|
state = api._shutdown_services(components)
|
||||||
|
|
||||||
expected_state = [
|
expected_state = [
|
||||||
api.ServiceHandler.create(apps[0],
|
api.ServiceHandler.create(components[0],
|
||||||
apps[0].manifest['services'][0]),
|
components[0].services[0]),
|
||||||
api.ServiceHandler.create(apps[0],
|
api.ServiceHandler.create(components[0],
|
||||||
apps[0].manifest['services'][1]),
|
components[0].services[1]),
|
||||||
api.ServiceHandler.create(apps[1],
|
api.ServiceHandler.create(components[1],
|
||||||
apps[1].manifest['services'][0]),
|
components[1].services[0]),
|
||||||
api.ServiceHandler.create(apps[1], apps[1].manifest['services'][1])
|
api.ServiceHandler.create(components[1],
|
||||||
|
components[1].services[1]),
|
||||||
]
|
]
|
||||||
assert state == expected_state
|
assert state == expected_state
|
||||||
|
|
||||||
@ -207,21 +211,26 @@ class TestBackupProcesses:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def test__run_operation():
|
def test__run_operation():
|
||||||
"""Test that operation runs handler and app hooks."""
|
"""Test that operation runs handler and app hooks."""
|
||||||
apps = [_get_backup_app('a'), _get_backup_app('b')]
|
components = [_get_backup_component('a'), _get_backup_component('b')]
|
||||||
packet = api.Packet('backup', 'apps', '/', apps)
|
packet = api.Packet('backup', 'apps', '/', components)
|
||||||
packet.apps[0].run_hook = MagicMock()
|
packet.components[0].backup_pre = MagicMock()
|
||||||
packet.apps[1].run_hook = MagicMock()
|
packet.components[0].backup_post = MagicMock()
|
||||||
|
packet.components[1].backup_pre = MagicMock()
|
||||||
|
packet.components[1].backup_post = MagicMock()
|
||||||
handler = MagicMock()
|
handler = MagicMock()
|
||||||
api._run_operation(handler, packet)
|
api._run_operation(handler, packet)
|
||||||
handler.assert_has_calls([call(packet, encryption_passphrase=None)])
|
handler.assert_has_calls([call(packet, encryption_passphrase=None)])
|
||||||
|
|
||||||
calls = [call('backup_pre', packet), call('backup_post', packet)]
|
calls = [call(packet)]
|
||||||
packet.apps[0].run_hook.assert_has_calls(calls)
|
packet.components[0].backup_pre.assert_has_calls(calls)
|
||||||
packet.apps[1].run_hook.assert_has_calls(calls)
|
packet.components[0].backup_post.assert_has_calls(calls)
|
||||||
|
packet.components[1].backup_pre.assert_has_calls(calls)
|
||||||
|
packet.components[1].backup_post.assert_has_calls(calls)
|
||||||
|
|
||||||
|
|
||||||
class TestBackupModule:
|
class TestBackupModule:
|
||||||
"""Tests of the backups django module, like views or forms."""
|
"""Tests of the backups django module, like views or forms."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test_file_upload():
|
def test_file_upload():
|
||||||
# posting a video should fail
|
# posting a video should fail
|
||||||
|
|||||||
@ -147,7 +147,7 @@ class BaseRestoreView(SuccessMessageMixin, FormView):
|
|||||||
"""Pass additional keyword args for instantiating the form."""
|
"""Pass additional keyword args for instantiating the form."""
|
||||||
kwargs = super().get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
included_apps = self._get_included_apps()
|
included_apps = self._get_included_apps()
|
||||||
kwargs['apps'] = api.get_apps_in_order(included_apps)
|
kwargs['components'] = api.get_components_in_order(included_apps)
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
|||||||
@ -11,9 +11,10 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.modules.apache.components import Uwsgi, Webserver
|
from plinth.modules.apache.components import Uwsgi, Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 2
|
version = 2
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ class BepastyApp(app_module.App):
|
|||||||
icon_filename='bepasty',
|
icon_filename='bepasty',
|
||||||
short_description=_('File & Snippet Sharing'),
|
short_description=_('File & Snippet Sharing'),
|
||||||
description=_description, manual_page='bepasty',
|
description=_description, manual_page='bepasty',
|
||||||
clients=clients)
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-bepasty', info.name,
|
menu_item = menu.Menu('menu-bepasty', info.name,
|
||||||
@ -75,7 +76,7 @@ class BepastyApp(app_module.App):
|
|||||||
shortcut = frontpage.Shortcut('shortcut-bepasty', info.name,
|
shortcut = frontpage.Shortcut('shortcut-bepasty', info.name,
|
||||||
info.short_description,
|
info.short_description,
|
||||||
info.icon_filename, '/bepasty',
|
info.icon_filename, '/bepasty',
|
||||||
clients=clients)
|
clients=manifest.clients)
|
||||||
self.add(shortcut)
|
self.add(shortcut)
|
||||||
|
|
||||||
firewall = Firewall('firewall-bepasty', info.name,
|
firewall = Firewall('firewall-bepasty', info.name,
|
||||||
@ -89,6 +90,10 @@ class BepastyApp(app_module.App):
|
|||||||
urls=['https://{host}/bepasty/'])
|
urls=['https://{host}/bepasty/'])
|
||||||
self.add(webserver)
|
self.add(webserver)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-bepasty',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name': _('bepasty'),
|
'name': _('bepasty'),
|
||||||
@ -13,7 +12,7 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'config': {
|
'config': {
|
||||||
'files': ['/etc/bepasty-freedombox.conf']
|
'files': ['/etc/bepasty-freedombox.conf']
|
||||||
},
|
},
|
||||||
@ -21,4 +20,4 @@ backup = validate_backup({
|
|||||||
'directories': ['/var/lib/bepasty']
|
'directories': ['/var/lib/bepasty']
|
||||||
},
|
},
|
||||||
'services': ['uwsgi'],
|
'services': ['uwsgi'],
|
||||||
})
|
}
|
||||||
|
|||||||
@ -14,10 +14,11 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, menu
|
from plinth import cfg, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 2
|
version = 2
|
||||||
|
|
||||||
@ -96,6 +97,10 @@ class BindApp(app_module.App):
|
|||||||
alias=managed_services[1])
|
alias=managed_services[1])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-bind',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,11 +3,9 @@
|
|||||||
Application manifest for bind.
|
Application manifest for bind.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {
|
||||||
|
|
||||||
backup = validate_backup({
|
|
||||||
'config': {
|
'config': {
|
||||||
'files': ['/etc/bind/named.conf.options']
|
'files': ['/etc/bind/named.conf.options']
|
||||||
},
|
},
|
||||||
'services': ['bind9']
|
'services': ['bind9']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -13,11 +13,12 @@ from plinth import app as app_module
|
|||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ class CalibreApp(app_module.App):
|
|||||||
name=_('calibre'), icon_filename='calibre',
|
name=_('calibre'), icon_filename='calibre',
|
||||||
short_description=_('E-book Library'),
|
short_description=_('E-book Library'),
|
||||||
description=_description, manual_page='Calibre',
|
description=_description, manual_page='Calibre',
|
||||||
clients=clients,
|
clients=manifest.clients,
|
||||||
donation_url='https://calibre-ebook.com/donate')
|
donation_url='https://calibre-ebook.com/donate')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
@ -94,6 +95,10 @@ class CalibreApp(app_module.App):
|
|||||||
groups=groups)
|
groups=groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-calibre',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name': _('calibre'),
|
'name': _('calibre'),
|
||||||
@ -13,9 +12,9 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'data': {
|
'data': {
|
||||||
'directories': ['/var/lib/private/calibre-server-freedombox/']
|
'directories': ['/var/lib/private/calibre-server-freedombox/']
|
||||||
},
|
},
|
||||||
'services': ['calibre-server-freedombox']
|
'services': ['calibre-server-freedombox']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -12,12 +12,12 @@ from plinth import cfg, frontpage, menu
|
|||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules import names
|
from plinth.modules import names
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.signals import domain_added, domain_removed
|
from plinth.signals import domain_added, domain_removed
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from . import utils
|
from . import manifest, utils
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ class CockpitApp(app_module.App):
|
|||||||
icon='fa-wrench', icon_filename='cockpit',
|
icon='fa-wrench', icon_filename='cockpit',
|
||||||
short_description=_('Server Administration'),
|
short_description=_('Server Administration'),
|
||||||
description=_description, manual_page='Cockpit',
|
description=_description, manual_page='Cockpit',
|
||||||
clients=clients)
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-cockpit', info.name,
|
menu_item = menu.Menu('menu-cockpit', info.name,
|
||||||
@ -92,6 +92,10 @@ class CockpitApp(app_module.App):
|
|||||||
daemon = Daemon('daemon-cockpit', managed_services[0])
|
daemon = Daemon('daemon-cockpit', managed_services[0])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-cockpit',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
domain_added.connect(on_domain_added)
|
domain_added.connect(on_domain_added)
|
||||||
domain_removed.connect(on_domain_removed)
|
domain_removed.connect(on_domain_removed)
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,6 @@ Application manifest for cockpit.
|
|||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
@ -20,4 +19,4 @@ clients = validate([{
|
|||||||
# triggered on every Plinth domain change (and cockpit application install) and
|
# triggered on every Plinth domain change (and cockpit application install) and
|
||||||
# will set the value of allowed domains correctly. This is the only key the is
|
# will set the value of allowed domains correctly. This is the only key the is
|
||||||
# customized in cockpit.conf.
|
# customized in cockpit.conf.
|
||||||
backup = validate_backup({})
|
backup = {}
|
||||||
|
|||||||
@ -13,11 +13,12 @@ from plinth import app as app_module
|
|||||||
from plinth import menu
|
from plinth import menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules import names
|
from plinth.modules import names
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.letsencrypt.components import LetsEncrypt
|
from plinth.modules.letsencrypt.components import LetsEncrypt
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -86,6 +87,10 @@ class CoturnApp(app_module.App):
|
|||||||
reserved_usernames=['turnserver'])
|
reserved_usernames=['turnserver'])
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-coturn',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -1,10 +1,3 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {'secrets': {'directories': ['/etc/coturn']}, 'services': ['coturn']}
|
||||||
|
|
||||||
backup = validate_backup({
|
|
||||||
'secrets': {
|
|
||||||
'directories': ['/etc/coturn']
|
|
||||||
},
|
|
||||||
'services': ['coturn']
|
|
||||||
})
|
|
||||||
|
|||||||
@ -10,8 +10,9 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import menu
|
from plinth import menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 2
|
version = 2
|
||||||
|
|
||||||
@ -79,6 +80,10 @@ class DateTimeApp(app_module.App):
|
|||||||
daemon = Daemon('daemon-datetime', managed_services[0])
|
daemon = Daemon('daemon-datetime', managed_services[0])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-datetime',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
def diagnose(self):
|
def diagnose(self):
|
||||||
"""Run diagnostics and return the results."""
|
"""Run diagnostics and return the results."""
|
||||||
results = super().diagnose()
|
results = super().diagnose()
|
||||||
|
|||||||
@ -3,6 +3,4 @@
|
|||||||
Application manifest for datetime.
|
Application manifest for datetime.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {'data': {'files': ['/etc/timezone']}}
|
||||||
|
|
||||||
backup = validate_backup({'data': {'files': ['/etc/timezone']}})
|
|
||||||
|
|||||||
@ -10,11 +10,12 @@ from plinth import app as app_module
|
|||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users import add_user_to_share_group
|
from plinth.modules.users import add_user_to_share_group
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 6
|
version = 6
|
||||||
|
|
||||||
@ -50,7 +51,8 @@ class DelugeApp(app_module.App):
|
|||||||
app_id=self.app_id, version=version, name=_('Deluge'),
|
app_id=self.app_id, version=version, name=_('Deluge'),
|
||||||
icon_filename='deluge',
|
icon_filename='deluge',
|
||||||
short_description=_('BitTorrent Web Client'),
|
short_description=_('BitTorrent Web Client'),
|
||||||
description=_description, manual_page='Deluge', clients=clients,
|
description=_description, manual_page='Deluge',
|
||||||
|
clients=manifest.clients,
|
||||||
donation_url='https://www.patreon.com/deluge_cas')
|
donation_url='https://www.patreon.com/deluge_cas')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
@ -88,6 +90,10 @@ class DelugeApp(app_module.App):
|
|||||||
groups=groups)
|
groups=groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-deluge',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name': _('Deluge'),
|
'name': _('Deluge'),
|
||||||
@ -14,9 +13,9 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'config': {
|
'config': {
|
||||||
'directories': ['/var/lib/deluged/.config']
|
'directories': ['/var/lib/deluged/.config']
|
||||||
},
|
},
|
||||||
'services': ['deluged', 'deluge-web']
|
'services': ['deluged', 'deluge-web']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -16,8 +16,9 @@ from django.utils.translation import ugettext_noop
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, daemon, glib, menu
|
from plinth import cfg, daemon, glib, menu
|
||||||
from plinth.modules.apache.components import diagnose_url_on_all
|
from plinth.modules.apache.components import diagnose_url_on_all
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -57,6 +58,10 @@ class DiagnosticsApp(app_module.App):
|
|||||||
'diagnostics:index', parent_url_name='system')
|
'diagnostics:index', parent_url_name='system')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-diagnostics',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
# Check periodically for low RAM space
|
# Check periodically for low RAM space
|
||||||
interval = 180 if cfg.develop else 3600
|
interval = 180 if cfg.develop else 3600
|
||||||
glib.schedule(interval, _warn_about_low_ram_space)
|
glib.schedule(interval, _warn_about_low_ram_space)
|
||||||
|
|||||||
@ -3,6 +3,4 @@
|
|||||||
Application manifest for diagnostics.
|
Application manifest for diagnostics.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {}
|
||||||
|
|
||||||
backup = validate_backup({})
|
|
||||||
|
|||||||
@ -52,8 +52,6 @@ _description = [
|
|||||||
' federate with other diaspora* pods.')
|
' federate with other diaspora* pods.')
|
||||||
]
|
]
|
||||||
|
|
||||||
from .manifest import clients # noqa pylint:disable=E402 isort:skip
|
|
||||||
|
|
||||||
app = None
|
app = None
|
||||||
|
|
||||||
|
|
||||||
@ -65,10 +63,12 @@ class DiasporaApp(app_module.App):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Create components for the app."""
|
"""Create components for the app."""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
from . import manifest
|
||||||
info = app_module.Info(app_id=self.app_id, version=version,
|
info = app_module.Info(app_id=self.app_id, version=version,
|
||||||
name=_('diaspora*'), icon_filename='diaspora',
|
name=_('diaspora*'), icon_filename='diaspora',
|
||||||
short_description=_('Federated Social Network'),
|
short_description=_('Federated Social Network'),
|
||||||
description=_description, clients=clients)
|
description=_description,
|
||||||
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-diaspora', info.name,
|
menu_item = menu.Menu('menu-diaspora', info.name,
|
||||||
|
|||||||
@ -8,12 +8,13 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
from plinth import actions
|
from plinth import actions
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, menu
|
from plinth import cfg, menu
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.names.components import DomainType
|
from plinth.modules.names.components import DomainType
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.signals import domain_added
|
from plinth.signals import domain_added
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -70,6 +71,10 @@ class DynamicDNSApp(app_module.App):
|
|||||||
reserved_usernames=['ez-ipupd'])
|
reserved_usernames=['ez-ipupd'])
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-dynamicdns',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
current_status = get_status()
|
current_status = get_status()
|
||||||
if current_status['enabled']:
|
if current_status['enabled']:
|
||||||
domain_added.send_robust(sender='dynamicdns',
|
domain_added.send_robust(sender='dynamicdns',
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {'config': {'directories': ['/etc/ez-ipupdate/']}}
|
||||||
|
|
||||||
backup = validate_backup({'config': {'directories': ['/etc/ez-ipupdate/']}})
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@ from plinth import cfg, frontpage, menu
|
|||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules import config
|
from plinth.modules import config
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.letsencrypt.components import LetsEncrypt
|
from plinth.modules.letsencrypt.components import LetsEncrypt
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
@ -23,7 +24,7 @@ from plinth.signals import (domain_added, post_hostname_change,
|
|||||||
pre_hostname_change)
|
pre_hostname_change)
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
@ -63,7 +64,8 @@ class EjabberdApp(app_module.App):
|
|||||||
name=_('ejabberd'), icon_filename='ejabberd',
|
name=_('ejabberd'), icon_filename='ejabberd',
|
||||||
short_description=_('Chat Server'),
|
short_description=_('Chat Server'),
|
||||||
description=_description,
|
description=_description,
|
||||||
manual_page='ejabberd', clients=clients)
|
manual_page='ejabberd',
|
||||||
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-ejabberd', info.name,
|
menu_item = menu.Menu('menu-ejabberd', info.name,
|
||||||
@ -107,6 +109,10 @@ class EjabberdApp(app_module.App):
|
|||||||
reserved_usernames=['ejabberd'])
|
reserved_usernames=['ejabberd'])
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-ejabberd',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
pre_hostname_change.connect(on_pre_hostname_change)
|
pre_hostname_change.connect(on_pre_hostname_change)
|
||||||
post_hostname_change.connect(on_post_hostname_change)
|
post_hostname_change.connect(on_post_hostname_change)
|
||||||
domain_added.connect(on_domain_added)
|
domain_added.connect(on_domain_added)
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
from plinth.modules.jsxc import manifest as jsxc_manifest
|
from plinth.modules.jsxc import manifest as jsxc_manifest
|
||||||
|
|
||||||
_clients = validate([{
|
_clients = validate([{
|
||||||
@ -106,7 +105,7 @@ _clients.extend(jsxc_manifest.clients)
|
|||||||
|
|
||||||
clients = _clients
|
clients = _clients
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'config': {
|
'config': {
|
||||||
'files': ['/etc/ejabberd/ejabberd.yml']
|
'files': ['/etc/ejabberd/ejabberd.yml']
|
||||||
},
|
},
|
||||||
@ -118,4 +117,4 @@ backup = validate_backup({
|
|||||||
'directories': ['/etc/ejabberd/letsencrypt/']
|
'directories': ['/etc/ejabberd/letsencrypt/']
|
||||||
},
|
},
|
||||||
'services': ['ejabberd']
|
'services': ['ejabberd']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -12,9 +12,10 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, menu
|
from plinth import cfg, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.utils import Version, format_lazy, import_from_gi
|
from plinth.utils import Version, format_lazy, import_from_gi
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
gio = import_from_gi('Gio', '2.0')
|
gio = import_from_gi('Gio', '2.0')
|
||||||
glib = import_from_gi('GLib', '2.0')
|
glib = import_from_gi('GLib', '2.0')
|
||||||
@ -74,6 +75,10 @@ class FirewallApp(app_module.App):
|
|||||||
daemon = Daemon('daemon-firewall', managed_services[0])
|
daemon = Daemon('daemon-firewall', managed_services[0])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-firewall',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def _run_setup():
|
def _run_setup():
|
||||||
"""Run firewalld setup."""
|
"""Run firewalld setup."""
|
||||||
|
|||||||
@ -3,6 +3,4 @@
|
|||||||
Application manifest for firewall.
|
Application manifest for firewall.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {}
|
||||||
|
|
||||||
backup = validate_backup({})
|
|
||||||
|
|||||||
@ -13,12 +13,13 @@ from plinth import app as app_module
|
|||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.errors import ActionError
|
from plinth.errors import ActionError
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
|
|
||||||
|
from . import manifest
|
||||||
from .forms import is_repo_url
|
from .forms import is_repo_url
|
||||||
from .manifest import ( # noqa, pylint: disable=unused-import
|
from .manifest import GIT_REPO_PATH
|
||||||
GIT_REPO_PATH, backup, clients)
|
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ class GitwebApp(app_module.App):
|
|||||||
name=_('Gitweb'), icon_filename='gitweb',
|
name=_('Gitweb'), icon_filename='gitweb',
|
||||||
short_description=_('Simple Git Hosting'),
|
short_description=_('Simple Git Hosting'),
|
||||||
description=_description, manual_page='GitWeb',
|
description=_description, manual_page='GitWeb',
|
||||||
clients=clients)
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-gitweb', info.name, info.short_description,
|
menu_item = menu.Menu('menu-gitweb', info.name, info.short_description,
|
||||||
@ -88,6 +89,10 @@ class GitwebApp(app_module.App):
|
|||||||
groups=groups)
|
groups=groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = GitwebBackupRestore('backup-restore-gitweb',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
setup_helper = globals()['setup_helper']
|
setup_helper = globals()['setup_helper']
|
||||||
if setup_helper.get_state() != 'needs-setup':
|
if setup_helper.get_state() != 'needs-setup':
|
||||||
self.update_service_access()
|
self.update_service_access()
|
||||||
@ -140,6 +145,14 @@ class GitwebWebserverAuth(Webserver):
|
|||||||
super().enable()
|
super().enable()
|
||||||
|
|
||||||
|
|
||||||
|
class GitwebBackupRestore(BackupRestore):
|
||||||
|
"""Component to handle backup/restore for Gitweb."""
|
||||||
|
|
||||||
|
def restore_post(self, packet):
|
||||||
|
"""Update access after restoration of backups."""
|
||||||
|
app.update_service_access()
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
helper.install(managed_packages)
|
helper.install(managed_packages)
|
||||||
@ -147,11 +160,6 @@ def setup(helper, old_version=None):
|
|||||||
helper.call('post', app.enable)
|
helper.call('post', app.enable)
|
||||||
|
|
||||||
|
|
||||||
def restore_post(packet):
|
|
||||||
"""Update access after restoration of backups."""
|
|
||||||
app.update_service_access()
|
|
||||||
|
|
||||||
|
|
||||||
def repo_exists(name):
|
def repo_exists(name):
|
||||||
"""Check whether a remote repository exists."""
|
"""Check whether a remote repository exists."""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
CONFIG_FILE = '/etc/gitweb-freedombox.conf'
|
CONFIG_FILE = '/etc/gitweb-freedombox.conf'
|
||||||
GIT_REPO_PATH = '/var/lib/git'
|
GIT_REPO_PATH = '/var/lib/git'
|
||||||
@ -35,11 +34,11 @@ clients = validate([
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'config': {
|
'config': {
|
||||||
'files': [CONFIG_FILE]
|
'files': [CONFIG_FILE]
|
||||||
},
|
},
|
||||||
'data': {
|
'data': {
|
||||||
'directories': [GIT_REPO_PATH]
|
'directories': [GIT_REPO_PATH]
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|||||||
@ -10,11 +10,12 @@ from plinth import app as app_module
|
|||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.i2p.resources import FAVORITES
|
from plinth.modules.i2p.resources import FAVORITES
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -58,7 +59,8 @@ class I2PApp(app_module.App):
|
|||||||
info = app_module.Info(
|
info = app_module.Info(
|
||||||
app_id=self.app_id, version=version, name=_('I2P'),
|
app_id=self.app_id, version=version, name=_('I2P'),
|
||||||
icon_filename='i2p', short_description=_('Anonymity Network'),
|
icon_filename='i2p', short_description=_('Anonymity Network'),
|
||||||
description=_description, manual_page='I2P', clients=clients,
|
description=_description, manual_page='I2P',
|
||||||
|
clients=manifest.clients,
|
||||||
donation_url='https://geti2p.net/en/get-involved/donate')
|
donation_url='https://geti2p.net/en/get-involved/donate')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
@ -96,6 +98,9 @@ class I2PApp(app_module.App):
|
|||||||
groups=groups)
|
groups=groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-i2p', **manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -6,7 +6,6 @@ Application manifest for I2P.
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
_package_id = 'net.geti2p.i2p'
|
_package_id = 'net.geti2p.i2p'
|
||||||
_download_url = 'https://geti2p.net/download'
|
_download_url = 'https://geti2p.net/download'
|
||||||
@ -36,9 +35,9 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'secrets': {
|
'secrets': {
|
||||||
'directories': ['/var/lib/i2p/i2p-config']
|
'directories': ['/var/lib/i2p/i2p-config']
|
||||||
},
|
},
|
||||||
'services': ['i2p']
|
'services': ['i2p']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -10,11 +10,12 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ class IkiwikiApp(app_module.App):
|
|||||||
name=_('ikiwiki'), icon_filename='ikiwiki',
|
name=_('ikiwiki'), icon_filename='ikiwiki',
|
||||||
short_description=_('Wiki and Blog'),
|
short_description=_('Wiki and Blog'),
|
||||||
description=_description, manual_page='Ikiwiki',
|
description=_description, manual_page='Ikiwiki',
|
||||||
clients=clients,
|
clients=manifest.clients,
|
||||||
donation_url='https://ikiwiki.info/tipjar/')
|
donation_url='https://ikiwiki.info/tipjar/')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
@ -76,6 +77,10 @@ class IkiwikiApp(app_module.App):
|
|||||||
groups=groups)
|
groups=groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-ikiwiki',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
def add_shortcut(self, site, title):
|
def add_shortcut(self, site, title):
|
||||||
"""Add an ikiwiki shortcut to frontpage."""
|
"""Add an ikiwiki shortcut to frontpage."""
|
||||||
shortcut = frontpage.Shortcut('shortcut-ikiwiki-' + site, title,
|
shortcut = frontpage.Shortcut('shortcut-ikiwiki-' + site, title,
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
@ -13,7 +12,4 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup(
|
backup = {'data': {'directories': ['/var/lib/ikiwiki/', '/var/www/ikiwiki/']}}
|
||||||
{'data': {
|
|
||||||
'directories': ['/var/lib/ikiwiki/', '/var/www/ikiwiki/']
|
|
||||||
}})
|
|
||||||
|
|||||||
@ -10,10 +10,11 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
@ -45,7 +46,8 @@ class InfinotedApp(app_module.App):
|
|||||||
name=_('infinoted'), icon_filename='infinoted',
|
name=_('infinoted'), icon_filename='infinoted',
|
||||||
short_description=_('Gobby Server'),
|
short_description=_('Gobby Server'),
|
||||||
description=_description,
|
description=_description,
|
||||||
manual_page='Infinoted', clients=clients)
|
manual_page='Infinoted',
|
||||||
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-infinoted', info.name,
|
menu_item = menu.Menu('menu-infinoted', info.name,
|
||||||
@ -69,6 +71,10 @@ class InfinotedApp(app_module.App):
|
|||||||
listen_ports=[(6523, 'tcp4'), (6523, 'tcp6')])
|
listen_ports=[(6523, 'tcp4'), (6523, 'tcp6')])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-infinoted',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth import cfg
|
from plinth import cfg
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
@ -32,7 +31,7 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'data': {
|
'data': {
|
||||||
'directories': ['/var/lib/infinoted/']
|
'directories': ['/var/lib/infinoted/']
|
||||||
},
|
},
|
||||||
@ -43,4 +42,4 @@ backup = validate_backup({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
'services': ['infinoted']
|
'services': ['infinoted']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -10,10 +10,11 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.web_server import StaticFiles
|
from plinth.web_server import StaticFiles
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ class JSXCApp(app_module.App):
|
|||||||
name=_('JSXC'), icon_filename='jsxc',
|
name=_('JSXC'), icon_filename='jsxc',
|
||||||
short_description=_('Chat Client'),
|
short_description=_('Chat Client'),
|
||||||
description=_description, manual_page='JSXC',
|
description=_description, manual_page='JSXC',
|
||||||
clients=clients)
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-jsxc', info.name, info.short_description,
|
menu_item = menu.Menu('menu-jsxc', info.name, info.short_description,
|
||||||
@ -72,6 +73,10 @@ class JSXCApp(app_module.App):
|
|||||||
directory_map=directory_map)
|
directory_map=directory_map)
|
||||||
self.add(static_files)
|
self.add(static_files)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-jsxc',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -4,7 +4,6 @@ from django.urls import reverse_lazy
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name': _('JSXC'),
|
'name': _('JSXC'),
|
||||||
@ -14,4 +13,4 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({})
|
backup = {}
|
||||||
|
|||||||
@ -15,12 +15,12 @@ from plinth import cfg, menu
|
|||||||
from plinth.errors import ActionError
|
from plinth.errors import ActionError
|
||||||
from plinth.modules import names
|
from plinth.modules import names
|
||||||
from plinth.modules.apache.components import diagnose_url
|
from plinth.modules.apache.components import diagnose_url
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.names.components import DomainType
|
from plinth.modules.names.components import DomainType
|
||||||
from plinth.signals import domain_added, domain_removed, post_module_loading
|
from plinth.signals import domain_added, domain_removed, post_module_loading
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from . import components
|
from . import components, manifest
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
|
||||||
|
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
@ -74,6 +74,10 @@ class LetsEncryptApp(app_module.App):
|
|||||||
'letsencrypt:index', parent_url_name='system')
|
'letsencrypt:index', parent_url_name='system')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-letsencrypt',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
domain_added.connect(on_domain_added)
|
domain_added.connect(on_domain_added)
|
||||||
domain_removed.connect(on_domain_removed)
|
domain_removed.connect(on_domain_removed)
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,5 @@
|
|||||||
Application manfiest for letsencrypt.
|
Application manfiest for letsencrypt.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
# XXX: Backup and restore the Apache site configuration.
|
# XXX: Backup and restore the Apache site configuration.
|
||||||
backup = validate_backup({'secrets': {'directories': ['/etc/letsencrypt/']}})
|
backup = {'secrets': {'directories': ['/etc/letsencrypt/']}}
|
||||||
|
|||||||
@ -16,10 +16,11 @@ from plinth import app as app_module
|
|||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.letsencrypt.components import LetsEncrypt
|
from plinth.modules.letsencrypt.components import LetsEncrypt
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 6
|
version = 6
|
||||||
|
|
||||||
@ -63,12 +64,11 @@ class MatrixSynapseApp(app_module.App):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Create components for the app."""
|
"""Create components for the app."""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
info = app_module.Info(app_id=self.app_id, version=version,
|
info = app_module.Info(
|
||||||
name=_('Matrix Synapse'),
|
app_id=self.app_id, version=version, name=_('Matrix Synapse'),
|
||||||
icon_filename='matrixsynapse',
|
icon_filename='matrixsynapse', short_description=_('Chat Server'),
|
||||||
short_description=_('Chat Server'),
|
description=_description, manual_page='MatrixSynapse',
|
||||||
description=_description,
|
clients=manifest.clients)
|
||||||
manual_page='MatrixSynapse', clients=clients)
|
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-matrixsynapse', info.name,
|
menu_item = menu.Menu('menu-matrixsynapse', info.name,
|
||||||
@ -106,6 +106,10 @@ class MatrixSynapseApp(app_module.App):
|
|||||||
listen_ports=[(8008, 'tcp4'), (8448, 'tcp4')])
|
listen_ports=[(8008, 'tcp4'), (8448, 'tcp4')])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-matrixsynapse',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
_android_package_id = 'im.vector.app'
|
_android_package_id = 'im.vector.app'
|
||||||
_element_desktop_download_url = 'https://element.io/get-started'
|
_element_desktop_download_url = 'https://element.io/get-started'
|
||||||
@ -44,7 +43,7 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'config': {
|
'config': {
|
||||||
'directories': ['/etc/matrix-synapse/conf.d/'],
|
'directories': ['/etc/matrix-synapse/conf.d/'],
|
||||||
'files': [
|
'files': [
|
||||||
@ -68,4 +67,4 @@ backup = validate_backup({
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
'services': ['matrix-synapse']
|
'services': ['matrix-synapse']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -13,9 +13,10 @@ from plinth import app as app_module
|
|||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 9
|
version = 9
|
||||||
|
|
||||||
@ -58,7 +59,8 @@ class MediaWikiApp(app_module.App):
|
|||||||
name=_('MediaWiki'), icon_filename='mediawiki',
|
name=_('MediaWiki'), icon_filename='mediawiki',
|
||||||
short_description=_('Wiki'),
|
short_description=_('Wiki'),
|
||||||
description=_description,
|
description=_description,
|
||||||
manual_page='MediaWiki', clients=clients)
|
manual_page='MediaWiki',
|
||||||
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-mediawiki', info.name,
|
menu_item = menu.Menu('menu-mediawiki', info.name,
|
||||||
@ -87,6 +89,10 @@ class MediaWikiApp(app_module.App):
|
|||||||
daemon = Daemon('daemon-mediawiki', managed_services[0])
|
daemon = Daemon('daemon-mediawiki', managed_services[0])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-mediawiki',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
class Shortcut(frontpage.Shortcut):
|
class Shortcut(frontpage.Shortcut):
|
||||||
"""Frontpage shortcut for only logged users when in private mode."""
|
"""Frontpage shortcut for only logged users when in private mode."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name': _('MediaWiki'),
|
'name': _('MediaWiki'),
|
||||||
@ -13,7 +12,7 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'config': {
|
'config': {
|
||||||
'files': ['/etc/mediawiki/FreedomBoxSettings.php']
|
'files': ['/etc/mediawiki/FreedomBoxSettings.php']
|
||||||
},
|
},
|
||||||
@ -21,4 +20,4 @@ backup = validate_backup({
|
|||||||
'directories': ['/var/lib/mediawiki-db/']
|
'directories': ['/var/lib/mediawiki-db/']
|
||||||
},
|
},
|
||||||
'services': ['mediawiki-jobrunner']
|
'services': ['mediawiki-jobrunner']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -10,11 +10,12 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 2
|
version = 2
|
||||||
|
|
||||||
@ -59,7 +60,8 @@ class MinetestApp(app_module.App):
|
|||||||
info = app_module.Info(
|
info = app_module.Info(
|
||||||
app_id=self.app_id, version=version, name=_('Minetest'),
|
app_id=self.app_id, version=version, name=_('Minetest'),
|
||||||
icon_filename='minetest', short_description=_('Block Sandbox'),
|
icon_filename='minetest', short_description=_('Block Sandbox'),
|
||||||
description=_description, manual_page='Minetest', clients=clients,
|
description=_description, manual_page='Minetest',
|
||||||
|
clients=manifest.clients,
|
||||||
donation_url='https://www.minetest.net/get-involved/#donate')
|
donation_url='https://www.minetest.net/get-involved/#donate')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
@ -89,6 +91,10 @@ class MinetestApp(app_module.App):
|
|||||||
reserved_usernames=['Debian-minetest'])
|
reserved_usernames=['Debian-minetest'])
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-minetest',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
@ -37,7 +36,7 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'config': {
|
'config': {
|
||||||
'files': ['/etc/minetest/minetest.conf']
|
'files': ['/etc/minetest/minetest.conf']
|
||||||
},
|
},
|
||||||
@ -45,4 +44,4 @@ backup = validate_backup({
|
|||||||
'directories': ['/var/games/minetest-server/']
|
'directories': ['/var/games/minetest-server/']
|
||||||
},
|
},
|
||||||
'services': ['minetest-server']
|
'services': ['minetest-server']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -8,10 +8,11 @@ import plinth.app as app_module
|
|||||||
from plinth import actions, frontpage, menu
|
from plinth import actions, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa
|
from . import manifest
|
||||||
|
|
||||||
version = 2
|
version = 2
|
||||||
|
|
||||||
@ -47,7 +48,8 @@ class MiniDLNAApp(app_module.App):
|
|||||||
name=_('MiniDLNA'), icon_filename='minidlna',
|
name=_('MiniDLNA'), icon_filename='minidlna',
|
||||||
short_description=_('Simple Media Server'),
|
short_description=_('Simple Media Server'),
|
||||||
description=_description,
|
description=_description,
|
||||||
manual_page='MiniDLNA', clients=clients)
|
manual_page='MiniDLNA',
|
||||||
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu(
|
menu_item = menu.Menu(
|
||||||
@ -70,6 +72,10 @@ class MiniDLNAApp(app_module.App):
|
|||||||
allowed_groups=list(groups))
|
allowed_groups=list(groups))
|
||||||
daemon = Daemon('daemon-minidlna', managed_services[0])
|
daemon = Daemon('daemon-minidlna', managed_services[0])
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-minidlna',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
self.add(webserver)
|
self.add(webserver)
|
||||||
self.add(firewall)
|
self.add(firewall)
|
||||||
|
|||||||
@ -2,124 +2,108 @@
|
|||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
from plinth.clients import store_url, validate
|
||||||
from plinth.clients import validate, store_url
|
|
||||||
|
|
||||||
clients = validate([
|
clients = validate([
|
||||||
{
|
{
|
||||||
'name': _('vlc'),
|
'name':
|
||||||
'platforms': [
|
_('vlc'),
|
||||||
{
|
'platforms': [{
|
||||||
'type': 'package',
|
'type': 'package',
|
||||||
'os': 'gnu-linux',
|
'os': 'gnu-linux',
|
||||||
'format': 'deb',
|
'format': 'deb',
|
||||||
'name': 'vlc',
|
'name': 'vlc',
|
||||||
},
|
}, {
|
||||||
{
|
'type': 'package',
|
||||||
'type': 'package',
|
'os': 'gnu-linux',
|
||||||
'os': 'gnu-linux',
|
'format': 'rpm',
|
||||||
'format': 'rpm',
|
'name': 'vlc',
|
||||||
'name': 'vlc',
|
}, {
|
||||||
},
|
'type': 'download',
|
||||||
{
|
'os': 'windows',
|
||||||
'type': 'download',
|
'url': 'https://www.videolan.org/vlc/download-windows.html',
|
||||||
'os': 'windows',
|
}, {
|
||||||
'url': 'https://www.videolan.org/vlc/download-windows.html',
|
'type': 'download',
|
||||||
},
|
'os': 'macos',
|
||||||
{
|
'url': 'https://www.videolan.org/vlc/download-macosx.html',
|
||||||
'type': 'download',
|
}, {
|
||||||
'os': 'macos',
|
'type': 'store',
|
||||||
'url': 'https://www.videolan.org/vlc/download-macosx.html',
|
'os': 'android',
|
||||||
},
|
'store_name': 'google-play',
|
||||||
{
|
'url': store_url('google-play', 'org.videolan.vlc')
|
||||||
'type': 'store',
|
}, {
|
||||||
'os': 'android',
|
'type': 'store',
|
||||||
'store_name': 'google-play',
|
'os': 'android',
|
||||||
'url': store_url('google-play', 'org.videolan.vlc')
|
'store_name': 'f-droid',
|
||||||
},
|
'url': store_url('f-droid', 'org.videolan.vlc')
|
||||||
{
|
}]
|
||||||
'type': 'store',
|
|
||||||
'os': 'android',
|
|
||||||
'store_name': 'f-droid',
|
|
||||||
'url': store_url('f-droid', 'org.videolan.vlc')
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': _('kodi'),
|
'name':
|
||||||
'platforms': [
|
_('kodi'),
|
||||||
{
|
'platforms': [{
|
||||||
'type': 'package',
|
'type': 'package',
|
||||||
'os': 'gnu-linux',
|
'os': 'gnu-linux',
|
||||||
'format': 'deb',
|
'format': 'deb',
|
||||||
'name': 'kodi',
|
'name': 'kodi',
|
||||||
},
|
}, {
|
||||||
{
|
'type': 'package',
|
||||||
'type': 'package',
|
'os': 'gnu-linux',
|
||||||
'os': 'gnu-linux',
|
'format': 'rpm',
|
||||||
'format': 'rpm',
|
'name': 'kodi',
|
||||||
'name': 'kodi',
|
}, {
|
||||||
},
|
'type': 'download',
|
||||||
{
|
'os': 'windows',
|
||||||
'type': 'download',
|
'url': 'http://kodi.tv/download/',
|
||||||
'os': 'windows',
|
}, {
|
||||||
'url': 'http://kodi.tv/download/',
|
'type': 'download',
|
||||||
},
|
'os': 'macos',
|
||||||
{
|
'url': 'http://kodi.tv/download/',
|
||||||
'type': 'download',
|
}, {
|
||||||
'os': 'macos',
|
'type': 'store',
|
||||||
'url': 'http://kodi.tv/download/',
|
'os': 'android',
|
||||||
},
|
'store_name': 'google-play',
|
||||||
{
|
'url': store_url('google-play', 'org.xbmc.kodi')
|
||||||
'type': 'store',
|
}, {
|
||||||
'os': 'android',
|
'type': 'store',
|
||||||
'store_name': 'google-play',
|
'os': 'android',
|
||||||
'url': store_url('google-play', 'org.xbmc.kodi')
|
'store_name': 'f-droid',
|
||||||
},
|
'url': store_url('f-droid', 'org.xbmc.kodi')
|
||||||
{
|
}]
|
||||||
'type': 'store',
|
|
||||||
'os': 'android',
|
|
||||||
'store_name': 'f-droid',
|
|
||||||
'url': store_url('f-droid', 'org.xbmc.kodi')
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': _('yaacc'),
|
'name':
|
||||||
'platforms': [
|
_('yaacc'),
|
||||||
{
|
'platforms': [{
|
||||||
'type': 'store',
|
'type': 'store',
|
||||||
'os': 'android',
|
'os': 'android',
|
||||||
'store_name': 'f-droid',
|
'store_name': 'f-droid',
|
||||||
'url': store_url('f-droid', 'de.yaacc')
|
'url': store_url('f-droid', 'de.yaacc')
|
||||||
},
|
}]
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': _('totem'),
|
'name':
|
||||||
'platforms': [
|
_('totem'),
|
||||||
{
|
'platforms': [{
|
||||||
'type': 'package',
|
'type': 'package',
|
||||||
'os': 'gnu-linux',
|
'os': 'gnu-linux',
|
||||||
'format': 'deb',
|
'format': 'deb',
|
||||||
'name': 'totem',
|
'name': 'totem',
|
||||||
},
|
}, {
|
||||||
{
|
'type': 'package',
|
||||||
'type': 'package',
|
'os': 'gnu-linux',
|
||||||
'os': 'gnu-linux',
|
'format': 'rpm',
|
||||||
'format': 'rpm',
|
'name': 'totem',
|
||||||
'name': 'totem',
|
}]
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
# TODO: get all media directories from config file
|
# TODO: get all media directories from config file
|
||||||
# for now hard code default media folder.
|
# for now hard code default media folder.
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'data': {
|
'data': {
|
||||||
'files': ['/etc/minidlna.conf'],
|
'files': ['/etc/minidlna.conf'],
|
||||||
'directories': ['/var/lib/minidlna']
|
'directories': ['/var/lib/minidlna']
|
||||||
},
|
},
|
||||||
'services': ['minidlna']
|
'services': ['minidlna']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -10,12 +10,13 @@ from plinth import app as app_module
|
|||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users import add_user_to_share_group
|
from plinth.modules.users import add_user_to_share_group
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 2
|
version = 2
|
||||||
|
|
||||||
@ -56,7 +57,8 @@ class MLDonkeyApp(app_module.App):
|
|||||||
app_id=self.app_id, version=version, name=_('MLDonkey'),
|
app_id=self.app_id, version=version, name=_('MLDonkey'),
|
||||||
icon_filename='mldonkey',
|
icon_filename='mldonkey',
|
||||||
short_description=_('Peer-to-peer File Sharing'),
|
short_description=_('Peer-to-peer File Sharing'),
|
||||||
description=_description, manual_page='MLDonkey', clients=clients)
|
description=_description, manual_page='MLDonkey',
|
||||||
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-mldonkey', info.name,
|
menu_item = menu.Menu('menu-mldonkey', info.name,
|
||||||
@ -88,6 +90,10 @@ class MLDonkeyApp(app_module.App):
|
|||||||
groups=groups)
|
groups=groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-mldonkey',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -6,7 +6,6 @@ Application manifest for mldonkey.
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name': _('MLDonkey'),
|
'name': _('MLDonkey'),
|
||||||
@ -37,7 +36,7 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'config': {
|
'config': {
|
||||||
'files': [
|
'files': [
|
||||||
'/var/lib/mldonkey/bittorrent.ini', '/var/lib/mldonkey/bt_dht.ini',
|
'/var/lib/mldonkey/bittorrent.ini', '/var/lib/mldonkey/bt_dht.ini',
|
||||||
@ -55,4 +54,4 @@ backup = validate_backup({
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
'services': ['mldonkey-server']
|
'services': ['mldonkey-server']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -7,9 +7,10 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import menu
|
from plinth import menu
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -60,6 +61,10 @@ class MonkeysphereApp(app_module.App):
|
|||||||
reserved_usernames=['monkeysphere'])
|
reserved_usernames=['monkeysphere'])
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-monkeysphere',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,13 +3,11 @@
|
|||||||
Application manfiest for monkeysphere.
|
Application manfiest for monkeysphere.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {
|
||||||
|
|
||||||
backup = validate_backup({
|
|
||||||
'config': {
|
'config': {
|
||||||
'directories': ['/etc/monkeysphere/']
|
'directories': ['/etc/monkeysphere/']
|
||||||
},
|
},
|
||||||
'secrets': {
|
'secrets': {
|
||||||
'directories': ['/var/lib/monkeysphere/']
|
'directories': ['/var/lib/monkeysphere/']
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|||||||
@ -13,12 +13,13 @@ from plinth import app as app_module
|
|||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules import names
|
from plinth.modules import names
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.letsencrypt.components import LetsEncrypt
|
from plinth.modules.letsencrypt.components import LetsEncrypt
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.utils import Version
|
from plinth.utils import Version
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 2
|
version = 2
|
||||||
|
|
||||||
@ -50,7 +51,8 @@ class MumbleApp(app_module.App):
|
|||||||
info = app_module.Info(
|
info = app_module.Info(
|
||||||
app_id=self.app_id, version=version, name=_('Mumble'),
|
app_id=self.app_id, version=version, name=_('Mumble'),
|
||||||
icon_filename='mumble', short_description=_('Voice Chat'),
|
icon_filename='mumble', short_description=_('Voice Chat'),
|
||||||
description=_description, manual_page='Mumble', clients=clients,
|
description=_description, manual_page='Mumble',
|
||||||
|
clients=manifest.clients,
|
||||||
donation_url='https://wiki.mumble.info/wiki/Donate')
|
donation_url='https://wiki.mumble.info/wiki/Donate')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
@ -88,6 +90,10 @@ class MumbleApp(app_module.App):
|
|||||||
reserved_usernames=['mumble-server'])
|
reserved_usernames=['mumble-server'])
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-mumble',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name':
|
'name':
|
||||||
@ -55,9 +54,9 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'data': {
|
'data': {
|
||||||
'directories': ['/var/lib/mumble-server']
|
'directories': ['/var/lib/mumble-server']
|
||||||
},
|
},
|
||||||
'services': ['mumble-server']
|
'services': ['mumble-server']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -9,11 +9,11 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, menu
|
from plinth import cfg, menu
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.signals import domain_added, domain_removed
|
from plinth.signals import domain_added, domain_removed
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from . import components
|
from . import components, manifest
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -52,6 +52,10 @@ class NamesApp(app_module.App):
|
|||||||
'names:index', parent_url_name='system')
|
'names:index', parent_url_name='system')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-names',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
domain_added.connect(on_domain_added)
|
domain_added.connect(on_domain_added)
|
||||||
domain_removed.connect(on_domain_removed)
|
domain_removed.connect(on_domain_removed)
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,4 @@
|
|||||||
Application manifest for names.
|
Application manifest for names.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {}
|
||||||
|
|
||||||
backup = validate_backup({})
|
|
||||||
|
|||||||
@ -12,11 +12,12 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ class OpenVPNApp(app_module.App):
|
|||||||
name=_('OpenVPN'), icon_filename='openvpn',
|
name=_('OpenVPN'), icon_filename='openvpn',
|
||||||
short_description=_('Virtual Private Network'),
|
short_description=_('Virtual Private Network'),
|
||||||
description=_description, manual_page='OpenVPN',
|
description=_description, manual_page='OpenVPN',
|
||||||
clients=clients)
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-openvpn', info.name,
|
menu_item = menu.Menu('menu-openvpn', info.name,
|
||||||
@ -92,6 +93,10 @@ class OpenVPNApp(app_module.App):
|
|||||||
groups=self.groups)
|
groups=self.groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-openvpn',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
def is_enabled(self):
|
def is_enabled(self):
|
||||||
"""Return whether all the leader components are enabled.
|
"""Return whether all the leader components are enabled.
|
||||||
|
|
||||||
|
|||||||
@ -6,12 +6,11 @@ Application manifest for OpenVPN.
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
_package_id = 'de.blinkt.openvpn'
|
_package_id = 'de.blinkt.openvpn'
|
||||||
_download_url = 'https://openvpn.net/community-downloads'
|
_download_url = 'https://openvpn.net/community-downloads'
|
||||||
|
|
||||||
backup = validate_backup({'secrets': {'directories': ['/etc/openvpn/']}})
|
backup = {'secrets': {'directories': ['/etc/openvpn/']}}
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name':
|
'name':
|
||||||
|
|||||||
@ -9,11 +9,11 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, menu
|
from plinth import cfg, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.names.components import DomainType
|
from plinth.modules.names.components import DomainType
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from . import utils
|
from . import manifest, utils
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
|
||||||
|
|
||||||
version = 2
|
version = 2
|
||||||
|
|
||||||
@ -80,6 +80,10 @@ class PagekiteApp(app_module.App):
|
|||||||
daemon = Daemon('daemon-pagekite', managed_services[0])
|
daemon = Daemon('daemon-pagekite', managed_services[0])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-pagekite',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
# Register kite name with Name Services module.
|
# Register kite name with Name Services module.
|
||||||
setup_helper = globals()['setup_helper']
|
setup_helper = globals()['setup_helper']
|
||||||
if setup_helper.get_state() != 'needs-setup' and self.is_enabled():
|
if setup_helper.get_state() != 'needs-setup' and self.is_enabled():
|
||||||
|
|||||||
@ -3,11 +3,9 @@
|
|||||||
Application manifest for pagekite.
|
Application manifest for pagekite.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {
|
||||||
|
|
||||||
backup = validate_backup({
|
|
||||||
'config': {
|
'config': {
|
||||||
'directories': ['/etc/pagekite.d/']
|
'directories': ['/etc/pagekite.d/']
|
||||||
},
|
},
|
||||||
'services': ['pagekite']
|
'services': ['pagekite']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ from plinth import app as app_module
|
|||||||
from plinth import menu
|
from plinth import menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
|
||||||
from .manifest import clients
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -45,7 +45,8 @@ class PerformanceApp(app_module.App):
|
|||||||
name=_('Performance'), icon='fa-bar-chart',
|
name=_('Performance'), icon='fa-bar-chart',
|
||||||
short_description=_('System Monitoring'),
|
short_description=_('System Monitoring'),
|
||||||
description=_description,
|
description=_description,
|
||||||
manual_page='Performance', clients=clients)
|
manual_page='Performance',
|
||||||
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-performance', info.name,
|
menu_item = menu.Menu('menu-performance', info.name,
|
||||||
|
|||||||
@ -6,8 +6,9 @@ FreedomBox app for power controls.
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -32,4 +33,8 @@ class PowerApp(app_module.App):
|
|||||||
description=_description, manual_page='Power')
|
description=_description, manual_page='Power')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-power',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
# not in menu, see issue #834
|
# not in menu, see issue #834
|
||||||
|
|||||||
@ -3,6 +3,4 @@
|
|||||||
Application manifest for power.
|
Application manifest for power.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {}
|
||||||
|
|
||||||
backup = validate_backup({})
|
|
||||||
|
|||||||
@ -11,11 +11,12 @@ from plinth import app as app_module
|
|||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import diagnose_url
|
from plinth.modules.apache.components import diagnose_url
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.utils import format_lazy
|
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -82,6 +83,10 @@ class PrivoxyApp(app_module.App):
|
|||||||
reserved_usernames=['privoxy'])
|
reserved_usernames=['privoxy'])
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-privoxy',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
def diagnose(self):
|
def diagnose(self):
|
||||||
"""Run diagnostics and return the results."""
|
"""Run diagnostics and return the results."""
|
||||||
results = super().diagnose()
|
results = super().diagnose()
|
||||||
|
|||||||
@ -3,6 +3,4 @@
|
|||||||
Application manifest for privoxy.
|
Application manifest for privoxy.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {}
|
||||||
|
|
||||||
backup = validate_backup({})
|
|
||||||
|
|||||||
@ -13,12 +13,13 @@ from plinth import app as app_module
|
|||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules import names
|
from plinth.modules import names
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.letsencrypt.components import LetsEncrypt
|
from plinth.modules.letsencrypt.components import LetsEncrypt
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ class QuasselApp(app_module.App):
|
|||||||
name=_('Quassel'), icon_filename='quassel',
|
name=_('Quassel'), icon_filename='quassel',
|
||||||
short_description=_('IRC Client'),
|
short_description=_('IRC Client'),
|
||||||
description=_description, manual_page='Quassel',
|
description=_description, manual_page='Quassel',
|
||||||
clients=clients)
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-quassel', info.name,
|
menu_item = menu.Menu('menu-quassel', info.name,
|
||||||
@ -96,6 +97,10 @@ class QuasselApp(app_module.App):
|
|||||||
reserved_usernames=['quasselcore'])
|
reserved_usernames=['quasselcore'])
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-quassel',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name':
|
'name':
|
||||||
@ -45,9 +44,9 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'secrets': {
|
'secrets': {
|
||||||
'directories': ['/var/lib/quassel/']
|
'directories': ['/var/lib/quassel/']
|
||||||
},
|
},
|
||||||
'services': ['quasselcore'],
|
'services': ['quasselcore'],
|
||||||
})
|
}
|
||||||
|
|||||||
@ -12,11 +12,12 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.modules.apache.components import Uwsgi, Webserver
|
from plinth.modules.apache.components import Uwsgi, Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.utils import Version, format_lazy
|
from plinth.utils import Version, format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 2
|
version = 2
|
||||||
|
|
||||||
@ -54,7 +55,8 @@ class RadicaleApp(app_module.App):
|
|||||||
name=_('Radicale'), icon_filename='radicale',
|
name=_('Radicale'), icon_filename='radicale',
|
||||||
short_description=_('Calendar and Addressbook'),
|
short_description=_('Calendar and Addressbook'),
|
||||||
description=_description,
|
description=_description,
|
||||||
manual_page='Radicale', clients=clients)
|
manual_page='Radicale',
|
||||||
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-radicale', info.name,
|
menu_item = menu.Menu('menu-radicale', info.name,
|
||||||
@ -84,6 +86,10 @@ class RadicaleApp(app_module.App):
|
|||||||
reserved_usernames=['radicale'])
|
reserved_usernames=['radicale'])
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-radicale',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
def enable(self):
|
def enable(self):
|
||||||
"""Fix missing directories before enabling radicale."""
|
"""Fix missing directories before enabling radicale."""
|
||||||
actions.superuser_run('radicale', ['fix-paths'])
|
actions.superuser_run('radicale', ['fix-paths'])
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name':
|
'name':
|
||||||
@ -79,9 +78,9 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'data': {
|
'data': {
|
||||||
'directories': ['/var/lib/radicale/']
|
'directories': ['/var/lib/radicale/']
|
||||||
},
|
},
|
||||||
'services': ['uwsgi']
|
'services': ['uwsgi']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -9,9 +9,10 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -53,7 +54,8 @@ class RoundcubeApp(app_module.App):
|
|||||||
name=_('Roundcube'), icon_filename='roundcube',
|
name=_('Roundcube'), icon_filename='roundcube',
|
||||||
short_description=_('Email Client'),
|
short_description=_('Email Client'),
|
||||||
description=_description,
|
description=_description,
|
||||||
manual_page='Roundcube', clients=clients)
|
manual_page='Roundcube',
|
||||||
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-roundcube', info.name,
|
menu_item = menu.Menu('menu-roundcube', info.name,
|
||||||
@ -76,6 +78,10 @@ class RoundcubeApp(app_module.App):
|
|||||||
urls=['https://{host}/roundcube'])
|
urls=['https://{host}/roundcube'])
|
||||||
self.add(webserver)
|
self.add(webserver)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-roundcube',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name': _('Roundcube'),
|
'name': _('Roundcube'),
|
||||||
@ -13,4 +12,4 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({})
|
backup = {}
|
||||||
|
|||||||
@ -15,11 +15,12 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 2
|
version = 2
|
||||||
|
|
||||||
@ -60,7 +61,8 @@ class SambaApp(app_module.App):
|
|||||||
info = app_module.Info(
|
info = app_module.Info(
|
||||||
app_id=self.app_id, version=version, name=_('Samba'),
|
app_id=self.app_id, version=version, name=_('Samba'),
|
||||||
icon_filename='samba', short_description=_('Network File Storage'),
|
icon_filename='samba', short_description=_('Network File Storage'),
|
||||||
manual_page='Samba', description=_description, clients=clients,
|
manual_page='Samba', description=_description,
|
||||||
|
clients=manifest.clients,
|
||||||
donation_url='https://www.samba.org/samba/donations.html')
|
donation_url='https://www.samba.org/samba/donations.html')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
@ -96,6 +98,23 @@ class SambaApp(app_module.App):
|
|||||||
groups=groups)
|
groups=groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = SambaBackupRestore('backup-restore-samba',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
|
class SambaBackupRestore(BackupRestore):
|
||||||
|
"""Component to backup/restore Samba."""
|
||||||
|
|
||||||
|
def backup_pre(self, packet):
|
||||||
|
"""Save registry share configuration."""
|
||||||
|
actions.superuser_run('samba', ['dump-shares'])
|
||||||
|
|
||||||
|
def restore_post(self, packet):
|
||||||
|
"""Restore configuration."""
|
||||||
|
actions.superuser_run('samba', ['setup'])
|
||||||
|
actions.superuser_run('samba', ['restore-shares'])
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
@ -148,14 +167,3 @@ def get_shares():
|
|||||||
output = actions.superuser_run('samba', ['get-shares'])
|
output = actions.superuser_run('samba', ['get-shares'])
|
||||||
|
|
||||||
return json.loads(output)
|
return json.loads(output)
|
||||||
|
|
||||||
|
|
||||||
def backup_pre(packet):
|
|
||||||
"""Save registry share configuration."""
|
|
||||||
actions.superuser_run('samba', ['dump-shares'])
|
|
||||||
|
|
||||||
|
|
||||||
def restore_post(packet):
|
|
||||||
"""Restore configuration."""
|
|
||||||
actions.superuser_run('samba', ['setup'])
|
|
||||||
actions.superuser_run('samba', ['restore-shares'])
|
|
||||||
|
|||||||
@ -6,7 +6,6 @@ Application manifest for Samba.
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
SHARES_CONF_BACKUP_FILE = '/var/lib/plinth/backups-data/samba-shares-dump.conf'
|
SHARES_CONF_BACKUP_FILE = '/var/lib/plinth/backups-data/samba-shares-dump.conf'
|
||||||
|
|
||||||
@ -77,9 +76,9 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'data': {
|
'data': {
|
||||||
'files': [SHARES_CONF_BACKUP_FILE]
|
'files': [SHARES_CONF_BACKUP_FILE]
|
||||||
},
|
},
|
||||||
'services': ['smbd', 'nmbd']
|
'services': ['smbd', 'nmbd']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -11,11 +11,11 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.modules.apache.components import Uwsgi, Webserver
|
from plinth.modules.apache.components import Uwsgi, Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
from .manifest import (PUBLIC_ACCESS_SETTING_FILE, clients)
|
|
||||||
|
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
@ -47,7 +47,8 @@ class SearxApp(app_module.App):
|
|||||||
info = app_module.Info(
|
info = app_module.Info(
|
||||||
app_id=self.app_id, version=version, name=_('Searx'),
|
app_id=self.app_id, version=version, name=_('Searx'),
|
||||||
icon_filename='searx', short_description=_('Web Search'),
|
icon_filename='searx', short_description=_('Web Search'),
|
||||||
description=_description, manual_page='Searx', clients=clients,
|
description=_description, manual_page='Searx',
|
||||||
|
clients=manifest.clients,
|
||||||
donation_url='https://searx.me/static/donate.html')
|
donation_url='https://searx.me/static/donate.html')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
@ -83,6 +84,10 @@ class SearxApp(app_module.App):
|
|||||||
groups=groups)
|
groups=groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-searx',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
def set_shortcut_login_required(self, login_required):
|
def set_shortcut_login_required(self, login_required):
|
||||||
"""Change the login_required property of shortcut."""
|
"""Change the login_required property of shortcut."""
|
||||||
shortcut = self.remove('shortcut-searx')
|
shortcut = self.remove('shortcut-searx')
|
||||||
@ -122,7 +127,7 @@ def get_safe_search_setting():
|
|||||||
|
|
||||||
def is_public_access_enabled():
|
def is_public_access_enabled():
|
||||||
"""Check whether public access is enabled for Searx."""
|
"""Check whether public access is enabled for Searx."""
|
||||||
return os.path.exists(PUBLIC_ACCESS_SETTING_FILE)
|
return os.path.exists(manifest.PUBLIC_ACCESS_SETTING_FILE)
|
||||||
|
|
||||||
|
|
||||||
def enable_public_access():
|
def enable_public_access():
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name': _('Searx'),
|
'name': _('Searx'),
|
||||||
@ -15,4 +14,4 @@ clients = validate([{
|
|||||||
|
|
||||||
PUBLIC_ACCESS_SETTING_FILE = '/etc/searx/allow_public_access'
|
PUBLIC_ACCESS_SETTING_FILE = '/etc/searx/allow_public_access'
|
||||||
|
|
||||||
backup = validate_backup({'config': {'files': [PUBLIC_ACCESS_SETTING_FILE]}})
|
backup = {'config': {'files': [PUBLIC_ACCESS_SETTING_FILE]}}
|
||||||
|
|||||||
@ -13,8 +13,9 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
from plinth import actions
|
from plinth import actions
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import menu, module_loader
|
from plinth import menu, module_loader
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 6
|
version = 6
|
||||||
|
|
||||||
@ -50,6 +51,10 @@ class SecurityApp(app_module.App):
|
|||||||
'security:index', parent_url_name='system')
|
'security:index', parent_url_name='system')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-security',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install the required packages"""
|
"""Install the required packages"""
|
||||||
|
|||||||
@ -3,9 +3,4 @@
|
|||||||
Application manifest for security.
|
Application manifest for security.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {'config': {'files': ['/etc/security/access.d/50freedombox.conf']}}
|
||||||
|
|
||||||
backup = validate_backup(
|
|
||||||
{'config': {
|
|
||||||
'files': ['/etc/security/access.d/50freedombox.conf']
|
|
||||||
}})
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ from plinth import frontpage, menu
|
|||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
|
|
||||||
from .manifest import clients
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ class ShaarliApp(app_module.App):
|
|||||||
name=_('Shaarli'), icon_filename='shaarli',
|
name=_('Shaarli'), icon_filename='shaarli',
|
||||||
short_description=_('Bookmarks'),
|
short_description=_('Bookmarks'),
|
||||||
description=_description, manual_page='Shaarli',
|
description=_description, manual_page='Shaarli',
|
||||||
clients=clients)
|
clients=manifest.clients)
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-shaarli', info.name,
|
menu_item = menu.Menu('menu-shaarli', info.name,
|
||||||
|
|||||||
@ -10,10 +10,11 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
@ -76,6 +77,10 @@ class ShadowsocksApp(app_module.App):
|
|||||||
listen_ports=[(1080, 'tcp4'), (1080, 'tcp6')])
|
listen_ports=[(1080, 'tcp4'), (1080, 'tcp6')])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-shadowsocks',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,13 +3,11 @@
|
|||||||
Application manifest for shadowsocks.
|
Application manifest for shadowsocks.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {
|
||||||
|
|
||||||
backup = validate_backup({
|
|
||||||
'secrets': {
|
'secrets': {
|
||||||
'files': [
|
'files': [
|
||||||
'/var/lib/private/shadowsocks-libev/freedombox/freedombox.json'
|
'/var/lib/private/shadowsocks-libev/freedombox/freedombox.json'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'services': ['shadowsocks-libev-local@freedombox']
|
'services': ['shadowsocks-libev-local@freedombox']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -10,9 +10,10 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
from plinth import actions
|
from plinth import actions
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, menu
|
from plinth import cfg, menu
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -44,6 +45,10 @@ class SharingApp(app_module.App):
|
|||||||
parent_url_name='apps')
|
parent_url_name='apps')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-sharing',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def list_shares():
|
def list_shares():
|
||||||
"""Return a list of shares."""
|
"""Return a list of shares."""
|
||||||
|
|||||||
@ -3,9 +3,7 @@
|
|||||||
Application manifest for sharing.
|
Application manifest for sharing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {
|
||||||
|
|
||||||
backup = validate_backup({
|
|
||||||
'config': {
|
'config': {
|
||||||
'files': ['/etc/apache2/conf-available/sharing-freedombox.conf']
|
'files': ['/etc/apache2/conf-available/sharing-freedombox.conf']
|
||||||
},
|
},
|
||||||
@ -14,4 +12,4 @@ backup = validate_backup({
|
|||||||
'kind': 'config',
|
'kind': 'config',
|
||||||
'name': 'sharing-freedombox'
|
'name': 'sharing-freedombox'
|
||||||
}]
|
}]
|
||||||
})
|
}
|
||||||
|
|||||||
@ -13,8 +13,9 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import menu
|
from plinth import menu
|
||||||
from plinth.modules import storage
|
from plinth.modules import storage
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
@ -61,6 +62,18 @@ class SnapshotApp(app_module.App):
|
|||||||
'snapshot:index', parent_url_name='system')
|
'snapshot:index', parent_url_name='system')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
|
backup_restore = SnapshotBackupRestore('backup-restore-snapshot',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
|
class SnapshotBackupRestore(BackupRestore):
|
||||||
|
"""Component to backup/restore snapshot module."""
|
||||||
|
|
||||||
|
def restore_post(self, packet):
|
||||||
|
"""Run after restore."""
|
||||||
|
actions.superuser_run('snapshot', ['kill-daemon'])
|
||||||
|
|
||||||
|
|
||||||
def is_supported():
|
def is_supported():
|
||||||
"""Return whether snapshots are support on current setup."""
|
"""Return whether snapshots are support on current setup."""
|
||||||
@ -129,8 +142,3 @@ def get_configuration():
|
|||||||
'free_space':
|
'free_space':
|
||||||
output['FREE_LIMIT'],
|
output['FREE_LIMIT'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def restore_post(packet):
|
|
||||||
"""Run after restore."""
|
|
||||||
actions.superuser_run('snapshot', ['kill-daemon'])
|
|
||||||
|
|||||||
@ -3,10 +3,8 @@
|
|||||||
Application manifest for snapshot.
|
Application manifest for snapshot.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {
|
||||||
|
|
||||||
backup = validate_backup({
|
|
||||||
'config': {
|
'config': {
|
||||||
'files': ['/etc/snapper/configs/root', '/etc/default/snapper']
|
'files': ['/etc/snapper/configs/root', '/etc/default/snapper']
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|||||||
@ -13,9 +13,10 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import menu
|
from plinth import menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
|
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -60,6 +61,9 @@ class SSHApp(app_module.App):
|
|||||||
daemon = Daemon('daemon-ssh', managed_services[0])
|
daemon = Daemon('daemon-ssh', managed_services[0])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-ssh', **manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Configure the module."""
|
"""Configure the module."""
|
||||||
|
|||||||
@ -3,9 +3,7 @@
|
|||||||
Application manifest for ssh.
|
Application manifest for ssh.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {
|
||||||
|
|
||||||
backup = validate_backup({
|
|
||||||
'secrets': {
|
'secrets': {
|
||||||
'files': [
|
'files': [
|
||||||
'/etc/ssh/ssh_host_ecdsa_key', '/etc/ssh/ssh_host_ecdsa_key.pub',
|
'/etc/ssh/ssh_host_ecdsa_key', '/etc/ssh/ssh_host_ecdsa_key.pub',
|
||||||
@ -14,4 +12,4 @@ backup = validate_backup({
|
|||||||
'/etc/ssh/ssh_host_rsa_key.pub'
|
'/etc/ssh/ssh_host_rsa_key.pub'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|||||||
@ -15,10 +15,10 @@ from plinth import actions
|
|||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, glib, menu
|
from plinth import cfg, glib, menu
|
||||||
from plinth.errors import ActionError, PlinthError
|
from plinth.errors import ActionError, PlinthError
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from . import udisks2
|
from . import manifest, udisks2
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
|
||||||
|
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
@ -59,6 +59,10 @@ class StorageApp(app_module.App):
|
|||||||
'storage:index', parent_url_name='system')
|
'storage:index', parent_url_name='system')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-storage',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
# Check every hour for low disk space, every 3 minutes in debug mode
|
# Check every hour for low disk space, every 3 minutes in debug mode
|
||||||
interval = 180 if cfg.develop else 3600
|
interval = 180 if cfg.develop else 3600
|
||||||
glib.schedule(interval, warn_about_low_disk_space)
|
glib.schedule(interval, warn_about_low_disk_space)
|
||||||
|
|||||||
@ -3,6 +3,4 @@
|
|||||||
Application manifest for storage.
|
Application manifest for storage.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {}
|
||||||
|
|
||||||
backup = validate_backup({})
|
|
||||||
|
|||||||
@ -10,12 +10,13 @@ from plinth import app as app_module
|
|||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
|
||||||
from plinth.modules.users import add_user_to_share_group
|
from plinth.modules.users import add_user_to_share_group
|
||||||
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
@ -59,7 +60,8 @@ class SyncthingApp(app_module.App):
|
|||||||
name=_('Syncthing'), icon_filename='syncthing',
|
name=_('Syncthing'), icon_filename='syncthing',
|
||||||
short_description=_('File Synchronization'),
|
short_description=_('File Synchronization'),
|
||||||
description=_description,
|
description=_description,
|
||||||
manual_page='Syncthing', clients=clients,
|
manual_page='Syncthing',
|
||||||
|
clients=manifest.clients,
|
||||||
donation_url='https://syncthing.net/donations/')
|
donation_url='https://syncthing.net/donations/')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
@ -95,6 +97,10 @@ class SyncthingApp(app_module.App):
|
|||||||
[SYSTEM_USER], self.groups)
|
[SYSTEM_USER], self.groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-syncthing',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
_package_id = 'com.nutomic.syncthingandroid'
|
_package_id = 'com.nutomic.syncthingandroid'
|
||||||
_download_url = 'https://syncthing.net/'
|
_download_url = 'https://syncthing.net/'
|
||||||
@ -47,9 +46,9 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'secrets': {
|
'secrets': {
|
||||||
'directories': ['/var/lib/syncthing/.config']
|
'directories': ['/var/lib/syncthing/.config']
|
||||||
},
|
},
|
||||||
'services': ['syncthing@syncthing']
|
'services': ['syncthing@syncthing']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -14,11 +14,12 @@ from plinth import app as app_module
|
|||||||
from plinth import cfg, frontpage, menu
|
from plinth import cfg, frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import Webserver, diagnose_url
|
from plinth.modules.apache.components import Webserver, diagnose_url
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
|
from . import manifest
|
||||||
from .errors import TahoeConfigurationError
|
from .errors import TahoeConfigurationError
|
||||||
from .manifest import backup # noqa, pylint: disable=unused-import
|
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -87,6 +88,10 @@ class TahoeApp(app_module.App):
|
|||||||
daemon = Daemon('daemon-tahoe', managed_services[0])
|
daemon = Daemon('daemon-tahoe', managed_services[0])
|
||||||
self.add(daemon)
|
self.add(daemon)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-tahoe',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
def is_enabled(self):
|
def is_enabled(self):
|
||||||
"""Return whether all the leader components are enabled.
|
"""Return whether all the leader components are enabled.
|
||||||
|
|
||||||
|
|||||||
@ -3,11 +3,9 @@
|
|||||||
Application manfiest for tahoe-lafs.
|
Application manfiest for tahoe-lafs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
backup = {
|
||||||
|
|
||||||
backup = validate_backup({
|
|
||||||
'secrets': {
|
'secrets': {
|
||||||
'directories': ['/var/lib/tahoe-lafs/']
|
'directories': ['/var/lib/tahoe-lafs/']
|
||||||
},
|
},
|
||||||
'services': ['tahoe-lafs']
|
'services': ['tahoe-lafs']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -13,13 +13,13 @@ from plinth import menu
|
|||||||
from plinth.daemon import (Daemon, app_is_running, diagnose_netcat,
|
from plinth.daemon import (Daemon, app_is_running, diagnose_netcat,
|
||||||
diagnose_port_listening)
|
diagnose_port_listening)
|
||||||
from plinth.modules.apache.components import diagnose_url
|
from plinth.modules.apache.components import diagnose_url
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.names.components import DomainType
|
from plinth.modules.names.components import DomainType
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
from plinth.signals import domain_added, domain_removed
|
from plinth.signals import domain_added, domain_removed
|
||||||
|
|
||||||
from . import utils
|
from . import manifest, utils
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
|
||||||
|
|
||||||
version = 5
|
version = 5
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ class TorApp(app_module.App):
|
|||||||
name=_('Tor'), icon_filename='tor',
|
name=_('Tor'), icon_filename='tor',
|
||||||
short_description=_('Anonymity Network'),
|
short_description=_('Anonymity Network'),
|
||||||
description=_description, manual_page='Tor',
|
description=_description, manual_page='Tor',
|
||||||
clients=clients,
|
clients=manifest.clients,
|
||||||
donation_url='https://donate.torproject.org/')
|
donation_url='https://donate.torproject.org/')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
@ -87,6 +87,9 @@ class TorApp(app_module.App):
|
|||||||
reserved_usernames=['debian-tor'])
|
reserved_usernames=['debian-tor'])
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-tor', **manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
# Register hidden service name with Name Services module.
|
# Register hidden service name with Name Services module.
|
||||||
setup_helper = globals()['setup_helper']
|
setup_helper = globals()['setup_helper']
|
||||||
if setup_helper.get_state() != 'needs-setup' and \
|
if setup_helper.get_state() != 'needs-setup' and \
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import store_url, validate
|
from plinth.clients import store_url, validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
_orbot_package_id = 'org.torproject.android'
|
_orbot_package_id = 'org.torproject.android'
|
||||||
_tor_browser_download_url = \
|
_tor_browser_download_url = \
|
||||||
@ -41,7 +40,7 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'config': {
|
'config': {
|
||||||
'directories': ['/etc/tor/']
|
'directories': ['/etc/tor/']
|
||||||
},
|
},
|
||||||
@ -49,4 +48,4 @@ backup = validate_backup({
|
|||||||
'directories': ['/var/lib/tor/', '/var/lib/tor-instances/']
|
'directories': ['/var/lib/tor/', '/var/lib/tor-instances/']
|
||||||
},
|
},
|
||||||
'services': ['tor@plinth']
|
'services': ['tor@plinth']
|
||||||
})
|
}
|
||||||
|
|||||||
@ -12,11 +12,12 @@ from plinth import app as app_module
|
|||||||
from plinth import frontpage, menu
|
from plinth import frontpage, menu
|
||||||
from plinth.daemon import Daemon
|
from plinth.daemon import Daemon
|
||||||
from plinth.modules.apache.components import Webserver
|
from plinth.modules.apache.components import Webserver
|
||||||
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.modules.firewall.components import Firewall
|
from plinth.modules.firewall.components import Firewall
|
||||||
from plinth.modules.users import add_user_to_share_group
|
from plinth.modules.users import add_user_to_share_group
|
||||||
from plinth.modules.users.components import UsersAndGroups
|
from plinth.modules.users.components import UsersAndGroups
|
||||||
|
|
||||||
from .manifest import backup, clients # noqa, pylint: disable=unused-import
|
from . import manifest
|
||||||
|
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
@ -52,7 +53,8 @@ class TransmissionApp(app_module.App):
|
|||||||
icon_filename='transmission',
|
icon_filename='transmission',
|
||||||
short_description=_('BitTorrent Web Client'),
|
short_description=_('BitTorrent Web Client'),
|
||||||
description=_description, manual_page='Transmission',
|
description=_description, manual_page='Transmission',
|
||||||
clients=clients, donation_url='https://transmissionbt.com/donate/')
|
clients=manifest.clients,
|
||||||
|
donation_url='https://transmissionbt.com/donate/')
|
||||||
self.add(info)
|
self.add(info)
|
||||||
|
|
||||||
menu_item = menu.Menu('menu-transmission', info.name,
|
menu_item = menu.Menu('menu-transmission', info.name,
|
||||||
@ -84,6 +86,10 @@ class TransmissionApp(app_module.App):
|
|||||||
groups=groups)
|
groups=groups)
|
||||||
self.add(users_and_groups)
|
self.add(users_and_groups)
|
||||||
|
|
||||||
|
backup_restore = BackupRestore('backup-restore-transmission',
|
||||||
|
**manifest.backup)
|
||||||
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
"""Install and configure the module."""
|
"""Install and configure the module."""
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from plinth.clients import validate
|
from plinth.clients import validate
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
|
||||||
|
|
||||||
clients = validate([{
|
clients = validate([{
|
||||||
'name': _('Transmission'),
|
'name': _('Transmission'),
|
||||||
@ -13,7 +12,7 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = {
|
||||||
'data': {
|
'data': {
|
||||||
'directories': ['/var/lib/transmission-daemon/.config']
|
'directories': ['/var/lib/transmission-daemon/.config']
|
||||||
},
|
},
|
||||||
@ -21,4 +20,4 @@ backup = validate_backup({
|
|||||||
'files': ['/etc/transmission-daemon/settings.json']
|
'files': ['/etc/transmission-daemon/settings.json']
|
||||||
},
|
},
|
||||||
'services': ['transmission-daemon']
|
'services': ['transmission-daemon']
|
||||||
})
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user