Disable auto boot for add-ons with missconfig (#2057)

This commit is contained in:
Pascal Vizeli 2020-09-15 14:54:18 +02:00 committed by GitHub
parent 4da2715d14
commit 045a3ba416
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 198 additions and 150 deletions

View File

@ -5,13 +5,17 @@ import logging
import tarfile import tarfile
from typing import Dict, List, Optional, Union 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 ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import ( from ..exceptions import (
AddonConfigurationError,
AddonsError, AddonsError,
AddonsNotSupportedError, AddonsNotSupportedError,
CoreDNSError, CoreDNSError,
DockerAPIError, DockerAPIError,
DockerError,
DockerNotFound,
DockerRequestError,
HomeAssistantAPIError, HomeAssistantAPIError,
HostAppArmorError, HostAppArmorError,
) )
@ -84,7 +88,7 @@ class AddonManager(CoreSysAttributes):
"""Boot add-ons with mode auto.""" """Boot add-ons with mode auto."""
tasks: List[Addon] = [] tasks: List[Addon] = []
for addon in self.installed: for addon in self.installed:
if addon.boot != BOOT_AUTO or addon.startup != stage: if addon.boot != AddonBoot.AUTO or addon.startup != stage:
continue continue
tasks.append(addon) tasks.append(addon)
@ -98,9 +102,17 @@ class AddonManager(CoreSysAttributes):
for addon in tasks: for addon in tasks:
try: try:
await addon.start() 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 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) 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) await asyncio.sleep(self.sys_config.wait_boot)
@ -153,7 +165,7 @@ class AddonManager(CoreSysAttributes):
try: try:
await addon.instance.install(store.version, store.image) await addon.instance.install(store.version, store.image)
except DockerAPIError as err: except DockerError as err:
self.data.uninstall(addon) self.data.uninstall(addon)
raise AddonsError() from err raise AddonsError() from err
else: else:
@ -174,7 +186,7 @@ class AddonManager(CoreSysAttributes):
try: try:
await addon.instance.remove() await addon.instance.remove()
except DockerAPIError as err: except DockerError as err:
raise AddonsError() from err raise AddonsError() from err
else: else:
addon.state = AddonState.UNKNOWN addon.state = AddonState.UNKNOWN
@ -245,9 +257,9 @@ class AddonManager(CoreSysAttributes):
await addon.instance.update(store.version, store.image) await addon.instance.update(store.version, store.image)
# Cleanup # Cleanup
with suppress(DockerAPIError): with suppress(DockerError):
await addon.instance.cleanup() await addon.instance.cleanup()
except DockerAPIError as err: except DockerError as err:
raise AddonsError() from err raise AddonsError() from err
else: else:
self.data.update(store) self.data.update(store)
@ -285,7 +297,7 @@ class AddonManager(CoreSysAttributes):
try: try:
await addon.instance.remove() await addon.instance.remove()
await addon.instance.install(addon.version) await addon.instance.install(addon.version)
except DockerAPIError as err: except DockerError as err:
raise AddonsError() from err raise AddonsError() from err
else: else:
self.data.update(store) self.data.update(store)
@ -337,7 +349,7 @@ class AddonManager(CoreSysAttributes):
self.sys_docker.network.stale_cleanup, addon.instance.name self.sys_docker.network.stale_cleanup, addon.instance.name
) )
with suppress(DockerAPIError, KeyError): with suppress(DockerError, KeyError):
# Need pull a image again # Need pull a image again
if not addon.need_build: if not addon.need_build:
await addon.instance.install(addon.version, addon.image) await addon.instance.install(addon.version, addon.image)
@ -362,7 +374,7 @@ class AddonManager(CoreSysAttributes):
try: try:
if not await addon.instance.is_running(): if not await addon.instance.is_running():
continue continue
except DockerAPIError as err: except DockerError as err:
_LOGGER.warning("Add-on %s is corrupt: %s", addon.slug, err) _LOGGER.warning("Add-on %s is corrupt: %s", addon.slug, err)
self.sys_core.healthy = False self.sys_core.healthy = False
self.sys_capture_exception(err) self.sys_capture_exception(err)

View File

