diff --git a/hassio_api/hassio/__main__.py b/hassio_api/hassio/__main__.py index 0425fb94e..d92df3e86 100644 --- a/hassio_api/hassio/__main__.py +++ b/hassio_api/hassio/__main__.py @@ -11,6 +11,9 @@ _LOGGER = logging.getLogger(__name__) if __name__ == "__main__": bootstrap.initialize_logging() + if not bootstrap.check_environment(): + exit(1) + loop = asyncio.get_event_loop() _LOGGER.info("Start Hassio task") loop.create_task(core.run_hassio(loop)) diff --git a/hassio_api/hassio/bootstrap.py b/hassio_api/hassio/bootstrap.py index a4c06cb55..fa05291d6 100644 --- a/hassio_api/hassio/bootstrap.py +++ b/hassio_api/hassio/bootstrap.py @@ -57,3 +57,19 @@ def initialize_logging(): 'CRITICAL': 'red', } )) + + +def check_environment(): + """Check if all environment are exists.""" + for key in ('SUPERVISOR_SHARE', 'SUPERVISOR_NAME', 'DOCKER_SOCKET'): + try: + os.environ[key] + except KeyError: + _LOGGER.fatal("Can't find %s in env!", key) + return False + + if not os.path.isFile(os.environ['DOCKER_SOCKET']): + _LOGGER.fatal("Can't find docker socket!") + return False + + return True diff --git a/hassio_api/hassio/const.py b/hassio_api/hassio/const.py index 6b0337cfc..898679263 100644 --- a/hassio_api/hassio/const.py +++ b/hassio_api/hassio/const.py @@ -12,7 +12,7 @@ FILE_HASSIO_ADDONS = '/data/addons.json' FILE_HASSIO_CONFIG = '/data/config.json' HASSIO_SHARE_EXT = os.environ['SUPERVISOR_SHARE'] -HASSIO_SHARE_INT = '/shared-data' +HASSIO_SHARE_INT = '/data' HASSIO_DOCKER = os.environ['SUPERVISOR_NAME'] HOMEASSISTANT_CONFIG = "{}/homeassistant_config" diff --git a/hassio_api/hassio/core.py b/hassio_api/hassio/core.py index 376bcfdc1..a85f4644a 100644 --- a/hassio_api/hassio/core.py +++ b/hassio_api/hassio/core.py @@ -9,6 +9,7 @@ import .bootstrap import .tools from .const import CONF_HOMEASSISTANT_TAG from .docker.homeassistant import DockerHomeAssistant +from .docker.supervisor import DockerSupervisor _LOGGER = logging.getLogger(__name__) @@ -16,11 +17,16 @@ _LOGGER = logging.getLogger(__name__) async def run_hassio(loop): """Start HassIO.""" websession = aiohttp.ClientSession(loop=loop) - dock = docker.Client(base_url='unix://var/run/docker.sock', version='auto') + dock = docker.DockerClient( + base_url='unix://var/run/docker.sock', version='auto') # init system config = bootstrap.initialize_system_data() + # init Supervisor Docker + docker_super = DockerSupervisor(config, loop, dock) + await docker_super.attach() + # init HomeAssistant Docker docker_hass = DockerHomeAssistant( config, loop, dock, config.homeassistant_image, diff --git a/hassio_api/hassio/docker/__init__.py b/hassio_api/hassio/docker/__init__.py index f95d6e3a9..4463ccecb 100644 --- a/hassio_api/hassio/docker/__init__.py +++ b/hassio_api/hassio/docker/__init__.py @@ -17,6 +17,7 @@ class DockerBase(object): self.image = image self.tag = tag self.container = None + self.version = None @property def docker_name(self): diff --git a/hassio_api/hassio/docker/supervisor.py b/hassio_api/hassio/docker/supervisor.py new file mode 100644 index 000000000..bd476b19a --- /dev/null +++ b/hassio_api/hassio/docker/supervisor.py @@ -0,0 +1,52 @@ +"""Init file for HassIO docker object.""" +import logging + +import docker + +from . import DockerBase +from ..const import HASSIO_DOCKER +from ..tools import get_version_from_env, extract_image_name + +_LOGGER = logging.getLogger(__name__) + + +class DockerSupervisor(DockerBase): + """Docker hassio wrapper for HomeAssistant.""" + + def __init__(self, config, loop, dock): + """Initialize docker base wrapper.""" + super().__init__(config, loop, dock, None): + + def attach(self): + """Pull docker image. + + Return a Future. + """ + return self.loop.run_in_executor(None, self._attach) + + def _attach(self): + """Attach object to supervisor container. + + Need run inside executor. + """ + try: + self.container = dock.containers.get(self.docker_name) + self.image, self.tag = self.image = extract_image_name( + self.container.attrs['Config']['Image']) + self.version = get_version_from_env( + self.container.attrs['Config']['Env']) + except (docker.errors.DockerException, KeyError): + _LOGGER.fatal("Can't attach to supervisor docker container!") + + @property + def docker_name(self): + """Return name of docker container.""" + return HASSIO_DOCKER + + async def run(self): + """Run docker image.""" + raise RuntimeError("Not support on supervisor docker container!") + + async def install(self, tag='latest'): + """Pull docker image.""" + raise RuntimeError("Not support on supervisor docker container!") diff --git a/hassio_api/hassio/tools.py b/hassio_api/hassio/tools.py index 26bebde3b..21c92e390 100644 --- a/hassio_api/hassio/tools.py +++ b/hassio_api/hassio/tools.py @@ -1,5 +1,6 @@ """Tools file for HassIO.""" import logging +import re import async_timeout @@ -7,6 +8,9 @@ from .const import URL_SUPERVISOR_VERSION _LOGGER = logging.getLogger(__name__) +_RE_VERSION = re.compile(r"VERSION=(.*)") +_RE_IMAGE = re.compile(r"(.*):(.*)") + async def fetch_current_versions(websession): """Fetch current versions from github.""" @@ -17,3 +21,23 @@ async def fetch_current_versions(websession): except Exception as err: # pylint: disable=broad-except _LOGGER.warning("Can't fetch versions from github! %s", err) + + +def get_version_from_env(env_list): + """Extract Version from ENV list.""" + for env in env_list: + found = _RE_VERSION.match(env) + if found: + return found.group(1) + + _LOGGER.error("Can't find VERSION in env") + return None + +def extract_image_name(image): + """Extract image name and tag from docker attrs.""" + data = _RE_IMAGE.match(image) + if not data: + _LOGGER.error("Invalid docker information: %s", image) + return (None, None) + + return (data.group(1), data.group(2)) diff --git a/hassio_api/setup.py b/hassio_api/setup.py index 2f65c1857..852d7db96 100644 --- a/hassio_api/setup.py +++ b/hassio_api/setup.py @@ -33,7 +33,7 @@ setup( install_requires=[ 'async_timeout', 'aiohttp', - 'docker-py', + 'docker', '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 8ba3b16b8..a4eb3f718 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,13 +12,9 @@ runSupervisor() { -v /var/run/docker.sock:/var/run/docker.sock \ -v $CONFIG_PATH:/boot/config.json \ -v $BOOT_MOUNTPOINT/system-connections/resin-sample:/boot/network \ - -v /resin-data/resin-supervisor:/data \ - -v /resin-data:/shared-data \ + -v /resin-data:/data \ -v /var/log/supervisor-log:/var/log \ - -e DOCKER_ROOT=/mnt/root/var/lib/docker \ -e DOCKER_SOCKET=/var/run/docker.sock \ - -e SUPERVISOR_IMAGE=${SUPERVISOR_IMAGE} \ - -e SUPERVISOR_TAG=${SUPERVISOR_TAG} \ -e SUPERVISOR_SHARE=/resin-data \ -e SUPERVISOR_NAME=resin_supervisor \ -e HOMEASSISTANT_REPOSITORY=${HOMEASSISTANT_REPOSITORY} \ diff --git a/supervisor/Dockerfile b/supervisor/Dockerfile index 49a47e5ca..e17e68d58 100644 --- a/supervisor/Dockerfile +++ b/supervisor/Dockerfile @@ -7,21 +7,14 @@ ENV LANG C.UTF-8 # remove several traces of python RUN apk del --no-cache python* -# http://bugs.python.org/issue19846 -# > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK. -ENV LANG C.UTF-8 - # setup base RUN apk add --no-cache python3 git -# install aiohttp -RUN pip3 install pip --no-cache-dir --upgrade \ - && pip3 install --no-cache-dir aiohttp \ - && pip3 install --no-cache-dir docker \ - && pip3 install --no-cache-dir colorlog +# update pip +RUN pip3 install pip --no-cache-dir --upgrade # install HassIO COPY hassio_api /usr/src/hassio_api RUN pip3 install --no-cache-dir /usr/src/hassio_api -CMD [ "hassio" ] +CMD [ "python3", "-m", "hassio" ] diff --git a/supervisor/README.md b/supervisor/README.md index d9f20b994..389bf7858 100644 --- a/supervisor/README.md +++ b/supervisor/README.md @@ -6,13 +6,9 @@ docker run --privileged --name resin_supervisor \ -v /var/run/docker.sock:/var/run/docker.sock \ -v $CONFIG_PATH:/boot/config.json \ -v $BOOT_MOUNTPOINT/system-connections/resin-sample:/boot/network \ - -v /resin-data/resin-supervisor:/data \ - -v /resin-data:/shared-data \ + -v /resin-data:/data \ -v /var/log/supervisor-log:/var/log \ - -e DOCKER_ROOT=/mnt/root/var/lib/docker \ -e DOCKER_SOCKET=/var/run/docker.sock \ - -e SUPERVISOR_IMAGE=${SUPERVISOR_IMAGE} \ - -e SUPERVISOR_TAG=${SUPERVISOR_TAG} \ -e SUPERVISOR_SHARE=/resin-data \ -e SUPERVISOR_NAME=resin_supervisor \ -e HOMEASSISTANT_REPOSITORY=${HOMEASSISTANT_REPOSITORY} \