Update supervisor immediately on new version (#5375)

* Update supervisor immediately on new version

* Switch reload updater task
This commit is contained in:
Mike Degatano 2024-10-30 12:12:43 -04:00 committed by GitHub
parent 1a278f2590
commit 9a07ff7fc4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 148 additions and 4 deletions

View File

@ -10,7 +10,7 @@ from ..const import AddonState
from ..coresys import CoreSysAttributes from ..coresys import CoreSysAttributes
from ..exceptions import AddonsError, HomeAssistantError, ObserverError from ..exceptions import AddonsError, HomeAssistantError, ObserverError
from ..homeassistant.const import LANDINGPAGE from ..homeassistant.const import LANDINGPAGE
from ..jobs.decorator import Job, JobCondition from ..jobs.decorator import Job, JobCondition, JobExecutionLimit
from ..plugins.const import PLUGIN_UPDATE_CONDITIONS from ..plugins.const import PLUGIN_UPDATE_CONDITIONS
from ..utils.dt import utcnow from ..utils.dt import utcnow
from ..utils.sentry import capture_exception from ..utils.sentry import capture_exception
@ -66,7 +66,7 @@ class Tasks(CoreSysAttributes):
# Reload # Reload
self.sys_scheduler.register_task(self._reload_store, RUN_RELOAD_ADDONS) self.sys_scheduler.register_task(self._reload_store, RUN_RELOAD_ADDONS)
self.sys_scheduler.register_task(self.sys_updater.reload, RUN_RELOAD_UPDATER) self.sys_scheduler.register_task(self._reload_updater, RUN_RELOAD_UPDATER)
self.sys_scheduler.register_task(self.sys_backups.reload, RUN_RELOAD_BACKUPS) self.sys_scheduler.register_task(self.sys_backups.reload, RUN_RELOAD_BACKUPS)
self.sys_scheduler.register_task(self.sys_host.reload, RUN_RELOAD_HOST) self.sys_scheduler.register_task(self.sys_host.reload, RUN_RELOAD_HOST)
self.sys_scheduler.register_task(self.sys_ingress.reload, RUN_RELOAD_INGRESS) self.sys_scheduler.register_task(self.sys_ingress.reload, RUN_RELOAD_INGRESS)
@ -136,6 +136,7 @@ class Tasks(CoreSysAttributes):
JobCondition.INTERNET_HOST, JobCondition.INTERNET_HOST,
JobCondition.RUNNING, JobCondition.RUNNING,
], ],
limit=JobExecutionLimit.ONCE,
) )
async def _update_supervisor(self): async def _update_supervisor(self):
"""Check and run update of Supervisor Supervisor.""" """Check and run update of Supervisor Supervisor."""
@ -333,3 +334,12 @@ class Tasks(CoreSysAttributes):
async def _reload_store(self) -> None: async def _reload_store(self) -> None:
"""Reload store and check for addon updates.""" """Reload store and check for addon updates."""
await self.sys_store.reload() await self.sys_store.reload()
@Job(name="tasks_reload_updater")
async def _reload_updater(self) -> None:
"""Check for new versions of Home Assistant, Supervisor, OS, etc."""
await self.sys_updater.reload()
# If there's a new version of supervisor, start update immediately
if self.sys_supervisor.need_update:
await self._update_supervisor()

85
tests/fixtures/version_stable.json vendored Normal file
View File

