daemon: Implement diagnostic test for daemon component

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-12-11 22:44:50 -05:00 committed by James Valleroy
parent 0d5493dae7
commit 9cc3ddea2c
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
3 changed files with 43 additions and 4 deletions

View File

@ -26,14 +26,17 @@ our app's class.
def __init__(self):
...
daemon = Daemon('daemon-transmission', managed_services[0])
daemon = Daemon('daemon-transmission', managed_services[0],
listen_ports=[(9091, 'tcp4')])
self.add(daemon)
The first argument to instantiate the :class:`~plinth.daemon.Daemon` class is a
unique ID. The second is the name of the `systemd
<https://www.freedesktop.org/wiki/Software/systemd/>`_ unit file which manages
the daemon.
the daemon. The final argument is the list of ports that this daemon listens on.
This information is used to check if the daemon is listening on the expected
ports when the user requests diagnostic tests on the app.
Managing web server configuration
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -23,7 +23,8 @@ 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):
def __init__(self, component_id, unit, strict_check=False,
listen_ports=None):
"""Initialize a new daemon component.
'component_id' must be a unique string across all apps and components
@ -31,11 +32,17 @@ class Daemon(app.LeaderComponent):
'unit' must the name of systemd unit that this component should manage.
'listen_ports' is a list of tuples. Each tuple contains the port number
as integer followed by a string with one of the values 'tcp4', 'tcp6',
'tcp', 'udp4', 'udp6', 'udp' indicating the protocol that the daemon
listens on. This information is used to run diagnostic tests.
"""
super().__init__(component_id)
self.unit = unit
self.strict_check = strict_check
self.listen_ports = listen_ports or []
def is_enabled(self):
"""Return if the daemon/unit is enabled."""
@ -54,6 +61,15 @@ class Daemon(app.LeaderComponent):
"""Return whether the daemon/unit is running."""
return action_utils.service_is_running(self.unit)
def diagnose(self):
"""Check if the daemon is listening on expected ports."""
results = []
for port in self.listen_ports:
results.append(
action_utils.diagnose_port_listening(port[0], port[1]))
return results
def app_is_running(app_):
"""Return whether all the daemons in the app are running."""

View File

@ -41,9 +41,13 @@ def test_initialization():
assert daemon.component_id == 'test-daemon'
assert daemon.unit == 'test-unit'
assert not daemon.strict_check
assert daemon.listen_ports == []
daemon = Daemon('test-daemon', 'test-unit', strict_check=True)
listen_ports = [(345, 'tcp4'), (123, 'udp')]
daemon = Daemon('test-daemon', 'test-unit', strict_check=True,
listen_ports=listen_ports)
assert daemon.strict_check
assert daemon.listen_ports == listen_ports
@patch('plinth.action_utils.service_is_enabled')
@ -88,6 +92,22 @@ def test_is_running(service_is_running, daemon):
assert not daemon.is_running()
@patch('plinth.action_utils.diagnose_port_listening')
def test_diagnose(diagnose_port_listening, daemon):
"""Test running diagnostics."""
def side_effect(port, kind):
return [f'test-result-{port}-{kind}', 'passed']
daemon = Daemon('test-daemon', 'test-unit', listen_ports=[(8273, 'tcp4'),
(345, 'udp')])
diagnose_port_listening.side_effect = side_effect
results = daemon.diagnose()
assert results == [['test-result-8273-tcp4', 'passed'],
['test-result-345-udp', 'passed']]
diagnose_port_listening.assert_has_calls(
[call(8273, 'tcp4'), call(345, 'udp')])
@patch('plinth.action_utils.service_is_running')
def test_app_is_running(service_is_running):
"""Test that checking whether app is running works."""