From 3ec832184c7ae87295d32af7cf177586da9b8999 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Mon, 20 Mar 2017 00:19:37 +0100 Subject: [PATCH] Update hassio api & init scripts --- hassio_api/hassio/__main__.py | 49 +++++++++++++++++++ hassio_api/hassio/bootstrap.py | 35 +++++++++++++ hassio_api/hassio/const.py | 5 +- hassio_api/hassio/docker/__init__.py | 28 +++++++++++ hassio_api/hassio/docker/homeassistant.py | 20 ++++++++ hassio_api/hassio/tools.py | 19 +++++++ hassio_api/setup.py | 3 +- .../start-resin-supervisor | 4 +- supervisor/Dockerfile | 5 +- 9 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 hassio_api/hassio/__main__.py create mode 100644 hassio_api/hassio/docker/__init__.py create mode 100644 hassio_api/hassio/docker/homeassistant.py create mode 100644 hassio_api/hassio/tools.py diff --git a/hassio_api/hassio/__main__.py b/hassio_api/hassio/__main__.py new file mode 100644 index 000000000..2c4c6702b --- /dev/null +++ b/hassio_api/hassio/__main__.py @@ -0,0 +1,49 @@ +"""Main file for HassIO.""" +import asyncio +import logging + +import aiohttp +from aiohttp import web +import docker + +import .bootstrap +import .tools +from .docker.homeassistant import DockerHomeAssistant + +_LOGGER = logging.getLogger(__name__) + + +def main(): + """Start HassIO.""" + bootstrap.initialize_logging() + + # init asyncio & aiohttp client + loop = asyncio.get_event_loop() + websession = aiohttp.ClientSession(loop=loop) + dock = docker.from_env() + + # init system + versions = bootstrap.initialize_system_data() + + # init HomeAssistant Docker + docker_hass = DockerHomeAssistant( + loop, dock, versions[CONF_HOMEASSISTANT_IMAGE], + versions[CONF_HOMEASSISTANT_TAG]) + + # first start of supervisor? + if versions['CONF_HOMEASSISTANT_TAG'] is None: + _LOGGER.info("First start of supervisor, read version from github.") + + # read homeassistant tag and install it + current = None + while True: + current = await tools.fetch_current_versions(websession) + if current and 'homeassistant_tag' in current: + if docker_hass.install(current['homeassistant_tag']): + break + _LOGGER.waring("Can't fetch info from github. Retry in 60") + await asyncio.sleep(60, loop=loop) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/hassio_api/hassio/bootstrap.py b/hassio_api/hassio/bootstrap.py index 68ff7ddce..b281860bb 100644 --- a/hassio_api/hassio/bootstrap.py +++ b/hassio_api/hassio/bootstrap.py @@ -1,17 +1,24 @@ """Bootstrap HassIO.""" import asyncio import json +import logging import os +from colorlog import ColoredFormatter + from .const import ( FILE_HASSIO_ADDONS, FILE_HASSIO_VERSION, FILE_RESIN_CONFIG, HOMEASSISTANT_CONFIG, CONF_SUPERVISOR_TAG, CONF_SUPERVISOR_IMAGE) +_LOGGER = logging.getLogger(__name__) + def initialize_system_data(): """Setup default config and create folders.""" # homeassistant config folder if not os.path.isdir(HOMEASSISTANT_CONFIG): + _LOGGER.info( + "Create Home-Assistant config folder %s", HOMEASSISTANT_CONFIG) os.mkdir(HOMEASSISTANT_CONFIG) # installed addons @@ -38,3 +45,31 @@ def initialize_system_data(): with open(FILE_HASSIO_VERSION, 'w') as conf_file: conf_file.write(json.dumps(versions)) + + _LOGGER("initialize system done: %s", versions) + return versions + + +def initialize_logging(): + """Setup the logging.""" + logging.basicConfig(level=logging.INFO) + fmt = ("%(asctime)s %(levelname)s (%(threadName)s) " + "[%(name)s] %(message)s") + colorfmt = "%(log_color)s{}%(reset)s".format(fmt) + datefmt = '%y-%m-%d %H:%M:%S' + + # suppress overly verbose logs from libraries that aren't helpful + logging.getLogger("aiohttp.access").setLevel(logging.WARNING) + + logging.getLogger().handlers[0].setFormatter(ColoredFormatter( + colorfmt, + datefmt=datefmt, + reset=True, + log_colors={ + 'DEBUG': 'cyan', + 'INFO': 'green', + 'WARNING': 'yellow', + 'ERROR': 'red', + 'CRITICAL': 'red', + } + )) diff --git a/hassio_api/hassio/const.py b/hassio_api/hassio/const.py index 1e6e08c4d..2f049d86c 100644 --- a/hassio_api/hassio/const.py +++ b/hassio_api/hassio/const.py @@ -1,4 +1,6 @@ """Const file for HassIO.""" +import os + URL_SUPERVISOR_VERSION = \ 'https://raw.githubusercontent.com/pvizeli/hassio/master/version.json' @@ -8,7 +10,8 @@ FILE_RESIN_CONFIG = '/boot/config.json' FILE_HASSIO_ADDONS = '/data/addons.json' FILE_HASSIO_VERSION = '/data/version.json' -HOMEASSISTANT_CONFIG = '/resin-data/config' +HOMEASSISTANT_SHARE = os.environ['SUPERVISOR_SHARE'] +HOMEASSISTANT_CONFIG = "{}/config".format(HOMEASSISTANT_SHARE) HTTP_PORT = 9123 diff --git a/hassio_api/hassio/docker/__init__.py b/hassio_api/hassio/docker/__init__.py new file mode 100644 index 000000000..fa0d251b2 --- /dev/null +++ b/hassio_api/hassio/docker/__init__.py @@ -0,0 +1,28 @@ +"""Init file for HassIO docker object.""" +import asyncio + +import docker + + +class DockerBase(object): + """Docker hassio wrapper.""" + + def __init__(self, loop, dock, image, tag=None): + """Initialize docker base wrapper.""" + self.loop = loop + self.dock = dock + self.image = image + self.tag = tag + + async def install(tag='latest'): + """Pull docker image.""" + try: + self.dock.images.pull(self.image, tag=tag) + except docker.errors.APIError as err: + _LOGGER.error("Can't pull %s:%s", self.image, tag) + return False + return True + + async def run(): + """Run docker image.""" + raise NotImplementedError() diff --git a/hassio_api/hassio/docker/homeassistant.py b/hassio_api/hassio/docker/homeassistant.py new file mode 100644 index 000000000..d17c3c550 --- /dev/null +++ b/hassio_api/hassio/docker/homeassistant.py @@ -0,0 +1,20 @@ +"""Init file for HassIO docker object.""" +import asyncio + +import docker + +import . from DockerBase + + +class DockerHomeAssistant(DockerBase): + """Docker hassio wrapper for HomeAssistant.""" + + async def run(): + """Run docker image.""" + try: + self.docker.images.pull(self.image, tag=tag) + except docker.errors.APIError as err: + _LOGGER.error("Can't pull %s:%s", self.image, tag) + return False + + return True diff --git a/hassio_api/hassio/tools.py b/hassio_api/hassio/tools.py new file mode 100644 index 000000000..0be6325ab --- /dev/null +++ b/hassio_api/hassio/tools.py @@ -0,0 +1,19 @@ +"""Tools file for HassIO.""" +import asyncio +import logging + +import aiohttp +import async_timeout + +from .const import URL_SUPERVISOR_VERSION + + +async def fetch_current_versions(websession): + """Fetch current versions from github.""" + try: + with async_timeout.timeout(10, loop=websession.loop): + async with websession.get(URL_SUPERVISOR_VERSION) as request: + return (await request.json()) + + except Exception: # pylint: disable=broad-except + return None diff --git a/hassio_api/setup.py b/hassio_api/setup.py index 2c841685e..966de5a56 100644 --- a/hassio_api/setup.py +++ b/hassio_api/setup.py @@ -33,6 +33,7 @@ setup( install_requires=[ 'async_timeout', 'aiohttp', - 'docker-py' + 'docker-py', + 'colorlog' ] ) diff --git a/meta-hassio/recipes-containers/docker-disk/docker-resin-supervisor-disk/start-resin-supervisor b/meta-hassio/recipes-containers/docker-disk/docker-resin-supervisor-disk/start-resin-supervisor index 3c89cec50..0fb2269a1 100644 --- a/meta-hassio/recipes-containers/docker-disk/docker-resin-supervisor-disk/start-resin-supervisor +++ b/meta-hassio/recipes-containers/docker-disk/docker-resin-supervisor-disk/start-resin-supervisor @@ -12,7 +12,7 @@ runSupervisor() { -v /var/run/docker.sock:/var/run/docker.sock \ -v $CONFIG_PATH:/boot/config.json \ -v /resin-data/resin-supervisor:/data \ - -v /resin-data:/resin-data \ + -v /resin-data:/shared-data \ -v /proc/net/fib_trie:/mnt/fib_trie \ -v /var/log/supervisor-log:/var/log \ -v /:/mnt/root \ @@ -22,6 +22,8 @@ runSupervisor() { -e LED_FILE=${LED_FILE} \ -e SUPERVISOR_IMAGE=${SUPERVISOR_IMAGE} \ -e SUPERVISOR_TAG=${SUPERVISOR_TAG} \ + -e SUPERVISOR_SHARE=/shared-data \ + -e SUPERVISOR_NAME=resin_supervisor \ -e HOMEASSISTANT_REPOSITORY=${HOMEASSISTANT_REPOSITORY} \ ${SUPERVISOR_IMAGE} } diff --git a/supervisor/Dockerfile b/supervisor/Dockerfile index 2b546f342..9a7ed4968 100644 --- a/supervisor/Dockerfile +++ b/supervisor/Dockerfile @@ -11,4 +11,7 @@ ENV LANG C.UTF-8 RUN apk add --no-cache python3 git # install aiohttp -RUN pip3 install pip --no-cache --upgrade && pip3 install --no-cache aiohttp && pip3 install --no-cache docker +RUN pip3 install pip --no-cache --upgrade \ + && pip3 install --no-cache aiohttp \ + && pip3 install --no-cache docker \ + && pip3 install --no-cache colorlog