Introduce daemon component to handle systemd units

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2019-06-05 14:27:09 -07:00 committed by James Valleroy
parent 46f162d093
commit e4351b6b97
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
171 changed files with 1073 additions and 1993 deletions

View File

@ -27,8 +27,6 @@ import os
from OpenSSL import crypto
from plinth import action_utils
KEYS_DIRECTORY = '/etc/apache2/auth-pubtkt-keys'

View File

@ -37,8 +37,6 @@ def parse_arguments():
help='Setup Cockpit configuration')
subparser.add_argument('domain_names', nargs='*',
help='Domain names to be allowed')
subparsers.add_parser('enable', help='Enable Cockpit')
subparsers.add_parser('disable', help='Disable Cockpit')
subparser = subparsers.add_parser(
'add-domain',
help='Allow a new domain to be origin for Cockpit\'s WebSocket')
@ -67,16 +65,6 @@ def subcommand_setup(arguments):
action_utils.service_restart('cockpit.socket')
def subcommand_enable(_):
"""Enable web configuration and reload."""
action_utils.service_enable('cockpit.socket')
def subcommand_disable(_):
"""Disable web configuration and reload."""
action_utils.service_disable('cockpit.socket')
def _get_origin_domains(aug):
"""Return the list of allowed origin domains."""
origins = aug.get('/files' + CONFIG_FILE + '/WebService/Origins')

View File

@ -39,8 +39,6 @@ def parse_arguments():
subparsers.add_parser('setup',
help='Post-installation operations for coquelicot')
subparsers.add_parser('enable', help='Enable coquelicot')
subparsers.add_parser('disable', help='Disable coquelicot')
subparsers.add_parser(
'set-upload-password',
@ -70,16 +68,6 @@ def subcommand_setup(_):
action_utils.service_restart('coquelicot')
def subcommand_enable(_):
"""Enable web configuration and reload."""
action_utils.service_enable('coquelicot')
def subcommand_disable(_):
"""Disable web configuration and reload."""
action_utils.service_disable('coquelicot')
def subcommand_set_upload_password(arguments):
"""Set a new upload password for Coquelicot."""
upload_password = ''.join(sys.stdin)

View File

@ -52,25 +52,13 @@ def parse_arguments():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('enable', help='Enable deluge-web site')
subparsers.add_parser('disable', help='Disable deluge-web site')
subparsers.add_parser('setup', help='Setup deluge')
subparsers.required = True
return parser.parse_args()
def subcommand_enable(_):
"""Enable deluge-web site and start deluge-web."""
setup()
action_utils.service_enable('deluge-web')
def subcommand_disable(_):
"""Disable deluge-web site and stop deluge-web."""
action_utils.service_disable('deluge-web')
def setup():
def subcommand_setup(_):
"""Perform initial setup for deluge-web."""
if not os.path.isfile(SYSTEMD_SERVICE_PATH):
with open(SYSTEMD_SERVICE_PATH, 'w') as file_handle:

View File

@ -38,8 +38,6 @@ def parse_arguments():
'pre-install',
help='Preseed debconf values before packages are installed.')
subparsers.add_parser('enable', help='Enable diaspora* web server')
subparsers.add_parser('disable', help='Disable diaspora* web server')
subparsers.add_parser('enable-user-registrations', help='Allow users to' \
'sign up to this diaspora* pod without an invitation.')
subparsers.add_parser('disable-user-registrations', help='Allow only, ' \
@ -148,16 +146,6 @@ def subcommand_pre_install(_):
subprocess.check_output(['debconf-set-selections'], input=preset)
def subcommand_enable(_):
"""Enable web configuration and reload."""
action_utils.service_enable('diaspora')
def subcommand_disable(_):
"""Disable web configuration and reload."""
action_utils.service_disable('diaspora')
def main():
"""Parse arguments and perform all duties."""
arguments = parse_arguments()

View File

@ -58,9 +58,6 @@ def parse_arguments():
# Setup ejabberd configuration
subparsers.add_parser('setup', help='Setup ejabberd configuration')
subparsers.add_parser('enable', help='Enable XMPP service')
subparsers.add_parser('disable', help='Disable XMPP service')
# Prepare ejabberd for hostname change
pre_hostname_change = subparsers.add_parser(
'pre-change-hostname', help='Prepare ejabberd for nodename change')
@ -162,16 +159,6 @@ def upgrade_config():
ruamel.yaml.round_trip_dump(conf, file_handle)
def subcommand_enable(_):
"""Enable XMPP service"""
action_utils.service_enable('ejabberd')
def subcommand_disable(_):
"""Disable XMPP service"""
action_utils.service_disable('ejabberd')
def subcommand_pre_change_hostname(arguments):
"""Prepare ejabberd for hostname change"""
if not shutil.which('ejabberdctl'):

View File

@ -22,7 +22,7 @@ Wrapper to list and handle system services
import argparse
import os
from plinth import action_utils, cfg
from plinth import cfg
from plinth.modules.i2p.helpers import RouterEditor, TunnelEditor
cfg.read()
@ -36,9 +36,6 @@ def parse_arguments():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('enable', help='enable i2p service')
subparsers.add_parser('disable', help='disable i2p service')
subparser = subparsers.add_parser(
'add-favorite', help='Add an eepsite to the list of favorites')
subparser.add_argument('--name', help='Name of the entry', required=True)
@ -58,16 +55,6 @@ def parse_arguments():
return parser.parse_args()
def subcommand_enable(_):
"""Enable I2P service."""
action_utils.service_enable('i2p')
def subcommand_disable(_):
"""Disable I2P service."""
action_utils.service_disable('i2p')
def subcommand_set_tunnel_property(arguments):
"""Modify the configuration file for a certain tunnel."""
editor = TunnelEditor()

View File

@ -25,8 +25,6 @@ import shutil
import subprocess
import sys
from plinth import action_utils
SETUP_WIKI = '/etc/ikiwiki/plinth-wiki.setup'
SETUP_BLOG = '/etc/ikiwiki/plinth-blog.setup'
SITE_PATH = '/var/www/ikiwiki'

View File

@ -39,8 +39,6 @@ def parse_arguments():
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('post-install', help='Perform post install steps')
subparsers.add_parser('enable', help='Enable matrix-synapse service')
subparsers.add_parser('disable', help='Disable matrix-synapse service')
help_pubreg = 'Enable/Disable/Status public user registration.'
pubreg = subparsers.add_parser('public-registration', help=help_pubreg)
pubreg.add_argument('command', choices=('enable', 'disable', 'status'),
@ -166,17 +164,6 @@ def subcommand_setup(arguments):
action_utils.dpkg_reconfigure('matrix-synapse',
{'server-name': domain_name})
_update_tls_certificate()
subcommand_enable(arguments)
def subcommand_enable(_):
"""Enable service."""
action_utils.service_enable('matrix-synapse')
def subcommand_disable(_):
"""Disable service."""
action_utils.service_disable('matrix-synapse')
def subcommand_public_registration(argument):

View File

@ -25,7 +25,6 @@ import subprocess
import sys
import tempfile
from plinth import action_utils
from plinth.utils import generate_password, grep
MAINTENANCE_SCRIPTS_DIR = "/usr/share/mediawiki/maintenance"
@ -38,8 +37,6 @@ def parse_arguments():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('enable', help='Enable MediaWiki')
subparsers.add_parser('disable', help='Disable MediaWiki')
subparsers.add_parser('setup', help='Setup MediaWiki')
subparsers.add_parser('update', help='Run MediaWiki update script')
@ -116,16 +113,6 @@ def subcommand_update(_):
subprocess.check_call(['php', update_script])
def subcommand_enable(_):
"""Enable web configuration and reload."""
action_utils.service_enable('mediawiki-jobrunner')
def subcommand_disable(_):
"""Disable web configuration and reload."""
action_utils.service_disable('mediawiki-jobrunner')
def subcommand_public_registrations(arguments):
"""Enable or Disable public registrations for MediaWiki."""

View File

@ -23,8 +23,6 @@ Configuration helper for mldonkey.
import argparse
import subprocess
from plinth import action_utils
def parse_arguments():
"""Return parsed command line arguments as dictionary."""
@ -32,8 +30,6 @@ def parse_arguments():
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('pre-install', help='Perform pre-install operations')
subparsers.add_parser('enable', help='Enable mldonkey')
subparsers.add_parser('disable', help='Disable mldonkey')
subparsers.required = True
return parser.parse_args()
@ -46,16 +42,6 @@ def subcommand_pre_install(_):
], input=b'mldonkey-server mldonkey-server/launch_at_startup boolean true')
def subcommand_enable(_):
"""Enable web configuration and reload."""
action_utils.service_enable('mldonkey-server')
def subcommand_disable(_):
"""Disable web configuration and reload."""
action_utils.service_disable('mldonkey-server')
def main():
"""Parse arguments and perform all duties."""
arguments = parse_arguments()

View File

