mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-17 06:06:29 +00:00
Skip unnecessary mounts and privileges for landingpage (#4518)
* Skip unnecessary mounts for landingpage * Remove privileged and cgroup rules from landingpage
This commit is contained in:
parent
6adb4fbcf7
commit
f30d21361f
@ -66,10 +66,14 @@ class DockerHomeAssistant(DockerInterface):
|
|||||||
def cgroups_rules(self) -> list[str]:
|
def cgroups_rules(self) -> list[str]:
|
||||||
"""Return a list of needed cgroups permission."""
|
"""Return a list of needed cgroups permission."""
|
||||||
return (
|
return (
|
||||||
self.sys_hardware.policy.get_cgroups_rules(PolicyGroup.UART)
|
[]
|
||||||
+ self.sys_hardware.policy.get_cgroups_rules(PolicyGroup.VIDEO)
|
if self.sys_homeassistant.version == LANDINGPAGE
|
||||||
+ self.sys_hardware.policy.get_cgroups_rules(PolicyGroup.GPIO)
|
else (
|
||||||
+ self.sys_hardware.policy.get_cgroups_rules(PolicyGroup.USB)
|
self.sys_hardware.policy.get_cgroups_rules(PolicyGroup.UART)
|
||||||
|
+ self.sys_hardware.policy.get_cgroups_rules(PolicyGroup.VIDEO)
|
||||||
|
+ self.sys_hardware.policy.get_cgroups_rules(PolicyGroup.GPIO)
|
||||||
|
+ self.sys_hardware.policy.get_cgroups_rules(PolicyGroup.USB)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -79,54 +83,62 @@ class DockerHomeAssistant(DockerInterface):
|
|||||||
MOUNT_DEV,
|
MOUNT_DEV,
|
||||||
MOUNT_DBUS,
|
MOUNT_DBUS,
|
||||||
MOUNT_UDEV,
|
MOUNT_UDEV,
|
||||||
# Add folders
|
# HA config folder
|
||||||
Mount(
|
Mount(
|
||||||
type=MountType.BIND.value,
|
type=MountType.BIND.value,
|
||||||
source=self.sys_config.path_extern_homeassistant.as_posix(),
|
source=self.sys_config.path_extern_homeassistant.as_posix(),
|
||||||
target="/config",
|
target="/config",
|
||||||
read_only=False,
|
read_only=False,
|
||||||
),
|
),
|
||||||
Mount(
|
|
||||||
type=MountType.BIND.value,
|
|
||||||
source=self.sys_config.path_extern_ssl.as_posix(),
|
|
||||||
target="/ssl",
|
|
||||||
read_only=True,
|
|
||||||
),
|
|
||||||
Mount(
|
|
||||||
type=MountType.BIND.value,
|
|
||||||
source=self.sys_config.path_extern_share.as_posix(),
|
|
||||||
target="/share",
|
|
||||||
read_only=False,
|
|
||||||
propagation=PropagationMode.RSLAVE.value,
|
|
||||||
),
|
|
||||||
Mount(
|
|
||||||
type=MountType.BIND.value,
|
|
||||||
source=self.sys_config.path_extern_media.as_posix(),
|
|
||||||
target="/media",
|
|
||||||
read_only=False,
|
|
||||||
propagation=PropagationMode.RSLAVE.value,
|
|
||||||
),
|
|
||||||
# Configuration audio
|
|
||||||
Mount(
|
|
||||||
type=MountType.BIND.value,
|
|
||||||
source=self.sys_homeassistant.path_extern_pulse.as_posix(),
|
|
||||||
target="/etc/pulse/client.conf",
|
|
||||||
read_only=True,
|
|
||||||
),
|
|
||||||
Mount(
|
|
||||||
type=MountType.BIND.value,
|
|
||||||
source=self.sys_plugins.audio.path_extern_pulse.as_posix(),
|
|
||||||
target="/run/audio",
|
|
||||||
read_only=True,
|
|
||||||
),
|
|
||||||
Mount(
|
|
||||||
type=MountType.BIND.value,
|
|
||||||
source=self.sys_plugins.audio.path_extern_asound.as_posix(),
|
|
||||||
target="/etc/asound.conf",
|
|
||||||
read_only=True,
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Landingpage does not need all this access
|
||||||
|
if self.sys_homeassistant.version != LANDINGPAGE:
|
||||||
|
mounts.extend(
|
||||||
|
[
|
||||||
|
# All other folders
|
||||||
|
Mount(
|
||||||
|
type=MountType.BIND.value,
|
||||||
|
source=self.sys_config.path_extern_ssl.as_posix(),
|
||||||
|
target="/ssl",
|
||||||
|
read_only=True,
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type=MountType.BIND.value,
|
||||||
|
source=self.sys_config.path_extern_share.as_posix(),
|
||||||
|
target="/share",
|
||||||
|
read_only=False,
|
||||||
|
propagation=PropagationMode.RSLAVE.value,
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type=MountType.BIND.value,
|
||||||
|
source=self.sys_config.path_extern_media.as_posix(),
|
||||||
|
target="/media",
|
||||||
|
read_only=False,
|
||||||
|
propagation=PropagationMode.RSLAVE.value,
|
||||||
|
),
|
||||||
|
# Configuration audio
|
||||||
|
Mount(
|
||||||
|
type=MountType.BIND.value,
|
||||||
|
source=self.sys_homeassistant.path_extern_pulse.as_posix(),
|
||||||
|
target="/etc/pulse/client.conf",
|
||||||
|
read_only=True,
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type=MountType.BIND.value,
|
||||||
|
source=self.sys_plugins.audio.path_extern_pulse.as_posix(),
|
||||||
|
target="/run/audio",
|
||||||
|
read_only=True,
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type=MountType.BIND.value,
|
||||||
|
source=self.sys_plugins.audio.path_extern_asound.as_posix(),
|
||||||
|
target="/etc/asound.conf",
|
||||||
|
read_only=True,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# Machine ID
|
# Machine ID
|
||||||
if MACHINE_ID.exists():
|
if MACHINE_ID.exists():
|
||||||
mounts.append(MOUNT_MACHINE_ID)
|
mounts.append(MOUNT_MACHINE_ID)
|
||||||
@ -154,7 +166,7 @@ class DockerHomeAssistant(DockerInterface):
|
|||||||
name=self.name,
|
name=self.name,
|
||||||
hostname=self.name,
|
hostname=self.name,
|
||||||
detach=True,
|
detach=True,
|
||||||
privileged=True,
|
privileged=self.sys_homeassistant.version != LANDINGPAGE,
|
||||||
init=False,
|
init=False,
|
||||||
security_opt=self.security_opt,
|
security_opt=self.security_opt,
|
||||||
network_mode="host",
|
network_mode="host",
|
||||||
|
147
tests/docker/test_homeassistant.py
Normal file
147
tests/docker/test_homeassistant.py
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
"""Test Home Assistant container."""
|
||||||
|
|
||||||
|
from ipaddress import IPv4Address
|
||||||
|
from pathlib import Path
|
||||||
|
from unittest.mock import ANY, patch
|
||||||
|
|
||||||
|
from awesomeversion import AwesomeVersion
|
||||||
|
from docker.types import Mount
|
||||||
|
|
||||||
|
from supervisor.coresys import CoreSys
|
||||||
|
from supervisor.docker.homeassistant import DockerHomeAssistant
|
||||||
|
from supervisor.docker.manager import DockerAPI
|
||||||
|
from supervisor.homeassistant.const import LANDINGPAGE
|
||||||
|
|
||||||
|
|
||||||
|
async def test_homeassistant_start(
|
||||||
|
coresys: CoreSys, tmp_supervisor_data: Path, path_extern
|
||||||
|
):
|
||||||
|
"""Test starting homeassistant."""
|
||||||
|
coresys.homeassistant.version = AwesomeVersion("2023.8.1")
|
||||||
|
|
||||||
|
with patch.object(DockerAPI, "run") as run, patch.object(
|
||||||
|
DockerHomeAssistant, "is_running", side_effect=[False, False, True]
|
||||||
|
), patch("supervisor.homeassistant.core.asyncio.sleep"):
|
||||||
|
await coresys.homeassistant.core.start()
|
||||||
|
|
||||||
|
run.assert_called_once()
|
||||||
|
assert run.call_args.kwargs["name"] == "homeassistant"
|
||||||
|
assert run.call_args.kwargs["hostname"] == "homeassistant"
|
||||||
|
assert run.call_args.kwargs["privileged"] is True
|
||||||
|
assert run.call_args.kwargs["oom_score_adj"] == -300
|
||||||
|
assert run.call_args.kwargs["device_cgroup_rules"]
|
||||||
|
assert run.call_args.kwargs["extra_hosts"] == {
|
||||||
|
"supervisor": IPv4Address("172.30.32.2"),
|
||||||
|
"observer": IPv4Address("172.30.32.6"),
|
||||||
|
}
|
||||||
|
assert run.call_args.kwargs["environment"] == {
|
||||||
|
"SUPERVISOR": IPv4Address("172.30.32.2"),
|
||||||
|
"HASSIO": IPv4Address("172.30.32.2"),
|
||||||
|
"TZ": ANY,
|
||||||
|
"SUPERVISOR_TOKEN": ANY,
|
||||||
|
"HASSIO_TOKEN": ANY,
|
||||||
|
}
|
||||||
|
assert run.call_args.kwargs["mounts"] == [
|
||||||
|
Mount(type="bind", source="/dev", target="/dev", read_only=True),
|
||||||
|
Mount(type="bind", source="/run/dbus", target="/run/dbus", read_only=True),
|
||||||
|
Mount(type="bind", source="/run/udev", target="/run/udev", read_only=True),
|
||||||
|
Mount(
|
||||||
|
type="bind",
|
||||||
|
source=coresys.config.path_extern_homeassistant.as_posix(),
|
||||||
|
target="/config",
|
||||||
|
read_only=False,
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type="bind",
|
||||||
|
source=coresys.config.path_extern_ssl.as_posix(),
|
||||||
|
target="/ssl",
|
||||||
|
read_only=True,
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type="bind",
|
||||||
|
source=coresys.config.path_extern_share.as_posix(),
|
||||||
|
target="/share",
|
||||||
|
read_only=False,
|
||||||
|
propagation="rslave",
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type="bind",
|
||||||
|
source=coresys.config.path_extern_media.as_posix(),
|
||||||
|
target="/media",
|
||||||
|
read_only=False,
|
||||||
|
propagation="rslave",
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type="bind",
|
||||||
|
source=coresys.homeassistant.path_extern_pulse.as_posix(),
|
||||||
|
target="/etc/pulse/client.conf",
|
||||||
|
read_only=True,
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type="bind",
|
||||||
|
source=coresys.plugins.audio.path_extern_pulse.as_posix(),
|
||||||
|
target="/run/audio",
|
||||||
|
read_only=True,
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type="bind",
|
||||||
|
source=coresys.plugins.audio.path_extern_asound.as_posix(),
|
||||||
|
target="/etc/asound.conf",
|
||||||
|
read_only=True,
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type="bind",
|
||||||
|
source="/etc/machine-id",
|
||||||
|
target="/etc/machine-id",
|
||||||
|
read_only=True,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
assert "volumes" not in run.call_args.kwargs
|
||||||
|
|
||||||
|
|
||||||
|
async def test_landingpage_start(
|
||||||
|
coresys: CoreSys, tmp_supervisor_data: Path, path_extern
|
||||||
|
):
|
||||||
|
"""Test starting landingpage."""
|
||||||
|
coresys.homeassistant.version = LANDINGPAGE
|
||||||
|
|
||||||
|
with patch.object(DockerAPI, "run") as run, patch.object(
|
||||||
|
DockerHomeAssistant, "is_running", return_value=False
|
||||||
|
):
|
||||||
|
await coresys.homeassistant.core.start()
|
||||||
|
|
||||||
|
run.assert_called_once()
|
||||||
|
assert run.call_args.kwargs["name"] == "homeassistant"
|
||||||
|
assert run.call_args.kwargs["hostname"] == "homeassistant"
|
||||||
|
assert run.call_args.kwargs["privileged"] is False
|
||||||
|
assert run.call_args.kwargs["oom_score_adj"] == -300
|
||||||
|
assert not run.call_args.kwargs["device_cgroup_rules"]
|
||||||
|
assert run.call_args.kwargs["extra_hosts"] == {
|
||||||
|
"supervisor": IPv4Address("172.30.32.2"),
|
||||||
|
"observer": IPv4Address("172.30.32.6"),
|
||||||
|
}
|
||||||
|
assert run.call_args.kwargs["environment"] == {
|
||||||
|
"SUPERVISOR": IPv4Address("172.30.32.2"),
|
||||||
|
"HASSIO": IPv4Address("172.30.32.2"),
|
||||||
|
"TZ": ANY,
|
||||||
|
"SUPERVISOR_TOKEN": ANY,
|
||||||
|
"HASSIO_TOKEN": ANY,
|
||||||
|
}
|
||||||
|
assert run.call_args.kwargs["mounts"] == [
|
||||||
|
Mount(type="bind", source="/dev", target="/dev", read_only=True),
|
||||||
|
Mount(type="bind", source="/run/dbus", target="/run/dbus", read_only=True),
|
||||||
|
Mount(type="bind", source="/run/udev", target="/run/udev", read_only=True),
|
||||||
|
Mount(
|
||||||
|
type="bind",
|
||||||
|
source=coresys.config.path_extern_homeassistant.as_posix(),
|
||||||
|
target="/config",
|
||||||
|
read_only=False,
|
||||||
|
),
|
||||||
|
Mount(
|
||||||
|
type="bind",
|
||||||
|
source="/etc/machine-id",
|
||||||
|
target="/etc/machine-id",
|
||||||
|
read_only=True,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
assert "volumes" not in run.call_args.kwargs
|
Loading…
x
Reference in New Issue
Block a user