@ -39,6 +39,7 @@ from ..const import (
ATTR_VERSION, ATTR_VERSION,
ATTR_WATCHDOG, ATTR_WATCHDOG,
DNS_SUFFIX, DNS_SUFFIX,
AddonBoot,
AddonStartup, AddonStartup,
AddonState, AddonState,
) )
@ -49,7 +50,8 @@ from ..exceptions import (
AddonConfigurationError, AddonConfigurationError,
AddonsError, AddonsError,
AddonsNotSupportedError, AddonsNotSupportedError,
DockerAPIError, DockerError,
DockerRequestError,
HostAppArmorError, HostAppArmorError,
JsonFileError, JsonFileError,
) )
@ -98,7 +100,7 @@ class Addon(AddonModel):
async def load(self) -> None: async def load(self) -> None:
"""Async initialize of object.""" """Async initialize of object."""
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.attach(tag=self.version) await self.instance.attach(tag=self.version)
# Evaluate state # Evaluate state
@ -163,12 +165,12 @@ class Addon(AddonModel):
self.persist[ATTR_OPTIONS] = {} if value is None else deepcopy(value) self.persist[ATTR_OPTIONS] = {} if value is None else deepcopy(value)
@property @property
def boot(self) -> bool: def boot(self) -> AddonBoot:
"""Return boot config with prio local settings.""" """Return boot config with prio local settings."""
return self.persist.get(ATTR_BOOT, super().boot) return self.persist.get(ATTR_BOOT, super().boot)
@boot.setter @boot.setter
def boot(self, value: bool) -> None: def boot(self, value: AddonBoot) -> None:
"""Store user boot options.""" """Store user boot options."""
self.persist[ATTR_BOOT] = value self.persist[ATTR_BOOT] = value
@ -560,7 +562,10 @@ class Addon(AddonModel):
# Start Add-on # Start Add-on
try: try:
await self.instance.run() 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 self.state = AddonState.ERROR
raise AddonsError(err) from err raise AddonsError(err) from err
else: else:
@ -570,7 +575,9 @@ class Addon(AddonModel):
"""Stop add-on.""" """Stop add-on."""
try: try:
return await self.instance.stop() 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 self.state = AddonState.ERROR
raise AddonsError() from err raise AddonsError() from err
else: else:
@ -600,7 +607,7 @@ class Addon(AddonModel):
"""Return stats of container.""" """Return stats of container."""
try: try:
return await self.instance.stats() return await self.instance.stats()
except DockerAPIError as err: except DockerError as err:
raise AddonsError() from err raise AddonsError() from err
async def write_stdin(self, data) -> None: async def write_stdin(self, data) -> None:
@ -614,7 +621,7 @@ class Addon(AddonModel):
try: try:
return await self.instance.write_stdin(data) return await self.instance.write_stdin(data)
except DockerAPIError as err: except DockerError as err:
raise AddonsError() from err raise AddonsError() from err
async def snapshot(self, tar_file: tarfile.TarFile) -> None: async def snapshot(self, tar_file: tarfile.TarFile) -> None:
@ -626,7 +633,7 @@ class Addon(AddonModel):
if self.need_build: if self.need_build:
try: try:
await self.instance.export_image(temp_path.joinpath("image.tar")) await self.instance.export_image(temp_path.joinpath("image.tar"))
except DockerAPIError as err: except DockerError as err:
raise AddonsError() from err raise AddonsError() from err
data = { data = {
@ -728,18 +735,18 @@ class Addon(AddonModel):
image_file = Path(temp, "image.tar") image_file = Path(temp, "image.tar")
if image_file.is_file(): if image_file.is_file():
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.import_image(image_file) await self.instance.import_image(image_file)
else: else:
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.install(version, restore_image) await self.instance.install(version, restore_image)
await self.instance.cleanup() await self.instance.cleanup()
elif self.instance.version != version or self.legacy: elif self.instance.version != version or self.legacy:
_LOGGER.info("Restore/Update image for addon %s", self.slug) _LOGGER.info("Restore/Update image for addon %s", self.slug)
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.update(version, restore_image) await self.instance.update(version, restore_image)
else: else:
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.stop() await self.instance.stop()
# Restore data # Restore data

View File

@ -66,6 +66,7 @@ from ..const import (
SECURITY_DEFAULT, SECURITY_DEFAULT,
SECURITY_DISABLE, SECURITY_DISABLE,
SECURITY_PROFILE, SECURITY_PROFILE,
AddonBoot,
AddonStage, AddonStage,
AddonStartup, AddonStartup,
) )
@ -109,7 +110,7 @@ class AddonModel(CoreSysAttributes, ABC):
return self.data[ATTR_OPTIONS] return self.data[ATTR_OPTIONS]
@property @property
def boot(self) -> bool: def boot(self) -> AddonBoot:
"""Return boot config with prio local settings.""" """Return boot config with prio local settings."""
return self.data[ATTR_BOOT] return self.data[ATTR_BOOT]

View File

@ -82,11 +82,10 @@ from ..const import (
ATTR_VIDEO, ATTR_VIDEO,
ATTR_WATCHDOG, ATTR_WATCHDOG,
ATTR_WEBUI, ATTR_WEBUI,
BOOT_AUTO,
BOOT_MANUAL,
PRIVILEGED_ALL, PRIVILEGED_ALL,
ROLE_ALL, ROLE_ALL,
ROLE_DEFAULT, ROLE_DEFAULT,
AddonBoot,
AddonStage, AddonStage,
AddonStartup, AddonStartup,
AddonState, 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_MACHINE): vol.All([vol.Match(RE_MACHINE)], vol.Unique()),
vol.Optional(ATTR_URL): vol.Url(), vol.Optional(ATTR_URL): vol.Url(),
vol.Required(ATTR_STARTUP): vol.All(_simple_startup, vol.Coerce(AddonStartup)), 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_INIT, default=True): vol.Boolean(),
vol.Optional(ATTR_ADVANCED, default=False): vol.Boolean(), vol.Optional(ATTR_ADVANCED, default=False): vol.Boolean(),
vol.Optional(ATTR_STAGE, default=AddonStage.STABLE): vol.Coerce(AddonStage), 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_OPTIONS, default=dict): dict,
vol.Optional(ATTR_AUTO_UPDATE, default=False): vol.Boolean(), 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_NETWORK): docker_ports,
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(vol.Coerce(str)), vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(vol.Coerce(str)), vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(vol.Coerce(str)),

View File

@ -91,12 +91,11 @@ from ..const import (
ATTR_VIDEO, ATTR_VIDEO,
ATTR_WATCHDOG, ATTR_WATCHDOG,
ATTR_WEBUI, ATTR_WEBUI,
BOOT_AUTO,
BOOT_MANUAL,
CONTENT_TYPE_BINARY, CONTENT_TYPE_BINARY,
CONTENT_TYPE_PNG, CONTENT_TYPE_PNG,
CONTENT_TYPE_TEXT, CONTENT_TYPE_TEXT,
REQUEST_FROM, REQUEST_FROM,
AddonBoot,
AddonState, AddonState,
) )
from ..coresys import CoreSysAttributes 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 # pylint: disable=no-value-for-parameter
SCHEMA_OPTIONS = vol.Schema( 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_NETWORK): vol.Maybe(docker_ports),
vol.Optional(ATTR_AUTO_UPDATE): vol.Boolean(), vol.Optional(ATTR_AUTO_UPDATE): vol.Boolean(),
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(vol.Coerce(str)), vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(vol.Coerce(str)),

View File

@ -277,9 +277,6 @@ PROVIDE_SERVICE = "provide"
NEED_SERVICE = "need" NEED_SERVICE = "need"
WANT_SERVICE = "want" WANT_SERVICE = "want"
BOOT_AUTO = "auto"
BOOT_MANUAL = "manual"
MAP_CONFIG = "config" MAP_CONFIG = "config"
MAP_SSL = "ssl" MAP_SSL = "ssl"
@ -352,6 +349,13 @@ CHAN_TYPE = "chan_type"
SUPERVISED_SUPPORTED_OS = ["Debian GNU/Linux 10 (buster)"] 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): class AddonStartup(str, Enum):
"""Startup types of Add-on.""" """Startup types of Add-on."""

View File

