From 862d87920adf6e5249ff534741a6202791937cfc Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Thu, 23 May 2019 17:27:31 -0700 Subject: [PATCH] Introduce uwsgi component to manage uWSGI configuration Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- actions/apache | 18 +++++ actions/radicale | 6 +- actions/searx | 12 --- plinth/modules/apache/components.py | 38 +++++++++ .../modules/apache/tests/test_components.py | 79 ++++++++++++++++++- plinth/modules/radicale/__init__.py | 39 +++++++-- plinth/modules/searx/__init__.py | 9 ++- 7 files changed, 173 insertions(+), 28 deletions(-) diff --git a/actions/apache b/actions/apache index a703e1588..1e907d808 100755 --- a/actions/apache +++ b/actions/apache @@ -46,6 +46,14 @@ def parse_arguments(): subparser.add_argument('--name', help='Name of the site/config/module to disable') subparser.add_argument('--kind', choices=['site', 'config', 'module']) + subparser = subparsers.add_parser( + 'uwsgi-enable', help='Enable a site/config/module in UWSGI') + subparser.add_argument('--name', + help='Name of the site/config/module to enable') + subparser = subparsers.add_parser( + 'uwsgi-disable', help='Disable a site/config/module in UWSGI') + subparser.add_argument('--name', + help='Name of the site/config/module to disable') subparsers.required = True return parser.parse_args() @@ -177,6 +185,16 @@ def subcommand_disable(arguments): action_utils.webserver_disable(arguments.name, arguments.kind) +def subcommand_uwsgi_enable(arguments): + """Enable uWSGI configuration and reload.""" + action_utils.uwsgi_enable(arguments.name) + + +def subcommand_uwsgi_disable(arguments): + """Disable uWSGI configuration and reload.""" + action_utils.uwsgi_disable(arguments.name) + + def main(): """Parse arguments and perform all duties""" arguments = parse_arguments() diff --git a/actions/radicale b/actions/radicale index 917aa819c..0fc97e689 100755 --- a/actions/radicale +++ b/actions/radicale @@ -128,7 +128,6 @@ def subcommand_enable(_): if not os.path.exists(COLLECTIONS_PATH): os.makedirs(COLLECTIONS_PATH) action_utils.service_disable('radicale') - action_utils.uwsgi_enable('radicale') else: action_utils.service_enable('radicale') action_utils.service_restart('radicale') @@ -136,9 +135,8 @@ def subcommand_enable(_): def subcommand_disable(_): """Stop service.""" - if radicale.get_package_version() >= radicale.VERSION_2: - action_utils.uwsgi_disable('radicale') - else: + package_version = radicale.get_package_version() + if package_version and package_version < radicale.VERSION_2: action_utils.service_disable('radicale') diff --git a/actions/searx b/actions/searx index 6cd4f5bac..3d1b8045f 100755 --- a/actions/searx +++ b/actions/searx @@ -41,8 +41,6 @@ def parse_arguments(): parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(dest='subcommand', help='Sub command') - subparsers.add_parser('enable', help='Enable Searx') - subparsers.add_parser('disable', help='Disable Searx') subparsers.add_parser( 'setup', help='Perform post-installation operations for Searx') @@ -157,16 +155,6 @@ def subcommand_setup(_): action_utils.service_restart('uwsgi') -def subcommand_enable(_): - """Enable web configuration and reload.""" - action_utils.uwsgi_enable('searx') - - -def subcommand_disable(_): - """Disable web configuration and reload.""" - action_utils.uwsgi_disable('searx') - - def subcommand_enable_public_access(_): """Enable public access to the SearX application.""" open(PUBLIC_ACCESS_SETTING_FILE, 'w').close() diff --git a/plinth/modules/apache/components.py b/plinth/modules/apache/components.py index dbc6c623a..f64864640 100644 --- a/plinth/modules/apache/components.py +++ b/plinth/modules/apache/components.py @@ -58,3 +58,41 @@ class Webserver(app.LeaderComponent): actions.superuser_run( 'apache', ['disable', '--name', self.web_name, '--kind', self.kind]) + + +class Uwsgi(app.LeaderComponent): + """Component to enable/disable uWSGI configuration.""" + + def __init__(self, component_id, uwsgi_name): + """Initialize the uWSGI component. + + component_id should be a unique ID across all components of an app and + across all components. + + uwsgi_name is the primary part of the configuration file path which must + be enabled/disabled by this component. + + """ + super().__init__(component_id) + + self.uwsgi_name = uwsgi_name + + def is_enabled(self): + """Return whether the uWSGI configuration is enabled.""" + return action_utils.uwsgi_is_enabled(self.uwsgi_name) \ + and action_utils.service_is_enabled('uwsgi') + + def enable(self): + """Enable the uWSGI configuration.""" + actions.superuser_run('apache', + ['uwsgi-enable', '--name', self.uwsgi_name]) + + def disable(self): + """Disable the uWSGI configuration.""" + actions.superuser_run('apache', + ['uwsgi-disable', '--name', self.uwsgi_name]) + + def is_running(self): + """Return whether the uWSGI daemon is running with configuration.""" + return action_utils.uwsgi_is_enabled(self.uwsgi_name) \ + and action_utils.service_is_running('uwsgi') diff --git a/plinth/modules/apache/tests/test_components.py b/plinth/modules/apache/tests/test_components.py index bc75af8bc..142195e8d 100644 --- a/plinth/modules/apache/tests/test_components.py +++ b/plinth/modules/apache/tests/test_components.py @@ -22,7 +22,7 @@ from unittest.mock import call, patch import pytest -from plinth.modules.apache.components import Webserver +from plinth.modules.apache.components import Uwsgi, Webserver def test_webserver_init(): @@ -75,3 +75,80 @@ def test_webserver_disable(superuser_run): call('apache', ['disable', '--name', 'test-config', '--kind', 'module']) ]) + + +def test_uwsgi_init(): + """Test that uWSGI component can be initialized.""" + with pytest.raises(ValueError): + Uwsgi(None, None) + + uwsgi = Uwsgi('test-uwsgi', 'test-config') + assert uwsgi.component_id == 'test-uwsgi' + assert uwsgi.uwsgi_name == 'test-config' + + +@patch('plinth.action_utils.service_is_enabled') +@patch('plinth.action_utils.uwsgi_is_enabled') +def test_uwsgi_is_enabled(uwsgi_is_enabled, service_is_enabled): + """Test that checking uwsgi configuration enabled works.""" + uwsgi = Uwsgi('test-uwsgi', 'test-config') + + uwsgi_is_enabled.return_value = True + service_is_enabled.return_value = True + assert uwsgi.is_enabled() + uwsgi_is_enabled.assert_has_calls([call('test-config')]) + service_is_enabled.assert_has_calls([call('uwsgi')]) + + service_is_enabled.return_value = False + assert not uwsgi.is_enabled() + + uwsgi_is_enabled.return_value = False + assert not uwsgi.is_enabled() + + service_is_enabled.return_value = False + assert not uwsgi.is_enabled() + + +@patch('plinth.actions.superuser_run') +def test_uwsgi_enable(superuser_run): + """Test that enabling uwsgi configuration works.""" + uwsgi = Uwsgi('test-uwsgi', 'test-config') + + uwsgi.enable() + superuser_run.assert_has_calls( + [call('apache', ['uwsgi-enable', '--name', 'test-config'])]) + + +@patch('plinth.actions.superuser_run') +def test_uwsgi_disable(superuser_run): + """Test that disabling uwsgi configuration works.""" + uwsgi = Uwsgi('test-uwsgi', 'test-config') + + uwsgi.disable() + superuser_run.assert_has_calls( + [call('apache', ['uwsgi-disable', '--name', 'test-config'])]) + + +@patch('plinth.action_utils.service_is_running') +@patch('plinth.action_utils.uwsgi_is_enabled') +def test_uwsgi_is_running(uwsgi_is_enabled, service_is_running): + """Test checking whether uwsgi is running with a configuration.""" + uwsgi = Uwsgi('test-uwsgi', 'test-config') + + uwsgi_is_enabled.return_value = True + service_is_running.return_value = True + assert uwsgi.is_running() + uwsgi_is_enabled.assert_has_calls([call('test-config')]) + service_is_running.assert_has_calls([call('uwsgi')]) + + uwsgi_is_enabled.return_value = False + service_is_running.return_value = True + assert not uwsgi.is_running() + + uwsgi_is_enabled.return_value = True + service_is_running.return_value = False + assert not uwsgi.is_running() + + uwsgi_is_enabled.return_value = False + service_is_running.return_value = False + assert not uwsgi.is_running() diff --git a/plinth/modules/radicale/__init__.py b/plinth/modules/radicale/__init__.py index 214d5e73d..af07907ca 100644 --- a/plinth/modules/radicale/__init__.py +++ b/plinth/modules/radicale/__init__.py @@ -30,7 +30,7 @@ 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.apache.components import Uwsgi, Webserver from plinth.modules.firewall.components import Firewall from plinth.utils import format_lazy @@ -99,6 +99,9 @@ class RadicaleApp(app_module.App): webserver = RadicaleWebserver('webserver-radicale', None) self.add(webserver) + uwsgi = RadicaleUwsgi('uwsgi-radicale', 'radicale') + self.add(uwsgi) + class RadicaleWebserver(Webserver): """Webserver enable/disable behavior specific for radicale.""" @@ -117,6 +120,30 @@ class RadicaleWebserver(Webserver): """Set the web name""" +class RadicaleUwsgi(Uwsgi): + """uWSGI enable/disable behavior specific for radicale.""" + + def is_enabled(self): + """Return whether the uWSGI configuration is enabled if version>=2.""" + package_version = get_package_version() + if package_version and package_version >= VERSION_2: + return super().is_enabled() + + return True + + def enable(self): + """Enable the uWSGI configuration if version >=2.""" + package_version = get_package_version() + if package_version and package_version >= VERSION_2: + super().enable() + + def disable(self): + """Disable the uWSGI configuration if version >=2.""" + package_version = get_package_version() + if package_version and package_version >= VERSION_2: + super().disable() + + def init(): """Initialize the radicale module.""" global app @@ -184,19 +211,17 @@ def is_running(): if get_package_version() < VERSION_2: return action_utils.service_is_running('radicale') - return action_utils.service_is_running('uwsgi') \ - and action_utils.uwsgi_is_enabled('radicale') + return app.is_enabled() def is_enabled(): """Return whether the module is enabled.""" package_version = get_package_version() - if package_version >= VERSION_2: - daemon_enabled = action_utils.uwsgi_is_enabled('radicale') - else: + daemon_enabled = True + if package_version and package_version < VERSION_2: daemon_enabled = action_utils.service_is_enabled('radicale') - return (app.is_enabled() and daemon_enabled) + return app.is_enabled() and daemon_enabled def enable(): diff --git a/plinth/modules/searx/__init__.py b/plinth/modules/searx/__init__.py index ebd67e49c..eb7ec19ac 100644 --- a/plinth/modules/searx/__init__.py +++ b/plinth/modules/searx/__init__.py @@ -26,7 +26,7 @@ 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.modules.apache.components import Webserver +from plinth.modules.apache.components import Uwsgi, Webserver from plinth.modules.firewall.components import Firewall from plinth.modules.users import register_group @@ -88,6 +88,9 @@ class SearxApp(app_module.App): 'searx-freedombox-auth') self.add(webserver) + uwsgi = Uwsgi('uwsgi-searx', 'searx') + self.add(uwsgi) + def set_shortcut_login_required(self, login_required): """Change the login_required property of shortcut.""" shortcut = self.remove('shortcut-searx') @@ -157,18 +160,16 @@ def is_public_access_enabled(): def is_enabled(): """Return whether the module is enabled.""" - return (app.is_enabled() and action_utils.uwsgi_is_enabled('searx')) + return app.is_enabled() def enable(): """Enable the module.""" - actions.superuser_run('searx', ['enable']) app.enable() def disable(): """Disable the module.""" - actions.superuser_run('searx', ['disable']) app.disable()