1
1
from labgrid .protocol import CommandProtocol
2
+ import json
2
3
import re
3
4
4
5
def get_systemd_version (command ):
@@ -21,39 +22,81 @@ def get_systemd_version(command):
21
22
return int (parsed .group ("version" ))
22
23
23
24
def get_systemd_status (command ):
25
+ """Returns parsed output of systemd Manager's ListUnits DBus command
26
+
27
+ Args:
28
+ command (CommandProtocol): An instance of a Driver implementing the CommandProtocol
29
+
30
+ Returns:
31
+ dict: dictionary of service names to their properties
32
+ """
24
33
assert isinstance (command , CommandProtocol ), "command must be a CommandProtocol"
25
- # TODO: Use busctl --json if systemd>239
26
34
array_notation = "a(ssssssouso)"
27
- out = command .run_check (
28
- "busctl call --no-pager org.freedesktop.systemd1 \
29
- /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager ListUnits"
30
- )
31
35
32
- out = out [0 ]
33
- if array_notation not in out :
34
- raise ValueError ("Systemd ListUnits output changed" )
35
- out = out [len (array_notation ):]
36
- array_length = int (out [:out .index ('"' )].strip (" " ))
37
- out = out [out .index ('"' )+ 1 :- 1 ]
38
- out = out .split ('\" \" ' )
39
- data = iter (out )
40
- services = {}
41
- for _ in range (array_length ):
42
- name = next (data )
43
- services [name ] = {}
44
- services [name ]["description" ] = next (data )
45
- services [name ]["load" ] = next (data )
46
- services [name ]["active" ] = next (data )
47
- services [name ]["sub" ] = next (data )
48
- services [name ]["follow" ] = next (data )
49
- path_and_id = next (data )
50
- pos = path_and_id .index ('"' )
51
- services [name ]["path" ] = path_and_id [:pos ]
52
- services [name ]["id" ] = int (path_and_id [pos + 1 :- 1 ].strip (" " ))
53
- services [name ]["type" ] = path_and_id [path_and_id .rfind ('"' ):]
54
- services [name ]["objpath" ] = next (data )
55
-
56
- return services
36
+ def get_systemd_status_json (command ):
37
+ out = command .run_check (
38
+ "busctl call --json=short --no-pager org.freedesktop.systemd1 \
39
+ /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager ListUnits"
40
+ )
41
+ out = out [0 ]
42
+ out = json .loads (out )
43
+ if out ["type" ] != array_notation :
44
+ raise ValueError ("Systemd ListUnits output changed" )
45
+
46
+ services = {}
47
+ for record in out ["data" ][0 ]:
48
+ data = iter (record )
49
+ name = next (data )
50
+ services [name ] = {}
51
+ services [name ]["description" ] = next (data )
52
+ services [name ]["load" ] = next (data )
53
+ services [name ]["active" ] = next (data )
54
+ services [name ]["sub" ] = next (data )
55
+ services [name ]["follow" ] = next (data )
56
+ services [name ]["path" ] = next (data )
57
+ services [name ]["id" ] = int (next (data ))
58
+ services [name ]["type" ] = next (data )
59
+ services [name ]["objpath" ] = next (data )
60
+
61
+ return services
62
+
63
+ def get_systemd_status_raw (command ):
64
+ out = command .run_check (
65
+ "busctl call --no-pager org.freedesktop.systemd1 \
66
+ /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager ListUnits"
67
+ )
68
+
69
+ out = out [0 ]
70
+ if array_notation not in out :
71
+ raise ValueError ("Systemd ListUnits output changed" )
72
+ out = out [len (array_notation ):]
73
+ array_length = int (out [:out .index ('"' )].strip (" " ))
74
+ out = out [out .index ('"' )+ 1 :- 1 ]
75
+ out = out .split ('\" \" ' )
76
+ data = iter (out )
77
+ services = {}
78
+ for _ in range (array_length ):
79
+ name = next (data )
80
+ services [name ] = {}
81
+ services [name ]["description" ] = next (data )
82
+ services [name ]["load" ] = next (data )
83
+ services [name ]["active" ] = next (data )
84
+ services [name ]["sub" ] = next (data )
85
+ services [name ]["follow" ] = next (data )
86
+ path_and_id = next (data )
87
+ pos = path_and_id .index ('"' )
88
+ services [name ]["path" ] = path_and_id [:pos ]
89
+ services [name ]["id" ] = int (path_and_id [pos + 1 :- 1 ].strip (" " ))
90
+ services [name ]["type" ] = path_and_id [path_and_id .rfind ('"' ):]
91
+ services [name ]["objpath" ] = next (data )
92
+
93
+ return services
94
+
95
+ if get_systemd_version (command ) > 239 :
96
+ return get_systemd_status_json (command )
97
+ else :
98
+ return get_systemd_status_raw (command )
99
+
57
100
58
101
def get_commands (command , directories = None ):
59
102
"""Returns the commands of a running linux system
0 commit comments