@ -44,8 +44,8 @@ def parse_arguments():
subparsers.add_parser('setup', help='Setup Radicale configuration')
subparsers.add_parser('migrate', help='Migrate config to radicale 2.x')
subparsers.add_parser('enable', help='Enable Radicale service')
subparsers.add_parser('disable', help='Disable Radicale service')
subparsers.add_parser('fix-collections',
help='Ensure collections path exists')
configure = subparsers.add_parser('configure',
help='Configure various options')
configure.add_argument('--rights_type',
@ -77,8 +77,6 @@ def subcommand_setup(_):
aug.save()
subcommand_enable(None)
def subcommand_migrate(_):
"""Migrate from radicale 1.x to 2.x."""
@ -121,23 +119,11 @@ def subcommand_configure(arguments):
action_utils.service_try_restart('radicale')
def subcommand_enable(_):
"""Start service."""
if radicale.get_package_version() >= radicale.VERSION_2:
# Workaround for bug in radicale's uwsgi script (#919339)
if not os.path.exists(COLLECTIONS_PATH):
os.makedirs(COLLECTIONS_PATH)
action_utils.service_disable('radicale')
else:
action_utils.service_enable('radicale')
action_utils.service_restart('radicale')
def subcommand_disable(_):
"""Stop service."""
package_version = radicale.get_package_version()
if package_version and package_version < radicale.VERSION_2:
action_utils.service_disable('radicale')
def subcommand_fix_collections(_):
"""Fix collections path to work around a bug."""
# Workaround for bug in radicale's uwsgi script (#919339)
if not os.path.exists(COLLECTIONS_PATH):
os.makedirs(COLLECTIONS_PATH)
def load_augeas():

View File

@ -26,22 +26,19 @@ import pwd
import shutil
import subprocess
from plinth import action_utils
def parse_arguments():
"""Return parsed command line arguments as dictionary."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('enable', help='Enable Syncthing')
subparsers.add_parser('disable', help='Disable Syncthing')
subparsers.add_parser('setup', help='Setup Syncthing')
subparsers.required = True
return parser.parse_args()
def setup():
def subcommand_setup(_):
"""Actions to be performed before installing Syncthing"""
data_dir = '/var/lib/syncthing'
@ -66,17 +63,6 @@ def setup():
shutil.chown(data_dir, user='syncthing', group='syncthing')
def subcommand_enable(_):
"""Enable web configuration and reload."""
setup()
action_utils.service_enable('syncthing@syncthing')
def subcommand_disable(_):
"""Disable web configuration and reload."""
action_utils.service_disable('syncthing@syncthing')
def main():
"""Parse arguments and perform all duties."""
arguments = parse_arguments()

View File

@ -30,7 +30,6 @@ import subprocess
import augeas
import ruamel.yaml
from plinth import action_utils
from plinth.modules.tahoe import (introducer_furl_file, introducer_name,
introducers_file, storage_node_name,
tahoe_home)
@ -47,8 +46,6 @@ def parse_arguments():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('enable', help='Enable Tahoe-LAFS')
subparsers.add_parser('disable', help='Disable Tahoe-LAFS')
setup = subparsers.add_parser('setup',
help='Set domain name for Tahoe-LAFS')
setup.add_argument('--domain-name',
@ -224,16 +221,6 @@ def subcommand_get_local_introducer(_):
print(json.dumps((introducer_name, furl)))
def subcommand_enable(_):
"""Enable web configuration and reload."""
action_utils.service_enable('tahoe-lafs')
def subcommand_disable(_):
"""Disable web configuration and reload."""
action_utils.service_disable('tahoe-lafs')
def restart_storage_node():
"""Called after exiting context of editing introducers file."""
try:

View File

@ -20,19 +20,19 @@ Configuration helper for the Tor service
"""
import argparse
import augeas
import codecs
import json
import os
import re
import socket
import time
import subprocess
import time
import augeas
from plinth import action_utils
from plinth.modules.tor.utils import get_real_apt_uri_path, iter_apt_uris, \
get_augeas, is_running, is_enabled, \
APT_TOR_PREFIX
from plinth.modules.tor.utils import (APT_TOR_PREFIX, get_augeas,
get_real_apt_uri_path, iter_apt_uris)
SERVICE_FILE = '/etc/firewalld/services/tor-{0}.xml'
TOR_CONFIG = '/files/etc/tor/instances/plinth/torrc'
@ -212,7 +212,8 @@ def subcommand_configure(arguments):
def subcommand_restart(_):
"""Restart Tor."""
if is_enabled() and is_running():
if (action_utils.service_is_enabled('tor@plinth', strict_check=True)
and action_utils.service_is_running('tor@plinth')):
action_utils.service_restart('tor@plinth')
aug = augeas_load()
@ -527,8 +528,8 @@ def _update_ports():
def augeas_load():
"""Initialize Augeas."""
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
augeas.Augeas.NO_MODL_AUTOLOAD)
aug = augeas.Augeas(
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
aug.set('/augeas/load/Tor/lens', 'Tor.lns')
aug.set('/augeas/load/Tor/incl[last() + 1]',
'/etc/tor/instances/plinth/torrc')

View File

@ -15,7 +15,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Configuration helper for Transmission daemon.
"""
@ -26,7 +25,6 @@ import sys
from plinth import action_utils
TRANSMISSION_CONFIG = '/etc/transmission-daemon/settings.json'
@ -35,10 +33,8 @@ def parse_arguments():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('enable', help='Enable Transmission service')
subparsers.add_parser('disable', help='Disable Transmission service')
subparsers.add_parser(
'get-configuration', help='Return the current configuration')
subparsers.add_parser('get-configuration',
help='Return the current configuration')
subparsers.add_parser(
'merge-configuration',
help='Merge JSON configuration from stdin with existing')
@ -47,16 +43,6 @@ def parse_arguments():
return parser.parse_args()
def subcommand_enable(_):
"""Start Transmission service."""
action_utils.service_enable('transmission-daemon')
def subcommand_disable(_):
"""Stop Transmission service."""
action_utils.service_disable('transmission-daemon')
def subcommand_get_configuration(_):
"""Return the current configuration in JSON format."""
configuration = open(TRANSMISSION_CONFIG, 'r').read()

View File

@ -40,8 +40,7 @@ def parse_arguments():
subparsers.add_parser('pre-setup', help='Perform pre-setup operations')
subparsers.add_parser('setup', help='Setup Tiny Tiny RSS configuration')
subparsers.add_parser('enable', help='Enable Tiny Tiny RSS site')
subparsers.add_parser('disable', help='Disable Tiny Tiny RSS site')
subparsers.add_parser('enable-api-access', help='Enable Tiny Tiny RSS API')
subparsers.add_parser('dump-database', help='Dump database to file')
subparsers.add_parser('restore-database',
help='Restore database from file')
@ -84,7 +83,7 @@ def subcommand_setup(_):
action_utils.service_restart('tt-rss')
def enable_api_access():
def subcommand_enable_api_access(_):
"""Enable API access so that tt-rss can be accessed through mobile app."""
import psycopg2 # Only available post installation
@ -111,17 +110,6 @@ def enable_api_access():
connection.close()
def subcommand_enable(_):
"""Enable web configuration and reload."""
action_utils.service_enable('tt-rss')
enable_api_access()
def subcommand_disable(_):
"""Disable web configuration and reload."""
action_utils.service_disable('tt-rss')
def subcommand_dump_database(_):
"""Dump database to file."""
os.makedirs(os.path.dirname(DB_BACKUP_FILE), exist_ok=True)

View File

@ -1,60 +0,0 @@
#!/usr/bin/python3
# -*- mode: python -*-
#
# This file is part of FreedomBox.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Configuration helper for udiskie.
"""
import argparse
from plinth import action_utils
def parse_arguments():
"""Return parsed command line arguments as dictionary."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('enable', help='Enable udiskie')
subparsers.add_parser('disable', help='Disable udiskie')
subparsers.required = True
return parser.parse_args()
def subcommand_enable(_):
"""Enable web configuration and reload."""
action_utils.service_enable('freedombox-udiskie')
def subcommand_disable(_):
"""Disable web configuration and reload."""
action_utils.service_disable('freedombox-udiskie')
def main():
"""Parse arguments and perform all duties."""
arguments = parse_arguments()
subcommand = arguments.subcommand.replace('-', '_')
subcommand_method = globals()['subcommand_' + subcommand]
subcommand_method(arguments)
if __name__ == '__main__':
main()

View File

@ -24,7 +24,7 @@ import sys
import axes
from . import (__version__, cfg, dbus, frontpage, log, menu, module_loader,
service, setup, web_framework, web_server)
setup, web_framework, web_server)
axes.default_app_config = "plinth.axes_app_config.AppConfig"
precedence_commandline_arguments = ["server_dir", "develop"]

View File

@ -64,6 +64,12 @@ class App:
"""Return a component given the component's ID."""
return self.components[component_id]
def get_components_of_type(self, component_type):
"""Return all components of a given type."""
for component in self.components.values():
if isinstance(component, component_type):
yield component
def enable(self):
"""Enable all the components of the app."""
for component in self.components.values():
@ -75,7 +81,10 @@ class App:
component.disable()
def is_enabled(self):
"""Return whether all the leader components are enabled."""
"""Return whether all the leader components are enabled.
Return True when there are no leader components.
"""
return all((component.is_enabled()
for component in self.components.values()
if component.is_leader))

65
plinth/daemon.py Normal file
View File

@ -0,0 +1,65 @@
#
# This file is part of FreedomBox.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Component for managing a background daemon or any systemd unit.
"""
from plinth import action_utils, actions, app
class Daemon(app.LeaderComponent):
"""Component to manage a background daemon or any systemd unit."""
def __init__(self, component_id, unit, strict_check=False):
"""Initialize a new daemon component.
'component_id' must be a unique string across all apps and components
of a app. Conventionally starts with 'daemon-'.
'unit' must the name of systemd unit that this component should manage.
"""
super().__init__(component_id)
self.unit = unit
self.strict_check = strict_check
def is_enabled(self):
"""Return if the daemon/unit is enabled."""
return action_utils.service_is_enabled(self.unit,
strict_check=self.strict_check)
def enable(self):
"""Run operations to enable the daemon/unit."""
actions.superuser_run('service', ['enable', self.unit])
def disable(self):
"""Run operations to disable the daemon/unit."""
actions.superuser_run('service', ['disable', self.unit])
def is_running(self):
"""Return whether the daemon/unit is running."""
return action_utils.service_is_running(self.unit)
def app_is_running(app_):
"""Return whether all the daemons in the app are running."""
for component in app_.components.values():
if hasattr(component, 'is_running') and not component.is_running():
return False
return True

View File

@ -26,15 +26,15 @@ from django.conf import settings
from django.forms import CheckboxInput
from django.utils import translation
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import get_language_info
from django.utils.translation import ugettext_lazy as _
import plinth
from plinth import utils
class ServiceForm(forms.Form):
"""Generic configuration form for a service."""
class AppForm(forms.Form):
"""Generic configuration form for an app."""
is_enabled = forms.BooleanField(
label=_('Enable application'), required=False)

View File

@ -23,10 +23,10 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth import app as app_module
from plinth import cfg, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy
from plinth.views import ServiceView
from plinth.views import AppView
from .manifest import backup
@ -53,8 +53,6 @@ description = [
'hostile local network.'), box_name=_(cfg.box_name))
]
service = None
manual_page = 'ServiceDiscovery'
app = None
@ -76,6 +74,9 @@ class AvahiApp(app_module.App):
is_external=False)
self.add(firewall)
daemon = Daemon('daemon-avahi', managed_services[0])
self.add(daemon)
def init():
"""Intialize the service discovery module."""
@ -83,9 +84,6 @@ def init():
app = AvahiApp()
app.set_enabled(True)
global service # pylint: disable=W0603
service = service_module.Service(managed_services[0], name)
def setup(helper, old_version=None):
"""Install and configure the module."""
@ -97,7 +95,8 @@ def setup(helper, old_version=None):
['reload', 'avahi-daemon'])
class AvahiServiceView(ServiceView):
service_id = managed_services[0]
class AvahiAppView(AppView):
app_id = 'avahi'
name = name
description = description
manual_page = manual_page

View File

@ -14,17 +14,14 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
URLs for the service discovery module.
"""
from django.conf.urls import url
from plinth.modules.avahi import AvahiServiceView
from plinth.modules.avahi import AvahiAppView
urlpatterns = [
url(r'^sys/avahi/$', AvahiServiceView.as_view(),
name='index'),
url(r'^sys/avahi/$', AvahiAppView.as_view(), name='index'),
]

View File

@ -41,8 +41,6 @@ description = [
_('Backups allows creating and managing backup archives.'),
]
service = None
manual_page = 'Backups'
MANIFESTS_FOLDER = '/var/lib/plinth/backups-manifests/'
@ -74,9 +72,8 @@ def init():
global app
app = BackupsApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)

