diff --git a/supervisor/addons/__init__.py b/supervisor/addons/__init__.py index 2be27f014..c7eadb588 100644 --- a/supervisor/addons/__init__.py +++ b/supervisor/addons/__init__.py @@ -154,17 +154,16 @@ class AddonManager(CoreSysAttributes): async def install(self, slug: str) -> None: """Install an add-on.""" if slug in self.local: - _LOGGER.warning("Add-on %s is already installed", slug) - return + raise AddonsError(f"Add-on {slug} is already installed", _LOGGER.warning) store = self.store.get(slug) if not store: - _LOGGER.error("Add-on %s not exists", slug) - raise AddonsError() + raise AddonsError(f"Add-on {slug} not exists", _LOGGER.error) if not store.available: - _LOGGER.error("Add-on %s not supported on that platform", slug) - raise AddonsNotSupportedError() + raise AddonsNotSupportedError( + f"Add-on {slug} not supported on that platform", _LOGGER.error + ) self.data.install(store) addon = Addon(self.coresys, slug) @@ -256,23 +255,23 @@ class AddonManager(CoreSysAttributes): async def update(self, slug: str) -> None: """Update add-on.""" if slug not in self.local: - _LOGGER.error("Add-on %s is not installed", slug) - raise AddonsError() + raise AddonsError(f"Add-on {slug} is not installed", _LOGGER.error) addon = self.local[slug] if addon.is_detached: - _LOGGER.error("Add-on %s is not available inside store", slug) - raise AddonsError() + raise AddonsError( + f"Add-on {slug} is not available inside store", _LOGGER.error + ) store = self.store[slug] if addon.version == store.version: - _LOGGER.warning("No update available for add-on %s", slug) - return + raise AddonsError(f"No update available for add-on {slug}", _LOGGER.warning) # Check if available, Maybe something have changed if not store.available: - _LOGGER.error("Add-on %s not supported on that platform", slug) - raise AddonsNotSupportedError() + raise AddonsNotSupportedError( + f"Add-on {slug} not supported on that platform", _LOGGER.error + ) # Update instance last_state: AddonState = addon.state diff --git a/supervisor/exceptions.py b/supervisor/exceptions.py index 92be74db4..564f8d3fc 100644 --- a/supervisor/exceptions.py +++ b/supervisor/exceptions.py @@ -1,9 +1,22 @@ """Core Exceptions.""" +from typing import Callable, Optional + + class HassioError(Exception): """Root exception.""" + def __init__( + self, + message: Optional[str] = None, + logger: Optional[Callable[..., None]] = None, + ) -> None: + """Raise & log.""" + if logger: + logger(message) + super().__init__(message) + class HassioNotSupportedError(HassioError): """Function is not supported.""" diff --git a/supervisor/hassos.py b/supervisor/hassos.py index 69ef1e933..20047b1d1 100644 --- a/supervisor/hassos.py +++ b/supervisor/hassos.py @@ -143,8 +143,9 @@ class HassOS(CoreSysAttributes): # Check installed version self._check_host() if version == self.version: - _LOGGER.warning("Version %s is already installed", version) - raise HassOSUpdateError() + raise HassOSUpdateError( + f"Version {version!s} is already installed", _LOGGER.warning + ) # Fetch files from internet int_ota = await self._download_raucb(version) diff --git a/supervisor/homeassistant/core.py b/supervisor/homeassistant/core.py index 7994f1841..e80645e95 100644 --- a/supervisor/homeassistant/core.py +++ b/supervisor/homeassistant/core.py @@ -182,8 +182,9 @@ class HomeAssistantCore(CoreSysAttributes): exists = await self.instance.exists() if exists and version == self.instance.version: - _LOGGER.warning("Version %s is already installed", version) - return + raise HomeAssistantUpdateError( + f"Version {version!s} is already installed", _LOGGER.warning + ) # process an update async def _update(to_version: AwesomeVersion) -> None: @@ -194,8 +195,9 @@ class HomeAssistantCore(CoreSysAttributes): to_version, image=self.sys_updater.image_homeassistant ) except DockerError as err: - _LOGGER.warning("Updating Home Assistant image failed") - raise HomeAssistantUpdateError() from err + raise HomeAssistantUpdateError( + "Updating Home Assistant image failed", _LOGGER.warning + ) from err else: self.sys_homeassistant.version = self.instance.version self.sys_homeassistant.image = self.sys_updater.image_homeassistant @@ -344,8 +346,7 @@ class HomeAssistantCore(CoreSysAttributes): # If not valid if result.exit_code is None: - _LOGGER.error("Fatal error on config check!") - raise HomeAssistantError() + raise HomeAssistantError("Fatal error on config check!", _LOGGER.error) # Convert output log = convert_to_ascii(result.output) diff --git a/supervisor/snapshots/__init__.py b/supervisor/snapshots/__init__.py index 8ad525d1d..150e49660 100644 --- a/supervisor/snapshots/__init__.py +++ b/supervisor/snapshots/__init__.py @@ -2,7 +2,10 @@ import asyncio import logging from pathlib import Path -from typing import Set +from typing import Awaitable, Set + +from awesomeversion.awesomeversion import AwesomeVersion +from awesomeversion.exceptions import AwesomeVersionCompare from ..const import FOLDER_HOMEASSISTANT, SNAPSHOT_FULL, SNAPSHOT_PARTIAL, CoreState from ..coresys import CoreSysAttributes @@ -263,9 +266,7 @@ class SnapshotManager(CoreSysAttributes): # Start homeassistant restore _LOGGER.info("Restoring %s Home-Assistant", snapshot.slug) snapshot.restore_homeassistant() - task_hass = self.sys_create_task( - self.sys_homeassistant.core.update(snapshot.homeassistant_version) - ) + task_hass = self._update_core_task(snapshot.homeassistant_version) # Restore repositories _LOGGER.info("Restoring %s Repositories", snapshot.slug) @@ -354,11 +355,7 @@ class SnapshotManager(CoreSysAttributes): task_hass = None if homeassistant: _LOGGER.info("Restoring %s Home-Assistant", snapshot.slug) - task_hass = self.sys_create_task( - self.sys_homeassistant.core.update( - snapshot.homeassistant_version - ) - ) + task_hass = self._update_core_task(snapshot.homeassistant_version) if addons: _LOGGER.info("Restoring %s Repositories", snapshot.slug) @@ -393,3 +390,16 @@ class SnapshotManager(CoreSysAttributes): finally: self.sys_core.state = CoreState.RUNNING self.lock.release() + + def _update_core_task(self, version: AwesomeVersion) -> Awaitable[None]: + """Process core update if needed and make awaitable object.""" + + async def _core_update(): + try: + if version == self.sys_homeassistant.version: + return + except (AwesomeVersionCompare, TypeError): + pass + await self.sys_homeassistant.core.update(version) + + return self.sys_create_task(_core_update())