@ -15,7 +15,7 @@ from .const import (
) )
from .coresys import CoreSys, CoreSysAttributes from .coresys import CoreSys, CoreSysAttributes
from .exceptions import ( from .exceptions import (
DockerAPIError, DockerError,
HassioError, HassioError,
HomeAssistantError, HomeAssistantError,
SupervisorUpdateError, SupervisorUpdateError,
@ -177,7 +177,7 @@ class Core(CoreSysAttributes):
if await self.sys_run_in_executor(self.sys_docker.check_denylist_images): if await self.sys_run_in_executor(self.sys_docker.check_denylist_images):
self.supported = False self.supported = False
self.healthy = False self.healthy = False
except DockerAPIError: except DockerError:
self.healthy = False self.healthy = False
async def start(self): async def start(self):

View File

@ -11,7 +11,7 @@ from packaging import version as pkg_version
import requests import requests
from ..const import DNS_SUFFIX, DOCKER_IMAGE_DENYLIST, SOCKET_DOCKER 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 from .network import DockerNetwork
_LOGGER: logging.Logger = logging.getLogger(__name__) _LOGGER: logging.Logger = logging.getLogger(__name__)
@ -129,27 +129,36 @@ class DockerAPI:
container = self.docker.containers.create( container = self.docker.containers.create(
f"{image}:{version}", use_config_proxy=False, **kwargs 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) _LOGGER.error("Can't create container from %s: %s", name, err)
raise DockerAPIError() 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
# Attach network # Attach network
if not network_mode: if not network_mode:
alias = [hostname] if hostname else None alias = [hostname] if hostname else None
try: try:
self.network.attach_container(container, alias=alias, ipv4=ipv4) self.network.attach_container(container, alias=alias, ipv4=ipv4)
except DockerAPIError: except DockerError:
_LOGGER.warning("Can't attach %s to hassio-net!", name) _LOGGER.warning("Can't attach %s to hassio-net!", name)
else: else:
with suppress(DockerAPIError): with suppress(DockerError):
self.network.detach_default_bridge(container) self.network.detach_default_bridge(container)
# Run container # Run container
try: try:
container.start() 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) _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 # Update metadata
with suppress(docker.errors.DockerException, requests.RequestException): with suppress(docker.errors.DockerException, requests.RequestException):
@ -187,7 +196,7 @@ class DockerAPI:
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Can't execute command: %s", err) _LOGGER.error("Can't execute command: %s", err)
raise DockerAPIError() from err raise DockerError() from err
finally: finally:
# cleanup container # cleanup container
@ -249,7 +258,7 @@ class DockerAPI:
denied_images.add(image_name) denied_images.add(image_name)
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Corrupt docker overlayfs detect: %s", err) _LOGGER.error("Corrupt docker overlayfs detect: %s", err)
raise DockerAPIError() from err raise DockerError() from err
if not denied_images: if not denied_images:
return False return False

View File

@ -26,7 +26,7 @@ from ..const import (
SECURITY_PROFILE, SECURITY_PROFILE,
) )
from ..coresys import CoreSys from ..coresys import CoreSys
from ..exceptions import CoreDNSError, DockerAPIError from ..exceptions import CoreDNSError, DockerError
from ..utils import process_lock from ..utils import process_lock
from .interface import DockerInterface from .interface import DockerInterface
@ -419,7 +419,7 @@ class DockerAddon(DockerInterface):
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Can't build %s:%s: %s", self.image, tag, 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) _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}") image = self.sys_docker.api.get_image(f"{self.image}:{self.version}")
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Can't fetch image %s: %s", self.image, 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) _LOGGER.info("Export image %s to %s", self.image, tar_file)
try: try:
@ -446,7 +446,7 @@ class DockerAddon(DockerInterface):
write_tar.write(chunk) write_tar.write(chunk)
except (OSError, requests.RequestException) as err: except (OSError, requests.RequestException) as err:
_LOGGER.error("Can't write tar file %s: %s", tar_file, 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) _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}") docker_image = self.sys_docker.images.get(f"{self.image}:{self.version}")
except (docker.errors.DockerException, OSError) as err: except (docker.errors.DockerException, OSError) as err:
_LOGGER.error("Can't import image %s: %s", self.image, 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 self._meta = docker_image.attrs
_LOGGER.info("Import image %s and version %s", tar_file, self.version) _LOGGER.info("Import image %s and version %s", tar_file, self.version)
with suppress(DockerAPIError): with suppress(DockerError):
self._cleanup() self._cleanup()
@process_lock @process_lock
@ -486,7 +486,7 @@ class DockerAddon(DockerInterface):
Need run inside executor. Need run inside executor.
""" """
if not self._is_running(): if not self._is_running():
raise DockerAPIError() raise DockerError()
try: try:
# Load needed docker objects # Load needed docker objects
@ -494,7 +494,7 @@ class DockerAddon(DockerInterface):
socket = container.attach_socket(params={"stdin": 1, "stream": 1}) socket = container.attach_socket(params={"stdin": 1, "stream": 1})
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Can't attach to %s stdin: %s", self.name, err) _LOGGER.error("Can't attach to %s stdin: %s", self.name, err)
raise DockerAPIError() from err raise DockerError() from err
try: try:
# Write to stdin # Write to stdin
@ -503,7 +503,7 @@ class DockerAddon(DockerInterface):
socket.close() socket.close()
except OSError as err: except OSError as err:
_LOGGER.error("Can't write to %s stdin: %s", self.name, 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: def _stop(self, remove_container=True) -> None:
"""Stop/remove Docker container. """Stop/remove Docker container.

View File

@ -7,7 +7,7 @@ import docker
import requests import requests
from ..const import ENV_TIME, ENV_TOKEN, ENV_TOKEN_HASSIO, LABEL_MACHINE, MACHINE_ID 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 from .interface import CommandReturn, DockerInterface
_LOGGER: logging.Logger = logging.getLogger(__name__) _LOGGER: logging.Logger = logging.getLogger(__name__)
@ -177,7 +177,7 @@ class DockerHomeAssistant(DockerInterface):
except docker.errors.NotFound: except docker.errors.NotFound:
return False return False
except (docker.errors.DockerException, requests.RequestException): except (docker.errors.DockerException, requests.RequestException):
return DockerAPIError() return DockerError()
# we run on an old image, stop and start it # we run on an old image, stop and start it
if docker_container.image.id != docker_image.id: if docker_container.image.id != docker_image.id:

View File

@ -11,7 +11,7 @@ import requests
from . import CommandReturn from . import CommandReturn
from ..const import LABEL_ARCH, LABEL_VERSION from ..const import LABEL_ARCH, LABEL_VERSION
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import DockerAPIError from ..exceptions import DockerAPIError, DockerError, DockerNotFound, DockerRequestError
from ..utils import process_lock from ..utils import process_lock
from .stats import DockerStats from .stats import DockerStats
@ -108,11 +108,11 @@ class DockerInterface(CoreSysAttributes):
"Available space in /data is: %s GiB", "Available space in /data is: %s GiB",
free_space, free_space,
) )
raise DockerAPIError() from err raise DockerError() from err
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Unknown error with %s:%s -> %s", image, tag, err) _LOGGER.error("Unknown error with %s:%s -> %s", image, tag, err)
self.sys_capture_exception(err) self.sys_capture_exception(err)
raise DockerAPIError() from err raise DockerError() from err
else: else:
self._meta = docker_image.attrs self._meta = docker_image.attrs
@ -146,8 +146,10 @@ class DockerInterface(CoreSysAttributes):
docker_container = self.sys_docker.containers.get(self.name) docker_container = self.sys_docker.containers.get(self.name)
except docker.errors.NotFound: except docker.errors.NotFound:
return False return False
except (docker.errors.DockerException, requests.RequestException) as err: except docker.errors.DockerException as err:
raise DockerAPIError() from err raise DockerAPIError() from err
except requests.RequestException as err:
raise DockerRequestError() from err
return docker_container.status == "running" return docker_container.status == "running"
@ -170,7 +172,7 @@ class DockerInterface(CoreSysAttributes):
# Successfull? # Successfull?
if not self._meta: if not self._meta:
raise DockerAPIError() raise DockerError()
_LOGGER.info("Attach to %s with version %s", self.image, self.version) _LOGGER.info("Attach to %s with version %s", self.image, self.version)
@process_lock @process_lock
@ -200,7 +202,7 @@ class DockerInterface(CoreSysAttributes):
except docker.errors.NotFound: except docker.errors.NotFound:
return return
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
raise DockerAPIError() from err raise DockerError() from err
if docker_container.status == "running": if docker_container.status == "running":
_LOGGER.info("Stop %s application", self.name) _LOGGER.info("Stop %s application", self.name)
@ -226,14 +228,14 @@ class DockerInterface(CoreSysAttributes):
docker_container = self.sys_docker.containers.get(self.name) docker_container = self.sys_docker.containers.get(self.name)
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("%s not found for starting up", self.name) _LOGGER.error("%s not found for starting up", self.name)
raise DockerAPIError() from err raise DockerError() from err
_LOGGER.info("Start %s", self.name) _LOGGER.info("Start %s", self.name)
try: try:
docker_container.start() docker_container.start()
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Can't start %s: %s", self.name, err) _LOGGER.error("Can't start %s: %s", self.name, err)
raise DockerAPIError() from err raise DockerError() from err
@process_lock @process_lock
def remove(self) -> Awaitable[None]: def remove(self) -> Awaitable[None]:
@ -246,7 +248,7 @@ class DockerInterface(CoreSysAttributes):
Needs run inside executor. Needs run inside executor.
""" """
# Cleanup container # Cleanup container
with suppress(DockerAPIError): with suppress(DockerError):
self._stop() self._stop()
_LOGGER.info("Remove image %s with latest and %s", self.image, self.version) _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: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.warning("Can't remove image %s: %s", self.image, err) _LOGGER.warning("Can't remove image %s: %s", self.image, err)
raise DockerAPIError() from err raise DockerError() from err
self._meta = None self._meta = None
@ -290,7 +292,7 @@ class DockerInterface(CoreSysAttributes):
self._install(tag, image=image, latest=latest) self._install(tag, image=image, latest=latest)
# Stop container & cleanup # Stop container & cleanup
with suppress(DockerAPIError): with suppress(DockerError):
self._stop() self._stop()
def logs(self) -> Awaitable[bytes]: def logs(self) -> Awaitable[bytes]:
@ -331,14 +333,14 @@ class DockerInterface(CoreSysAttributes):
origin = self.sys_docker.images.get(f"{self.image}:{self.version}") origin = self.sys_docker.images.get(f"{self.image}:{self.version}")
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.warning("Can't find %s for cleanup", self.image) _LOGGER.warning("Can't find %s for cleanup", self.image)
raise DockerAPIError() from err raise DockerError() from err
# Cleanup Current # Cleanup Current
try: try:
images_list = self.sys_docker.images.list(name=self.image) images_list = self.sys_docker.images.list(name=self.image)
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.waring("Corrupt docker overlayfs found: %s", err) _LOGGER.waring("Corrupt docker overlayfs found: %s", err)
raise DockerAPIError() from err raise DockerError() from err
for image in images_list: for image in images_list:
if origin.id == image.id: if origin.id == image.id:
@ -356,7 +358,7 @@ class DockerInterface(CoreSysAttributes):
images_list = self.sys_docker.images.list(name=old_image) images_list = self.sys_docker.images.list(name=old_image)
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.waring("Corrupt docker overlayfs found: %s", err) _LOGGER.waring("Corrupt docker overlayfs found: %s", err)
raise DockerAPIError() from err raise DockerError() from err
for image in images_list: for image in images_list:
with suppress(docker.errors.DockerException, requests.RequestException): with suppress(docker.errors.DockerException, requests.RequestException):
@ -376,14 +378,14 @@ class DockerInterface(CoreSysAttributes):
try: try:
container = self.sys_docker.containers.get(self.name) container = self.sys_docker.containers.get(self.name)
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
raise DockerAPIError() from err raise DockerError() from err
_LOGGER.info("Restart %s", self.image) _LOGGER.info("Restart %s", self.image)
try: try:
container.restart(timeout=self.timeout) container.restart(timeout=self.timeout)
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.warning("Can't restart %s: %s", self.image, err) _LOGGER.warning("Can't restart %s: %s", self.image, err)
raise DockerAPIError() from err raise DockerError() from err
@process_lock @process_lock
def execute_command(self, command: str) -> Awaitable[CommandReturn]: def execute_command(self, command: str) -> Awaitable[CommandReturn]:
@ -409,14 +411,14 @@ class DockerInterface(CoreSysAttributes):
try: try:
docker_container = self.sys_docker.containers.get(self.name) docker_container = self.sys_docker.containers.get(self.name)
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
raise DockerAPIError() from err raise DockerError() from err
try: try:
stats = docker_container.stats(stream=False) stats = docker_container.stats(stream=False)
return DockerStats(stats) return DockerStats(stats)
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Can't read stats from %s: %s", self.name, 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]: def is_failed(self) -> Awaitable[bool]:
"""Return True if Docker is failing state. """Return True if Docker is failing state.
@ -435,7 +437,7 @@ class DockerInterface(CoreSysAttributes):
except docker.errors.NotFound: except docker.errors.NotFound:
return False return False
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
raise DockerAPIError() from err raise DockerError() from err
# container is not running # container is not running
if docker_container.status != "exited": if docker_container.status != "exited":
@ -469,7 +471,10 @@ class DockerInterface(CoreSysAttributes):
except (docker.errors.DockerException, ValueError) as err: except (docker.errors.DockerException, ValueError) as err:
_LOGGER.debug("No version found for %s", self.image) _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: else:
_LOGGER.debug("Found %s versions: %s", self.image, available_version) _LOGGER.debug("Found %s versions: %s", self.image, available_version)