View File

@ -1,4 +1,4 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -1,4 +1,4 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -1,4 +1,4 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -25,7 +25,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import cfg, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy
@ -37,8 +37,6 @@ name = _('BIND')
short_description = _('Domain Name Server')
service = None
managed_services = ['bind9']
managed_packages = ['bind9']
@ -104,26 +102,23 @@ class BindApp(app_module.App):
is_external=False)
self.add(firewall)
daemon = Daemon('daemon-bind', managed_services[0])
self.add(daemon)
def init():
"""Intialize the BIND module."""
global app
app = BindApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name)
app.set_enabled(True) # XXX: Perform better check
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
global service
if service is None:
service = service_module.Service(managed_services[0], name,
enable=enable, disable=disable)
helper.call('post', actions.superuser_run, 'bind', ['setup'])
helper.call('post', app.enable)
@ -133,18 +128,6 @@ def force_upgrade(helper, _packages):
helper.install(managed_packages, force_configuration='old')
def enable():
"""Enable the module."""
actions.superuser_run('service', ['enable', managed_services[0]])
app.enable()
def disable():
"""Disable the module."""
actions.superuser_run('service', ['disable', managed_services[0]])
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

View File

@ -22,7 +22,7 @@ from django import forms
from django.core.validators import validate_ipv46_address
from django.utils.translation import ugettext_lazy as _
from plinth.forms import ServiceForm
from plinth.forms import AppForm
def validate_ips(ips):
@ -31,7 +31,7 @@ def validate_ips(ips):
validate_ipv46_address(ip_addr)
class BindForm(ServiceForm):
class BindForm(AppForm):
"""BIND configuration form"""
forwarders = forms.CharField(
label=_('Forwarders'), required=False, validators=[validate_ips],

View File

@ -20,6 +20,8 @@ URLs for the BIND module.
from django.conf.urls import url
from plinth.modules.bind.views import BindServiceView
from plinth.modules.bind.views import BindAppView
urlpatterns = [url(r'^sys/bind/$', BindServiceView.as_view(), name='index'), ]
urlpatterns = [
url(r'^sys/bind/$', BindAppView.as_view(), name='index'),
]

View File

@ -22,16 +22,17 @@ from django.contrib import messages
from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth.views import ServiceView
from plinth.views import AppView
from . import description, get_config, managed_services, port_forwarding_info
from . import description, get_config, name, port_forwarding_info
from .forms import BindForm
class BindServiceView(ServiceView): # pylint: disable=too-many-ancestors
class BindAppView(AppView): # pylint: disable=too-many-ancestors
"""A specialized view for configuring Bind."""
service_id = managed_services[0]
diagnostics_module_name = "bind"
app_id = 'bind'
diagnostics_module_name = 'bind'
name = name
description = description
show_status_block = True
form_class = BindForm

View File

@ -24,7 +24,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import cfg, frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules import names
from plinth.modules.apache.components import Webserver
from plinth.modules.firewall.components import Firewall
@ -58,8 +58,6 @@ description = [
users_url=reverse_lazy('users:index')),
]
service = None
manual_page = 'Cockpit'
app = None
@ -91,21 +89,18 @@ class CockpitApp(app_module.App):
webserver = Webserver('webserver-cockpit', 'cockpit-freedombox')
self.add(webserver)
daemon = Daemon('daemon-cockpit', managed_services[0])
self.add(daemon)
def init():
"""Intialize the module."""
global app
app = CockpitApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name,
is_enabled=is_enabled, enable=enable,
disable=disable)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
domain_added.connect(on_domain_added)
domain_removed.connect(on_domain_removed)
@ -120,32 +115,9 @@ def setup(helper, old_version=None):
for domain in domains_of_a_type
]
helper.call('post', actions.superuser_run, 'cockpit', ['setup'] + domains)
global service
if service is None:
service = service_module.Service(managed_services[0], name,
is_enabled=is_enabled, enable=enable,
disable=disable)
helper.call('post', app.enable)
def is_enabled():
"""Return whether the module is enabled."""
return (app.is_enabled()
and action_utils.service_is_running('cockpit.socket'))
def enable():
"""Enable the module."""
actions.superuser_run('cockpit', ['enable'])
app.enable()
def disable():
"""Disable the module."""
actions.superuser_run('cockpit', ['disable'])
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

View File

@ -20,17 +20,15 @@ URLs for Cockpit module.
from django.conf.urls import url
from plinth.views import ServiceView
from plinth.modules import cockpit
from plinth.views import AppView
urlpatterns = [
url(r'^sys/cockpit/$',
ServiceView.as_view(
service_id=cockpit.managed_services[0],
diagnostics_module_name='cockpit',
description=cockpit.description,
show_status_block=True,
clients=cockpit.clients,
manual_page=cockpit.manual_page),
name='index'),
url(
r'^sys/cockpit/$',
AppView.as_view(app_id='cockpit', name=cockpit.name,
diagnostics_module_name='cockpit',
description=cockpit.description,
show_status_block=True, clients=cockpit.clients,
manual_page=cockpit.manual_page), name='index'),
]

View File

