Skip to content

Commit 2f6d165

Browse files
committed
Merge tag 'refs/tags/2025.05.3'
2 parents 1c6f046 + bbb8fa0 commit 2f6d165

40 files changed

+671
-266
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,4 +378,4 @@ jobs:
378378
coverage report
379379
coverage xml
380380
- name: Upload coverage to Codecov
381-
uses: codecov/[email protected].2
381+
uses: codecov/[email protected].3

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: v0.9.1
3+
rev: v0.11.10
44
hooks:
55
- id: ruff
66
args:

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ ARG BUILD_FROM
22
FROM ${BUILD_FROM}
33

44
ENV \
5+
S6_READ_ONLY_ROOT=1 \
56
S6_SERVICES_GRACETIME=10000 \
67
SUPERVISOR_API=http://localhost \
78
CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1 \

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[build-system]
2-
requires = ["setuptools~=80.4.0", "wheel~=0.46.1"]
2+
requires = ["setuptools~=80.8.0", "wheel~=0.46.1"]
33
build-backend = "setuptools.build_meta"
44

55
[project]

requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ brotli==1.1.0
88
ciso8601==2.3.2
99
colorlog==6.9.0
1010
cpe==1.3.1
11-
cryptography==44.0.3
11+
cryptography==45.0.2
1212
debugpy==1.8.14
1313
deepmerge==2.0
1414
dirhash==0.5.0
@@ -23,8 +23,8 @@ pyudev==0.24.3
2323
PyYAML==6.0.2
2424
requests==2.32.3
2525
securetar==2025.2.1
26-
sentry-sdk==2.28.0
27-
setuptools==80.4.0
26+
sentry-sdk==2.29.1
27+
setuptools==80.8.0
2828
voluptuous==0.15.2
2929
dbus-fast==2.44.1
3030
zlib-fast==0.2.1

requirements_tests.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
astroid==3.3.10
2-
coverage==7.8.0
2+
coverage==7.8.1
33
pre-commit==4.2.0
44
pylint==3.3.7
55
pytest-aiohttp==1.1.0
66
pytest-asyncio==0.25.2
77
pytest-cov==6.1.1
88
pytest-timeout==2.4.0
99
pytest==8.3.5
10-
ruff==0.11.9
10+
ruff==0.11.11
1111
time-machine==2.16.0
1212
urllib3==2.4.0

supervisor/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
# pylint: disable=wrong-import-position
1515
from supervisor import bootstrap # noqa: E402
16-
from supervisor.utils.blockbuster import activate_blockbuster # noqa: E402
16+
from supervisor.utils.blockbuster import BlockBusterManager # noqa: E402
1717
from supervisor.utils.logging import activate_log_queue_handler # noqa: E402
1818

1919
# pylint: enable=wrong-import-position
@@ -55,7 +55,7 @@ def run_os_startup_check_cleanup() -> None:
5555
coresys = loop.run_until_complete(bootstrap.initialize_coresys())
5656
loop.set_debug(coresys.config.debug)
5757
if coresys.config.detect_blocking_io:
58-
activate_blockbuster()
58+
BlockBusterManager.activate()
5959
loop.run_until_complete(coresys.core.connect())
6060

6161
loop.run_until_complete(bootstrap.supervisor_debugger(coresys))

supervisor/addons/addon.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,9 +1359,7 @@ def _addon_backup(
13591359
)
13601360
_LOGGER.info("Finish backup for addon %s", self.slug)
13611361
except (tarfile.TarError, OSError, AddFileError) as err:
1362-
raise AddonsError(
1363-
f"Can't write tarfile {tar_file}: {err}", _LOGGER.error
1364-
) from err
1362+
raise AddonsError(f"Can't write tarfile: {err}", _LOGGER.error) from err
13651363
finally:
13661364
if was_running:
13671365
wait_for_start = await self.end_backup()

