mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-10 02:36:29 +00:00
Finish new homeassistant handling
This commit is contained in:
parent
02c8baef68
commit
906c4e03fb
8
API.md
8
API.md
@ -269,7 +269,9 @@ Optional:
|
|||||||
{
|
{
|
||||||
"version": "INSTALL_VERSION",
|
"version": "INSTALL_VERSION",
|
||||||
"last_version": "LAST_VERSION",
|
"last_version": "LAST_VERSION",
|
||||||
"devices": []
|
"devices": [""],
|
||||||
|
"image": "str",
|
||||||
|
"custom": "bool -> if custom image"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -291,9 +293,13 @@ Output the raw docker log
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"devices": [],
|
"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
|
### REST API addons
|
||||||
|
|
||||||
- POST `/addons/reload`
|
- POST `/addons/reload`
|
||||||
|
@ -5,7 +5,8 @@ import logging
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from .util import api_process, api_process_raw, api_validate
|
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
|
from ..validate import HASS_DEVICES
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -13,6 +14,9 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
SCHEMA_OPTIONS = vol.Schema({
|
SCHEMA_OPTIONS = vol.Schema({
|
||||||
vol.Optional(ATTR_DEVICES): HASS_DEVICES,
|
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({
|
SCHEMA_VERSION = vol.Schema({
|
||||||
@ -34,8 +38,10 @@ class APIHomeAssistant(object):
|
|||||||
"""Return host information."""
|
"""Return host information."""
|
||||||
return {
|
return {
|
||||||
ATTR_VERSION: self.homeassistant.version,
|
ATTR_VERSION: self.homeassistant.version,
|
||||||
ATTR_LAST_VERSION: self.config.last_homeassistant,
|
ATTR_LAST_VERSION: self.homeassistant.last_version,
|
||||||
ATTR_DEVICES: self.config.homeassistant_devices,
|
ATTR_IMAGE: self.homeassistant.image,
|
||||||
|
ATTR_DEVICES: self.homeassistant.devices,
|
||||||
|
ATTR_CUSTOM: self.homeassistant.is_custom_image,
|
||||||
}
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
@ -44,7 +50,11 @@ class APIHomeAssistant(object):
|
|||||||
body = await api_validate(SCHEMA_OPTIONS, request)
|
body = await api_validate(SCHEMA_OPTIONS, request)
|
||||||
|
|
||||||
if ATTR_DEVICES in body:
|
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
|
return True
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@ ATTR_SIZE = 'size'
|
|||||||
ATTR_TYPE = 'type'
|
ATTR_TYPE = 'type'
|
||||||
ATTR_TIMEOUT = 'timeout'
|
ATTR_TIMEOUT = 'timeout'
|
||||||
ATTR_AUTO_UPDATE = 'auto_update'
|
ATTR_AUTO_UPDATE = 'auto_update'
|
||||||
|
ATTR_CUSTOM = 'custom'
|
||||||
|
|
||||||
STARTUP_INITIALIZE = 'initialize'
|
STARTUP_INITIALIZE = 'initialize'
|
||||||
STARTUP_BEFORE = 'before'
|
STARTUP_BEFORE = 'before'
|
||||||
|
@ -13,13 +13,12 @@ from .const import (
|
|||||||
RUN_UPDATE_SUPERVISOR_TASKS, RUN_WATCHDOG_HOMEASSISTANT,
|
RUN_UPDATE_SUPERVISOR_TASKS, RUN_WATCHDOG_HOMEASSISTANT,
|
||||||
RUN_CLEANUP_API_SESSIONS, STARTUP_AFTER, STARTUP_BEFORE,
|
RUN_CLEANUP_API_SESSIONS, STARTUP_AFTER, STARTUP_BEFORE,
|
||||||
STARTUP_INITIALIZE, RUN_RELOAD_SNAPSHOTS_TASKS, RUN_UPDATE_ADDONS_TASKS)
|
STARTUP_INITIALIZE, RUN_RELOAD_SNAPSHOTS_TASKS, RUN_UPDATE_ADDONS_TASKS)
|
||||||
|
from .homeassistant import HomeAssistant
|
||||||
from .scheduler import Scheduler
|
from .scheduler import Scheduler
|
||||||
from .dock.homeassistant import DockerHomeAssistant
|
|
||||||
from .dock.supervisor import DockerSupervisor
|
from .dock.supervisor import DockerSupervisor
|
||||||
from .snapshots import SnapshotsManager
|
from .snapshots import SnapshotsManager
|
||||||
from .tasks import (
|
from .tasks import (
|
||||||
hassio_update, homeassistant_watchdog, homeassistant_setup,
|
hassio_update, homeassistant_watchdog, api_sessions_cleanup, addons_update)
|
||||||
api_sessions_cleanup, addons_update)
|
|
||||||
from .tools import get_local_ip, fetch_timezone
|
from .tools import get_local_ip, fetch_timezone
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -41,7 +40,9 @@ class HassIO(object):
|
|||||||
|
|
||||||
# init basic docker container
|
# init basic docker container
|
||||||
self.supervisor = DockerSupervisor(config, loop, self.dock, self.stop)
|
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
|
# init HostControl
|
||||||
self.host_control = HostControl(loop)
|
self.host_control = HostControl(loop)
|
||||||
@ -94,13 +95,8 @@ class HassIO(object):
|
|||||||
api_sessions_cleanup(self.config), RUN_CLEANUP_API_SESSIONS,
|
api_sessions_cleanup(self.config), RUN_CLEANUP_API_SESSIONS,
|
||||||
now=True)
|
now=True)
|
||||||
|
|
||||||
# first start of supervisor?
|
# Load homeassistant
|
||||||
if not await self.homeassistant.exists():
|
await self.homeassistant.prepare():
|
||||||
_LOGGER.info("No HomeAssistant docker found.")
|
|
||||||
await homeassistant_setup(
|
|
||||||
self.config, self.loop, self.homeassistant, self.websession)
|
|
||||||
else:
|
|
||||||
await self.homeassistant.attach()
|
|
||||||
|
|
||||||
# Load addons
|
# Load addons
|
||||||
await self.addons.prepare()
|
await self.addons.prepare()
|
||||||
@ -132,6 +128,10 @@ class HassIO(object):
|
|||||||
loop=self.loop
|
loop=self.loop
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# If laningpage / run upgrade in background
|
||||||
|
if self.homeassistant.version == 'landingpage':
|
||||||
|
self.loop.create_task(self.homeassistant.install())
|
||||||
|
|
||||||
# start api
|
# start api
|
||||||
await self.api.start()
|
await self.api.start()
|
||||||
_LOGGER.info("Start hassio api on %s", self.config.api_endpoint)
|
_LOGGER.info("Start hassio api on %s", self.config.api_endpoint)
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
"""HomeAssistant control object."""
|
"""HomeAssistant control object."""
|
||||||
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import os
|
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 .dock.homeassistant import DockerHomeAssistant
|
||||||
from .tools import JsonConfig
|
from .tools import JsonConfig
|
||||||
from .validate import SCHEMA_HASS_CONFIG
|
from .validate import SCHEMA_HASS_CONFIG
|
||||||
@ -11,14 +13,24 @@ from .validate import SCHEMA_HASS_CONFIG
|
|||||||
class HomeAssistant(JsonConfig):
|
class HomeAssistant(JsonConfig):
|
||||||
"""Hass core object for handle it."""
|
"""Hass core object for handle it."""
|
||||||
|
|
||||||
def __init__(self, config, loop, dock):
|
def __init__(self, config, loop, dock, websession):
|
||||||
"""Initialize hass object."""
|
"""Initialize hass object."""
|
||||||
super().__init__(FILE_HASSIO_HOMEASSISTANT, SCHEMA_HASS_CONFIG)
|
super().__init__(FILE_HASSIO_HOMEASSISTANT, SCHEMA_HASS_CONFIG)
|
||||||
self.config = config
|
self.config = config
|
||||||
self.loop = loop
|
self.loop = loop
|
||||||
|
self.websession = websession
|
||||||
|
self.docker = DockerHomeAssistant(config, loop, dock, self)
|
||||||
|
|
||||||
async def prepare(self):
|
async def prepare(self):
|
||||||
"""Prepare HomeAssistant object."""
|
"""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
|
@property
|
||||||
def version(self):
|
def version(self):
|
||||||
@ -28,6 +40,8 @@ class HomeAssistant(JsonConfig):
|
|||||||
@property
|
@property
|
||||||
def last_version(self):
|
def last_version(self):
|
||||||
"""Return last available version of homeassistant."""
|
"""Return last available version of homeassistant."""
|
||||||
|
if self.is_custom_image:
|
||||||
|
return self._data.get(ATTR_LAST_VERSION)
|
||||||
return self.config.last_homeassistant
|
return self.config.last_homeassistant
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -37,14 +51,10 @@ class HomeAssistant(JsonConfig):
|
|||||||
return self._data[ATTR_IMAGE]
|
return self._data[ATTR_IMAGE]
|
||||||
return os.environ['HOMEASSISTANT_REPOSITORY']
|
return os.environ['HOMEASSISTANT_REPOSITORY']
|
||||||
|
|
||||||
@image.setter
|
@property
|
||||||
def image(self, value):
|
def is_custom_image(self):
|
||||||
"""Set image name of hass containter."""
|
"""Return True if a custom image is used."""
|
||||||
if value is None:
|
return ATTR_IMAGE in self._data
|
||||||
self._data.pop(ATTR_IMAGE, None)
|
|
||||||
else:
|
|
||||||
self._data[ATTR_IMAGE] = value
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def devices(self):
|
def devices(self):
|
||||||
@ -56,3 +66,57 @@ class HomeAssistant(JsonConfig):
|
|||||||
"""Set extend device mapping."""
|
"""Set extend device mapping."""
|
||||||
self._data[ATTR_DEVICES] = value
|
self._data[ATTR_DEVICES] = value
|
||||||
self.save()
|
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()
|
||||||
|
@ -47,7 +47,7 @@ class SnapshotsManager(object):
|
|||||||
|
|
||||||
# set general data
|
# set general data
|
||||||
snapshot.homeassistant_version = self.homeassistant.version
|
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
|
snapshot.repositories = self.config.addons_repositories
|
||||||
|
|
||||||
return snapshot
|
return snapshot
|
||||||
@ -198,8 +198,7 @@ class SnapshotsManager(object):
|
|||||||
await snapshot.restore_folders()
|
await snapshot.restore_folders()
|
||||||
|
|
||||||
# start homeassistant restore
|
# start homeassistant restore
|
||||||
self.config.homeassistant_devices = \
|
self.homeassistant.devices = snapshot.homeassistant_devices
|
||||||
snapshot.homeassistant_devices
|
|
||||||
task_hass = self.loop.create_task(
|
task_hass = self.loop.create_task(
|
||||||
self.homeassistant.update(snapshot.homeassistant_version))
|
self.homeassistant.update(snapshot.homeassistant_version))
|
||||||
|
|
||||||
@ -281,8 +280,7 @@ class SnapshotsManager(object):
|
|||||||
await snapshot.restore_folders(folders)
|
await snapshot.restore_folders(folders)
|
||||||
|
|
||||||
if homeassistant:
|
if homeassistant:
|
||||||
self.config.homeassistant_devices = \
|
self.homeassistant.devices = snapshot.homeassistant_devices
|
||||||
snapshot.homeassistant_devices
|
|
||||||
tasks.append(self.homeassistant.update(
|
tasks.append(self.homeassistant.update(
|
||||||
snapshot.homeassistant_version))
|
snapshot.homeassistant_version))
|
||||||
|
|
||||||
|
@ -66,20 +66,3 @@ def homeassistant_watchdog(loop, homeassistant):
|
|||||||
loop.create_task(homeassistant.run())
|
loop.create_task(homeassistant.run())
|
||||||
|
|
||||||
return _homeassistant_watchdog
|
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.")
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Validate functions."""
|
"""Validate functions."""
|
||||||
import voluptuous as vol
|
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))
|
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({
|
SCHEMA_HASS_CONFIG = vol.Schema({
|
||||||
vol.Optional(ATTR_DEVICES, default=[]): HASS_DEVICES,
|
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),
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user