Skip to content

Commit 3476b83

Browse files
Add host.get_disk_usage to support the new API (#152)
* Add `host.get_disk_usage` to support the new API * Update tests/fixtures/host_disk_usage.json Co-authored-by: Martin Hjelmare <[email protected]> * update with new url and format --------- Co-authored-by: Martin Hjelmare <[email protected]>
1 parent 6cb6d04 commit 3476b83

File tree

4 files changed

+260
-0
lines changed

4 files changed

+260
-0
lines changed

aiohasupervisor/host.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .client import _SupervisorComponentClient
44
from .const import TIMEOUT_60_SECONDS
55
from .models.host import (
6+
DiskUsage,
67
HostInfo,
78
HostOptions,
89
RebootOptions,
@@ -47,4 +48,12 @@ async def services(self) -> list[Service]:
4748
result = await self._client.get("host/services")
4849
return ServiceList.from_dict(result.data).services
4950

51+
async def get_disk_usage(self, max_depth: int = 1) -> DiskUsage:
52+
"""Get disk usage."""
53+
result = await self._client.get(
54+
"host/disks/default/usage",
55+
params={"max_depth": str(max_depth)},
56+
)
57+
return DiskUsage.from_dict(result.data)
58+
5059
# Omitted for now - Log endpoints

aiohasupervisor/models/host.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,14 @@ class ServiceList(ResponseData):
9696
"""ServiceList model."""
9797

9898
services: list[Service]
99+
100+
101+
@dataclass(frozen=True, slots=True)
102+
class DiskUsage(ResponseData):
103+
"""DiskUsage model."""
104+
105+
id: str
106+
used_bytes: int
107+
label: str | None = None
108+
total_bytes: int | None = None
109+
children: list["DiskUsage"] | None = None
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
{
2+
"result": "ok",
3+
"data": {
4+
"id": "default",
5+
"label": "Default",
6+
"total_bytes": 503312781312,
7+
"used_bytes": 430243422208,
8+
"children": [
9+
{
10+
"id": "addons_data",
11+
"label": "Addons Data",
12+
"used_bytes": 42347618720,
13+
"children": [
14+
{
15+
"id": "77f1785d_remote_api",
16+
"label": "Remote API",
17+
"used_bytes": 2,
18+
"children": null
19+
},
20+
{
21+
"id": "core_samba",
22+
"label": "Core Samba",
23+
"used_bytes": 517,
24+
"children": null
25+
},
26+
{
27+
"id": "a0d7b954_plex",
28+
"label": "Plex",
29+
"used_bytes": 757750613,
30+
"children": null
31+
},
32+
{
33+
"id": "core_whisper",
34+
"label": "Core Whisper",
35+
"used_bytes": 560933406,
36+
"children": null
37+
}
38+
]
39+
},
40+
{
41+
"id": "addons_config",
42+
"label": "Addons Config",
43+
"used_bytes": 5283318814,
44+
"children": [
45+
{
46+
"id": "core_zwave_js",
47+
"label": "Core Z-Wave JS",
48+
"used_bytes": 258064,
49+
"children": null
50+
},
51+
{
52+
"id": "db21ed7f_qbittorrent",
53+
"label": "QBittorrent",
54+
"used_bytes": 9508283,
55+
"children": null
56+
}
57+
]
58+
},
59+
{
60+
"id": "media",
61+
"label": "Media",
62+
"used_bytes": 476680019,
63+
"children": [
64+
{
65+
"id": "jellyfin",
66+
"label": "Jellyfin",
67+
"used_bytes": 409122725,
68+
"children": null
69+
}
70+
]
71+
},
72+
{
73+
"id": "share",
74+
"label": "Share",
75+
"used_bytes": 37477206419,
76+
"children": [
77+
{
78+
"id": "supervisor",
79+
"label": "Supervisor",
80+
"used_bytes": 929143825,
81+
"children": null
82+
},
83+
{
84+
"id": "openwakeword",
85+
"label": "OpenWakeword",
86+
"used_bytes": 2263836,
87+
"children": null
88+
}
89+
]
90+
},
91+
{
92+
"id": "backup",
93+
"label": "Backup",
94+
"used_bytes": 268350699520,
95+
"children": null
96+
},
97+
{
98+
"id": "ssl",
99+
"label": "SSL",
100+
"used_bytes": 202912633,
101+
"children": [
102+
{
103+
"id": "nginxproxymanager",
104+
"label": "Nginx Proxy Manager",
105+
"used_bytes": 202879859,
106+
"children": null
107+
},
108+
{
109+
"id": "openvpn_server",
110+
"label": "OpenVPN Server",
111+
"used_bytes": 27500,
112+
"children": null
113+
}
114+
]
115+
},
116+
{
117+
"id": "homeassistant",
118+
"label": "Home Assistant",
119+
"used_bytes": 444089236,
120+
"children": [
121+
{
122+
"id": "image",
123+
"label": "Image",
124+
"used_bytes": 571875,
125+
"children": null
126+
},
127+
{
128+
"id": "custom_components",
129+
"label": "Custom Components",
130+
"used_bytes": 58343146,
131+
"children": null
132+
},
133+
{
134+
"id": "www",
135+
"label": "www",
136+
"used_bytes": 70562846,
137+
"children": null
138+
}
139+
]
140+
},
141+
{
142+
"id": "system",
143+
"label": "System",
144+
"used_bytes": 75660896847,
145+
"children": null
146+
}
147+
]
148+
}
149+
}

tests/test_host.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,94 @@ async def test_host_services(
111111
assert result[-1].name == "systemd-resolved.service"
112112
assert result[-1].description == "Network Name Resolution"
113113
assert result[-1].state == "active"
114+
115+
116+
async def test_host_disk_usage(
117+
responses: aioresponses, supervisor_client: SupervisorClient
118+
) -> None:
119+
"""Test host disk usage API."""
120+
responses.get(
121+
f"{SUPERVISOR_URL}/host/disks/default/usage?max_depth=1",
122+
status=200,
123+
body=load_fixture("host_disk_usage.json"),
124+
)
125+
result = await supervisor_client.host.get_disk_usage()
126+
127+
# Test top-level properties
128+
assert result.total_bytes == 503312781312
129+
assert result.used_bytes == 430243422208
130+
assert result.children is not None
131+
132+
# Test children structure
133+
children = result.children
134+
assert children is not None
135+
assert len(children) == 8 # Should have 8 children
136+
137+
# Find specific children by id
138+
assert (
139+
addons_data := next(child for child in children if child.id == "addons_data")
140+
)
141+
assert next(child for child in children if child.id == "addons_config")
142+
assert next(child for child in children if child.id == "media")
143+
assert next(child for child in children if child.id == "share")
144+
assert (backup := next(child for child in children if child.id == "backup"))
145+
assert next(child for child in children if child.id == "ssl")
146+
assert (
147+
homeassistant := next(
148+
child for child in children if child.id == "homeassistant"
149+
)
150+
)
151+
assert next(child for child in children if child.id == "system")
152+
153+
# Test nested children (recursive structure)
154+
assert addons_data.used_bytes == 42347618720
155+
assert addons_data.children is not None
156+
assert len(addons_data.children) == 4
157+
158+
# Find specific nested children
159+
assert next(
160+
child for child in addons_data.children if child.id == "77f1785d_remote_api"
161+
)
162+
assert next(child for child in addons_data.children if child.id == "core_samba")
163+
assert (
164+
plex_addon := next(
165+
child for child in addons_data.children if child.id == "a0d7b954_plex"
166+
)
167+
)
168+
assert next(child for child in addons_data.children if child.id == "core_whisper")
169+
170+
# Test deeper nesting
171+
assert plex_addon.used_bytes == 757750613
172+
assert plex_addon.children is None # Leaf node
173+
174+
# Test another branch
175+
assert homeassistant.used_bytes == 444089236
176+
assert homeassistant.children is not None
177+
assert len(homeassistant.children) == 3
178+
179+
# Find specific homeassistant children
180+
assert next(child for child in homeassistant.children if child.id == "image")
181+
assert next(
182+
child for child in homeassistant.children if child.id == "custom_components"
183+
)
184+
assert next(child for child in homeassistant.children if child.id == "www")
185+
186+
# Test leaf node without children
187+
assert backup.used_bytes == 268350699520
188+
assert backup.children is None
189+
190+
191+
async def test_host_disk_usage_with_custom_depth(
192+
responses: aioresponses, supervisor_client: SupervisorClient
193+
) -> None:
194+
"""Test host disk usage API with custom max_depth."""
195+
responses.get(
196+
f"{SUPERVISOR_URL}/host/disks/default/usage?max_depth=3",
197+
status=200,
198+
body=load_fixture("host_disk_usage.json"),
199+
)
200+
result = await supervisor_client.host.get_disk_usage(max_depth=3)
201+
202+
# Test that the custom max_depth parameter was used
203+
assert result.total_bytes == 503312781312
204+
assert result.used_bytes == 430243422208

0 commit comments

Comments
 (0)