@ -0,0 +1,85 @@
{
"channel": "stable",
"supervisor": "2024.10.0",
"homeassistant": {
"default": "2024.10.4",
"qemux86": "2024.10.4",
"qemux86-64": "2024.10.4",
"qemuarm": "2024.10.4",
"qemuarm-64": "2024.10.4",
"generic-x86-64": "2024.10.4",
"intel-nuc": "2024.10.4",
"khadas-vim3": "2024.10.4",
"raspberrypi": "2024.10.4",
"raspberrypi2": "2024.10.4",
"raspberrypi3": "2024.10.4",
"raspberrypi3-64": "2024.10.4",
"raspberrypi4": "2024.10.4",
"raspberrypi4-64": "2024.10.4",
"raspberrypi5-64": "2024.10.4",
"yellow": "2024.10.4",
"green": "2024.10.4",
"tinker": "2024.10.4",
"odroid-c2": "2024.10.4",
"odroid-c4": "2024.10.4",
"odroid-m1": "2024.10.4",
"odroid-n2": "2024.10.4",
"odroid-xu": "2024.10.4"
},
"hassos": {
"ova": "13.2",
"rpi2": "13.2",
"rpi3": "13.2",
"rpi3-64": "13.2",
"rpi4": "13.2",
"rpi4-64": "13.2",
"rpi5-64": "13.2",
"yellow": "13.2",
"green": "13.2",
"tinker": "13.2",
"odroid-c2": "13.2",
"odroid-c4": "13.2",
"odroid-m1": "13.2",
"odroid-m1s": "13.2",
"odroid-n2": "13.2",
"odroid-xu4": "13.2",
"generic-x86-64": "13.2",
"generic-aarch64": "13.2",
"khadas-vim3": "13.2"
},
"hassos-upgrade": {
"11": "11.5",
"10": "10.5",
"9": "9.5",
"8": "8.5",
"7": "7.6",
"6": "6.6",
"5": "5.13",
"4": "4.20",
"3": "3.13"
},
"ota": "https://os-artifacts.home-assistant.io/{version}/{os_name}_{board}-{version}.raucb",
"cli": "2024.09.0",
"dns": "2024.04.0",
"audio": "2023.12.0",
"multicast": "2024.03.0",
"observer": "2023.06.0",
"image": {
"core": "homeassistant/{machine}-homeassistant",
"supervisor": "homeassistant/{arch}-hassio-supervisor",
"cli": "homeassistant/{arch}-hassio-cli",
"audio": "homeassistant/{arch}-hassio-audio",
"dns": "homeassistant/{arch}-hassio-dns",
"observer": "homeassistant/{arch}-hassio-observer",
"multicast": "homeassistant/{arch}-hassio-multicast"
},
"images": {
"core": "ghcr.io/home-assistant/{machine}-homeassistant",
"supervisor": "ghcr.io/home-assistant/{arch}-hassio-supervisor",
"cli": "ghcr.io/home-assistant/{arch}-hassio-cli",
"audio": "ghcr.io/home-assistant/{arch}-hassio-audio",
"dns": "ghcr.io/home-assistant/{arch}-hassio-dns",
"observer": "ghcr.io/home-assistant/{arch}-hassio-observer",
"multicast": "ghcr.io/home-assistant/{arch}-hassio-multicast"
}
}

View File

@ -1,22 +1,30 @@
"""Test scheduled tasks.""" """Test scheduled tasks."""
from unittest.mock import MagicMock, Mock, patch from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager
from unittest.mock import AsyncMock, MagicMock, Mock, PropertyMock, patch
from awesomeversion import AwesomeVersion from awesomeversion import AwesomeVersion
import pytest import pytest
from supervisor.const import CoreState
from supervisor.coresys import CoreSys from supervisor.coresys import CoreSys
from supervisor.exceptions import HomeAssistantError from supervisor.exceptions import HomeAssistantError
from supervisor.homeassistant.api import HomeAssistantAPI from supervisor.homeassistant.api import HomeAssistantAPI
from supervisor.homeassistant.const import LANDINGPAGE from supervisor.homeassistant.const import LANDINGPAGE
from supervisor.homeassistant.core import HomeAssistantCore from supervisor.homeassistant.core import HomeAssistantCore
from supervisor.misc.tasks import Tasks from supervisor.misc.tasks import Tasks
from supervisor.supervisor import Supervisor
from tests.common import load_fixture
# pylint: disable=protected-access # pylint: disable=protected-access
@pytest.fixture(name="tasks") @pytest.fixture(name="tasks")
async def fixture_tasks(coresys: CoreSys, container: MagicMock) -> Tasks: async def fixture_tasks(
coresys: CoreSys, container: MagicMock
) -> AsyncGenerator[Tasks]:
"""Return task manager.""" """Return task manager."""
coresys.homeassistant.watchdog = True coresys.homeassistant.watchdog = True
coresys.homeassistant.version = AwesomeVersion("2023.12.0") coresys.homeassistant.version = AwesomeVersion("2023.12.0")
@ -159,3 +167,44 @@ async def test_watchdog_homeassistant_api_reanimation_limit(
assert not caplog.text assert not caplog.text
restart.assert_not_called() restart.assert_not_called()
rebuild.assert_not_called() rebuild.assert_not_called()
async def test_reload_updater_triggers_supervisor_update(
tasks: Tasks, coresys: CoreSys
):
"""Test an updater reload triggers a supervisor update if there is one."""
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
coresys.core.state = CoreState.RUNNING
coresys.security.content_trust = False
version_data = load_fixture("version_stable.json")
version_resp = AsyncMock()
version_resp.status = 200
version_resp.read.return_value = version_data
@asynccontextmanager
async def mock_get_for_version(*args, **kwargs) -> AsyncGenerator[AsyncMock]:
"""Mock get call for version information."""
yield version_resp
with (
patch("supervisor.coresys.aiohttp.ClientSession.get", new=mock_get_for_version),
patch.object(
Supervisor,
"version",
new=PropertyMock(return_value=AwesomeVersion("2024.10.0")),
),
patch.object(Supervisor, "update") as update,
):
# Set supervisor's version intially
await coresys.updater.reload()
assert coresys.supervisor.latest_version == AwesomeVersion("2024.10.0")
# No change in version means no update
await tasks._reload_updater()
update.assert_not_called()
# Version change causes an update
version_resp.read.return_value = version_data.replace("2024.10.0", "2024.10.1")
await tasks._reload_updater()
update.assert_called_once()