supervisor/api/host.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,13 @@ async def advanced_logs_handler(
269269
err,
270270
)
271271
break
272+
except ConnectionError as err:
273+
_LOGGER.warning(
274+
"%s raised when returning journal logs: %s",
275+
type(err).__name__,
276+
err,
277+
)
278+
break
272279
except (ConnectionResetError, ClientPayloadError) as ex:
273280
# ClientPayloadError is most likely caused by the closing the connection
274281
raise APIError(

supervisor/api/network.py

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from ..const import (
1212
ATTR_ACCESSPOINTS,
13+
ATTR_ADDR_GEN_MODE,
1314
ATTR_ADDRESS,
1415
ATTR_AUTH,
1516
ATTR_CONNECTED,
@@ -22,6 +23,7 @@
2223
ATTR_ID,
2324
ATTR_INTERFACE,
2425
ATTR_INTERFACES,
26+
ATTR_IP6_PRIVACY,
2527
ATTR_IPV4,
2628
ATTR_IPV6,
2729
ATTR_MAC,
@@ -46,7 +48,10 @@
4648
from ..host.configuration import (
4749
AccessPoint,
4850
Interface,
51+
InterfaceAddrGenMode,
52+
InterfaceIp6Privacy,
4953
InterfaceMethod,
54+
Ip6Setting,
5055
IpConfig,
5156
IpSetting,
5257
VlanConfig,
@@ -68,6 +73,8 @@
6873
{
6974
vol.Optional(ATTR_ADDRESS): [vol.Coerce(IPv6Interface)],
7075
vol.Optional(ATTR_METHOD): vol.Coerce(InterfaceMethod),
76+
vol.Optional(ATTR_ADDR_GEN_MODE): vol.Coerce(InterfaceAddrGenMode),
77+
vol.Optional(ATTR_IP6_PRIVACY): vol.Coerce(InterfaceIp6Privacy),
7178
vol.Optional(ATTR_GATEWAY): vol.Coerce(IPv6Address),
7279
vol.Optional(ATTR_NAMESERVERS): [vol.Coerce(IPv6Address)],
7380
}
@@ -94,8 +101,8 @@
94101
)
95102

96103

97-
def ipconfig_struct(config: IpConfig, setting: IpSetting) -> dict[str, Any]:
98-
"""Return a dict with information about ip configuration."""
104+
def ip4config_struct(config: IpConfig, setting: IpSetting) -> dict[str, Any]:
105+
"""Return a dict with information about IPv4 configuration."""
99106
return {
100107
ATTR_METHOD: setting.method,
101108
ATTR_ADDRESS: [address.with_prefixlen for address in config.address],
@@ -105,6 +112,19 @@ def ipconfig_struct(config: IpConfig, setting: IpSetting) -> dict[str, Any]:
105112
}
106113

107114

115+
def ip6config_struct(config: IpConfig, setting: Ip6Setting) -> dict[str, Any]:
116+
"""Return a dict with information about IPv6 configuration."""
117+
return {
118+
ATTR_METHOD: setting.method,
119+
ATTR_ADDR_GEN_MODE: setting.addr_gen_mode,
120+
ATTR_IP6_PRIVACY: setting.ip6_privacy,
121+
ATTR_ADDRESS: [address.with_prefixlen for address in config.address],
122+
ATTR_NAMESERVERS: [str(address) for address in config.nameservers],
123+
ATTR_GATEWAY: str(config.gateway) if config.gateway else None,
124+
ATTR_READY: config.ready,
125+
}
126+
127+
108128
def wifi_struct(config: WifiConfig) -> dict[str, Any]:
109129
"""Return a dict with information about wifi configuration."""
110130
return {
@@ -132,10 +152,10 @@ def interface_struct(interface: Interface) -> dict[str, Any]:
132152
ATTR_CONNECTED: interface.connected,
133153
ATTR_PRIMARY: interface.primary,
134154
ATTR_MAC: interface.mac,
135-
ATTR_IPV4: ipconfig_struct(interface.ipv4, interface.ipv4setting)
155+
ATTR_IPV4: ip4config_struct(interface.ipv4, interface.ipv4setting)
136156
if interface.ipv4 and interface.ipv4setting
137157
else None,
138-
ATTR_IPV6: ipconfig_struct(interface.ipv6, interface.ipv6setting)
158+
ATTR_IPV6: ip6config_struct(interface.ipv6, interface.ipv6setting)
139159
if interface.ipv6 and interface.ipv6setting
140160
else None,
141161
ATTR_WIFI: wifi_struct(interface.wifi) if interface.wifi else None,
@@ -212,25 +232,31 @@ async def interface_update(self, request: web.Request) -> None:
212232
for key, config in body.items():
213233
if key == ATTR_IPV4:
214234
interface.ipv4setting = IpSetting(
215-
config.get(ATTR_METHOD, InterfaceMethod.STATIC),
216-
config.get(ATTR_ADDRESS, []),
217-
config.get(ATTR_GATEWAY),
218-
config.get(ATTR_NAMESERVERS, []),
235+
method=config.get(ATTR_METHOD, InterfaceMethod.STATIC),
236+
address=config.get(ATTR_ADDRESS, []),
237+
gateway=config.get(ATTR_GATEWAY),
238+
nameservers=config.get(ATTR_NAMESERVERS, []),
219239
)
220240
elif key == ATTR_IPV6:
221-
interface.ipv6setting = IpSetting(
222-
config.get(ATTR_METHOD, InterfaceMethod.STATIC),
223-
config.get(ATTR_ADDRESS, []),
224-
config.get(ATTR_GATEWAY),
225-
config.get(ATTR_NAMESERVERS, []),
241+
interface.ipv6setting = Ip6Setting(
242+
method=config.get(ATTR_METHOD, InterfaceMethod.STATIC),
243+
addr_gen_mode=config.get(
244+
ATTR_ADDR_GEN_MODE, InterfaceAddrGenMode.DEFAULT
245+
),
246+
ip6_privacy=config.get(
247+
ATTR_IP6_PRIVACY, InterfaceIp6Privacy.DEFAULT
248+
),
249+
address=config.get(ATTR_ADDRESS, []),
250+
gateway=config.get(ATTR_GATEWAY),
251+
nameservers=config.get(ATTR_NAMESERVERS, []),
226252
)
227253
elif key == ATTR_WIFI:
228254
interface.wifi = WifiConfig(
229-
config.get(ATTR_MODE, WifiMode.INFRASTRUCTURE),
230-
config.get(ATTR_SSID, ""),
231-
config.get(ATTR_AUTH, AuthMethod.OPEN),
232-
config.get(ATTR_PSK, None),
233-
None,
255+
mode=config.get(ATTR_MODE, WifiMode.INFRASTRUCTURE),
256+
ssid=config.get(ATTR_SSID, ""),
257+
auth=config.get(ATTR_AUTH, AuthMethod.OPEN),
258+
psk=config.get(ATTR_PSK, None),
259+
signal=None,
234260
)
235261
elif key == ATTR_ENABLED:
236262
interface.enabled = config
@@ -277,19 +303,25 @@ async def create_vlan(self, request: web.Request) -> None:
277303
ipv4_setting = None
278304
if ATTR_IPV4 in body:
279305
ipv4_setting = IpSetting(
280-
body[ATTR_IPV4].get(ATTR_METHOD, InterfaceMethod.AUTO),
281-
body[ATTR_IPV4].get(ATTR_ADDRESS, []),
282-
body[ATTR_IPV4].get(ATTR_GATEWAY, None),
283-
body[ATTR_IPV4].get(ATTR_NAMESERVERS, []),
306+
method=body[ATTR_IPV4].get(ATTR_METHOD, InterfaceMethod.AUTO),
307+
address=body[ATTR_IPV4].get(ATTR_ADDRESS, []),
308+
gateway=body[ATTR_IPV4].get(ATTR_GATEWAY, None),
309+
nameservers=body[ATTR_IPV4].get(ATTR_NAMESERVERS, []),
284310
)
285311

286312
ipv6_setting = None
287313
if ATTR_IPV6 in body:
288-
ipv6_setting = IpSetting(
289-
body[ATTR_IPV6].get(ATTR_METHOD, InterfaceMethod.AUTO),
290-
body[ATTR_IPV6].get(ATTR_ADDRESS, []),
291-
body[ATTR_IPV6].get(ATTR_GATEWAY, None),
292-
body[ATTR_IPV6].get(ATTR_NAMESERVERS, []),
314+
ipv6_setting = Ip6Setting(
315+
method=body[ATTR_IPV6].get(ATTR_METHOD, InterfaceMethod.AUTO),
316+
addr_gen_mode=body[ATTR_IPV6].get(
317+
ATTR_ADDR_GEN_MODE, InterfaceAddrGenMode.DEFAULT
318+
),
319+
ip6_privacy=body[ATTR_IPV6].get(
320+
ATTR_IP6_PRIVACY, InterfaceIp6Privacy.DEFAULT
321+
),
322+
address=body[ATTR_IPV6].get(ATTR_ADDRESS, []),
323+
gateway=body[ATTR_IPV6].get(ATTR_GATEWAY, None),
324+
nameservers=body[ATTR_IPV6].get(ATTR_NAMESERVERS, []),
293325
)
294326

295327
vlan_interface = Interface(

0 commit comments

Comments
 (0)