View File

@ -8,7 +8,7 @@ import docker
import requests import requests
from ..const import DOCKER_NETWORK, DOCKER_NETWORK_MASK, DOCKER_NETWORK_RANGE 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__) _LOGGER: logging.Logger = logging.getLogger(__name__)
@ -113,7 +113,7 @@ class DockerNetwork:
self.network.connect(container, aliases=alias, ipv4_address=ipv4_address) self.network.connect(container, aliases=alias, ipv4_address=ipv4_address)
except docker.errors.APIError as err: except docker.errors.APIError as err:
_LOGGER.error("Can't link container to hassio-net: %s", err) _LOGGER.error("Can't link container to hassio-net: %s", err)
raise DockerAPIError() from err raise DockerError() from err
self.network.reload() self.network.reload()
@ -133,7 +133,7 @@ class DockerNetwork:
except docker.errors.APIError as err: except docker.errors.APIError as err:
_LOGGER.warning("Can't disconnect container from default: %s", 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): def stale_cleanup(self, container_name: str):
"""Remove force a container from Network. """Remove force a container from Network.

View File

@ -8,7 +8,7 @@ import docker
import requests import requests
from ..coresys import CoreSysAttributes from ..coresys import CoreSysAttributes
from ..exceptions import DockerAPIError from ..exceptions import DockerError
from .interface import DockerInterface from .interface import DockerInterface
_LOGGER: logging.Logger = logging.getLogger(__name__) _LOGGER: logging.Logger = logging.getLogger(__name__)
@ -40,7 +40,7 @@ class DockerSupervisor(DockerInterface, CoreSysAttributes):
try: try:
docker_container = self.sys_docker.containers.get(self.name) docker_container = self.sys_docker.containers.get(self.name)
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
raise DockerAPIError() from err raise DockerError() from err
self._meta = docker_container.attrs self._meta = docker_container.attrs
_LOGGER.info( _LOGGER.info(
@ -77,7 +77,7 @@ class DockerSupervisor(DockerInterface, CoreSysAttributes):
docker_container.image.tag(self.image, tag="latest") docker_container.image.tag(self.image, tag="latest")
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Can't retag supervisor version: %s", 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]: def update_start_tag(self, image: str, version: str) -> Awaitable[None]:
"""Update start tag to new version.""" """Update start tag to new version."""
@ -104,4 +104,4 @@ class DockerSupervisor(DockerInterface, CoreSysAttributes):
except (docker.errors.DockerException, requests.RequestException) as err: except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Can't fix start tag: %s", err) _LOGGER.error("Can't fix start tag: %s", err)
raise DockerAPIError() from err raise DockerError() from err

View File

@ -238,10 +238,22 @@ class JsonFileError(HassioError):
# docker/api # docker/api
class DockerAPIError(HassioError): class DockerError(HassioError):
"""Docker API/Transport errors."""
class DockerAPIError(DockerError):
"""Docker API error.""" """Docker API error."""
class DockerRequestError(DockerError):
"""Dockerd OS issues."""
class DockerNotFound(DockerError):
"""Docker object don't Exists."""
# Hardware # Hardware

View File

@ -15,7 +15,7 @@ from packaging import version as pkg_version
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..docker.homeassistant import DockerHomeAssistant from ..docker.homeassistant import DockerHomeAssistant
from ..docker.stats import DockerStats 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 from ..utils import convert_to_ascii, process_lock
_LOGGER: logging.Logger = logging.getLogger(__name__) _LOGGER: logging.Logger = logging.getLogger(__name__)
@ -58,7 +58,7 @@ class HomeAssistantCore(CoreSysAttributes):
) )
await self.instance.attach(tag=self.sys_homeassistant.version) await self.instance.attach(tag=self.sys_homeassistant.version)
except DockerAPIError: except DockerError:
_LOGGER.info( _LOGGER.info(
"No Home Assistant Docker image %s found.", self.sys_homeassistant.image "No Home Assistant Docker image %s found.", self.sys_homeassistant.image
) )
@ -85,7 +85,7 @@ class HomeAssistantCore(CoreSysAttributes):
await self.instance.install( await self.instance.install(
LANDINGPAGE, image=self.sys_updater.image_homeassistant LANDINGPAGE, image=self.sys_updater.image_homeassistant
) )
except DockerAPIError: except DockerError:
_LOGGER.warning("Fails install landingpage, retry after 30sec") _LOGGER.warning("Fails install landingpage, retry after 30sec")
await asyncio.sleep(30) await asyncio.sleep(30)
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except
@ -117,7 +117,7 @@ class HomeAssistantCore(CoreSysAttributes):
tag, image=self.sys_updater.image_homeassistant tag, image=self.sys_updater.image_homeassistant
) )
break break
except DockerAPIError: except DockerError:
pass pass
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except
self.sys_capture_exception(err) self.sys_capture_exception(err)
@ -138,7 +138,7 @@ class HomeAssistantCore(CoreSysAttributes):
_LOGGER.error("Can't start Home Assistant!") _LOGGER.error("Can't start Home Assistant!")
# Cleanup # Cleanup
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.cleanup() await self.instance.cleanup()
@process_lock @process_lock
@ -162,7 +162,7 @@ class HomeAssistantCore(CoreSysAttributes):
await self.instance.update( await self.instance.update(
to_version, image=self.sys_updater.image_homeassistant to_version, image=self.sys_updater.image_homeassistant
) )
except DockerAPIError as err: except DockerError as err:
_LOGGER.warning("Update Home Assistant image failed") _LOGGER.warning("Update Home Assistant image failed")
raise HomeAssistantUpdateError() from err raise HomeAssistantUpdateError() from err
else: else:
@ -175,7 +175,7 @@ class HomeAssistantCore(CoreSysAttributes):
# Successfull - last step # Successfull - last step
self.sys_homeassistant.save_data() self.sys_homeassistant.save_data()
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.cleanup(old_image=old_image) await self.instance.cleanup(old_image=old_image)
# Update Home Assistant # Update Home Assistant
@ -212,7 +212,7 @@ class HomeAssistantCore(CoreSysAttributes):
try: try:
await self.instance.run() await self.instance.run()
except DockerAPIError as err: except DockerError as err:
raise HomeAssistantError() from err raise HomeAssistantError() from err
await self._block_till_run(self.sys_homeassistant.version) await self._block_till_run(self.sys_homeassistant.version)
@ -228,7 +228,7 @@ class HomeAssistantCore(CoreSysAttributes):
if await self.instance.is_initialize(): if await self.instance.is_initialize():
try: try:
await self.instance.start() await self.instance.start()
except DockerAPIError as err: except DockerError as err:
raise HomeAssistantError() from err raise HomeAssistantError() from err
await self._block_till_run(self.sys_homeassistant.version) await self._block_till_run(self.sys_homeassistant.version)
@ -244,7 +244,7 @@ class HomeAssistantCore(CoreSysAttributes):
""" """
try: try:
return await self.instance.stop(remove_container=False) return await self.instance.stop(remove_container=False)
except DockerAPIError as err: except DockerError as err:
raise HomeAssistantError() from err raise HomeAssistantError() from err
@process_lock @process_lock
@ -252,7 +252,7 @@ class HomeAssistantCore(CoreSysAttributes):
"""Restart Home Assistant Docker.""" """Restart Home Assistant Docker."""
try: try:
await self.instance.restart() await self.instance.restart()
except DockerAPIError as err: except DockerError as err:
raise HomeAssistantError() from err raise HomeAssistantError() from err
await self._block_till_run(self.sys_homeassistant.version) await self._block_till_run(self.sys_homeassistant.version)
@ -260,7 +260,7 @@ class HomeAssistantCore(CoreSysAttributes):
@process_lock @process_lock
async def rebuild(self) -> None: async def rebuild(self) -> None:
"""Rebuild Home Assistant Docker container.""" """Rebuild Home Assistant Docker container."""
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.stop() await self.instance.stop()
await self._start() await self._start()
@ -278,7 +278,7 @@ class HomeAssistantCore(CoreSysAttributes):
""" """
try: try:
return await self.instance.stats() return await self.instance.stats()
except DockerAPIError as err: except DockerError as err:
raise HomeAssistantError() from err raise HomeAssistantError() from err
def is_running(self) -> Awaitable[bool]: def is_running(self) -> Awaitable[bool]:
@ -407,5 +407,5 @@ class HomeAssistantCore(CoreSysAttributes):
# Pull image # Pull image
try: try:
await self.instance.install(self.sys_homeassistant.version) await self.instance.install(self.sys_homeassistant.version)
except DockerAPIError: except DockerError:
_LOGGER.error("Repairing of Home Assistant failed") _LOGGER.error("Repairing of Home Assistant failed")

