From 045a3ba416c3ad94abbe8f356874a985527750b2 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 15 Sep 2020 14:54:18 +0200 Subject: [PATCH] Disable auto boot for add-ons with missconfig (#2057) --- supervisor/addons/__init__.py | 32 ++++++++++++++------- supervisor/addons/addon.py | 33 +++++++++++++--------- supervisor/addons/model.py | 3 +- supervisor/addons/validate.py | 7 ++--- supervisor/api/addons.py | 5 ++-- supervisor/const.py | 10 +++++-- supervisor/core.py | 4 +-- supervisor/docker/__init__.py | 25 +++++++++++------ supervisor/docker/addon.py | 18 ++++++------ supervisor/docker/homeassistant.py | 4 +-- supervisor/docker/interface.py | 45 +++++++++++++++++------------- supervisor/docker/network.py | 6 ++-- supervisor/docker/supervisor.py | 8 +++--- supervisor/exceptions.py | 14 +++++++++- supervisor/homeassistant/core.py | 28 +++++++++---------- supervisor/plugins/audio.py | 20 ++++++------- supervisor/plugins/cli.py | 18 ++++++------ supervisor/plugins/dns.py | 20 ++++++------- supervisor/plugins/multicast.py | 20 ++++++------- supervisor/plugins/observer.py | 16 +++++------ supervisor/supervisor.py | 12 ++++---- 21 files changed, 198 insertions(+), 150 deletions(-) diff --git a/supervisor/addons/__init__.py b/supervisor/addons/__init__.py index 53ae136cf..1acadd1a7 100644 --- a/supervisor/addons/__init__.py +++ b/supervisor/addons/__init__.py @@ -5,13 +5,17 @@ import logging import tarfile from typing import Dict, List, Optional, Union -from ..const import BOOT_AUTO, AddonStartup, AddonState +from ..const import AddonBoot, AddonStartup, AddonState from ..coresys import CoreSys, CoreSysAttributes from ..exceptions import ( + AddonConfigurationError, AddonsError, AddonsNotSupportedError, CoreDNSError, DockerAPIError, + DockerError, + DockerNotFound, + DockerRequestError, HomeAssistantAPIError, HostAppArmorError, ) @@ -84,7 +88,7 @@ class AddonManager(CoreSysAttributes): """Boot add-ons with mode auto.""" tasks: List[Addon] = [] for addon in self.installed: - if addon.boot != BOOT_AUTO or addon.startup != stage: + if addon.boot != AddonBoot.AUTO or addon.startup != stage: continue tasks.append(addon) @@ -98,9 +102,17 @@ class AddonManager(CoreSysAttributes): for addon in tasks: try: await addon.start() + except DockerRequestError: + pass + except (AddonConfigurationError, DockerAPIError, DockerNotFound): + addon.boot = AddonBoot.MANUAL + addon.save_persist() except Exception as err: # pylint: disable=broad-except - _LOGGER.warning("Can't start Add-on %s: %s", addon.slug, err) self.sys_capture_exception(err) + else: + continue + + _LOGGER.warning("Can't start Add-on %s", addon.slug) await asyncio.sleep(self.sys_config.wait_boot) @@ -153,7 +165,7 @@ class AddonManager(CoreSysAttributes): try: await addon.instance.install(store.version, store.image) - except DockerAPIError as err: + except DockerError as err: self.data.uninstall(addon) raise AddonsError() from err else: @@ -174,7 +186,7 @@ class AddonManager(CoreSysAttributes): try: await addon.instance.remove() - except DockerAPIError as err: + except DockerError as err: raise AddonsError() from err else: addon.state = AddonState.UNKNOWN @@ -245,9 +257,9 @@ class AddonManager(CoreSysAttributes): await addon.instance.update(store.version, store.image) # Cleanup - with suppress(DockerAPIError): + with suppress(DockerError): await addon.instance.cleanup() - except DockerAPIError as err: + except DockerError as err: raise AddonsError() from err else: self.data.update(store) @@ -285,7 +297,7 @@ class AddonManager(CoreSysAttributes): try: await addon.instance.remove() await addon.instance.install(addon.version) - except DockerAPIError as err: + except DockerError as err: raise AddonsError() from err else: self.data.update(store) @@ -337,7 +349,7 @@ class AddonManager(CoreSysAttributes): self.sys_docker.network.stale_cleanup, addon.instance.name ) - with suppress(DockerAPIError, KeyError): + with suppress(DockerError, KeyError): # Need pull a image again if not addon.need_build: await addon.instance.install(addon.version, addon.image) @@ -362,7 +374,7 @@ class AddonManager(CoreSysAttributes): try: if not await addon.instance.is_running(): continue - except DockerAPIError as err: + except DockerError as err: _LOGGER.warning("Add-on %s is corrupt: %s", addon.slug, err) self.sys_core.healthy = False self.sys_capture_exception(err) diff --git a/supervisor/addons/addon.py b/supervisor/addons/addon.py index c9fc5a1f3..b49cc10f5 100644 --- a/supervisor/addons/addon.py +++ b/supervisor/addons/addon.py @@ -39,6 +39,7 @@ from ..const import ( ATTR_VERSION, ATTR_WATCHDOG, DNS_SUFFIX, + AddonBoot, AddonStartup, AddonState, ) @@ -49,7 +50,8 @@ from ..exceptions import ( AddonConfigurationError, AddonsError, AddonsNotSupportedError, - DockerAPIError, + DockerError, + DockerRequestError, HostAppArmorError, JsonFileError, ) @@ -98,7 +100,7 @@ class Addon(AddonModel): async def load(self) -> None: """Async initialize of object.""" - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.attach(tag=self.version) # Evaluate state @@ -163,12 +165,12 @@ class Addon(AddonModel): self.persist[ATTR_OPTIONS] = {} if value is None else deepcopy(value) @property - def boot(self) -> bool: + def boot(self) -> AddonBoot: """Return boot config with prio local settings.""" return self.persist.get(ATTR_BOOT, super().boot) @boot.setter - def boot(self, value: bool) -> None: + def boot(self, value: AddonBoot) -> None: """Store user boot options.""" self.persist[ATTR_BOOT] = value @@ -560,7 +562,10 @@ class Addon(AddonModel): # Start Add-on try: await self.instance.run() - except DockerAPIError as err: + except DockerRequestError as err: + self.state = AddonState.STOPPED + raise AddonsError() from err + except DockerError as err: self.state = AddonState.ERROR raise AddonsError(err) from err else: @@ -570,7 +575,9 @@ class Addon(AddonModel): """Stop add-on.""" try: return await self.instance.stop() - except DockerAPIError as err: + except DockerRequestError as err: + raise AddonsError() from err + except DockerError as err: self.state = AddonState.ERROR raise AddonsError() from err else: @@ -600,7 +607,7 @@ class Addon(AddonModel): """Return stats of container.""" try: return await self.instance.stats() - except DockerAPIError as err: + except DockerError as err: raise AddonsError() from err async def write_stdin(self, data) -> None: @@ -614,7 +621,7 @@ class Addon(AddonModel): try: return await self.instance.write_stdin(data) - except DockerAPIError as err: + except DockerError as err: raise AddonsError() from err async def snapshot(self, tar_file: tarfile.TarFile) -> None: @@ -626,7 +633,7 @@ class Addon(AddonModel): if self.need_build: try: await self.instance.export_image(temp_path.joinpath("image.tar")) - except DockerAPIError as err: + except DockerError as err: raise AddonsError() from err data = { @@ -728,18 +735,18 @@ class Addon(AddonModel): image_file = Path(temp, "image.tar") if image_file.is_file(): - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.import_image(image_file) else: - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.install(version, restore_image) await self.instance.cleanup() elif self.instance.version != version or self.legacy: _LOGGER.info("Restore/Update image for addon %s", self.slug) - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.update(version, restore_image) else: - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.stop() # Restore data diff --git a/supervisor/addons/model.py b/supervisor/addons/model.py index 48e97bbde..362a06192 100644 --- a/supervisor/addons/model.py +++ b/supervisor/addons/model.py @@ -66,6 +66,7 @@ from ..const import ( SECURITY_DEFAULT, SECURITY_DISABLE, SECURITY_PROFILE, + AddonBoot, AddonStage, AddonStartup, ) @@ -109,7 +110,7 @@ class AddonModel(CoreSysAttributes, ABC): return self.data[ATTR_OPTIONS] @property - def boot(self) -> bool: + def boot(self) -> AddonBoot: """Return boot config with prio local settings.""" return self.data[ATTR_BOOT] diff --git a/supervisor/addons/validate.py b/supervisor/addons/validate.py index 54f884ca4..3430a722c 100644 --- a/supervisor/addons/validate.py +++ b/supervisor/addons/validate.py @@ -82,11 +82,10 @@ from ..const import ( ATTR_VIDEO, ATTR_WATCHDOG, ATTR_WEBUI, - BOOT_AUTO, - BOOT_MANUAL, PRIVILEGED_ALL, ROLE_ALL, ROLE_DEFAULT, + AddonBoot, AddonStage, AddonStartup, AddonState, @@ -193,7 +192,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema( vol.Optional(ATTR_MACHINE): vol.All([vol.Match(RE_MACHINE)], vol.Unique()), vol.Optional(ATTR_URL): vol.Url(), vol.Required(ATTR_STARTUP): vol.All(_simple_startup, vol.Coerce(AddonStartup)), - vol.Required(ATTR_BOOT): vol.In([BOOT_AUTO, BOOT_MANUAL]), + vol.Required(ATTR_BOOT): vol.Coerce(AddonBoot), vol.Optional(ATTR_INIT, default=True): vol.Boolean(), vol.Optional(ATTR_ADVANCED, default=False): vol.Boolean(), vol.Optional(ATTR_STAGE, default=AddonStage.STABLE): vol.Coerce(AddonStage), @@ -303,7 +302,7 @@ SCHEMA_ADDON_USER = vol.Schema( ), vol.Optional(ATTR_OPTIONS, default=dict): dict, vol.Optional(ATTR_AUTO_UPDATE, default=False): vol.Boolean(), - vol.Optional(ATTR_BOOT): vol.In([BOOT_AUTO, BOOT_MANUAL]), + vol.Optional(ATTR_BOOT): vol.Coerce(AddonBoot), vol.Optional(ATTR_NETWORK): docker_ports, vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(vol.Coerce(str)), vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(vol.Coerce(str)), diff --git a/supervisor/api/addons.py b/supervisor/api/addons.py index 0ddfcbcff..674c24b79 100644 --- a/supervisor/api/addons.py +++ b/supervisor/api/addons.py @@ -91,12 +91,11 @@ from ..const import ( ATTR_VIDEO, ATTR_WATCHDOG, ATTR_WEBUI, - BOOT_AUTO, - BOOT_MANUAL, CONTENT_TYPE_BINARY, CONTENT_TYPE_PNG, CONTENT_TYPE_TEXT, REQUEST_FROM, + AddonBoot, AddonState, ) from ..coresys import CoreSysAttributes @@ -112,7 +111,7 @@ SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)}) # pylint: disable=no-value-for-parameter SCHEMA_OPTIONS = vol.Schema( { - vol.Optional(ATTR_BOOT): vol.In([BOOT_AUTO, BOOT_MANUAL]), + vol.Optional(ATTR_BOOT): vol.Coerce(AddonBoot), vol.Optional(ATTR_NETWORK): vol.Maybe(docker_ports), vol.Optional(ATTR_AUTO_UPDATE): vol.Boolean(), vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(vol.Coerce(str)), diff --git a/supervisor/const.py b/supervisor/const.py index cf8848138..53486befe 100644 --- a/supervisor/const.py +++ b/supervisor/const.py @@ -277,9 +277,6 @@ PROVIDE_SERVICE = "provide" NEED_SERVICE = "need" WANT_SERVICE = "want" -BOOT_AUTO = "auto" -BOOT_MANUAL = "manual" - MAP_CONFIG = "config" MAP_SSL = "ssl" @@ -352,6 +349,13 @@ CHAN_TYPE = "chan_type" SUPERVISED_SUPPORTED_OS = ["Debian GNU/Linux 10 (buster)"] +class AddonBoot(str, Enum): + """Boot mode for the add-on.""" + + AUTO = "auto" + MANUAL = "manual" + + class AddonStartup(str, Enum): """Startup types of Add-on.""" diff --git a/supervisor/core.py b/supervisor/core.py index de007d2f6..5646ac18f 100644 --- a/supervisor/core.py +++ b/supervisor/core.py @@ -15,7 +15,7 @@ from .const import ( ) from .coresys import CoreSys, CoreSysAttributes from .exceptions import ( - DockerAPIError, + DockerError, HassioError, HomeAssistantError, SupervisorUpdateError, @@ -177,7 +177,7 @@ class Core(CoreSysAttributes): if await self.sys_run_in_executor(self.sys_docker.check_denylist_images): self.supported = False self.healthy = False - except DockerAPIError: + except DockerError: self.healthy = False async def start(self): diff --git a/supervisor/docker/__init__.py b/supervisor/docker/__init__.py index fdfc0decf..e29001fae 100644 --- a/supervisor/docker/__init__.py +++ b/supervisor/docker/__init__.py @@ -11,7 +11,7 @@ from packaging import version as pkg_version import requests from ..const import DNS_SUFFIX, DOCKER_IMAGE_DENYLIST, SOCKET_DOCKER -from ..exceptions import DockerAPIError +from ..exceptions import DockerAPIError, DockerError, DockerNotFound, DockerRequestError from .network import DockerNetwork _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -129,27 +129,36 @@ class DockerAPI: container = self.docker.containers.create( f"{image}:{version}", use_config_proxy=False, **kwargs ) - except (docker.errors.DockerException, requests.RequestException) as err: + except docker.errors.NotFound as err: + _LOGGER.error("Image %s not exists for %s", image, name) + raise DockerNotFound() from err + except docker.errors.DockerException as err: _LOGGER.error("Can't create container from %s: %s", name, err) raise DockerAPIError() from err + except requests.RequestException as err: + _LOGGER.error("Dockerd connection issue for %s: %s", name, err) + raise DockerRequestError() from err # Attach network if not network_mode: alias = [hostname] if hostname else None try: self.network.attach_container(container, alias=alias, ipv4=ipv4) - except DockerAPIError: + except DockerError: _LOGGER.warning("Can't attach %s to hassio-net!", name) else: - with suppress(DockerAPIError): + with suppress(DockerError): self.network.detach_default_bridge(container) # Run container try: container.start() - except (docker.errors.DockerException, requests.RequestException) as err: + except docker.errors.DockerException as err: _LOGGER.error("Can't start %s: %s", name, err) - raise DockerAPIError(err) from err + raise DockerAPIError() from err + except requests.RequestException as err: + _LOGGER.error("Dockerd connection issue for %s: %s", name, err) + raise DockerRequestError() from err # Update metadata with suppress(docker.errors.DockerException, requests.RequestException): @@ -187,7 +196,7 @@ class DockerAPI: except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("Can't execute command: %s", err) - raise DockerAPIError() from err + raise DockerError() from err finally: # cleanup container @@ -249,7 +258,7 @@ class DockerAPI: denied_images.add(image_name) except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("Corrupt docker overlayfs detect: %s", err) - raise DockerAPIError() from err + raise DockerError() from err if not denied_images: return False diff --git a/supervisor/docker/addon.py b/supervisor/docker/addon.py index 860695a15..93af23c15 100644 --- a/supervisor/docker/addon.py +++ b/supervisor/docker/addon.py @@ -26,7 +26,7 @@ from ..const import ( SECURITY_PROFILE, ) from ..coresys import CoreSys -from ..exceptions import CoreDNSError, DockerAPIError +from ..exceptions import CoreDNSError, DockerError from ..utils import process_lock from .interface import DockerInterface @@ -419,7 +419,7 @@ class DockerAddon(DockerInterface): except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("Can't build %s:%s: %s", self.image, tag, err) - raise DockerAPIError() from err + raise DockerError() from err _LOGGER.info("Build %s:%s done", self.image, tag) @@ -437,7 +437,7 @@ class DockerAddon(DockerInterface): image = self.sys_docker.api.get_image(f"{self.image}:{self.version}") except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("Can't fetch image %s: %s", self.image, err) - raise DockerAPIError() from err + raise DockerError() from err _LOGGER.info("Export image %s to %s", self.image, tar_file) try: @@ -446,7 +446,7 @@ class DockerAddon(DockerInterface): write_tar.write(chunk) except (OSError, requests.RequestException) as err: _LOGGER.error("Can't write tar file %s: %s", tar_file, err) - raise DockerAPIError() from err + raise DockerError() from err _LOGGER.info("Export image %s done", self.image) @@ -467,12 +467,12 @@ class DockerAddon(DockerInterface): docker_image = self.sys_docker.images.get(f"{self.image}:{self.version}") except (docker.errors.DockerException, OSError) as err: _LOGGER.error("Can't import image %s: %s", self.image, err) - raise DockerAPIError() from err + raise DockerError() from err self._meta = docker_image.attrs _LOGGER.info("Import image %s and version %s", tar_file, self.version) - with suppress(DockerAPIError): + with suppress(DockerError): self._cleanup() @process_lock @@ -486,7 +486,7 @@ class DockerAddon(DockerInterface): Need run inside executor. """ if not self._is_running(): - raise DockerAPIError() + raise DockerError() try: # Load needed docker objects @@ -494,7 +494,7 @@ class DockerAddon(DockerInterface): socket = container.attach_socket(params={"stdin": 1, "stream": 1}) except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("Can't attach to %s stdin: %s", self.name, err) - raise DockerAPIError() from err + raise DockerError() from err try: # Write to stdin @@ -503,7 +503,7 @@ class DockerAddon(DockerInterface): socket.close() except OSError as err: _LOGGER.error("Can't write to %s stdin: %s", self.name, err) - raise DockerAPIError() from err + raise DockerError() from err def _stop(self, remove_container=True) -> None: """Stop/remove Docker container. diff --git a/supervisor/docker/homeassistant.py b/supervisor/docker/homeassistant.py index 8fbc4f08c..96d75d750 100644 --- a/supervisor/docker/homeassistant.py +++ b/supervisor/docker/homeassistant.py @@ -7,7 +7,7 @@ import docker import requests from ..const import ENV_TIME, ENV_TOKEN, ENV_TOKEN_HASSIO, LABEL_MACHINE, MACHINE_ID -from ..exceptions import DockerAPIError +from ..exceptions import DockerError from .interface import CommandReturn, DockerInterface _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -177,7 +177,7 @@ class DockerHomeAssistant(DockerInterface): except docker.errors.NotFound: return False except (docker.errors.DockerException, requests.RequestException): - return DockerAPIError() + return DockerError() # we run on an old image, stop and start it if docker_container.image.id != docker_image.id: diff --git a/supervisor/docker/interface.py b/supervisor/docker/interface.py index fffc9e03e..ee86dd772 100644 --- a/supervisor/docker/interface.py +++ b/supervisor/docker/interface.py @@ -11,7 +11,7 @@ import requests from . import CommandReturn from ..const import LABEL_ARCH, LABEL_VERSION from ..coresys import CoreSys, CoreSysAttributes -from ..exceptions import DockerAPIError +from ..exceptions import DockerAPIError, DockerError, DockerNotFound, DockerRequestError from ..utils import process_lock from .stats import DockerStats @@ -108,11 +108,11 @@ class DockerInterface(CoreSysAttributes): "Available space in /data is: %s GiB", free_space, ) - raise DockerAPIError() from err + raise DockerError() from err except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("Unknown error with %s:%s -> %s", image, tag, err) self.sys_capture_exception(err) - raise DockerAPIError() from err + raise DockerError() from err else: self._meta = docker_image.attrs @@ -146,8 +146,10 @@ class DockerInterface(CoreSysAttributes): docker_container = self.sys_docker.containers.get(self.name) except docker.errors.NotFound: return False - except (docker.errors.DockerException, requests.RequestException) as err: + except docker.errors.DockerException as err: raise DockerAPIError() from err + except requests.RequestException as err: + raise DockerRequestError() from err return docker_container.status == "running" @@ -170,7 +172,7 @@ class DockerInterface(CoreSysAttributes): # Successfull? if not self._meta: - raise DockerAPIError() + raise DockerError() _LOGGER.info("Attach to %s with version %s", self.image, self.version) @process_lock @@ -200,7 +202,7 @@ class DockerInterface(CoreSysAttributes): except docker.errors.NotFound: return except (docker.errors.DockerException, requests.RequestException) as err: - raise DockerAPIError() from err + raise DockerError() from err if docker_container.status == "running": _LOGGER.info("Stop %s application", self.name) @@ -226,14 +228,14 @@ class DockerInterface(CoreSysAttributes): docker_container = self.sys_docker.containers.get(self.name) except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("%s not found for starting up", self.name) - raise DockerAPIError() from err + raise DockerError() from err _LOGGER.info("Start %s", self.name) try: docker_container.start() except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("Can't start %s: %s", self.name, err) - raise DockerAPIError() from err + raise DockerError() from err @process_lock def remove(self) -> Awaitable[None]: @@ -246,7 +248,7 @@ class DockerInterface(CoreSysAttributes): Needs run inside executor. """ # Cleanup container - with suppress(DockerAPIError): + with suppress(DockerError): self._stop() _LOGGER.info("Remove image %s with latest and %s", self.image, self.version) @@ -262,7 +264,7 @@ class DockerInterface(CoreSysAttributes): except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.warning("Can't remove image %s: %s", self.image, err) - raise DockerAPIError() from err + raise DockerError() from err self._meta = None @@ -290,7 +292,7 @@ class DockerInterface(CoreSysAttributes): self._install(tag, image=image, latest=latest) # Stop container & cleanup - with suppress(DockerAPIError): + with suppress(DockerError): self._stop() def logs(self) -> Awaitable[bytes]: @@ -331,14 +333,14 @@ class DockerInterface(CoreSysAttributes): origin = self.sys_docker.images.get(f"{self.image}:{self.version}") except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.warning("Can't find %s for cleanup", self.image) - raise DockerAPIError() from err + raise DockerError() from err # Cleanup Current try: images_list = self.sys_docker.images.list(name=self.image) except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.waring("Corrupt docker overlayfs found: %s", err) - raise DockerAPIError() from err + raise DockerError() from err for image in images_list: if origin.id == image.id: @@ -356,7 +358,7 @@ class DockerInterface(CoreSysAttributes): images_list = self.sys_docker.images.list(name=old_image) except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.waring("Corrupt docker overlayfs found: %s", err) - raise DockerAPIError() from err + raise DockerError() from err for image in images_list: with suppress(docker.errors.DockerException, requests.RequestException): @@ -376,14 +378,14 @@ class DockerInterface(CoreSysAttributes): try: container = self.sys_docker.containers.get(self.name) except (docker.errors.DockerException, requests.RequestException) as err: - raise DockerAPIError() from err + raise DockerError() from err _LOGGER.info("Restart %s", self.image) try: container.restart(timeout=self.timeout) except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.warning("Can't restart %s: %s", self.image, err) - raise DockerAPIError() from err + raise DockerError() from err @process_lock def execute_command(self, command: str) -> Awaitable[CommandReturn]: @@ -409,14 +411,14 @@ class DockerInterface(CoreSysAttributes): try: docker_container = self.sys_docker.containers.get(self.name) except (docker.errors.DockerException, requests.RequestException) as err: - raise DockerAPIError() from err + raise DockerError() from err try: stats = docker_container.stats(stream=False) return DockerStats(stats) except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("Can't read stats from %s: %s", self.name, err) - raise DockerAPIError() from err + raise DockerError() from err def is_failed(self) -> Awaitable[bool]: """Return True if Docker is failing state. @@ -435,7 +437,7 @@ class DockerInterface(CoreSysAttributes): except docker.errors.NotFound: return False except (docker.errors.DockerException, requests.RequestException) as err: - raise DockerAPIError() from err + raise DockerError() from err # container is not running if docker_container.status != "exited": @@ -469,7 +471,10 @@ class DockerInterface(CoreSysAttributes): except (docker.errors.DockerException, ValueError) as err: _LOGGER.debug("No version found for %s", self.image) - raise DockerAPIError() from err + raise DockerNotFound() from err + except requests.RequestException as err: + _LOGGER.warning("Communication issues with dockerd on Host: %s", err) + raise DockerRequestError() from err else: _LOGGER.debug("Found %s versions: %s", self.image, available_version) diff --git a/supervisor/docker/network.py b/supervisor/docker/network.py index 16c3a46cb..6fd1ff5da 100644 --- a/supervisor/docker/network.py +++ b/supervisor/docker/network.py @@ -8,7 +8,7 @@ import docker import requests from ..const import DOCKER_NETWORK, DOCKER_NETWORK_MASK, DOCKER_NETWORK_RANGE -from ..exceptions import DockerAPIError +from ..exceptions import DockerError _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -113,7 +113,7 @@ class DockerNetwork: self.network.connect(container, aliases=alias, ipv4_address=ipv4_address) except docker.errors.APIError as err: _LOGGER.error("Can't link container to hassio-net: %s", err) - raise DockerAPIError() from err + raise DockerError() from err self.network.reload() @@ -133,7 +133,7 @@ class DockerNetwork: except docker.errors.APIError as err: _LOGGER.warning("Can't disconnect container from default: %s", err) - raise DockerAPIError() from err + raise DockerError() from err def stale_cleanup(self, container_name: str): """Remove force a container from Network. diff --git a/supervisor/docker/supervisor.py b/supervisor/docker/supervisor.py index 7413d46d0..7ee381cb1 100644 --- a/supervisor/docker/supervisor.py +++ b/supervisor/docker/supervisor.py @@ -8,7 +8,7 @@ import docker import requests from ..coresys import CoreSysAttributes -from ..exceptions import DockerAPIError +from ..exceptions import DockerError from .interface import DockerInterface _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -40,7 +40,7 @@ class DockerSupervisor(DockerInterface, CoreSysAttributes): try: docker_container = self.sys_docker.containers.get(self.name) except (docker.errors.DockerException, requests.RequestException) as err: - raise DockerAPIError() from err + raise DockerError() from err self._meta = docker_container.attrs _LOGGER.info( @@ -77,7 +77,7 @@ class DockerSupervisor(DockerInterface, CoreSysAttributes): docker_container.image.tag(self.image, tag="latest") except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("Can't retag supervisor version: %s", err) - raise DockerAPIError() from err + raise DockerError() from err def update_start_tag(self, image: str, version: str) -> Awaitable[None]: """Update start tag to new version.""" @@ -104,4 +104,4 @@ class DockerSupervisor(DockerInterface, CoreSysAttributes): except (docker.errors.DockerException, requests.RequestException) as err: _LOGGER.error("Can't fix start tag: %s", err) - raise DockerAPIError() from err + raise DockerError() from err diff --git a/supervisor/exceptions.py b/supervisor/exceptions.py index 852c0a30b..f2fbc6e64 100644 --- a/supervisor/exceptions.py +++ b/supervisor/exceptions.py @@ -238,10 +238,22 @@ class JsonFileError(HassioError): # docker/api -class DockerAPIError(HassioError): +class DockerError(HassioError): + """Docker API/Transport errors.""" + + +class DockerAPIError(DockerError): """Docker API error.""" +class DockerRequestError(DockerError): + """Dockerd OS issues.""" + + +class DockerNotFound(DockerError): + """Docker object don't Exists.""" + + # Hardware diff --git a/supervisor/homeassistant/core.py b/supervisor/homeassistant/core.py index e6810f3e9..36f20cf33 100644 --- a/supervisor/homeassistant/core.py +++ b/supervisor/homeassistant/core.py @@ -15,7 +15,7 @@ from packaging import version as pkg_version from ..coresys import CoreSys, CoreSysAttributes from ..docker.homeassistant import DockerHomeAssistant from ..docker.stats import DockerStats -from ..exceptions import DockerAPIError, HomeAssistantError, HomeAssistantUpdateError +from ..exceptions import DockerError, HomeAssistantError, HomeAssistantUpdateError from ..utils import convert_to_ascii, process_lock _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -58,7 +58,7 @@ class HomeAssistantCore(CoreSysAttributes): ) await self.instance.attach(tag=self.sys_homeassistant.version) - except DockerAPIError: + except DockerError: _LOGGER.info( "No Home Assistant Docker image %s found.", self.sys_homeassistant.image ) @@ -85,7 +85,7 @@ class HomeAssistantCore(CoreSysAttributes): await self.instance.install( LANDINGPAGE, image=self.sys_updater.image_homeassistant ) - except DockerAPIError: + except DockerError: _LOGGER.warning("Fails install landingpage, retry after 30sec") await asyncio.sleep(30) except Exception as err: # pylint: disable=broad-except @@ -117,7 +117,7 @@ class HomeAssistantCore(CoreSysAttributes): tag, image=self.sys_updater.image_homeassistant ) break - except DockerAPIError: + except DockerError: pass except Exception as err: # pylint: disable=broad-except self.sys_capture_exception(err) @@ -138,7 +138,7 @@ class HomeAssistantCore(CoreSysAttributes): _LOGGER.error("Can't start Home Assistant!") # Cleanup - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.cleanup() @process_lock @@ -162,7 +162,7 @@ class HomeAssistantCore(CoreSysAttributes): await self.instance.update( to_version, image=self.sys_updater.image_homeassistant ) - except DockerAPIError as err: + except DockerError as err: _LOGGER.warning("Update Home Assistant image failed") raise HomeAssistantUpdateError() from err else: @@ -175,7 +175,7 @@ class HomeAssistantCore(CoreSysAttributes): # Successfull - last step self.sys_homeassistant.save_data() - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.cleanup(old_image=old_image) # Update Home Assistant @@ -212,7 +212,7 @@ class HomeAssistantCore(CoreSysAttributes): try: await self.instance.run() - except DockerAPIError as err: + except DockerError as err: raise HomeAssistantError() from err await self._block_till_run(self.sys_homeassistant.version) @@ -228,7 +228,7 @@ class HomeAssistantCore(CoreSysAttributes): if await self.instance.is_initialize(): try: await self.instance.start() - except DockerAPIError as err: + except DockerError as err: raise HomeAssistantError() from err await self._block_till_run(self.sys_homeassistant.version) @@ -244,7 +244,7 @@ class HomeAssistantCore(CoreSysAttributes): """ try: return await self.instance.stop(remove_container=False) - except DockerAPIError as err: + except DockerError as err: raise HomeAssistantError() from err @process_lock @@ -252,7 +252,7 @@ class HomeAssistantCore(CoreSysAttributes): """Restart Home Assistant Docker.""" try: await self.instance.restart() - except DockerAPIError as err: + except DockerError as err: raise HomeAssistantError() from err await self._block_till_run(self.sys_homeassistant.version) @@ -260,7 +260,7 @@ class HomeAssistantCore(CoreSysAttributes): @process_lock async def rebuild(self) -> None: """Rebuild Home Assistant Docker container.""" - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.stop() await self._start() @@ -278,7 +278,7 @@ class HomeAssistantCore(CoreSysAttributes): """ try: return await self.instance.stats() - except DockerAPIError as err: + except DockerError as err: raise HomeAssistantError() from err def is_running(self) -> Awaitable[bool]: @@ -407,5 +407,5 @@ class HomeAssistantCore(CoreSysAttributes): # Pull image try: await self.instance.install(self.sys_homeassistant.version) - except DockerAPIError: + except DockerError: _LOGGER.error("Repairing of Home Assistant failed") diff --git a/supervisor/plugins/audio.py b/supervisor/plugins/audio.py index 3f98e24ce..d88ec668b 100644 --- a/supervisor/plugins/audio.py +++ b/supervisor/plugins/audio.py @@ -15,7 +15,7 @@ from ..const import ATTR_IMAGE, ATTR_VERSION from ..coresys import CoreSys, CoreSysAttributes from ..docker.audio import DockerAudio from ..docker.stats import DockerStats -from ..exceptions import AudioError, AudioUpdateError, DockerAPIError +from ..exceptions import AudioError, AudioUpdateError, DockerError from ..utils.json import JsonConfig from .const import FILE_HASSIO_AUDIO from .validate import SCHEMA_AUDIO_CONFIG @@ -92,7 +92,7 @@ class Audio(JsonConfig, CoreSysAttributes): self.version = await self.instance.get_latest_version() await self.instance.attach(tag=self.version) - except DockerAPIError: + except DockerError: _LOGGER.info("No Audio plugin Docker image %s found.", self.instance.image) # Install PulseAudio @@ -131,7 +131,7 @@ class Audio(JsonConfig, CoreSysAttributes): await self.sys_updater.reload() if self.latest_version: - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.install( self.latest_version, image=self.sys_updater.image_audio ) @@ -155,7 +155,7 @@ class Audio(JsonConfig, CoreSysAttributes): try: await self.instance.update(version, image=self.sys_updater.image_audio) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Audio update failed") raise AudioUpdateError() from err else: @@ -164,7 +164,7 @@ class Audio(JsonConfig, CoreSysAttributes): self.save_data() # Cleanup - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.cleanup(old_image=old_image) # Start Audio @@ -175,7 +175,7 @@ class Audio(JsonConfig, CoreSysAttributes): _LOGGER.info("Restart Audio plugin") try: await self.instance.restart() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't start Audio plugin") raise AudioError() from err @@ -184,7 +184,7 @@ class Audio(JsonConfig, CoreSysAttributes): _LOGGER.info("Start Audio plugin") try: await self.instance.run() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't start Audio plugin") raise AudioError() from err @@ -193,7 +193,7 @@ class Audio(JsonConfig, CoreSysAttributes): _LOGGER.info("Stop Audio plugin") try: await self.instance.stop() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't stop Audio plugin") raise AudioError() from err @@ -208,7 +208,7 @@ class Audio(JsonConfig, CoreSysAttributes): """Return stats of CoreDNS.""" try: return await self.instance.stats() - except DockerAPIError as err: + except DockerError as err: raise AudioError() from err def is_running(self) -> Awaitable[bool]: @@ -226,7 +226,7 @@ class Audio(JsonConfig, CoreSysAttributes): _LOGGER.info("Repair Audio %s", self.version) try: await self.instance.install(self.version) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Repairing of Audio failed") self.sys_capture_exception(err) diff --git a/supervisor/plugins/cli.py b/supervisor/plugins/cli.py index 7df5cf4ee..88979dd04 100644 --- a/supervisor/plugins/cli.py +++ b/supervisor/plugins/cli.py @@ -12,7 +12,7 @@ from ..const import ATTR_ACCESS_TOKEN, ATTR_IMAGE, ATTR_VERSION from ..coresys import CoreSys, CoreSysAttributes from ..docker.cli import DockerCli from ..docker.stats import DockerStats -from ..exceptions import CliError, CliUpdateError, DockerAPIError +from ..exceptions import CliError, CliUpdateError, DockerError from ..utils.json import JsonConfig from .const import FILE_HASSIO_CLI from .validate import SCHEMA_CLI_CONFIG @@ -80,7 +80,7 @@ class HaCli(CoreSysAttributes, JsonConfig): self.version = await self.instance.get_latest_version() await self.instance.attach(tag=self.version) - except DockerAPIError: + except DockerError: _LOGGER.info("No cli plugin Docker image %s found.", self.instance.image) # Install cli @@ -105,7 +105,7 @@ class HaCli(CoreSysAttributes, JsonConfig): await self.sys_updater.reload() if self.latest_version: - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.install( self.latest_version, image=self.sys_updater.image_cli, @@ -133,7 +133,7 @@ class HaCli(CoreSysAttributes, JsonConfig): await self.instance.update( version, image=self.sys_updater.image_cli, latest=True ) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("HA cli update failed") raise CliUpdateError() from err else: @@ -142,7 +142,7 @@ class HaCli(CoreSysAttributes, JsonConfig): self.save_data() # Cleanup - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.cleanup(old_image=old_image) # Start cli @@ -158,7 +158,7 @@ class HaCli(CoreSysAttributes, JsonConfig): _LOGGER.info("Start cli plugin") try: await self.instance.run() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't start cli plugin") raise CliError() from err @@ -167,7 +167,7 @@ class HaCli(CoreSysAttributes, JsonConfig): _LOGGER.info("Stop cli plugin") try: await self.instance.stop() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't stop cli plugin") raise CliError() from err @@ -175,7 +175,7 @@ class HaCli(CoreSysAttributes, JsonConfig): """Return stats of cli.""" try: return await self.instance.stats() - except DockerAPIError as err: + except DockerError as err: raise CliError() from err def is_running(self) -> Awaitable[bool]: @@ -193,6 +193,6 @@ class HaCli(CoreSysAttributes, JsonConfig): _LOGGER.info("Repair HA cli %s", self.version) try: await self.instance.install(self.version, latest=True) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Repairing of HA cli failed") self.sys_capture_exception(err) diff --git a/supervisor/plugins/dns.py b/supervisor/plugins/dns.py index 3fff1110e..ddc49c92c 100644 --- a/supervisor/plugins/dns.py +++ b/supervisor/plugins/dns.py @@ -17,7 +17,7 @@ from ..const import ATTR_IMAGE, ATTR_SERVERS, ATTR_VERSION, DNS_SUFFIX, LogLevel from ..coresys import CoreSys, CoreSysAttributes from ..docker.dns import DockerDNS from ..docker.stats import DockerStats -from ..exceptions import CoreDNSError, CoreDNSUpdateError, DockerAPIError +from ..exceptions import CoreDNSError, CoreDNSUpdateError, DockerError from ..utils.json import JsonConfig from ..validate import dns_url from .const import FILE_HASSIO_DNS @@ -120,7 +120,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes): self.version = await self.instance.get_latest_version() await self.instance.attach(tag=self.version) - except DockerAPIError: + except DockerError: _LOGGER.info( "No CoreDNS plugin Docker image %s found.", self.instance.image ) @@ -162,7 +162,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes): await self.sys_updater.reload() if self.latest_version: - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.install( self.latest_version, image=self.sys_updater.image_dns ) @@ -190,7 +190,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes): # Update try: await self.instance.update(version, image=self.sys_updater.image_dns) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("CoreDNS update failed") raise CoreDNSUpdateError() from err else: @@ -199,7 +199,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes): self.save_data() # Cleanup - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.cleanup(old_image=old_image) # Start CoreDNS @@ -211,7 +211,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes): _LOGGER.info("Restart CoreDNS plugin") try: await self.instance.restart() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't start CoreDNS plugin") raise CoreDNSError() from err @@ -223,7 +223,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes): _LOGGER.info("Start CoreDNS plugin") try: await self.instance.run() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't start CoreDNS plugin") raise CoreDNSError() from err @@ -232,7 +232,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes): _LOGGER.info("Stop CoreDNS plugin") try: await self.instance.stop() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't stop CoreDNS plugin") raise CoreDNSError() from err @@ -389,7 +389,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes): """Return stats of CoreDNS.""" try: return await self.instance.stats() - except DockerAPIError as err: + except DockerError as err: raise CoreDNSError() from err def is_running(self) -> Awaitable[bool]: @@ -414,7 +414,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes): _LOGGER.info("Repair CoreDNS %s", self.version) try: await self.instance.install(self.version) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Repairing of CoreDNS failed") self.sys_capture_exception(err) diff --git a/supervisor/plugins/multicast.py b/supervisor/plugins/multicast.py index 1a11d7095..674f9e7ba 100644 --- a/supervisor/plugins/multicast.py +++ b/supervisor/plugins/multicast.py @@ -11,7 +11,7 @@ from ..const import ATTR_IMAGE, ATTR_VERSION from ..coresys import CoreSys, CoreSysAttributes from ..docker.multicast import DockerMulticast from ..docker.stats import DockerStats -from ..exceptions import DockerAPIError, MulticastError, MulticastUpdateError +from ..exceptions import DockerError, MulticastError, MulticastUpdateError from ..utils.json import JsonConfig from .const import FILE_HASSIO_MULTICAST from .validate import SCHEMA_MULTICAST_CONFIG @@ -74,7 +74,7 @@ class Multicast(JsonConfig, CoreSysAttributes): self.version = await self.instance.get_latest_version() await self.instance.attach(tag=self.version) - except DockerAPIError: + except DockerError: _LOGGER.info( "No Multicast plugin Docker image %s found.", self.instance.image ) @@ -103,7 +103,7 @@ class Multicast(JsonConfig, CoreSysAttributes): await self.sys_updater.reload() if self.latest_version: - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.install( self.latest_version, image=self.sys_updater.image_multicast ) @@ -128,7 +128,7 @@ class Multicast(JsonConfig, CoreSysAttributes): # Update try: await self.instance.update(version, image=self.sys_updater.image_multicast) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Multicast update failed") raise MulticastUpdateError() from err else: @@ -137,7 +137,7 @@ class Multicast(JsonConfig, CoreSysAttributes): self.save_data() # Cleanup - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.cleanup(old_image=old_image) # Start Multicast plugin @@ -148,7 +148,7 @@ class Multicast(JsonConfig, CoreSysAttributes): _LOGGER.info("Restart Multicast plugin") try: await self.instance.restart() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't start Multicast plugin") raise MulticastError() from err @@ -157,7 +157,7 @@ class Multicast(JsonConfig, CoreSysAttributes): _LOGGER.info("Start Multicast plugin") try: await self.instance.run() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't start Multicast plugin") raise MulticastError() from err @@ -166,7 +166,7 @@ class Multicast(JsonConfig, CoreSysAttributes): _LOGGER.info("Stop Multicast plugin") try: await self.instance.stop() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't stop Multicast plugin") raise MulticastError() from err @@ -181,7 +181,7 @@ class Multicast(JsonConfig, CoreSysAttributes): """Return stats of Multicast.""" try: return await self.instance.stats() - except DockerAPIError as err: + except DockerError as err: raise MulticastError() from err def is_running(self) -> Awaitable[bool]: @@ -206,6 +206,6 @@ class Multicast(JsonConfig, CoreSysAttributes): _LOGGER.info("Repair Multicast %s", self.version) try: await self.instance.install(self.version) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Repairing of Multicast failed") self.sys_capture_exception(err) diff --git a/supervisor/plugins/observer.py b/supervisor/plugins/observer.py index bea5ad357..eb13cbc9c 100644 --- a/supervisor/plugins/observer.py +++ b/supervisor/plugins/observer.py @@ -12,7 +12,7 @@ from ..const import ATTR_ACCESS_TOKEN, ATTR_IMAGE, ATTR_VERSION from ..coresys import CoreSys, CoreSysAttributes from ..docker.observer import DockerObserver from ..docker.stats import DockerStats -from ..exceptions import DockerAPIError, ObserverError, ObserverUpdateError +from ..exceptions import DockerError, ObserverError, ObserverUpdateError from ..utils.json import JsonConfig from .const import FILE_HASSIO_OBSERVER from .validate import SCHEMA_OBSERVER_CONFIG @@ -80,7 +80,7 @@ class Observer(CoreSysAttributes, JsonConfig): self.version = await self.instance.get_latest_version() await self.instance.attach(tag=self.version) - except DockerAPIError: + except DockerError: _LOGGER.info( "No observer plugin Docker image %s found.", self.instance.image ) @@ -107,7 +107,7 @@ class Observer(CoreSysAttributes, JsonConfig): await self.sys_updater.reload() if self.latest_version: - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.install( self.latest_version, image=self.sys_updater.image_observer ) @@ -131,7 +131,7 @@ class Observer(CoreSysAttributes, JsonConfig): try: await self.instance.update(version, image=self.sys_updater.image_observer) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("HA observer update failed") raise ObserverUpdateError() from err else: @@ -140,7 +140,7 @@ class Observer(CoreSysAttributes, JsonConfig): self.save_data() # Cleanup - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.cleanup(old_image=old_image) # Start observer @@ -157,7 +157,7 @@ class Observer(CoreSysAttributes, JsonConfig): _LOGGER.info("Start observer plugin") try: await self.instance.run() - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Can't start observer plugin") raise ObserverError() from err @@ -165,7 +165,7 @@ class Observer(CoreSysAttributes, JsonConfig): """Return stats of observer.""" try: return await self.instance.stats() - except DockerAPIError as err: + except DockerError as err: raise ObserverError() from err def is_running(self) -> Awaitable[bool]: @@ -183,6 +183,6 @@ class Observer(CoreSysAttributes, JsonConfig): _LOGGER.info("Repair HA observer %s", self.version) try: await self.instance.install(self.version) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Repairing of HA observer failed") self.sys_capture_exception(err) diff --git a/supervisor/supervisor.py b/supervisor/supervisor.py index a79279b02..4fcd853e4 100644 --- a/supervisor/supervisor.py +++ b/supervisor/supervisor.py @@ -14,7 +14,7 @@ from .coresys import CoreSys, CoreSysAttributes from .docker.stats import DockerStats from .docker.supervisor import DockerSupervisor from .exceptions import ( - DockerAPIError, + DockerError, HostAppArmorError, SupervisorError, SupervisorUpdateError, @@ -35,10 +35,10 @@ class Supervisor(CoreSysAttributes): """Prepare Home Assistant object.""" try: await self.instance.attach(tag="latest") - except DockerAPIError: + except DockerError: _LOGGER.critical("Can't setup Supervisor Docker container!") - with suppress(DockerAPIError): + with suppress(DockerError): await self.instance.cleanup() @property @@ -115,7 +115,7 @@ class Supervisor(CoreSysAttributes): await self.instance.update_start_tag( self.sys_updater.image_supervisor, version ) - except DockerAPIError as err: + except DockerError as err: _LOGGER.error("Update of Supervisor failed!") raise SupervisorUpdateError() from err else: @@ -142,7 +142,7 @@ class Supervisor(CoreSysAttributes): """Return stats of Supervisor.""" try: return await self.instance.stats() - except DockerAPIError as err: + except DockerError as err: raise SupervisorError() from err async def repair(self): @@ -153,5 +153,5 @@ class Supervisor(CoreSysAttributes): _LOGGER.info("Repair Supervisor %s", self.version) try: await self.instance.retag() - except DockerAPIError: + except DockerError: _LOGGER.error("Repairing of Supervisor failed")