@ -23,7 +23,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.apache.components import Webserver
from plinth.modules.firewall.components import Firewall
@ -51,8 +51,6 @@ description = [
'The default upload password is "test".')
]
service = None
manual_page = 'Coquelicot'
app = None
@ -84,58 +82,27 @@ class CoquelicotApp(app_module.App):
webserver = Webserver('webserver-coquelicot', 'coquelicot-freedombox')
self.add(webserver)
daemon = Daemon('daemon-coquelicot', managed_services[0])
self.add(daemon)
def init():
"""Intialize the module."""
global app
app = CoquelicotApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(
managed_services[0], name, is_enabled=is_enabled, enable=enable,
disable=disable, is_running=is_running)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
helper.call('post', actions.superuser_run, 'coquelicot', ['setup'])
helper.call('post', actions.superuser_run, 'coquelicot', ['enable'])
global service
if service is None:
service = service_module.Service(
managed_services[0], name, is_enabled=is_enabled, enable=enable,
disable=disable, is_running=is_running)
helper.call('post', app.enable)
def is_running():
"""Return whether the service is running."""
return action_utils.service_is_running('coquelicot')
def is_enabled():
"""Return whether the module is enabled."""
return (action_utils.service_is_enabled('coquelicot') and app.is_enabled())
def enable():
"""Enable the module."""
actions.superuser_run('coquelicot', ['enable'])
app.enable()
def disable():
"""Disable the module."""
actions.superuser_run('coquelicot', ['disable'])
app.disable()
def get_current_max_file_size():
"""Get the current value of maximum file size."""
size = actions.superuser_run('coquelicot', ['get-max-file-size'])

View File

@ -21,10 +21,10 @@ Plinth form for configuring Coquelicot.
from django import forms
from django.utils.translation import ugettext_lazy as _
from plinth.forms import ServiceForm
from plinth.forms import AppForm
class CoquelicotForm(ServiceForm): # pylint: disable=W0232
class CoquelicotForm(AppForm): # pylint: disable=W0232
"""Coquelicot configuration form."""
upload_password = forms.CharField(
label=_('Upload Password'),

View File

@ -20,8 +20,8 @@ URLs for the coquelicot module.
from django.conf.urls import url
from .views import CoquelicotServiceView
from .views import CoquelicotAppView
urlpatterns = [
url(r'^apps/coquelicot/$', CoquelicotServiceView.as_view(), name='index'),
url(r'^apps/coquelicot/$', CoquelicotAppView.as_view(), name='index'),
]

View File

@ -24,17 +24,19 @@ from django.utils.translation import ugettext as _
from plinth import actions, views
from plinth.errors import ActionError
from plinth.modules.coquelicot import (clients, description,
get_current_max_file_size, manual_page)
get_current_max_file_size, manual_page,
name)
from .forms import CoquelicotForm
class CoquelicotServiceView(views.ServiceView):
class CoquelicotAppView(views.AppView):
"""Serve configuration page."""
clients = clients
name = name
description = description
diagnostics_module_name = 'coquelicot'
service_id = 'coquelicot'
app_id = 'coquelicot'
form_class = CoquelicotForm
show_status_block = True
manual_page = manual_page

View File

@ -24,7 +24,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import app as app_module
from plinth import menu
from plinth import service as service_module
from plinth.daemon import Daemon
from .manifest import backup
@ -45,8 +45,6 @@ description = [
manual_page = 'DateTime'
service = None
app = None
@ -62,6 +60,9 @@ class DateTimeApp(app_module.App):
'datetime:index', parent_url_name='system')
self.add(menu_item)
daemon = Daemon('daemon-datetime', managed_services[0])
self.add(daemon)
def init():
"""Intialize the date/time module."""
@ -69,18 +70,9 @@ def init():
app = DateTimeApp()
app.set_enabled(True)
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name)
def setup(helper, old_version=None):
"""Install and configure the module."""
global service
if service is None:
service = service_module.Service(managed_services[0], name)
service.enable()
helper.call('post', app.enable)

View File

@ -14,23 +14,22 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Forms for configuring date and time
"""
from django import forms
from django.utils.translation import ugettext_lazy as _
import logging
import subprocess
from plinth.forms import ServiceForm
from django import forms
from django.utils.translation import ugettext_lazy as _
from plinth.forms import AppForm
logger = logging.getLogger(__name__)
class DateTimeForm(ServiceForm):
class DateTimeForm(AppForm):
"""Date/time configuration form."""
time_zone = forms.ChoiceField(
label=_('Time Zone'),
@ -41,8 +40,7 @@ class DateTimeForm(ServiceForm):
"""Initialize the date/time form."""
forms.Form.__init__(self, *args, **kwargs)
time_zone_options = [(zone, zone)
for zone in self.get_time_zones()]
time_zone_options = [(zone, zone) for zone in self.get_time_zones()]
# Show not-set option only when time zone is not set
current_time_zone = self.initial.get('time_zone')
if current_time_zone == 'none':

View File

@ -14,16 +14,14 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
URLs for the date and time module
"""
from django.conf.urls import url
from .views import DateTimeServiceView
from .views import DateTimeAppView
urlpatterns = [
url(r'^sys/datetime/$', DateTimeServiceView.as_view(), name='index'),
url(r'^sys/datetime/$', DateTimeAppView.as_view(), name='index'),
]

View File

@ -25,26 +25,25 @@ from django.utils.translation import ugettext as _
from plinth import actions
from plinth.modules import datetime
from plinth.views import ServiceView
from plinth.views import AppView
from .forms import DateTimeForm
logger = logging.getLogger(__name__)
class DateTimeServiceView(ServiceView):
class DateTimeAppView(AppView):
name = datetime.name
description = datetime.description
form_class = DateTimeForm
service_id = datetime.managed_services[0]
diagnostics_module_name = "datetime"
app_id = 'datetime'
diagnostics_module_name = 'datetime'
manual_page = datetime.manual_page
def get_initial(self):
return {
'is_enabled': self.service.is_enabled(),
'is_running': self.service.is_running(),
'time_zone': self.get_current_time_zone()
}
status = super().get_initial()
status['time_zone'] = self.get_current_time_zone()
return status
def get_current_time_zone(self):
"""Get current time zone."""
@ -61,9 +60,10 @@ class DateTimeServiceView(ServiceView):
actions.superuser_run('timezone-change',
[new_status['time_zone']])
except Exception as exception:
messages.error(self.request,
_('Error setting time zone: {exception}')
.format(exception=exception))
messages.error(
self.request,
_('Error setting time zone: {exception}').format(
exception=exception))
else:
messages.success(self.request, _('Time zone set'))

View File

@ -23,7 +23,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.apache.components import Webserver
from plinth.modules.firewall.components import Firewall
from plinth.modules.users import register_group
@ -32,8 +32,6 @@ from .manifest import backup, clients
version = 2
service = None
managed_services = ['deluge-web']
managed_packages = ['deluged', 'deluge-web']
@ -86,6 +84,9 @@ class DelugeApp(app_module.App):
webserver = Webserver('webserver-deluge', 'deluge-plinth')
self.add(webserver)
daemon = Daemon('daemon-deluge', managed_services[0])
self.add(daemon)
def init():
"""Initialize the Deluge module."""
@ -93,45 +94,18 @@ def init():
app = DelugeApp()
register_group(group)
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name,
is_enabled=is_enabled, enable=enable,
disable=disable)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
helper.call('post', actions.superuser_run, 'deluge', ['enable'])
global service
if service is None:
service = service_module.Service(managed_services[0], name,
is_enabled=is_enabled, enable=enable,
disable=disable)
helper.call('post', actions.superuser_run, 'deluge', ['setup'])
helper.call('post', app.enable)
def is_enabled():
"""Return whether the module is enabled."""
return (app.is_enabled() and action_utils.service_is_enabled('deluge-web'))
def enable():
"""Enable the module."""
actions.superuser_run('deluge', ['enable'])
app.enable()
def disable():
"""Disable the module."""
actions.superuser_run('deluge', ['disable'])
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

View File

@ -21,12 +21,13 @@ URLs for the Deluge module.
from django.conf.urls import url
from plinth.modules import deluge
from plinth.views import ServiceView
from plinth.views import AppView
urlpatterns = [
url(r'^apps/deluge/$',
ServiceView.as_view(
description=deluge.description, diagnostics_module_name="deluge",
clients=deluge.clients, service_id=deluge.managed_services[0],
manual_page=deluge.manual_page), name='index'),
url(
r'^apps/deluge/$',
AppView.as_view(name=deluge.name, description=deluge.description,
diagnostics_module_name='deluge',
clients=deluge.clients, app_id='deluge',
manual_page=deluge.manual_page), name='index'),
]

View File

@ -1,4 +1,4 @@
{% extends 'simple_service.html' %}
{% extends 'simple_app.html' %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -22,7 +22,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.errors import DomainNotRegisteredError
from plinth.modules.apache.components import Webserver
from plinth.modules.firewall.components import Firewall
@ -55,8 +55,6 @@ name = _('diaspora*')
short_description = _('Federated Social Network')
service = None
managed_services = ['diaspora']
managed_packages = ['diaspora']
@ -103,6 +101,9 @@ class DiasporaApp(app_module.App):
webserver = Webserver('webserver-diaspora', 'diaspora-plinth')
self.add(webserver)
daemon = Daemon('daemon-diaspora', managed_services[0])
self.add(daemon)
class Shortcut(frontpage.Shortcut):
"""Frontpage shortcut to use configured domain name for URL."""
@ -118,15 +119,9 @@ def init():
global app
app = DiasporaApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name,
is_enabled=is_enabled, enable=enable,
disable=disable)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
@ -139,31 +134,9 @@ def setup(helper, old_version=None):
def setup_domain_name(domain_name):
actions.superuser_run('diaspora', ['setup', '--domain-name', domain_name])
global service
if service is None:
service = service_module.Service(managed_services[0], name,
is_enabled=is_enabled, enable=enable,
disable=disable)
app.enable()
def is_enabled():
"""Return whether the module is enabled."""
return app.is_enabled()
def enable():
"""Enable the module."""
actions.superuser_run('diaspora', ['enable'])
app.enable()
def disable():
"""Disable the module."""
actions.superuser_run('diaspora', ['disable'])
app.disable()
def is_user_registrations_enabled():
"""Return whether user registrations are enabled"""
with open('/etc/diaspora/diaspora.yml') as f:

View File

@ -21,12 +21,10 @@ Forms for configuring diaspora*
from django import forms
from django.utils.translation import ugettext_lazy as _
from plinth.forms import ServiceForm
from plinth.forms import AppForm
class DiasporaServiceForm(ServiceForm):
class DiasporaAppForm(AppForm):
"""Service Form with additional fields for diaspora*"""
is_user_registrations_enabled = forms.BooleanField(
label=_('Enable new user registrations'),
required=False
)
label=_('Enable new user registrations'), required=False)

View File

@ -1,4 +1,4 @@
{% extends "service.html" %}
{% extends "app.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -14,18 +14,15 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
URLs for the diaspora module
"""
from django.conf.urls import url
from .views import DiasporaSetupView, DiasporaServiceView
from .views import DiasporaAppView, DiasporaSetupView
urlpatterns = [
url(r'^apps/diaspora/setup$', DiasporaSetupView.as_view(),
name='setup'),
url(r'^apps/diaspora/$', DiasporaServiceView.as_view(),
name='index')
url(r'^apps/diaspora/setup$', DiasporaSetupView.as_view(), name='setup'),
url(r'^apps/diaspora/$', DiasporaAppView.as_view(), name='index')
]

View File

@ -27,9 +27,9 @@ from django.views.generic import FormView
from plinth.forms import DomainSelectionForm
from plinth.modules import diaspora
from plinth.utils import get_domain_names
from plinth.views import ServiceView
from plinth.views import AppView
from .forms import DiasporaServiceForm
from .forms import DiasporaAppForm
class DiasporaSetupView(FormView):
@ -55,12 +55,13 @@ class DiasporaSetupView(FormView):
return context
class DiasporaServiceView(ServiceView):
class DiasporaAppView(AppView):
"""Show diaspora service page."""
form_class = DiasporaServiceForm
service_id = diaspora.managed_services[0]
form_class = DiasporaAppForm
app_id = 'diaspora'
template_name = 'diaspora-post-setup.html'
diagnostics_module_name = 'diaspora'
name = diaspora.name
def dispatch(self, request, *args, **kwargs):
if not diaspora.is_setup():
@ -75,14 +76,10 @@ class DiasporaServiceView(ServiceView):
def get_initial(self):
"""Return the status of the service to fill in the form."""
return {
'is_enabled':
self.service.is_enabled(),
'is_user_registrations_enabled':
diaspora.is_user_registrations_enabled(),
'is_running':
self.service.is_running()
}
status = super().get_initial()
status['is_user_registrations_enabled'] = \
diaspora.is_user_registrations_enabled()
return status
def form_valid(self, form):
"""Enable/disable user registrations"""

View File

@ -1,4 +1,4 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -1,4 +1,4 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -1,4 +1,4 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -39,13 +39,15 @@ EMPTYSTRING = 'none'
subsubmenu = [{
'url': reverse_lazy('dynamicdns:index'),
'text': ugettext_lazy('About')
}, {
'url': reverse_lazy('dynamicdns:configure'),
'text': ugettext_lazy('Configure')
}, {
'url': reverse_lazy('dynamicdns:statuspage'),
'text': ugettext_lazy('Status')
}]
},
{
'url': reverse_lazy('dynamicdns:configure'),
'text': ugettext_lazy('Configure')
},
{
'url': reverse_lazy('dynamicdns:statuspage'),
'text': ugettext_lazy('Status')
}]
def index(request):

View File

@ -26,7 +26,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import cfg, frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules import config
from plinth.modules.apache.components import Webserver
from plinth.modules.firewall.components import Firewall
@ -63,8 +63,6 @@ clients = clients
reserved_usernames = ['ejabberd']
service = None
manual_page = 'ejabberd'
port_forwarding_info = [
@ -106,20 +104,18 @@ class EjabberdApp(app_module.App):
webserver = Webserver('webserver-ejabberd', 'jwchat-plinth')
self.add(webserver)
daemon = Daemon('daemon-ejabberd', managed_services[0])
self.add(daemon)
def init():
"""Initialize the ejabberd module"""
global app
app = EjabberdApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service('ejabberd', name,
is_enabled=is_enabled, enable=enable,
disable=disable)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
pre_hostname_change.connect(on_pre_hostname_change)
post_hostname_change.connect(on_post_hostname_change)
@ -135,31 +131,9 @@ def setup(helper, old_version=None):
['pre-install', '--domainname', domainname])
helper.install(managed_packages)
helper.call('post', actions.superuser_run, 'ejabberd', ['setup'])
global service
if service is None:
service = service_module.Service('ejabberd', name,
is_enabled=is_enabled, enable=enable,
disable=disable)
helper.call('post', app.enable)
def is_enabled():
"""Return whether the module is enabled."""
return action_utils.service_is_enabled('ejabberd')
def enable():
"""Enable the module."""
actions.superuser_run('ejabberd', ['enable'])
app.enable()
def disable():
"""Enable the module."""
actions.superuser_run('ejabberd', ['disable'])
app.disable()
def on_pre_hostname_change(sender, old_hostname, new_hostname, **kwargs):
"""
Backup ejabberd database before hostname is changed.

View File

@ -14,27 +14,25 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Forms for configuring Ejabberd.
"""
from plinth import forms as plinthForms
from django import forms as djangoForms
from django import forms
from django.utils.translation import ugettext_lazy as _
from plinth import cfg
from plinth.forms import AppForm
from plinth.utils import format_lazy
class EjabberdForm(plinthForms.ServiceForm):
class EjabberdForm(AppForm):
"""Ejabberd configuration form."""
MAM_enabled = djangoForms.BooleanField(
label=_('Enable Message Archive Management'),
required=False,
help_text=format_lazy(_(
'If enabled, your {box_name} will store chat message histories. '
'This allows synchronization of conversations between multiple '
'clients, and reading the history of a multi-user chat room. '
'It depends on the client settings whether the histories are '
'stored as plain text or encrypted.'), box_name=_(cfg.box_name)))
MAM_enabled = forms.BooleanField(
label=_('Enable Message Archive Management'), required=False,
help_text=format_lazy(
_('If enabled, your {box_name} will store chat message histories. '
'This allows synchronization of conversations between multiple '
'clients, and reading the history of a multi-user chat room. '
'It depends on the client settings whether the histories are '
'stored as plain text or encrypted.'), box_name=_(cfg.box_name)))

View File

@ -1,4 +1,4 @@
{% extends "service.html" %}
{% extends "app.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -14,16 +14,14 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
URL for the Ejabberd module
"""
from django.conf.urls import url
from .views import EjabberdServiceView
from .views import EjabberdAppView
urlpatterns = [
url(r'^apps/ejabberd/$', EjabberdServiceView.as_view(), name='index')
url(r'^apps/ejabberd/$', EjabberdAppView.as_view(), name='index')
]

View File

@ -23,15 +23,16 @@ from django.utils.translation import ugettext as _
from plinth import actions
from plinth.modules import config, ejabberd
from plinth.views import ServiceView
from plinth.views import AppView
from .forms import EjabberdForm
class EjabberdServiceView(ServiceView):
class EjabberdAppView(AppView):
"""Show ejabberd as a service."""
service_id = ejabberd.managed_services[0]
app_id = 'ejabberd'
template_name = 'ejabberd.html'
name = ejabberd.name
description = ejabberd.description
diagnostics_module_name = 'ejabberd'
form_class = EjabberdForm
@ -64,11 +65,9 @@ class EjabberdServiceView(ServiceView):
messages.info(self.request, _('Setting unchanged'))
elif not app_same:
if new_status['is_enabled']:
self.service.enable()
messages.success(self.request, _('Application enabled'))
self.app.enable()
else:
self.service.disable()
messages.success(self.request, _('Application disabled'))
self.app.disable()
if not mam_same:
# note ejabberd action "enable" or "disable" restarts, if running
@ -81,7 +80,7 @@ class EjabberdServiceView(ServiceView):
messages.success(self.request,
_('Message Archive Management disabled'))
return super(ServiceView, self).form_valid(form)
return super().form_valid(form)
def is_MAM_enabled(self):
"""Return whether Message Archive Management (MAM) is enabled."""

View File

@ -104,3 +104,8 @@ class Firewall(app.FollowerComponent):
]
if not any(enabled_components_on_port):
firewall.remove_service(port, zone='external')
@staticmethod
def get_internal_interfaces():
"""Returns a list of interfaces in a firewall zone."""
return firewall.get_interfaces('internal')

View File

