some cleanups / auto remove old addons.

This commit is contained in:
pvizeli 2017-04-13 16:15:50 +02:00 committed by Pascal Vizeli
parent dbc080c24d
commit 40e5e6eb9d
10 changed files with 56 additions and 31 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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