View File

@ -15,7 +15,7 @@ from ..const import ATTR_IMAGE, ATTR_VERSION
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..docker.audio import DockerAudio from ..docker.audio import DockerAudio
from ..docker.stats import DockerStats from ..docker.stats import DockerStats
from ..exceptions import AudioError, AudioUpdateError, DockerAPIError from ..exceptions import AudioError, AudioUpdateError, DockerError
from ..utils.json import JsonConfig from ..utils.json import JsonConfig
from .const import FILE_HASSIO_AUDIO from .const import FILE_HASSIO_AUDIO
from .validate import SCHEMA_AUDIO_CONFIG from .validate import SCHEMA_AUDIO_CONFIG
@ -92,7 +92,7 @@ class Audio(JsonConfig, CoreSysAttributes):
self.version = await self.instance.get_latest_version() self.version = await self.instance.get_latest_version()
await self.instance.attach(tag=self.version) await self.instance.attach(tag=self.version)
except DockerAPIError: except DockerError:
_LOGGER.info("No Audio plugin Docker image %s found.", self.instance.image) _LOGGER.info("No Audio plugin Docker image %s found.", self.instance.image)
# Install PulseAudio # Install PulseAudio
@ -131,7 +131,7 @@ class Audio(JsonConfig, CoreSysAttributes):
await self.sys_updater.reload() await self.sys_updater.reload()
if self.latest_version: if self.latest_version:
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.install( await self.instance.install(
self.latest_version, image=self.sys_updater.image_audio self.latest_version, image=self.sys_updater.image_audio
) )
@ -155,7 +155,7 @@ class Audio(JsonConfig, CoreSysAttributes):
try: try:
await self.instance.update(version, image=self.sys_updater.image_audio) await self.instance.update(version, image=self.sys_updater.image_audio)
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Audio update failed") _LOGGER.error("Audio update failed")
raise AudioUpdateError() from err raise AudioUpdateError() from err
else: else:
@ -164,7 +164,7 @@ class Audio(JsonConfig, CoreSysAttributes):
self.save_data() self.save_data()
# Cleanup # Cleanup
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.cleanup(old_image=old_image) await self.instance.cleanup(old_image=old_image)
# Start Audio # Start Audio
@ -175,7 +175,7 @@ class Audio(JsonConfig, CoreSysAttributes):
_LOGGER.info("Restart Audio plugin") _LOGGER.info("Restart Audio plugin")
try: try:
await self.instance.restart() await self.instance.restart()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't start Audio plugin") _LOGGER.error("Can't start Audio plugin")
raise AudioError() from err raise AudioError() from err
@ -184,7 +184,7 @@ class Audio(JsonConfig, CoreSysAttributes):
_LOGGER.info("Start Audio plugin") _LOGGER.info("Start Audio plugin")
try: try:
await self.instance.run() await self.instance.run()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't start Audio plugin") _LOGGER.error("Can't start Audio plugin")
raise AudioError() from err raise AudioError() from err
@ -193,7 +193,7 @@ class Audio(JsonConfig, CoreSysAttributes):
_LOGGER.info("Stop Audio plugin") _LOGGER.info("Stop Audio plugin")
try: try:
await self.instance.stop() await self.instance.stop()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't stop Audio plugin") _LOGGER.error("Can't stop Audio plugin")
raise AudioError() from err raise AudioError() from err
@ -208,7 +208,7 @@ class Audio(JsonConfig, CoreSysAttributes):
"""Return stats of CoreDNS.""" """Return stats of CoreDNS."""
try: try:
return await self.instance.stats() return await self.instance.stats()
except DockerAPIError as err: except DockerError as err:
raise AudioError() from err raise AudioError() from err
def is_running(self) -> Awaitable[bool]: def is_running(self) -> Awaitable[bool]:
@ -226,7 +226,7 @@ class Audio(JsonConfig, CoreSysAttributes):
_LOGGER.info("Repair Audio %s", self.version) _LOGGER.info("Repair Audio %s", self.version)
try: try:
await self.instance.install(self.version) await self.instance.install(self.version)
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Repairing of Audio failed") _LOGGER.error("Repairing of Audio failed")
self.sys_capture_exception(err) self.sys_capture_exception(err)