@ -1,4 +1,4 @@
{% extends "simple_service.html" %}
{% extends "simple_app.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -20,7 +20,6 @@ FreedomBox app to configure a firewall.
from django.template.response import TemplateResponse
import plinth.service as service_module
from plinth.modules import firewall
from . import components

View File

@ -23,7 +23,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.apache.components import Webserver
from plinth.modules.firewall.components import Firewall
from plinth.modules.i2p.resources import FAVORITES
@ -58,8 +58,6 @@ clients = clients
group = ('i2p', _('Manage I2P application'))
service = None
manual_page = 'I2P'
port_forwarding_info = [
@ -107,6 +105,9 @@ class I2PApp(app_module.App):
webserver = Webserver('webserver-i2p', 'i2p-freedombox')
self.add(webserver)
daemon = Daemon('daemon-i2p', managed_services[0])
self.add(daemon)
def init():
"""Intialize the module."""
@ -114,21 +115,16 @@ def init():
app = I2PApp()
register_group(group)
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(
managed_services[0], name, is_enabled=is_enabled, enable=enable,
disable=disable, is_running=is_running)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
helper.call('post', disable)
helper.call('post', app.disable)
# Add favorites to the configuration
for fav in FAVORITES:
args = [
@ -152,38 +148,9 @@ def setup(helper, old_version=None):
'set-tunnel-property', '--name', tunnel, '--property', 'interface',
'--value', '0.0.0.0'
])
helper.call('post', enable)
global service
if service is None:
service = service_module.Service(
managed_services[0], name, is_enabled=is_enabled, enable=enable,
disable=disable, is_running=is_running)
helper.call('post', app.enable)
def is_running():
"""Return whether the service is running."""
return action_utils.service_is_running('i2p')
def is_enabled():
"""Return whether the module is enabled."""
return action_utils.service_is_enabled('i2p') and app.is_enabled()
def enable():
"""Enable the module."""
actions.superuser_run('i2p', ['enable'])
app.enable()
def disable():
"""Enable the module."""
actions.superuser_run('i2p', ['disable'])
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

View File

@ -1,4 +1,4 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.
@ -26,8 +26,8 @@
{% if show_status_block %}
<h3>{% trans "Status" %}</h3>
<p class="running-status-parent">
{% with service_name=service.name %}
{% if service.is_running %}
{% with service_name=name %}
{% if is_running %}
<span class="running-status active"></span>
{% blocktrans trimmed %}
Service <em>{{ service_name }}</em> is running.
@ -45,7 +45,7 @@
{% block diagnostics %}
{% if diagnostics_module_name %}
{% include "diagnostics_button.html" with module=diagnostics_module_name enabled=service.is_enabled %}
{% include "diagnostics_button.html" with module=diagnostics_module_name enabled=is_enabled %}
{% endif %}
{% endblock %}

View File

@ -1,4 +1,22 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
{% endcomment %}
{% load i18n %}

View File

@ -23,7 +23,8 @@ from django.conf.urls import url
from plinth.modules.i2p import views
urlpatterns = [
url(r'^apps/i2p/$', views.I2PServiceView.as_view(), name='index'),
url(r'^apps/i2p/$', views.I2PAppView.as_view(), name='index'),
url(r'^apps/i2p/tunnels/?$', views.TunnelsView.as_view(), name='tunnels'),
url(r'^apps/i2p/torrents/?$', views.TorrentsView.as_view(), name='torrents'),
url(r'^apps/i2p/torrents/?$', views.TorrentsView.as_view(),
name='torrents'),
]

View File

@ -24,7 +24,7 @@ from django.utils.translation import ugettext_lazy
from django.views.generic import TemplateView
import plinth.modules.i2p as i2p
from plinth.views import ServiceView
from plinth.views import AppView
subsubmenu = [{
'url': reverse_lazy('i2p:index'),
@ -39,10 +39,11 @@ subsubmenu = [{
}]
class I2PServiceView(ServiceView):
class I2PAppView(AppView):
"""Serve configuration page."""
service_id = i2p.service_name
app_id = 'i2p'
clients = i2p.clients
name = i2p.name
description = i2p.description
diagnostics_module_name = i2p.service_name
show_status_block = True
@ -74,6 +75,7 @@ class ServiceBaseView(TemplateView):
context['clients'] = i2p.clients
context['manual_page'] = i2p.manual_page
context['subsubmenu'] = subsubmenu
context['is_enabled'] = i2p.app.is_enabled()
context['service_title'] = self.service_title
context['service_path'] = self.service_path
context['service_description'] = self.service_description

View File

@ -24,7 +24,6 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import cfg, frontpage, menu
from plinth import service as service_module
from plinth.modules.apache.components import Webserver
from plinth.modules.firewall.components import Firewall
from plinth.modules.users import register_group
@ -39,8 +38,6 @@ managed_packages = [
'libsearch-xapian-perl', 'libimage-magick-perl'
]
service = None
name = _('ikiwiki')
short_description = _('Wiki and Blog')
@ -114,43 +111,18 @@ def init():
app = IkiwikiApp()
register_group(group)
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service('ikiwiki', name,
is_enabled=is_enabled, enable=enable,
disable=disable)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
helper.call('post', actions.superuser_run, 'ikiwiki', ['setup'])
global service
if service is None:
service = service_module.Service('ikiwiki', name,
is_enabled=is_enabled, enable=enable,
disable=disable)
helper.call('post', app.enable)
def is_enabled():
"""Return whether the module is enabled."""
return app.is_enabled()
def enable():
"""Enable the module."""
app.enable()
def disable():
"""Enable the module."""
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

View File

@ -1,4 +1,4 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.
@ -26,7 +26,7 @@
{% block diagnostics %}
{% if diagnostics_module_name %}
{% include "diagnostics_button.html" with module=diagnostics_module_name enabled=service.is_enabled %}
{% include "diagnostics_button.html" with module=diagnostics_module_name enabled=is_enabled %}
{% endif %}
{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -1,4 +1,4 @@
{% extends "service-subsubmenu.html" %}
{% extends "app-subsubmenu.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -14,7 +14,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
URLs for the ikiwiki module
"""
@ -23,10 +22,8 @@ from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^apps/ikiwiki/$',
views.IkiwikiServiceView.as_view(), name='index'),
url(r'^apps/ikiwiki/$', views.IkiwikiAppView.as_view(), name='index'),
url(r'^apps/ikiwiki/manage/$', views.manage, name='manage'),
url(r'^apps/ikiwiki/(?P<name>[\w.@+-]+)/delete/$', views.delete,
name='delete'),

View File

@ -42,13 +42,14 @@ subsubmenu = [{
}]
class IkiwikiServiceView(views.ServiceView):
class IkiwikiAppView(views.AppView):
"""Serve configuration page."""
service_id = "ikiwiki"
app_id = 'ikiwiki'
name = ikiwiki.name
description = ikiwiki.description
diagnostics_module_name = "ikiwiki"
diagnostics_module_name = 'ikiwiki'
show_status_block = False
template_name = "ikiwiki_configure.html"
template_name = 'ikiwiki_configure.html'
def get_context_data(self, **kwargs):
"""Return the context data for rendering the template view."""
@ -72,7 +73,8 @@ def manage(request):
'description': ikiwiki.description,
'manual_page': ikiwiki.manual_page,
'subsubmenu': subsubmenu,
'sites': sites
'sites': sites,
'is_enabled': ikiwiki.app.is_enabled(),
})
@ -108,6 +110,7 @@ def create(request):
'form': form,
'manual_page': ikiwiki.manual_page,
'subsubmenu': subsubmenu,
'is_enabled': ikiwiki.app.is_enabled(),
})

View File

@ -24,17 +24,15 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import cfg, frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy
from plinth.views import ServiceView
from plinth.views import AppView
from .manifest import backup, clients
version = 1
service = None
managed_services = ['infinoted']
managed_packages = ['infinoted']
@ -83,24 +81,24 @@ class InfinotedApp(app_module.App):
ports=['infinoted-plinth'], is_external=True)
self.add(firewall)
daemon = Daemon('daemon-infinoted', managed_services[0])
self.add(daemon)
def init():
"""Initialize the infinoted module."""
global app
app = InfinotedApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name,
enable=enable, disable=disable)
if service.is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
class InfinotedServiceView(ServiceView):
service_id = managed_services[0]
diagnostics_module_name = "infinoted"
class InfinotedAppView(AppView):
app_id = 'infinoted'
diagnostics_module_name = 'infinoted'
name = name
description = description
clients = clients
port_forwarding_info = port_forwarding_info
@ -110,26 +108,9 @@ def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
helper.call('post', actions.superuser_run, 'infinoted', ['setup'])
global service
if service is None:
service = service_module.Service(managed_services[0], name,
enable=enable, disable=disable)
helper.call('post', app.enable)
def enable():
"""Enable the module."""
actions.superuser_run('service', ['enable', managed_services[0]])
app.enable()
def disable():
"""Disable the module."""
actions.superuser_run('service', ['disable', managed_services[0]])
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

View File

@ -14,16 +14,14 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
URLs for the infinoted module.
"""
from django.conf.urls import url
from plinth.modules.infinoted import InfinotedServiceView
from plinth.modules.infinoted import InfinotedAppView
urlpatterns = [
url(r'^apps/infinoted/$', InfinotedServiceView.as_view(), name='index'),
url(r'^apps/infinoted/$', InfinotedAppView.as_view(), name='index'),
]

View File

@ -25,7 +25,6 @@ from django.utils.translation import ugettext_lazy as _
from plinth import app as app_module
from plinth import frontpage, menu
from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from .manifest import backup, clients
@ -45,8 +44,6 @@ description = [
clients = clients
service = None
logger = logging.getLogger(__name__)
app = None
@ -79,36 +76,12 @@ def init():
global app
app = JSXCApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service('jsxc', name, is_enabled=is_enabled,
enable=enable, disable=disable)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
global service
if not service:
service = service_module.Service('jsxc', name, is_enabled=is_enabled,
enable=enable, disable=disable)
helper.call('post', app.enable)
def is_enabled():
"""Return whether the module is enabled."""
setup_helper = globals()['setup_helper']
return setup_helper.get_state() != 'needs-setup'
def enable():
app.enable()
def disable():
app.disable()

View File

@ -1,4 +1,4 @@
{% extends "service.html" %}
{% extends "app.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -20,9 +20,9 @@ URLs for the JSXC module
from django.conf.urls import url
from .views import JSXCServiceView, JsxcView
from .views import JSXCAppView, JsxcView
urlpatterns = [
url(r'^apps/jsxc/$', JSXCServiceView.as_view(), name='index'),
url(r'^apps/jsxc/$', JSXCAppView.as_view(), name='index'),
url(r'^apps/jsxc/jsxc/$', JsxcView.as_view(), name='jsxc')
]

View File

@ -18,18 +18,19 @@
Views for the JSXC module
"""
from django.views.generic import TemplateView
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView
from stronghold.decorators import public
from plinth.modules import config, jsxc
from plinth.views import ServiceView
from plinth.views import AppView
class JSXCServiceView(ServiceView):
"""Show ejabberd as a service."""
service_id = 'jsxc'
class JSXCAppView(AppView):
"""Show ejabberd as an app."""
app_id = 'jsxc'
template_name = 'jsxc.html'
name = jsxc.name
description = jsxc.description
show_status_block = False
clients = jsxc.clients

View File

@ -60,8 +60,6 @@ description = [
'Subscriber Agreement</a> before using this service.')
]
service = None
manual_page = 'LetsEncrypt'
MODULES_WITH_HOOKS = ['ejabberd', 'matrixsynapse']

View File

@ -1,4 +1,4 @@
{% extends "simple_service.html" %}
{% extends "simple_app.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -28,7 +28,7 @@ from ruamel.yaml.util import load_yaml_guess_indent
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.apache.components import Webserver
from plinth.modules.firewall.components import Firewall
@ -60,8 +60,6 @@ description = [
clients = clients
service = None
manual_page = 'MatrixSynapse'
port_forwarding_info = [('TCP', 8448)]
@ -103,31 +101,23 @@ class MatrixSynapseApp(app_module.App):
'matrix-synapse-plinth')
self.add(webserver)
daemon = Daemon('daemon-matrixsynapse', managed_services[0])
self.add(daemon)
def init():
"""Initialize the matrix-synapse module."""
global app
app = MatrixSynapseApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service('matrix-synapse', name,
is_enabled=is_enabled, enable=enable,
disable=disable)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
global service
if service is None:
service = service_module.Service('matrix-synapse', name,
is_enabled=is_enabled, enable=enable,
disable=disable)
helper.call('post', actions.superuser_run, 'matrixsynapse',
['post-install'])
helper.call('post', app.enable)
@ -138,24 +128,6 @@ def is_setup():
return os.path.exists(SERVER_NAME_PATH)
def is_enabled():
"""Return whether the module is enabled."""
return (action_utils.service_is_enabled('matrix-synapse')
and app.is_enabled())
def enable():
"""Enable the module."""
actions.superuser_run('matrixsynapse', ['enable'])
app.enable()
def disable():
"""Enable the module."""
actions.superuser_run('matrixsynapse', ['disable'])
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

View File

@ -14,21 +14,19 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Forms for the Matrix Synapse module.
"""
from django import forms
from django.utils.translation import ugettext_lazy as _
from plinth.forms import ServiceForm
from plinth.forms import AppForm
class MatrixSynapseForm(ServiceForm):
class MatrixSynapseForm(AppForm):
enable_public_registration = forms.BooleanField(
label=_('Enable Public Registration'),
required=False,
help_text=_(
label=_('Enable Public Registration'), required=False, help_text=_(
'Enabling public registration means that anyone on the Internet '
'can register a new account on your Matrix server. Disable this '
'if you only want existing users to be able to use it.'))

View File

@ -1,4 +1,4 @@
{% extends "service.html" %}
{% extends "app.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -14,17 +14,16 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
URLs for the matrix-synapse module.
"""
from django.conf.urls import url
from .views import SetupView, MatrixSynapseServiceView
from .views import MatrixSynapseAppView, SetupView
urlpatterns = [
url(r'^apps/matrixsynapse/setup/$', SetupView.as_view(), name='setup'),
url(r'^apps/matrixsynapse/$', MatrixSynapseServiceView.as_view(),
url(r'^apps/matrixsynapse/$', MatrixSynapseAppView.as_view(),
name='index'),
]

View File

@ -28,7 +28,7 @@ from plinth import actions
from plinth.forms import DomainSelectionForm
from plinth.modules import matrixsynapse
from plinth.utils import get_domain_names
from plinth.views import ServiceView
from plinth.views import AppView
from . import get_public_registration_status, has_valid_certificate
from .forms import MatrixSynapseForm
@ -59,10 +59,11 @@ class SetupView(FormView):
return context
class MatrixSynapseServiceView(ServiceView):
class MatrixSynapseAppView(AppView):
"""Show matrix-synapse service page."""
service_id = matrixsynapse.managed_services[0]
app_id = 'matrixsynapse'
template_name = 'matrix-synapse.html'
name = matrixsynapse.name
description = matrixsynapse.description
diagnostics_module_name = 'matrixsynapse'
form_class = MatrixSynapseForm
@ -107,11 +108,9 @@ class MatrixSynapseServiceView(ServiceView):
messages.info(self.request, _('Setting unchanged'))
elif not app_same:
if new_config['is_enabled']:
self.service.enable()
messages.success(self.request, _('Application enabled'))
self.app.enable()
else:
self.service.disable()
messages.success(self.request, _('Application disabled'))
self.app.disable()
if not pubreg_same:
# note action public-registration restarts, if running now
@ -126,4 +125,4 @@ class MatrixSynapseServiceView(ServiceView):
messages.success(self.request,
_('Public registration disabled'))
return super(ServiceView, self).form_valid(form)
return super().form_valid(form)

View File

@ -23,7 +23,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.apache.components import Webserver
from plinth.modules.firewall.components import Firewall
@ -33,6 +33,8 @@ version = 6
managed_packages = ['mediawiki', 'imagemagick', 'php-sqlite3']
managed_services = ['mediawiki-jobrunner']
name = _('MediaWiki')
short_description = _('Wiki')
@ -52,8 +54,6 @@ description = [
'logged in can make changes to the content.')
]
service = None
manual_page = 'MediaWiki'
clients = clients
@ -93,6 +93,9 @@ class MediaWikiApp(app_module.App):
'mediawiki-freedombox')
self.add(webserver)
daemon = Daemon('daemon-mediawiki', managed_services[0])
self.add(daemon)
class Shortcut(frontpage.Shortcut):
"""Frontpage shortcut for only logged users when in private mode."""
@ -108,14 +111,9 @@ def init():
global app
app = MediaWikiApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service('mediawiki', name,
is_enabled=is_enabled, enable=enable,
disable=disable)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
@ -123,32 +121,9 @@ def setup(helper, old_version=None):
helper.install(managed_packages)
helper.call('setup', actions.superuser_run, 'mediawiki', ['setup'])
helper.call('update', actions.superuser_run, 'mediawiki', ['update'])
helper.call('enable', actions.superuser_run, 'mediawiki', ['enable'])
global service
if service is None:
service = service_module.Service('mediawiki', name,
is_enabled=is_enabled, enable=enable,
disable=disable)
helper.call('post', app.enable)
def is_enabled():
"""Return whether the module is enabled."""
return app.is_enabled()
def enable():
"""Enable the module."""
actions.superuser_run('mediawiki', ['enable'])
app.enable()
def disable():
"""Enable the module."""
actions.superuser_run('mediawiki', ['disable'])
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

View File

@ -21,10 +21,10 @@ FreedomBox app for configuring MediaWiki.
from django import forms
from django.utils.translation import ugettext_lazy as _
from plinth.forms import ServiceForm
from plinth.forms import AppForm
class MediaWikiForm(ServiceForm): # pylint: disable=W0232
class MediaWikiForm(AppForm): # pylint: disable=W0232
"""MediaWiki configuration form."""
password = forms.CharField(
label=_('Administrator Password'), help_text=_(

View File

@ -1,4 +1,4 @@
{% extends "service.html" %}
{% extends "app.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -20,8 +20,8 @@ URLs for the mediawiki module.
from django.conf.urls import url
from .views import MediaWikiServiceView
from .views import MediaWikiAppView
urlpatterns = [
url(r'^apps/mediawiki/$', MediaWikiServiceView.as_view(), name='index'),
url(r'^apps/mediawiki/$', MediaWikiAppView.as_view(), name='index'),
]

View File

@ -26,19 +26,19 @@ from django.utils.translation import ugettext as _
from plinth import actions, views
from plinth.modules import mediawiki
from . import (is_enabled, is_private_mode_enabled,
is_public_registration_enabled)
from . import is_private_mode_enabled, is_public_registration_enabled
from .forms import MediaWikiForm
logger = logging.getLogger(__name__)
class MediaWikiServiceView(views.ServiceView):
"""Serve configuration page."""
class MediaWikiAppView(views.AppView):
"""App configuration page."""
clients = mediawiki.clients
name = mediawiki.name
description = mediawiki.description
diagnostics_module_name = 'mediawiki'
service_id = 'mediawiki'
app_id = 'mediawiki'
form_class = MediaWikiForm
manual_page = mediawiki.manual_page
show_status_block = False
@ -75,11 +75,9 @@ class MediaWikiServiceView(views.ServiceView):
messages.info(self.request, _('Setting unchanged'))
elif not app_same:
if new_config['is_enabled']:
self.service.enable()
messages.success(self.request, _('Application enabled'))
self.app.enable()
else:
self.service.disable()
messages.success(self.request, _('Application disabled'))
self.app.disable()
if not pub_reg_same:
# note action public-registration restarts, if running now

View File

@ -22,10 +22,10 @@ import augeas
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import action_utils
from plinth import app as app_module
from plinth import cfg, frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy
@ -33,8 +33,6 @@ from .manifest import backup, clients
version = 2
service = None
managed_services = ['minetest-server']
mods = [
@ -102,43 +100,26 @@ class MinetestApp(app_module.App):
ports=['minetest-plinth'], is_external=True)
self.add(firewall)
daemon = Daemon('daemon-minetest', managed_services[0])
self.add(daemon)
def init():
"""Initialize the module."""
global app
app = MinetestApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name,
enable=enable, disable=disable)
if service.is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
global service
if service is None:
service = service_module.Service(managed_services[0], name,
enable=enable, disable=disable)
helper.call('post', app.enable)
def enable():
"""Enable the module."""
actions.superuser_run('service', ['enable', managed_services[0]])
app.enable()
def disable():
"""Disable the module."""
actions.superuser_run('service', ['disable', managed_services[0]])
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

View File

@ -14,7 +14,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Forms for minetest module.
"""
@ -22,34 +21,29 @@ Forms for minetest module.
from django import forms
from django.utils.translation import ugettext_lazy as _
from plinth.forms import ServiceForm
from plinth.forms import AppForm
class MinetestForm(ServiceForm):
class MinetestForm(AppForm):
"""Minetest configuration form"""
max_players = forms.IntegerField(
label=_('Maximum number of players'),
required=True,
min_value=1,
max_value=100,
help_text=_('You can change the maximum number of players playing '
'minetest at a single instance of time.'))
label=_('Maximum number of players'), required=True, min_value=1,
max_value=100, help_text=_(
'You can change the maximum number of players playing '
'minetest at a single instance of time.'))
creative_mode = forms.BooleanField(
label=_('Enable creative mode'),
required=False,
label=_('Enable creative mode'), required=False,
help_text=_('Creative mode changes the rules of the game to make it '
'more suitable for creative gameplay, rather than '
'challenging "survival" gameplay.'))
enable_pvp = forms.BooleanField(
label=_('Enable PVP'),
required=False,
label=_('Enable PVP'), required=False,
help_text=_('Enabling Player Vs Player will allow players to damage '
'other players.'))
enable_damage = forms.BooleanField(
label=_('Enable damage'),
required=False,
label=_('Enable damage'), required=False,
help_text=_('When disabled, players cannot die or receive damage of '
'any kind.'))

View File

@ -1,4 +1,4 @@
{% extends "service.html" %}
{% extends "app.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -14,16 +14,14 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
URLs for the minetest module.
"""
from django.conf.urls import url
from plinth.modules.minetest.views import MinetestServiceView
from plinth.modules.minetest.views import MinetestAppView
urlpatterns = [
url(r'^apps/minetest/$', MinetestServiceView.as_view(), name='index'),
url(r'^apps/minetest/$', MinetestAppView.as_view(), name='index'),
]

View File

@ -23,16 +23,17 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions
from plinth.modules import minetest, names
from plinth.views import ServiceView
from plinth.views import AppView
from . import description, get_configuration, managed_services
from . import description, get_configuration
from .forms import MinetestForm
class MinetestServiceView(ServiceView): # pylint: disable=too-many-ancestors
class MinetestAppView(AppView): # pylint: disable=too-many-ancestors
"""A specialized view for configuring minetest."""
service_id = managed_services[0]
diagnostics_module_name = "minetest"
app_id = 'minetest'
diagnostics_module_name = 'minetest'
name = minetest.name
description = description
show_status_block = True
template_name = 'minetest.html'

View File

@ -23,7 +23,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import app as app_module
from plinth import cfg, frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.apache.components import Webserver
from plinth.modules.firewall.components import Firewall
from plinth.modules.users import register_group
@ -60,8 +60,6 @@ reserved_usernames = ['mldonkey']
group = ('ed2k', _('Download files using eDonkey applications'))
service = None
manual_page = 'MLDonkey'
app = None
@ -93,6 +91,9 @@ class MLDonkeyApp(app_module.App):
webserver = Webserver('webserver-mldonkey', 'mldonkey-freedombox')
self.add(webserver)
daemon = Daemon('daemon-mldonkey', managed_services[0])
self.add(daemon)
def init():
"""Initialize the MLDonkey module."""
@ -100,53 +101,18 @@ def init():
app = MLDonkeyApp()
register_group(group)
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(
managed_services[0], name, is_enabled=is_enabled, enable=enable,
disable=disable, is_running=is_running)
if is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.call('pre', actions.superuser_run, 'mldonkey', ['pre-install'])
helper.install(managed_packages)
helper.call('post', actions.superuser_run, 'mldonkey', ['enable'])
global service
if service is None:
service = service_module.Service(
managed_services[0], name, is_enabled=is_enabled, enable=enable,
disable=disable, is_running=is_running)
helper.call('post', app.enable)
def is_running():
"""Return whether the service is running."""
return action_utils.service_is_running('mldonkey-server')
def is_enabled():
"""Return whether the module is enabled."""
return (action_utils.service_is_enabled('mldonkey-server')
and app.is_enabled())
def enable():
"""Enable the module."""
actions.superuser_run('mldonkey', ['enable'])
app.enable()
def disable():
"""Disable the module."""
actions.superuser_run('mldonkey', ['disable'])
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

View File

@ -21,16 +21,15 @@ URLs for the mldonkey module.
from django.conf.urls import url
from plinth.modules import mldonkey
from plinth.views import ServiceView
from plinth.views import AppView
urlpatterns = [
url(
r'^apps/mldonkey/$',
ServiceView.as_view(service_id=mldonkey.managed_services[0],
diagnostics_module_name='mldonkey',
description=mldonkey.description,
clients=mldonkey.clients,
manual_page=mldonkey.manual_page,
show_status_block=True),
AppView.as_view(
app_id='mldonkey', name=mldonkey.name,
diagnostics_module_name='mldonkey',
description=mldonkey.description, clients=mldonkey.clients,
manual_page=mldonkey.manual_page, show_status_block=True),
name='index'),
]

View File

@ -1,4 +1,4 @@
{% extends "simple_service.html" %}
{% extends "simple_app.html" %}
{% comment %}
#
# This file is part of FreedomBox.

View File

@ -21,12 +21,12 @@ FreedomBox app to configure Mumble server.
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth import action_utils
from plinth import app as app_module
from plinth import frontpage, menu
from plinth import service as service_module
from plinth.daemon import Daemon
from plinth.modules.firewall.components import Firewall
from plinth.views import ServiceView
from plinth.views import AppView
from .manifest import backup, clients
@ -36,8 +36,6 @@ name = _('Mumble')
short_description = _('Voice Chat')
service = None
managed_services = ['mumble-server']
managed_packages = ['mumble-server']
@ -86,25 +84,24 @@ class MumbleApp(app_module.App):
is_external=True)
self.add(firewall)
daemon = Daemon('daemon-mumble', managed_services[0])
self.add(daemon)
def init():
"""Intialize the Mumble module."""
global app
app = MumbleApp()
global service
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name,
enable=enable, disable=disable)
if service.is_enabled():
app.set_enabled(True)
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
class MumbleServiceView(ServiceView):
service_id = managed_services[0]
diagnostics_module_name = "mumble"
class MumbleAppView(AppView):
app_id = 'mumble'
diagnostics_module_name = 'mumble'
name = name
description = description
clients = clients
manual_page = manual_page
@ -114,25 +111,9 @@ class MumbleServiceView(ServiceView):
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
global service
if service is None:
service = service_module.Service(managed_services[0], name,
enable=enable, disable=disable)
helper.call('post', app.enable)
def enable():
"""Enable the module."""
actions.superuser_run('service', ['enable', managed_services[0]])
app.enable()
def disable():
"""Disable the module."""
actions.superuser_run('service', ['disable', managed_services[0]])
app.disable()
def diagnose():
"""Run diagnostics and return the results."""
results = []

Some files were not shown because too many files have changed in this diff Show More