Finish new homeassistant handling

This commit is contained in:
pvizeli 2017-07-11 16:19:24 +02:00
parent 02c8baef68
commit 906c4e03fb
8 changed files with 113 additions and 50 deletions

8
API.md
View File

@ -269,7 +269,9 @@ Optional:
{
"version": "INSTALL_VERSION",
"last_version": "LAST_VERSION",
"devices": []
"devices": [""],
"image": "str",
"custom": "bool -> if custom image"
}
```
@ -291,9 +293,13 @@ Output the raw docker log
```json
{
"devices": [],
"image": "Optional|null",
"last_version": "Optional for custom image|null"
}
```
Image with `null` and last_version with `null` reset this options.
### REST API addons
- POST `/addons/reload`

View File

@ -5,7 +5,8 @@ import logging
import voluptuous as vol
from .util import api_process, api_process_raw, api_validate
from ..const import ATTR_VERSION, ATTR_LAST_VERSION, ATTR_DEVICES
from ..const import (
ATTR_VERSION, ATTR_LAST_VERSION, ATTR_DEVICES, ATTR_IMAGE, ATTR_CUSTOM)
from ..validate import HASS_DEVICES
_LOGGER = logging.getLogger(__name__)
@ -13,6 +14,9 @@ _LOGGER = logging.getLogger(__name__)
SCHEMA_OPTIONS = vol.Schema({
vol.Optional(ATTR_DEVICES): HASS_DEVICES,
vol.Inclusive(ATTR_IMAGE, 'custom_hass'): vol.Any(None, vol.Coerce(str)),
vol.Inclusive(ATTR_LAST_VERSION, 'custom_hass'):
vol.Any(None, vol.Coerce(str)),
})
SCHEMA_VERSION = vol.Schema({
@ -34,8 +38,10 @@ class APIHomeAssistant(object):
"""Return host information."""
return {
ATTR_VERSION: self.homeassistant.version,
ATTR_LAST_VERSION: self.config.last_homeassistant,
ATTR_DEVICES: self.config.homeassistant_devices,
ATTR_LAST_VERSION: self.homeassistant.last_version,
ATTR_IMAGE: self.homeassistant.image,
ATTR_DEVICES: self.homeassistant.devices,
ATTR_CUSTOM: self.homeassistant.is_custom_image,
}
@api_process
@ -44,7 +50,11 @@ class APIHomeAssistant(object):
body = await api_validate(SCHEMA_OPTIONS, request)
if ATTR_DEVICES in body:
self.config.homeassistant_devices = body[ATTR_DEVICES]
self.homeassistant.devices = body[ATTR_DEVICES]
if ATTR_IMAGE in body:
self.homeassistant.set_custom(
body[ATTR_IMAGE], body[ATTR_LAST_VERSION])
return True

View File

@ -95,6 +95,7 @@ ATTR_SIZE = 'size'
ATTR_TYPE = 'type'
ATTR_TIMEOUT = 'timeout'
ATTR_AUTO_UPDATE = 'auto_update'
ATTR_CUSTOM = 'custom'
STARTUP_INITIALIZE = 'initialize'
STARTUP_BEFORE = 'before'

View File

@ -13,13 +13,12 @@ from .const import (
RUN_UPDATE_SUPERVISOR_TASKS, RUN_WATCHDOG_HOMEASSISTANT,
RUN_CLEANUP_API_SESSIONS, STARTUP_AFTER, STARTUP_BEFORE,
STARTUP_INITIALIZE, RUN_RELOAD_SNAPSHOTS_TASKS, RUN_UPDATE_ADDONS_TASKS)
from .homeassistant import HomeAssistant
from .scheduler import Scheduler
from .dock.homeassistant import DockerHomeAssistant
from .dock.supervisor import DockerSupervisor
from .snapshots import SnapshotsManager
from .tasks import (
hassio_update, homeassistant_watchdog, homeassistant_setup,
api_sessions_cleanup, addons_update)
hassio_update, homeassistant_watchdog, api_sessions_cleanup, addons_update)
from .tools import get_local_ip, fetch_timezone
_LOGGER = logging.getLogger(__name__)
@ -41,7 +40,9 @@ class HassIO(object):
# init basic docker container
self.supervisor = DockerSupervisor(config, loop, self.dock, self.stop)
self.homeassistant = DockerHomeAssistant(config, loop, self.dock)
# init homeassistant
self.homeassistant = HomeAssistant(config, loop, self.dock)
# init HostControl
self.host_control = HostControl(loop)
@ -94,13 +95,8 @@ class HassIO(object):
api_sessions_cleanup(self.config), RUN_CLEANUP_API_SESSIONS,
now=True)
# first start of supervisor?
if not await self.homeassistant.exists():
_LOGGER.info("No HomeAssistant docker found.")
await homeassistant_setup(
self.config, self.loop, self.homeassistant, self.websession)
else:
await self.homeassistant.attach()
# Load homeassistant
await self.homeassistant.prepare():
# Load addons
await self.addons.prepare()
@ -132,6 +128,10 @@ class HassIO(object):
loop=self.loop
)
# If laningpage / run upgrade in background
if self.homeassistant.version == 'landingpage':
self.loop.create_task(self.homeassistant.install())
# start api
await self.api.start()
_LOGGER.info("Start hassio api on %s", self.config.api_endpoint)

View File

@ -1,8 +1,10 @@
"""HomeAssistant control object."""
import asyncio
import logging
import os
from .const import FILE_HASSIO_HOMEASSISTANT, ATTR_DEVICES, ATTR_IMAGE
from .const import (
FILE_HASSIO_HOMEASSISTANT, ATTR_DEVICES, ATTR_IMAGE, ATTR_LAST_VERSION)
from .dock.homeassistant import DockerHomeAssistant
from .tools import JsonConfig
from .validate import SCHEMA_HASS_CONFIG
@ -11,14 +13,24 @@ from .validate import SCHEMA_HASS_CONFIG
class HomeAssistant(JsonConfig):
"""Hass core object for handle it."""
def __init__(self, config, loop, dock):
def __init__(self, config, loop, dock, websession):
"""Initialize hass object."""
super().__init__(FILE_HASSIO_HOMEASSISTANT, SCHEMA_HASS_CONFIG)
self.config = config
self.loop = loop
self.websession = websession
self.docker = DockerHomeAssistant(config, loop, dock, self)
async def prepare(self):
"""Prepare HomeAssistant object."""
if not await self.docker.exists():
_LOGGER.info("No HomeAssistant docker %s found.", self.image)
if self.is_custom_image:
await self.install()
else:
await self.install_landingpage()
else:
await self.docker.attach()
@property
def version(self):
@ -28,6 +40,8 @@ class HomeAssistant(JsonConfig):
@property
def last_version(self):
"""Return last available version of homeassistant."""
if self.is_custom_image:
return self._data.get(ATTR_LAST_VERSION)
return self.config.last_homeassistant
@property
@ -37,14 +51,10 @@ class HomeAssistant(JsonConfig):
return self._data[ATTR_IMAGE]
return os.environ['HOMEASSISTANT_REPOSITORY']
@image.setter
def image(self, value):
"""Set image name of hass containter."""
if value is None:
self._data.pop(ATTR_IMAGE, None)
else:
self._data[ATTR_IMAGE] = value
self.save()
@property
def is_custom_image(self):
"""Return True if a custom image is used."""
return ATTR_IMAGE in self._data
@property
def devices(self):
@ -56,3 +66,57 @@ class HomeAssistant(JsonConfig):
"""Set extend device mapping."""
self._data[ATTR_DEVICES] = value
self.save()
def set_custom(self, image, version):
"""Set a custom image for homeassistant."""
# reset
if image is None and version is None:
self._data.pop(ATTR_IMAGE, None)
self._data.pop(ATTR_VERSION, None)
else:
if image:
self._data[ATTR_IMAGE] = image
if version:
self._data[ATTR_VERSION] = version
self.save()
async def install_landingpage(self):
"""Install a landingpage."""
_LOGGER.info("Setup HomeAssistant landingpage")
while True:
if self.docker.install('landingpage'):
break
_LOGGER.warning("Fails install landingpage, retry after 60sec")
await asyncio.sleep(60, loop=self.loop)
async def install(self):
"""Install a landingpage."""
_LOGGER.info("Setup HomeAssistant")
while True:
# read homeassistant tag and install it
if not self.last_version:
await self.config.fetch_update_infos(websession)
tag = self.last_version
if tag and await self.docker.install(tag):
break
_LOGGER.warning("Error on install HomeAssistant. Retry in 60sec")
await asyncio.sleep(60, loop=loop)
# store version
_LOGGER.info("HomeAssistant docker now installed")
async def update(self, version=None):
"""Update HomeAssistant version."""
version = version or self.last_version
if version == self.version:
return True
return self.docker.update(version)
def run(self):
"""Run HomeAssistant docker.
Return a coroutine.
"""
return self.docker.run()

View File

@ -47,7 +47,7 @@ class SnapshotsManager(object):
# set general data
snapshot.homeassistant_version = self.homeassistant.version
snapshot.homeassistant_devices = self.config.homeassistant_devices
snapshot.homeassistant_devices = self.homeassistant.devices
snapshot.repositories = self.config.addons_repositories
return snapshot
@ -198,8 +198,7 @@ class SnapshotsManager(object):
await snapshot.restore_folders()
# start homeassistant restore
self.config.homeassistant_devices = \
snapshot.homeassistant_devices
self.homeassistant.devices = snapshot.homeassistant_devices
task_hass = self.loop.create_task(
self.homeassistant.update(snapshot.homeassistant_version))
@ -281,8 +280,7 @@ class SnapshotsManager(object):
await snapshot.restore_folders(folders)
if homeassistant:
self.config.homeassistant_devices = \
snapshot.homeassistant_devices
self.homeassistant.devices = snapshot.homeassistant_devices
tasks.append(self.homeassistant.update(
snapshot.homeassistant_version))

View File

@ -66,20 +66,3 @@ def homeassistant_watchdog(loop, homeassistant):
loop.create_task(homeassistant.run())
return _homeassistant_watchdog
async def homeassistant_setup(config, loop, homeassistant, websession):
"""Install a homeassistant docker container."""
while True:
# read homeassistant tag and install it
if not config.last_homeassistant:
await config.fetch_update_infos(websession)
tag = config.last_homeassistant
if tag and await homeassistant.install(tag):
break
_LOGGER.warning("Error on setup HomeAssistant. Retry in 60.")
await asyncio.sleep(60, loop=loop)
# store version
_LOGGER.info("HomeAssistant docker now installed.")

View File

@ -1,7 +1,7 @@
"""Validate functions."""
import voluptuous as vol
from .const import ATTR_DEVICES, ATTR_IMAGE
from .const import ATTR_DEVICES, ATTR_IMAGE, ATTR_LAST_VERSION
NETWORK_PORT = vol.All(vol.Coerce(int), vol.Range(min=1, max=65535))
@ -37,5 +37,6 @@ DOCKER_PORTS = vol.Schema({
SCHEMA_HASS_CONFIG = vol.Schema({
vol.Optional(ATTR_DEVICES, default=[]): HASS_DEVICES,
vol.Optional(ATTR_IMAGE): vol.Coerce(str)
vol.inclusive(ATTR_IMAGE, 'custom_hass'): vol.Coerce(str),
vol.inclusive(ATTR_LAST_VERSION, 'custom_hass'): vol.Coerce(str),
})