Better handle runtime recovery mode in bootstrap (#138624)

* Better handle runtime recovery mode in bootstrap

* Add test
This commit is contained in:
Artur Pragacz 2025-02-24 13:23:39 +01:00 committed by GitHub
parent fc8affd243
commit d9eb248e91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 32 deletions

View File

@ -328,10 +328,10 @@ async def async_setup_hass(
block_async_io.enable()
config_dict = None
basic_setup_success = False
if not (recovery_mode := runtime_config.recovery_mode):
config_dict = None
basic_setup_success = False
await hass.async_add_executor_job(conf_util.process_ha_config_upgrade, hass)
try:
@ -349,39 +349,43 @@ async def async_setup_hass(
await async_from_config_dict(config_dict, hass) is not None
)
if config_dict is None:
recovery_mode = True
await stop_hass(hass)
hass = await create_hass()
if config_dict is None:
recovery_mode = True
await stop_hass(hass)
hass = await create_hass()
elif not basic_setup_success:
_LOGGER.warning("Unable to set up core integrations. Activating recovery mode")
recovery_mode = True
await stop_hass(hass)
hass = await create_hass()
elif not basic_setup_success:
_LOGGER.warning(
"Unable to set up core integrations. Activating recovery mode"
)
recovery_mode = True
await stop_hass(hass)
hass = await create_hass()
elif any(domain not in hass.config.components for domain in CRITICAL_INTEGRATIONS):
_LOGGER.warning(
"Detected that %s did not load. Activating recovery mode",
",".join(CRITICAL_INTEGRATIONS),
)
elif any(
domain not in hass.config.components for domain in CRITICAL_INTEGRATIONS
):
_LOGGER.warning(
"Detected that %s did not load. Activating recovery mode",
",".join(CRITICAL_INTEGRATIONS),
)
old_config = hass.config
old_logging = hass.data.get(DATA_LOGGING)
old_config = hass.config
old_logging = hass.data.get(DATA_LOGGING)
recovery_mode = True
await stop_hass(hass)
hass = await create_hass()
recovery_mode = True
await stop_hass(hass)
hass = await create_hass()
if old_logging:
hass.data[DATA_LOGGING] = old_logging
hass.config.debug = old_config.debug
hass.config.skip_pip = old_config.skip_pip
hass.config.skip_pip_packages = old_config.skip_pip_packages
hass.config.internal_url = old_config.internal_url
hass.config.external_url = old_config.external_url
# Setup loader cache after the config dir has been set
loader.async_setup(hass)
if old_logging:
hass.data[DATA_LOGGING] = old_logging
hass.config.debug = old_config.debug
hass.config.skip_pip = old_config.skip_pip
hass.config.skip_pip_packages = old_config.skip_pip_packages
hass.config.internal_url = old_config.internal_url
hass.config.external_url = old_config.external_url
# Setup loader cache after the config dir has been set
loader.async_setup(hass)
if recovery_mode:
_LOGGER.info("Starting in recovery mode")

View File

@ -12,7 +12,7 @@ from unittest.mock import AsyncMock, Mock, patch
import pytest
from homeassistant import bootstrap, config as config_util, loader, runner
from homeassistant import bootstrap, config as config_util, core, loader, runner
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
BASE_PLATFORMS,
@ -787,6 +787,9 @@ async def test_setup_hass_recovery_mode(
) -> None:
"""Test it works."""
with (
patch(
"homeassistant.core.HomeAssistant", wraps=core.HomeAssistant
) as mock_hass,
patch("homeassistant.components.browser.setup") as browser_setup,
patch(
"homeassistant.config_entries.ConfigEntries.async_domains",
@ -805,6 +808,8 @@ async def test_setup_hass_recovery_mode(
),
)
mock_hass.assert_called_once()
assert "recovery_mode" in hass.config.components
assert len(mock_mount_local_lib_path.mock_calls) == 0