Skip to content

Commit 5c3f3f1

Browse files
committed
linux: use json in get_systemd_status if systemd version > 239
Signed-off-by: Adam Trhon <[email protected]>
1 parent 55d35d5 commit 5c3f3f1

File tree

1 file changed

+73
-30
lines changed

1 file changed

+73
-30
lines changed

labgridhelper/linux.py

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from labgrid.protocol import CommandProtocol
2+
import json
23
import re
34

45
def get_systemd_version(command):
@@ -21,39 +22,81 @@ def get_systemd_version(command):
2122
return int(parsed.group("version"))
2223

2324
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+
"""
2433
assert isinstance(command, CommandProtocol), "command must be a CommandProtocol"
25-
# TODO: Use busctl --json if systemd>239
2634
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-
)
3135

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+
57100

58101
def get_commands(command, directories=None):
59102
"""Returns the commands of a running linux system

0 commit comments

Comments
 (0)