diff --git a/hassio/addons/__init__.py b/hassio/addons/__init__.py index a14a514b5..5fd0e332b 100644 --- a/hassio/addons/__init__.py +++ b/hassio/addons/__init__.py @@ -40,6 +40,15 @@ class AddonManager(AddonsData): return self.read_addons_repo() + # remove stalled addons + tasks = [] + for addon in self.list_removed: + _LOGGER.info("Old addon %s found") + tasks.append(self.loop.create_task(self.dockers[addon].remove())) + + if tasks: + await asyncio.wait(tasks, loop=self.loop) + async def auto_boot(self, start_type): """Boot addons with mode auto.""" boot_list = self.list_startup(start_type) @@ -48,18 +57,18 @@ class AddonManager(AddonsData): for addon in boot_list: tasks.append(self.loop.create_task(self.start_addon(addon))) - _LOGGER.info("Startup %s run %d addons.", start_type, len(tasks)) + _LOGGER.info("Startup %s run %d addons", start_type, len(tasks)) if tasks: await asyncio.wait(tasks, loop=self.loop) async def install_addon(self, addon, version=None): """Install a addon.""" if not self.exists_addon(addon): - _LOGGER.error("Addon %s not exists for install.", addon) + _LOGGER.error("Addon %s not exists for install", addon) return False if self.is_installed(addon): - _LOGGER.error("Addon %s is already installed.", addon) + _LOGGER.error("Addon %s is already installed", addon) return False if not os.path.isdir(self.path_data(addon)): @@ -81,11 +90,11 @@ class AddonManager(AddonsData): async def uninstall_addon(self, addon): """Remove a addon.""" if not self.is_installed(addon): - _LOGGER.error("Addon %s is already uninstalled.", addon) + _LOGGER.error("Addon %s is already uninstalled", addon) return False if addon not in self.dockers: - _LOGGER.error("No docker found for addon %s.", addon) + _LOGGER.error("No docker found for addon %s", addon) return False if not await self.dockers[addon].remove(): @@ -103,7 +112,7 @@ class AddonManager(AddonsData): async def state_addon(self, addon): """Return running state of addon.""" if addon not in self.dockers: - _LOGGER.error("No docker found for addon %s.", addon) + _LOGGER.error("No docker found for addon %s", addon) return if await self.dockers[addon].is_running(): @@ -113,11 +122,11 @@ class AddonManager(AddonsData): async def start_addon(self, addon): """Set options and start addon.""" if addon not in self.dockers: - _LOGGER.error("No docker found for addon %s.", addon) + _LOGGER.error("No docker found for addon %s", addon) return False if not self.write_addon_options(addon): - _LOGGER.error("Can't write options for addon %s.", addon) + _LOGGER.error("Can't write options for addon %s", addon) return False return await self.dockers[addon].run(): @@ -125,7 +134,7 @@ class AddonManager(AddonsData): async def stop_addon(self, addon): """Stop addon.""" if addon not in self.dockers: - _LOGGER.error("No docker found for addon %s.", addon) + _LOGGER.error("No docker found for addon %s", addon) return False return await self.dockers[addon].stop(): @@ -133,11 +142,11 @@ class AddonManager(AddonsData): async def update_addon(self, addon, version=None): """Update addon.""" if self.is_installed(addon): - _LOGGER.error("Addon %s is not installed.", addon) + _LOGGER.error("Addon %s is not installed", addon) return False if addon not in self.dockers: - _LOGGER.error("No docker found for addon %s.", addon) + _LOGGER.error("No docker found for addon %s", addon) return False version = version or self.get_version(addon) diff --git a/hassio/addons/data.py b/hassio/addons/data.py index e15c84a35..aed6d02f1 100644 --- a/hassio/addons/data.py +++ b/hassio/addons/data.py @@ -67,7 +67,7 @@ class AddonsData(Config): _LOGGER.warning("Can't read %s", addon) except vol.Invalid as ex: - _LOGGER.warning("Can't read %s -> %s.", addon, + _LOGGER.warning("Can't read %s -> %s", addon, humanize_error(addon_config, ex)) @property @@ -106,10 +106,21 @@ class AddonsData(Config): if self._addons_data[addon][ATTR_STARTUP] == start_type: addon_list.add(addon) except KeyError: + _LOGGER.warning("Orphaned addon detect %s", addon) continue return addon_list + @property + def list_removed(self): + """Return local addons they not support from repo.""" + addon_list = set() + for addon in self._data.keys(): + if addon not in self._addons_data: + addon_list.add(addon) + + return addon_list + def exists_addon(self, addon): """Return True if a addon exists.""" return addon in self._addons_data diff --git a/hassio/api/addons.py b/hassio/api/addons.py index 28a9d9c5e..748b1639f 100644 --- a/hassio/api/addons.py +++ b/hassio/api/addons.py @@ -31,9 +31,9 @@ class APIAddons(object): # check data if not self.addons.exists_addon(addon): - raise RuntimeError("Addon not exists.") + raise RuntimeError("Addon not exists") if check_installed and not self.addons.is_installed(addon): - raise RuntimeError("Addon is not installed.") + raise RuntimeError("Addon is not installed") return addon @@ -86,7 +86,7 @@ class APIAddons(object): addon = self._extract_addon(request) if await self.addons.state_addon(addon) == STATE_STARTED: - raise RuntimeError("Addon is already running.") + raise RuntimeError("Addon is already running") return await asyncio.shield( self.addons.addon_start(addon), loop=self.loop) @@ -97,7 +97,7 @@ class APIAddons(object): addon = self._extract_addon(request) if await self.addons.state_addon(addon) == STATE_STOPPED: - raise RuntimeError("Addon is already stoped.") + raise RuntimeError("Addon is already stoped") return await asyncio.shield( self.addons.addon_stop(addon), loop=self.loop) @@ -111,7 +111,7 @@ class APIAddons(object): ATTR_VERSION, self.addons.get_version(addon)) if version == self.addons.version_installed(addon): - raise RuntimeError("Version is already in use.") + raise RuntimeError("Version is already in use") return await asyncio.shield( self.addons.addon_update(addon, version), loop=self.loop) diff --git a/hassio/api/homeassistant.py b/hassio/api/homeassistant.py index a36ba5f0d..6a81e66f6 100644 --- a/hassio/api/homeassistant.py +++ b/hassio/api/homeassistant.py @@ -40,10 +40,10 @@ class APIHomeAssistant(object): version = body.get(ATTR_VERSION, self.config.current_homeassistant) if self.dock_hass.in_progress: - raise RuntimeError("Other task is in progress.") + raise RuntimeError("Other task is in progress") if version == self.dock_hass.version: - raise RuntimeError("%s is already in use.", version) + raise RuntimeError("Version is already in use") return await asyncio.shield( self.dock_hass.update(version), loop=self.loop) diff --git a/hassio/api/host.py b/hassio/api/host.py index 23f0fb453..c799a42cf 100644 --- a/hassio/api/host.py +++ b/hassio/api/host.py @@ -56,6 +56,6 @@ class APIHost(object): version = body.get(ATTR_VERSION) if version == self.host_controll.version: - raise RuntimeError("%s is already in use.", version) + raise RuntimeError("Version is already in use") return await self.host_controll.host_update(version=version) diff --git a/hassio/api/supervisor.py b/hassio/api/supervisor.py index 109ff76ec..9ce407d71 100644 --- a/hassio/api/supervisor.py +++ b/hassio/api/supervisor.py @@ -62,6 +62,6 @@ class APISupervisor(object): version = body.get(ATTR_VERSION, self.config.current_hassio) if version == HASSIO_VERSION: - raise RuntimeError("%s is already in use.", version) + raise RuntimeError("Version is already in use") return await self.host_controll.supervisor_update(version=version) diff --git a/hassio/core.py b/hassio/core.py index 62fcffb02..d1b0bf8c3 100644 --- a/hassio/core.py +++ b/hassio/core.py @@ -88,6 +88,11 @@ class HassIO(object): # start api await self.api.start() + # HomeAssistant is already running / supervisor have only reboot + if await self.homeassistant.is_running(): + _LOGGER.info("HassIO reboot detected") + return + # start addon mark as before await self.addons.auto_boot(STARTUP_BEFORE) diff --git a/hassio/dock/__init__.py b/hassio/dock/__init__.py index bfb53df21..cb3630a7c 100644 --- a/hassio/dock/__init__.py +++ b/hassio/dock/__init__.py @@ -53,7 +53,7 @@ class DockerBase(object): image.tag(self.image, tag='latest') self.version = get_version_from_env(image.attrs['Config']['Env']) - _LOGGER.info("Tag image %s with version %s as latest.", + _LOGGER.info("Tag image %s with version %s as latest", self.image, self.version) except docker.errors.APIError as err: _LOGGER.error("Can't install %s:%s -> %s.", self.image, tag, err) @@ -122,7 +122,7 @@ class DockerBase(object): self.image = self.container.attrs['Config']['Image'] self.version = get_version_from_env( self.container.attrs['Config']['Env']) - _LOGGER.info("Attach to image %s with version %s.", + _LOGGER.info("Attach to image %s with version %s", self.image, self.version) except (docker.errors.DockerException, KeyError): _LOGGER.fatal( @@ -138,7 +138,7 @@ class DockerBase(object): return False async with self._lock: - _LOGGER.info("Run docker image %s with version %s.", + _LOGGER.info("Run docker image %s with version %s", self.image, self.version) return await self.loop.run_in_executor(None, self._run) @@ -191,14 +191,14 @@ class DockerBase(object): Need run inside executor. """ - if self.container: + if self._is_running(): self._stop() image = "{}:latest".format(self.image) try: self.dock.images.remove(image=image, force=True) except docker.errors.DockerException as err: - _LOGGER.warning("Can't remove image %s -> %s.", image, err) + _LOGGER.warning("Can't remove image %s -> %s", image, err) return False return True @@ -220,10 +220,10 @@ class DockerBase(object): Need run inside executor. """ - old_image = "{}:{}".format(self.image, self.version) old_run = self._is_running() + old_image = "{}:{}".format(self.image, self.version) - _LOGGER.info("Update docker %s with %s:%s.", + _LOGGER.info("Update docker %s with %s:%s", old_image, self.image, tag) # update docker image @@ -234,7 +234,7 @@ class DockerBase(object): self.dock.images.remove(image=old_image, force=True) except docker.errors.DockerException as err: _LOGGER.warning( - "Can't remove old image %s -> %s.", old_image, err) + "Can't remove old image %s -> %s", old_image, err) # restore if old_run: self._run() diff --git a/hassio/dock/addon.py b/hassio/dock/addon.py index 07ffb3fbe..3afeb2889 100644 --- a/hassio/dock/addon.py +++ b/hassio/dock/addon.py @@ -70,7 +70,7 @@ class DockerAddon(DockerBase): self.version = get_version_from_env( self.container.attrs['Config']['Env']) except docker.errors.DockerException as err: - _LOGGER.error("Can't run %s -> %s.", self.image, err) + _LOGGER.error("Can't run %s -> %s", self.image, err) return False return True diff --git a/hassio/dock/homeassistant.py b/hassio/dock/homeassistant.py index 5bcbcac84..b9f0c829f 100644 --- a/hassio/dock/homeassistant.py +++ b/hassio/dock/homeassistant.py @@ -60,7 +60,7 @@ class DockerHomeAssistant(DockerBase): self.version = get_version_from_env( self.container.attrs['Config']['Env']) except docker.errors.DockerException as err: - _LOGGER.error("Can't run %s -> %s.", self.image, err) + _LOGGER.error("Can't run %s -> %s", self.image, err) return False return True