From a9528c56d9852162192eb07cb992bd5b59188154 Mon Sep 17 00:00:00 2001 From: fonfon Date: Mon, 25 Apr 2016 10:25:14 +0000 Subject: [PATCH] Service object to handle services on a system-level The Service object now offers handling services on a system level, and gathering information whether it's enabled or running. New methods: enable, disable, is_enabled, is_running; For this it needs the correct (system-level) service name. All of the methods can be overridden/customized. This changes all modules to the new Service object and deletes action scripts that are not required anymore. --- actions/avahi | 59 ---------------- actions/datetime | 60 ---------------- actions/minetest | 59 ---------------- actions/mumble | 63 ----------------- actions/openvpn | 13 ---- actions/privoxy | 12 ---- actions/quassel | 59 ---------------- actions/repro | 12 ---- actions/restore | 60 ---------------- plinth/modules/avahi/__init__.py | 27 +++----- plinth/modules/datetime/__init__.py | 27 ++++---- plinth/modules/datetime/views.py | 7 +- plinth/modules/deluge/__init__.py | 20 +++--- plinth/modules/ikiwiki/__init__.py | 9 ++- plinth/modules/minetest/__init__.py | 28 +++----- plinth/modules/mumble/__init__.py | 26 +++---- plinth/modules/openvpn/__init__.py | 14 +--- plinth/modules/openvpn/views.py | 11 +-- plinth/modules/owncloud/__init__.py | 9 ++- plinth/modules/privoxy/__init__.py | 25 +++---- plinth/modules/quassel/__init__.py | 28 +++----- plinth/modules/radicale/__init__.py | 26 ++++--- plinth/modules/repro/__init__.py | 27 +++----- plinth/modules/restore/__init__.py | 23 +++---- plinth/modules/shaarli/__init__.py | 12 +++- plinth/modules/tor/__init__.py | 4 +- plinth/modules/transmission/__init__.py | 21 +++--- plinth/modules/ttrss/__init__.py | 18 ++--- plinth/modules/xmpp/__init__.py | 21 +++--- plinth/service.py | 92 +++++++++++++++++++------ 30 files changed, 243 insertions(+), 629 deletions(-) delete mode 100755 actions/avahi delete mode 100755 actions/datetime delete mode 100755 actions/minetest delete mode 100755 actions/mumble delete mode 100755 actions/quassel delete mode 100755 actions/restore diff --git a/actions/avahi b/actions/avahi deleted file mode 100755 index 7b3657886..000000000 --- a/actions/avahi +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python3 -# -# This file is part of Plinth. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - -""" -Configuration helper for service discovery. -""" - -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 avahi-daemon service') - subparsers.add_parser('disable', help='Disable avahi-daemon service') - - return parser.parse_args() - - -def subcommand_enable(_): - """Start service.""" - action_utils.service_enable('avahi-daemon') - - -def subcommand_disable(_): - """Stop service.""" - action_utils.service_disable('avahi-daemon') - - -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() diff --git a/actions/datetime b/actions/datetime deleted file mode 100755 index fce52ef62..000000000 --- a/actions/datetime +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/python3 -# -*- mode: python -*- -# -# This file is part of Plinth. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - -""" -Configuration helper for date and time -""" - -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 NTP service') - subparsers.add_parser('disable', help='Disable NTP service') - - return parser.parse_args() - - -def subcommand_enable(_): - """Start service.""" - action_utils.service_enable('ntp') - - -def subcommand_disable(_): - """Stop service.""" - action_utils.service_disable('ntp') - - -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() diff --git a/actions/minetest b/actions/minetest deleted file mode 100755 index 67c8f2106..000000000 --- a/actions/minetest +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python3 -# -# This file is part of Plinth. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - -""" -Configuration helper for Minetest server. -""" - -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 Minetest server') - subparsers.add_parser('disable', help='Disable Minetest server') - - return parser.parse_args() - - -def subcommand_enable(_): - """Enable and start server.""" - action_utils.service_enable('minetest-server') - - -def subcommand_disable(_): - """Disable and stop server.""" - action_utils.service_disable('minetest-server') - - -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() diff --git a/actions/mumble b/actions/mumble deleted file mode 100755 index 5b80c4e33..000000000 --- a/actions/mumble +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/python3 -# -*- mode: python -*- -# -# This file is part of Plinth. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - -""" -Configuration helper for Mumble server -""" - -import argparse - -from plinth import action_utils - - -SERVICE_CONFIG = '/etc/default/mumble-server' - - -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 Mumble service') - subparsers.add_parser('disable', help='Disable Mumble service') - - return parser.parse_args() - - -def subcommand_enable(_): - """Start service.""" - action_utils.service_enable('mumble-server') - - -def subcommand_disable(_): - """Stop service.""" - action_utils.service_disable('mumble-server') - - -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() diff --git a/actions/openvpn b/actions/openvpn index 9d622494c..d62e84bf2 100755 --- a/actions/openvpn +++ b/actions/openvpn @@ -98,9 +98,6 @@ def parse_arguments(): subparsers.add_parser('is-setup', help='Return whether setup is completed') subparsers.add_parser('setup', help='Setup OpenVPN server configuration') - subparsers.add_parser('enable', help='Enable OpenVPN server') - subparsers.add_parser('disable', help='Disable OpenVPN server') - get_profile = subparsers.add_parser( 'get-profile', help='Return the OpenVPN profile of a user') get_profile.add_argument('username', help='User to get profile for') @@ -156,16 +153,6 @@ def _create_certificates(): subprocess.check_call(['/usr/share/easy-rsa/build-dh'], **COMMON_ARGS) -def subcommand_enable(_): - """Start OpenVPN service.""" - action_utils.service_enable('openvpn@freedombox') - - -def subcommand_disable(_): - """Stop OpenVPN service.""" - action_utils.service_disable('openvpn@freedombox') - - def subcommand_get_profile(arguments): """Return the profile for a user.""" username = arguments.username diff --git a/actions/privoxy b/actions/privoxy index f8ba905de..ef60b7067 100755 --- a/actions/privoxy +++ b/actions/privoxy @@ -37,8 +37,6 @@ def parse_arguments(): subparsers.add_parser('setup', help='Perform Privoxy configuration setup') - subparsers.add_parser('enable', help='Enable Privoxy service') - subparsers.add_parser('disable', help='Disable Privoxy service') return parser.parse_args() @@ -63,16 +61,6 @@ def subcommand_setup(_): action_utils.service_restart('privoxy') -def subcommand_enable(_): - """Start service.""" - action_utils.service_enable('privoxy') - - -def subcommand_disable(_): - """Stop service.""" - action_utils.service_disable('privoxy') - - def main(): """Parse arguments and perform all duties.""" arguments = parse_arguments() diff --git a/actions/quassel b/actions/quassel deleted file mode 100755 index e40ccc1ca..000000000 --- a/actions/quassel +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python3 -# -# This file is part of Plinth. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - -""" -Configuration helper for Quassel core. -""" - -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 Quassel core service') - subparsers.add_parser('disable', help='Disable Quassel core service') - - return parser.parse_args() - - -def subcommand_enable(_): - """Start service.""" - action_utils.service_enable('quasselcore') - - -def subcommand_disable(_): - """Stop service.""" - action_utils.service_disable('quasselcore') - - -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() diff --git a/actions/repro b/actions/repro index 0cd2edbe2..5c61eb75f 100755 --- a/actions/repro +++ b/actions/repro @@ -33,8 +33,6 @@ def parse_arguments(): subparsers = parser.add_subparsers(dest='subcommand', help='Sub command') subparsers.add_parser('setup', help='Configure repro') - subparsers.add_parser('enable', help='Enable repro service') - subparsers.add_parser('disable', help='Disable repro service') return parser.parse_args() @@ -61,16 +59,6 @@ def subcommand_setup(_): action_utils.webserver_enable('repro-plinth') -def subcommand_enable(_): - """Start service.""" - action_utils.service_enable('repro') - - -def subcommand_disable(_): - """Stop service.""" - action_utils.service_disable('repro') - - def main(): """Parse arguments and perform all duties.""" arguments = parse_arguments() diff --git a/actions/restore b/actions/restore deleted file mode 100755 index 73735f0b8..000000000 --- a/actions/restore +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/python3 -# -*- mode: python -*- -# -# This file is part of Plinth. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - -""" -Configuration helper for reStore. -""" - -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 reStore') - subparsers.add_parser('disable', help='Disable reStore') - - return parser.parse_args() - - -def subcommand_enable(_): - """Enable reStore.""" - action_utils.service_enable('node-restore') - - -def subcommand_disable(_): - """Disable reStore.""" - action_utils.service_disable('node-restore') - - -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() diff --git a/plinth/modules/avahi/__init__.py b/plinth/modules/avahi/__init__.py index 1e07bc9aa..bf68b952e 100644 --- a/plinth/modules/avahi/__init__.py +++ b/plinth/modules/avahi/__init__.py @@ -21,8 +21,6 @@ Plinth module for service discovery. from django.utils.translation import ugettext_lazy as _ -from plinth import actions -from plinth import action_utils from plinth import cfg from plinth import service as service_module from plinth.utils import format_lazy @@ -35,6 +33,8 @@ is_essential = True depends = ['system'] +managed_services = ['avahi-daemon'] + title = _('Service Discovery') description = [ @@ -58,7 +58,7 @@ def init(): global service # pylint: disable=W0603 service = service_module.Service( - 'avahi', title, ['mdns'], is_external=False, enabled=is_enabled()) + managed_services[0], title, ports=['mdns'], is_external=False) def setup(helper, old_version=False): @@ -68,22 +68,13 @@ def setup(helper, old_version=False): def get_status(): """Get the current settings from server.""" - return {'enabled': is_enabled(), - 'is_running': is_running()} - - -def is_enabled(): - """Return whether the module is enabled.""" - return action_utils.service_is_enabled('avahi-daemon') - - -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('avahi-daemon') + return {'enabled': service.is_enabled(), + 'is_running': service.is_running()} def enable(should_enable): """Enable/disable the module.""" - sub_command = 'enable' if should_enable else 'disable' - actions.superuser_run('avahi', [sub_command]) - service.notify_enabled(None, should_enable) + if should_enable: + service.enable() + else: + service.disable() diff --git a/plinth/modules/datetime/__init__.py b/plinth/modules/datetime/__init__.py index b82a92169..8ba219ab0 100644 --- a/plinth/modules/datetime/__init__.py +++ b/plinth/modules/datetime/__init__.py @@ -22,7 +22,6 @@ Plinth module to configure system date and time from django.utils.translation import ugettext_lazy as _ import subprocess -from plinth import action_utils from plinth import cfg from plinth import service as service_module @@ -33,6 +32,8 @@ is_essential = True depends = ['system'] +managed_services = ['ntp'] + title = _('Date & Time') description = [ @@ -50,7 +51,7 @@ def init(): global service service = service_module.Service( - 'ntp', title, is_external=False, enabled=is_enabled()) + managed_services[0], title, is_external=False) def setup(helper, old_version=None): @@ -61,27 +62,25 @@ def setup(helper, old_version=None): def get_status(): """Get the current settings from server.""" - return {'enabled': is_enabled(), - 'is_running': is_running(), + return {'enabled': service.is_enabled(), + 'is_running': service.is_running(), 'time_zone': get_current_time_zone()} +def enable(should_enable): + """Enable/disable the module.""" + if should_enable: + service.enable() + else: + service.disable() + + def get_current_time_zone(): """Get current time zone.""" time_zone = open('/etc/timezone').read().rstrip() return time_zone or 'none' -def is_enabled(): - """Return whether the module is enabled.""" - return action_utils.service_is_enabled('ntp') - - -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('ntp') - - def diagnose(): """Run diagnostics and return the results.""" results = [] diff --git a/plinth/modules/datetime/views.py b/plinth/modules/datetime/views.py index cb2ac9a90..343b96b8e 100644 --- a/plinth/modules/datetime/views.py +++ b/plinth/modules/datetime/views.py @@ -40,10 +40,11 @@ class ConfigurationView(views.ConfigurationView): modified = False if old_status['enabled'] != new_status['enabled']: - sub_command = 'enable' if new_status['enabled'] else 'disable' + if new_status['enabled']: + datetime.service.enable() + else: + datetime.service.disable() modified = True - actions.superuser_run('datetime', [sub_command]) - datetime.service.notify_enabled(None, new_status['enabled']) messages.success(self.request, _('Configuration updated')) if old_status['time_zone'] != new_status['time_zone'] and \ diff --git a/plinth/modules/deluge/__init__.py b/plinth/modules/deluge/__init__.py index 794817b36..ba313605d 100644 --- a/plinth/modules/deluge/__init__.py +++ b/plinth/modules/deluge/__init__.py @@ -20,6 +20,7 @@ Plinth module to configure a Deluge web client. """ from django.utils.translation import ugettext_lazy as _ +from functools import partial from plinth import actions from plinth import action_utils @@ -44,6 +45,8 @@ description = [ service = None +managed_services = ['deluge-web'] + def init(): """Initialize the Deluge module.""" @@ -52,8 +55,8 @@ def init(): global service service = service_module.Service( - 'deluge', title, ['http', 'https'], is_external=True, - enabled=is_enabled()) + managed_services[0], title, ports=['http', 'https'], is_external=True, + is_enabled=is_enabled, enable=_enable, disable=_disable) def setup(helper, old_version=None): @@ -65,8 +68,8 @@ def setup(helper, old_version=None): def get_status(): """Get the current settings.""" - return {'enabled': is_enabled(), - 'is_running': is_running()} + return {'enabled': service.is_enabled(), + 'is_running': service.is_running()} def is_enabled(): @@ -75,11 +78,6 @@ def is_enabled(): action_utils.service_is_enabled('deluge-web')) -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('deluge-web') - - def enable(should_enable): """Enable/disable the module.""" sub_command = 'enable' if should_enable else 'disable' @@ -97,3 +95,7 @@ def diagnose(): 'https://{host}/deluge', extra_options=['--no-check-certificate'])) return results + + +_enable = partial(enable, True) +_disable = partial(enable, False) diff --git a/plinth/modules/ikiwiki/__init__.py b/plinth/modules/ikiwiki/__init__.py index f6bc67ce3..588bb1ba3 100644 --- a/plinth/modules/ikiwiki/__init__.py +++ b/plinth/modules/ikiwiki/__init__.py @@ -20,6 +20,7 @@ Plinth module to configure ikiwiki """ from django.utils.translation import ugettext_lazy as _ +from functools import partial from plinth import actions from plinth import action_utils @@ -48,8 +49,8 @@ def init(): global service service = service_module.Service( - 'ikiwiki', title, ['http', 'https'], is_external=True, - enabled=is_enabled()) + 'ikiwiki', title, ports=['http', 'https'], is_external=True, + is_enabled=is_enabled, enable=_enable, disable=_disable) def setup(helper, old_version=None): @@ -90,3 +91,7 @@ def diagnose(): 'https://{host}/ikiwiki', extra_options=['--no-check-certificate'])) return results + + +_enable = partial(enable, True) +_disable = partial(enable, False) diff --git a/plinth/modules/minetest/__init__.py b/plinth/modules/minetest/__init__.py index a8f90b48b..d628f5b65 100644 --- a/plinth/modules/minetest/__init__.py +++ b/plinth/modules/minetest/__init__.py @@ -21,7 +21,6 @@ Plinth module for minetest. from django.utils.translation import ugettext_lazy as _ -from plinth import actions from plinth import action_utils from plinth import cfg from plinth import service as service_module @@ -45,6 +44,8 @@ description = [ service = None +managed_services = ['minetest-server'] + def init(): """Initialize the module.""" @@ -53,36 +54,27 @@ def init(): global service service = service_module.Service( - 'minetest-plinth', title, is_external=True, enabled=is_enabled()) + managed_services[0], title, is_external=True) def setup(helper, old_version=None): """Install and configure the module.""" - helper.install(['minetest-server']) + helper.install(managed_services) helper.call('post', service.notify_enabled, None, True) def get_status(): """Get the current service status.""" - return {'enabled': is_enabled(), - 'is_running': is_running()} - - -def is_enabled(): - """Return whether the service is enabled.""" - return action_utils.service_is_enabled('minetest-server') - - -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('minetest-server') + return {'enabled': service.is_enabled(), + 'is_running': service.is_running()} def enable(should_enable): """Enable/disable the module.""" - sub_command = 'enable' if should_enable else 'disable' - actions.superuser_run('minetest', [sub_command]) - service.notify_enabled(None, should_enable) + if should_enable: + service.enable() + else: + service.disable() def diagnose(): diff --git a/plinth/modules/mumble/__init__.py b/plinth/modules/mumble/__init__.py index a5ccd5902..426d2f11c 100644 --- a/plinth/modules/mumble/__init__.py +++ b/plinth/modules/mumble/__init__.py @@ -21,7 +21,6 @@ Plinth module to configure Mumble server from django.utils.translation import ugettext_lazy as _ -from plinth import actions from plinth import action_utils from plinth import cfg from plinth import service as service_module @@ -44,6 +43,8 @@ description = [ service = None +managed_services = ['mumble-server'] + def init(): """Intialize the Mumble module.""" @@ -52,7 +53,7 @@ def init(): global service service = service_module.Service( - 'mumble-plinth', title, is_external=True, enabled=is_enabled()) + managed_services[0], title, is_external=True) def setup(helper, old_version=None): @@ -63,25 +64,16 @@ def setup(helper, old_version=None): def get_status(): """Get the current settings from server.""" - return {'enabled': is_enabled(), - 'is_running': is_running()} - - -def is_enabled(): - """Return whether the module is enabled.""" - return action_utils.service_is_enabled('mumble-server') - - -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('mumble-server') + return {'enabled': service.is_enabled(), + 'is_running': service.is_running()} def enable(should_enable): """Enable/disable the module.""" - sub_command = 'enable' if should_enable else 'disable' - actions.superuser_run('mumble', [sub_command]) - service.notify_enabled(None, should_enable) + if should_enable: + service.enable() + else: + service.disable() def diagnose(): diff --git a/plinth/modules/openvpn/__init__.py b/plinth/modules/openvpn/__init__.py index c035abb99..7e8a8e26e 100644 --- a/plinth/modules/openvpn/__init__.py +++ b/plinth/modules/openvpn/__init__.py @@ -47,6 +47,8 @@ description = [ service = None +managed_services = ['openvpn@freedombox'] + def init(): """Intialize the OpenVPN module.""" @@ -55,7 +57,7 @@ def init(): global service service = service_module.Service( - 'openvpn', title, ['openvpn'], is_external=True, enabled=is_enabled()) + managed_services[0], title, ports=['openvpn'], is_external=True) def setup(helper, old_version=None): @@ -63,16 +65,6 @@ def setup(helper, old_version=None): helper.install(['openvpn', 'easy-rsa']) -def is_enabled(): - """Return whether the module is enabled.""" - return action_utils.service_is_enabled('openvpn@freedombox') - - -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('openvpn@freedombox') - - def is_setup(): """Return whether the service is running.""" return actions.superuser_run('openvpn', ['is-setup']).strip() == 'true' diff --git a/plinth/modules/openvpn/views.py b/plinth/modules/openvpn/views.py index ea460589c..38119e992 100644 --- a/plinth/modules/openvpn/views.py +++ b/plinth/modules/openvpn/views.py @@ -99,8 +99,8 @@ def get_status(): """Get the current settings from OpenVPN server.""" status = {'is_setup': openvpn.is_setup(), 'setup_running': False, - 'enabled': openvpn.is_enabled(), - 'is_running': openvpn.is_running()} + 'enabled': openvpn.service.is_enabled(), + 'is_running': openvpn.service.is_running()} status['setup_running'] = bool(setup_process) @@ -132,9 +132,10 @@ def _apply_changes(request, old_status, new_status): modified = False if old_status['enabled'] != new_status['enabled']: - sub_command = 'enable' if new_status['enabled'] else 'disable' - actions.superuser_run('openvpn', [sub_command]) - openvpn.service.notify_enabled(None, new_status['enabled']) + if new_status['enabled']: + openvpn.service.enable() + else: + openvpn.service.disable() modified = True if modified: diff --git a/plinth/modules/owncloud/__init__.py b/plinth/modules/owncloud/__init__.py index c5a77b3f4..836e22879 100644 --- a/plinth/modules/owncloud/__init__.py +++ b/plinth/modules/owncloud/__init__.py @@ -20,6 +20,7 @@ Plinth module to configure ownCloud """ from django.utils.translation import ugettext_lazy as _ +from functools import partial from plinth import actions from plinth import action_utils @@ -57,8 +58,8 @@ def init(): global service service = service_module.Service( - 'owncloud', title, ['http', 'https'], is_external=True, - enabled=is_enabled()) + 'owncloud', title, ports=['http', 'https'], is_external=True, + is_enabled=is_enabled, enable=_enable, disable=_disable) def setup(helper, old_version=None): @@ -98,3 +99,7 @@ def diagnose(): 'https://{host}/owncloud', extra_options=['--no-check-certificate'])) return results + + +_enable = partial(enable, True) +_disable = partial(enable, False) diff --git a/plinth/modules/privoxy/__init__.py b/plinth/modules/privoxy/__init__.py index 4416d8f53..3a4e47734 100644 --- a/plinth/modules/privoxy/__init__.py +++ b/plinth/modules/privoxy/__init__.py @@ -53,6 +53,8 @@ description = [ service = None +managed_services = ['privoxy'] + def init(): """Intialize the module.""" @@ -61,7 +63,7 @@ def init(): global service service = service_module.Service( - 'privoxy', title, is_external=False, enabled=is_enabled()) + managed_services[0], title, is_external=False) def setup(helper, old_version=None): @@ -73,25 +75,16 @@ def setup(helper, old_version=None): def get_status(): """Get the current settings from server.""" - return {'enabled': is_enabled(), - 'is_running': is_running()} - - -def is_enabled(): - """Return whether the module is enabled.""" - return action_utils.service_is_enabled('privoxy') - - -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('privoxy') + return {'enabled': service.is_enabled(), + 'is_running': service.is_running()} def enable(should_enable): """Enable/disable the module.""" - sub_command = 'enable' if should_enable else 'disable' - actions.superuser_run('privoxy', [sub_command]) - service.notify_enabled(None, should_enable) + if should_enable: + service.enable() + else: + service.disable() def diagnose(): diff --git a/plinth/modules/quassel/__init__.py b/plinth/modules/quassel/__init__.py index cf4316c5a..d01ffcb41 100644 --- a/plinth/modules/quassel/__init__.py +++ b/plinth/modules/quassel/__init__.py @@ -21,7 +21,6 @@ Plinth module for Quassel. from django.utils.translation import ugettext_lazy as _ -from plinth import actions from plinth import action_utils from plinth import cfg from plinth import service as service_module @@ -31,8 +30,6 @@ version = 1 depends = ['apps'] -managed_services = ['quasselcore'] - title = _('IRC Client (Quassel)') description = [ @@ -54,6 +51,8 @@ description = [ service = None +managed_services = ['quasselcore'] + def init(): """Initialize the quassel module.""" @@ -62,7 +61,7 @@ def init(): global service service = service_module.Service( - 'quassel-plinth', title, is_external=True, enabled=is_enabled()) + managed_services[0], title, description=description, is_external=True) def setup(helper, old_version=None): @@ -73,25 +72,16 @@ def setup(helper, old_version=None): def get_status(): """Get the current service status.""" - return {'enabled': is_enabled(), - 'is_running': is_running()} - - -def is_enabled(): - """Return whether the service is enabled.""" - return action_utils.service_is_enabled('quasselcore') - - -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('quasselcore') + return {'enabled': service.is_enabled(), + 'is_running': service.is_running()} def enable(should_enable): """Enable/disable the module.""" - sub_command = 'enable' if should_enable else 'disable' - actions.superuser_run('quassel', [sub_command]) - service.notify_enabled(None, should_enable) + if should_enable: + service.enable() + else: + service.disable() def diagnose(): diff --git a/plinth/modules/radicale/__init__.py b/plinth/modules/radicale/__init__.py index b421ce174..6f595eff3 100644 --- a/plinth/modules/radicale/__init__.py +++ b/plinth/modules/radicale/__init__.py @@ -19,6 +19,8 @@ Plinth module for radicale. """ +from functools import partial + from django.utils.translation import ugettext_lazy as _ from plinth import actions @@ -46,6 +48,8 @@ description = [ service = None +managed_services = ['radicale'] + def init(): """Initialize the radicale module.""" @@ -54,8 +58,8 @@ def init(): global service service = service_module.Service( - 'radicale', title, ['http', 'https'], is_external=True, - enabled=is_enabled()) + managed_services[0], title, ports=['http', 'https'], is_external=True, + enable=_enable, disable=_disable) def setup(helper, old_version=None): @@ -67,18 +71,8 @@ def setup(helper, old_version=None): def get_status(): """Get the current service status.""" - return {'enabled': is_enabled(), - 'is_running': is_running()} - - -def is_enabled(): - """Return whether the service is enabled.""" - return action_utils.service_is_enabled('radicale') - - -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('radicale') + return {'enabled': service.is_enabled(), + 'is_running': service.is_running()} def enable(should_enable): @@ -98,3 +92,7 @@ def diagnose(): 'https://{host}/radicale', extra_options=['--no-check-certificate'])) return results + + +_enable = partial(enable, True) +_disable = partial(enable, False) diff --git a/plinth/modules/repro/__init__.py b/plinth/modules/repro/__init__.py index 586923be8..2ce9faa73 100644 --- a/plinth/modules/repro/__init__.py +++ b/plinth/modules/repro/__init__.py @@ -55,6 +55,8 @@ description = [ service = None +managed_services = ['repro'] + def init(): """Initialize the repro module.""" @@ -63,8 +65,8 @@ def init(): global service service = service_module.Service( - 'repro', title, ['sip-plinth', 'sip-tls-plinth'], is_external=True, - enabled=is_enabled()) + managed_services[0], title, ports=['sip-plinth', 'sip-tls-plinth'], + is_external=True) def setup(helper, old_version=None): @@ -76,25 +78,16 @@ def setup(helper, old_version=None): def get_status(): """Get the current service status.""" - return {'enabled': is_enabled(), - 'is_running': is_running()} - - -def is_enabled(): - """Return whether the service is enabled.""" - return action_utils.service_is_enabled('repro') - - -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('repro') + return {'enabled': service.is_enabled(), + 'is_running': service.is_running()} def enable(should_enable): """Enable/disable the module.""" - sub_command = 'enable' if should_enable else 'disable' - actions.superuser_run('repro', [sub_command]) - service.notify_enabled(None, should_enable) + if should_enable: + service.enable() + else: + service.disable() def diagnose(): diff --git a/plinth/modules/restore/__init__.py b/plinth/modules/restore/__init__.py index 532cabd0a..0ec2a20b3 100644 --- a/plinth/modules/restore/__init__.py +++ b/plinth/modules/restore/__init__.py @@ -21,8 +21,7 @@ Plinth module to configure reStore. from django.utils.translation import ugettext_lazy as _ -from plinth import actions -from plinth import action_utils, cfg +from plinth import cfg from plinth import service as service_module from plinth.utils import format_lazy @@ -48,6 +47,8 @@ description = [ service = None +managed_services = ['node-restore'] + def init(): """Initialize the reStore module.""" @@ -56,8 +57,8 @@ def init(): global service service = service_module.Service( - 'node-restore', title, ['http', 'https'], is_external=False, - enabled=is_enabled()) + managed_services[0], title, ports=['http', 'https'], is_external=False, + description=description) def setup(helper, old_version=None): @@ -67,16 +68,12 @@ def setup(helper, old_version=None): def get_status(): """Get the current settings.""" - return {'enabled': is_enabled()} - - -def is_enabled(): - """Return whether the module is enabled.""" - return action_utils.service_is_enabled('node-restore') + return {'enabled': service.is_enabled()} def enable(should_enable): """Enable/disable the module.""" - sub_command = 'enable' if should_enable else 'disable' - actions.superuser_run('restore', [sub_command]) - service.notify_enabled(None, should_enable) + if should_enable: + service.enable() + else: + service.disable() diff --git a/plinth/modules/shaarli/__init__.py b/plinth/modules/shaarli/__init__.py index bbb35cc1e..febc84776 100644 --- a/plinth/modules/shaarli/__init__.py +++ b/plinth/modules/shaarli/__init__.py @@ -19,6 +19,8 @@ Plinth module to configure Shaarli. """ +from functools import partial + from django.utils.translation import ugettext_lazy as _ from plinth import actions @@ -52,8 +54,8 @@ def init(): global service service = service_module.Service( - 'shaarli', title, ['http', 'https'], is_external=True, - enabled=is_enabled()) + 'shaarli', title, ports=['http', 'https'], is_external=True, + is_enabled=is_enabled, enable=_enable, disable=_disable) def setup(helper, old_version=None): @@ -64,7 +66,7 @@ def setup(helper, old_version=None): def get_status(): """Get the current settings.""" - return {'enabled': is_enabled()} + return {'enabled': service.is_enabled()} def is_enabled(): @@ -77,3 +79,7 @@ def enable(should_enable): sub_command = 'enable' if should_enable else 'disable' actions.superuser_run('shaarli', [sub_command]) service.notify_enabled(None, should_enable) + + +_enable = partial(enable, True) +_disable = partial(enable, False) diff --git a/plinth/modules/tor/__init__.py b/plinth/modules/tor/__init__.py index 0149e4a6a..71bef6a0b 100644 --- a/plinth/modules/tor/__init__.py +++ b/plinth/modules/tor/__init__.py @@ -64,13 +64,13 @@ def init(): global socks_service socks_service = service_module.Service( 'tor-socks', _('Tor Anonymity Network'), - is_external=False, enabled=is_enabled()) + is_external=False, is_enabled=is_enabled, is_running=is_running) global bridge_service bridge_service = service_module.Service( 'tor-bridge', _('Tor Bridge Relay'), ports=['tor-orport', 'tor-obfs3', 'tor-obfs4'], - is_external=True, enabled=is_enabled()) + is_external=True, is_enabled=is_enabled, is_running=is_running) # Register hidden service name with Name Services module. hs_info = get_hs() diff --git a/plinth/modules/transmission/__init__.py b/plinth/modules/transmission/__init__.py index 497016421..255063f21 100644 --- a/plinth/modules/transmission/__init__.py +++ b/plinth/modules/transmission/__init__.py @@ -20,6 +20,7 @@ Plinth module to configure Transmission server """ from django.utils.translation import ugettext_lazy as _ +from functools import partial import json import socket @@ -33,8 +34,6 @@ version = 1 depends = ['apps'] -managed_services = ['transmission-daemon'] - title = _('BitTorrent (Transmission)') description = [ @@ -45,6 +44,8 @@ description = [ service = None +managed_services = ['transmission-daemon'] + TRANSMISSION_CONFIG = '/etc/transmission-daemon/settings.json' @@ -55,8 +56,9 @@ def init(): global service service = service_module.Service( - 'transmission', title, ['http', 'https'], is_external=True, - enabled=is_enabled()) + managed_services[0], title, ports=['http', 'https'], is_external=True, + is_enabled=is_enabled, enable=_enable, disable=_disable, + description=description) def setup(helper, old_version=None): @@ -79,7 +81,7 @@ def get_status(): status = {key.translate(str.maketrans({'-': '_'})): value for key, value in status.items()} status['enabled'] = is_enabled() - status['is_running'] = is_running() + status['is_running'] = service.is_running() status['hostname'] = socket.gethostname() return status @@ -91,11 +93,6 @@ def is_enabled(): action_utils.webserver_is_enabled('transmission-plinth')) -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('transmission-daemon') - - def enable(should_enable): """Enable/disable the module.""" sub_command = 'enable' if should_enable else 'disable' @@ -114,3 +111,7 @@ def diagnose(): extra_options=['--no-check-certificate'])) return results + + +_enable = partial(enable, True) +_disable = partial(enable, False) diff --git a/plinth/modules/ttrss/__init__.py b/plinth/modules/ttrss/__init__.py index 9cb4a6f0c..42d240e5d 100644 --- a/plinth/modules/ttrss/__init__.py +++ b/plinth/modules/ttrss/__init__.py @@ -20,6 +20,7 @@ Plinth module to configure Tiny Tiny RSS. """ from django.utils.translation import ugettext_lazy as _ +from functools import partial from plinth import actions from plinth import action_utils @@ -44,6 +45,8 @@ description = [ service = None +managed_services = ['tt-rss'] + def init(): """Intialize the module.""" @@ -52,8 +55,8 @@ def init(): global service service = service_module.Service( - 'tt-rss', title, ['http', 'https'], is_external=True, - enabled=is_enabled()) + managed_services[0], title, ports=['http', 'https'], is_external=True, + is_enabled=is_enabled, enable=_enable, disable=_disable) def setup(helper, old_version=None): @@ -67,7 +70,7 @@ def setup(helper, old_version=None): def get_status(): """Get the current settings.""" return {'enabled': is_enabled(), - 'is_running': is_running()} + 'is_running': service.is_running()} def is_enabled(): @@ -76,11 +79,6 @@ def is_enabled(): action_utils.webserver_is_enabled('tt-rss-plinth')) -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('tt-rss') - - def enable(should_enable): """Enable/disable the module.""" sub_command = 'enable' if should_enable else 'disable' @@ -96,3 +94,7 @@ def diagnose(): 'https://{host}/tt-rss', extra_options=['--no-check-certificate'])) return results + + +_enable = partial(enable, True) +_disable = partial(enable, False) diff --git a/plinth/modules/xmpp/__init__.py b/plinth/modules/xmpp/__init__.py index d823530bd..8602b7146 100644 --- a/plinth/modules/xmpp/__init__.py +++ b/plinth/modules/xmpp/__init__.py @@ -20,6 +20,7 @@ Plinth module to configure XMPP server """ from django.utils.translation import ugettext_lazy as _ +from functools import partial import logging import socket @@ -51,6 +52,8 @@ service = None logger = logging.getLogger(__name__) +managed_services = ['ejabberd'] + def init(): """Initialize the XMPP module""" @@ -59,8 +62,9 @@ def init(): global service service = service_module.Service( - 'xmpp', title, ['xmpp-client', 'xmpp-server', 'xmpp-bosh'], - is_external=True, enabled=is_enabled()) + 'ejabberd', title, ports=['xmpp-client', 'xmpp-server', 'xmpp-bosh'], + is_external=True, is_enabled=is_enabled, enable=_enable, + disable=_disable) pre_hostname_change.connect(on_pre_hostname_change) post_hostname_change.connect(on_post_hostname_change) @@ -81,8 +85,8 @@ def setup(helper, old_version=None): def get_status(): """Get the current settings.""" - return {'enabled': is_enabled(), - 'is_running': is_running(), + return {'enabled': service.is_enabled(), + 'is_running': service.is_running(), 'domainname': get_domainname()} @@ -92,11 +96,6 @@ def is_enabled(): action_utils.webserver_is_enabled('jwchat-plinth')) -def is_running(): - """Return whether the service is running.""" - return action_utils.service_is_running('ejabberd') - - def get_domainname(): """Return the domainname""" fqdn = socket.getfqdn() @@ -164,3 +163,7 @@ def diagnose(): results.extend(action_utils.diagnose_url_on_all('http://{host}/jwchat')) return results + + +_enable = partial(enable, True) +_disable = partial(enable, False) diff --git a/plinth/service.py b/plinth/service.py index 3a087ca32..1f2dc379a 100644 --- a/plinth/service.py +++ b/plinth/service.py @@ -20,9 +20,10 @@ Framework for working with servers and their services. """ import collections + from django.utils.translation import ugettext_lazy as _ -from plinth import cfg +from plinth import action_utils, actions, cfg from plinth.signals import service_enabled from plinth.utils import format_lazy @@ -34,48 +35,95 @@ class Service(object): Representation of an application service provided by the machine containing information such as current status and ports required for operation. + + - service_id: unique service name. If possible this should be the name of + the service on operating system level (as in /etc/init.d/). + - name: service name as to be displayed in the GUI + - description (optional): list of paragraphs that describe the service + - is_enabled (optional): Boolean, or a Function returning Boolean + - enable (optional): Function + - disable (optional): Function + - is_running (optional): Boolean, or a Function returning Boolean + """ - def __init__(self, service_id, name, ports=None, is_external=False, - enabled=True): - if not ports: + def __init__(self, service_id, name, ports=None, description=None, + is_external=False, is_enabled=None, enable=None, disable=None, + is_running=None): + if ports is None: ports = [service_id] + if is_enabled is None: + is_enabled = self._default_is_enabled + self.service_id = service_id self.name = name + self.description = description self.ports = ports self.is_external = is_external - self._enabled = enabled + self._is_enabled = is_enabled + self._enable = enable + self._disable = disable + self._is_running = is_running # Maintain a complete list of services + assert(service_id not in services) services[service_id] = self + def enable(self): + if self._enable is None: + actions.superuser_run('service', ['enable', self.service_id]) + else: + self._call_or_return(self._enable) + self.notify_enabled(None, True) + + def disable(self): + if self._disable is None: + actions.superuser_run('service', ['disable', self.service_id]) + else: + self._call_or_return(self._disable) + self.notify_enabled(None, False) + def is_enabled(self): """Return whether the service is enabled.""" + # TODO: we could cache the service state if we only use this service + # interface to change service status. + return self._call_or_return(self._is_enabled) - if isinstance(self._enabled, collections.Callable): - return self._enabled() - - return self._enabled + def is_running(self): + if self._is_running is None: + return action_utils.service_is_running(self.service_id) + else: + return self._call_or_return(self._is_running) def notify_enabled(self, sender, enabled): """Notify observers about change in state of service.""" - - if not isinstance(self._enabled, collections.Callable): - self._enabled = enabled - service_enabled.send_robust(sender=sender, service_id=self.service_id, enabled=enabled) + def _call_or_return(self, obj): + """Calls obj if it's callable, returns it if it's Boolean.""" + if isinstance(obj, collections.Callable): + return obj() + elif type(obj) is bool: + return obj + else: + message = 'obj is expected to be callable or a boolean.' + raise ValueError(message) + + def _default_is_enabled(self): + """Returns is_enabled relying on a correct service_id""" + return action_utils.service_is_enabled(self.service_id) + def init(): """Register some misc. services that don't fit elsewhere.""" - Service('http', _('Web Server'), ['http'], is_external=True, enabled=True) - Service('https', _('Web Server over Secure Socket Layer'), ['https'], - is_external=True, enabled=True) - Service('ssh', _('Secure Shell (SSH) Server'), ['ssh'], is_external=True, - enabled=True) - Service('plinth', - format_lazy(_('{box_name} Web Interface (Plinth)'), - box_name=_(cfg.box_name)), - ['https'], is_external=True, enabled=True) + Service('http', _('Web Server'), ports=['http'], is_external=True, + is_enabled=True) + Service('https', _('Web Server over Secure Socket Layer'), ports=['https'], + is_external=True, is_enabled=True) + Service('ssh', _('Secure Shell (SSH) Server'), ports=['ssh'], + is_external=True, is_enabled=True) + Service('plinth', format_lazy(_('{box_name} Web Interface (Plinth)'), + box_name=_(cfg.box_name)), + ports=['https'], is_external=True, is_enabled=True)