View File

@ -12,7 +12,7 @@ from ..const import ATTR_ACCESS_TOKEN, ATTR_IMAGE, ATTR_VERSION
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..docker.cli import DockerCli from ..docker.cli import DockerCli
from ..docker.stats import DockerStats from ..docker.stats import DockerStats
from ..exceptions import CliError, CliUpdateError, DockerAPIError from ..exceptions import CliError, CliUpdateError, DockerError
from ..utils.json import JsonConfig from ..utils.json import JsonConfig
from .const import FILE_HASSIO_CLI from .const import FILE_HASSIO_CLI
from .validate import SCHEMA_CLI_CONFIG from .validate import SCHEMA_CLI_CONFIG
@ -80,7 +80,7 @@ class HaCli(CoreSysAttributes, JsonConfig):
self.version = await self.instance.get_latest_version() self.version = await self.instance.get_latest_version()
await self.instance.attach(tag=self.version) await self.instance.attach(tag=self.version)
except DockerAPIError: except DockerError:
_LOGGER.info("No cli plugin Docker image %s found.", self.instance.image) _LOGGER.info("No cli plugin Docker image %s found.", self.instance.image)
# Install cli # Install cli
@ -105,7 +105,7 @@ class HaCli(CoreSysAttributes, JsonConfig):
await self.sys_updater.reload() await self.sys_updater.reload()
if self.latest_version: if self.latest_version:
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.install( await self.instance.install(
self.latest_version, self.latest_version,
image=self.sys_updater.image_cli, image=self.sys_updater.image_cli,
@ -133,7 +133,7 @@ class HaCli(CoreSysAttributes, JsonConfig):
await self.instance.update( await self.instance.update(
version, image=self.sys_updater.image_cli, latest=True version, image=self.sys_updater.image_cli, latest=True
) )
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("HA cli update failed") _LOGGER.error("HA cli update failed")
raise CliUpdateError() from err raise CliUpdateError() from err
else: else:
@ -142,7 +142,7 @@ class HaCli(CoreSysAttributes, JsonConfig):
self.save_data() self.save_data()
# Cleanup # Cleanup
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.cleanup(old_image=old_image) await self.instance.cleanup(old_image=old_image)
# Start cli # Start cli
@ -158,7 +158,7 @@ class HaCli(CoreSysAttributes, JsonConfig):
_LOGGER.info("Start cli plugin") _LOGGER.info("Start cli plugin")
try: try:
await self.instance.run() await self.instance.run()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't start cli plugin") _LOGGER.error("Can't start cli plugin")
raise CliError() from err raise CliError() from err
@ -167,7 +167,7 @@ class HaCli(CoreSysAttributes, JsonConfig):
_LOGGER.info("Stop cli plugin") _LOGGER.info("Stop cli plugin")
try: try:
await self.instance.stop() await self.instance.stop()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't stop cli plugin") _LOGGER.error("Can't stop cli plugin")
raise CliError() from err raise CliError() from err
@ -175,7 +175,7 @@ class HaCli(CoreSysAttributes, JsonConfig):
"""Return stats of cli.""" """Return stats of cli."""
try: try:
return await self.instance.stats() return await self.instance.stats()
except DockerAPIError as err: except DockerError as err:
raise CliError() from err raise CliError() from err
def is_running(self) -> Awaitable[bool]: def is_running(self) -> Awaitable[bool]:
@ -193,6 +193,6 @@ class HaCli(CoreSysAttributes, JsonConfig):
_LOGGER.info("Repair HA cli %s", self.version) _LOGGER.info("Repair HA cli %s", self.version)
try: try:
await self.instance.install(self.version, latest=True) await self.instance.install(self.version, latest=True)
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Repairing of HA cli failed") _LOGGER.error("Repairing of HA cli failed")
self.sys_capture_exception(err) self.sys_capture_exception(err)

View File

@ -17,7 +17,7 @@ from ..const import ATTR_IMAGE, ATTR_SERVERS, ATTR_VERSION, DNS_SUFFIX, LogLevel
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..docker.dns import DockerDNS from ..docker.dns import DockerDNS
from ..docker.stats import DockerStats from ..docker.stats import DockerStats
from ..exceptions import CoreDNSError, CoreDNSUpdateError, DockerAPIError from ..exceptions import CoreDNSError, CoreDNSUpdateError, DockerError
from ..utils.json import JsonConfig from ..utils.json import JsonConfig
from ..validate import dns_url from ..validate import dns_url
from .const import FILE_HASSIO_DNS from .const import FILE_HASSIO_DNS
@ -120,7 +120,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
self.version = await self.instance.get_latest_version() self.version = await self.instance.get_latest_version()
await self.instance.attach(tag=self.version) await self.instance.attach(tag=self.version)
except DockerAPIError: except DockerError:
_LOGGER.info( _LOGGER.info(
"No CoreDNS plugin Docker image %s found.", self.instance.image "No CoreDNS plugin Docker image %s found.", self.instance.image
) )
@ -162,7 +162,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
await self.sys_updater.reload() await self.sys_updater.reload()
if self.latest_version: if self.latest_version:
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.install( await self.instance.install(
self.latest_version, image=self.sys_updater.image_dns self.latest_version, image=self.sys_updater.image_dns
) )
@ -190,7 +190,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
# Update # Update
try: try:
await self.instance.update(version, image=self.sys_updater.image_dns) await self.instance.update(version, image=self.sys_updater.image_dns)
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("CoreDNS update failed") _LOGGER.error("CoreDNS update failed")
raise CoreDNSUpdateError() from err raise CoreDNSUpdateError() from err
else: else:
@ -199,7 +199,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
self.save_data() self.save_data()
# Cleanup # Cleanup
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.cleanup(old_image=old_image) await self.instance.cleanup(old_image=old_image)
# Start CoreDNS # Start CoreDNS
@ -211,7 +211,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
_LOGGER.info("Restart CoreDNS plugin") _LOGGER.info("Restart CoreDNS plugin")
try: try:
await self.instance.restart() await self.instance.restart()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't start CoreDNS plugin") _LOGGER.error("Can't start CoreDNS plugin")
raise CoreDNSError() from err raise CoreDNSError() from err
@ -223,7 +223,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
_LOGGER.info("Start CoreDNS plugin") _LOGGER.info("Start CoreDNS plugin")
try: try:
await self.instance.run() await self.instance.run()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't start CoreDNS plugin") _LOGGER.error("Can't start CoreDNS plugin")
raise CoreDNSError() from err raise CoreDNSError() from err
@ -232,7 +232,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
_LOGGER.info("Stop CoreDNS plugin") _LOGGER.info("Stop CoreDNS plugin")
try: try:
await self.instance.stop() await self.instance.stop()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't stop CoreDNS plugin") _LOGGER.error("Can't stop CoreDNS plugin")
raise CoreDNSError() from err raise CoreDNSError() from err
@ -389,7 +389,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
"""Return stats of CoreDNS.""" """Return stats of CoreDNS."""
try: try:
return await self.instance.stats() return await self.instance.stats()
except DockerAPIError as err: except DockerError as err:
raise CoreDNSError() from err raise CoreDNSError() from err
def is_running(self) -> Awaitable[bool]: def is_running(self) -> Awaitable[bool]:
@ -414,7 +414,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
_LOGGER.info("Repair CoreDNS %s", self.version) _LOGGER.info("Repair CoreDNS %s", self.version)
try: try:
await self.instance.install(self.version) await self.instance.install(self.version)
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Repairing of CoreDNS failed") _LOGGER.error("Repairing of CoreDNS failed")
self.sys_capture_exception(err) self.sys_capture_exception(err)

View File

@ -11,7 +11,7 @@ from ..const import ATTR_IMAGE, ATTR_VERSION
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..docker.multicast import DockerMulticast from ..docker.multicast import DockerMulticast
from ..docker.stats import DockerStats from ..docker.stats import DockerStats
from ..exceptions import DockerAPIError, MulticastError, MulticastUpdateError from ..exceptions import DockerError, MulticastError, MulticastUpdateError
from ..utils.json import JsonConfig from ..utils.json import JsonConfig
from .const import FILE_HASSIO_MULTICAST from .const import FILE_HASSIO_MULTICAST
from .validate import SCHEMA_MULTICAST_CONFIG from .validate import SCHEMA_MULTICAST_CONFIG
@ -74,7 +74,7 @@ class Multicast(JsonConfig, CoreSysAttributes):
self.version = await self.instance.get_latest_version() self.version = await self.instance.get_latest_version()
await self.instance.attach(tag=self.version) await self.instance.attach(tag=self.version)
except DockerAPIError: except DockerError:
_LOGGER.info( _LOGGER.info(
"No Multicast plugin Docker image %s found.", self.instance.image "No Multicast plugin Docker image %s found.", self.instance.image
) )
@ -103,7 +103,7 @@ class Multicast(JsonConfig, CoreSysAttributes):
await self.sys_updater.reload() await self.sys_updater.reload()
if self.latest_version: if self.latest_version:
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.install( await self.instance.install(
self.latest_version, image=self.sys_updater.image_multicast self.latest_version, image=self.sys_updater.image_multicast
) )
@ -128,7 +128,7 @@ class Multicast(JsonConfig, CoreSysAttributes):
# Update # Update
try: try:
await self.instance.update(version, image=self.sys_updater.image_multicast) await self.instance.update(version, image=self.sys_updater.image_multicast)
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Multicast update failed") _LOGGER.error("Multicast update failed")
raise MulticastUpdateError() from err raise MulticastUpdateError() from err
else: else:
@ -137,7 +137,7 @@ class Multicast(JsonConfig, CoreSysAttributes):
self.save_data() self.save_data()
# Cleanup # Cleanup
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.cleanup(old_image=old_image) await self.instance.cleanup(old_image=old_image)
# Start Multicast plugin # Start Multicast plugin
@ -148,7 +148,7 @@ class Multicast(JsonConfig, CoreSysAttributes):
_LOGGER.info("Restart Multicast plugin") _LOGGER.info("Restart Multicast plugin")
try: try:
await self.instance.restart() await self.instance.restart()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't start Multicast plugin") _LOGGER.error("Can't start Multicast plugin")
raise MulticastError() from err raise MulticastError() from err
@ -157,7 +157,7 @@ class Multicast(JsonConfig, CoreSysAttributes):
_LOGGER.info("Start Multicast plugin") _LOGGER.info("Start Multicast plugin")
try: try:
await self.instance.run() await self.instance.run()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't start Multicast plugin") _LOGGER.error("Can't start Multicast plugin")
raise MulticastError() from err raise MulticastError() from err
@ -166,7 +166,7 @@ class Multicast(JsonConfig, CoreSysAttributes):
_LOGGER.info("Stop Multicast plugin") _LOGGER.info("Stop Multicast plugin")
try: try:
await self.instance.stop() await self.instance.stop()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't stop Multicast plugin") _LOGGER.error("Can't stop Multicast plugin")
raise MulticastError() from err raise MulticastError() from err
@ -181,7 +181,7 @@ class Multicast(JsonConfig, CoreSysAttributes):
"""Return stats of Multicast.""" """Return stats of Multicast."""
try: try:
return await self.instance.stats() return await self.instance.stats()
except DockerAPIError as err: except DockerError as err:
raise MulticastError() from err raise MulticastError() from err
def is_running(self) -> Awaitable[bool]: def is_running(self) -> Awaitable[bool]:
@ -206,6 +206,6 @@ class Multicast(JsonConfig, CoreSysAttributes):
_LOGGER.info("Repair Multicast %s", self.version) _LOGGER.info("Repair Multicast %s", self.version)
try: try:
await self.instance.install(self.version) await self.instance.install(self.version)
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Repairing of Multicast failed") _LOGGER.error("Repairing of Multicast failed")
self.sys_capture_exception(err) self.sys_capture_exception(err)

View File

@ -12,7 +12,7 @@ from ..const import ATTR_ACCESS_TOKEN, ATTR_IMAGE, ATTR_VERSION
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..docker.observer import DockerObserver from ..docker.observer import DockerObserver
from ..docker.stats import DockerStats from ..docker.stats import DockerStats
from ..exceptions import DockerAPIError, ObserverError, ObserverUpdateError from ..exceptions import DockerError, ObserverError, ObserverUpdateError
from ..utils.json import JsonConfig from ..utils.json import JsonConfig
from .const import FILE_HASSIO_OBSERVER from .const import FILE_HASSIO_OBSERVER
from .validate import SCHEMA_OBSERVER_CONFIG from .validate import SCHEMA_OBSERVER_CONFIG
@ -80,7 +80,7 @@ class Observer(CoreSysAttributes, JsonConfig):
self.version = await self.instance.get_latest_version() self.version = await self.instance.get_latest_version()
await self.instance.attach(tag=self.version) await self.instance.attach(tag=self.version)
except DockerAPIError: except DockerError:
_LOGGER.info( _LOGGER.info(
"No observer plugin Docker image %s found.", self.instance.image "No observer plugin Docker image %s found.", self.instance.image
) )
@ -107,7 +107,7 @@ class Observer(CoreSysAttributes, JsonConfig):
await self.sys_updater.reload() await self.sys_updater.reload()
if self.latest_version: if self.latest_version:
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.install( await self.instance.install(
self.latest_version, image=self.sys_updater.image_observer self.latest_version, image=self.sys_updater.image_observer
) )
@ -131,7 +131,7 @@ class Observer(CoreSysAttributes, JsonConfig):
try: try:
await self.instance.update(version, image=self.sys_updater.image_observer) 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") _LOGGER.error("HA observer update failed")
raise ObserverUpdateError() from err raise ObserverUpdateError() from err
else: else:
@ -140,7 +140,7 @@ class Observer(CoreSysAttributes, JsonConfig):
self.save_data() self.save_data()
# Cleanup # Cleanup
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.cleanup(old_image=old_image) await self.instance.cleanup(old_image=old_image)
# Start observer # Start observer
@ -157,7 +157,7 @@ class Observer(CoreSysAttributes, JsonConfig):
_LOGGER.info("Start observer plugin") _LOGGER.info("Start observer plugin")
try: try:
await self.instance.run() await self.instance.run()
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Can't start observer plugin") _LOGGER.error("Can't start observer plugin")
raise ObserverError() from err raise ObserverError() from err
@ -165,7 +165,7 @@ class Observer(CoreSysAttributes, JsonConfig):
"""Return stats of observer.""" """Return stats of observer."""
try: try:
return await self.instance.stats() return await self.instance.stats()
except DockerAPIError as err: except DockerError as err:
raise ObserverError() from err raise ObserverError() from err
def is_running(self) -> Awaitable[bool]: def is_running(self) -> Awaitable[bool]:
@ -183,6 +183,6 @@ class Observer(CoreSysAttributes, JsonConfig):
_LOGGER.info("Repair HA observer %s", self.version) _LOGGER.info("Repair HA observer %s", self.version)
try: try:
await self.instance.install(self.version) await self.instance.install(self.version)
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Repairing of HA observer failed") _LOGGER.error("Repairing of HA observer failed")
self.sys_capture_exception(err) self.sys_capture_exception(err)

View File

@ -14,7 +14,7 @@ from .coresys import CoreSys, CoreSysAttributes
from .docker.stats import DockerStats from .docker.stats import DockerStats
from .docker.supervisor import DockerSupervisor from .docker.supervisor import DockerSupervisor
from .exceptions import ( from .exceptions import (
DockerAPIError, DockerError,
HostAppArmorError, HostAppArmorError,
SupervisorError, SupervisorError,
SupervisorUpdateError, SupervisorUpdateError,
@ -35,10 +35,10 @@ class Supervisor(CoreSysAttributes):
"""Prepare Home Assistant object.""" """Prepare Home Assistant object."""
try: try:
await self.instance.attach(tag="latest") await self.instance.attach(tag="latest")
except DockerAPIError: except DockerError:
_LOGGER.critical("Can't setup Supervisor Docker container!") _LOGGER.critical("Can't setup Supervisor Docker container!")
with suppress(DockerAPIError): with suppress(DockerError):
await self.instance.cleanup() await self.instance.cleanup()
@property @property
@ -115,7 +115,7 @@ class Supervisor(CoreSysAttributes):
await self.instance.update_start_tag( await self.instance.update_start_tag(
self.sys_updater.image_supervisor, version self.sys_updater.image_supervisor, version
) )
except DockerAPIError as err: except DockerError as err:
_LOGGER.error("Update of Supervisor failed!") _LOGGER.error("Update of Supervisor failed!")
raise SupervisorUpdateError() from err raise SupervisorUpdateError() from err
else: else:
@ -142,7 +142,7 @@ class Supervisor(CoreSysAttributes):
"""Return stats of Supervisor.""" """Return stats of Supervisor."""
try: try:
return await self.instance.stats() return await self.instance.stats()
except DockerAPIError as err: except DockerError as err:
raise SupervisorError() from err raise SupervisorError() from err
async def repair(self): async def repair(self):
@ -153,5 +153,5 @@ class Supervisor(CoreSysAttributes):
_LOGGER.info("Repair Supervisor %s", self.version) _LOGGER.info("Repair Supervisor %s", self.version)
try: try:
await self.instance.retag() await self.instance.retag()
except DockerAPIError: except DockerError:
_LOGGER.error("Repairing of Supervisor failed") _LOGGER.error("Repairing of Supervisor failed")