python3-cyberfusion-systemd-support 1.1.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cyberfusion/SystemdSupport/__init__.py +43 -0
- cyberfusion/SystemdSupport/_constants.py +5 -0
- cyberfusion/SystemdSupport/manager.py +14 -0
- cyberfusion/SystemdSupport/tmp_files.py +59 -0
- cyberfusion/SystemdSupport/units.py +137 -0
- python3_cyberfusion_systemd_support-1.1.1.3.dist-info/METADATA +63 -0
- python3_cyberfusion_systemd_support-1.1.1.3.dist-info/RECORD +9 -0
- python3_cyberfusion_systemd_support-1.1.1.3.dist-info/WHEEL +5 -0
- python3_cyberfusion_systemd_support-1.1.1.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Classes for systemd."""
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
from cyberfusion.SystemdSupport._constants import SYSTEMCTL_BIN
|
|
7
|
+
from cyberfusion.SystemdSupport.units import Unit
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Systemd:
|
|
11
|
+
"""Represents systemd."""
|
|
12
|
+
|
|
13
|
+
def __init__(self) -> None:
|
|
14
|
+
"""Do nothing."""
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
def search_units(self, string: str) -> List[Unit]:
|
|
18
|
+
"""Search units."""
|
|
19
|
+
output = []
|
|
20
|
+
|
|
21
|
+
units = subprocess.run(
|
|
22
|
+
[
|
|
23
|
+
SYSTEMCTL_BIN,
|
|
24
|
+
"list-units",
|
|
25
|
+
"--plain",
|
|
26
|
+
"--type",
|
|
27
|
+
"service",
|
|
28
|
+
"--all",
|
|
29
|
+
string,
|
|
30
|
+
"--no-pager",
|
|
31
|
+
"--no-legend",
|
|
32
|
+
],
|
|
33
|
+
check=True,
|
|
34
|
+
stdout=subprocess.PIPE,
|
|
35
|
+
text=True,
|
|
36
|
+
).stdout.splitlines()
|
|
37
|
+
|
|
38
|
+
for unit in units:
|
|
39
|
+
name = unit.split()[0]
|
|
40
|
+
|
|
41
|
+
output.append(Unit(name))
|
|
42
|
+
|
|
43
|
+
return output
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Classes for systemd manager."""
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
from cyberfusion.SystemdSupport._constants import SYSTEMCTL_BIN
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SystemdManager:
|
|
9
|
+
"""Represents systemd manager."""
|
|
10
|
+
|
|
11
|
+
@staticmethod
|
|
12
|
+
def daemon_reload() -> None:
|
|
13
|
+
"""Reload manager configuration."""
|
|
14
|
+
subprocess.run([SYSTEMCTL_BIN, "daemon-reload"], check=True)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Classes for systemd tmp files."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
SYSTEMCTL_TMPFILES_BIN = os.path.join(os.path.sep, "bin", "systemd-tmpfiles")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TmpFileConfigurationFile:
|
|
11
|
+
"""Represents tmp file configuration file."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, path: str) -> None:
|
|
14
|
+
"""Set attributes."""
|
|
15
|
+
self.path = path
|
|
16
|
+
|
|
17
|
+
def create(self) -> None:
|
|
18
|
+
"""Create tmp files."""
|
|
19
|
+
subprocess.run([SYSTEMCTL_TMPFILES_BIN, "--create", self.path], check=True)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TmpFileConfigurationLine:
|
|
23
|
+
"""Represents tmp file configuration line."""
|
|
24
|
+
|
|
25
|
+
TYPE_DIRECTORY_CREATE = "d"
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
type_: str,
|
|
30
|
+
path: str,
|
|
31
|
+
*,
|
|
32
|
+
mode: str,
|
|
33
|
+
user: str,
|
|
34
|
+
group: str,
|
|
35
|
+
age: Optional[str] = None,
|
|
36
|
+
) -> None:
|
|
37
|
+
"""Set attributes."""
|
|
38
|
+
self.type = type_
|
|
39
|
+
self.path = path
|
|
40
|
+
self.mode = mode
|
|
41
|
+
self.user = user
|
|
42
|
+
self.group = group
|
|
43
|
+
self.age = age
|
|
44
|
+
|
|
45
|
+
def __str__(self) -> str:
|
|
46
|
+
"""Get line for in configuration."""
|
|
47
|
+
return (
|
|
48
|
+
self.type
|
|
49
|
+
+ " "
|
|
50
|
+
+ self.path
|
|
51
|
+
+ " "
|
|
52
|
+
+ self.mode
|
|
53
|
+
+ " "
|
|
54
|
+
+ self.user
|
|
55
|
+
+ " "
|
|
56
|
+
+ self.group
|
|
57
|
+
+ " "
|
|
58
|
+
+ (self.age if self.age else "-")
|
|
59
|
+
)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Classes for systemd units."""
|
|
2
|
+
|
|
3
|
+
import glob
|
|
4
|
+
import os
|
|
5
|
+
import subprocess
|
|
6
|
+
from functools import wraps
|
|
7
|
+
from typing import Callable, Optional, TypeVar, cast
|
|
8
|
+
|
|
9
|
+
from cyberfusion.SystemdSupport._constants import SYSTEMCTL_BIN
|
|
10
|
+
from cyberfusion.SystemdSupport.manager import SystemdManager
|
|
11
|
+
|
|
12
|
+
F = TypeVar("F", bound=Callable[..., None])
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def reload_manager(f: F) -> F:
|
|
16
|
+
"""Reload manager configuration if needed.."""
|
|
17
|
+
|
|
18
|
+
@wraps(f)
|
|
19
|
+
def wrapper(
|
|
20
|
+
self: "Unit",
|
|
21
|
+
*args: tuple,
|
|
22
|
+
**kwargs: dict,
|
|
23
|
+
) -> None:
|
|
24
|
+
if self.needs_reload:
|
|
25
|
+
SystemdManager.daemon_reload()
|
|
26
|
+
|
|
27
|
+
f(self, *args, **kwargs)
|
|
28
|
+
|
|
29
|
+
return cast(F, wrapper)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Unit:
|
|
33
|
+
"""Represents unit."""
|
|
34
|
+
|
|
35
|
+
SUFFIX_SERVICE = "service"
|
|
36
|
+
|
|
37
|
+
DIRECTORY_SYSTEMD_OVERRIDE = os.path.join(os.path.sep, "etc", "systemd", "system")
|
|
38
|
+
|
|
39
|
+
def __init__(self, name: str) -> None:
|
|
40
|
+
"""Set attributes."""
|
|
41
|
+
self.name = name
|
|
42
|
+
|
|
43
|
+
def get_property(self, name: str) -> Optional[str]:
|
|
44
|
+
"""Get unit property from systemd."""
|
|
45
|
+
output = subprocess.run(
|
|
46
|
+
[SYSTEMCTL_BIN, "-P", name, "show", self.name],
|
|
47
|
+
check=True,
|
|
48
|
+
stdout=subprocess.PIPE,
|
|
49
|
+
text=True,
|
|
50
|
+
).stdout.rstrip()
|
|
51
|
+
|
|
52
|
+
if output == "":
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
return output
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def drop_in_directory(self) -> str:
|
|
59
|
+
"""Get path to drop-in directory."""
|
|
60
|
+
return os.path.join(os.path.sep, "etc", "systemd", "system", self.name + ".d")
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def needs_reload(self) -> bool:
|
|
64
|
+
"""Get if manager needs to be reloaded for unit."""
|
|
65
|
+
|
|
66
|
+
# systemd itself decides that daemon-reload is needed
|
|
67
|
+
|
|
68
|
+
if self.get_property("NeedDaemonReload") == "yes":
|
|
69
|
+
return True
|
|
70
|
+
|
|
71
|
+
# Drop-in directory was added after the latest daemon-reload (systemd
|
|
72
|
+
# does not detect it itself in that case, see: https://github.com/systemd/systemd/issues/31752)
|
|
73
|
+
|
|
74
|
+
if (
|
|
75
|
+
os.path.isdir(self.drop_in_directory)
|
|
76
|
+
and glob.glob(os.path.join(self.drop_in_directory, "*.conf"))
|
|
77
|
+
and self.get_property("DropInPaths") is None
|
|
78
|
+
):
|
|
79
|
+
return True
|
|
80
|
+
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
def disable(self) -> None:
|
|
84
|
+
"""Disable unit."""
|
|
85
|
+
if not self.is_enabled:
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
subprocess.run([SYSTEMCTL_BIN, "disable", self.name], check=True)
|
|
89
|
+
|
|
90
|
+
def enable(self) -> None:
|
|
91
|
+
"""Enable unit."""
|
|
92
|
+
if self.is_enabled:
|
|
93
|
+
return
|
|
94
|
+
|
|
95
|
+
subprocess.run([SYSTEMCTL_BIN, "enable", self.name], check=True)
|
|
96
|
+
|
|
97
|
+
@reload_manager
|
|
98
|
+
def stop(self) -> None:
|
|
99
|
+
"""Stop unit."""
|
|
100
|
+
if not self.is_active:
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
subprocess.run([SYSTEMCTL_BIN, "stop", self.name], check=True)
|
|
104
|
+
|
|
105
|
+
@reload_manager
|
|
106
|
+
def restart(self) -> None:
|
|
107
|
+
"""Restart unit."""
|
|
108
|
+
subprocess.run([SYSTEMCTL_BIN, "restart", self.name], check=True)
|
|
109
|
+
|
|
110
|
+
@reload_manager
|
|
111
|
+
def reload(self) -> None:
|
|
112
|
+
"""Reload unit."""
|
|
113
|
+
subprocess.run([SYSTEMCTL_BIN, "reload", self.name], check=True)
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def is_active(self) -> bool:
|
|
117
|
+
"""Get if unit is active."""
|
|
118
|
+
try:
|
|
119
|
+
subprocess.run(
|
|
120
|
+
[SYSTEMCTL_BIN, "is-active", "--quiet", self.name], check=True
|
|
121
|
+
)
|
|
122
|
+
except subprocess.CalledProcessError:
|
|
123
|
+
return False
|
|
124
|
+
|
|
125
|
+
return True
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def is_enabled(self) -> bool:
|
|
129
|
+
"""Get if unit is enabled."""
|
|
130
|
+
try:
|
|
131
|
+
subprocess.run(
|
|
132
|
+
[SYSTEMCTL_BIN, "is-enabled", "--quiet", self.name], check=True
|
|
133
|
+
)
|
|
134
|
+
except subprocess.CalledProcessError:
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
return True
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: python3-cyberfusion-systemd-support
|
|
3
|
+
Version: 1.1.1.3
|
|
4
|
+
Summary: Library for systemd.
|
|
5
|
+
Author-email: Cyberfusion <support@cyberfusion.io>
|
|
6
|
+
Project-URL: Source, https://github.com/CyberfusionIO/python3-cyberfusion-systemd-support
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: python3-cyberfusion-common ~=2.0
|
|
9
|
+
|
|
10
|
+
# python3-cyberfusion-systemd-support
|
|
11
|
+
|
|
12
|
+
Library for [systemd](https://systemd.io/).
|
|
13
|
+
|
|
14
|
+
# Install
|
|
15
|
+
|
|
16
|
+
## PyPI
|
|
17
|
+
|
|
18
|
+
Run the following command to install the package from PyPI:
|
|
19
|
+
|
|
20
|
+
pip3 install python3-cyberfusion-systemd-support
|
|
21
|
+
|
|
22
|
+
Next, ensure you are working on a system that ships systemd.
|
|
23
|
+
|
|
24
|
+
## Debian
|
|
25
|
+
|
|
26
|
+
Run the following commands to build a Debian package:
|
|
27
|
+
|
|
28
|
+
mk-build-deps -i -t 'apt -o Debug::pkgProblemResolver=yes --no-install-recommends -y'
|
|
29
|
+
dpkg-buildpackage -us -uc
|
|
30
|
+
|
|
31
|
+
# Configure
|
|
32
|
+
|
|
33
|
+
No configuration is supported.
|
|
34
|
+
|
|
35
|
+
# Usage
|
|
36
|
+
|
|
37
|
+
## Units
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from cyberfusion.SystemdSupport.units import Unit
|
|
41
|
+
|
|
42
|
+
unit = Unit(f"example.{Unit.SUFFIX_SERVICE}")
|
|
43
|
+
|
|
44
|
+
unit.disable()
|
|
45
|
+
unit.stop()
|
|
46
|
+
unit.enable()
|
|
47
|
+
unit.restart()
|
|
48
|
+
unit.reload()
|
|
49
|
+
|
|
50
|
+
print(unit.is_active)
|
|
51
|
+
print(unit.is_enabled)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Tmp files
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from cyberfusion.SystemdSupport.tmp_files import TmpFileConfigurationLine, TmpFileConfigurationFile
|
|
58
|
+
|
|
59
|
+
tmp_file_configuration_line = str(TmpFileConfigurationLine(type_="d", path="/tmp/example", mode="0755", user="example", group="example"))
|
|
60
|
+
tmp_file_configuration_file = TmpFileConfigurationFile(path="/etc/tmpfiles.d/example.conf")
|
|
61
|
+
|
|
62
|
+
tmp_file_configuration_file.create()
|
|
63
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
cyberfusion/SystemdSupport/__init__.py,sha256=tFF-tVDTfOjoIE41CSx_hJeKZCnN4FukSFcjUnfEZkc,959
|
|
2
|
+
cyberfusion/SystemdSupport/_constants.py,sha256=OKlVPEdUByBTc6hvVAB9SVuZlmEqTnNOwVDuH-0RkaU,91
|
|
3
|
+
cyberfusion/SystemdSupport/manager.py,sha256=cWM2kqjEpmO88CCgalQsUlhbzqH0RFbmLbuVBvFGW_8,346
|
|
4
|
+
cyberfusion/SystemdSupport/tmp_files.py,sha256=0EHIN6wZnPthytOCPxozwC2t0dgQfI08OuEvlERVk-A,1350
|
|
5
|
+
cyberfusion/SystemdSupport/units.py,sha256=49Uu8JRILV5hkTWNlwoNNzYzYuanN7GFfYXj4p9d9VE,3671
|
|
6
|
+
python3_cyberfusion_systemd_support-1.1.1.3.dist-info/METADATA,sha256=hOZYke1makSD2lEvv4Xhpvealz50nSKHVMeznR2sDNw,1499
|
|
7
|
+
python3_cyberfusion_systemd_support-1.1.1.3.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
|
|
8
|
+
python3_cyberfusion_systemd_support-1.1.1.3.dist-info/top_level.txt,sha256=ss011q9S6SL_KIIyq7iujFmIYa0grSjlnInO7cDkeag,12
|
|
9
|
+
python3_cyberfusion_systemd_support-1.1.1.3.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cyberfusion
|