Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions supervisor/api/homeassistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
ATTR_BLK_WRITE,
ATTR_BOOT,
ATTR_CPU_PERCENT,
ATTR_DUPLICATE_LOG_FILE,
ATTR_IMAGE,
ATTR_IP_ADDRESS,
ATTR_JOB_ID,
Expand Down Expand Up @@ -55,6 +56,7 @@
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(str),
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(str),
vol.Optional(ATTR_BACKUPS_EXCLUDE_DATABASE): vol.Boolean(),
vol.Optional(ATTR_DUPLICATE_LOG_FILE): vol.Boolean(),
}
)

Expand Down Expand Up @@ -112,6 +114,7 @@ async def info(self, request: web.Request) -> dict[str, Any]:
ATTR_AUDIO_INPUT: self.sys_homeassistant.audio_input,
ATTR_AUDIO_OUTPUT: self.sys_homeassistant.audio_output,
ATTR_BACKUPS_EXCLUDE_DATABASE: self.sys_homeassistant.backups_exclude_database,
ATTR_DUPLICATE_LOG_FILE: self.sys_homeassistant.duplicate_log_file,
}

@api_process
Expand Down Expand Up @@ -151,6 +154,9 @@ async def options(self, request: web.Request) -> None:
ATTR_BACKUPS_EXCLUDE_DATABASE
]

if ATTR_DUPLICATE_LOG_FILE in body:
self.sys_homeassistant.duplicate_log_file = body[ATTR_DUPLICATE_LOG_FILE]

await self.sys_homeassistant.save_data()

@api_process
Expand Down
1 change: 1 addition & 0 deletions supervisor/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@
ATTR_DOCKER_API = "docker_api"
ATTR_DOCUMENTATION = "documentation"
ATTR_DOMAINS = "domains"
ATTR_DUPLICATE_LOG_FILE = "duplicate_log_file"
ATTR_ENABLE = "enable"
ATTR_ENABLE_IPV6 = "enable_ipv6"
ATTR_ENABLED = "enabled"
Expand Down
1 change: 1 addition & 0 deletions supervisor/docker/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ def from_status(cls, status: str) -> PullImageLayerStage | None:
return None


ENV_DUPLICATE_LOG_FILE = "HA_DUPLICATE_LOG_FILE"
ENV_TIME = "TZ"
ENV_TOKEN = "SUPERVISOR_TOKEN"
ENV_TOKEN_OLD = "HASSIO_TOKEN"
Expand Down
3 changes: 3 additions & 0 deletions supervisor/docker/homeassistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from ..jobs.const import JobConcurrency
from ..jobs.decorator import Job
from .const import (
ENV_DUPLICATE_LOG_FILE,
ENV_TIME,
ENV_TOKEN,
ENV_TOKEN_OLD,
Expand Down Expand Up @@ -174,6 +175,8 @@ async def run(self, *, restore_job_id: str | None = None) -> None:
}
if restore_job_id:
environment[ENV_RESTORE_JOB_ID] = restore_job_id
if self.sys_homeassistant.duplicate_log_file:
environment[ENV_DUPLICATE_LOG_FILE] = "1"
await self._run(
tag=(self.sys_homeassistant.version),
name=self.name,
Expand Down
11 changes: 11 additions & 0 deletions supervisor/homeassistant/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
ATTR_AUDIO_OUTPUT,
ATTR_BACKUPS_EXCLUDE_DATABASE,
ATTR_BOOT,
ATTR_DUPLICATE_LOG_FILE,
ATTR_IMAGE,
ATTR_MESSAGE,
ATTR_PORT,
Expand Down Expand Up @@ -299,6 +300,16 @@ def backups_exclude_database(self, value: bool) -> None:
"""Set whether backups should exclude database by default."""
self._data[ATTR_BACKUPS_EXCLUDE_DATABASE] = value

@property
def duplicate_log_file(self) -> bool:
"""Return True if Home Assistant should duplicate logs to file."""
return self._data[ATTR_DUPLICATE_LOG_FILE]

@duplicate_log_file.setter
def duplicate_log_file(self, value: bool) -> None:
"""Set whether Home Assistant should duplicate logs to file."""
self._data[ATTR_DUPLICATE_LOG_FILE] = value

async def load(self) -> None:
"""Prepare Home Assistant object."""
await asyncio.wait(
Expand Down
2 changes: 2 additions & 0 deletions supervisor/homeassistant/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
ATTR_AUDIO_OUTPUT,
ATTR_BACKUPS_EXCLUDE_DATABASE,
ATTR_BOOT,
ATTR_DUPLICATE_LOG_FILE,
ATTR_IMAGE,
ATTR_PORT,
ATTR_REFRESH_TOKEN,
Expand All @@ -36,6 +37,7 @@
vol.Optional(ATTR_AUDIO_OUTPUT, default=None): vol.Maybe(str),
vol.Optional(ATTR_AUDIO_INPUT, default=None): vol.Maybe(str),
vol.Optional(ATTR_BACKUPS_EXCLUDE_DATABASE, default=False): vol.Boolean(),
vol.Optional(ATTR_DUPLICATE_LOG_FILE, default=False): vol.Boolean(),
vol.Optional(ATTR_OVERRIDE_IMAGE, default=False): vol.Boolean(),
},
extra=vol.REMOVE_EXTRA,
Expand Down
24 changes: 24 additions & 0 deletions tests/docker/test_homeassistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ async def test_homeassistant_start(
"TZ": ANY,
"SUPERVISOR_TOKEN": ANY,
"HASSIO_TOKEN": ANY,
# no "HA_DUPLICATE_LOG_FILE"
}
assert run.call_args.kwargs["mounts"] == [
DEV_MOUNT,
Expand Down Expand Up @@ -105,6 +106,28 @@ async def test_homeassistant_start(
assert "volumes" not in run.call_args.kwargs


async def test_homeassistant_start_with_duplicate_log_file(
coresys: CoreSys, tmp_supervisor_data: Path, path_extern
):
"""Test starting homeassistant with duplicate_log_file enabled."""
coresys.homeassistant.version = AwesomeVersion("2025.12.0")
coresys.homeassistant.duplicate_log_file = True

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()
env = run.call_args.kwargs["environment"]
assert "HA_DUPLICATE_LOG_FILE" in env
assert env["HA_DUPLICATE_LOG_FILE"] == "1"


async def test_landingpage_start(
coresys: CoreSys, tmp_supervisor_data: Path, path_extern
):
Expand Down Expand Up @@ -133,6 +156,7 @@ async def test_landingpage_start(
"TZ": ANY,
"SUPERVISOR_TOKEN": ANY,
"HASSIO_TOKEN": ANY,
# no "HA_DUPLICATE_LOG_FILE"
}
assert run.call_args.kwargs["mounts"] == [
DEV_MOUNT,
Expand Down
Loading