Skip to content

Commit e6e0e38

Browse files
committed
Add a new service plugin
Signed-off-by: Ronan Abhamon <[email protected]>
1 parent 9e6280e commit e6e0e38

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,42 @@ $ xe host-call-plugin host-uuid=<uuid> plugin=ipmitool.py fn=get_ipmi_lan
302302
303303
```
304304

305+
## Service
306+
307+
A xapi plugin that uses `systemctl` to manage services.
308+
309+
### `start_service`
310+
311+
Start a service if it is not already running.
312+
313+
```
314+
$ xe host-call-plugin host-uuid<uuid> plugin=service.py fn=start_service args:service=<service>
315+
```
316+
317+
### `stop_service`
318+
319+
Stop a service if it is currently running.
320+
321+
```
322+
$ xe host-call-plugin host-uuid<uuid> plugin=service.py fn=stop_service args:service=<service>
323+
```
324+
325+
### `restart_service`
326+
327+
Stop a service if it is running and then start it.
328+
329+
```
330+
$ xe host-call-plugin host-uuid<uuid> plugin=service.py fn=restart_service args:service=<service>
331+
```
332+
333+
### `try_restart_service`
334+
335+
Restart a service only if it is already running.
336+
337+
```
338+
$ xe host-call-plugin host-uuid<uuid> plugin=service.py fn=try_restart_service args:service=<service>
339+
```
340+
305341
## Tests
306342

307343
To run the plugins' unit tests you'll need to install `pytest`, `pyfakefs` and `mock`.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import json
5+
6+
import XenAPIPlugin
7+
8+
from xcpngutils import configure_logging, run_command, error_wrapped
9+
10+
def run_service_command(cmd_name, args):
11+
service = args.get('service')
12+
if not service:
13+
raise Exception('Missing or empty argument `service`')
14+
run_command(['systemctl', cmd_name, service])
15+
return json.dumps(True)
16+
17+
@error_wrapped
18+
def start_service(session, args):
19+
return run_service_command('start', args)
20+
21+
@error_wrapped
22+
def stop_service(session, args):
23+
return run_service_command('stop', args)
24+
25+
@error_wrapped
26+
def restart_service(session, args):
27+
return run_service_command('restart', args)
28+
29+
@error_wrapped
30+
def try_restart_service(session, args):
31+
return run_service_command('try-restart', args)
32+
33+
_LOGGER = configure_logging('service')
34+
if __name__ == "__main__":
35+
XenAPIPlugin.dispatch({
36+
'start_service': start_service,
37+
'stop_service': stop_service,
38+
'restart_service': restart_service,
39+
'try_restart_service': try_restart_service
40+
})

tests/test_service.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import mock
2+
import pytest
3+
import XenAPIPlugin
4+
5+
from service import start_service, stop_service, restart_service, try_restart_service
6+
7+
@mock.patch("service.run_command", autospec=True)
8+
class TestService:
9+
SERVICE = 'linstor-satellite'
10+
11+
def _test_command(self, cmd, cmd_name, run_command):
12+
cmd(mock.MagicMock(), {'service': self.SERVICE})
13+
run_command.assert_called_once_with(['systemctl', cmd_name, self.SERVICE])
14+
15+
def _test_command_without_service(self, cmd):
16+
with pytest.raises(XenAPIPlugin.Failure) as e:
17+
cmd(mock.MagicMock(), {})
18+
assert e.value.params[0] == '-1'
19+
assert e.value.params[1] == 'Missing or empty argument `service`'
20+
21+
def test_start(self, run_command):
22+
self._test_command(start_service, 'start', run_command)
23+
24+
def test_stop(self, run_command):
25+
self._test_command(stop_service, 'stop', run_command)
26+
27+
def test_restart(self, run_command):
28+
self._test_command(restart_service, 'restart', run_command)
29+
30+
def test_try_restart(self, run_command):
31+
self._test_command(try_restart_service, 'try-restart', run_command)
32+
33+
def test_start_without_service(self, run_command):
34+
self._test_command_without_service(start_service)
35+
36+
def test_stop_without_service(self, run_command):
37+
self._test_command_without_service(stop_service)
38+
39+
def test_restart_without_service(self, run_command):
40+
self._test_command_without_service(restart_service)
41+
42+
def test_try_restart_without_service(self, run_command):
43+
self._test_command_without_service(try_restart_service)

0 commit comments

Comments
 (0)